summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java16
-rw-r--r--apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java4
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java21
-rw-r--r--core/api/current.txt6
-rw-r--r--core/api/system-current.txt91
-rw-r--r--core/api/test-current.txt26
-rw-r--r--core/java/android/app/IActivityManager.aidl2
-rw-r--r--core/java/android/app/Notification.java76
-rw-r--r--core/java/android/app/NotificationManager.java15
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java11
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl8
-rw-r--r--core/java/android/companion/CompanionDeviceManager.java14
-rw-r--r--core/java/android/companion/ICompanionDeviceManager.aidl2
-rw-r--r--core/java/android/content/ContentCaptureOptions.java40
-rw-r--r--core/java/android/content/ContentProvider.java149
-rw-r--r--core/java/android/content/ContentProviderNative.java42
-rw-r--r--core/java/android/content/ContentResolver.java20
-rw-r--r--core/java/android/content/ContextWrapper.java8
-rw-r--r--core/java/android/content/IContentProvider.java36
-rw-r--r--core/java/android/content/pm/PackageInstaller.java216
-rw-r--r--core/java/android/content/pm/PackageManager.java7
-rw-r--r--core/java/android/content/pm/UserInfo.java16
-rw-r--r--core/java/android/hardware/biometrics/AuthenticateOptions.java77
-rw-r--r--core/java/android/hardware/display/DisplayManager.java11
-rw-r--r--core/java/android/hardware/face/FaceAuthenticateOptions.aidl19
-rw-r--r--core/java/android/hardware/face/FaceAuthenticateOptions.java624
-rw-r--r--core/java/android/hardware/face/FaceManager.java39
-rw-r--r--core/java/android/hardware/face/IFaceService.aidl11
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.aidl19
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.java447
-rw-r--r--core/java/android/hardware/fingerprint/FingerprintManager.java40
-rw-r--r--core/java/android/hardware/fingerprint/IFingerprintService.aidl10
-rw-r--r--core/java/android/hardware/input/InputManager.java21
-rw-r--r--core/java/android/net/Ikev2VpnProfile.java5
-rw-r--r--core/java/android/os/IPowerManager.aidl2
-rw-r--r--core/java/android/os/PowerManager.java64
-rw-r--r--core/java/android/os/UserManager.java7
-rw-r--r--core/java/android/service/voice/AbstractDetector.java9
-rw-r--r--core/java/android/service/voice/AlwaysOnHotwordDetector.java21
-rw-r--r--core/java/android/service/voice/DetectedPhrase.aidl19
-rw-r--r--core/java/android/service/voice/DetectedPhrase.java286
-rw-r--r--core/java/android/service/voice/DetectorFailure.aidl19
-rw-r--r--core/java/android/service/voice/DetectorFailure.java218
-rw-r--r--core/java/android/service/voice/HotwordDetectedResult.java129
-rw-r--r--core/java/android/service/voice/HotwordDetectionServiceFailure.aidl19
-rw-r--r--core/java/android/service/voice/HotwordDetectionServiceFailure.java152
-rw-r--r--core/java/android/service/voice/HotwordDetector.java19
-rw-r--r--core/java/android/service/voice/IMicrophoneHotwordDetectionVoiceInteractionCallback.aidl3
-rw-r--r--core/java/android/service/voice/IVisualQueryDetectionVoiceInteractionCallback.aidl5
-rw-r--r--core/java/android/service/voice/SoftwareHotwordDetector.java19
-rw-r--r--core/java/android/service/voice/SoundTriggerFailure.aidl19
-rw-r--r--core/java/android/service/voice/SoundTriggerFailure.java126
-rw-r--r--core/java/android/service/voice/UnknownFailure.aidl19
-rw-r--r--core/java/android/service/voice/UnknownFailure.java77
-rw-r--r--core/java/android/service/voice/VisualQueryDetectionServiceFailure.aidl19
-rw-r--r--core/java/android/service/voice/VisualQueryDetectionServiceFailure.java136
-rw-r--r--core/java/android/service/voice/VisualQueryDetector.java14
-rw-r--r--core/java/android/service/voice/VoiceInteractionSession.java29
-rw-r--r--core/java/android/service/wallpaper/IWallpaperService.aidl2
-rw-r--r--core/java/android/service/wallpaper/WallpaperService.java246
-rw-r--r--core/java/android/view/SurfaceControl.java43
-rw-r--r--core/java/android/view/ViewRootImpl.java4
-rw-r--r--core/java/android/view/WindowManager.java21
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureContext.java13
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureManager.java44
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureSession.java17
-rw-r--r--core/java/android/view/contentcapture/MainContentCaptureSession.java21
-rw-r--r--core/java/android/view/textclassifier/TextLinks.java2
-rw-r--r--core/java/android/widget/RemoteViews.java4
-rw-r--r--core/java/android/widget/TextView.java19
-rw-r--r--core/java/android/window/IWindowOrganizerController.aidl2
-rw-r--r--core/java/android/window/TaskFragmentCreationParams.java59
-rw-r--r--core/java/com/android/internal/app/IHotwordRecognitionStatusCallback.aidl8
-rw-r--r--core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl2
-rw-r--r--core/java/com/android/internal/app/IntentForwarderActivity.java56
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java14
-rw-r--r--core/java/com/android/internal/policy/GestureNavigationSettingsObserver.java52
-rw-r--r--core/jni/android_media_MicrophoneInfo.cpp1
-rw-r--r--core/jni/android_view_SurfaceControl.cpp9
-rw-r--r--core/res/AndroidManifest.xml14
-rw-r--r--core/res/res/layout/miniresolver.xml6
-rw-r--r--core/res/res/values/attrs.xml116
-rw-r--r--core/res/res/values/config.xml7
-rw-r--r--core/res/res/values/symbols.xml49
-rw-r--r--core/res/res/values/themes_device_defaults.xml2295
-rw-r--r--core/tests/companiontests/OWNERS1
-rw-r--r--core/tests/companiontests/src/android/companion/SystemDataTransportTest.java2
-rw-r--r--core/tests/coretests/src/android/hardware/face/FaceManagerTest.java151
-rw-r--r--core/tests/coretests/src/android/hardware/face/OWNERS1
-rw-r--r--core/tests/coretests/src/android/hardware/fingerprint/FingerprintManagerTest.java152
-rw-r--r--core/tests/coretests/src/android/hardware/fingerprint/OWNERS1
-rw-r--r--core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java17
-rw-r--r--core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java35
-rw-r--r--data/etc/preinstalled-packages-platform.xml18
-rw-r--r--data/etc/privapp-permissions-platform.xml2
-rw-r--r--graphics/java/android/graphics/Gainmap.java2
-rw-r--r--graphics/java/android/graphics/text/LineBreaker.java34
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java24
-rw-r--r--libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java123
-rw-r--r--libs/WindowManager/Shell/Android.bp1
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background.xml21
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background_ripple.xml31
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background.xml22
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background_ripple.xml32
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background.xml23
-rw-r--r--libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background_ripple.xml34
-rw-r--r--libs/WindowManager/Shell/res/layout/compat_mode_hint.xml6
-rw-r--r--libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml2
-rw-r--r--libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml8
-rw-r--r--libs/WindowManager/Shell/res/values/dimen.xml45
-rw-r--r--libs/WindowManager/Shell/res/values/styles.xml25
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/ProtoLogController.java5
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/TaskViewTaskController.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/TaskViewTransitions.java98
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblesNavBarGestureTracker.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/DevicePostureController.java147
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java11
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropConstants.java27
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java12
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java6
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogImpl.java3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java4
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java8
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java21
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java22
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java23
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java2
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java14
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/TaskOperations.java2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DevicePostureControllerTest.java109
-rw-r--r--libs/hwui/hwui/Bitmap.cpp2
-rw-r--r--media/java/android/media/RingtoneManager.java2
-rw-r--r--media/java/android/media/tv/tuner/filter/MediaEvent.java4
-rw-r--r--media/tests/MediaFrameworkTest/AndroidManifest.xml1
-rw-r--r--packages/CarrierDefaultApp/res/values/strings.xml4
-rw-r--r--packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiver.java2
-rw-r--r--packages/LocalTransport/src/com/android/localtransport/LocalTransport.java3
-rw-r--r--packages/PackageInstaller/AndroidManifest.xml4
-rw-r--r--packages/PackageInstaller/res/values/strings.xml3
-rw-r--r--packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java17
-rw-r--r--packages/SettingsLib/ActionBarShadow/Android.bp3
-rw-r--r--packages/SettingsLib/CollapsingToolbarBaseActivity/Android.bp1
-rw-r--r--packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java4
-rw-r--r--packages/SettingsLib/MainSwitchPreference/Android.bp1
-rw-r--r--packages/SettingsLib/SettingsTheme/Android.bp8
-rw-r--r--packages/SettingsLib/SettingsTransition/Android.bp1
-rw-r--r--packages/SettingsLib/Utils/Android.bp3
-rw-r--r--packages/SettingsLib/res/values/styles.xml4
-rw-r--r--packages/Shell/AndroidManifest.xml3
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt3
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableImageView.kt2
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableTextView.kt2
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt2
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt146
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt120
-rw-r--r--packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/SdfShaderLibrary.kt15
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt2
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/Weather.kt85
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/WeatherData.kt107
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml2
-rw-r--r--packages/SystemUI/res-keyguard/values/dimens.xml2
-rw-r--r--packages/SystemUI/res/drawable/pin_dot_avd.xml57
-rw-r--r--packages/SystemUI/res/drawable/pin_dot_delete_avd.xml2
-rw-r--r--packages/SystemUI/res/drawable/pin_dot_shape_1_avd.xml2
-rw-r--r--packages/SystemUI/res/drawable/pin_dot_shape_2_avd.xml2
-rw-r--r--packages/SystemUI/res/drawable/pin_dot_shape_3_avd.xml2
-rw-r--r--packages/SystemUI/res/drawable/pin_dot_shape_4_avd.xml2
-rw-r--r--packages/SystemUI/res/drawable/pin_dot_shape_5_avd.xml2
-rw-r--r--packages/SystemUI/res/drawable/pin_dot_shape_6_avd.xml2
-rw-r--r--packages/SystemUI/res/values/strings.xml2
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt2
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java78
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java219
-rw-r--r--packages/SystemUI/src/com/android/keyguard/ClockEventController.kt8
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java12
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java61
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java22
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/PinShapeHintingView.java4
-rw-r--r--packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java94
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/devicepolicy/DevicePolicyManagerExt.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/Flags.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/data/model/BacklightModel.kt24
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt100
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt21
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManager.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt66
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt25
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt18
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt16
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/process/ProcessWrapper.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/process/condition/SystemProcessCondition.java (renamed from packages/SystemUI/src/com/android/systemui/process/condition/UserProcessCondition.java)15
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFragment.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt24
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java40
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt58
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt20
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeOverScroller.kt167
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt27
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java37
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLogger.kt114
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java166
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java101
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt28
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/devicepolicy/DevicePolicyManagerExtTest.kt93
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt191
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManagerTest.kt9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt108
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt83
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataFilterTest.kt55
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt94
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/process/condition/SystemProcessConditionTest.java (renamed from packages/SystemUI/tests/src/com/android/systemui/process/condition/UserProcessConditionTest.java)29
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt130
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/transition/SplitShadeOverScrollerTest.kt112
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java14
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt231
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java85
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLoggerTest.kt300
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleShaderTest.kt121
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt9
-rw-r--r--services/Android.bp4
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java11
-rw-r--r--services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java2
-rw-r--r--services/accessibility/java/com/android/server/accessibility/magnification/AlwaysOnMagnificationFeatureFlag.java38
-rw-r--r--services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java4
-rw-r--r--services/companion/Android.bp3
-rw-r--r--services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java5
-rw-r--r--services/companion/java/com/android/server/companion/RolesUtils.java8
-rw-r--r--services/companion/java/com/android/server/companion/securechannel/AttestationVerifier.java100
-rw-r--r--services/companion/java/com/android/server/companion/securechannel/KeyStoreUtils.java130
-rw-r--r--services/companion/java/com/android/server/companion/securechannel/SecureChannel.java543
-rw-r--r--services/companion/java/com/android/server/companion/securechannel/SecureChannelException.java34
-rw-r--r--services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java302
-rw-r--r--services/companion/java/com/android/server/companion/transport/CryptoManager.java143
-rw-r--r--services/companion/java/com/android/server/companion/virtual/InputController.java109
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java30
-rw-r--r--services/core/java/com/android/server/TelephonyRegistry.java14
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java40
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java55
-rw-r--r--services/core/java/com/android/server/am/BroadcastProcessQueue.java16
-rw-r--r--services/core/java/com/android/server/am/BroadcastQueueModernImpl.java21
-rw-r--r--services/core/java/com/android/server/am/BroadcastRecord.java12
-rw-r--r--services/core/java/com/android/server/am/ContentProviderHelper.java132
-rw-r--r--services/core/java/com/android/server/am/UserController.java124
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceBroker.java15
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceInventory.java51
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java32
-rw-r--r--services/core/java/com/android/server/audio/BtHelper.java70
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java12
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/FaceService.java34
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java13
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java26
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java23
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java4
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java29
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java1
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestHal.java10
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java3
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java72
-rw-r--r--services/core/java/com/android/server/connectivity/VpnIkev2Utils.java4
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java54
-rw-r--r--services/core/java/com/android/server/display/DisplayModeDirector.java2
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java78
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController2.java78
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerControllerInterface.java5
-rw-r--r--services/core/java/com/android/server/display/LogicalDisplay.java13
-rw-r--r--services/core/java/com/android/server/display/LogicalDisplayMapper.java14
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiEarcController.java60
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java82
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java37
-rw-r--r--services/core/java/com/android/server/notification/PreferencesHelper.java9
-rw-r--r--services/core/java/com/android/server/pm/ComputerEngine.java15
-rw-r--r--services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java80
-rw-r--r--services/core/java/com/android/server/pm/InstallPackageHelper.java97
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java5
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java27
-rw-r--r--services/core/java/com/android/server/pm/RestrictionsSet.java61
-rw-r--r--services/core/java/com/android/server/pm/UserManagerInternal.java12
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java336
-rw-r--r--services/core/java/com/android/server/pm/UserTypeDetails.java19
-rw-r--r--services/core/java/com/android/server/pm/UserTypeFactory.java12
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java7
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java13
-rw-r--r--services/core/java/com/android/server/power/stats/BatteryStatsImpl.java250
-rw-r--r--services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java26
-rw-r--r--services/core/java/com/android/server/timedetector/NetworkTimeUpdateServiceShellCommand.java2
-rw-r--r--services/core/java/com/android/server/timedetector/ServerFlags.java11
-rw-r--r--services/core/java/com/android/server/vibrator/HalVibration.java2
-rw-r--r--services/core/java/com/android/server/vibrator/Vibration.java5
-rw-r--r--services/core/java/com/android/server/vibrator/VibratorManagerService.java211
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperDataParser.java61
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java80
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java121
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java7
-rw-r--r--services/core/java/com/android/server/wm/AsyncRotationController.java28
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java5
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java3
-rw-r--r--services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java34
-rw-r--r--services/core/java/com/android/server/wm/LetterboxConfiguration.java15
-rw-r--r--services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java27
-rw-r--r--services/core/java/com/android/server/wm/LetterboxConfigurationPersister.java4
-rw-r--r--services/core/java/com/android/server/wm/LetterboxUiController.java40
-rw-r--r--services/core/java/com/android/server/wm/Task.java49
-rw-r--r--services/core/java/com/android/server/wm/TaskDisplayArea.java9
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotController.java2
-rw-r--r--services/core/java/com/android/server/wm/Transition.java19
-rw-r--r--services/core/java/com/android/server/wm/TransitionController.java38
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java72
-rw-r--r--services/core/java/com/android/server/wm/WindowOrganizerController.java12
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java16
-rw-r--r--services/core/java/com/android/server/wm/WindowStateAnimator.java52
-rw-r--r--services/core/java/com/android/server/wm/WindowSurfaceController.java5
-rw-r--r--services/core/jni/com_android_server_companion_virtual_InputController.cpp470
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java22
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java6
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java237
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java5
-rw-r--r--services/robotests/src/com/android/server/media/OWNERS3
-rw-r--r--services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/RestrictionsSetTest.java3
-rw-r--r--services/tests/mockingservicestests/src/android/hardware/face/FaceManagerTest.java86
-rw-r--r--services/tests/mockingservicestests/src/android/hardware/fingerprint/FingerprintManagerTest.java88
-rw-r--r--services/tests/mockingservicestests/src/android/hardware/fingerprint/OWNERS2
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java42
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java62
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java41
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java225
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java221
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/am/UserControllerTest.java30
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/companion/virtual/InputManagerMockHelper.java5
-rw-r--r--services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java12
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/FakeEarcNativeWrapper.java (renamed from services/tests/servicestests/src/com/android/server/hdmi/FakeEArcNativeWrapper.java)14
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java127
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/hdmi/HdmiEarcLocalDeviceTxTest.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/power/LowPowerStandbyControllerTest.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsResetTest.java360
-rw-r--r--services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java8
-rw-r--r--services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsStoreTest.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/timedetector/NetworkTimeUpdateServiceTest.java88
-rw-r--r--services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java225
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java249
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java42
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java36
-rw-r--r--services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java13
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java28
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java12
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java31
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TransitionTests.java7
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java31
-rw-r--r--services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java13
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java34
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/DspTrustedHotwordDetectorSession.java13
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java4
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/SoftwareTrustedHotwordDetectorSession.java9
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VisualQueryDetectorSession.java27
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java7
-rw-r--r--services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java10
-rw-r--r--telecomm/java/android/telecom/CallControl.java32
-rw-r--r--telecomm/java/android/telecom/CallEventCallback.java14
-rw-r--r--telecomm/java/com/android/internal/telecom/ClientTransactionalServiceWrapper.java20
-rw-r--r--telecomm/java/com/android/internal/telecom/ICallControl.aidl2
-rw-r--r--telecomm/java/com/android/internal/telecom/ICallEventCallback.aidl3
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java44
-rw-r--r--telephony/java/android/telephony/satellite/ISatelliteDatagramCallback.aidl14
-rw-r--r--telephony/java/android/telephony/satellite/ISatelliteDatagramReceiverAck.aidl41
-rw-r--r--telephony/java/android/telephony/satellite/ISatellitePositionUpdateCallback.aidl8
-rw-r--r--telephony/java/android/telephony/satellite/ISatelliteStateCallback.aidl2
-rw-r--r--telephony/java/android/telephony/satellite/PointingInfo.java6
-rw-r--r--telephony/java/android/telephony/satellite/SatelliteCapabilities.java8
-rw-r--r--telephony/java/android/telephony/satellite/SatelliteDatagramCallback.java21
-rw-r--r--telephony/java/android/telephony/satellite/SatelliteManager.java307
-rw-r--r--telephony/java/android/telephony/satellite/SatellitePositionUpdateCallback.java16
-rw-r--r--telephony/java/android/telephony/satellite/SatelliteStateCallback.java6
-rw-r--r--telephony/java/android/telephony/satellite/stub/ISatellite.aidl17
-rw-r--r--telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl21
-rw-r--r--telephony/java/android/telephony/satellite/stub/NTRadioTechnology.aidl29
-rw-r--r--telephony/java/android/telephony/satellite/stub/PointingInfo.aidl10
-rw-r--r--telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java84
-rw-r--r--telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl29
-rw-r--r--telephony/java/com/android/internal/telephony/ISub.aidl2
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl59
-rw-r--r--test-mock/src/android/test/mock/MockContentProvider.java27
-rw-r--r--test-mock/src/android/test/mock/MockIContentProvider.java20
-rw-r--r--tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java3
-rw-r--r--tests/SilkFX/assets/gainmaps/granddam.jpgbin0 -> 1830308 bytes
-rw-r--r--tests/SilkFX/assets/gainmaps/lightbulb.jpgbin0 -> 2757109 bytes
-rw-r--r--tests/SilkFX/assets/gainmaps/porsche911.jpgbin0 -> 2869087 bytes
-rw-r--r--tools/processors/immutability/TEST_MAPPING7
-rw-r--r--wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java11
-rw-r--r--wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java52
438 files changed, 16178 insertions, 4597 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
index 4bddbd65c0c3..4caaa09f6a31 100644
--- a/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/DeviceIdleController.java
@@ -4589,6 +4589,22 @@ public class DeviceIdleController extends SystemService
Binder.restoreCallingIdentity(token);
}
}
+ } else if ("force-active".equals(cmd)) {
+ getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
+ null);
+ synchronized (this) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mForceIdle = true;
+ becomeActiveLocked("force-active", Process.myUid());
+ pw.print("Light state: ");
+ pw.print(lightStateToString(mLightState));
+ pw.print(", deep state: ");
+ pw.println(stateToString(mState));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
} else if ("force-idle".equals(cmd)) {
getContext().enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER,
null);
diff --git a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
index e2fff0f9af77..deb8a630e8a9 100644
--- a/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/alarm/AlarmManagerService.java
@@ -766,11 +766,11 @@ public class AlarmManagerService extends SystemService {
* Default quota for pre-S apps. The same as allowing an alarm slot once
* every ALLOW_WHILE_IDLE_LONG_DELAY, which was 9 minutes.
*/
- private static final int DEFAULT_ALLOW_WHILE_IDLE_COMPAT_QUOTA = 1;
+ private static final int DEFAULT_ALLOW_WHILE_IDLE_COMPAT_QUOTA = 7;
private static final int DEFAULT_ALLOW_WHILE_IDLE_QUOTA = 72;
private static final long DEFAULT_ALLOW_WHILE_IDLE_WINDOW = 60 * 60 * 1000; // 1 hour.
- private static final long DEFAULT_ALLOW_WHILE_IDLE_COMPAT_WINDOW = 9 * 60 * 1000; // 9 mins.
+ private static final long DEFAULT_ALLOW_WHILE_IDLE_COMPAT_WINDOW = 60 * 60 * 1000;
private static final long DEFAULT_PRIORITY_ALARM_DELAY = 9 * 60_000;
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 70bf3530eab3..4088a4832f96 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -478,7 +478,6 @@ public class JobSchedulerService extends com.android.server.SystemService
case Constants.KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS:
case Constants.KEY_RUNTIME_MIN_GUARANTEE_MS:
case Constants.KEY_RUNTIME_MIN_EJ_GUARANTEE_MS:
- case Constants.KEY_RUNTIME_MIN_HIGH_PRIORITY_GUARANTEE_MS:
case Constants.KEY_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS:
case Constants.KEY_RUNTIME_DATA_TRANSFER_LIMIT_MS:
case Constants.KEY_RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS:
@@ -575,8 +574,6 @@ public class JobSchedulerService extends com.android.server.SystemService
"runtime_free_quota_max_limit_ms";
private static final String KEY_RUNTIME_MIN_GUARANTEE_MS = "runtime_min_guarantee_ms";
private static final String KEY_RUNTIME_MIN_EJ_GUARANTEE_MS = "runtime_min_ej_guarantee_ms";
- private static final String KEY_RUNTIME_MIN_HIGH_PRIORITY_GUARANTEE_MS =
- "runtime_min_high_priority_guarantee_ms";
private static final String KEY_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS =
"runtime_min_data_transfer_guarantee_ms";
private static final String KEY_RUNTIME_DATA_TRANSFER_LIMIT_MS =
@@ -619,8 +616,6 @@ public class JobSchedulerService extends com.android.server.SystemService
public static final long DEFAULT_RUNTIME_MIN_GUARANTEE_MS = 10 * MINUTE_IN_MILLIS;
@VisibleForTesting
public static final long DEFAULT_RUNTIME_MIN_EJ_GUARANTEE_MS = 3 * MINUTE_IN_MILLIS;
- @VisibleForTesting
- static final long DEFAULT_RUNTIME_MIN_HIGH_PRIORITY_GUARANTEE_MS = 5 * MINUTE_IN_MILLIS;
public static final long DEFAULT_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS =
DEFAULT_RUNTIME_MIN_GUARANTEE_MS;
public static final long DEFAULT_RUNTIME_DATA_TRANSFER_LIMIT_MS =
@@ -744,12 +739,6 @@ public class JobSchedulerService extends com.android.server.SystemService
public long RUNTIME_MIN_EJ_GUARANTEE_MS = DEFAULT_RUNTIME_MIN_EJ_GUARANTEE_MS;
/**
- * The minimum amount of time we try to guarantee high priority jobs will run for.
- */
- public long RUNTIME_MIN_HIGH_PRIORITY_GUARANTEE_MS =
- DEFAULT_RUNTIME_MIN_HIGH_PRIORITY_GUARANTEE_MS;
-
- /**
* The minimum amount of time we try to guarantee normal data transfer jobs will run for.
*/
public long RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS =
@@ -895,7 +884,6 @@ public class JobSchedulerService extends com.android.server.SystemService
DeviceConfig.NAMESPACE_JOB_SCHEDULER,
KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
KEY_RUNTIME_MIN_GUARANTEE_MS, KEY_RUNTIME_MIN_EJ_GUARANTEE_MS,
- KEY_RUNTIME_MIN_HIGH_PRIORITY_GUARANTEE_MS,
KEY_RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_BUFFER_FACTOR,
KEY_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
KEY_RUNTIME_DATA_TRANSFER_LIMIT_MS,
@@ -908,11 +896,6 @@ public class JobSchedulerService extends com.android.server.SystemService
RUNTIME_MIN_GUARANTEE_MS = Math.max(10 * MINUTE_IN_MILLIS,
properties.getLong(
KEY_RUNTIME_MIN_GUARANTEE_MS, DEFAULT_RUNTIME_MIN_GUARANTEE_MS));
- // Make sure min runtime for high priority jobs is at least 4 minutes.
- RUNTIME_MIN_HIGH_PRIORITY_GUARANTEE_MS = Math.max(4 * MINUTE_IN_MILLIS,
- properties.getLong(
- KEY_RUNTIME_MIN_HIGH_PRIORITY_GUARANTEE_MS,
- DEFAULT_RUNTIME_MIN_HIGH_PRIORITY_GUARANTEE_MS));
// Make sure min runtime for expedited jobs is at least one minute.
RUNTIME_MIN_EJ_GUARANTEE_MS = Math.max(MINUTE_IN_MILLIS,
properties.getLong(
@@ -1008,8 +991,6 @@ public class JobSchedulerService extends com.android.server.SystemService
pw.print(KEY_RUNTIME_MIN_GUARANTEE_MS, RUNTIME_MIN_GUARANTEE_MS).println();
pw.print(KEY_RUNTIME_MIN_EJ_GUARANTEE_MS, RUNTIME_MIN_EJ_GUARANTEE_MS).println();
- pw.print(KEY_RUNTIME_MIN_HIGH_PRIORITY_GUARANTEE_MS,
- RUNTIME_MIN_HIGH_PRIORITY_GUARANTEE_MS).println();
pw.print(KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS, RUNTIME_FREE_QUOTA_MAX_LIMIT_MS)
.println();
pw.print(KEY_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
@@ -3333,8 +3314,6 @@ public class JobSchedulerService extends com.android.server.SystemService
return job.getEffectiveStandbyBucket() != RESTRICTED_INDEX
? mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS
: Math.min(mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS, 5 * MINUTE_IN_MILLIS);
- } else if (job.getEffectivePriority() >= JobInfo.PRIORITY_HIGH) {
- return mConstants.RUNTIME_MIN_HIGH_PRIORITY_GUARANTEE_MS;
} else {
return mConstants.RUNTIME_MIN_GUARANTEE_MS;
}
diff --git a/core/api/current.txt b/core/api/current.txt
index eef16bebea83..9955112649d3 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -9848,6 +9848,7 @@ package android.content {
method @Nullable public final String getReadPermission();
method @Nullable public String[] getStreamTypes(@NonNull android.net.Uri, @NonNull String);
method @Nullable public abstract String getType(@NonNull android.net.Uri);
+ method @Nullable public String getTypeAnonymous(@NonNull android.net.Uri);
method @Nullable public final String getWritePermission();
method @Nullable public abstract android.net.Uri insert(@NonNull android.net.Uri, @Nullable android.content.ContentValues);
method @Nullable public android.net.Uri insert(@NonNull android.net.Uri, @Nullable android.content.ContentValues, @Nullable android.os.Bundle);
@@ -33460,6 +33461,7 @@ package android.os {
field public static final String ACTION_LOW_POWER_STANDBY_ENABLED_CHANGED = "android.os.action.LOW_POWER_STANDBY_ENABLED_CHANGED";
field public static final String ACTION_LOW_POWER_STANDBY_POLICY_CHANGED = "android.os.action.LOW_POWER_STANDBY_POLICY_CHANGED";
field public static final String ACTION_POWER_SAVE_MODE_CHANGED = "android.os.action.POWER_SAVE_MODE_CHANGED";
+ field public static final String FEATURE_WAKE_ON_LAN_IN_LOW_POWER_STANDBY = "com.android.lowpowerstandby.WAKE_ON_LAN";
field @Deprecated public static final int FULL_WAKE_LOCK = 26; // 0x1a
field public static final int LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF = 2; // 0x2
field public static final int LOCATION_MODE_FOREGROUND_ONLY = 3; // 0x3
@@ -33469,7 +33471,6 @@ package android.os {
field public static final int LOW_POWER_STANDBY_ALLOWED_REASON_ONGOING_CALL = 4; // 0x4
field public static final int LOW_POWER_STANDBY_ALLOWED_REASON_TEMP_POWER_SAVE_ALLOWLIST = 2; // 0x2
field public static final int LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION = 1; // 0x1
- field public static final String LOW_POWER_STANDBY_FEATURE_WAKE_ON_LAN = "com.android.lowpowerstandby.WAKE_ON_LAN";
field public static final int ON_AFTER_RELEASE = 536870912; // 0x20000000
field public static final int PARTIAL_WAKE_LOCK = 1; // 0x1
field public static final int PROXIMITY_SCREEN_OFF_WAKE_LOCK = 32; // 0x20
@@ -41246,6 +41247,7 @@ package android.service.voice {
method public void setUiEnabled(boolean);
method public void show(android.os.Bundle, int);
method public void startAssistantActivity(android.content.Intent);
+ method public void startAssistantActivity(@NonNull android.content.Intent, @NonNull android.os.Bundle);
method public void startVoiceActivity(android.content.Intent);
method public final void unregisterVisibleActivityCallback(@NonNull android.service.voice.VoiceInteractionSession.VisibleActivityCallback);
field public static final String KEY_SHOW_SESSION_ID = "android.service.voice.SHOW_SESSION_ID";
@@ -42054,6 +42056,7 @@ package android.telecom {
method public void disconnect(@NonNull android.telecom.DisconnectCause, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
method @NonNull public android.os.ParcelUuid getCallId();
method public void requestCallEndpointChange(@NonNull android.telecom.CallEndpoint, @NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
+ method public void sendEvent(@NonNull String, @NonNull android.os.Bundle);
method public void setActive(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
method public void setInactive(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
method public void startCallStreaming(@NonNull java.util.concurrent.Executor, @NonNull android.os.OutcomeReceiver<java.lang.Void,android.telecom.CallException>);
@@ -42100,6 +42103,7 @@ package android.telecom {
method public void onAvailableCallEndpointsChanged(@NonNull java.util.List<android.telecom.CallEndpoint>);
method public void onCallEndpointChanged(@NonNull android.telecom.CallEndpoint);
method public void onCallStreamingFailed(int);
+ method public void onEvent(@NonNull String, @NonNull android.os.Bundle);
method public void onMuteStateChanged(boolean);
}
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 664961fa8346..8c0a9175fe94 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -10152,7 +10152,6 @@ package android.net.wifi.sharedconnectivity.service {
public abstract class SharedConnectivityService extends android.app.Service {
ctor public SharedConnectivityService();
- ctor public SharedConnectivityService(@NonNull android.os.Handler);
method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
method public abstract void onConnectKnownNetwork(@NonNull android.net.wifi.sharedconnectivity.app.KnownNetwork);
method public abstract void onConnectTetherNetwork(@NonNull android.net.wifi.sharedconnectivity.app.TetherNetwork);
@@ -10720,15 +10719,15 @@ package android.os {
public static final class PowerManager.LowPowerStandbyPortDescription {
ctor public PowerManager.LowPowerStandbyPortDescription(int, int, int);
- ctor public PowerManager.LowPowerStandbyPortDescription(int, int, int, @Nullable android.net.LinkAddress);
- method @Nullable public android.net.LinkAddress getBindAddress();
+ ctor public PowerManager.LowPowerStandbyPortDescription(int, int, int, @Nullable java.net.InetAddress);
+ method @Nullable public java.net.InetAddress getLocalAddress();
method public int getPortMatcher();
method public int getPortNumber();
method public int getProtocol();
field public static final int MATCH_PORT_LOCAL = 1; // 0x1
field public static final int MATCH_PORT_REMOTE = 2; // 0x2
- field public static final int PROTOCOL_TCP = 1; // 0x1
- field public static final int PROTOCOL_UDP = 2; // 0x2
+ field public static final int PROTOCOL_TCP = 6; // 0x6
+ field public static final int PROTOCOL_UDP = 17; // 0x11
}
public final class PowerManager.LowPowerStandbyPortsLock {
@@ -13041,6 +13040,34 @@ package android.service.voice {
method public int getStart();
}
+ public final class DetectedPhrase implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getId();
+ method @Nullable public String getPhrase();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.service.voice.DetectedPhrase> CREATOR;
+ }
+
+ public static final class DetectedPhrase.Builder {
+ ctor public DetectedPhrase.Builder();
+ method @NonNull public android.service.voice.DetectedPhrase build();
+ method @NonNull public android.service.voice.DetectedPhrase.Builder setId(int);
+ method @NonNull public android.service.voice.DetectedPhrase.Builder setPhrase(@NonNull String);
+ }
+
+ public abstract class DetectorFailure implements android.os.Parcelable {
+ method public int describeContents();
+ method @NonNull public String getErrorMessage();
+ method public abstract int getSuggestedAction();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field @NonNull public static final android.os.Parcelable.Creator<android.service.voice.DetectorFailure> CREATOR;
+ field public static final int SUGGESTED_ACTION_DISABLE_DETECTION = 2; // 0x2
+ field public static final int SUGGESTED_ACTION_NONE = 1; // 0x1
+ field public static final int SUGGESTED_ACTION_RECREATE_DETECTOR = 3; // 0x3
+ field public static final int SUGGESTED_ACTION_RESTART_RECOGNITION = 4; // 0x4
+ field public static final int SUGGESTED_ACTION_UNKNOWN = 0; // 0x0
+ }
+
public final class HotwordAudioStream implements android.os.Parcelable {
method public int describeContents();
method @NonNull public android.media.AudioFormat getAudioFormat();
@@ -13068,12 +13095,13 @@ package android.service.voice {
method public int getAudioChannel();
method @NonNull public java.util.List<android.service.voice.HotwordAudioStream> getAudioStreams();
method public int getConfidenceLevel();
+ method @NonNull public android.service.voice.DetectedPhrase getDetectedPhrase();
method @NonNull public android.os.PersistableBundle getExtras();
method public int getHotwordDurationMillis();
method public int getHotwordOffsetMillis();
- method public int getHotwordPhraseId();
+ method @Deprecated public int getHotwordPhraseId();
method public static int getMaxBundleSize();
- method public static int getMaxHotwordPhraseId();
+ method @Deprecated public static int getMaxHotwordPhraseId();
method public static int getMaxScore();
method @Nullable public android.media.MediaSyncEvent getMediaSyncEvent();
method public int getPersonalizedScore();
@@ -13102,11 +13130,12 @@ package android.service.voice {
method @NonNull public android.service.voice.HotwordDetectedResult.Builder setAudioChannel(int);
method @NonNull public android.service.voice.HotwordDetectedResult.Builder setAudioStreams(@NonNull java.util.List<android.service.voice.HotwordAudioStream>);
method @NonNull public android.service.voice.HotwordDetectedResult.Builder setConfidenceLevel(int);
+ method @NonNull public android.service.voice.HotwordDetectedResult.Builder setDetectedPhrase(@NonNull android.service.voice.DetectedPhrase);
method @NonNull public android.service.voice.HotwordDetectedResult.Builder setExtras(@NonNull android.os.PersistableBundle);
method @NonNull public android.service.voice.HotwordDetectedResult.Builder setHotwordDetectionPersonalized(boolean);
method @NonNull public android.service.voice.HotwordDetectedResult.Builder setHotwordDurationMillis(int);
method @NonNull public android.service.voice.HotwordDetectedResult.Builder setHotwordOffsetMillis(int);
- method @NonNull public android.service.voice.HotwordDetectedResult.Builder setHotwordPhraseId(int);
+ method @Deprecated @NonNull public android.service.voice.HotwordDetectedResult.Builder setHotwordPhraseId(int);
method @NonNull public android.service.voice.HotwordDetectedResult.Builder setMediaSyncEvent(@NonNull android.media.MediaSyncEvent);
method @NonNull public android.service.voice.HotwordDetectedResult.Builder setPersonalizedScore(int);
method @NonNull public android.service.voice.HotwordDetectedResult.Builder setScore(int);
@@ -13131,6 +13160,20 @@ package android.service.voice {
method public void onRejected(@NonNull android.service.voice.HotwordRejectedResult);
}
+ public final class HotwordDetectionServiceFailure extends android.service.voice.DetectorFailure {
+ method public int getErrorCode();
+ method public int getSuggestedAction();
+ field @NonNull public static final android.os.Parcelable.Creator<android.service.voice.HotwordDetectionServiceFailure> CREATOR;
+ field public static final int ERROR_CODE_BINDING_DIED = 2; // 0x2
+ field public static final int ERROR_CODE_BIND_FAILURE = 1; // 0x1
+ field public static final int ERROR_CODE_COPY_AUDIO_DATA_FAILURE = 3; // 0x3
+ field public static final int ERROR_CODE_DETECT_TIMEOUT = 4; // 0x4
+ field public static final int ERROR_CODE_ON_DETECTED_SECURITY_EXCEPTION = 5; // 0x5
+ field public static final int ERROR_CODE_ON_DETECTED_STREAM_COPY_FAILURE = 6; // 0x6
+ field public static final int ERROR_CODE_REMOTE_EXCEPTION = 7; // 0x7
+ field public static final int ERROR_CODE_UNKNOWN = 0; // 0x0
+ }
+
public interface HotwordDetector {
method public default void destroy();
method @RequiresPermission(allOf={android.Manifest.permission.RECORD_AUDIO, android.Manifest.permission.CAPTURE_AUDIO_HOTWORD}) public boolean startRecognition() throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
@@ -13141,7 +13184,8 @@ package android.service.voice {
public static interface HotwordDetector.Callback {
method public void onDetected(@NonNull android.service.voice.AlwaysOnHotwordDetector.EventPayload);
- method public void onError();
+ method @Deprecated public void onError();
+ method public default void onFailure(@NonNull android.service.voice.DetectorFailure);
method public void onHotwordDetectionServiceInitialized(int);
method public void onHotwordDetectionServiceRestarted();
method public void onRecognitionPaused();
@@ -13176,6 +13220,21 @@ package android.service.voice {
field public static final int INITIALIZATION_STATUS_UNKNOWN = 100; // 0x64
}
+ public final class SoundTriggerFailure extends android.service.voice.DetectorFailure {
+ method public int getErrorCode();
+ method public int getSuggestedAction();
+ field @NonNull public static final android.os.Parcelable.Creator<android.service.voice.SoundTriggerFailure> CREATOR;
+ field public static final int ERROR_CODE_MODULE_DIED = 1; // 0x1
+ field public static final int ERROR_CODE_RECOGNITION_RESUME_FAILED = 2; // 0x2
+ field public static final int ERROR_CODE_UNEXPECTED_PREEMPTION = 3; // 0x3
+ field public static final int ERROR_CODE_UNKNOWN = 0; // 0x0
+ }
+
+ public final class UnknownFailure extends android.service.voice.DetectorFailure {
+ method public int getSuggestedAction();
+ field @NonNull public static final android.os.Parcelable.Creator<android.service.voice.UnknownFailure> CREATOR;
+ }
+
public abstract class VisualQueryDetectionService extends android.app.Service implements android.service.voice.SandboxedDetectionServiceBase {
ctor public VisualQueryDetectionService();
method @Nullable public android.os.IBinder onBind(@NonNull android.content.Intent);
@@ -13194,6 +13253,18 @@ package android.service.voice {
method public void onQueryRejected() throws java.lang.IllegalStateException;
}
+ public final class VisualQueryDetectionServiceFailure extends android.service.voice.DetectorFailure {
+ method public int getErrorCode();
+ method public int getSuggestedAction();
+ field @NonNull public static final android.os.Parcelable.Creator<android.service.voice.VisualQueryDetectionServiceFailure> CREATOR;
+ field public static final int ERROR_CODE_BINDING_DIED = 2; // 0x2
+ field public static final int ERROR_CODE_BIND_FAILURE = 1; // 0x1
+ field public static final int ERROR_CODE_ILLEGAL_ATTENTION_STATE = 3; // 0x3
+ field public static final int ERROR_CODE_ILLEGAL_STREAMING_STATE = 4; // 0x4
+ field public static final int ERROR_CODE_REMOTE_EXCEPTION = 5; // 0x5
+ field public static final int ERROR_CODE_UNKNOWN = 0; // 0x0
+ }
+
public class VisualQueryDetector {
method public void destroy();
method @RequiresPermission(allOf={android.Manifest.permission.CAMERA, android.Manifest.permission.RECORD_AUDIO}) public boolean startRecognition() throws android.service.voice.HotwordDetector.IllegalDetectorStateException;
@@ -13202,7 +13273,7 @@ package android.service.voice {
}
public static interface VisualQueryDetector.Callback {
- method public void onError();
+ method public void onFailure(@NonNull android.service.voice.DetectorFailure);
method public void onQueryDetected(@NonNull String);
method public void onQueryFinished();
method public void onQueryRejected();
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index c0cd6386aec2..def3fa93ce3c 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -985,7 +985,7 @@ package android.content.pm {
method public boolean isInitialized();
method public boolean isMain();
method public boolean isManagedProfile();
- method public boolean isPrimary();
+ method @Deprecated public boolean isPrimary();
method public boolean isProfile();
method public boolean isQuietModeEnabled();
method public boolean isRestricted();
@@ -1002,7 +1002,7 @@ package android.content.pm {
field public static final int FLAG_INITIALIZED = 16; // 0x10
field public static final int FLAG_MAIN = 16384; // 0x4000
field @Deprecated public static final int FLAG_MANAGED_PROFILE = 32; // 0x20
- field public static final int FLAG_PRIMARY = 1; // 0x1
+ field @Deprecated public static final int FLAG_PRIMARY = 1; // 0x1
field public static final int FLAG_PROFILE = 4096; // 0x1000
field public static final int FLAG_QUIET_MODE = 128; // 0x80
field @Deprecated public static final int FLAG_RESTRICTED = 8; // 0x8
@@ -1444,6 +1444,7 @@ package android.hardware.display {
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setUserDisabledHdrTypes(@NonNull int[]);
method @RequiresPermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS) public boolean shouldAlwaysRespectAppRequestedMode();
field public static final String DISPLAY_CATEGORY_REAR = "android.hardware.display.category.REAR";
+ field public static final String HDR_OUTPUT_CONTROL_FLAG = "enable_hdr_output_control";
field public static final int SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS = 2; // 0x2
field public static final int SWITCHING_TYPE_NONE = 0; // 0x0
field public static final int SWITCHING_TYPE_RENDER_FRAME_RATE_ONLY = 3; // 0x3
@@ -2796,10 +2797,26 @@ package android.service.voice {
field public static final boolean ENABLE_PROXIMITY_RESULT = true;
}
+ public final class HotwordDetectionServiceFailure extends android.service.voice.DetectorFailure {
+ ctor public HotwordDetectionServiceFailure(int, @NonNull String);
+ }
+
+ public final class SoundTriggerFailure extends android.service.voice.DetectorFailure {
+ ctor public SoundTriggerFailure(int, @NonNull String);
+ }
+
+ public final class UnknownFailure extends android.service.voice.DetectorFailure {
+ ctor public UnknownFailure(@NonNull String);
+ }
+
public final class VisibleActivityInfo implements android.os.Parcelable {
ctor public VisibleActivityInfo(int, @NonNull android.os.IBinder);
}
+ public final class VisualQueryDetectionServiceFailure extends android.service.voice.DetectorFailure {
+ ctor public VisualQueryDetectionServiceFailure(int, @NonNull String);
+ }
+
public class VoiceInteractionService extends android.app.Service {
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_HOTWORD_DETECTION) public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetectorForTest(@NonNull String, @NonNull java.util.Locale, @NonNull android.hardware.soundtrigger.SoundTrigger.ModuleProperties, @NonNull java.util.concurrent.Executor, @NonNull android.service.voice.AlwaysOnHotwordDetector.Callback);
method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_HOTWORD_DETECTION) public final android.service.voice.AlwaysOnHotwordDetector createAlwaysOnHotwordDetectorForTest(@NonNull String, @NonNull java.util.Locale, @Nullable android.os.PersistableBundle, @Nullable android.os.SharedMemory, @NonNull android.hardware.soundtrigger.SoundTrigger.ModuleProperties, @NonNull java.util.concurrent.Executor, @NonNull android.service.voice.AlwaysOnHotwordDetector.Callback);
@@ -3294,6 +3311,7 @@ package android.view {
public interface WindowManager extends android.view.ViewManager {
method public default int getDisplayImePolicy(int);
+ method public static boolean hasWindowExtensionsEnabled();
method public default void holdLock(android.os.IBinder, int);
method public default boolean isGlobalKey(int);
method public default boolean isTaskSnapshotSupported();
@@ -3716,7 +3734,7 @@ package android.window {
public final class TaskFragmentCreationParams implements android.os.Parcelable {
method @NonNull public android.os.IBinder getFragmentToken();
- method @NonNull public android.graphics.Rect getInitialBounds();
+ method @NonNull public android.graphics.Rect getInitialRelativeBounds();
method @NonNull public android.window.TaskFragmentOrganizerToken getOrganizer();
method @NonNull public android.os.IBinder getOwnerToken();
method public int getWindowingMode();
@@ -3726,7 +3744,7 @@ package android.window {
public static final class TaskFragmentCreationParams.Builder {
ctor public TaskFragmentCreationParams.Builder(@NonNull android.window.TaskFragmentOrganizerToken, @NonNull android.os.IBinder, @NonNull android.os.IBinder);
method @NonNull public android.window.TaskFragmentCreationParams build();
- method @NonNull public android.window.TaskFragmentCreationParams.Builder setInitialBounds(@NonNull android.graphics.Rect);
+ method @NonNull public android.window.TaskFragmentCreationParams.Builder setInitialRelativeBounds(@NonNull android.graphics.Rect);
method @NonNull public android.window.TaskFragmentCreationParams.Builder setWindowingMode(int);
}
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index aa5b86679849..f653e132f7e3 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -347,7 +347,7 @@ interface IActivityManager {
String getProviderMimeType(in Uri uri, int userId);
oneway void getProviderMimeTypeAsync(in Uri uri, int userId, in RemoteCallback resultCallback);
-
+ oneway void getMimeTypeFilterAsync(in Uri uri, int userId, in RemoteCallback resultCallback);
// Cause the specified process to dump the specified heap.
boolean dumpHeap(in String process, int userId, boolean managed, boolean mallocInfo,
boolean runGc, in String path, in ParcelFileDescriptor fd,
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 3a3ad8cef1e9..ef5cd9334be7 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -4634,8 +4634,8 @@ public class Notification implements Parcelable
* Set whether this is an "ongoing" notification.
*
* Ongoing notifications cannot be dismissed by the user on locked devices, or by
- * notification listeners, and some notifications cannnot be dismissed on unlocked
- * devices (system, device management, media), so your application or service must take
+ * notification listeners, and some notifications (device management, media) cannot be
+ * dismissed on unlocked devices, so your application or service must take
* care of canceling them.
*
* They are typically used to indicate a background task that the user is actively engaged
@@ -5249,17 +5249,17 @@ public class Notification implements Parcelable
boolean hasSecondLine = showProgress;
if (p.hasTitle()) {
contentView.setViewVisibility(p.mTitleViewId, View.VISIBLE);
- contentView.setTextViewText(p.mTitleViewId, processTextSpans(p.title));
+ contentView.setTextViewText(p.mTitleViewId, processTextSpans(p.mTitle));
setTextViewColorPrimary(contentView, p.mTitleViewId, p);
} else if (p.mTitleViewId != R.id.title) {
// This alternate title view ID is not cleared by resetStandardTemplate
contentView.setViewVisibility(p.mTitleViewId, View.GONE);
contentView.setTextViewText(p.mTitleViewId, null);
}
- if (p.text != null && p.text.length() != 0
+ if (p.mText != null && p.mText.length() != 0
&& (!showProgress || p.mAllowTextWithProgress)) {
contentView.setViewVisibility(p.mTextViewId, View.VISIBLE);
- contentView.setTextViewText(p.mTextViewId, processTextSpans(p.text));
+ contentView.setTextViewText(p.mTextViewId, processTextSpans(p.mText));
setTextViewColorSecondary(contentView, p.mTextViewId, p);
hasSecondLine = true;
} else if (p.mTextViewId != R.id.text) {
@@ -5533,20 +5533,20 @@ public class Notification implements Parcelable
if (p.mHideSubText) {
return false;
}
- CharSequence summaryText = p.summaryText;
- if (summaryText == null && mStyle != null && mStyle.mSummaryTextSet
+ CharSequence headerText = p.mSubText;
+ if (headerText == null && mStyle != null && mStyle.mSummaryTextSet
&& mStyle.hasSummaryInHeader()) {
- summaryText = mStyle.mSummaryText;
+ headerText = mStyle.mSummaryText;
}
- if (summaryText == null
+ if (headerText == null
&& mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N
&& mN.extras.getCharSequence(EXTRA_INFO_TEXT) != null) {
- summaryText = mN.extras.getCharSequence(EXTRA_INFO_TEXT);
+ headerText = mN.extras.getCharSequence(EXTRA_INFO_TEXT);
}
- if (!TextUtils.isEmpty(summaryText)) {
+ if (!TextUtils.isEmpty(headerText)) {
// TODO: Remove the span entirely to only have the string with propper formating.
contentView.setTextViewText(R.id.header_text, processTextSpans(
- processLegacyText(summaryText)));
+ processLegacyText(headerText)));
setTextViewColorSecondary(contentView, R.id.header_text, p);
contentView.setViewVisibility(R.id.header_text, View.VISIBLE);
if (hasTextToLeft) {
@@ -5566,9 +5566,9 @@ public class Notification implements Parcelable
if (p.mHideSubText) {
return false;
}
- if (!TextUtils.isEmpty(p.headerTextSecondary)) {
+ if (!TextUtils.isEmpty(p.mHeaderTextSecondary)) {
contentView.setTextViewText(R.id.header_text_secondary, processTextSpans(
- processLegacyText(p.headerTextSecondary)));
+ processLegacyText(p.mHeaderTextSecondary)));
setTextViewColorSecondary(contentView, R.id.header_text_secondary, p);
contentView.setViewVisibility(R.id.header_text_secondary, View.VISIBLE);
if (hasTextToLeft) {
@@ -6175,7 +6175,7 @@ public class Notification implements Parcelable
.viewType(StandardTemplateParams.VIEW_TYPE_MINIMIZED)
.highlightExpander(false)
.fillTextsFrom(this);
- if (!useRegularSubtext || TextUtils.isEmpty(p.summaryText)) {
+ if (!useRegularSubtext || TextUtils.isEmpty(p.mSubText)) {
p.summaryText(createSummaryText());
}
RemoteViews header = makeNotificationHeader(p);
@@ -6992,8 +6992,10 @@ public class Notification implements Parcelable
/**
* Returns whether an app can colorize due to the android.permission.USE_COLORIZED_NOTIFICATIONS
* permission. The permission is checked when a notification is enqueued.
+ *
+ * @hide
*/
- private boolean hasColorizedPermission() {
+ public boolean hasColorizedPermission() {
return (flags & Notification.FLAG_CAN_COLORIZE) != 0;
}
@@ -7190,7 +7192,7 @@ public class Notification implements Parcelable
checkBuilder();
if (mBigContentTitle != null) {
- p.title = mBigContentTitle;
+ p.mTitle = mBigContentTitle;
}
return mBuilder.applyStandardTemplateWithActions(layoutId, p, result);
@@ -12453,10 +12455,10 @@ public class Notification implements Parcelable
boolean mAllowTextWithProgress;
int mTitleViewId;
int mTextViewId;
- CharSequence title;
- CharSequence text;
- CharSequence headerTextSecondary;
- CharSequence summaryText;
+ @Nullable CharSequence mTitle;
+ @Nullable CharSequence mText;
+ @Nullable CharSequence mHeaderTextSecondary;
+ @Nullable CharSequence mSubText;
int maxRemoteInputHistory = Style.MAX_REMOTE_INPUT_HISTORY_LINES;
boolean allowColorization = true;
boolean mHighlightExpander = false;
@@ -12478,10 +12480,10 @@ public class Notification implements Parcelable
mAllowTextWithProgress = false;
mTitleViewId = R.id.title;
mTextViewId = R.id.text;
- title = null;
- text = null;
- summaryText = null;
- headerTextSecondary = null;
+ mTitle = null;
+ mText = null;
+ mSubText = null;
+ mHeaderTextSecondary = null;
maxRemoteInputHistory = Style.MAX_REMOTE_INPUT_HISTORY_LINES;
allowColorization = true;
mHighlightExpander = false;
@@ -12489,7 +12491,7 @@ public class Notification implements Parcelable
}
final boolean hasTitle() {
- return !TextUtils.isEmpty(title) && !mHideTitle;
+ return !TextUtils.isEmpty(mTitle) && !mHideTitle;
}
final StandardTemplateParams viewType(int viewType) {
@@ -12562,23 +12564,23 @@ public class Notification implements Parcelable
return this;
}
- final StandardTemplateParams title(CharSequence title) {
- this.title = title;
+ final StandardTemplateParams title(@Nullable CharSequence title) {
+ this.mTitle = title;
return this;
}
- final StandardTemplateParams text(CharSequence text) {
- this.text = text;
+ final StandardTemplateParams text(@Nullable CharSequence text) {
+ this.mText = text;
return this;
}
- final StandardTemplateParams summaryText(CharSequence text) {
- this.summaryText = text;
+ final StandardTemplateParams summaryText(@Nullable CharSequence text) {
+ this.mSubText = text;
return this;
}
- final StandardTemplateParams headerTextSecondary(CharSequence text) {
- this.headerTextSecondary = text;
+ final StandardTemplateParams headerTextSecondary(@Nullable CharSequence text) {
+ this.mHeaderTextSecondary = text;
return this;
}
@@ -12605,9 +12607,9 @@ public class Notification implements Parcelable
final StandardTemplateParams fillTextsFrom(Builder b) {
Bundle extras = b.mN.extras;
- this.title = b.processLegacyText(extras.getCharSequence(EXTRA_TITLE));
- this.text = b.processLegacyText(extras.getCharSequence(EXTRA_TEXT));
- this.summaryText = extras.getCharSequence(EXTRA_SUB_TEXT);
+ this.mTitle = b.processLegacyText(extras.getCharSequence(EXTRA_TITLE));
+ this.mText = b.processLegacyText(extras.getCharSequence(EXTRA_TEXT));
+ this.mSubText = extras.getCharSequence(EXTRA_SUB_TEXT);
return this;
}
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 4330831642db..91efa755e4c9 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -318,7 +318,10 @@ public class NotificationManager {
/**
* Intent that is broadcast when the state of {@link #getEffectsSuppressor()} changes.
- * This broadcast is only sent to registered receivers.
+ *
+ * <p>This broadcast is only sent to registered receivers and (starting from
+ * {@link Build.VERSION_CODES#Q}) receivers in packages that have been granted Do Not
+ * Disturb access (see {@link #isNotificationPolicyAccessGranted()}).
*
* @hide
*/
@@ -338,7 +341,10 @@ public class NotificationManager {
/**
* Intent that is broadcast when the state of getNotificationPolicy() changes.
- * This broadcast is only sent to registered receivers.
+ *
+ * <p>This broadcast is only sent to registered receivers and (starting from
+ * {@link Build.VERSION_CODES#Q}) receivers in packages that have been granted Do Not
+ * Disturb access (see {@link #isNotificationPolicyAccessGranted()}).
*/
@SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_NOTIFICATION_POLICY_CHANGED
@@ -346,7 +352,10 @@ public class NotificationManager {
/**
* Intent that is broadcast when the state of getCurrentInterruptionFilter() changes.
- * This broadcast is only sent to registered receivers.
+ *
+ * <p>This broadcast is only sent to registered receivers and (starting from
+ * {@link Build.VERSION_CODES#Q}) receivers in packages that have been granted Do Not
+ * Disturb access (see {@link #isNotificationPolicyAccessGranted()}).
*/
@SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION)
public static final String ACTION_INTERRUPTION_FILTER_CHANGED
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index a331b404047b..024141777604 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -5462,7 +5462,8 @@ public class DevicePolicyManager {
public boolean isActivePasswordSufficient() {
if (mService != null) {
try {
- return mService.isActivePasswordSufficient(myUserId(), mParentInstance);
+ return mService.isActivePasswordSufficient(
+ mContext.getPackageName(), myUserId(), mParentInstance);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -5619,7 +5620,8 @@ public class DevicePolicyManager {
}
try {
- return mService.getRequiredPasswordComplexity(mParentInstance);
+ return mService.getRequiredPasswordComplexity(
+ mContext.getPackageName(), mParentInstance);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -5743,7 +5745,8 @@ public class DevicePolicyManager {
public int getCurrentFailedPasswordAttempts(int userHandle) {
if (mService != null) {
try {
- return mService.getCurrentFailedPasswordAttempts(userHandle, mParentInstance);
+ return mService.getCurrentFailedPasswordAttempts(
+ mContext.getPackageName(), userHandle, mParentInstance);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -16643,7 +16646,7 @@ public class DevicePolicyManager {
return null;
}
try {
- return mService.getWifiSsidPolicy();
+ return mService.getWifiSsidPolicy(mContext.getPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 3a75da340745..51aff9ef71ba 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -96,15 +96,15 @@ interface IDevicePolicyManager {
long getPasswordExpiration(in ComponentName who, int userHandle, boolean parent);
- boolean isActivePasswordSufficient(int userHandle, boolean parent);
+ boolean isActivePasswordSufficient(String callerPackageName, int userHandle, boolean parent);
boolean isActivePasswordSufficientForDeviceRequirement();
boolean isPasswordSufficientAfterProfileUnification(int userHandle, int profileUser);
int getPasswordComplexity(boolean parent);
void setRequiredPasswordComplexity(String callerPackageName, int passwordComplexity, boolean parent);
- int getRequiredPasswordComplexity(boolean parent);
+ int getRequiredPasswordComplexity(String callerPackageName, boolean parent);
int getAggregatedPasswordComplexityForUser(int userId, boolean deviceWideOnly);
boolean isUsingUnifiedPassword(in ComponentName admin);
- int getCurrentFailedPasswordAttempts(int userHandle, boolean parent);
+ int getCurrentFailedPasswordAttempts(String callerPackageName, int userHandle, boolean parent);
int getProfileWithMinimumFailedPasswordsForWipe(int userHandle, boolean parent);
void setMaximumFailedPasswordsForWipe(
@@ -572,7 +572,7 @@ interface IDevicePolicyManager {
int getMinimumRequiredWifiSecurityLevel();
void setWifiSsidPolicy(String callerPackageName, in WifiSsidPolicy policy);
- WifiSsidPolicy getWifiSsidPolicy();
+ WifiSsidPolicy getWifiSsidPolicy(String callerPackageName);
List<UserHandle> listForegroundAffiliatedUsers();
void setDrawables(in List<DevicePolicyDrawableResource> drawables);
diff --git a/core/java/android/companion/CompanionDeviceManager.java b/core/java/android/companion/CompanionDeviceManager.java
index 5df2d5e1de35..de4f619392c1 100644
--- a/core/java/android/companion/CompanionDeviceManager.java
+++ b/core/java/android/companion/CompanionDeviceManager.java
@@ -1194,6 +1194,20 @@ public final class CompanionDeviceManager {
}
}
+ /**
+ * Enable or disable secure transport for testing. Defaults to enabled.
+ *
+ * @param enabled true to enable. false to disable.
+ * @hide
+ */
+ public void enableSecureTransport(boolean enabled) {
+ try {
+ mService.enableSecureTransport(enabled);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
private boolean checkFeaturePresent() {
boolean featurePresent = mService != null;
if (!featurePresent && DEBUG) {
diff --git a/core/java/android/companion/ICompanionDeviceManager.aidl b/core/java/android/companion/ICompanionDeviceManager.aidl
index 010aa8f8a504..cb4baca73ba0 100644
--- a/core/java/android/companion/ICompanionDeviceManager.aidl
+++ b/core/java/android/companion/ICompanionDeviceManager.aidl
@@ -88,4 +88,6 @@ interface ICompanionDeviceManager {
void enableSystemDataSync(int associationId, int flags);
void disableSystemDataSync(int associationId, int flags);
+
+ void enableSecureTransport(boolean enabled);
}
diff --git a/core/java/android/content/ContentCaptureOptions.java b/core/java/android/content/ContentCaptureOptions.java
index 77072890a1eb..856bde870bcf 100644
--- a/core/java/android/content/ContentCaptureOptions.java
+++ b/core/java/android/content/ContentCaptureOptions.java
@@ -70,6 +70,12 @@ public final class ContentCaptureOptions implements Parcelable {
public final int logHistorySize;
/**
+ * Disable flush when receiving a VIEW_TREE_APPEARING event.
+ * @hide
+ */
+ public final boolean disableFlushForViewTreeAppearing;
+
+ /**
* List of activities explicitly allowlisted for content capture (or {@code null} if allowlisted
* for all acitivites in the package).
*/
@@ -90,7 +96,8 @@ public final class ContentCaptureOptions implements Parcelable {
public ContentCaptureOptions(int loggingLevel) {
this(/* lite= */ true, loggingLevel, /* maxBufferSize= */ 0,
/* idleFlushingFrequencyMs= */ 0, /* textChangeFlushingFrequencyMs= */ 0,
- /* logHistorySize= */ 0, /* whitelistedComponents= */ null);
+ /* logHistorySize= */ 0, /* disableFlushForViewTreeAppearing= */ false,
+ /* whitelistedComponents= */ null);
}
/**
@@ -98,10 +105,23 @@ public final class ContentCaptureOptions implements Parcelable {
*/
public ContentCaptureOptions(int loggingLevel, int maxBufferSize, int idleFlushingFrequencyMs,
int textChangeFlushingFrequencyMs, int logHistorySize,
- @SuppressLint("NullableCollection")
+ @SuppressLint({"ConcreteCollection", "NullableCollection"})
+ @Nullable ArraySet<ComponentName> whitelistedComponents) {
+ this(/* lite= */ false, loggingLevel, maxBufferSize, idleFlushingFrequencyMs,
+ textChangeFlushingFrequencyMs, logHistorySize,
+ ContentCaptureManager.DEFAULT_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING,
+ whitelistedComponents);
+ }
+
+ /** @hide */
+ public ContentCaptureOptions(int loggingLevel, int maxBufferSize, int idleFlushingFrequencyMs,
+ int textChangeFlushingFrequencyMs, int logHistorySize,
+ boolean disableFlushForViewTreeAppearing,
+ @SuppressLint({"ConcreteCollection", "NullableCollection"})
@Nullable ArraySet<ComponentName> whitelistedComponents) {
this(/* lite= */ false, loggingLevel, maxBufferSize, idleFlushingFrequencyMs,
- textChangeFlushingFrequencyMs, logHistorySize, whitelistedComponents);
+ textChangeFlushingFrequencyMs, logHistorySize, disableFlushForViewTreeAppearing,
+ whitelistedComponents);
}
/** @hide */
@@ -111,11 +131,14 @@ public final class ContentCaptureOptions implements Parcelable {
ContentCaptureManager.DEFAULT_MAX_BUFFER_SIZE,
ContentCaptureManager.DEFAULT_IDLE_FLUSHING_FREQUENCY_MS,
ContentCaptureManager.DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS,
- ContentCaptureManager.DEFAULT_LOG_HISTORY_SIZE, whitelistedComponents);
+ ContentCaptureManager.DEFAULT_LOG_HISTORY_SIZE,
+ ContentCaptureManager.DEFAULT_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING,
+ whitelistedComponents);
}
private ContentCaptureOptions(boolean lite, int loggingLevel, int maxBufferSize,
int idleFlushingFrequencyMs, int textChangeFlushingFrequencyMs, int logHistorySize,
+ boolean disableFlushForViewTreeAppearing,
@Nullable ArraySet<ComponentName> whitelistedComponents) {
this.lite = lite;
this.loggingLevel = loggingLevel;
@@ -123,6 +146,7 @@ public final class ContentCaptureOptions implements Parcelable {
this.idleFlushingFrequencyMs = idleFlushingFrequencyMs;
this.textChangeFlushingFrequencyMs = textChangeFlushingFrequencyMs;
this.logHistorySize = logHistorySize;
+ this.disableFlushForViewTreeAppearing = disableFlushForViewTreeAppearing;
this.whitelistedComponents = whitelistedComponents;
}
@@ -171,7 +195,8 @@ public final class ContentCaptureOptions implements Parcelable {
.append(", maxBufferSize=").append(maxBufferSize)
.append(", idleFlushingFrequencyMs=").append(idleFlushingFrequencyMs)
.append(", textChangeFlushingFrequencyMs=").append(textChangeFlushingFrequencyMs)
- .append(", logHistorySize=").append(logHistorySize);
+ .append(", logHistorySize=").append(logHistorySize)
+ .append(", disableFlushForViewTreeAppearing=").append(disableFlushForViewTreeAppearing);
if (whitelistedComponents != null) {
string.append(", whitelisted=").append(whitelistedComponents);
}
@@ -189,6 +214,7 @@ public final class ContentCaptureOptions implements Parcelable {
pw.print(", idle="); pw.print(idleFlushingFrequencyMs);
pw.print(", textIdle="); pw.print(textChangeFlushingFrequencyMs);
pw.print(", logSize="); pw.print(logHistorySize);
+ pw.print(", disableFlushForViewTreeAppearing="); pw.print(disableFlushForViewTreeAppearing);
if (whitelistedComponents != null) {
pw.print(", whitelisted="); pw.print(whitelistedComponents);
}
@@ -209,6 +235,7 @@ public final class ContentCaptureOptions implements Parcelable {
parcel.writeInt(idleFlushingFrequencyMs);
parcel.writeInt(textChangeFlushingFrequencyMs);
parcel.writeInt(logHistorySize);
+ parcel.writeBoolean(disableFlushForViewTreeAppearing);
parcel.writeArraySet(whitelistedComponents);
}
@@ -226,12 +253,13 @@ public final class ContentCaptureOptions implements Parcelable {
final int idleFlushingFrequencyMs = parcel.readInt();
final int textChangeFlushingFrequencyMs = parcel.readInt();
final int logHistorySize = parcel.readInt();
+ final boolean disableFlushForViewTreeAppearing = parcel.readBoolean();
@SuppressWarnings("unchecked")
final ArraySet<ComponentName> whitelistedComponents =
(ArraySet<ComponentName>) parcel.readArraySet(null);
return new ContentCaptureOptions(loggingLevel, maxBufferSize,
idleFlushingFrequencyMs, textChangeFlushingFrequencyMs, logHistorySize,
- whitelistedComponents);
+ disableFlushForViewTreeAppearing, whitelistedComponents);
}
@Override
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index e8f0a89930ad..795c77ff5105 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -18,14 +18,15 @@ package android.content;
import static android.Manifest.permission.INTERACT_ACROSS_USERS;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+import static android.os.Process.SYSTEM_UID;
import static android.os.Process.myUserHandle;
import static android.os.Trace.TRACE_TAG_DATABASE;
import static com.android.internal.util.FrameworkStatsLog.GET_TYPE_ACCESSED_WITHOUT_PERMISSION;
import static com.android.internal.util.FrameworkStatsLog.GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__PROVIDER_CHECK_URI_PERMISSION;
-import static com.android.internal.util.FrameworkStatsLog.GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__PROVIDER_ERROR;
import static com.android.internal.util.FrameworkStatsLog.GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__PROVIDER_FRAMEWORK_PERMISSION;
+import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -300,17 +301,32 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
}
@Override
- public String getType(Uri uri) {
+ public String getType(AttributionSource attributionSource, Uri uri) {
// getCallingPackage() isn't available in getType(), as the javadoc states.
uri = validateIncomingUri(uri);
uri = maybeGetUriWithoutUserId(uri);
traceBegin(TRACE_TAG_DATABASE, "getType: ", uri.getAuthority());
try {
- final String type = mInterface.getType(uri);
- if (type != null) {
- logGetTypeData(Binder.getCallingUid(), uri, type);
+ if (checkGetTypePermission(attributionSource, uri)
+ == PermissionChecker.PERMISSION_GRANTED) {
+ final String type = mInterface.getType(uri);
+ if (type != null) {
+ logGetTypeData(Binder.getCallingUid(), uri, type, true);
+ }
+ return type;
+ } else {
+ final int callingUid = Binder.getCallingUid();
+ final long origId = Binder.clearCallingIdentity();
+ try {
+ final String type = getTypeAnonymous(uri);
+ if (type != null) {
+ logGetTypeData(callingUid, uri, type, false);
+ }
+ return type;
+ } finally {
+ Binder.restoreCallingIdentity(origId);
+ }
}
- return type;
} catch (RemoteException e) {
throw e.rethrowAsRuntimeException();
} finally {
@@ -319,59 +335,63 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
}
// Utility function to log the getTypeData calls
- private void logGetTypeData(int callingUid, Uri uri, String type) {
+ private void logGetTypeData(int callingUid, Uri uri, String type,
+ boolean permissionCheckPassed) {
final int enumFrameworkPermission =
GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__PROVIDER_FRAMEWORK_PERMISSION;
final int enumCheckUriPermission =
GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__PROVIDER_CHECK_URI_PERMISSION;
- final int enumError = GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__PROVIDER_ERROR;
-
- try {
- final AttributionSource attributionSource = new AttributionSource.Builder(
- callingUid).build();
+ if (permissionCheckPassed) {
try {
- if (enforceReadPermission(attributionSource, uri)
- != PermissionChecker.PERMISSION_GRANTED) {
+ // Just for logging for mediaProvider cases
+ final ProviderInfo cpi = mContext.getPackageManager()
+ .resolveContentProvider(uri.getAuthority(),
+ PackageManager.ComponentInfoFlags.of(
+ PackageManager.GET_META_DATA));
+ final int callingUserId = UserHandle.getUserId(callingUid);
+ final Uri userUri = (mSingleUser
+ && !UserHandle.isSameUser(mMyUid, callingUid))
+ ? maybeAddUserId(uri, callingUserId) : uri;
+ if (cpi.forceUriPermissions
+ && mInterface.checkUriPermission(uri,
+ callingUid, Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ != PermissionChecker.PERMISSION_GRANTED
+ && getContext().checkUriPermission(userUri, Binder.getCallingPid(),
+ callingUid, Intent.FLAG_GRANT_READ_URI_PERMISSION)
+ != PackageManager.PERMISSION_GRANTED) {
FrameworkStatsLog.write(GET_TYPE_ACCESSED_WITHOUT_PERMISSION,
- enumFrameworkPermission,
+ enumCheckUriPermission,
callingUid, uri.getAuthority(), type);
- } else {
- final ProviderInfo cpi = mContext.getPackageManager()
- .resolveContentProvider(uri.getAuthority(),
- PackageManager.ComponentInfoFlags.of(PackageManager.GET_META_DATA));
- final int callingUserId = UserHandle.getUserId(callingUid);
- final Uri userUri = (mSingleUser
- && !UserHandle.isSameUser(mMyUid, callingUid))
- ? maybeAddUserId(uri, callingUserId) : uri;
- if (cpi.forceUriPermissions
- && mInterface.checkUriPermission(uri,
- callingUid, Intent.FLAG_GRANT_READ_URI_PERMISSION)
- != PermissionChecker.PERMISSION_GRANTED
- && getContext().checkUriPermission(userUri, Binder.getCallingPid(),
- callingUid, Intent.FLAG_GRANT_READ_URI_PERMISSION)
- != PackageManager.PERMISSION_GRANTED) {
- FrameworkStatsLog.write(GET_TYPE_ACCESSED_WITHOUT_PERMISSION,
- enumCheckUriPermission,
- callingUid, uri.getAuthority(), type);
- }
}
- } catch (SecurityException e) {
- FrameworkStatsLog.write(GET_TYPE_ACCESSED_WITHOUT_PERMISSION,
- enumFrameworkPermission,
- callingUid, uri.getAuthority(), type);
+ } catch (Exception e) {
+ //does nothing
}
- } catch (Exception e) {
+ } else {
FrameworkStatsLog.write(GET_TYPE_ACCESSED_WITHOUT_PERMISSION,
- enumError,
+ enumFrameworkPermission,
callingUid, uri.getAuthority(), type);
}
}
@Override
- public void getTypeAsync(Uri uri, RemoteCallback callback) {
+ public void getTypeAsync(AttributionSource attributionSource,
+ Uri uri, RemoteCallback callback) {
+ final Bundle result = new Bundle();
+ try {
+ result.putString(ContentResolver.REMOTE_CALLBACK_RESULT,
+ getType(attributionSource, uri));
+ } catch (Exception e) {
+ result.putParcelable(ContentResolver.REMOTE_CALLBACK_ERROR,
+ new ParcelableException(e));
+ }
+ callback.sendResult(result);
+ }
+
+ @Override
+ public void getTypeAnonymousAsync(Uri uri, RemoteCallback callback) {
final Bundle result = new Bundle();
try {
- result.putString(ContentResolver.REMOTE_CALLBACK_RESULT, getType(uri));
+ result.putString(ContentResolver.REMOTE_CALLBACK_RESULT, getTypeAnonymous(uri));
} catch (Exception e) {
result.putParcelable(ContentResolver.REMOTE_CALLBACK_ERROR,
new ParcelableException(e));
@@ -795,6 +815,23 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
}
return PermissionChecker.PERMISSION_GRANTED;
}
+
+ @PermissionCheckerManager.PermissionResult
+ private int checkGetTypePermission(@NonNull AttributionSource attributionSource,
+ Uri uri) {
+ final int callingUid = Binder.getCallingUid();
+ if (UserHandle.getAppId(callingUid) == SYSTEM_UID
+ || checkPermission(Manifest.permission.GET_ANY_PROVIDER_TYPE, attributionSource)
+ == PermissionChecker.PERMISSION_GRANTED) {
+ // Allowing System Uid and apps with permission to get any type, to access all types
+ return PermissionChecker.PERMISSION_GRANTED;
+ }
+ try {
+ return enforceReadPermission(attributionSource, uri);
+ } catch (SecurityException e) {
+ return PermissionChecker.PERMISSION_HARD_DENIED;
+ }
+ }
}
boolean checkUser(int pid, int uid, Context context) {
@@ -1625,11 +1662,15 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
* <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
* and Threads</a>.
*
- * <p>Note that there are no permissions needed for an application to
+ * <p>Note that by default there are no permissions needed for an application to
* access this information; if your content provider requires read and/or
* write permissions, or is not exported, all applications can still call
- * this method regardless of their access permissions. This allows them
- * to retrieve the MIME type for a URI when dispatching intents.
+ * this method regardless of their access permissions. </p>
+ *
+ * <p>If your mime type reveals details that should be protected,
+ * then you should protect this method by implementing {@link #getTypeAnonymous}.
+ * Implementing {@link #getTypeAnonymous} ensures your {@link #getType} can be
+ * only accessed by caller's having associated readPermission for the URI. </p>
*
* @param uri the URI to query.
* @return a MIME type string, or {@code null} if there is no type.
@@ -1638,6 +1679,24 @@ public abstract class ContentProvider implements ContentInterface, ComponentCall
public abstract @Nullable String getType(@NonNull Uri uri);
/**
+ * Implement this to handle requests for MIME type of URIs, that does not need to
+ * reveal any internal information which should be protected by any permission.
+ *
+ * <p>If your mime type reveals details that should be protected, then you should protect those
+ * by implementing those in {@link #getType}, and in this function, only return types of
+ * URIs which can be obtained by anyone without any access.
+ *
+ * Implementing ths function will make sure {@link #getType} is protected by readPermission.
+ * This function by default works as the {@link #getType}</p>
+ *
+ * @param uri the URI to query.
+ * @return a MIME type string, or {@code null} if type needs to be protected.
+ */
+ public @Nullable String getTypeAnonymous(@NonNull Uri uri) {
+ return getType(uri);
+ }
+
+ /**
* Implement this to support canonicalization of URIs that refer to your
* content provider. A canonical URI is one that can be transported across
* devices, backup/restore, and other contexts, and still be able to refer
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index 47c966990861..4ba3ff4fe3d3 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -140,8 +140,10 @@ abstract public class ContentProviderNative extends Binder implements IContentPr
case GET_TYPE_TRANSACTION:
{
data.enforceInterface(IContentProvider.descriptor);
+ AttributionSource attributionSource = AttributionSource.CREATOR
+ .createFromParcel(data);
Uri url = Uri.CREATOR.createFromParcel(data);
- String type = getType(url);
+ String type = getType(attributionSource, url);
reply.writeNoException();
reply.writeString(type);
@@ -150,9 +152,19 @@ abstract public class ContentProviderNative extends Binder implements IContentPr
case GET_TYPE_ASYNC_TRANSACTION: {
data.enforceInterface(IContentProvider.descriptor);
+ AttributionSource attributionSource = AttributionSource.CREATOR
+ .createFromParcel(data);
Uri url = Uri.CREATOR.createFromParcel(data);
RemoteCallback callback = RemoteCallback.CREATOR.createFromParcel(data);
- getTypeAsync(url, callback);
+ getTypeAsync(attributionSource, url, callback);
+ return true;
+ }
+
+ case GET_TYPE_ANONYMOUS_ASYNC_TRANSACTION: {
+ data.enforceInterface(IContentProvider.descriptor);
+ Uri url = Uri.CREATOR.createFromParcel(data);
+ RemoteCallback callback = RemoteCallback.CREATOR.createFromParcel(data);
+ getTypeAnonymousAsync(url, callback);
return true;
}
@@ -502,13 +514,13 @@ final class ContentProviderProxy implements IContentProvider
}
@Override
- public String getType(Uri url) throws RemoteException
+ public String getType(AttributionSource attributionSource, Uri url) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
-
+ attributionSource.writeToParcel(data, 0);
url.writeToParcel(data, 0);
mRemote.transact(IContentProvider.GET_TYPE_TRANSACTION, data, reply, 0);
@@ -523,11 +535,12 @@ final class ContentProviderProxy implements IContentProvider
}
@Override
- /* oneway */ public void getTypeAsync(Uri uri, RemoteCallback callback) throws RemoteException {
+ /* oneway */ public void getTypeAsync(AttributionSource attributionSource,
+ Uri uri, RemoteCallback callback) throws RemoteException {
Parcel data = Parcel.obtain();
try {
data.writeInterfaceToken(IContentProvider.descriptor);
-
+ attributionSource.writeToParcel(data, 0);
uri.writeToParcel(data, 0);
callback.writeToParcel(data, 0);
@@ -539,6 +552,23 @@ final class ContentProviderProxy implements IContentProvider
}
@Override
+ /* oneway */ public void getTypeAnonymousAsync(Uri uri, RemoteCallback callback)
+ throws RemoteException {
+ Parcel data = Parcel.obtain();
+ try {
+ data.writeInterfaceToken(IContentProvider.descriptor);
+
+ uri.writeToParcel(data, 0);
+ callback.writeToParcel(data, 0);
+
+ mRemote.transact(IContentProvider.GET_TYPE_ANONYMOUS_ASYNC_TRANSACTION, data, null,
+ IBinder.FLAG_ONEWAY);
+ } finally {
+ data.recycle();
+ }
+ }
+
+ @Override
public Uri insert(@NonNull AttributionSource attributionSource, Uri url,
ContentValues values, Bundle extras) throws RemoteException
{
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 37794531dfa3..456d21897711 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -920,12 +920,18 @@ public abstract class ContentResolver implements ContentInterface {
return null;
}
- // XXX would like to have an acquireExistingUnstableProvider for this.
- IContentProvider provider = acquireExistingProvider(url);
+ IContentProvider provider = null;
+ try {
+ provider = acquireProvider(url);
+ } catch (Exception e) {
+ // if unable to acquire the provider, then it should try to get the type
+ // using getTypeAnonymous via ActivityManagerService
+ }
if (provider != null) {
try {
final StringResultListener resultListener = new StringResultListener();
- provider.getTypeAsync(url, new RemoteCallback(resultListener));
+ provider.getTypeAsync(mContext.getAttributionSource(),
+ url, new RemoteCallback(resultListener));
resultListener.waitForResult(CONTENT_PROVIDER_TIMEOUT_MILLIS);
if (resultListener.exception != null) {
throw resultListener.exception;
@@ -939,7 +945,11 @@ public abstract class ContentResolver implements ContentInterface {
Log.w(TAG, "Failed to get type for: " + url + " (" + e.getMessage() + ")");
return null;
} finally {
- releaseProvider(provider);
+ try {
+ releaseProvider(provider);
+ } catch (java.lang.NullPointerException e) {
+ // does nothing, Binder connection already null
+ }
}
}
@@ -949,7 +959,7 @@ public abstract class ContentResolver implements ContentInterface {
try {
final StringResultListener resultListener = new StringResultListener();
- ActivityManager.getService().getProviderMimeTypeAsync(
+ ActivityManager.getService().getMimeTypeFilterAsync(
ContentProvider.getUriWithoutUserId(url),
resolveUserId(url),
new RemoteCallback(resultListener));
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index ca537a46baca..1775bf7d1390 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -1209,6 +1209,14 @@ public class ContextWrapper extends Context {
* @hide
*/
@Override
+ public int getAssociatedDisplayId() {
+ return mBase.getAssociatedDisplayId();
+ }
+
+ /**
+ * @hide
+ */
+ @Override
public void updateDisplay(int displayId) {
mBase.updateDisplay(displayId);
}
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index e0315a3e171b..eb80148250b9 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -18,6 +18,7 @@ package android.content;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.AppGlobals;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.res.AssetFileDescriptor;
import android.database.Cursor;
@@ -44,14 +45,42 @@ public interface IContentProvider extends IInterface {
@Nullable String[] projection,
@Nullable Bundle queryArgs, @Nullable ICancellationSignal cancellationSignal)
throws RemoteException;
- String getType(Uri url) throws RemoteException;
+ /**
+ * getType function with AttributionSource
+ */
+ String getType(@NonNull AttributionSource attributionSource,
+ Uri url) throws RemoteException;
+ /**
+ * one way getType function with AttributionSource
+ */
+ void getTypeAsync(@NonNull AttributionSource attributionSource,
+ Uri url, RemoteCallback callback) throws RemoteException;
+ /**
+ * @deprecated -- use getType with AttributionSource
+ */
+ @Deprecated
+ default String getType(Uri url) throws RemoteException {
+ return getType(new AttributionSource(Binder.getCallingUid(),
+ AppGlobals.getPackageManager().getPackagesForUid(Binder.getCallingUid())[0],
+ null), url);
+ }
/**
* A oneway version of getType. The functionality is exactly the same, except that the
* call returns immediately, and the resulting type is returned when available via
* a binder callback.
+ *
+ * @deprecated -- use getTypeAsync with AttributionSource
*/
- void getTypeAsync(Uri uri, RemoteCallback callback) throws RemoteException;
+ @Deprecated
+ default void getTypeAsync(Uri uri, RemoteCallback callback) throws RemoteException {
+ getTypeAsync(new AttributionSource(Binder.getCallingUid(),
+ AppGlobals.getPackageManager().getPackagesForUid(Binder.getCallingUid())[0],
+ null), uri, callback);
+ }
+
+ /** oneway version of getTypeAnonymous*/
+ void getTypeAnonymousAsync(Uri uri, RemoteCallback callback) throws RemoteException;
@Deprecated
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.Q, publicAlternatives = "Use {@link "
@@ -185,4 +214,7 @@ public interface IContentProvider extends IInterface {
int GET_TYPE_ASYNC_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 28;
int CANONICALIZE_ASYNC_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 29;
int UNCANONICALIZE_ASYNC_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 30;
+ int GET_TYPE_ANONYMOUS_ASYNC_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 31;
+
+
}
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 2b4ea70aabf4..8acdf510484b 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -581,7 +581,7 @@ public class PackageInstaller {
/**
* Indicate the user intervention is required because the update ownership enforcement is
- * enabled, and remind the update owner will retain.
+ * enabled, and remind the update owner is a different package.
*
* @see PackageInstaller.SessionParams#setRequestUpdateOwnership
* @see InstallSourceInfo#getUpdateOwnerPackageName
@@ -2978,8 +2978,7 @@ public class PackageInstaller {
* permission. Default to {@code false}.
*
* The update ownership enforcement can only be enabled on initial installation. Set
- * this to {@code true} on package update indicates the installer package wants to be
- * the update owner if the update ownership enforcement has enabled.
+ * this to {@code true} on package update is a no-op.
*
* Note: To enable the update ownership enforcement, the installer must have the
* {@link android.Manifest.permission#ENFORCE_UPDATE_OWNERSHIP ENFORCE_UPDATE_OWNERSHIP}
@@ -3982,8 +3981,7 @@ public class PackageInstaller {
/**
* Details for requesting the pre-commit install approval.
*/
- @DataClass(genParcelable = true, genHiddenConstructor = true, genBuilder = true,
- genToString = true)
+ @DataClass(genConstructor = false, genToString = true)
public static final class PreapprovalDetails implements Parcelable {
/**
* The icon representing the app to be installed.
@@ -4002,22 +4000,6 @@ public class PackageInstaller {
*/
private final @NonNull String mPackageName;
-
-
-
- // Code below generated by codegen v1.0.23.
- //
- // DO NOT MODIFY!
- // CHECKSTYLE:OFF Generated code
- //
- // To regenerate run:
- // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/PackageInstaller.java
- //
- // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
- // Settings > Editor > Code Style > Formatter Control
- //@formatter:off
-
-
/**
* Creates a new PreapprovalDetails.
*
@@ -4031,78 +4013,25 @@ public class PackageInstaller {
* The package name of the app to be installed.
* @hide
*/
- @DataClass.Generated.Member
public PreapprovalDetails(
@Nullable Bitmap icon,
@NonNull CharSequence label,
@NonNull ULocale locale,
@NonNull String packageName) {
- this.mIcon = icon;
- this.mLabel = label;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mLabel);
- this.mLocale = locale;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mLocale);
- this.mPackageName = packageName;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mPackageName);
-
- // onConstructed(); // You can define this method to get a callback
- }
-
- /**
- * The icon representing the app to be installed.
- */
- @DataClass.Generated.Member
- public @Nullable Bitmap getIcon() {
- return mIcon;
- }
-
- /**
- * The label representing the app to be installed.
- */
- @DataClass.Generated.Member
- public @NonNull CharSequence getLabel() {
- return mLabel;
- }
-
- /**
- * The locale of the app label being used.
- */
- @DataClass.Generated.Member
- public @NonNull ULocale getLocale() {
- return mLocale;
- }
-
- /**
- * The package name of the app to be installed.
- */
- @DataClass.Generated.Member
- public @NonNull String getPackageName() {
- return mPackageName;
+ mIcon = icon;
+ mLabel = label;
+ Preconditions.checkArgument(!TextUtils.isEmpty(mLabel),
+ "App label cannot be empty.");
+ mLocale = locale;
+ Preconditions.checkArgument(!Objects.isNull(mLocale),
+ "Locale cannot be null.");
+ mPackageName = packageName;
+ Preconditions.checkArgument(!TextUtils.isEmpty(mPackageName),
+ "Package name cannot be empty.");
}
@Override
- @DataClass.Generated.Member
- public String toString() {
- // You can override field toString logic by defining methods like:
- // String fieldNameToString() { ... }
-
- return "PreapprovalDetails { " +
- "icon = " + mIcon + ", " +
- "label = " + mLabel + ", " +
- "locale = " + mLocale + ", " +
- "packageName = " + mPackageName +
- " }";
- }
-
- @Override
- @DataClass.Generated.Member
public void writeToParcel(@NonNull Parcel dest, int flags) {
- // You can override field parcelling by defining methods like:
- // void parcelFieldName(Parcel dest, int flags) { ... }
-
byte flg = 0;
if (mIcon != null) flg |= 0x1;
dest.writeByte(flg);
@@ -4113,37 +4042,28 @@ public class PackageInstaller {
}
@Override
- @DataClass.Generated.Member
public int describeContents() { return 0; }
/** @hide */
- @SuppressWarnings({"unchecked", "RedundantCast"})
- @DataClass.Generated.Member
/* package-private */ PreapprovalDetails(@NonNull Parcel in) {
- // You can override field unparcelling by defining methods like:
- // static FieldType unparcelFieldName(Parcel in) { ... }
-
byte flg = in.readByte();
- Bitmap icon = (flg & 0x1) == 0 ? null : Bitmap.CREATOR.createFromParcel(in);
- CharSequence label = (CharSequence) in.readCharSequence();
- ULocale locale = new ULocale(in.readString8());
- String packageName = in.readString8();
-
- this.mIcon = icon;
- this.mLabel = label;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mLabel);
- this.mLocale = locale;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mLocale);
- this.mPackageName = packageName;
- com.android.internal.util.AnnotationValidations.validate(
- NonNull.class, null, mPackageName);
-
- // onConstructed(); // You can define this method to get a callback
+ final Bitmap icon = (flg & 0x1) == 0 ? null : Bitmap.CREATOR.createFromParcel(in);
+ final CharSequence label = in.readCharSequence();
+ final ULocale locale = new ULocale(in.readString8());
+ final String packageName = in.readString8();
+
+ mIcon = icon;
+ mLabel = label;
+ Preconditions.checkArgument(!TextUtils.isEmpty(mLabel),
+ "App label cannot be empty.");
+ mLocale = locale;
+ Preconditions.checkArgument(!Objects.isNull(mLocale),
+ "Locale cannot be null.");
+ mPackageName = packageName;
+ Preconditions.checkArgument(!TextUtils.isEmpty(mPackageName),
+ "Package name cannot be empty.");
}
- @DataClass.Generated.Member
public static final @NonNull Parcelable.Creator<PreapprovalDetails> CREATOR
= new Parcelable.Creator<PreapprovalDetails>() {
@Override
@@ -4160,8 +4080,6 @@ public class PackageInstaller {
/**
* A builder for {@link PreapprovalDetails}
*/
- @SuppressWarnings("WeakerAccess")
- @DataClass.Generated.Member
public static final class Builder {
private @Nullable Bitmap mIcon;
@@ -4179,7 +4097,6 @@ public class PackageInstaller {
/**
* The icon representing the app to be installed.
*/
- @DataClass.Generated.Member
public @NonNull Builder setIcon(@NonNull Bitmap value) {
checkNotUsed();
mBuilderFieldsSet |= 0x1;
@@ -4190,7 +4107,6 @@ public class PackageInstaller {
/**
* The label representing the app to be installed.
*/
- @DataClass.Generated.Member
public @NonNull Builder setLabel(@NonNull CharSequence value) {
checkNotUsed();
mBuilderFieldsSet |= 0x2;
@@ -4201,7 +4117,6 @@ public class PackageInstaller {
/**
* The locale of the app label being used.
*/
- @DataClass.Generated.Member
public @NonNull Builder setLocale(@NonNull ULocale value) {
checkNotUsed();
mBuilderFieldsSet |= 0x4;
@@ -4212,7 +4127,6 @@ public class PackageInstaller {
/**
* The package name of the app to be installed.
*/
- @DataClass.Generated.Member
public @NonNull Builder setPackageName(@NonNull String value) {
checkNotUsed();
mBuilderFieldsSet |= 0x8;
@@ -4235,17 +4149,79 @@ public class PackageInstaller {
private void checkNotUsed() {
if ((mBuilderFieldsSet & 0x10) != 0) {
- throw new IllegalStateException(
- "This Builder should not be reused. Use a new Builder instance instead");
+ throw new IllegalStateException("This Builder should not be reused. "
+ + "Use a new Builder instance instead");
}
}
}
+
+
+
+ // Code below generated by codegen v1.0.23.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/PackageInstaller.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ /**
+ * The icon representing the app to be installed.
+ */
+ @DataClass.Generated.Member
+ public @Nullable Bitmap getIcon() {
+ return mIcon;
+ }
+
+ /**
+ * The label representing the app to be installed.
+ */
+ @DataClass.Generated.Member
+ public @NonNull CharSequence getLabel() {
+ return mLabel;
+ }
+
+ /**
+ * The locale of the app label being used.
+ */
+ @DataClass.Generated.Member
+ public @NonNull ULocale getLocale() {
+ return mLocale;
+ }
+
+ /**
+ * The package name of the app to be installed.
+ */
+ @DataClass.Generated.Member
+ public @NonNull String getPackageName() {
+ return mPackageName;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "PreapprovalDetails { " +
+ "icon = " + mIcon + ", " +
+ "label = " + mLabel + ", " +
+ "locale = " + mLocale + ", " +
+ "packageName = " + mPackageName +
+ " }";
+ }
+
@DataClass.Generated(
- time = 1666748098353L,
+ time = 1676970504308L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/content/pm/PackageInstaller.java",
- inputSignatures = "private final @android.annotation.Nullable android.graphics.Bitmap mIcon\nprivate final @android.annotation.NonNull java.lang.CharSequence mLabel\nprivate final @android.annotation.NonNull android.icu.util.ULocale mLocale\nprivate final @android.annotation.NonNull java.lang.String mPackageName\nclass PreapprovalDetails extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genHiddenConstructor=true, genBuilder=true, genToString=true)")
+ inputSignatures = "private final @android.annotation.Nullable android.graphics.Bitmap mIcon\nprivate final @android.annotation.NonNull java.lang.CharSequence mLabel\nprivate final @android.annotation.NonNull android.icu.util.ULocale mLocale\nprivate final @android.annotation.NonNull java.lang.String mPackageName\npublic static final @android.annotation.NonNull android.os.Parcelable.Creator<android.content.pm.PackageInstaller.PreapprovalDetails> CREATOR\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\npublic @java.lang.Override int describeContents()\nclass PreapprovalDetails extends java.lang.Object implements [android.os.Parcelable]\nprivate @android.annotation.Nullable android.graphics.Bitmap mIcon\nprivate @android.annotation.NonNull java.lang.CharSequence mLabel\nprivate @android.annotation.NonNull android.icu.util.ULocale mLocale\nprivate @android.annotation.NonNull java.lang.String mPackageName\nprivate long mBuilderFieldsSet\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails.Builder setIcon(android.graphics.Bitmap)\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails.Builder setLabel(java.lang.CharSequence)\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails.Builder setLocale(android.icu.util.ULocale)\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails.Builder setPackageName(java.lang.String)\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.PreapprovalDetails build()\nprivate void checkNotUsed()\nclass Builder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genToString=true)")
@Deprecated
private void __metadata() {}
@@ -4348,7 +4324,7 @@ public class PackageInstaller {
};
@DataClass.Generated(
- time = 1675135664641L,
+ time = 1676970504336L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/content/pm/PackageInstaller.java",
inputSignatures = "private boolean mAllConstraintsSatisfied\npublic boolean areAllConstraintsSatisfied()\nclass InstallConstraintsResult extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genHiddenConstructor=true)")
@@ -4636,7 +4612,7 @@ public class PackageInstaller {
};
@DataClass.Generated(
- time = 1675135664653L,
+ time = 1676970504352L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/content/pm/PackageInstaller.java",
inputSignatures = "public static final @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints GENTLE_UPDATE\nprivate final boolean mDeviceIdleRequired\nprivate final boolean mAppNotForegroundRequired\nprivate final boolean mAppNotInteractingRequired\nprivate final boolean mAppNotTopVisibleRequired\nprivate final boolean mNotInCallRequired\nclass InstallConstraints extends java.lang.Object implements [android.os.Parcelable]\nprivate boolean mDeviceIdleRequired\nprivate boolean mAppNotForegroundRequired\nprivate boolean mAppNotInteractingRequired\nprivate boolean mAppNotTopVisibleRequired\nprivate boolean mNotInCallRequired\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setDeviceIdleRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setAppNotForegroundRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setAppNotInteractingRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setAppNotTopVisibleRequired()\npublic @android.annotation.SuppressLint @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints.Builder setNotInCallRequired()\npublic @android.annotation.NonNull android.content.pm.PackageInstaller.InstallConstraints build()\nclass Builder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genParcelable=true, genHiddenConstructor=true, genEqualsHashCode=true)")
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 23cce6a1c135..db05b959a7b1 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1607,6 +1607,13 @@ public abstract class PackageManager {
*/
public static final int INSTALL_REQUEST_UPDATE_OWNERSHIP = 1 << 25;
+ /**
+ * Flag parameter for {@link PackageInstaller.SessionParams} to indicate that this
+ * session is from a managed user or profile.
+ * @hide
+ */
+ public static final int INSTALL_FROM_MANAGED_USER_OR_PROFILE = 1 << 26;
+
/** @hide */
@IntDef(flag = true, value = {
DONT_KILL_APP,
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 6386f75ae2f3..81fc0293b685 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -60,10 +60,17 @@ public class UserInfo implements Parcelable {
*/
/**
- * Primary user. Only one user can have this flag set. It identifies the first human user
- * on a device. This flag is not supported in headless system user mode.
+ * Primary user. In practice, this is just synonymous with {@link #FLAG_SYSTEM}.
+ *
+ * <p>On many devices, this will also be the first human user.
+ * However, in {@link UserManager#isHeadlessSystemUserMode() headless system user mode}, this
+ * should be regarded as unsupported since the system user may not be a human.
+ *
+ * @deprecated For checking for user 0, use {@link #FLAG_SYSTEM}.
+ * For checking for the designated "main human user", use {@link #FLAG_MAIN}.
*/
@UnsupportedAppUsage
+ @Deprecated
public static final int FLAG_PRIMARY = 0x00000001;
/**
@@ -335,7 +342,12 @@ public class UserInfo implements Parcelable {
}
}
+ /**
+ * @deprecated For checking for user 0, compare {@link #id} to {@link UserHandle#USER_SYSTEM}.
+ * For checking for the designated "main human user", use {@link #isMain()}.
+ */
@UnsupportedAppUsage
+ @Deprecated
public boolean isPrimary() {
return (flags & FLAG_PRIMARY) == FLAG_PRIMARY;
}
diff --git a/core/java/android/hardware/biometrics/AuthenticateOptions.java b/core/java/android/hardware/biometrics/AuthenticateOptions.java
new file mode 100644
index 000000000000..77660713275f
--- /dev/null
+++ b/core/java/android/hardware/biometrics/AuthenticateOptions.java
@@ -0,0 +1,77 @@
+/*
+ * 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 android.hardware.biometrics;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Common authentication options that are exposed across all modalities.
+ *
+ * @hide
+ */
+public interface AuthenticateOptions {
+
+ /** The user id for this operation. */
+ int getUserId();
+
+ /** The sensor id for this operation. */
+ int getSensorId();
+
+ /** The state is unknown. */
+ int DISPLAY_STATE_UNKNOWN = 0;
+
+ /** The display is on and showing the lockscreen (or an occluding app). */
+ int DISPLAY_STATE_LOCKSCREEN = 1;
+
+ /** The display is off or dozing. */
+ int DISPLAY_STATE_NO_UI = 2;
+
+ /** The display is showing a screensaver (dreaming). */
+ int DISPLAY_STATE_SCREENSAVER = 3;
+
+ /** The display is dreaming with always on display. */
+ int DISPLAY_STATE_AOD = 4;
+
+ /** The doze state of the device. */
+ @IntDef(prefix = "DISPLAY_STATE_", value = {
+ DISPLAY_STATE_UNKNOWN,
+ DISPLAY_STATE_LOCKSCREEN,
+ DISPLAY_STATE_NO_UI,
+ DISPLAY_STATE_SCREENSAVER,
+ DISPLAY_STATE_AOD
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface DisplayState {}
+
+ /** The current doze state of the device. */
+ @DisplayState
+ int getDisplayState();
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ */
+ @NonNull String getOpPackageName();
+
+ /** The attribution tag, if any. */
+ @Nullable String getAttributionTag();
+}
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index f693a2f6d0cf..b766cd19cdb0 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -66,7 +66,16 @@ import java.util.concurrent.Executor;
public final class DisplayManager {
private static final String TAG = "DisplayManager";
private static final boolean DEBUG = false;
- private static final boolean ENABLE_VIRTUAL_DISPLAY_REFRESH_RATE = false;
+ private static final boolean ENABLE_VIRTUAL_DISPLAY_REFRESH_RATE = true;
+
+ /**
+ * The hdr output control feature flag, the value should be read via
+ * {@link android.provider.DeviceConfig#getBoolean(String, String, boolean)} with
+ * {@link android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER} as the namespace.
+ * @hide
+ */
+ @TestApi
+ public static final String HDR_OUTPUT_CONTROL_FLAG = "enable_hdr_output_control";
private final Context mContext;
private final DisplayManagerGlobal mGlobal;
diff --git a/core/java/android/hardware/face/FaceAuthenticateOptions.aidl b/core/java/android/hardware/face/FaceAuthenticateOptions.aidl
new file mode 100644
index 000000000000..7c72b405383c
--- /dev/null
+++ b/core/java/android/hardware/face/FaceAuthenticateOptions.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 android.hardware.face;
+
+parcelable FaceAuthenticateOptions;
diff --git a/core/java/android/hardware/face/FaceAuthenticateOptions.java b/core/java/android/hardware/face/FaceAuthenticateOptions.java
new file mode 100644
index 000000000000..4009fa7682fe
--- /dev/null
+++ b/core/java/android/hardware/face/FaceAuthenticateOptions.java
@@ -0,0 +1,624 @@
+/*
+ * 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 android.hardware.face;
+
+
+import static android.os.PowerManager.WAKE_REASON_UNKNOWN;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.biometrics.AuthenticateOptions;
+import android.os.Parcelable;
+import android.os.PowerManager;
+
+import com.android.internal.util.DataClass;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Additional options when requesting Face authentication or detection.
+ *
+ * @hide
+ */
+@DataClass(
+ genParcelable = true,
+ genAidl = true,
+ genBuilder = true,
+ genSetters = true,
+ genEqualsHashCode = true
+)
+public class FaceAuthenticateOptions implements AuthenticateOptions, Parcelable {
+
+ /** The user id for this operation. */
+ private final int mUserId;
+ private static int defaultUserId() {
+ return 0;
+ }
+
+ /** The sensor id for this operation. */
+ private final int mSensorId;
+ private static int defaultSensorId() {
+ return -1;
+ }
+
+ /** The current doze state of the device. */
+ @AuthenticateOptions.DisplayState
+ private final int mDisplayState;
+ private static int defaultDisplayState() {
+ return DISPLAY_STATE_UNKNOWN;
+ }
+
+ public static final int AUTHENTICATE_REASON_UNKNOWN = 0;
+ public static final int AUTHENTICATE_REASON_STARTED_WAKING_UP = 1;
+ public static final int AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN = 2;
+ public static final int AUTHENTICATE_REASON_ASSISTANT_VISIBLE = 3;
+ public static final int AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN = 4;
+ public static final int AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED = 5;
+ public static final int AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED = 6;
+ public static final int AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED = 7;
+ public static final int AUTHENTICATE_REASON_QS_EXPANDED = 8;
+ public static final int AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER = 9;
+ public static final int AUTHENTICATE_REASON_UDFPS_POINTER_DOWN = 10;
+
+ /**
+ * The reason for this operation when requested by the system (sysui),
+ * otherwise AUTHENTICATE_REASON_UNKNOWN.
+ *
+ * See frameworks/base/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
+ * for more details about each reason.
+ */
+ @AuthenticateReason
+ private final int mAuthenticateReason;
+ private static int defaultAuthenticateReason() {
+ return AUTHENTICATE_REASON_UNKNOWN;
+ }
+
+ /** A reason if this request was triggered due to a power event or WAKE_REASON_UNKNOWN. */
+ @PowerManager.WakeReason
+ private final int mWakeReason;
+ private static int defaultWakeReason() {
+ return WAKE_REASON_UNKNOWN;
+ }
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @NonNull
+ private String mOpPackageName;
+ private static String defaultOpPackageName() {
+ return "";
+ }
+
+ /**
+ * The attribution tag, if any.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @Nullable
+ private String mAttributionTag;
+ private static String defaultAttributionTag() {
+ return null;
+ }
+
+
+
+ // Code below generated by codegen v1.0.23.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/hardware/face/FaceAuthenticateOptions.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @IntDef(prefix = "AUTHENTICATE_REASON_", value = {
+ AUTHENTICATE_REASON_UNKNOWN,
+ AUTHENTICATE_REASON_STARTED_WAKING_UP,
+ AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN,
+ AUTHENTICATE_REASON_ASSISTANT_VISIBLE,
+ AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN,
+ AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED,
+ AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED,
+ AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED,
+ AUTHENTICATE_REASON_QS_EXPANDED,
+ AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER,
+ AUTHENTICATE_REASON_UDFPS_POINTER_DOWN
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @DataClass.Generated.Member
+ public @interface AuthenticateReason {}
+
+ @DataClass.Generated.Member
+ public static String authenticateReasonToString(@AuthenticateReason int value) {
+ switch (value) {
+ case AUTHENTICATE_REASON_UNKNOWN:
+ return "AUTHENTICATE_REASON_UNKNOWN";
+ case AUTHENTICATE_REASON_STARTED_WAKING_UP:
+ return "AUTHENTICATE_REASON_STARTED_WAKING_UP";
+ case AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN:
+ return "AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN";
+ case AUTHENTICATE_REASON_ASSISTANT_VISIBLE:
+ return "AUTHENTICATE_REASON_ASSISTANT_VISIBLE";
+ case AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN:
+ return "AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN";
+ case AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED:
+ return "AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED";
+ case AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED:
+ return "AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED";
+ case AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED:
+ return "AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED";
+ case AUTHENTICATE_REASON_QS_EXPANDED:
+ return "AUTHENTICATE_REASON_QS_EXPANDED";
+ case AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER:
+ return "AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER";
+ case AUTHENTICATE_REASON_UDFPS_POINTER_DOWN:
+ return "AUTHENTICATE_REASON_UDFPS_POINTER_DOWN";
+ default: return Integer.toHexString(value);
+ }
+ }
+
+ @DataClass.Generated.Member
+ /* package-private */ FaceAuthenticateOptions(
+ int userId,
+ int sensorId,
+ @AuthenticateOptions.DisplayState int displayState,
+ @AuthenticateReason int authenticateReason,
+ @PowerManager.WakeReason int wakeReason,
+ @NonNull String opPackageName,
+ @Nullable String attributionTag) {
+ this.mUserId = userId;
+ this.mSensorId = sensorId;
+ this.mDisplayState = displayState;
+ com.android.internal.util.AnnotationValidations.validate(
+ AuthenticateOptions.DisplayState.class, null, mDisplayState);
+ this.mAuthenticateReason = authenticateReason;
+
+ if (!(mAuthenticateReason == AUTHENTICATE_REASON_UNKNOWN)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_STARTED_WAKING_UP)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_ASSISTANT_VISIBLE)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_QS_EXPANDED)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_UDFPS_POINTER_DOWN)) {
+ throw new java.lang.IllegalArgumentException(
+ "authenticateReason was " + mAuthenticateReason + " but must be one of: "
+ + "AUTHENTICATE_REASON_UNKNOWN(" + AUTHENTICATE_REASON_UNKNOWN + "), "
+ + "AUTHENTICATE_REASON_STARTED_WAKING_UP(" + AUTHENTICATE_REASON_STARTED_WAKING_UP + "), "
+ + "AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN(" + AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN + "), "
+ + "AUTHENTICATE_REASON_ASSISTANT_VISIBLE(" + AUTHENTICATE_REASON_ASSISTANT_VISIBLE + "), "
+ + "AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN(" + AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN + "), "
+ + "AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED(" + AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED + "), "
+ + "AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED(" + AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED + "), "
+ + "AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED(" + AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED + "), "
+ + "AUTHENTICATE_REASON_QS_EXPANDED(" + AUTHENTICATE_REASON_QS_EXPANDED + "), "
+ + "AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER(" + AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER + "), "
+ + "AUTHENTICATE_REASON_UDFPS_POINTER_DOWN(" + AUTHENTICATE_REASON_UDFPS_POINTER_DOWN + ")");
+ }
+
+ this.mWakeReason = wakeReason;
+ com.android.internal.util.AnnotationValidations.validate(
+ PowerManager.WakeReason.class, null, mWakeReason);
+ this.mOpPackageName = opPackageName;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mOpPackageName);
+ this.mAttributionTag = attributionTag;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * The user id for this operation.
+ */
+ @DataClass.Generated.Member
+ public int getUserId() {
+ return mUserId;
+ }
+
+ /**
+ * The sensor id for this operation.
+ */
+ @DataClass.Generated.Member
+ public int getSensorId() {
+ return mSensorId;
+ }
+
+ /**
+ * The current doze state of the device.
+ */
+ @DataClass.Generated.Member
+ public @AuthenticateOptions.DisplayState int getDisplayState() {
+ return mDisplayState;
+ }
+
+ /**
+ * The reason for this operation when requested by the system (sysui),
+ * otherwise AUTHENTICATE_REASON_UNKNOWN.
+ *
+ * See frameworks/base/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
+ * for more details about each reason.
+ */
+ @DataClass.Generated.Member
+ public @AuthenticateReason int getAuthenticateReason() {
+ return mAuthenticateReason;
+ }
+
+ /**
+ * A reason if this request was triggered due to a power event or WAKE_REASON_UNKNOWN.
+ */
+ @DataClass.Generated.Member
+ public @PowerManager.WakeReason int getWakeReason() {
+ return mWakeReason;
+ }
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull String getOpPackageName() {
+ return mOpPackageName;
+ }
+
+ /**
+ * The attribution tag, if any.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @Nullable String getAttributionTag() {
+ return mAttributionTag;
+ }
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull FaceAuthenticateOptions setOpPackageName(@NonNull String value) {
+ mOpPackageName = value;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mOpPackageName);
+ return this;
+ }
+
+ /**
+ * The attribution tag, if any.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull FaceAuthenticateOptions setAttributionTag(@NonNull String value) {
+ mAttributionTag = value;
+ return this;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(@Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(FaceAuthenticateOptions other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ FaceAuthenticateOptions that = (FaceAuthenticateOptions) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && mUserId == that.mUserId
+ && mSensorId == that.mSensorId
+ && mDisplayState == that.mDisplayState
+ && mAuthenticateReason == that.mAuthenticateReason
+ && mWakeReason == that.mWakeReason
+ && java.util.Objects.equals(mOpPackageName, that.mOpPackageName)
+ && java.util.Objects.equals(mAttributionTag, that.mAttributionTag);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + mUserId;
+ _hash = 31 * _hash + mSensorId;
+ _hash = 31 * _hash + mDisplayState;
+ _hash = 31 * _hash + mAuthenticateReason;
+ _hash = 31 * _hash + mWakeReason;
+ _hash = 31 * _hash + java.util.Objects.hashCode(mOpPackageName);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mAttributionTag);
+ return _hash;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ byte flg = 0;
+ if (mAttributionTag != null) flg |= 0x40;
+ dest.writeByte(flg);
+ dest.writeInt(mUserId);
+ dest.writeInt(mSensorId);
+ dest.writeInt(mDisplayState);
+ dest.writeInt(mAuthenticateReason);
+ dest.writeInt(mWakeReason);
+ dest.writeString(mOpPackageName);
+ if (mAttributionTag != null) dest.writeString(mAttributionTag);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ protected FaceAuthenticateOptions(@NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ byte flg = in.readByte();
+ int userId = in.readInt();
+ int sensorId = in.readInt();
+ int displayState = in.readInt();
+ int authenticateReason = in.readInt();
+ int wakeReason = in.readInt();
+ String opPackageName = in.readString();
+ String attributionTag = (flg & 0x40) == 0 ? null : in.readString();
+
+ this.mUserId = userId;
+ this.mSensorId = sensorId;
+ this.mDisplayState = displayState;
+ com.android.internal.util.AnnotationValidations.validate(
+ AuthenticateOptions.DisplayState.class, null, mDisplayState);
+ this.mAuthenticateReason = authenticateReason;
+
+ if (!(mAuthenticateReason == AUTHENTICATE_REASON_UNKNOWN)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_STARTED_WAKING_UP)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_ASSISTANT_VISIBLE)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_QS_EXPANDED)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER)
+ && !(mAuthenticateReason == AUTHENTICATE_REASON_UDFPS_POINTER_DOWN)) {
+ throw new java.lang.IllegalArgumentException(
+ "authenticateReason was " + mAuthenticateReason + " but must be one of: "
+ + "AUTHENTICATE_REASON_UNKNOWN(" + AUTHENTICATE_REASON_UNKNOWN + "), "
+ + "AUTHENTICATE_REASON_STARTED_WAKING_UP(" + AUTHENTICATE_REASON_STARTED_WAKING_UP + "), "
+ + "AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN(" + AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN + "), "
+ + "AUTHENTICATE_REASON_ASSISTANT_VISIBLE(" + AUTHENTICATE_REASON_ASSISTANT_VISIBLE + "), "
+ + "AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN(" + AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN + "), "
+ + "AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED(" + AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED + "), "
+ + "AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED(" + AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED + "), "
+ + "AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED(" + AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED + "), "
+ + "AUTHENTICATE_REASON_QS_EXPANDED(" + AUTHENTICATE_REASON_QS_EXPANDED + "), "
+ + "AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER(" + AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER + "), "
+ + "AUTHENTICATE_REASON_UDFPS_POINTER_DOWN(" + AUTHENTICATE_REASON_UDFPS_POINTER_DOWN + ")");
+ }
+
+ this.mWakeReason = wakeReason;
+ com.android.internal.util.AnnotationValidations.validate(
+ PowerManager.WakeReason.class, null, mWakeReason);
+ this.mOpPackageName = opPackageName;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mOpPackageName);
+ this.mAttributionTag = attributionTag;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<FaceAuthenticateOptions> CREATOR
+ = new Parcelable.Creator<FaceAuthenticateOptions>() {
+ @Override
+ public FaceAuthenticateOptions[] newArray(int size) {
+ return new FaceAuthenticateOptions[size];
+ }
+
+ @Override
+ public FaceAuthenticateOptions createFromParcel(@NonNull android.os.Parcel in) {
+ return new FaceAuthenticateOptions(in);
+ }
+ };
+
+ /**
+ * A builder for {@link FaceAuthenticateOptions}
+ */
+ @SuppressWarnings("WeakerAccess")
+ @DataClass.Generated.Member
+ public static class Builder {
+
+ private int mUserId;
+ private int mSensorId;
+ private @AuthenticateOptions.DisplayState int mDisplayState;
+ private @AuthenticateReason int mAuthenticateReason;
+ private @PowerManager.WakeReason int mWakeReason;
+ private @NonNull String mOpPackageName;
+ private @Nullable String mAttributionTag;
+
+ private long mBuilderFieldsSet = 0L;
+
+ public Builder() {
+ }
+
+ /**
+ * The user id for this operation.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setUserId(int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x1;
+ mUserId = value;
+ return this;
+ }
+
+ /**
+ * The sensor id for this operation.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setSensorId(int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x2;
+ mSensorId = value;
+ return this;
+ }
+
+ /**
+ * The current doze state of the device.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setDisplayState(@AuthenticateOptions.DisplayState int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x4;
+ mDisplayState = value;
+ return this;
+ }
+
+ /**
+ * The reason for this operation when requested by the system (sysui),
+ * otherwise AUTHENTICATE_REASON_UNKNOWN.
+ *
+ * See frameworks/base/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt
+ * for more details about each reason.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setAuthenticateReason(@AuthenticateReason int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x8;
+ mAuthenticateReason = value;
+ return this;
+ }
+
+ /**
+ * A reason if this request was triggered due to a power event or WAKE_REASON_UNKNOWN.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setWakeReason(@PowerManager.WakeReason int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x10;
+ mWakeReason = value;
+ return this;
+ }
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setOpPackageName(@NonNull String value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x20;
+ mOpPackageName = value;
+ return this;
+ }
+
+ /**
+ * The attribution tag, if any.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setAttributionTag(@NonNull String value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x40;
+ mAttributionTag = value;
+ return this;
+ }
+
+ /** Builds the instance. This builder should not be touched after calling this! */
+ public @NonNull FaceAuthenticateOptions build() {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x80; // Mark builder used
+
+ if ((mBuilderFieldsSet & 0x1) == 0) {
+ mUserId = defaultUserId();
+ }
+ if ((mBuilderFieldsSet & 0x2) == 0) {
+ mSensorId = defaultSensorId();
+ }
+ if ((mBuilderFieldsSet & 0x4) == 0) {
+ mDisplayState = defaultDisplayState();
+ }
+ if ((mBuilderFieldsSet & 0x8) == 0) {
+ mAuthenticateReason = defaultAuthenticateReason();
+ }
+ if ((mBuilderFieldsSet & 0x10) == 0) {
+ mWakeReason = defaultWakeReason();
+ }
+ if ((mBuilderFieldsSet & 0x20) == 0) {
+ mOpPackageName = defaultOpPackageName();
+ }
+ if ((mBuilderFieldsSet & 0x40) == 0) {
+ mAttributionTag = defaultAttributionTag();
+ }
+ FaceAuthenticateOptions o = new FaceAuthenticateOptions(
+ mUserId,
+ mSensorId,
+ mDisplayState,
+ mAuthenticateReason,
+ mWakeReason,
+ mOpPackageName,
+ mAttributionTag);
+ return o;
+ }
+
+ private void checkNotUsed() {
+ if ((mBuilderFieldsSet & 0x80) != 0) {
+ throw new IllegalStateException(
+ "This Builder should not be reused. Use a new Builder instance instead");
+ }
+ }
+ }
+
+ @DataClass.Generated(
+ time = 1676508211385L,
+ codegenVersion = "1.0.23",
+ sourceFile = "frameworks/base/core/java/android/hardware/face/FaceAuthenticateOptions.java",
+ inputSignatures = "private final int mUserId\nprivate final int mSensorId\nprivate final @android.hardware.biometrics.AuthenticateOptions.DisplayState int mDisplayState\npublic static final int AUTHENTICATE_REASON_UNKNOWN\npublic static final int AUTHENTICATE_REASON_STARTED_WAKING_UP\npublic static final int AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN\npublic static final int AUTHENTICATE_REASON_ASSISTANT_VISIBLE\npublic static final int AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN\npublic static final int AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED\npublic static final int AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED\npublic static final int AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED\npublic static final int AUTHENTICATE_REASON_QS_EXPANDED\npublic static final int AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER\npublic static final int AUTHENTICATE_REASON_UDFPS_POINTER_DOWN\nprivate final @android.hardware.face.FaceAuthenticateOptions.AuthenticateReason int mAuthenticateReason\nprivate final @android.os.PowerManager.WakeReason int mWakeReason\nprivate @android.annotation.NonNull java.lang.String mOpPackageName\nprivate @android.annotation.Nullable java.lang.String mAttributionTag\nprivate static int defaultUserId()\nprivate static int defaultSensorId()\nprivate static int defaultDisplayState()\nprivate static int defaultAuthenticateReason()\nprivate static int defaultWakeReason()\nprivate static java.lang.String defaultOpPackageName()\nprivate static java.lang.String defaultAttributionTag()\nclass FaceAuthenticateOptions extends java.lang.Object implements [android.hardware.biometrics.AuthenticateOptions, android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genAidl=true, genBuilder=true, genSetters=true, genEqualsHashCode=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 96098f853552..55b20e17d4d7 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -194,18 +194,30 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
}
/**
- * Request authentication of a crypto object. This call operates the face recognition hardware
- * and starts capturing images. It terminates when
+ * @deprecated use {@link #authenticate(CryptoObject, CancellationSignal, AuthenticationCallback, Handler, FaceAuthenticateOptions)}.
+ */
+ @Deprecated
+ @RequiresPermission(USE_BIOMETRIC_INTERNAL)
+ public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
+ @NonNull AuthenticationCallback callback, @Nullable Handler handler, int userId) {
+ authenticate(crypto, cancel, callback, handler, new FaceAuthenticateOptions.Builder()
+ .setUserId(userId)
+ .build());
+ }
+
+ /**
+ * Request authentication. This call operates the face recognition hardware and starts capturing images.
+ * It terminates when
* {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or
* {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult)} is called, at
* which point the object is no longer valid. The operation can be canceled by using the
* provided cancel object.
*
- * @param crypto object associated with the call or null if none required.
+ * @param crypto object associated with the call or null if none required
* @param cancel an object that can be used to cancel authentication
* @param callback an object to receive authentication events
* @param handler an optional handler to handle callback events
- * @param userId userId to authenticate for
+ * @param options additional options to customize this request
* @throws IllegalArgumentException if the crypto operation is not supported or is not backed
* by
* <a href="{@docRoot}training/articles/keystore.html">Android
@@ -215,8 +227,8 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
- @NonNull AuthenticationCallback callback, @Nullable Handler handler, int userId,
- boolean isKeyguardBypassEnabled) {
+ @NonNull AuthenticationCallback callback, @Nullable Handler handler,
+ @NonNull FaceAuthenticateOptions options) {
if (callback == null) {
throw new IllegalArgumentException("Must supply an authentication callback");
}
@@ -226,6 +238,9 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
return;
}
+ options.setOpPackageName(mContext.getOpPackageName());
+ options.setAttributionTag(mContext.getAttributionTag());
+
if (mService != null) {
try {
useHandler(handler);
@@ -233,8 +248,8 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
mCryptoObject = crypto;
final long operationId = crypto != null ? crypto.getOpId() : 0;
Trace.beginSection("FaceManager#authenticate");
- final long authId = mService.authenticate(mToken, operationId, userId,
- mServiceReceiver, mContext.getOpPackageName(), isKeyguardBypassEnabled);
+ final long authId = mService.authenticate(
+ mToken, operationId, mServiceReceiver, options);
if (cancel != null) {
cancel.setOnCancelListener(new OnAuthenticationCancelListener(authId));
}
@@ -258,7 +273,7 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
public void detectFace(@NonNull CancellationSignal cancel,
- @NonNull FaceDetectionCallback callback, int userId) {
+ @NonNull FaceDetectionCallback callback, @NonNull FaceAuthenticateOptions options) {
if (mService == null) {
return;
}
@@ -268,11 +283,13 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
return;
}
+ options.setOpPackageName(mContext.getOpPackageName());
+ options.setAttributionTag(mContext.getAttributionTag());
+
mFaceDetectionCallback = callback;
try {
- final long authId = mService.detectFace(
- mToken, userId, mServiceReceiver, mContext.getOpPackageName());
+ final long authId = mService.detectFace(mToken, mServiceReceiver, options);
cancel.setOnCancelListener(new OnFaceDetectionCancelListener(authId));
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception when requesting finger detect", e);
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index 5fcc31e3ea25..2857627bf712 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -24,6 +24,7 @@ import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.face.IFaceAuthenticatorsRegisteredCallback;
import android.hardware.face.IFaceServiceReceiver;
import android.hardware.face.Face;
+import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.view.Surface;
@@ -52,14 +53,14 @@ interface IFaceService {
// Authenticate with a face. A requestId is returned that can be used to cancel this operation.
@EnforcePermission("USE_BIOMETRIC_INTERNAL")
- long authenticate(IBinder token, long operationId, int userId, IFaceServiceReceiver receiver,
- String opPackageName, boolean isKeyguardBypassEnabled);
+ long authenticate(IBinder token, long operationId, IFaceServiceReceiver receiver,
+ in FaceAuthenticateOptions options);
// Uses the face hardware to detect for the presence of a face, without giving details
// about accept/reject/lockout. A requestId is returned that can be used to cancel this
// operation.
@EnforcePermission("USE_BIOMETRIC_INTERNAL")
- long detectFace(IBinder token, int userId, IFaceServiceReceiver receiver, String opPackageName);
+ long detectFace(IBinder token, IFaceServiceReceiver receiver, in FaceAuthenticateOptions options);
// This method prepares the service to start authenticating, but doesn't start authentication.
// This is protected by the MANAGE_BIOMETRIC signatuer permission. This method should only be
@@ -68,8 +69,8 @@ interface IFaceService {
// startPreparedClient().
@EnforcePermission("USE_BIOMETRIC_INTERNAL")
void prepareForAuthentication(int sensorId, boolean requireConfirmation, IBinder token,
- long operationId, int userId, IBiometricSensorReceiver sensorReceiver,
- String opPackageName, long requestId, int cookie,
+ long operationId, IBiometricSensorReceiver sensorReceiver,
+ in FaceAuthenticateOptions options, long requestId, int cookie,
boolean allowBackgroundAuthentication);
// Starts authentication with the previously prepared client.
diff --git a/core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.aidl b/core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.aidl
new file mode 100644
index 000000000000..ad30fab89a3b
--- /dev/null
+++ b/core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 android.hardware.fingerprint;
+
+parcelable FingerprintAuthenticateOptions;
diff --git a/core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.java b/core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.java
new file mode 100644
index 000000000000..cecb3172a8d1
--- /dev/null
+++ b/core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.java
@@ -0,0 +1,447 @@
+/*
+ * 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 android.hardware.fingerprint;
+
+import static android.hardware.fingerprint.FingerprintManager.SENSOR_ID_ANY;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.hardware.biometrics.AuthenticateOptions;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Additional options when requesting Fingerprint authentication or detection.
+ *
+ * @hide
+ */
+@DataClass(
+ genParcelable = true,
+ genAidl = true,
+ genBuilder = true,
+ genSetters = true,
+ genEqualsHashCode = true
+)
+public final class FingerprintAuthenticateOptions implements AuthenticateOptions, Parcelable {
+
+ /** The user id for this operation. */
+ private final int mUserId;
+ private static int defaultUserId() {
+ return 0;
+ }
+
+ /** The sensor id for this operation. */
+ private final int mSensorId;
+ private static int defaultSensorId() {
+ return SENSOR_ID_ANY;
+ }
+
+ /** If enrollment state should be ignored. */
+ private final boolean mIgnoreEnrollmentState;
+ private static boolean defaultIgnoreEnrollmentState() {
+ return false;
+ }
+
+ /** The current doze state of the device. */
+ @AuthenticateOptions.DisplayState
+ private final int mDisplayState;
+ private static int defaultDisplayState() {
+ return DISPLAY_STATE_UNKNOWN;
+ }
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @NonNull private String mOpPackageName;
+ private static String defaultOpPackageName() {
+ return "";
+ }
+
+ /**
+ * The attribution tag, if any.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @Nullable private String mAttributionTag;
+ private static String defaultAttributionTag() {
+ return null;
+ }
+
+
+
+ // Code below generated by codegen v1.0.23.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @DataClass.Generated.Member
+ /* package-private */ FingerprintAuthenticateOptions(
+ int userId,
+ int sensorId,
+ boolean ignoreEnrollmentState,
+ @AuthenticateOptions.DisplayState int displayState,
+ @NonNull String opPackageName,
+ @Nullable String attributionTag) {
+ this.mUserId = userId;
+ this.mSensorId = sensorId;
+ this.mIgnoreEnrollmentState = ignoreEnrollmentState;
+ this.mDisplayState = displayState;
+ com.android.internal.util.AnnotationValidations.validate(
+ AuthenticateOptions.DisplayState.class, null, mDisplayState);
+ this.mOpPackageName = opPackageName;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mOpPackageName);
+ this.mAttributionTag = attributionTag;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ /**
+ * The user id for this operation.
+ */
+ @DataClass.Generated.Member
+ public int getUserId() {
+ return mUserId;
+ }
+
+ /**
+ * The sensor id for this operation.
+ */
+ @DataClass.Generated.Member
+ public int getSensorId() {
+ return mSensorId;
+ }
+
+ /**
+ * If enrollment state should be ignored.
+ */
+ @DataClass.Generated.Member
+ public boolean isIgnoreEnrollmentState() {
+ return mIgnoreEnrollmentState;
+ }
+
+ /**
+ * The current doze state of the device.
+ */
+ @DataClass.Generated.Member
+ public @AuthenticateOptions.DisplayState int getDisplayState() {
+ return mDisplayState;
+ }
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull String getOpPackageName() {
+ return mOpPackageName;
+ }
+
+ /**
+ * The attribution tag, if any.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @Nullable String getAttributionTag() {
+ return mAttributionTag;
+ }
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull FingerprintAuthenticateOptions setOpPackageName(@NonNull String value) {
+ mOpPackageName = value;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mOpPackageName);
+ return this;
+ }
+
+ /**
+ * The attribution tag, if any.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull FingerprintAuthenticateOptions setAttributionTag(@NonNull String value) {
+ mAttributionTag = value;
+ return this;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(@Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(FingerprintAuthenticateOptions other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ FingerprintAuthenticateOptions that = (FingerprintAuthenticateOptions) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && mUserId == that.mUserId
+ && mSensorId == that.mSensorId
+ && mIgnoreEnrollmentState == that.mIgnoreEnrollmentState
+ && mDisplayState == that.mDisplayState
+ && java.util.Objects.equals(mOpPackageName, that.mOpPackageName)
+ && java.util.Objects.equals(mAttributionTag, that.mAttributionTag);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + mUserId;
+ _hash = 31 * _hash + mSensorId;
+ _hash = 31 * _hash + Boolean.hashCode(mIgnoreEnrollmentState);
+ _hash = 31 * _hash + mDisplayState;
+ _hash = 31 * _hash + java.util.Objects.hashCode(mOpPackageName);
+ _hash = 31 * _hash + java.util.Objects.hashCode(mAttributionTag);
+ return _hash;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ byte flg = 0;
+ if (mIgnoreEnrollmentState) flg |= 0x4;
+ if (mAttributionTag != null) flg |= 0x20;
+ dest.writeByte(flg);
+ dest.writeInt(mUserId);
+ dest.writeInt(mSensorId);
+ dest.writeInt(mDisplayState);
+ dest.writeString(mOpPackageName);
+ if (mAttributionTag != null) dest.writeString(mAttributionTag);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ FingerprintAuthenticateOptions(@NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ byte flg = in.readByte();
+ boolean ignoreEnrollmentState = (flg & 0x4) != 0;
+ int userId = in.readInt();
+ int sensorId = in.readInt();
+ int displayState = in.readInt();
+ String opPackageName = in.readString();
+ String attributionTag = (flg & 0x20) == 0 ? null : in.readString();
+
+ this.mUserId = userId;
+ this.mSensorId = sensorId;
+ this.mIgnoreEnrollmentState = ignoreEnrollmentState;
+ this.mDisplayState = displayState;
+ com.android.internal.util.AnnotationValidations.validate(
+ AuthenticateOptions.DisplayState.class, null, mDisplayState);
+ this.mOpPackageName = opPackageName;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mOpPackageName);
+ this.mAttributionTag = attributionTag;
+
+ // onConstructed(); // You can define this method to get a callback
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<FingerprintAuthenticateOptions> CREATOR
+ = new Parcelable.Creator<FingerprintAuthenticateOptions>() {
+ @Override
+ public FingerprintAuthenticateOptions[] newArray(int size) {
+ return new FingerprintAuthenticateOptions[size];
+ }
+
+ @Override
+ public FingerprintAuthenticateOptions createFromParcel(@NonNull android.os.Parcel in) {
+ return new FingerprintAuthenticateOptions(in);
+ }
+ };
+
+ /**
+ * A builder for {@link FingerprintAuthenticateOptions}
+ */
+ @SuppressWarnings("WeakerAccess")
+ @DataClass.Generated.Member
+ public static final class Builder {
+
+ private int mUserId;
+ private int mSensorId;
+ private boolean mIgnoreEnrollmentState;
+ private @AuthenticateOptions.DisplayState int mDisplayState;
+ private @NonNull String mOpPackageName;
+ private @Nullable String mAttributionTag;
+
+ private long mBuilderFieldsSet = 0L;
+
+ public Builder() {
+ }
+
+ /**
+ * The user id for this operation.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setUserId(int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x1;
+ mUserId = value;
+ return this;
+ }
+
+ /**
+ * The sensor id for this operation.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setSensorId(int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x2;
+ mSensorId = value;
+ return this;
+ }
+
+ /**
+ * If enrollment state should be ignored.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setIgnoreEnrollmentState(boolean value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x4;
+ mIgnoreEnrollmentState = value;
+ return this;
+ }
+
+ /**
+ * The current doze state of the device.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setDisplayState(@AuthenticateOptions.DisplayState int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x8;
+ mDisplayState = value;
+ return this;
+ }
+
+ /**
+ * The package name for that operation that should be used for
+ * {@link android.app.AppOpsManager} verification.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setOpPackageName(@NonNull String value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x10;
+ mOpPackageName = value;
+ return this;
+ }
+
+ /**
+ * The attribution tag, if any.
+ *
+ * This option may be overridden by the FingerprintManager using the caller's context.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setAttributionTag(@NonNull String value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x20;
+ mAttributionTag = value;
+ return this;
+ }
+
+ /** Builds the instance. This builder should not be touched after calling this! */
+ public @NonNull FingerprintAuthenticateOptions build() {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x40; // Mark builder used
+
+ if ((mBuilderFieldsSet & 0x1) == 0) {
+ mUserId = defaultUserId();
+ }
+ if ((mBuilderFieldsSet & 0x2) == 0) {
+ mSensorId = defaultSensorId();
+ }
+ if ((mBuilderFieldsSet & 0x4) == 0) {
+ mIgnoreEnrollmentState = defaultIgnoreEnrollmentState();
+ }
+ if ((mBuilderFieldsSet & 0x8) == 0) {
+ mDisplayState = defaultDisplayState();
+ }
+ if ((mBuilderFieldsSet & 0x10) == 0) {
+ mOpPackageName = defaultOpPackageName();
+ }
+ if ((mBuilderFieldsSet & 0x20) == 0) {
+ mAttributionTag = defaultAttributionTag();
+ }
+ FingerprintAuthenticateOptions o = new FingerprintAuthenticateOptions(
+ mUserId,
+ mSensorId,
+ mIgnoreEnrollmentState,
+ mDisplayState,
+ mOpPackageName,
+ mAttributionTag);
+ return o;
+ }
+
+ private void checkNotUsed() {
+ if ((mBuilderFieldsSet & 0x40) != 0) {
+ throw new IllegalStateException(
+ "This Builder should not be reused. Use a new Builder instance instead");
+ }
+ }
+ }
+
+ @DataClass.Generated(
+ time = 1676508212083L,
+ codegenVersion = "1.0.23",
+ sourceFile = "frameworks/base/core/java/android/hardware/fingerprint/FingerprintAuthenticateOptions.java",
+ inputSignatures = "private final int mUserId\nprivate final int mSensorId\nprivate final boolean mIgnoreEnrollmentState\nprivate final @android.hardware.biometrics.AuthenticateOptions.DisplayState int mDisplayState\nprivate @android.annotation.NonNull java.lang.String mOpPackageName\nprivate @android.annotation.Nullable java.lang.String mAttributionTag\nprivate static int defaultUserId()\nprivate static int defaultSensorId()\nprivate static boolean defaultIgnoreEnrollmentState()\nprivate static int defaultDisplayState()\nprivate static java.lang.String defaultOpPackageName()\nprivate static java.lang.String defaultAttributionTag()\nclass FingerprintAuthenticateOptions extends java.lang.Object implements [android.hardware.biometrics.AuthenticateOptions, android.os.Parcelable]\n@com.android.internal.util.DataClass(genParcelable=true, genAidl=true, genBuilder=true, genSetters=true, genEqualsHashCode=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index d9f8f8e0e715..eb8136e39d29 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -577,8 +577,10 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
/**
* Per-user version of authenticate.
+ * @deprecated use {@link #authenticate(CryptoObject, CancellationSignal, AuthenticationCallback, Handler, FingerprintAuthenticateOptions)}.
* @hide
*/
+ @Deprecated
@RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT})
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
@NonNull AuthenticationCallback callback, Handler handler, int userId) {
@@ -587,13 +589,29 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
/**
* Per-user and per-sensor version of authenticate.
+ * @deprecated use {@link #authenticate(CryptoObject, CancellationSignal, AuthenticationCallback, Handler, FingerprintAuthenticateOptions)}.
* @hide
*/
+ @Deprecated
@RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT})
public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
@NonNull AuthenticationCallback callback, Handler handler, int sensorId, int userId,
int flags) {
+ authenticate(crypto, cancel, callback, handler, new FingerprintAuthenticateOptions.Builder()
+ .setSensorId(sensorId)
+ .setUserId(userId)
+ .setIgnoreEnrollmentState(flags != 0)
+ .build());
+ }
+ /**
+ * Version of authenticate with additional options.
+ * @hide
+ */
+ @RequiresPermission(anyOf = {USE_BIOMETRIC, USE_FINGERPRINT})
+ public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel,
+ @NonNull AuthenticationCallback callback, @NonNull Handler handler,
+ @NonNull FingerprintAuthenticateOptions options) {
FrameworkStatsLog.write(FrameworkStatsLog.AUTH_DEPRECATED_API_USED,
AUTH_DEPRECATED_APIUSED__DEPRECATED_API__API_FINGERPRINT_MANAGER_AUTHENTICATE,
mContext.getApplicationInfo().uid,
@@ -608,7 +626,8 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
return;
}
- final boolean ignoreEnrollmentState = flags == 0 ? false : true;
+ options.setOpPackageName(mContext.getOpPackageName());
+ options.setAttributionTag(mContext.getAttributionTag());
if (mService != null) {
try {
@@ -616,16 +635,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
mAuthenticationCallback = callback;
mCryptoObject = crypto;
final long operationId = crypto != null ? crypto.getOpId() : 0;
- final long authId =
- mService.authenticate(
- mToken,
- operationId,
- sensorId,
- userId,
- mServiceReceiver,
- mContext.getOpPackageName(),
- mContext.getAttributionTag(),
- ignoreEnrollmentState);
+ final long authId = mService.authenticate(mToken, operationId, mServiceReceiver, options);
if (cancel != null) {
cancel.setOnCancelListener(new OnAuthenticationCancelListener(authId));
}
@@ -647,7 +657,7 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
public void detectFingerprint(@NonNull CancellationSignal cancel,
- @NonNull FingerprintDetectionCallback callback, int userId) {
+ @NonNull FingerprintDetectionCallback callback, @NonNull FingerprintAuthenticateOptions options) {
if (mService == null) {
return;
}
@@ -657,11 +667,13 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
return;
}
+ options.setOpPackageName(mContext.getOpPackageName());
+ options.setAttributionTag(mContext.getAttributionTag());
+
mFingerprintDetectionCallback = callback;
try {
- final long authId = mService.detectFingerprint(mToken, userId, mServiceReceiver,
- mContext.getOpPackageName());
+ final long authId = mService.detectFingerprint(mToken, mServiceReceiver, options);
cancel.setOnCancelListener(new OnFingerprintDetectionCancelListener(authId));
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception when requesting finger detect", e);
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index 6f35713d434f..e3ae299be730 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -29,6 +29,7 @@ import android.hardware.fingerprint.IUdfpsOverlayController;
import android.hardware.fingerprint.ISidefpsController;
import android.hardware.fingerprint.IUdfpsOverlay;
import android.hardware.fingerprint.Fingerprint;
+import android.hardware.fingerprint.FingerprintAuthenticateOptions;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import java.util.List;
@@ -56,16 +57,15 @@ interface IFingerprintService {
// Authenticate with a fingerprint. This is protected by USE_FINGERPRINT/USE_BIOMETRIC
// permission. This is effectively deprecated, since it only comes through FingerprintManager
// now. A requestId is returned that can be used to cancel this operation.
- long authenticate(IBinder token, long operationId, int sensorId, int userId,
- IFingerprintServiceReceiver receiver, String opPackageName, String attributionTag,
- boolean shouldIgnoreEnrollmentState);
+ long authenticate(IBinder token, long operationId, IFingerprintServiceReceiver receiver,
+ in FingerprintAuthenticateOptions options);
// Uses the fingerprint hardware to detect for the presence of a finger, without giving details
// about accept/reject/lockout. A requestId is returned that can be used to cancel this
// operation.
@EnforcePermission("USE_BIOMETRIC_INTERNAL")
- long detectFingerprint(IBinder token, int userId, IFingerprintServiceReceiver receiver,
- String opPackageName);
+ long detectFingerprint(IBinder token, IFingerprintServiceReceiver receiver,
+ in FingerprintAuthenticateOptions options);
// This method prepares the service to start authenticating, but doesn't start authentication.
// This is protected by the MANAGE_BIOMETRIC signatuer permission. This method should only be
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 2ea9ea06f720..a33cd9760091 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -74,6 +74,7 @@ import com.android.internal.os.SomeArgs;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -99,13 +100,12 @@ public final class InputManager {
private final IInputManager mIm;
/**
- * InputManager has historically used its own static getter {@link #getInstance()} that doesn't
- * provide a context. We provide a Context to the InputManager instance through the
- * {@link android.app.SystemServiceRegistry}. Methods that need a Context must use
- * {@link #getContext()} to obtain it.
+ * We hold a weak reference to the context to avoid leaking it indefinitely,
+ * since we currently store the input manager instance as a static variable that
+ * will outlive any context.
*/
@Nullable
- private Context mLateInitContext;
+ private WeakReference<Context> mWeakContext;
/**
* Whether a PointerIcon is shown for stylus pointers.
@@ -372,8 +372,8 @@ public final class InputManager {
throw new IllegalStateException(e);
}
}
- if (sInstance.mLateInitContext == null) {
- sInstance.mLateInitContext = context;
+ if (sInstance.mWeakContext == null || sInstance.mWeakContext.get() == null) {
+ sInstance.mWeakContext = new WeakReference(context);
}
return sInstance;
}
@@ -381,9 +381,14 @@ public final class InputManager {
@NonNull
private Context getContext() {
- return Objects.requireNonNull(mLateInitContext,
+ WeakReference<Context> weakContext = Objects.requireNonNull(mWeakContext,
"A context is required for InputManager. Get the InputManager instance using "
+ "Context#getSystemService before calling this method.");
+ // If we get at this point, an app calling this function could potentially expect a
+ // Context that has disappeared due to garbage collection. Holding a weak reference
+ // is a temporary solution that should be resolved before the release of a
+ // production version. This is being tracked in b/267758905
+ return Objects.requireNonNull(weakContext.get(), "missing Context");
}
/**
diff --git a/core/java/android/net/Ikev2VpnProfile.java b/core/java/android/net/Ikev2VpnProfile.java
index 647514486750..a20191cab774 100644
--- a/core/java/android/net/Ikev2VpnProfile.java
+++ b/core/java/android/net/Ikev2VpnProfile.java
@@ -1108,6 +1108,11 @@ public final class Ikev2VpnProfile extends PlatformVpnProfile {
/**
* Sets the enabled state of the automatic NAT-T keepalive timers
*
+ * Note that if this builder was constructed with a {@link IkeTunnelConnectionParams},
+ * but this is called with {@code true}, the framework will automatically choose the
+ * appropriate keepalive timer and ignore the settings in the session params embedded
+ * in the connection params.
+ *
* @param isEnabled {@code true} to enable automatic keepalive timers, based on internal
* platform signals. Defaults to {@code false}.
* @return this {@link Builder} object to facilitate chaining of method calls
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 80ae8a890c45..6f4cdcef266a 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -104,7 +104,7 @@ interface IPowerManager
int protocol;
int portMatcher;
int portNumber;
- @nullable String bindAddress;
+ @nullable byte[] localAddress;
}
@UnsupportedAppUsage
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 1a634f5ee33e..38e331c4ac0d 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -32,7 +32,6 @@ import android.annotation.TestApi;
import android.app.PropertyInvalidatedCache;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
-import android.net.LinkAddress;
import android.service.dreams.Sandman;
import android.sysprop.InitProperties;
import android.util.ArrayMap;
@@ -45,6 +44,8 @@ import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
@@ -3048,7 +3049,7 @@ public final class PowerManager {
*
* @see #isAllowedInLowPowerStandby(String)
*/
- public static final String LOW_POWER_STANDBY_FEATURE_WAKE_ON_LAN =
+ public static final String FEATURE_WAKE_ON_LAN_IN_LOW_POWER_STANDBY =
"com.android.lowpowerstandby.WAKE_ON_LAN";
/**
@@ -3130,10 +3131,25 @@ public final class PowerManager {
@LowPowerStandbyAllowedReason
private final int mAllowedReasons;
- /** Features that are allowed to be used in Low Power Standby. */
+ /**
+ * Features that are allowed to be used in Low Power Standby.
+ *
+ * @see #FEATURE_WAKE_ON_LAN_IN_LOW_POWER_STANDBY
+ */
@NonNull
private final Set<String> mAllowedFeatures;
+ /**
+ * Create a policy that defines the restrictions enforced by Low Power Standby.
+ *
+ * @param identifier Name of the policy, used for debugging & metrics.
+ * @param exemptPackages Packages that are exempt from Low Power Standby restrictions.
+ * @param allowedReasons Reasons that this policy allows apps to be automatically exempted
+ * from Low Power Standby restrictions for.
+ * @param allowedFeatures Features that are allowed to be used in Low Power Standby.
+ * Features are declared as strings, see
+ * {@link #FEATURE_WAKE_ON_LAN_IN_LOW_POWER_STANDBY} as an example.
+ */
public LowPowerStandbyPolicy(@NonNull String identifier,
@NonNull Set<String> exemptPackages,
@LowPowerStandbyAllowedReason int allowedReasons,
@@ -3244,11 +3260,11 @@ public final class PowerManager {
/**
* Constant to indicate the {@link LowPowerStandbyPortDescription} refers to a TCP port.
*/
- public static final int PROTOCOL_TCP = 1;
+ public static final int PROTOCOL_TCP = 6;
/**
* Constant to indicate the {@link LowPowerStandbyPortDescription} refers to a UDP port.
*/
- public static final int PROTOCOL_UDP = 2;
+ public static final int PROTOCOL_UDP = 17;
/** @hide */
@IntDef(prefix = { "MATCH_PORT_" }, value = {
@@ -3277,7 +3293,7 @@ public final class PowerManager {
private final int mPortMatcher;
private final int mPortNumber;
@Nullable
- private final LinkAddress mBindAddress;
+ private final InetAddress mLocalAddress;
/**
* Describes a port.
@@ -3296,7 +3312,7 @@ public final class PowerManager {
this.mProtocol = protocol;
this.mPortMatcher = portMatcher;
this.mPortNumber = portNumber;
- this.mBindAddress = null;
+ this.mLocalAddress = null;
}
/**
@@ -3308,16 +3324,16 @@ public final class PowerManager {
* ({@link #MATCH_PORT_REMOTE}), or the destination port
* ({@link #MATCH_PORT_LOCAL}).
* @param portNumber The port number to match.
- * @param bindAddress The bind address to match.
+ * @param localAddress The local address to match.
*
* @see #newLowPowerStandbyPortsLock(List)
*/
public LowPowerStandbyPortDescription(@Protocol int protocol, @PortMatcher int portMatcher,
- int portNumber, @Nullable LinkAddress bindAddress) {
+ int portNumber, @Nullable InetAddress localAddress) {
this.mProtocol = protocol;
this.mPortMatcher = portMatcher;
this.mPortNumber = portNumber;
- this.mBindAddress = bindAddress;
+ this.mLocalAddress = localAddress;
}
private String protocolToString(int protocol) {
@@ -3383,8 +3399,8 @@ public final class PowerManager {
* @see #getProtocol()
*/
@Nullable
- public LinkAddress getBindAddress() {
- return mBindAddress;
+ public InetAddress getLocalAddress() {
+ return mLocalAddress;
}
@Override
@@ -3393,7 +3409,7 @@ public final class PowerManager {
+ "mProtocol=" + protocolToString(mProtocol)
+ ", mPortMatcher=" + portMatcherToString(mPortMatcher)
+ ", mPortNumber=" + mPortNumber
- + ", mBindAddress=" + mBindAddress
+ + ", mLocalAddress=" + mLocalAddress
+ '}';
}
@@ -3403,13 +3419,13 @@ public final class PowerManager {
if (!(o instanceof LowPowerStandbyPortDescription)) return false;
LowPowerStandbyPortDescription that = (LowPowerStandbyPortDescription) o;
return mProtocol == that.mProtocol && mPortMatcher == that.mPortMatcher
- && mPortNumber == that.mPortNumber && Objects.equals(mBindAddress,
- that.mBindAddress);
+ && mPortNumber == that.mPortNumber && Objects.equals(mLocalAddress,
+ that.mLocalAddress);
}
@Override
public int hashCode() {
- return Objects.hash(mProtocol, mPortMatcher, mPortNumber, mBindAddress);
+ return Objects.hash(mProtocol, mPortMatcher, mPortNumber, mLocalAddress);
}
/** @hide */
@@ -3424,8 +3440,8 @@ public final class PowerManager {
parcelablePortDescription.protocol = portDescription.mProtocol;
parcelablePortDescription.portMatcher = portDescription.mPortMatcher;
parcelablePortDescription.portNumber = portDescription.mPortNumber;
- if (portDescription.mBindAddress != null) {
- parcelablePortDescription.bindAddress = portDescription.mBindAddress.toString();
+ if (portDescription.mLocalAddress != null) {
+ parcelablePortDescription.localAddress = portDescription.mLocalAddress.getAddress();
}
return parcelablePortDescription;
}
@@ -3451,15 +3467,19 @@ public final class PowerManager {
return null;
}
- LinkAddress bindAddress = null;
- if (parcelablePortDescription.bindAddress != null) {
- bindAddress = new LinkAddress(parcelablePortDescription.bindAddress);
+ InetAddress localAddress = null;
+ if (parcelablePortDescription.localAddress != null) {
+ try {
+ localAddress = InetAddress.getByAddress(parcelablePortDescription.localAddress);
+ } catch (UnknownHostException e) {
+ Log.w(TAG, "Address has invalid length", e);
+ }
}
return new LowPowerStandbyPortDescription(
parcelablePortDescription.protocol,
parcelablePortDescription.portMatcher,
parcelablePortDescription.portNumber,
- bindAddress);
+ localAddress);
}
/** @hide */
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 9c55ad692f42..bbf7f810b3c0 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -4381,11 +4381,16 @@ public class UserManager {
}
/**
- * Returns information for Primary user.
+ * Returns information for Primary user (which in practice is the same as the System user).
*
* @return the Primary user, null if not found.
+ * @deprecated For the system user, call {@link #getUserInfo} on {@link UserHandle#USER_SYSTEM},
+ * or just use {@link UserHandle#SYSTEM} or {@link UserHandle#USER_SYSTEM}.
+ * For the designated MainUser, use {@link #getMainUser()}.
+ *
* @hide
*/
+ @Deprecated
@RequiresPermission(android.Manifest.permission.MANAGE_USERS)
public @Nullable UserInfo getPrimaryUser() {
try {
diff --git a/core/java/android/service/voice/AbstractDetector.java b/core/java/android/service/voice/AbstractDetector.java
index 39c2b98fd9bc..466bc0520ee5 100644
--- a/core/java/android/service/voice/AbstractDetector.java
+++ b/core/java/android/service/voice/AbstractDetector.java
@@ -231,9 +231,12 @@ abstract class AbstractDetector implements HotwordDetector {
/** Called when the detection fails due to an error. */
@Override
- public void onError() {
- Slog.v(TAG, "BinderCallback#onError");
- Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> mCallback.onError()));
+ public void onError(DetectorFailure detectorFailure) {
+ Slog.v(TAG, "BinderCallback#onError detectorFailure: " + detectorFailure);
+ Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> {
+ mCallback.onFailure(detectorFailure != null ? detectorFailure
+ : new UnknownFailure("Error data is null"));
+ }));
}
@Override
diff --git a/core/java/android/service/voice/AlwaysOnHotwordDetector.java b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
index 48b7a5915658..50ac1f36099e 100644
--- a/core/java/android/service/voice/AlwaysOnHotwordDetector.java
+++ b/core/java/android/service/voice/AlwaysOnHotwordDetector.java
@@ -732,7 +732,13 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
*/
public abstract void onDetected(@NonNull EventPayload eventPayload);
- /** {@inheritDoc} */
+ /**
+ * {@inheritDoc}
+ *
+ * @deprecated Use {@link HotwordDetector.Callback#onError(DetectorFailure)} instead.
+ */
+ @Deprecated
+ @Override
public abstract void onError();
/** {@inheritDoc} */
@@ -1658,10 +1664,19 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
@Override
public void onError(int status) {
Slog.i(TAG, "onError: " + status);
- mHandler.sendEmptyMessage(MSG_DETECTION_ERROR);
+ // This is a workaround before the sound trigger uses the onDetectionFailure method.
+ Message.obtain(mHandler, MSG_DETECTION_ERROR,
+ new SoundTriggerFailure(status, "Sound trigger error")).sendToTarget();
}
@Override
+ public void onDetectionFailure(DetectorFailure detectorFailure) {
+ Slog.v(TAG, "onDetectionFailure detectorFailure: " + detectorFailure);
+ Message.obtain(mHandler, MSG_DETECTION_ERROR,
+ detectorFailure != null ? detectorFailure
+ : new UnknownFailure("Error data is null")).sendToTarget();
+ }
+ @Override
public void onRecognitionPaused() {
Slog.i(TAG, "onRecognitionPaused");
mHandler.sendEmptyMessage(MSG_DETECTION_PAUSE);
@@ -1716,7 +1731,7 @@ public class AlwaysOnHotwordDetector extends AbstractDetector {
mExternalCallback.onDetected((EventPayload) message.obj);
break;
case MSG_DETECTION_ERROR:
- mExternalCallback.onError();
+ mExternalCallback.onFailure((DetectorFailure) message.obj);
break;
case MSG_DETECTION_PAUSE:
mExternalCallback.onRecognitionPaused();
diff --git a/core/java/android/service/voice/DetectedPhrase.aidl b/core/java/android/service/voice/DetectedPhrase.aidl
new file mode 100644
index 000000000000..23a405d51ed9
--- /dev/null
+++ b/core/java/android/service/voice/DetectedPhrase.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 android.service.voice;
+
+parcelable DetectedPhrase;
diff --git a/core/java/android/service/voice/DetectedPhrase.java b/core/java/android/service/voice/DetectedPhrase.java
new file mode 100644
index 000000000000..bd906125f59d
--- /dev/null
+++ b/core/java/android/service/voice/DetectedPhrase.java
@@ -0,0 +1,286 @@
+/*
+ * 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 android.service.voice;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Preconditions;
+
+/**
+ * Details about the phrase used to generate a {@link HotwordDetectedResult}
+ *
+ * @hide
+ */
+@DataClass(
+ genConstructor = false,
+ genBuilder = true,
+ genEqualsHashCode = true,
+ genHiddenConstDefs = true,
+ genParcelable = true,
+ genToString = true
+)
+@SystemApi
+public final class DetectedPhrase implements Parcelable {
+
+ /**
+ * An ID representing the keyphrase that triggered the successful detection.
+ */
+ private int mId = 0;
+
+ static int defaultHotwordPhraseId() {
+ return 0;
+ }
+
+ /**
+ * A string representing exactly what was heard and interpreted by the service leading to
+ * a successful detection.
+ *
+ * <p>Can be null if not set in {@link DetectedPhrase.Builder}
+ */
+ @Nullable
+ private String mPhrase = null;
+
+ /**
+ * Provides an instance of {@link DetectedPhrase.Builder} with state corresponding to
+ * this instance.
+ * @hide
+ */
+ public DetectedPhrase.Builder buildUpon() {
+ return new DetectedPhrase.Builder()
+ .setId(mId)
+ .setPhrase(mPhrase);
+ }
+
+ private void onConstructed() {
+ Preconditions.checkArgumentNonnegative(mId, "hotwordPhraseId");
+ }
+
+
+
+ // Code below generated by codegen v1.0.23.
+ //
+ // DO NOT MODIFY!
+ // CHECKSTYLE:OFF Generated code
+ //
+ // To regenerate run:
+ // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/service/voice/DetectedPhrase.java
+ //
+ // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+ // Settings > Editor > Code Style > Formatter Control
+ //@formatter:off
+
+
+ @DataClass.Generated.Member
+ /* package-private */ DetectedPhrase(
+ int id,
+ @Nullable String phrase) {
+ this.mId = id;
+ this.mPhrase = phrase;
+
+ onConstructed();
+ }
+
+ /**
+ * An ID representing the keyphrase that triggered the successful detection.
+ */
+ @DataClass.Generated.Member
+ public int getId() {
+ return mId;
+ }
+
+ /**
+ * A string representing exactly what was heard and interpreted by the service leading to
+ * a successful detection.
+ *
+ * <p>Can be null if not set in {@link DetectedPhrase.Builder}
+ */
+ @DataClass.Generated.Member
+ public @Nullable String getPhrase() {
+ return mPhrase;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "DetectedPhrase { " +
+ "id = " + mId + ", " +
+ "phrase = " + mPhrase +
+ " }";
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public boolean equals(@Nullable Object o) {
+ // You can override field equality logic by defining either of the methods like:
+ // boolean fieldNameEquals(DetectedPhrase other) { ... }
+ // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ @SuppressWarnings("unchecked")
+ DetectedPhrase that = (DetectedPhrase) o;
+ //noinspection PointlessBooleanExpression
+ return true
+ && mId == that.mId
+ && java.util.Objects.equals(mPhrase, that.mPhrase);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int hashCode() {
+ // You can override field hashCode logic by defining methods like:
+ // int fieldNameHashCode() { ... }
+
+ int _hash = 1;
+ _hash = 31 * _hash + mId;
+ _hash = 31 * _hash + java.util.Objects.hashCode(mPhrase);
+ return _hash;
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+ // You can override field parcelling by defining methods like:
+ // void parcelFieldName(Parcel dest, int flags) { ... }
+
+ byte flg = 0;
+ if (mPhrase != null) flg |= 0x2;
+ dest.writeByte(flg);
+ dest.writeInt(mId);
+ if (mPhrase != null) dest.writeString(mPhrase);
+ }
+
+ @Override
+ @DataClass.Generated.Member
+ public int describeContents() { return 0; }
+
+ /** @hide */
+ @SuppressWarnings({"unchecked", "RedundantCast"})
+ @DataClass.Generated.Member
+ /* package-private */ DetectedPhrase(@NonNull android.os.Parcel in) {
+ // You can override field unparcelling by defining methods like:
+ // static FieldType unparcelFieldName(Parcel in) { ... }
+
+ byte flg = in.readByte();
+ int id = in.readInt();
+ String phrase = (flg & 0x2) == 0 ? null : in.readString();
+
+ this.mId = id;
+ this.mPhrase = phrase;
+
+ onConstructed();
+ }
+
+ @DataClass.Generated.Member
+ public static final @NonNull Parcelable.Creator<DetectedPhrase> CREATOR
+ = new Parcelable.Creator<DetectedPhrase>() {
+ @Override
+ public DetectedPhrase[] newArray(int size) {
+ return new DetectedPhrase[size];
+ }
+
+ @Override
+ public DetectedPhrase createFromParcel(@NonNull android.os.Parcel in) {
+ return new DetectedPhrase(in);
+ }
+ };
+
+ /**
+ * A builder for {@link DetectedPhrase}
+ */
+ @SuppressWarnings("WeakerAccess")
+ @DataClass.Generated.Member
+ public static final class Builder {
+
+ private int mId;
+ private @Nullable String mPhrase;
+
+ private long mBuilderFieldsSet = 0L;
+
+ public Builder() {
+ }
+
+ /**
+ * An ID representing the keyphrase that triggered the successful detection.
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setId(int value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x1;
+ mId = value;
+ return this;
+ }
+
+ /**
+ * A string representing exactly what was heard and interpreted by the service leading to
+ * a successful detection.
+ *
+ * <p>Can be null if not set in {@link DetectedPhrase.Builder}
+ */
+ @DataClass.Generated.Member
+ public @NonNull Builder setPhrase(@NonNull String value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x2;
+ mPhrase = value;
+ return this;
+ }
+
+ /** Builds the instance. This builder should not be touched after calling this! */
+ public @NonNull DetectedPhrase build() {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x4; // Mark builder used
+
+ if ((mBuilderFieldsSet & 0x1) == 0) {
+ mId = 0;
+ }
+ if ((mBuilderFieldsSet & 0x2) == 0) {
+ mPhrase = null;
+ }
+ DetectedPhrase o = new DetectedPhrase(
+ mId,
+ mPhrase);
+ return o;
+ }
+
+ private void checkNotUsed() {
+ if ((mBuilderFieldsSet & 0x4) != 0) {
+ throw new IllegalStateException(
+ "This Builder should not be reused. Use a new Builder instance instead");
+ }
+ }
+ }
+
+ @DataClass.Generated(
+ time = 1676870329959L,
+ codegenVersion = "1.0.23",
+ sourceFile = "frameworks/base/core/java/android/service/voice/DetectedPhrase.java",
+ inputSignatures = "private int mId\nprivate @android.annotation.Nullable java.lang.String mPhrase\nstatic int defaultHotwordPhraseId()\npublic android.service.voice.DetectedPhrase.Builder buildUpon()\nprivate void onConstructed()\nclass DetectedPhrase extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)")
+ @Deprecated
+ private void __metadata() {}
+
+
+ //@formatter:on
+ // End of generated code
+
+}
diff --git a/core/java/android/service/voice/DetectorFailure.aidl b/core/java/android/service/voice/DetectorFailure.aidl
new file mode 100644
index 000000000000..3591329ac111
--- /dev/null
+++ b/core/java/android/service/voice/DetectorFailure.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 android.service.voice;
+
+parcelable DetectorFailure;
diff --git a/core/java/android/service/voice/DetectorFailure.java b/core/java/android/service/voice/DetectorFailure.java
new file mode 100644
index 000000000000..c6efdc3063e3
--- /dev/null
+++ b/core/java/android/service/voice/DetectorFailure.java
@@ -0,0 +1,218 @@
+/*
+ * 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 android.service.voice;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * This is used by the assistant application to know what went wrong during using the detector
+ * and which action the application should take. The detector can be a HotwordDector or a visual
+ * query detector.
+ *
+ * <p>Any class that derives this class must only add an integer value of error source type, an
+ * integer value of error code and a string of error message passed into the constructor. Any other
+ * field will not be parceled through. If the derived class has custom parceling implementation,
+ * this class will not be able to unpack the parcel without having access to that implementation.
+ *
+ * @hide
+ */
+@SuppressLint("ParcelNotFinal") // Safe because the constructor is package-private
+@SystemApi
+public abstract class DetectorFailure implements Parcelable {
+
+ /**
+ * A suggested action due to an unknown error occurs.
+ */
+ public static final int SUGGESTED_ACTION_UNKNOWN = 0;
+
+ /**
+ * Indicates that an error occurs, but no action is needed for the client. The error will be
+ * recovered from within the framework.
+ */
+ public static final int SUGGESTED_ACTION_NONE = 1;
+
+ /**
+ * Indicates that an error occurs, but no action is needed for the client due to the error can
+ * not be recovered. It means that the detection will not work even though the assistant
+ * application creates the detector again.
+ *
+ * Example: The detection service always crashes after assistant application creates the
+ * detector. The assistant application can stop re-creating the detector and show a suitable
+ * error dialog to notify the user.
+ */
+ public static final int SUGGESTED_ACTION_DISABLE_DETECTION = 2;
+
+ /**
+ * Indicates that the detection service is invalid, the client needs to destroy its detector
+ * first and recreate its detector later.
+ */
+ public static final int SUGGESTED_ACTION_RECREATE_DETECTOR = 3;
+
+ /**
+ * Indicates that the detection has stopped. The client needs to start recognition again.
+ *
+ * Example: The system server receives a Dsp trigger event.
+ */
+ public static final int SUGGESTED_ACTION_RESTART_RECOGNITION = 4;
+
+ /**
+ * @hide
+ */
+ @IntDef(prefix = {"SUGGESTED_ACTION_"}, value = {
+ SUGGESTED_ACTION_UNKNOWN,
+ SUGGESTED_ACTION_NONE,
+ SUGGESTED_ACTION_DISABLE_DETECTION,
+ SUGGESTED_ACTION_RECREATE_DETECTOR,
+ SUGGESTED_ACTION_RESTART_RECOGNITION
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SuggestedAction {}
+
+ /**
+ * Indicates that an error occurs from the unknown error source.
+ *
+ * @hide
+ */
+ public static final int ERROR_SOURCE_TYPE_UNKNOWN = -1;
+
+ /**
+ * Indicates that an error occurs from the hotword detection.
+ *
+ * @see HotwordDetectionServiceFailure#ERROR_CODE_BIND_FAILURE
+ * @see HotwordDetectionServiceFailure#ERROR_CODE_BINDING_DIED
+ * @see HotwordDetectionServiceFailure#ERROR_CODE_COPY_AUDIO_DATA_FAILURE
+ * @see HotwordDetectionServiceFailure#ERROR_CODE_DETECT_TIMEOUT
+ * @see HotwordDetectionServiceFailure#ERROR_CODE_ON_DETECTED_SECURITY_EXCEPTION
+ * @see HotwordDetectionServiceFailure#ERROR_CODE_ON_DETECTED_STREAM_COPY_FAILURE
+ * @see HotwordDetectionServiceFailure#ERROR_CODE_REMOTE_EXCEPTION
+ *
+ * @hide
+ */
+ public static final int ERROR_SOURCE_TYPE_HOTWORD_DETECTION = 0;
+
+ /**
+ * Indicates that an error occurs from the sound trigger system service
+ * {@link com.android.server.soundtrigger.SoundTriggerService} and
+ * {@link com.android.server.soundtrigger_middleware.SoundTriggerMiddlewareService}.
+ *
+ * @see SoundTriggerFailure#ERROR_CODE_MODULE_DIED
+ * @see SoundTriggerFailure#ERROR_CODE_RECOGNITION_RESUME_FAILED
+ * @see SoundTriggerFailure#ERROR_CODE_UNEXPECTED_PREEMPTION
+ *
+ * @hide
+ */
+ public static final int ERROR_SOURCE_TYPE_SOUND_TRIGGER = 1;
+
+ /**
+ * Indicates that an error occurs from {@link VisualQueryDetectionService}.
+ *
+ * @see VisualQueryDetectionServiceFailure#ERROR_CODE_BIND_FAILURE
+ * @see VisualQueryDetectionServiceFailure#ERROR_CODE_BINDING_DIED
+ * @see VisualQueryDetectionServiceFailure#ERROR_CODE_ILLEGAL_ATTENTION_STATE
+ * @see VisualQueryDetectionServiceFailure#ERROR_CODE_ILLEGAL_STREAMING_STATE
+ * @see VisualQueryDetectionServiceFailure#ERROR_CODE_REMOTE_EXCEPTION
+ *
+ * @hide
+ */
+ public static final int ERROR_SOURCE_TYPE_VISUAL_QUERY_DETECTION = 2;
+
+ private int mErrorSourceType = ERROR_SOURCE_TYPE_UNKNOWN;
+ private int mErrorCode = UnknownFailure.ERROR_CODE_UNKNOWN;
+ private String mErrorMessage = "Unknown";
+
+ DetectorFailure(int errorSourceType, int errorCode, @NonNull String errorMessage) {
+ Preconditions.checkArgumentInRange(errorSourceType, ERROR_SOURCE_TYPE_UNKNOWN,
+ ERROR_SOURCE_TYPE_VISUAL_QUERY_DETECTION, "errorSourceType");
+ if (TextUtils.isEmpty(errorMessage)) {
+ throw new IllegalArgumentException("errorMessage is empty or null.");
+ }
+ mErrorSourceType = errorSourceType;
+ mErrorCode = errorCode;
+ mErrorMessage = errorMessage;
+ }
+
+ /**
+ * Returns the suggested action.
+ */
+ @SuggestedAction
+ public abstract int getSuggestedAction();
+
+ /**
+ * Returns the error code.
+ *
+ * @hide
+ */
+ public int getErrorCode() {
+ return mErrorCode;
+ }
+
+ /**
+ * Returns the error message.
+ */
+ @NonNull
+ public String getErrorMessage() {
+ return mErrorMessage;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mErrorSourceType);
+ dest.writeInt(mErrorCode);
+ dest.writeString8(mErrorMessage);
+ }
+
+ public static final @NonNull Parcelable.Creator<DetectorFailure> CREATOR =
+ new Parcelable.Creator<DetectorFailure>() {
+ @Override
+ public DetectorFailure[] newArray(int size) {
+ return new DetectorFailure[size];
+ }
+
+ @Override
+ public DetectorFailure createFromParcel(@NonNull Parcel in) {
+ final int errorSourceType = in.readInt();
+ final int errorCode = in.readInt();
+ final String errorMessage = in.readString8();
+ switch (errorSourceType) {
+ case ERROR_SOURCE_TYPE_HOTWORD_DETECTION:
+ return new HotwordDetectionServiceFailure(errorCode, errorMessage);
+ case ERROR_SOURCE_TYPE_SOUND_TRIGGER:
+ return new SoundTriggerFailure(errorCode, errorMessage);
+ case ERROR_SOURCE_TYPE_VISUAL_QUERY_DETECTION:
+ return new VisualQueryDetectionServiceFailure(errorCode, errorMessage);
+ default:
+ return new UnknownFailure(errorMessage);
+ }
+ }
+ };
+}
diff --git a/core/java/android/service/voice/HotwordDetectedResult.java b/core/java/android/service/voice/HotwordDetectedResult.java
index dee560b322bb..dd3f99cc27ef 100644
--- a/core/java/android/service/voice/HotwordDetectedResult.java
+++ b/core/java/android/service/voice/HotwordDetectedResult.java
@@ -203,17 +203,23 @@ public final class HotwordDetectedResult implements Parcelable {
* An ID representing the keyphrase that triggered the successful detection.
*
* <p>Only values between 0 and {@link #getMaxHotwordPhraseId()} (inclusive) are accepted.
+ *
+ * @deprecated Use {@link #getDetectedPhrase()} and
+ * {@link DetectedPhrase#getId()}.
*/
- private final int mHotwordPhraseId;
- private static int defaultHotwordPhraseId() {
- return 0;
+ @Deprecated
+ public int getHotwordPhraseId() {
+ return mDetectedPhrase.getId();
}
/**
* Returns the maximum value of {@link #getHotwordPhraseId()}.
+ *
+ * @deprecated There is no maximum phrase ID enforced
*/
+ @Deprecated
public static int getMaxHotwordPhraseId() {
- return 63;
+ return Integer.MAX_VALUE;
}
/**
@@ -285,6 +291,10 @@ public final class HotwordDetectedResult implements Parcelable {
return mMediaSyncEvent;
}
+ @NonNull
+ private DetectedPhrase mDetectedPhrase =
+ new DetectedPhrase.Builder().build();
+
/**
* Returns how many bytes should be written into the Parcel
*
@@ -302,6 +312,9 @@ public final class HotwordDetectedResult implements Parcelable {
/**
* Returns how many bits have been written into the HotwordDetectedResult.
*
+ * <p>{@link #getAudioStreams()} and {@link #getDetectedPhrase()}
+ * are not counted here.
+ *
* @hide
*/
public static int getUsageSize(@NonNull HotwordDetectedResult hotwordDetectedResult) {
@@ -329,9 +342,6 @@ public final class HotwordDetectedResult implements Parcelable {
if (hotwordDetectedResult.getPersonalizedScore() != defaultPersonalizedScore()) {
totalBits += bitCount(HotwordDetectedResult.getMaxScore());
}
- if (hotwordDetectedResult.getHotwordPhraseId() != defaultHotwordPhraseId()) {
- totalBits += bitCount(HotwordDetectedResult.getMaxHotwordPhraseId());
- }
PersistableBundle persistableBundle = hotwordDetectedResult.getExtras();
if (!persistableBundle.isEmpty()) {
totalBits += getParcelableSize(persistableBundle) * Byte.SIZE;
@@ -339,7 +349,7 @@ public final class HotwordDetectedResult implements Parcelable {
return totalBits;
}
- private static int bitCount(long value) {
+ static int bitCount(long value) {
int bits = 0;
while (value > 0) {
bits++;
@@ -352,8 +362,6 @@ public final class HotwordDetectedResult implements Parcelable {
Preconditions.checkArgumentInRange(mScore, 0, getMaxScore(), "score");
Preconditions.checkArgumentInRange(mPersonalizedScore, 0, getMaxScore(),
"personalizedScore");
- Preconditions.checkArgumentInRange(mHotwordPhraseId, 0, getMaxHotwordPhraseId(),
- "hotwordPhraseId");
Preconditions.checkArgumentInRange((long) mHotwordDurationMillis, 0,
AudioRecord.getMaxSharedAudioHistoryMillis(), "hotwordDurationMillis");
if (mHotwordOffsetMillis != HOTWORD_OFFSET_UNSET) {
@@ -448,10 +456,25 @@ public final class HotwordDetectedResult implements Parcelable {
Objects.requireNonNull(value, "value should not be null");
final Builder builder = (Builder) this;
// If the code gen flag in build() is changed, we must update the flag e.g. 0x200 here.
- builder.mBuilderFieldsSet |= 0x200;
+ builder.mBuilderFieldsSet |= 0x100;
builder.mAudioStreams = List.copyOf(value);
return builder;
}
+
+ /**
+ * An ID representing the keyphrase that triggered the successful detection.
+ *
+ * <p>Only values between 0 and {@link #getMaxHotwordPhraseId()} (inclusive) are accepted.
+ *
+ * @deprecated Use {@link HotwordDetectedResult.Builder#setDetectedPhrase(DetectedPhrase)}
+ * and {@link DetectedPhrase.Builder#setId(int)}
+ */
+ @Deprecated
+ public @NonNull Builder setHotwordPhraseId(int value) {
+ final Builder builder = (Builder) this;
+ builder.setDetectedPhrase(new DetectedPhrase.Builder().setId(value).build());
+ return builder;
+ }
}
/**
@@ -468,9 +491,9 @@ public final class HotwordDetectedResult implements Parcelable {
.setHotwordDetectionPersonalized(mHotwordDetectionPersonalized)
.setScore(mScore)
.setPersonalizedScore(mPersonalizedScore)
- .setHotwordPhraseId(mHotwordPhraseId)
.setAudioStreams(mAudioStreams)
- .setExtras(mExtras);
+ .setExtras(mExtras)
+ .setDetectedPhrase(mDetectedPhrase);
}
@@ -579,9 +602,9 @@ public final class HotwordDetectedResult implements Parcelable {
boolean hotwordDetectionPersonalized,
int score,
int personalizedScore,
- int hotwordPhraseId,
@NonNull List<HotwordAudioStream> audioStreams,
- @NonNull PersistableBundle extras) {
+ @NonNull PersistableBundle extras,
+ @NonNull DetectedPhrase detectedPhrase) {
this.mConfidenceLevel = confidenceLevel;
com.android.internal.util.AnnotationValidations.validate(
HotwordConfidenceLevelValue.class, null, mConfidenceLevel);
@@ -592,13 +615,15 @@ public final class HotwordDetectedResult implements Parcelable {
this.mHotwordDetectionPersonalized = hotwordDetectionPersonalized;
this.mScore = score;
this.mPersonalizedScore = personalizedScore;
- this.mHotwordPhraseId = hotwordPhraseId;
this.mAudioStreams = audioStreams;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mAudioStreams);
this.mExtras = extras;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mExtras);
+ this.mDetectedPhrase = detectedPhrase;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mDetectedPhrase);
onConstructed();
}
@@ -673,16 +698,6 @@ public final class HotwordDetectedResult implements Parcelable {
}
/**
- * An ID representing the keyphrase that triggered the successful detection.
- *
- * <p>Only values between 0 and {@link #getMaxHotwordPhraseId()} (inclusive) are accepted.
- */
- @DataClass.Generated.Member
- public int getHotwordPhraseId() {
- return mHotwordPhraseId;
- }
-
- /**
* App-specific extras to support trigger.
*
* <p>The size of this bundle will be limited to {@link #getMaxBundleSize}. Results will larger
@@ -712,6 +727,11 @@ public final class HotwordDetectedResult implements Parcelable {
return mExtras;
}
+ @DataClass.Generated.Member
+ public @NonNull DetectedPhrase getDetectedPhrase() {
+ return mDetectedPhrase;
+ }
+
@Override
@DataClass.Generated.Member
public String toString() {
@@ -727,9 +747,9 @@ public final class HotwordDetectedResult implements Parcelable {
"hotwordDetectionPersonalized = " + mHotwordDetectionPersonalized + ", " +
"score = " + mScore + ", " +
"personalizedScore = " + mPersonalizedScore + ", " +
- "hotwordPhraseId = " + mHotwordPhraseId + ", " +
"audioStreams = " + mAudioStreams + ", " +
- "extras = " + mExtras +
+ "extras = " + mExtras + ", " +
+ "detectedPhrase = " + mDetectedPhrase +
" }";
}
@@ -754,9 +774,9 @@ public final class HotwordDetectedResult implements Parcelable {
&& mHotwordDetectionPersonalized == that.mHotwordDetectionPersonalized
&& mScore == that.mScore
&& mPersonalizedScore == that.mPersonalizedScore
- && mHotwordPhraseId == that.mHotwordPhraseId
&& Objects.equals(mAudioStreams, that.mAudioStreams)
- && Objects.equals(mExtras, that.mExtras);
+ && Objects.equals(mExtras, that.mExtras)
+ && Objects.equals(mDetectedPhrase, that.mDetectedPhrase);
}
@Override
@@ -774,9 +794,9 @@ public final class HotwordDetectedResult implements Parcelable {
_hash = 31 * _hash + Boolean.hashCode(mHotwordDetectionPersonalized);
_hash = 31 * _hash + mScore;
_hash = 31 * _hash + mPersonalizedScore;
- _hash = 31 * _hash + mHotwordPhraseId;
_hash = 31 * _hash + Objects.hashCode(mAudioStreams);
_hash = 31 * _hash + Objects.hashCode(mExtras);
+ _hash = 31 * _hash + Objects.hashCode(mDetectedPhrase);
return _hash;
}
@@ -797,9 +817,9 @@ public final class HotwordDetectedResult implements Parcelable {
dest.writeInt(mAudioChannel);
dest.writeInt(mScore);
dest.writeInt(mPersonalizedScore);
- dest.writeInt(mHotwordPhraseId);
dest.writeParcelableList(mAudioStreams, flags);
dest.writeTypedObject(mExtras, flags);
+ dest.writeTypedObject(mDetectedPhrase, flags);
}
@Override
@@ -822,10 +842,10 @@ public final class HotwordDetectedResult implements Parcelable {
int audioChannel = in.readInt();
int score = in.readInt();
int personalizedScore = in.readInt();
- int hotwordPhraseId = in.readInt();
List<HotwordAudioStream> audioStreams = new ArrayList<>();
in.readParcelableList(audioStreams, HotwordAudioStream.class.getClassLoader());
PersistableBundle extras = (PersistableBundle) in.readTypedObject(PersistableBundle.CREATOR);
+ DetectedPhrase detectedPhrase = (DetectedPhrase) in.readTypedObject(DetectedPhrase.CREATOR);
this.mConfidenceLevel = confidenceLevel;
com.android.internal.util.AnnotationValidations.validate(
@@ -837,13 +857,15 @@ public final class HotwordDetectedResult implements Parcelable {
this.mHotwordDetectionPersonalized = hotwordDetectionPersonalized;
this.mScore = score;
this.mPersonalizedScore = personalizedScore;
- this.mHotwordPhraseId = hotwordPhraseId;
this.mAudioStreams = audioStreams;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mAudioStreams);
this.mExtras = extras;
com.android.internal.util.AnnotationValidations.validate(
NonNull.class, null, mExtras);
+ this.mDetectedPhrase = detectedPhrase;
+ com.android.internal.util.AnnotationValidations.validate(
+ NonNull.class, null, mDetectedPhrase);
onConstructed();
}
@@ -877,9 +899,9 @@ public final class HotwordDetectedResult implements Parcelable {
private boolean mHotwordDetectionPersonalized;
private int mScore;
private int mPersonalizedScore;
- private int mHotwordPhraseId;
private @NonNull List<HotwordAudioStream> mAudioStreams;
private @NonNull PersistableBundle mExtras;
+ private @NonNull DetectedPhrase mDetectedPhrase;
private long mBuilderFieldsSet = 0L;
@@ -990,19 +1012,6 @@ public final class HotwordDetectedResult implements Parcelable {
}
/**
- * An ID representing the keyphrase that triggered the successful detection.
- *
- * <p>Only values between 0 and {@link #getMaxHotwordPhraseId()} (inclusive) are accepted.
- */
- @DataClass.Generated.Member
- public @NonNull Builder setHotwordPhraseId(int value) {
- checkNotUsed();
- mBuilderFieldsSet |= 0x100;
- mHotwordPhraseId = value;
- return this;
- }
-
- /**
* App-specific extras to support trigger.
*
* <p>The size of this bundle will be limited to {@link #getMaxBundleSize}. Results will larger
@@ -1030,11 +1039,19 @@ public final class HotwordDetectedResult implements Parcelable {
@DataClass.Generated.Member
public @NonNull Builder setExtras(@NonNull PersistableBundle value) {
checkNotUsed();
- mBuilderFieldsSet |= 0x400;
+ mBuilderFieldsSet |= 0x200;
mExtras = value;
return this;
}
+ @DataClass.Generated.Member
+ public @NonNull Builder setDetectedPhrase(@NonNull DetectedPhrase value) {
+ checkNotUsed();
+ mBuilderFieldsSet |= 0x400;
+ mDetectedPhrase = value;
+ return this;
+ }
+
/** Builds the instance. This builder should not be touched after calling this! */
public @NonNull HotwordDetectedResult build() {
checkNotUsed();
@@ -1065,13 +1082,13 @@ public final class HotwordDetectedResult implements Parcelable {
mPersonalizedScore = defaultPersonalizedScore();
}
if ((mBuilderFieldsSet & 0x100) == 0) {
- mHotwordPhraseId = defaultHotwordPhraseId();
+ mAudioStreams = defaultAudioStreams();
}
if ((mBuilderFieldsSet & 0x200) == 0) {
- mAudioStreams = defaultAudioStreams();
+ mExtras = defaultExtras();
}
if ((mBuilderFieldsSet & 0x400) == 0) {
- mExtras = defaultExtras();
+ mDetectedPhrase = new DetectedPhrase.Builder().build();
}
HotwordDetectedResult o = new HotwordDetectedResult(
mConfidenceLevel,
@@ -1082,9 +1099,9 @@ public final class HotwordDetectedResult implements Parcelable {
mHotwordDetectionPersonalized,
mScore,
mPersonalizedScore,
- mHotwordPhraseId,
mAudioStreams,
- mExtras);
+ mExtras,
+ mDetectedPhrase);
return o;
}
@@ -1097,10 +1114,10 @@ public final class HotwordDetectedResult implements Parcelable {
}
@DataClass.Generated(
- time = 1668385264834L,
+ time = 1676870324215L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/service/voice/HotwordDetectedResult.java",
- inputSignatures = "public static final int CONFIDENCE_LEVEL_NONE\npublic static final int CONFIDENCE_LEVEL_LOW\npublic static final int CONFIDENCE_LEVEL_LOW_MEDIUM\npublic static final int CONFIDENCE_LEVEL_MEDIUM\npublic static final int CONFIDENCE_LEVEL_MEDIUM_HIGH\npublic static final int CONFIDENCE_LEVEL_HIGH\npublic static final int CONFIDENCE_LEVEL_VERY_HIGH\npublic static final int HOTWORD_OFFSET_UNSET\npublic static final int AUDIO_CHANNEL_UNSET\nprivate static final int LIMIT_HOTWORD_OFFSET_MAX_VALUE\nprivate static final int LIMIT_AUDIO_CHANNEL_MAX_VALUE\nprivate static final java.lang.String EXTRA_PROXIMITY\npublic static final int PROXIMITY_UNKNOWN\npublic static final int PROXIMITY_NEAR\npublic static final int PROXIMITY_FAR\nprivate final @android.service.voice.HotwordDetectedResult.HotwordConfidenceLevelValue int mConfidenceLevel\nprivate @android.annotation.Nullable android.media.MediaSyncEvent mMediaSyncEvent\nprivate int mHotwordOffsetMillis\nprivate int mHotwordDurationMillis\nprivate int mAudioChannel\nprivate boolean mHotwordDetectionPersonalized\nprivate final int mScore\nprivate final int mPersonalizedScore\nprivate final int mHotwordPhraseId\nprivate final @android.annotation.NonNull java.util.List<android.service.voice.HotwordAudioStream> mAudioStreams\nprivate final @android.annotation.NonNull android.os.PersistableBundle mExtras\nprivate static int sMaxBundleSize\nprivate static int defaultConfidenceLevel()\nprivate static int defaultScore()\nprivate static int defaultPersonalizedScore()\npublic static int getMaxScore()\nprivate static int defaultHotwordPhraseId()\npublic static int getMaxHotwordPhraseId()\nprivate static java.util.List<android.service.voice.HotwordAudioStream> defaultAudioStreams()\nprivate static android.os.PersistableBundle defaultExtras()\npublic static int getMaxBundleSize()\npublic @android.annotation.Nullable android.media.MediaSyncEvent getMediaSyncEvent()\npublic static int getParcelableSize(android.os.Parcelable)\npublic static int getUsageSize(android.service.voice.HotwordDetectedResult)\nprivate static int bitCount(long)\nprivate void onConstructed()\npublic @android.annotation.NonNull java.util.List<android.service.voice.HotwordAudioStream> getAudioStreams()\npublic void setProximity(double)\npublic @android.service.voice.HotwordDetectedResult.ProximityValue int getProximity()\nprivate @android.service.voice.HotwordDetectedResult.ProximityValue int convertToProximityLevel(double)\npublic android.service.voice.HotwordDetectedResult.Builder buildUpon()\nclass HotwordDetectedResult extends java.lang.Object implements [android.os.Parcelable]\npublic @android.annotation.NonNull android.service.voice.HotwordDetectedResult.Builder setAudioStreams(java.util.List<android.service.voice.HotwordAudioStream>)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)\npublic @android.annotation.NonNull android.service.voice.HotwordDetectedResult.Builder setAudioStreams(java.util.List<android.service.voice.HotwordAudioStream>)\nclass BaseBuilder extends java.lang.Object implements []")
+ inputSignatures = "public static final int CONFIDENCE_LEVEL_NONE\npublic static final int CONFIDENCE_LEVEL_LOW\npublic static final int CONFIDENCE_LEVEL_LOW_MEDIUM\npublic static final int CONFIDENCE_LEVEL_MEDIUM\npublic static final int CONFIDENCE_LEVEL_MEDIUM_HIGH\npublic static final int CONFIDENCE_LEVEL_HIGH\npublic static final int CONFIDENCE_LEVEL_VERY_HIGH\npublic static final int HOTWORD_OFFSET_UNSET\npublic static final int AUDIO_CHANNEL_UNSET\nprivate static final int LIMIT_HOTWORD_OFFSET_MAX_VALUE\nprivate static final int LIMIT_AUDIO_CHANNEL_MAX_VALUE\nprivate static final java.lang.String EXTRA_PROXIMITY\npublic static final int PROXIMITY_UNKNOWN\npublic static final int PROXIMITY_NEAR\npublic static final int PROXIMITY_FAR\nprivate final @android.service.voice.HotwordDetectedResult.HotwordConfidenceLevelValue int mConfidenceLevel\nprivate @android.annotation.Nullable android.media.MediaSyncEvent mMediaSyncEvent\nprivate int mHotwordOffsetMillis\nprivate int mHotwordDurationMillis\nprivate int mAudioChannel\nprivate boolean mHotwordDetectionPersonalized\nprivate final int mScore\nprivate final int mPersonalizedScore\nprivate final @android.annotation.NonNull java.util.List<android.service.voice.HotwordAudioStream> mAudioStreams\nprivate final @android.annotation.NonNull android.os.PersistableBundle mExtras\nprivate static int sMaxBundleSize\nprivate @android.annotation.NonNull android.service.voice.DetectedPhrase mDetectedPhrase\nprivate static int defaultConfidenceLevel()\nprivate static int defaultScore()\nprivate static int defaultPersonalizedScore()\npublic static int getMaxScore()\npublic @java.lang.Deprecated int getHotwordPhraseId()\npublic static @java.lang.Deprecated int getMaxHotwordPhraseId()\nprivate static java.util.List<android.service.voice.HotwordAudioStream> defaultAudioStreams()\nprivate static android.os.PersistableBundle defaultExtras()\npublic static int getMaxBundleSize()\npublic @android.annotation.Nullable android.media.MediaSyncEvent getMediaSyncEvent()\npublic static int getParcelableSize(android.os.Parcelable)\npublic static int getUsageSize(android.service.voice.HotwordDetectedResult)\nstatic int bitCount(long)\nprivate void onConstructed()\npublic @android.annotation.NonNull java.util.List<android.service.voice.HotwordAudioStream> getAudioStreams()\npublic void setProximity(double)\npublic @android.service.voice.HotwordDetectedResult.ProximityValue int getProximity()\nprivate @android.service.voice.HotwordDetectedResult.ProximityValue int convertToProximityLevel(double)\npublic android.service.voice.HotwordDetectedResult.Builder buildUpon()\nclass HotwordDetectedResult extends java.lang.Object implements [android.os.Parcelable]\npublic @android.annotation.NonNull android.service.voice.HotwordDetectedResult.Builder setAudioStreams(java.util.List<android.service.voice.HotwordAudioStream>)\npublic @java.lang.Deprecated @android.annotation.NonNull android.service.voice.HotwordDetectedResult.Builder setHotwordPhraseId(int)\nclass BaseBuilder extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false, genBuilder=true, genEqualsHashCode=true, genHiddenConstDefs=true, genParcelable=true, genToString=true)\npublic @android.annotation.NonNull android.service.voice.HotwordDetectedResult.Builder setAudioStreams(java.util.List<android.service.voice.HotwordAudioStream>)\npublic @java.lang.Deprecated @android.annotation.NonNull android.service.voice.HotwordDetectedResult.Builder setHotwordPhraseId(int)\nclass BaseBuilder extends java.lang.Object implements []")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/service/voice/HotwordDetectionServiceFailure.aidl b/core/java/android/service/voice/HotwordDetectionServiceFailure.aidl
new file mode 100644
index 000000000000..8d3cfc2de850
--- /dev/null
+++ b/core/java/android/service/voice/HotwordDetectionServiceFailure.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 android.service.voice;
+
+parcelable HotwordDetectionServiceFailure;
diff --git a/core/java/android/service/voice/HotwordDetectionServiceFailure.java b/core/java/android/service/voice/HotwordDetectionServiceFailure.java
new file mode 100644
index 000000000000..3d9f66b173d4
--- /dev/null
+++ b/core/java/android/service/voice/HotwordDetectionServiceFailure.java
@@ -0,0 +1,152 @@
+/*
+ * 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 android.service.voice;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * This class is used by the assistant application to know what went wrong during using the
+ * {@link HotwordDetector} and which action that the application should take. When an error occurs
+ * from Dsp hotword detection, software hotword detection and {@link HotwordDetectionService}, the
+ * system will send {@link HotwordDetectionServiceFailure} which contains the error code, error
+ * message and the suggested action to help the assistant application to take the next action.
+ *
+ * @hide
+ */
+@SystemApi
+public final class HotwordDetectionServiceFailure extends DetectorFailure {
+
+ /**
+ * An error code which means an unknown error occurs.
+ */
+ public static final int ERROR_CODE_UNKNOWN = 0;
+
+ /**
+ * Indicates that the system server binds hotword detection service failure.
+ */
+ public static final int ERROR_CODE_BIND_FAILURE = 1;
+
+ /**
+ * Indicates that the hotword detection service is dead.
+ */
+ public static final int ERROR_CODE_BINDING_DIED = 2;
+
+ /**
+ * Indicates to copy audio data failure for external source detection.
+ */
+ public static final int ERROR_CODE_COPY_AUDIO_DATA_FAILURE = 3;
+
+ /**
+ * Indicates that the detection service doesn’t respond to the detection result before timeout.
+ */
+ public static final int ERROR_CODE_DETECT_TIMEOUT = 4;
+
+ /**
+ * Indicates that the security exception occurs in #onDetected method.
+ */
+ public static final int ERROR_CODE_ON_DETECTED_SECURITY_EXCEPTION = 5;
+
+ /**
+ * Indicates to copy the audio stream failure in #onDetected method.
+ */
+ public static final int ERROR_CODE_ON_DETECTED_STREAM_COPY_FAILURE = 6;
+
+ /**
+ * Indicates that the remote exception occurs when calling callback method.
+ */
+ public static final int ERROR_CODE_REMOTE_EXCEPTION = 7;
+
+ /**
+ * @hide
+ */
+ @IntDef(prefix = {"ERROR_CODE_"}, value = {
+ ERROR_CODE_UNKNOWN,
+ ERROR_CODE_BIND_FAILURE,
+ ERROR_CODE_BINDING_DIED,
+ ERROR_CODE_COPY_AUDIO_DATA_FAILURE,
+ ERROR_CODE_DETECT_TIMEOUT,
+ ERROR_CODE_ON_DETECTED_SECURITY_EXCEPTION,
+ ERROR_CODE_ON_DETECTED_STREAM_COPY_FAILURE,
+ ERROR_CODE_REMOTE_EXCEPTION
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface HotwordDetectionServiceErrorCode {}
+
+ /**
+ * @hide
+ */
+ @TestApi
+ public HotwordDetectionServiceFailure(int errorCode, @NonNull String errorMessage) {
+ super(ERROR_SOURCE_TYPE_HOTWORD_DETECTION, errorCode, errorMessage);
+ }
+
+ /**
+ * Returns the error code.
+ */
+ @HotwordDetectionServiceErrorCode
+ public int getErrorCode() {
+ return super.getErrorCode();
+ }
+
+ @Override
+ public int getSuggestedAction() {
+ switch (getErrorCode()) {
+ case ERROR_CODE_BIND_FAILURE:
+ case ERROR_CODE_BINDING_DIED:
+ case ERROR_CODE_REMOTE_EXCEPTION:
+ return SUGGESTED_ACTION_RECREATE_DETECTOR;
+ case ERROR_CODE_DETECT_TIMEOUT:
+ case ERROR_CODE_ON_DETECTED_SECURITY_EXCEPTION:
+ case ERROR_CODE_ON_DETECTED_STREAM_COPY_FAILURE:
+ return SUGGESTED_ACTION_RESTART_RECOGNITION;
+ default:
+ return SUGGESTED_ACTION_NONE;
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ }
+
+ public static final @NonNull Parcelable.Creator<HotwordDetectionServiceFailure> CREATOR =
+ new Parcelable.Creator<HotwordDetectionServiceFailure>() {
+ @Override
+ public HotwordDetectionServiceFailure[] newArray(int size) {
+ return new HotwordDetectionServiceFailure[size];
+ }
+
+ @Override
+ public HotwordDetectionServiceFailure createFromParcel(@NonNull Parcel in) {
+ DetectorFailure detectorFailure = DetectorFailure.CREATOR.createFromParcel(in);
+ return (HotwordDetectionServiceFailure) detectorFailure;
+ }
+ };
+}
diff --git a/core/java/android/service/voice/HotwordDetector.java b/core/java/android/service/voice/HotwordDetector.java
index 562277e9d097..22d97b7bbcaa 100644
--- a/core/java/android/service/voice/HotwordDetector.java
+++ b/core/java/android/service/voice/HotwordDetector.java
@@ -231,10 +231,29 @@ public interface HotwordDetector {
/**
* Called when the detection fails due to an error.
+ *
+ * @deprecated On Android 14 and above, implement {@link #onFailure(DetectorFailure)}
+ * instead.
*/
+ @Deprecated
void onError();
/**
+ * Called when the detection fails due to an error, the subclasses of
+ * {@link DetectorFailure} will be reported to the detector.
+ *
+ * @see android.service.voice.HotwordDetectionServiceFailure
+ * @see android.service.voice.SoundTriggerFailure
+ * @see android.service.voice.UnknownFailure
+ * @see android.service.voice.VisualQueryDetectionServiceFailure
+ *
+ * @param detectorFailure It provides the error code, error message and suggested action.
+ */
+ default void onFailure(@NonNull DetectorFailure detectorFailure) {
+ onError();
+ }
+
+ /**
* Called when the recognition is paused temporarily for some reason.
* This is an informational callback, and the clients shouldn't be doing anything here
* except showing an indication on their UI if they have to.
diff --git a/core/java/android/service/voice/IMicrophoneHotwordDetectionVoiceInteractionCallback.aidl b/core/java/android/service/voice/IMicrophoneHotwordDetectionVoiceInteractionCallback.aidl
index 61ac68be9775..f800c1ee22d6 100644
--- a/core/java/android/service/voice/IMicrophoneHotwordDetectionVoiceInteractionCallback.aidl
+++ b/core/java/android/service/voice/IMicrophoneHotwordDetectionVoiceInteractionCallback.aidl
@@ -17,6 +17,7 @@
package android.service.voice;
import android.media.AudioFormat;
+import android.service.voice.DetectorFailure;
import android.service.voice.HotwordDetectedResult;
import android.service.voice.HotwordRejectedResult;
@@ -38,7 +39,7 @@ oneway interface IMicrophoneHotwordDetectionVoiceInteractionCallback {
/**
* Called when the detection fails due to an error.
*/
- void onError();
+ void onError(in DetectorFailure detectorFailure);
/**
* Called when the detected result was not detected.
diff --git a/core/java/android/service/voice/IVisualQueryDetectionVoiceInteractionCallback.aidl b/core/java/android/service/voice/IVisualQueryDetectionVoiceInteractionCallback.aidl
index 2eb24706da30..1a935c0acbf6 100644
--- a/core/java/android/service/voice/IVisualQueryDetectionVoiceInteractionCallback.aidl
+++ b/core/java/android/service/voice/IVisualQueryDetectionVoiceInteractionCallback.aidl
@@ -16,7 +16,7 @@
package android.service.voice;
-import android.media.AudioFormat;
+import android.service.voice.DetectorFailure;
/**
* Callback for returning the detected result from the VisualQueryDetectionService.
@@ -43,6 +43,5 @@ oneway interface IVisualQueryDetectionVoiceInteractionCallback {
/**
* Called when the detection fails due to an error.
*/
- void onError();
-
+ void onDetectionFailure(in DetectorFailure detectorFailure);
}
diff --git a/core/java/android/service/voice/SoftwareHotwordDetector.java b/core/java/android/service/voice/SoftwareHotwordDetector.java
index 6e17bd0e656d..d4b6f3bf5c4c 100644
--- a/core/java/android/service/voice/SoftwareHotwordDetector.java
+++ b/core/java/android/service/voice/SoftwareHotwordDetector.java
@@ -169,9 +169,12 @@ class SoftwareHotwordDetector extends AbstractDetector {
/** Called when the detection fails due to an error. */
@Override
- public void onError() {
- Slog.v(TAG, "BinderCallback#onError");
- Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> mCallback.onError()));
+ public void onError(DetectorFailure detectorFailure) {
+ Slog.v(TAG, "BinderCallback#onError detectorFailure: " + detectorFailure);
+ Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> {
+ mCallback.onFailure(detectorFailure != null ? detectorFailure
+ : new UnknownFailure("Error data is null"));
+ }));
}
@Override
@@ -222,6 +225,16 @@ class SoftwareHotwordDetector extends AbstractDetector {
if (DEBUG) {
Slog.i(TAG, "Ignored #onError (" + status + ") event");
}
+ // TODO: Check if we still need to implement this method with DetectorFailure mechanism.
+ }
+
+ @Override
+ public void onDetectionFailure(DetectorFailure detectorFailure) throws RemoteException {
+ Slog.v(TAG, "onDetectionFailure detectorFailure: " + detectorFailure);
+ Binder.withCleanCallingIdentity(() -> mExecutor.execute(() -> {
+ mCallback.onFailure(detectorFailure != null ? detectorFailure
+ : new UnknownFailure("Error data is null"));
+ }));
}
@Override
diff --git a/core/java/android/service/voice/SoundTriggerFailure.aidl b/core/java/android/service/voice/SoundTriggerFailure.aidl
new file mode 100644
index 000000000000..7ba1c7bf338e
--- /dev/null
+++ b/core/java/android/service/voice/SoundTriggerFailure.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 android.service.voice;
+
+parcelable SoundTriggerFailure;
diff --git a/core/java/android/service/voice/SoundTriggerFailure.java b/core/java/android/service/voice/SoundTriggerFailure.java
new file mode 100644
index 000000000000..a431fbc0fe1d
--- /dev/null
+++ b/core/java/android/service/voice/SoundTriggerFailure.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.voice;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * This class is used by the assistant application to know what went wrong during using the
+ * sound trigger system service {@link com.android.server.soundtrigger.SoundTriggerService} and
+ * {@link com.android.server.soundtrigger_middleware.SoundTriggerMiddlewareService}, and which
+ * action that the application should take.
+ *
+ * @hide
+ */
+@SystemApi
+public final class SoundTriggerFailure extends DetectorFailure {
+
+ /**
+ * An error code which means an unknown error occurs.
+ */
+ public static final int ERROR_CODE_UNKNOWN = 0;
+
+ /**
+ * Indicates that the underlying sound trigger module has died and will be restarted. All
+ * session state has been invalidated.
+ */
+ public static final int ERROR_CODE_MODULE_DIED = 1;
+
+ /**
+ * Indicates that sound trigger service recognition resume has failed. The model is in the
+ * stopped state and will not be restarted by the framework.
+ */
+ public static final int ERROR_CODE_RECOGNITION_RESUME_FAILED = 2;
+
+ /**
+ * Indicates that the sound trigger service has been unexpectedly preempted by another user.
+ * The model is in the stopped state and will not be restarted by the framework.
+ */
+ public static final int ERROR_CODE_UNEXPECTED_PREEMPTION = 3;
+
+ /**
+ * @hide
+ */
+ @IntDef(prefix = {"ERROR_CODE_"}, value = {
+ ERROR_CODE_UNKNOWN,
+ ERROR_CODE_MODULE_DIED,
+ ERROR_CODE_RECOGNITION_RESUME_FAILED,
+ ERROR_CODE_UNEXPECTED_PREEMPTION
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SoundTriggerErrorCode {}
+
+ /**
+ * @hide
+ */
+ @TestApi
+ public SoundTriggerFailure(int errorCode, @NonNull String errorMessage) {
+ super(ERROR_SOURCE_TYPE_SOUND_TRIGGER, errorCode, errorMessage);
+ }
+
+ /**
+ * Returns the error code.
+ */
+ @SoundTriggerErrorCode
+ public int getErrorCode() {
+ return super.getErrorCode();
+ }
+
+ @Override
+ public int getSuggestedAction() {
+ switch (getErrorCode()) {
+ case ERROR_CODE_MODULE_DIED:
+ case ERROR_CODE_UNEXPECTED_PREEMPTION:
+ return SUGGESTED_ACTION_RECREATE_DETECTOR;
+ case ERROR_CODE_RECOGNITION_RESUME_FAILED:
+ return SUGGESTED_ACTION_RESTART_RECOGNITION;
+ default:
+ return SUGGESTED_ACTION_NONE;
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ }
+
+ public static final @NonNull Parcelable.Creator<SoundTriggerFailure> CREATOR =
+ new Parcelable.Creator<SoundTriggerFailure>() {
+ @Override
+ public SoundTriggerFailure[] newArray(int size) {
+ return new SoundTriggerFailure[size];
+ }
+
+ @Override
+ public SoundTriggerFailure createFromParcel(@NonNull Parcel in) {
+ return (SoundTriggerFailure) DetectorFailure.CREATOR.createFromParcel(in);
+ }
+ };
+}
diff --git a/core/java/android/service/voice/UnknownFailure.aidl b/core/java/android/service/voice/UnknownFailure.aidl
new file mode 100644
index 000000000000..cf43cc2fad46
--- /dev/null
+++ b/core/java/android/service/voice/UnknownFailure.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 android.service.voice;
+
+parcelable UnknownFailure;
diff --git a/core/java/android/service/voice/UnknownFailure.java b/core/java/android/service/voice/UnknownFailure.java
new file mode 100644
index 000000000000..2ef2d5f880fd
--- /dev/null
+++ b/core/java/android/service/voice/UnknownFailure.java
@@ -0,0 +1,77 @@
+/*
+ * 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 android.service.voice;
+
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A class which indicates an unknown error occurs during the detector doing detection. The class
+ * is mainly used by the assistant application, the application still can get the suggested action
+ * for the unknown error.
+ *
+ * @hide
+ */
+@SystemApi
+public final class UnknownFailure extends DetectorFailure {
+
+ /**
+ * An error code which means an unknown error occurs.
+ *
+ * @hide
+ */
+ public static final int ERROR_CODE_UNKNOWN = 0;
+
+ /**
+ * @hide
+ */
+ @TestApi
+ public UnknownFailure(@NonNull String errorMessage) {
+ super(ERROR_SOURCE_TYPE_UNKNOWN, ERROR_CODE_UNKNOWN, errorMessage);
+ }
+
+ @Override
+ public int getSuggestedAction() {
+ return SUGGESTED_ACTION_UNKNOWN;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ }
+
+ public static final @NonNull Parcelable.Creator<UnknownFailure> CREATOR =
+ new Parcelable.Creator<UnknownFailure>() {
+ @Override
+ public UnknownFailure[] newArray(int size) {
+ return new UnknownFailure[size];
+ }
+
+ @Override
+ public UnknownFailure createFromParcel(@NonNull Parcel in) {
+ return (UnknownFailure) DetectorFailure.CREATOR.createFromParcel(in);
+ }
+ };
+}
diff --git a/core/java/android/service/voice/VisualQueryDetectionServiceFailure.aidl b/core/java/android/service/voice/VisualQueryDetectionServiceFailure.aidl
new file mode 100644
index 000000000000..877df2895357
--- /dev/null
+++ b/core/java/android/service/voice/VisualQueryDetectionServiceFailure.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 android.service.voice;
+
+parcelable VisualQueryDetectionServiceFailure;
diff --git a/core/java/android/service/voice/VisualQueryDetectionServiceFailure.java b/core/java/android/service/voice/VisualQueryDetectionServiceFailure.java
new file mode 100644
index 000000000000..aa02299b2b28
--- /dev/null
+++ b/core/java/android/service/voice/VisualQueryDetectionServiceFailure.java
@@ -0,0 +1,136 @@
+/*
+ * 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 android.service.voice;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.SystemApi;
+import android.annotation.TestApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * This class is used by the assistant application to know what went wrong during using
+ * {@link VisualQueryDetectionService} and which action that the application should take.
+ *
+ * @hide
+ */
+@SystemApi
+public final class VisualQueryDetectionServiceFailure extends DetectorFailure {
+
+ /**
+ * An error code which means an unknown error occurs.
+ */
+ public static final int ERROR_CODE_UNKNOWN = 0;
+
+ /**
+ * Indicates that the system server binds visual query detection service failure.
+ */
+ public static final int ERROR_CODE_BIND_FAILURE = 1;
+
+ /**
+ * Indicates that the visual query detection service is dead.
+ */
+ public static final int ERROR_CODE_BINDING_DIED = 2;
+
+ /**
+ * Indicates that the detection service has no attention listener registered.
+ */
+ public static final int ERROR_CODE_ILLEGAL_ATTENTION_STATE = 3;
+
+ /**
+ * Indicates that the detection service is not egressing and should not be streaming queries.
+ */
+ public static final int ERROR_CODE_ILLEGAL_STREAMING_STATE = 4;
+
+ /**
+ * Indicates that the remote exception occurs when calling callback method.
+ */
+ public static final int ERROR_CODE_REMOTE_EXCEPTION = 5;
+
+ /**
+ * @hide
+ */
+ @IntDef(prefix = {"ERROR_CODE_"}, value = {
+ ERROR_CODE_UNKNOWN,
+ ERROR_CODE_BIND_FAILURE,
+ ERROR_CODE_BINDING_DIED,
+ ERROR_CODE_ILLEGAL_ATTENTION_STATE,
+ ERROR_CODE_ILLEGAL_STREAMING_STATE,
+ ERROR_CODE_REMOTE_EXCEPTION
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface VisualQueryDetectionServiceErrorCode {}
+
+ /**
+ * @hide
+ */
+ @TestApi
+ public VisualQueryDetectionServiceFailure(int errorCode, @NonNull String errorMessage) {
+ super(ERROR_SOURCE_TYPE_VISUAL_QUERY_DETECTION, errorCode, errorMessage);
+ }
+
+ /**
+ * Returns the error code.
+ */
+ @VisualQueryDetectionServiceErrorCode
+ public int getErrorCode() {
+ return super.getErrorCode();
+ }
+
+ @Override
+ public int getSuggestedAction() {
+ switch (getErrorCode()) {
+ case ERROR_CODE_BIND_FAILURE:
+ case ERROR_CODE_BINDING_DIED:
+ case ERROR_CODE_ILLEGAL_ATTENTION_STATE:
+ case ERROR_CODE_REMOTE_EXCEPTION:
+ return SUGGESTED_ACTION_RECREATE_DETECTOR;
+ case ERROR_CODE_ILLEGAL_STREAMING_STATE:
+ return SUGGESTED_ACTION_RESTART_RECOGNITION;
+ default:
+ return SUGGESTED_ACTION_NONE;
+ }
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ super.writeToParcel(dest, flags);
+ }
+
+ public static final @NonNull Parcelable.Creator<VisualQueryDetectionServiceFailure> CREATOR =
+ new Parcelable.Creator<VisualQueryDetectionServiceFailure>() {
+ @Override
+ public VisualQueryDetectionServiceFailure[] newArray(int size) {
+ return new VisualQueryDetectionServiceFailure[size];
+ }
+
+ @Override
+ public VisualQueryDetectionServiceFailure createFromParcel(@NonNull Parcel in) {
+ DetectorFailure detectorFailure = DetectorFailure.CREATOR.createFromParcel(in);
+ return (VisualQueryDetectionServiceFailure) detectorFailure;
+ }
+ };
+}
diff --git a/core/java/android/service/voice/VisualQueryDetector.java b/core/java/android/service/voice/VisualQueryDetector.java
index e4c47ef7cee3..0be3253fc570 100644
--- a/core/java/android/service/voice/VisualQueryDetector.java
+++ b/core/java/android/service/voice/VisualQueryDetector.java
@@ -216,8 +216,7 @@ public class VisualQueryDetector {
/**
* Called when the detection fails due to an error.
*/
- //TODO(b/265390855): Replace this callback with the new onError(DetectorError) design.
- void onError();
+ void onFailure(@NonNull DetectorFailure detectorFailure);
}
private class VisualQueryDetectorInitializationDelegate extends AbstractDetector {
@@ -294,12 +293,11 @@ public class VisualQueryDetector {
/** Called when the detection fails due to an error. */
@Override
- public void onError() {
- Slog.v(TAG, "BinderCallback#onError");
+ public void onDetectionFailure(DetectorFailure detectorFailure) {
+ Slog.v(TAG, "BinderCallback#onDetectionFailure");
Binder.withCleanCallingIdentity(() -> mExecutor.execute(
- () -> mCallback.onError()));
+ () -> mCallback.onFailure(detectorFailure)));
}
-
}
@@ -373,5 +371,9 @@ public class VisualQueryDetector {
Slog.v(TAG, "Initialization Error: (" + status + ")");
// Do nothing
}
+
+ @Override
+ public void onDetectionFailure(DetectorFailure detectorFailure) throws RemoteException {
+ }
}
}
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 5778518921ca..cabcae30851f 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -26,6 +26,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.app.Activity;
+import android.app.ActivityOptions;
import android.app.Dialog;
import android.app.DirectAction;
import android.app.Instrumentation;
@@ -1527,8 +1528,34 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
* <p>By default, the system will create a window for the UI for this session. If you are using
* an assistant activity instead, then you can disable the window creation by calling
* {@link #setUiEnabled} in {@link #onPrepareShow(Bundle, int)}.</p>
+ *
+ * NOTE: if the app would like to override some options to start the Activity,
+ * use {@link #startAssistantActivity(Intent, Bundle)} instead.
*/
public void startAssistantActivity(Intent intent) {
+ startAssistantActivity(intent, ActivityOptions.makeBasic().toBundle());
+ }
+
+ /**
+ * <p>Ask that a new assistant activity be started. This will create a new task in the
+ * in activity manager: this means that
+ * {@link Intent#FLAG_ACTIVITY_NEW_TASK Intent.FLAG_ACTIVITY_NEW_TASK}
+ * will be set for you to make it a new task.</p>
+ *
+ * <p>The newly started activity will be displayed on top of other activities in the system
+ * in a new layer that is not affected by multi-window mode. Tasks started from this activity
+ * will go into the normal activity layer and not this new layer.</p>
+ *
+ * <p>By default, the system will create a window for the UI for this session. If you are using
+ * an assistant activity instead, then you can disable the window creation by calling
+ * {@link #setUiEnabled} in {@link #onPrepareShow(Bundle, int)}.</p>
+ *
+ * @param intent the intent used to start an assistant activity
+ * @param bundle Additional options for how the Activity should be started. See
+ * {@link ActivityOptions} for how to build the Bundle supplied here.
+ */
+ public void startAssistantActivity(@NonNull Intent intent, @NonNull Bundle bundle) {
+ Objects.requireNonNull(bundle);
if (mToken == null) {
throw new IllegalStateException("Can't call before onCreate()");
}
@@ -1537,7 +1564,7 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
intent.prepareToLeaveProcess(mContext);
int res = mSystemService.startAssistantActivity(mToken, intent,
intent.resolveType(mContext.getContentResolver()),
- mContext.getAttributionTag());
+ mContext.getAttributionTag(), bundle);
Instrumentation.checkStartActivityResult(res, intent);
} catch (RemoteException e) {
}
diff --git a/core/java/android/service/wallpaper/IWallpaperService.aidl b/core/java/android/service/wallpaper/IWallpaperService.aidl
index f46c60fc4f7a..da56b4b2f574 100644
--- a/core/java/android/service/wallpaper/IWallpaperService.aidl
+++ b/core/java/android/service/wallpaper/IWallpaperService.aidl
@@ -26,5 +26,5 @@ oneway interface IWallpaperService {
void attach(IWallpaperConnection connection,
IBinder windowToken, int windowType, boolean isPreview,
int reqWidth, int reqHeight, in Rect padding, int displayId, int which);
- void detach();
+ void detach(IBinder windowToken);
}
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index d21e5dffc88e..12cd5236017c 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -60,6 +60,7 @@ import android.hardware.display.DisplayManager.DisplayListener;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
+import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
@@ -68,9 +69,11 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
+import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
import android.util.MergedConfiguration;
+import android.util.Slog;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.Gravity;
@@ -102,7 +105,6 @@ import com.android.internal.view.BaseSurfaceHolder;
import java.io.FileDescriptor;
import java.io.PrintWriter;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
@@ -177,8 +179,10 @@ public abstract class WallpaperService extends Service {
private static final long DIMMING_ANIMATION_DURATION_MS = 300L;
- private final ArrayList<Engine> mActiveEngines
- = new ArrayList<Engine>();
+ private final ArrayMap<IBinder, IWallpaperEngineWrapper> mActiveEngines = new ArrayMap<>();
+
+ private Handler mBackgroundHandler;
+ private HandlerThread mBackgroundThread;
static final class WallpaperCommand {
String action;
@@ -198,14 +202,6 @@ public abstract class WallpaperService extends Service {
*/
public class Engine {
IWallpaperEngineWrapper mIWallpaperEngine;
- final ArraySet<RectF> mLocalColorAreas = new ArraySet<>(4);
- final ArraySet<RectF> mLocalColorsToAdd = new ArraySet<>(4);
-
- // 2D matrix [x][y] to represent a page of a portion of a window
- EngineWindowPage[] mWindowPages = new EngineWindowPage[0];
- Bitmap mLastScreenshot;
- int mLastWindowPage = -1;
- private boolean mResetWindowPages;
// Copies from mIWallpaperEngine.
HandlerCaller mCaller;
@@ -266,11 +262,27 @@ public abstract class WallpaperService extends Service {
final Object mLock = new Object();
boolean mOffsetMessageEnqueued;
+
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
float mPendingXOffset;
float mPendingYOffset;
float mPendingXOffsetStep;
float mPendingYOffsetStep;
+
+ /**
+ * local color extraction related fields
+ * to be used by the background thread only (except the atomic boolean)
+ */
+ final ArraySet<RectF> mLocalColorAreas = new ArraySet<>(4);
+ final ArraySet<RectF> mLocalColorsToAdd = new ArraySet<>(4);
+ private long mLastProcessLocalColorsTimestamp;
+ private AtomicBoolean mProcessLocalColorsPending = new AtomicBoolean(false);
+ private int mPixelCopyCount = 0;
+ // 2D matrix [x][y] to represent a page of a portion of a window
+ EngineWindowPage[] mWindowPages = new EngineWindowPage[0];
+ Bitmap mLastScreenshot;
+ private boolean mResetWindowPages;
+
boolean mPendingSync;
MotionEvent mPendingMove;
boolean mIsInAmbientMode;
@@ -279,12 +291,8 @@ public abstract class WallpaperService extends Service {
private long mLastColorInvalidation;
private final Runnable mNotifyColorsChanged = this::notifyColorsChanged;
- // used to throttle processLocalColors
- private long mLastProcessLocalColorsTimestamp;
- private AtomicBoolean mProcessLocalColorsPending = new AtomicBoolean(false);
private final Supplier<Long> mClockFunction;
private final Handler mHandler;
-
private Display mDisplay;
private Context mDisplayContext;
private int mDisplayState;
@@ -854,7 +862,7 @@ public abstract class WallpaperService extends Service {
+ "was not established.");
}
mResetWindowPages = true;
- processLocalColors(mPendingXOffset, mPendingXOffsetStep);
+ processLocalColors();
} catch (RemoteException e) {
Log.w(TAG, "Can't notify system because wallpaper connection was lost.", e);
}
@@ -1392,7 +1400,7 @@ public abstract class WallpaperService extends Service {
resetWindowPages();
mSession.finishDrawing(mWindow, null /* postDrawTransaction */,
Integer.MAX_VALUE);
- processLocalColors(mPendingXOffset, mPendingXOffsetStep);
+ processLocalColors();
}
reposition();
reportEngineShown(shouldWaitForEngineShown());
@@ -1536,7 +1544,7 @@ public abstract class WallpaperService extends Service {
if (!mDestroyed) {
mVisible = visible;
reportVisibility();
- if (mReportedVisible) processLocalColors(mPendingXOffset, mPendingXOffsetStep);
+ if (mReportedVisible) processLocalColors();
} else {
AnimationHandler.requestAnimatorsEnabled(visible, this);
}
@@ -1620,31 +1628,41 @@ public abstract class WallpaperService extends Service {
}
// setup local color extraction data
- processLocalColors(xOffset, xOffsetStep);
+ processLocalColors();
}
/**
* Thread-safe util to call {@link #processLocalColorsInternal} with a minimum interval of
* {@link #PROCESS_LOCAL_COLORS_INTERVAL_MS} between two calls.
*/
- private void processLocalColors(float xOffset, float xOffsetStep) {
+ private void processLocalColors() {
if (mProcessLocalColorsPending.compareAndSet(false, true)) {
final long now = mClockFunction.get();
final long timeSinceLastColorProcess = now - mLastProcessLocalColorsTimestamp;
final long timeToWait = Math.max(0,
PROCESS_LOCAL_COLORS_INTERVAL_MS - timeSinceLastColorProcess);
- mHandler.postDelayed(() -> {
+ mBackgroundHandler.postDelayed(() -> {
mLastProcessLocalColorsTimestamp = now + timeToWait;
mProcessLocalColorsPending.set(false);
- processLocalColorsInternal(xOffset, xOffsetStep);
+ processLocalColorsInternal();
}, timeToWait);
}
}
- private void processLocalColorsInternal(float xOffset, float xOffsetStep) {
+ private void processLocalColorsInternal() {
// implemented by the wallpaper
if (supportsLocalColorExtraction()) return;
+ assertBackgroundThread();
+ float xOffset;
+ float xOffsetStep;
+ float wallpaperDimAmount;
+ synchronized (mLock) {
+ xOffset = mPendingXOffset;
+ xOffsetStep = mPendingXOffsetStep;
+ wallpaperDimAmount = mWallpaperDimAmount;
+ }
+
if (DEBUG) {
Log.d(TAG, "processLocalColors " + xOffset + " of step "
+ xOffsetStep);
@@ -1707,7 +1725,7 @@ public abstract class WallpaperService extends Service {
xPage = mWindowPages.length - 1;
}
current = mWindowPages[xPage];
- updatePage(current, xPage, xPages, finalXOffsetStep);
+ updatePage(current, xPage, xPages, wallpaperDimAmount);
Trace.endSection();
}
@@ -1727,16 +1745,23 @@ public abstract class WallpaperService extends Service {
}
}
+ /**
+ * Must be called with the surface lock held.
+ * Must not be called if the surface is not valid.
+ * Will unlock the surface when done using it.
+ */
void updatePage(EngineWindowPage currentPage, int pageIndx, int numPages,
- float xOffsetStep) {
+ float wallpaperDimAmount) {
+
+ assertBackgroundThread();
+
// in case the clock is zero, we start with negative time
long current = SystemClock.elapsedRealtime() - DEFAULT_UPDATE_SCREENSHOT_DURATION;
long lapsed = current - currentPage.getLastUpdateTime();
// Always update the page when the last update time is <= 0
// This is important especially when the device first boots
- if (lapsed < DEFAULT_UPDATE_SCREENSHOT_DURATION) {
- return;
- }
+ if (lapsed < DEFAULT_UPDATE_SCREENSHOT_DURATION) return;
+
Surface surface = mSurfaceHolder.getSurface();
if (!surface.isValid()) return;
boolean widthIsLarger = mSurfaceSize.x > mSurfaceSize.y;
@@ -1752,33 +1777,42 @@ public abstract class WallpaperService extends Service {
Bitmap screenShot = Bitmap.createBitmap(width, height,
Bitmap.Config.ARGB_8888);
final Bitmap finalScreenShot = screenShot;
- Trace.beginSection("WallpaperService#pixelCopy");
- PixelCopy.request(surface, screenShot, (res) -> {
- Trace.endSection();
- if (DEBUG) Log.d(TAG, "result of pixel copy is " + res);
- if (res != PixelCopy.SUCCESS) {
- Bitmap lastBitmap = currentPage.getBitmap();
- // assign the last bitmap taken for now
- currentPage.setBitmap(mLastScreenshot);
- Bitmap lastScreenshot = mLastScreenshot;
- if (lastScreenshot != null && !lastScreenshot.isRecycled()
- && !Objects.equals(lastBitmap, lastScreenshot)) {
- updatePageColors(currentPage, pageIndx, numPages, xOffsetStep);
+ final String pixelCopySectionName = "WallpaperService#pixelCopy";
+ final int pixelCopyCount = mPixelCopyCount++;
+ Trace.beginAsyncSection(pixelCopySectionName, pixelCopyCount);
+ try {
+ PixelCopy.request(surface, screenShot, (res) -> {
+ Trace.endAsyncSection(pixelCopySectionName, pixelCopyCount);
+ if (DEBUG) Log.d(TAG, "result of pixel copy is " + res);
+ if (res != PixelCopy.SUCCESS) {
+ Bitmap lastBitmap = currentPage.getBitmap();
+ // assign the last bitmap taken for now
+ currentPage.setBitmap(mLastScreenshot);
+ Bitmap lastScreenshot = mLastScreenshot;
+ if (lastScreenshot != null && !lastScreenshot.isRecycled()
+ && !Objects.equals(lastBitmap, lastScreenshot)) {
+ updatePageColors(currentPage, pageIndx, numPages, wallpaperDimAmount);
+ }
+ } else {
+ mLastScreenshot = finalScreenShot;
+ // going to hold this lock for a while
+ currentPage.setBitmap(finalScreenShot);
+ currentPage.setLastUpdateTime(current);
+ updatePageColors(currentPage, pageIndx, numPages, wallpaperDimAmount);
}
- } else {
- mLastScreenshot = finalScreenShot;
- // going to hold this lock for a while
- currentPage.setBitmap(finalScreenShot);
- currentPage.setLastUpdateTime(current);
- updatePageColors(currentPage, pageIndx, numPages, xOffsetStep);
- }
- }, mHandler);
-
+ }, mBackgroundHandler);
+ } catch (IllegalArgumentException e) {
+ // this can potentially happen if the surface is invalidated right between the
+ // surface.isValid() check and the PixelCopy operation.
+ // in this case, stop: we'll compute colors on the next processLocalColors call.
+ Log.i(TAG, "Cancelling processLocalColors: exception caught during PixelCopy");
+ }
}
// locked by the passed page
- private void updatePageColors(EngineWindowPage page, int pageIndx, int numPages,
- float xOffsetStep) {
+ private void updatePageColors(
+ EngineWindowPage page, int pageIndx, int numPages, float wallpaperDimAmount) {
if (page.getBitmap() == null) return;
+ assertBackgroundThread();
Trace.beginSection("WallpaperService#updatePageColors");
if (DEBUG) {
Log.d(TAG, "updatePageColorsLocked for page " + pageIndx + " with areas "
@@ -1800,7 +1834,7 @@ public abstract class WallpaperService extends Service {
Log.e(TAG, "Error creating page local color bitmap", e);
continue;
}
- WallpaperColors color = WallpaperColors.fromBitmap(target, mWallpaperDimAmount);
+ WallpaperColors color = WallpaperColors.fromBitmap(target, wallpaperDimAmount);
target.recycle();
WallpaperColors currentColor = page.getColors(area);
@@ -1817,17 +1851,26 @@ public abstract class WallpaperService extends Service {
+ " local color callback for area" + area + " for page " + pageIndx
+ " of " + numPages);
}
- try {
- mConnection.onLocalWallpaperColorsChanged(area, color,
- mDisplayContext.getDisplayId());
- } catch (RemoteException e) {
- Log.e(TAG, "Error calling Connection.onLocalWallpaperColorsChanged", e);
- }
+ mHandler.post(() -> {
+ try {
+ mConnection.onLocalWallpaperColorsChanged(area, color,
+ mDisplayContext.getDisplayId());
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling Connection.onLocalWallpaperColorsChanged", e);
+ }
+ });
}
}
Trace.endSection();
}
+ private void assertBackgroundThread() {
+ if (!mBackgroundHandler.getLooper().isCurrentThread()) {
+ throw new IllegalStateException(
+ "ProcessLocalColors should be called from the background thread");
+ }
+ }
+
private RectF generateSubRect(RectF in, int pageInx, int numPages) {
float minLeft = (float) (pageInx) / (float) (numPages);
float maxRight = (float) (pageInx + 1) / (float) (numPages);
@@ -1852,7 +1895,6 @@ public abstract class WallpaperService extends Service {
if (supportsLocalColorExtraction()) return;
if (!mResetWindowPages) return;
mResetWindowPages = false;
- mLastWindowPage = -1;
for (int i = 0; i < mWindowPages.length; i++) {
mWindowPages[i].setLastUpdateTime(0L);
}
@@ -1878,12 +1920,10 @@ public abstract class WallpaperService extends Service {
if (DEBUG) {
Log.d(TAG, "addLocalColorsAreas adding local color areas " + regions);
}
- mHandler.post(() -> {
+ mBackgroundHandler.post(() -> {
mLocalColorsToAdd.addAll(regions);
- processLocalColors(mPendingXOffset, mPendingYOffset);
+ processLocalColors();
});
-
-
}
/**
@@ -1893,7 +1933,7 @@ public abstract class WallpaperService extends Service {
*/
public void removeLocalColorsAreas(@NonNull List<RectF> regions) {
if (supportsLocalColorExtraction()) return;
- mHandler.post(() -> {
+ mBackgroundHandler.post(() -> {
float step = mPendingXOffsetStep;
mLocalColorsToAdd.removeAll(regions);
mLocalColorAreas.removeAll(regions);
@@ -2231,7 +2271,6 @@ public abstract class WallpaperService extends Service {
final DisplayManager mDisplayManager;
final Display mDisplay;
final WallpaperManager mWallpaperManager;
- private final AtomicBoolean mDetached = new AtomicBoolean();
Engine mEngine;
@SetWallpaperFlags int mWhich;
@@ -2346,21 +2385,18 @@ public abstract class WallpaperService extends Service {
mEngine.removeLocalColorsAreas(regions);
}
- public void destroy() {
- Message msg = mCaller.obtainMessage(DO_DETACH);
- mCaller.sendMessage(msg);
- }
-
- public void detach() {
- mDetached.set(true);
- }
-
public void applyDimming(float dimAmount) throws RemoteException {
Message msg = mCaller.obtainMessageI(MSG_UPDATE_DIMMING,
Float.floatToIntBits(dimAmount));
mCaller.sendMessage(msg);
}
+ public void destroy() {
+ Message msg = mCaller.obtainMessage(DO_DETACH);
+ mCaller.getHandler().removeCallbacksAndMessages(null);
+ mCaller.sendMessage(msg);
+ }
+
public void resizePreview(Rect position) {
Message msg = mCaller.obtainMessageO(MSG_RESIZE_PREVIEW, position);
mCaller.sendMessage(msg);
@@ -2383,25 +2419,27 @@ public abstract class WallpaperService extends Service {
engine.detach();
Log.w(TAG, "Wallpaper host disappeared", e);
return;
+ } catch (IllegalStateException e) {
+ Log.w(TAG, "Connector instance already destroyed, "
+ + "can't attach engine to non existing connector", e);
+ return;
} finally {
Trace.endSection();
}
- mActiveEngines.add(engine);
Trace.beginSection("WPMS.engine.attach");
engine.attach(this);
Trace.endSection();
}
private void doDetachEngine() {
- mActiveEngines.remove(mEngine);
- mEngine.detach();
// Some wallpapers will not trigger the rendering threads of the remaining engines even
// if they are visible, so we need to toggle the state to get their attention.
- if (!mDetached.get()) {
- for (Engine eng : mActiveEngines) {
- if (eng.mVisible) {
- eng.doVisibilityChanged(false);
- eng.doVisibilityChanged(true);
+ if (!mEngine.mDestroyed) {
+ mEngine.detach();
+ for (IWallpaperEngineWrapper engineWrapper : mActiveEngines.values()) {
+ if (engineWrapper.mEngine != null && engineWrapper.mEngine.mVisible) {
+ engineWrapper.mEngine.doVisibilityChanged(false);
+ engineWrapper.mEngine.doVisibilityChanged(true);
}
}
}
@@ -2409,12 +2447,6 @@ public abstract class WallpaperService extends Service {
@Override
public void executeMessage(Message message) {
- if (mDetached.get()) {
- if (mActiveEngines.contains(mEngine)) {
- doDetachEngine();
- }
- return;
- }
switch (message.what) {
case DO_ATTACH: {
Trace.beginSection("WPMS.DO_ATTACH");
@@ -2525,7 +2557,6 @@ public abstract class WallpaperService extends Service {
*/
class IWallpaperServiceWrapper extends IWallpaperService.Stub {
private final WallpaperService mTarget;
- private IWallpaperEngineWrapper mEngineWrapper;
public IWallpaperServiceWrapper(WallpaperService context) {
mTarget = context;
@@ -2536,20 +2567,36 @@ public abstract class WallpaperService extends Service {
int windowType, boolean isPreview, int reqWidth, int reqHeight, Rect padding,
int displayId, @SetWallpaperFlags int which) {
Trace.beginSection("WPMS.ServiceWrapper.attach");
- mEngineWrapper = new IWallpaperEngineWrapper(mTarget, conn, windowToken,
- windowType, isPreview, reqWidth, reqHeight, padding, displayId, which);
+ IWallpaperEngineWrapper engineWrapper =
+ new IWallpaperEngineWrapper(mTarget, conn, windowToken, windowType,
+ isPreview, reqWidth, reqHeight, padding, displayId, which);
+ mActiveEngines.put(windowToken, engineWrapper);
+ if (DEBUG) {
+ Slog.v(TAG, "IWallpaperServiceWrapper Attaching window token " + windowToken);
+ }
Trace.endSection();
}
@Override
- public void detach() {
- mEngineWrapper.detach();
+ public void detach(IBinder windowToken) {
+ IWallpaperEngineWrapper engineWrapper = mActiveEngines.remove(windowToken);
+ if (engineWrapper == null) {
+ Log.w(TAG, "Engine for window token " + windowToken + " already detached");
+ return;
+ }
+ if (DEBUG) {
+ Slog.v(TAG, "IWallpaperServiceWrapper Detaching window token " + windowToken);
+ }
+ engineWrapper.destroy();
}
}
@Override
public void onCreate() {
Trace.beginSection("WPMS.onCreate");
+ mBackgroundThread = new HandlerThread("DefaultWallpaperLocalColorExtractor");
+ mBackgroundThread.start();
+ mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
super.onCreate();
Trace.endSection();
}
@@ -2558,10 +2605,11 @@ public abstract class WallpaperService extends Service {
public void onDestroy() {
Trace.beginSection("WPMS.onDestroy");
super.onDestroy();
- for (int i=0; i<mActiveEngines.size(); i++) {
- mActiveEngines.get(i).detach();
+ for (IWallpaperEngineWrapper engineWrapper : mActiveEngines.values()) {
+ engineWrapper.destroy();
}
mActiveEngines.clear();
+ mBackgroundThread.quitSafely();
Trace.endSection();
}
@@ -2586,8 +2634,12 @@ public abstract class WallpaperService extends Service {
@Override
protected void dump(FileDescriptor fd, PrintWriter out, String[] args) {
out.print("State of wallpaper "); out.print(this); out.println(":");
- for (int i=0; i<mActiveEngines.size(); i++) {
- Engine engine = mActiveEngines.get(i);
+ for (IWallpaperEngineWrapper engineWrapper : mActiveEngines.values()) {
+ Engine engine = engineWrapper.mEngine;
+ if (engine == null) {
+ Slog.w(TAG, "Engine for wrapper " + engineWrapper + " not attached");
+ continue;
+ }
out.print(" Engine "); out.print(engine); out.println(":");
engine.dump(" ", fd, out, args);
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index a99766f36ee4..4895aed60a3a 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -226,6 +226,9 @@ public final class SurfaceControl implements Parcelable {
@DataSpace.NamedDataSpace int dataSpace);
private static native void nativeSetExtendedRangeBrightness(long transactionObj,
long nativeObject, float currentBufferRatio, float desiredRatio);
+
+ private static native void nativeSetCachingHint(long transactionObj,
+ long nativeObject, int cachingHint);
private static native void nativeSetDamageRegion(long transactionObj, long nativeObject,
Region region);
private static native void nativeSetDimmingEnabled(long transactionObj, long nativeObject,
@@ -742,6 +745,29 @@ public final class SurfaceControl implements Parcelable {
*/
public static final int POWER_MODE_ON_SUSPEND = 4;
+ /**
+ * Hint that this SurfaceControl should not participate in layer caching within SurfaceFlinger.
+ *
+ * A system layer may request that a layer does not participate in caching when there are known
+ * quality limitations when caching via the compositor's GPU path.
+ * Use only with {@link SurfaceControl.Transaction#setCachingHint}.
+ * @hide
+ */
+ public static final int CACHING_DISABLED = 0;
+
+ /**
+ * Hint that this SurfaceControl should participate in layer caching within SurfaceFlinger.
+ *
+ * Use only with {@link SurfaceControl.Transaction#setCachingHint}.
+ * @hide
+ */
+ public static final int CACHING_ENABLED = 1;
+
+ /** @hide */
+ @IntDef(flag = true, value = {CACHING_DISABLED, CACHING_ENABLED})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface CachingHint {}
+
private void assignNativeObject(long nativeObject, String callsite) {
if (mNativeObject != 0) {
release();
@@ -3881,6 +3907,23 @@ public final class SurfaceControl implements Parcelable {
}
/**
+ * Sets the caching hint for the layer. By default, the caching hint is
+ * {@link CACHING_ENABLED}.
+ *
+ * @param sc The SurfaceControl to update
+ * @param cachingHint The caching hint to apply to the SurfaceControl. The CachingHint is
+ * not applied to any children of this SurfaceControl.
+ * @return this
+ * @hide
+ */
+ public @NonNull Transaction setCachingHint(
+ @NonNull SurfaceControl sc, @CachingHint int cachingHint) {
+ checkPreconditions(sc);
+ nativeSetCachingHint(mNativeObject, sc.mNativeObject, cachingHint);
+ return this;
+ }
+
+ /**
* Sets the trusted overlay state on this SurfaceControl and it is inherited to all the
* children. The caller must hold the ACCESS_SURFACE_FLINGER permission.
* @hide
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 472daf988924..e9b3e2808a6d 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1135,6 +1135,10 @@ public final class ViewRootImpl implements ViewParent,
updateLastConfigurationFromResources(getConfiguration());
// Make sure to report the completion of draw for relaunch with preserved window.
reportNextDraw("rebuilt");
+ // Make sure to resume this root view when relaunching its host activity which was stopped.
+ if (mStopped && getHostVisibility() != View.GONE) {
+ setWindowStopped(false);
+ }
}
private Configuration getConfiguration() {
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 725eb511737b..e7cefd60002b 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -108,6 +108,7 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.Log;
import android.util.proto.ProtoOutputStream;
@@ -1105,6 +1106,26 @@ public interface WindowManager extends ViewManager {
public static final String PARCEL_KEY_SHORTCUTS_ARRAY = "shortcuts_array";
/**
+ * Whether the device supports the WindowManager Extensions.
+ * OEMs can enable this by having their device config to inherit window_extensions.mk, such as:
+ * <pre>
+ * $(call inherit-product, $(SRC_TARGET_DIR)/product/window_extensions.mk)
+ * </pre>
+ * @hide
+ */
+ boolean WINDOW_EXTENSIONS_ENABLED =
+ SystemProperties.getBoolean("persist.wm.extensions.enabled", false);
+
+ /**
+ * @see #WINDOW_EXTENSIONS_ENABLED
+ * @hide
+ */
+ @TestApi
+ static boolean hasWindowExtensionsEnabled() {
+ return WINDOW_EXTENSIONS_ENABLED;
+ }
+
+ /**
* Application-level
* {@link android.content.pm.PackageManager.Property PackageManager.Property}
* tag that specifies whether OEMs are permitted to provide activity
diff --git a/core/java/android/view/contentcapture/ContentCaptureContext.java b/core/java/android/view/contentcapture/ContentCaptureContext.java
index 59b5286f6fc5..34c7b8b9889f 100644
--- a/core/java/android/view/contentcapture/ContentCaptureContext.java
+++ b/core/java/android/view/contentcapture/ContentCaptureContext.java
@@ -82,11 +82,19 @@ public final class ContentCaptureContext implements Parcelable {
@SystemApi
public static final int FLAG_RECONNECTED = 0x4;
+ /**
+ * Flag used to disable flush when receiving a VIEW_TREE_APPEARING event.
+ *
+ * @hide
+ */
+ public static final int FLAG_DISABLED_FLUSH_FOR_VIEW_TREE_APPEARING = 1 << 3;
+
/** @hide */
@IntDef(flag = true, prefix = { "FLAG_" }, value = {
FLAG_DISABLED_BY_APP,
FLAG_DISABLED_BY_FLAG_SECURE,
- FLAG_RECONNECTED
+ FLAG_RECONNECTED,
+ FLAG_DISABLED_FLUSH_FOR_VIEW_TREE_APPEARING
})
@Retention(RetentionPolicy.SOURCE)
@interface ContextCreationFlags{}
@@ -252,7 +260,8 @@ public final class ContentCaptureContext implements Parcelable {
* Gets the flags associated with this context.
*
* @return any combination of {@link #FLAG_DISABLED_BY_FLAG_SECURE},
- * {@link #FLAG_DISABLED_BY_APP} and {@link #FLAG_RECONNECTED}.
+ * {@link #FLAG_DISABLED_BY_APP}, {@link #FLAG_RECONNECTED} and {@link
+ * #FLAG_DISABLED_FLUSH_FOR_VIEW_TREE_APPEARING}.
*
* @hide
*/
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 497f0668107f..668351b949c1 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -51,6 +51,7 @@ import android.view.WindowManager;
import android.view.contentcapture.ContentCaptureSession.FlushReason;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.SyncResultReceiver;
import java.io.PrintWriter;
@@ -343,6 +344,14 @@ public final class ContentCaptureManager {
*/
public static final String DEVICE_CONFIG_PROPERTY_IDLE_UNBIND_TIMEOUT = "idle_unbind_timeout";
+ /**
+ * Sets to disable flush when receiving a VIEW_TREE_APPEARING event.
+ *
+ * @hide
+ */
+ public static final String DEVICE_CONFIG_PROPERTY_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING =
+ "disable_flush_for_view_tree_appearing";
+
/** @hide */
@TestApi
public static final int LOGGING_LEVEL_OFF = 0;
@@ -373,6 +382,8 @@ public final class ContentCaptureManager {
public static final int DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS = 1_000;
/** @hide */
public static final int DEFAULT_LOG_HISTORY_SIZE = 10;
+ /** @hide */
+ public static final boolean DEFAULT_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING = false;
private final Object mLock = new Object();
@@ -448,6 +459,7 @@ public final class ContentCaptureManager {
mOptions = Objects.requireNonNull(options, "options cannot be null");
ContentCaptureHelper.setLoggingLevel(mOptions.loggingLevel);
+ setFlushViewTreeAppearingEventDisabled(mOptions.disableFlushForViewTreeAppearing);
if (sVerbose) Log.v(TAG, "Constructor for " + context.getPackageName());
@@ -687,6 +699,38 @@ public final class ContentCaptureManager {
}
/**
+ * Explicitly sets enable or disable flush for view tree appearing event.
+ *
+ * @hide
+ */
+ @VisibleForTesting
+ public void setFlushViewTreeAppearingEventDisabled(boolean disabled) {
+ if (sDebug) {
+ Log.d(TAG, "setFlushViewTreeAppearingEventDisabled(): setting to " + disabled);
+ }
+
+ synchronized (mLock) {
+ if (disabled) {
+ mFlags |= ContentCaptureContext.FLAG_DISABLED_FLUSH_FOR_VIEW_TREE_APPEARING;
+ } else {
+ mFlags &= ~ContentCaptureContext.FLAG_DISABLED_FLUSH_FOR_VIEW_TREE_APPEARING;
+ }
+ }
+ }
+
+ /**
+ * Gets whether content capture is needed to flush for view tree appearing event.
+ *
+ * @hide
+ */
+ public boolean getFlushViewTreeAppearingEventDisabled() {
+ synchronized (mLock) {
+ return (mFlags & ContentCaptureContext.FLAG_DISABLED_FLUSH_FOR_VIEW_TREE_APPEARING)
+ != 0;
+ }
+ }
+
+ /**
* Gets whether content capture is enabled for the given user.
*
* <p>This method is typically used by the content capture service settings page, so it can
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index ee86fc141490..b7f03e1d6d72 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -175,6 +175,12 @@ public abstract class ContentCaptureSession implements AutoCloseable {
public static final int FLUSH_REASON_TEXT_CHANGE_TIMEOUT = 6;
/** @hide */
public static final int FLUSH_REASON_SESSION_CONNECTED = 7;
+ /** @hide */
+ public static final int FLUSH_REASON_FORCE_FLUSH = 8;
+ /** @hide */
+ public static final int FLUSH_REASON_VIEW_TREE_APPEARING = 9;
+ /** @hide */
+ public static final int FLUSH_REASON_VIEW_TREE_APPEARED = 10;
@ChangeId
@EnabledSince(targetSdkVersion = UPSIDE_DOWN_CAKE)
@@ -188,7 +194,10 @@ public abstract class ContentCaptureSession implements AutoCloseable {
FLUSH_REASON_SESSION_FINISHED,
FLUSH_REASON_IDLE_TIMEOUT,
FLUSH_REASON_TEXT_CHANGE_TIMEOUT,
- FLUSH_REASON_SESSION_CONNECTED
+ FLUSH_REASON_SESSION_CONNECTED,
+ FLUSH_REASON_FORCE_FLUSH,
+ FLUSH_REASON_VIEW_TREE_APPEARING,
+ FLUSH_REASON_VIEW_TREE_APPEARED
})
@Retention(RetentionPolicy.SOURCE)
public @interface FlushReason{}
@@ -666,6 +675,12 @@ public abstract class ContentCaptureSession implements AutoCloseable {
return "TEXT_CHANGE";
case FLUSH_REASON_SESSION_CONNECTED:
return "CONNECTED";
+ case FLUSH_REASON_FORCE_FLUSH:
+ return "FORCE_FLUSH";
+ case FLUSH_REASON_VIEW_TREE_APPEARING:
+ return "VIEW_TREE_APPEARING";
+ case FLUSH_REASON_VIEW_TREE_APPEARED:
+ return "VIEW_TREE_APPEARED";
default:
return "UNKOWN-" + reason;
}
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index a98955862d7b..6ddfcb825acc 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -458,8 +458,14 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
case ContentCaptureEvent.TYPE_SESSION_FINISHED:
flushReason = FLUSH_REASON_SESSION_FINISHED;
break;
+ case ContentCaptureEvent.TYPE_VIEW_TREE_APPEARING:
+ flushReason = FLUSH_REASON_VIEW_TREE_APPEARING;
+ break;
+ case ContentCaptureEvent.TYPE_VIEW_TREE_APPEARED:
+ flushReason = FLUSH_REASON_VIEW_TREE_APPEARED;
+ break;
default:
- flushReason = FLUSH_REASON_FULL;
+ flushReason = forceFlush ? FLUSH_REASON_FORCE_FLUSH : FLUSH_REASON_FULL;
}
flush(flushReason);
@@ -555,8 +561,13 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
final int numberEvents = mEvents.size();
final String reasonString = getFlushReasonAsString(reason);
+
if (sDebug) {
- Log.d(TAG, "Flushing " + numberEvents + " event(s) for " + getDebugState(reason));
+ ContentCaptureEvent event = mEvents.get(numberEvents - 1);
+ String forceString = (reason == FLUSH_REASON_FORCE_FLUSH) ? ". The force flush event "
+ + ContentCaptureEvent.getTypeAsString(event.getType()) : "";
+ Log.d(TAG, "Flushing " + numberEvents + " event(s) for " + getDebugState(reason)
+ + forceString);
}
if (mFlushHistory != null) {
// Logs reason, size, max size, idle timeout
@@ -769,7 +780,11 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
/** Public because is also used by ViewRootImpl */
public void notifyViewTreeEvent(int sessionId, boolean started) {
final int type = started ? TYPE_VIEW_TREE_APPEARING : TYPE_VIEW_TREE_APPEARED;
- mHandler.post(() -> sendEvent(new ContentCaptureEvent(sessionId, type), FORCE_FLUSH));
+ final boolean disableFlush = mManager.getFlushViewTreeAppearingEventDisabled();
+
+ mHandler.post(() -> sendEvent(
+ new ContentCaptureEvent(sessionId, type),
+ disableFlush ? !started : FORCE_FLUSH));
}
void notifySessionResumed(int sessionId) {
diff --git a/core/java/android/view/textclassifier/TextLinks.java b/core/java/android/view/textclassifier/TextLinks.java
index 445e9ecff54f..b5b6f5ae8af8 100644
--- a/core/java/android/view/textclassifier/TextLinks.java
+++ b/core/java/android/view/textclassifier/TextLinks.java
@@ -478,7 +478,7 @@ public final class TextLinks implements Parcelable {
/**
* Sets the entity configuration to use. This determines what types of entities the
* TextClassifier will look for.
- * Set to {@code null} for the default entity config and teh TextClassifier will
+ * Set to {@code null} for the default entity config and the TextClassifier will
* automatically determine what links to generate.
*
* @return this builder
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index a33906267736..18874f768929 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -6717,6 +6717,10 @@ public class RemoteViews implements Parcelable, Filter {
Log.w(LOG_TAG, "getLaunchOptions: view.getDisplay() is null!",
new Exception());
}
+ // If the user interacts with a visible element it is safe to assume they consent that
+ // something is going to start.
+ opts.setPendingIntentBackgroundActivityStartMode(
+ ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOWED);
return Pair.create(intent, opts);
}
}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5de807936c8a..fd8f5495464c 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -1117,7 +1117,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* @param actionId Identifier of the action. This will be either the
* identifier you supplied, or {@link EditorInfo#IME_NULL
* EditorInfo.IME_NULL} if being called due to the enter key
- * being pressed.
+ * being pressed. Starting from Android 14, the action identifier will
+ * also be included when triggered by an enter key if the input is
+ * constrained to a single line.
* @param event If triggered by an enter key, this is the event;
* otherwise, this is null.
* @return Return true if you have consumed the action, else false.
@@ -9272,7 +9274,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// chance to consume the event.
if (mEditor.mInputContentType.onEditorActionListener != null
&& mEditor.mInputContentType.onEditorActionListener.onEditorAction(
- this, EditorInfo.IME_NULL, event)) {
+ this,
+ getActionIdForEnterEvent(),
+ event)) {
mEditor.mInputContentType.enterDown = true;
// We are consuming the enter key for them.
return KEY_EVENT_HANDLED;
@@ -9495,7 +9499,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
&& mEditor.mInputContentType.enterDown) {
mEditor.mInputContentType.enterDown = false;
if (mEditor.mInputContentType.onEditorActionListener.onEditorAction(
- this, EditorInfo.IME_NULL, event)) {
+ this, getActionIdForEnterEvent(), event)) {
return true;
}
}
@@ -9559,6 +9563,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
return super.onKeyUp(keyCode, event);
}
+ private int getActionIdForEnterEvent() {
+ // If it's not single line, no action
+ if (!isSingleLine()) {
+ return EditorInfo.IME_NULL;
+ }
+ // Return the action that was specified for Enter
+ return getImeOptions() & EditorInfo.IME_MASK_ACTION;
+ }
+
@Override
public boolean onCheckIsTextEditor() {
return mEditor != null && mEditor.mInputType != EditorInfo.TYPE_NULL;
diff --git a/core/java/android/window/IWindowOrganizerController.aidl b/core/java/android/window/IWindowOrganizerController.aidl
index 57e0ce8ce8ed..534c9de8102c 100644
--- a/core/java/android/window/IWindowOrganizerController.aidl
+++ b/core/java/android/window/IWindowOrganizerController.aidl
@@ -63,7 +63,7 @@ interface IWindowOrganizerController {
* @param transitionToken A token associated with the transition to start.
* @param t Operations that are part of the transition.
*/
- oneway void startTransition(IBinder transitionToken, in @nullable WindowContainerTransaction t);
+ void startTransition(IBinder transitionToken, in @nullable WindowContainerTransaction t);
/**
* Starts a legacy transition.
diff --git a/core/java/android/window/TaskFragmentCreationParams.java b/core/java/android/window/TaskFragmentCreationParams.java
index c19abf941b05..5dbf328b6c0a 100644
--- a/core/java/android/window/TaskFragmentCreationParams.java
+++ b/core/java/android/window/TaskFragmentCreationParams.java
@@ -53,25 +53,12 @@ public final class TaskFragmentCreationParams implements Parcelable {
private final IBinder mOwnerToken;
/**
- * The initial bounds of the TaskFragment. Fills parent if empty.
- * TODO(b/232476698): cleanup with update CTS.
- */
- @NonNull
- private final Rect mInitialBounds = new Rect();
-
- /**
* The initial relative bounds of the TaskFragment in parent coordinate.
* Fills parent if empty.
*/
@NonNull
private final Rect mInitialRelativeBounds = new Rect();
- /**
- * Whether the params are using {@link Builder#setInitialRelativeBounds(Rect)}.
- * TODO(b/232476698): remove after remove mInitialBounds
- */
- private final boolean mAreInitialRelativeBoundsSet;
-
/** The initial windowing mode of the TaskFragment. Inherits from parent if not set. */
@WindowingMode
private final int mWindowingMode;
@@ -109,8 +96,7 @@ public final class TaskFragmentCreationParams implements Parcelable {
private TaskFragmentCreationParams(
@NonNull TaskFragmentOrganizerToken organizer, @NonNull IBinder fragmentToken,
- @NonNull IBinder ownerToken, @NonNull Rect initialBounds,
- @NonNull Rect initialRelativeBounds, boolean areInitialRelativeBoundsSet,
+ @NonNull IBinder ownerToken, @NonNull Rect initialRelativeBounds,
@WindowingMode int windowingMode, @Nullable IBinder pairedPrimaryFragmentToken,
@Nullable IBinder pairedActivityToken) {
if (pairedPrimaryFragmentToken != null && pairedActivityToken != null) {
@@ -120,9 +106,7 @@ public final class TaskFragmentCreationParams implements Parcelable {
mOrganizer = organizer;
mFragmentToken = fragmentToken;
mOwnerToken = ownerToken;
- mInitialBounds.set(initialBounds);
mInitialRelativeBounds.set(initialRelativeBounds);
- mAreInitialRelativeBoundsSet = areInitialRelativeBoundsSet;
mWindowingMode = windowingMode;
mPairedPrimaryFragmentToken = pairedPrimaryFragmentToken;
mPairedActivityToken = pairedActivityToken;
@@ -144,27 +128,10 @@ public final class TaskFragmentCreationParams implements Parcelable {
}
@NonNull
- public Rect getInitialBounds() {
- return mInitialBounds;
- }
-
- /**
- * TODO(b/232476698): remove the hide with adding CTS for this in next release.
- * @hide
- */
- @NonNull
public Rect getInitialRelativeBounds() {
return mInitialRelativeBounds;
}
- /**
- * TODO(b/232476698): remove after remove mInitialBounds.
- * @hide
- */
- public boolean areInitialRelativeBoundsSet() {
- return mAreInitialRelativeBoundsSet;
- }
-
@WindowingMode
public int getWindowingMode() {
return mWindowingMode;
@@ -192,9 +159,7 @@ public final class TaskFragmentCreationParams implements Parcelable {
mOrganizer = TaskFragmentOrganizerToken.CREATOR.createFromParcel(in);
mFragmentToken = in.readStrongBinder();
mOwnerToken = in.readStrongBinder();
- mInitialBounds.readFromParcel(in);
mInitialRelativeBounds.readFromParcel(in);
- mAreInitialRelativeBoundsSet = in.readBoolean();
mWindowingMode = in.readInt();
mPairedPrimaryFragmentToken = in.readStrongBinder();
mPairedActivityToken = in.readStrongBinder();
@@ -206,9 +171,7 @@ public final class TaskFragmentCreationParams implements Parcelable {
mOrganizer.writeToParcel(dest, flags);
dest.writeStrongBinder(mFragmentToken);
dest.writeStrongBinder(mOwnerToken);
- mInitialBounds.writeToParcel(dest, flags);
mInitialRelativeBounds.writeToParcel(dest, flags);
- dest.writeBoolean(mAreInitialRelativeBoundsSet);
dest.writeInt(mWindowingMode);
dest.writeStrongBinder(mPairedPrimaryFragmentToken);
dest.writeStrongBinder(mPairedActivityToken);
@@ -234,7 +197,6 @@ public final class TaskFragmentCreationParams implements Parcelable {
+ " organizer=" + mOrganizer
+ " fragmentToken=" + mFragmentToken
+ " ownerToken=" + mOwnerToken
- + " initialBounds=" + mInitialBounds
+ " initialRelativeBounds=" + mInitialRelativeBounds
+ " windowingMode=" + mWindowingMode
+ " pairedFragmentToken=" + mPairedPrimaryFragmentToken
@@ -261,13 +223,8 @@ public final class TaskFragmentCreationParams implements Parcelable {
private final IBinder mOwnerToken;
@NonNull
- private final Rect mInitialBounds = new Rect();
-
- @NonNull
private final Rect mInitialRelativeBounds = new Rect();
- private boolean mAreInitialRelativeBoundsSet;
-
@WindowingMode
private int mWindowingMode = WINDOWING_MODE_UNDEFINED;
@@ -284,23 +241,13 @@ public final class TaskFragmentCreationParams implements Parcelable {
mOwnerToken = ownerToken;
}
- /** Sets the initial bounds for the TaskFragment. */
- @NonNull
- public Builder setInitialBounds(@NonNull Rect bounds) {
- mInitialBounds.set(bounds);
- return this;
- }
-
/**
* Sets the initial relative bounds for the TaskFragment in parent coordinate.
* Set to empty to fill parent.
- * TODO(b/232476698): remove the hide with adding CTS for this in next release.
- * @hide
*/
@NonNull
public Builder setInitialRelativeBounds(@NonNull Rect bounds) {
mInitialRelativeBounds.set(bounds);
- mAreInitialRelativeBoundsSet = true;
return this;
}
@@ -355,8 +302,8 @@ public final class TaskFragmentCreationParams implements Parcelable {
@NonNull
public TaskFragmentCreationParams build() {
return new TaskFragmentCreationParams(mOrganizer, mFragmentToken, mOwnerToken,
- mInitialBounds, mInitialRelativeBounds, mAreInitialRelativeBoundsSet,
- mWindowingMode, mPairedPrimaryFragmentToken, mPairedActivityToken);
+ mInitialRelativeBounds, mWindowingMode, mPairedPrimaryFragmentToken,
+ mPairedActivityToken);
}
}
}
diff --git a/core/java/com/android/internal/app/IHotwordRecognitionStatusCallback.aidl b/core/java/com/android/internal/app/IHotwordRecognitionStatusCallback.aidl
index d0214e6e0082..813febf33964 100644
--- a/core/java/com/android/internal/app/IHotwordRecognitionStatusCallback.aidl
+++ b/core/java/com/android/internal/app/IHotwordRecognitionStatusCallback.aidl
@@ -17,6 +17,7 @@
package com.android.internal.app;
import android.hardware.soundtrigger.SoundTrigger;
+import android.service.voice.DetectorFailure;
import android.service.voice.HotwordDetectedResult;
import android.service.voice.HotwordRejectedResult;
@@ -62,6 +63,13 @@ oneway interface IHotwordRecognitionStatusCallback {
void onError(int status);
/**
+ * Called when the detection fails due to an error.
+ *
+ * @param detectorFailure It provides the error code, error message and suggested action.
+ */
+ void onDetectionFailure(in DetectorFailure detectorFailure);
+
+ /**
* Called when the recognition is paused temporarily for some reason.
*/
void onRecognitionPaused();
diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
index 5eb97862c79f..6b40d9873fbb 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
@@ -51,7 +51,7 @@ interface IVoiceInteractionManagerService {
int startVoiceActivity(IBinder token, in Intent intent, String resolvedType,
String attributionTag);
int startAssistantActivity(IBinder token, in Intent intent, String resolvedType,
- String attributionTag);
+ String attributionTag, in Bundle bundle);
void setKeepAwake(IBinder token, boolean keepAwake);
void closeSystemDialogs(IBinder token);
void finish(IBinder token);
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index 47b83be35f87..ae192a4effc7 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -45,8 +45,13 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.util.Slog;
+import android.view.View;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
import android.widget.Toast;
+import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -151,17 +156,60 @@ public class IntentForwarderActivity extends Activity {
if (isResolverActivityResolveInfo(targetResolveInfo)) {
launchResolverActivityWithCorrectTab(intentReceived, className, newIntent,
callingUserId, targetUserId);
- return targetResolveInfo;
+ // When switching to the personal profile, automatically start the activity
+ } else if (className.equals(FORWARD_INTENT_TO_PARENT)) {
+ startActivityAsCaller(newIntent, targetUserId);
}
- startActivityAsCaller(newIntent, targetUserId);
return targetResolveInfo;
}, mExecutorService)
.thenAcceptAsync(result -> {
- maybeShowDisclosure(intentReceived, result, userMessage);
- finish();
+ // When switching to the personal profile, inform user after starting activity
+ if (className.equals(FORWARD_INTENT_TO_PARENT)) {
+ maybeShowDisclosure(intentReceived, result, userMessage);
+ finish();
+ // When switching to the work profile, ask the user for consent before launching
+ } else if (className.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) {
+ maybeShowUserConsentMiniResolver(result, newIntent, targetUserId);
+ }
}, getApplicationContext().getMainExecutor());
}
+ private void maybeShowUserConsentMiniResolver(
+ ResolveInfo target, Intent launchIntent, int targetUserId) {
+ if (target == null || isIntentForwarderResolveInfo(target) || !isDeviceProvisioned()) {
+ finish();
+ return;
+ }
+
+ int layoutId = R.layout.miniresolver;
+ setContentView(layoutId);
+
+ findViewById(R.id.title_container).setElevation(0);
+
+ ImageView icon = findViewById(R.id.icon);
+ PackageManager packageManagerForTargetUser =
+ createContextAsUser(UserHandle.of(targetUserId), /* flags= */ 0)
+ .getPackageManager();
+ icon.setImageDrawable(target.loadIcon(packageManagerForTargetUser));
+
+ View buttonContainer = findViewById(R.id.button_bar_container);
+ buttonContainer.setPadding(0, 0, 0, buttonContainer.getPaddingBottom());
+
+ ((TextView) findViewById(R.id.open_cross_profile)).setText(
+ getResources().getString(
+ R.string.miniresolver_open_in_work,
+ target.loadLabel(packageManagerForTargetUser)));
+
+ // The mini-resolver's negative button is reused in this flow to cancel the intent
+ ((Button) findViewById(R.id.use_same_profile_browser)).setText(R.string.cancel);
+ findViewById(R.id.use_same_profile_browser).setOnClickListener(v -> finish());
+
+ findViewById(R.id.button_open).setOnClickListener(v -> {
+ startActivityAsCaller(launchIntent, targetUserId);
+ finish();
+ });
+ }
+
private String getForwardToPersonalMessage() {
return getSystemService(DevicePolicyManager.class).getResources().getString(
FORWARD_INTENT_TO_PERSONAL,
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index d6a515ae2da2..73c5207e6238 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -739,6 +739,11 @@ public class ResolverActivity extends Activity implements
}
protected UserHandle fetchPersonalProfileUserHandle() {
+ // ActivityManager.getCurrentUser() refers to the current Foreground user. When clone/work
+ // profile is active, we always make the personal tab from the foreground user.
+ // Outside profiles, current foreground user is potentially the same as the sharesheet
+ // process's user (UserHandle.myUserId()), so we continue to create personal tab with the
+ // current foreground user.
mPersonalProfileUserHandle = UserHandle.of(ActivityManager.getCurrentUser());
return mPersonalProfileUserHandle;
}
@@ -768,10 +773,11 @@ public class ResolverActivity extends Activity implements
}
private UserHandle fetchTabOwnerUserHandleForLaunch() {
- if (isLaunchedAsCloneProfile()) {
- return getPersonalProfileUserHandle();
- }
- return mLaunchedFromUserHandle;
+ // If we are in work profile's process, return WorkProfile user as owner, otherwise we
+ // always return PersonalProfile user as owner
+ return UserHandle.of(UserHandle.myUserId()).equals(getWorkProfileUserHandle())
+ ? getWorkProfileUserHandle()
+ : getPersonalProfileUserHandle();
}
private boolean hasWorkProfile() {
diff --git a/core/java/com/android/internal/policy/GestureNavigationSettingsObserver.java b/core/java/com/android/internal/policy/GestureNavigationSettingsObserver.java
index d2b612a9e6f3..f1ed3bed5d89 100644
--- a/core/java/com/android/internal/policy/GestureNavigationSettingsObserver.java
+++ b/core/java/com/android/internal/policy/GestureNavigationSettingsObserver.java
@@ -56,6 +56,9 @@ public class GestureNavigationSettingsObserver extends ContentObserver {
}
};
+ /**
+ * Registers the observer for all users.
+ */
public void register() {
ContentResolver r = mContext.getContentResolver();
r.registerContentObserver(
@@ -73,7 +76,10 @@ public class GestureNavigationSettingsObserver extends ContentObserver {
mOnPropertiesChangedListener);
}
- public void registerForCurrentUser() {
+ /**
+ * Registers the observer for the calling user.
+ */
+ public void registerForCallingUser() {
ContentResolver r = mContext.getContentResolver();
r.registerContentObserver(
Settings.Secure.getUriFor(Settings.Secure.BACK_GESTURE_INSET_SCALE_LEFT),
@@ -103,12 +109,46 @@ public class GestureNavigationSettingsObserver extends ContentObserver {
}
}
+ /**
+ * Returns the left sensitivity for the current user. To be used in code that runs primarily
+ * in one user's process.
+ */
public int getLeftSensitivity(Resources userRes) {
- return getSensitivity(userRes, Settings.Secure.BACK_GESTURE_INSET_SCALE_LEFT);
+ final float scale = Settings.Secure.getFloatForUser(mContext.getContentResolver(),
+ Settings.Secure.BACK_GESTURE_INSET_SCALE_LEFT, 1.0f, UserHandle.USER_CURRENT);
+ return (int) (getUnscaledInset(userRes) * scale);
}
+ /**
+ * Returns the left sensitivity for the calling user. To be used in code that runs in a
+ * per-user process.
+ */
+ @SuppressWarnings("NonUserGetterCalled")
+ public int getLeftSensitivityForCallingUser(Resources userRes) {
+ final float scale = Settings.Secure.getFloat(mContext.getContentResolver(),
+ Settings.Secure.BACK_GESTURE_INSET_SCALE_LEFT, 1.0f);
+ return (int) (getUnscaledInset(userRes) * scale);
+ }
+
+ /**
+ * Returns the right sensitivity for the current user. To be used in code that runs primarily
+ * in one user's process.
+ */
public int getRightSensitivity(Resources userRes) {
- return getSensitivity(userRes, Settings.Secure.BACK_GESTURE_INSET_SCALE_RIGHT);
+ final float scale = Settings.Secure.getFloatForUser(mContext.getContentResolver(),
+ Settings.Secure.BACK_GESTURE_INSET_SCALE_RIGHT, 1.0f, UserHandle.USER_CURRENT);
+ return (int) (getUnscaledInset(userRes) * scale);
+ }
+
+ /**
+ * Returns the right sensitivity for the calling user. To be used in code that runs in a
+ * per-user process.
+ */
+ @SuppressWarnings("NonUserGetterCalled")
+ public int getRightSensitivityForCallingUser(Resources userRes) {
+ final float scale = Settings.Secure.getFloat(mContext.getContentResolver(),
+ Settings.Secure.BACK_GESTURE_INSET_SCALE_RIGHT, 1.0f);
+ return (int) (getUnscaledInset(userRes) * scale);
}
public boolean areNavigationButtonForcedVisible() {
@@ -116,7 +156,7 @@ public class GestureNavigationSettingsObserver extends ContentObserver {
Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) == 0;
}
- private int getSensitivity(Resources userRes, String side) {
+ private float getUnscaledInset(Resources userRes) {
final DisplayMetrics dm = userRes.getDisplayMetrics();
final float defaultInset = userRes.getDimension(
com.android.internal.R.dimen.config_backGestureInset) / dm.density;
@@ -127,8 +167,6 @@ public class GestureNavigationSettingsObserver extends ContentObserver {
: defaultInset;
final float inset = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, backGestureInset,
dm);
- final float scale = Settings.Secure.getFloatForUser(
- mContext.getContentResolver(), side, 1.0f, UserHandle.USER_CURRENT);
- return (int) (inset * scale);
+ return inset;
}
}
diff --git a/core/jni/android_media_MicrophoneInfo.cpp b/core/jni/android_media_MicrophoneInfo.cpp
index 65e30d8b1ea3..18f81254af7d 100644
--- a/core/jni/android_media_MicrophoneInfo.cpp
+++ b/core/jni/android_media_MicrophoneInfo.cpp
@@ -92,6 +92,7 @@ jint convertMicrophoneInfoFromNative(JNIEnv *env, jobject *jMicrophoneInfo,
env->DeleteLocalRef(jFrequencyResponse);
}
// Create a list of Pair for channel mapping.
+ jChannelMappings = env->NewObject(gArrayListClass, gArrayListCstor);
const auto &channelMapping = micInfo.channel_mapping;
for (size_t i = 0; i < std::size(channelMapping); i++) {
int channelMappingType = channelMapping[i];
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index d2d87d6916d2..03d6eece61e6 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -639,6 +639,13 @@ static void nativeSetExtendedRangeBrightness(JNIEnv* env, jclass clazz, jlong tr
transaction->setExtendedRangeBrightness(ctrl, currentBufferRatio, desiredRatio);
}
+static void nativeSetCachingHint(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject, jint cachingHint) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
+ transaction->setCachingHint(ctrl, static_cast<gui::CachingHint>(cachingHint));
+}
+
static void nativeSetBlurRegions(JNIEnv* env, jclass clazz, jlong transactionObj,
jlong nativeObject, jobjectArray regions, jint regionsLength) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
@@ -2204,6 +2211,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeSetDataSpace },
{"nativeSetExtendedRangeBrightness", "(JJFF)V",
(void*)nativeSetExtendedRangeBrightness },
+ {"nativeSetCachingHint", "(JJI)V",
+ (void*)nativeSetCachingHint },
{"nativeAddWindowInfosReportedListener", "(JLjava/lang/Runnable;)V",
(void*)nativeAddWindowInfosReportedListener },
{"nativeGetDisplayBrightnessSupport", "(Landroid/os/IBinder;)Z",
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index e9771a9dcb7f..16db81825dd2 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -7564,7 +7564,7 @@
HealthConnect can later integrate it. -->
<permission android:name="android.permission.STAGE_HEALTH_CONNECT_REMOTE_DATA"
android:protectionLevel="signature|knownSigner"
- android:knownCerts="@array/config_healthConnectStagingDataKnownSigners"/>
+ android:knownCerts="@array/config_healthConnectRestoreKnownSigners"/>
<!-- @hide @TestApi Allows an application to clear HealthConnect's staged remote data for
testing only. For security reasons, this is a platform-only permission. -->
@@ -7604,6 +7604,13 @@
<permission android:name="android.permission.LOG_PROCESS_ACTIVITIES"
android:protectionLevel="signature|privileged" />
+ <!-- @hide Allows an application to get type of any provider uri.
+ <p>Not for use by third-party applications.
+ <p>Protection level: signature
+ -->
+ <permission android:name="android.permission.GET_ANY_PROVIDER_TYPE"
+ android:protectionLevel="signature" />
+
<!-- Attribution for Geofencing service. -->
<attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/>
<!-- Attribution for Country Detector. -->
@@ -7688,8 +7695,11 @@
</activity>
<activity android:name="com.android.internal.app.IntentForwarderActivity"
android:finishOnCloseSystemDialogs="true"
- android:theme="@style/Theme.Translucent.NoTitleBar"
+ android:theme="@style/Theme.DeviceDefault.Resolver"
android:excludeFromRecents="true"
+ android:documentLaunchMode="never"
+ android:relinquishTaskIdentity="true"
+ android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboard|keyboardHidden"
android:label="@string/user_owner_label"
android:exported="true"
android:visibleToInstantApps="true"
diff --git a/core/res/res/layout/miniresolver.xml b/core/res/res/layout/miniresolver.xml
index 38a71f0e17f6..d07ad8986dec 100644
--- a/core/res/res/layout/miniresolver.xml
+++ b/core/res/res/layout/miniresolver.xml
@@ -14,6 +14,11 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
+
+<!-- Layout used to decide whether to launch a single target in another profile.
+ When this layout is used in ResolverActivity, the user can choose between a verified app in the
+ other profile and the default browser in the current profile.
+ In IntentForwarderActivity, they choose whether to launch in the other profile or cancel. -->
<com.android.internal.widget.ResolverDrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
@@ -24,6 +29,7 @@
android:id="@id/contentPanel">
<RelativeLayout
+ android:id="@+id/title_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alwaysShow="true"
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index d1bef475be1d..9252b149797b 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1210,6 +1210,122 @@
a value of 'true' will not override any 'false' value in its parent chain nor will
it prevent any 'false' in any of its children. -->
<attr name="forceDarkAllowed" format="boolean" />
+
+ <!-- A lower-emphasized variant of the color on the fixed secondary branding color. @hide
+ -->
+ <attr name="materialColorOnSecondaryFixedVariant" format="color"/>
+ <!-- A lower-emphasized variant of the color on the fixed tertiary branding color. @hide
+ -->
+ <attr name="materialColorOnTertiaryFixedVariant" format="color"/>
+ <!-- The container color of surface the most lowered. @hide -->
+ <attr name="materialColorSurfaceContainerLowest" format="color"/>
+ <!-- A lower-emphasized variant of the color on the fixed primary branding color. @hide -->
+ <attr name="materialColorOnPrimaryFixedVariant" format="color"/>
+ <!-- A color that passes accessibility guidelines for text/iconography when drawn on top of
+ the secondary container color. @hide -->
+ <attr name="materialColorOnSecondaryContainer" format="color"/>
+ <!-- A color that passes accessibility guidelines for text/iconography when drawn on top of
+ the tertiary container color. @hide -->
+ <attr name="materialColorOnTertiaryContainer" format="color"/>
+ <!-- The container color of surface slightly lowered, which replaces the previous surface
+ at elevation level 1. @hide -->
+ <attr name="materialColorSurfaceContainerLow" format="color"/>
+ <!-- A color that passes accessibility guidelines for text/iconography when drawn on top of
+ the primary container color. @hide -->
+ <attr name="materialColorOnPrimaryContainer" format="color"/>
+ <!-- A stronger, more emphasized variant of the fixed secondary branding color. @hide -->
+ <attr name="materialColorSecondaryFixedDim" format="color"/>
+ <!-- A tonal variation of the on error color that passes accessibility guidelines for
+ text/iconography when drawn on top of error container. @hide -->
+ <attr name="materialColorOnErrorContainer" format="color"/>
+ <!-- The color text/iconography when drawn on top of the fixed secondary branding color.
+ @hide -->
+ <attr name="materialColorOnSecondaryFixed" format="color"/>
+ <!-- The "on surface" inverse color, useful for inverted backgrounds. @hide -->
+ <attr name="materialColorOnSurfaceInverse" format="color"/>
+ <!-- A stronger, more emphasized variant of the fixed tertiary branding color. @hide -->
+ <attr name="materialColorTertiaryFixedDim" format="color"/>
+ <!-- The color text/iconography when drawn on top of the fixed tertiary branding color.
+ @hide -->
+ <attr name="materialColorOnTertiaryFixed" format="color"/>
+ <!-- A stronger, more emphasized variant of the fixed primary branding color. @hide -->
+ <attr name="materialColorPrimaryFixedDim" format="color"/>
+ <!-- A tonal variation of the secondary color suitable for background color of container
+ views. @hide -->
+ <attr name="materialColorSecondaryContainer" format="color"/>
+ <!-- A tonal variation of the error color suitable for background color of container views.
+ @hide -->
+ <attr name="materialColorErrorContainer" format="color"/>
+ <!-- The color text/iconography when drawn on top of the fixed primary branding color.
+ @hide -->
+ <attr name="materialColorOnPrimaryFixed" format="color"/>
+ <!-- The inverse color of colorPrimary. @hide -->
+ <attr name="materialColorPrimaryInverse" format="color"/>
+ <!-- A secondary branding color for the app, which stays the same between light and dark
+ themes. @hide -->
+ <attr name="materialColorSecondaryFixed" format="color"/>
+ <!-- The surface inverse color, useful for inverted backgrounds. @hide -->
+ <attr name="materialColorSurfaceInverse" format="color"/>
+ <!-- A tonal variation of the surface color. @hide -->
+ <attr name="materialColorSurfaceVariant" format="color"/>
+ <!-- A tonal variation of the tertiary color suitable for background color of container
+ views. @hide -->
+ <attr name="materialColorTertiaryContainer" format="color"/>
+ <!-- A tertiary branding color for the app, which stays the same between light and dark
+ themes. @hide -->
+ <attr name="materialColorTertiaryFixed" format="color"/>
+ <!-- A tonal variation of the primary color suitable for background color of container
+ views. @hide -->
+ <attr name="materialColorPrimaryContainer" format="color"/>
+ <!-- A color that passes accessibility guidelines for text/iconography when drawn on top of
+ background. @hide -->
+ <attr name="materialColorOnBackground" format="color"/>
+ <!-- A primary branding color for the app, which stays the same between light and dark
+ themes. @hide -->
+ <attr name="materialColorPrimaryFixed" format="color"/>
+ <!-- A color that passes accessibility guidelines for text/iconography when drawn on top of
+ secondary. @hide -->
+ <attr name="materialColorOnSecondary" format="color"/>
+ <!-- A color that passes accessibility guidelines for text/iconography when drawn on top of
+ tertiary. @hide -->
+ <attr name="materialColorOnTertiary" format="color"/>
+ <!-- The surface color which always stay the dimmest in either dark or light theme. @hide
+ -->
+ <attr name="materialColorSurfaceDim" format="color"/>
+ <!-- The surface color which always stay the brightest in either dark or light theme. @hide
+ -->
+ <attr name="materialColorSurfaceBright" format="color"/>
+ <!-- The secondary branding color for the app, usually a bright complement to the primary
+ branding color. @hide -->
+ <attr name="materialColorSecondary" format="color"/>
+ <!-- A color that passes accessibility guidelines for text/iconography when drawn on top of
+ error. @hide -->
+ <attr name="materialColorOnError" format="color"/>
+ <!-- The color of surfaces such as cards, sheets, menus. @hide -->
+ <attr name="materialColorSurface" format="color"/>
+ <!-- The container color of surface slightly elevated, which replaces the previous surface
+ at elevation level 3. @hide -->
+ <attr name="materialColorSurfaceContainerHigh" format="color"/>
+ <!-- The tertiary branding color for the app, usually a bright complement to the primary
+ branding color. @hide -->
+ <attr name="materialColorTertiary" format="color"/>
+ <!-- The container color of surface the most elevated, which replaces the previous surface
+ variant. @hide -->
+ <attr name="materialColorSurfaceContainerHighest" format="color"/>
+ <!-- undefined @hide -->
+ <attr name="materialColorOnSurfaceVariant" format="color"/>
+ <!-- undefined @hide -->
+ <attr name="materialColorOutline" format="color"/>
+ <!-- undefined @hide -->
+ <attr name="materialColorOnPrimary" format="color"/>
+ <!-- undefined @hide -->
+ <attr name="materialColorOnSurface" format="color"/>
+ <!-- undefined @hide -->
+ <attr name="materialColorSurfaceContainer" format="color"/>
+ <!-- The container color of surface, which replaces the previous surface at elevation level
+ 2. @hide -->
+ <attr name="materialColorSurfaceContainer" format="color"/>
+
</declare-styleable>
<!-- **************************************************************** -->
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 31b9f9a848d9..12eff6723d88 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -6286,7 +6286,7 @@
<!-- Certificate digests for trusted apps that will be allowed to obtain the knownSigner
permission for staging HealthConnect's remote data. The digest should be computed over the
DER encoding of the trusted certificate using the SHA-256 digest algorithm. -->
- <string-array name="config_healthConnectStagingDataKnownSigners">
+ <string-array name="config_healthConnectRestoreKnownSigners">
</string-array>
<!-- Certificate digests for trusted apps that will be allowed to obtain the knownSigner Health
Connect Migration permissions. The digest should be computed over the DER encoding of the
@@ -6322,4 +6322,9 @@
<!-- Whether to show weather on the lock screen by default. -->
<bool name="config_lockscreenWeatherEnabledByDefault">false</bool>
+
+ <!-- Whether to reset Battery Stats on unplug when the battery level is high. -->
+ <bool name="config_batteryStatsResetOnUnplugHighBatteryLevel">true</bool>
+ <!-- Whether to reset Battery Stats on unplug if the battery was significantly charged -->
+ <bool name="config_batteryStatsResetOnUnplugAfterSignificantCharge">true</bool>
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 312ad1f9a170..7e89fc8b5e46 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4960,4 +4960,53 @@
<!-- Whether to show weather on the lockscreen by default. -->
<java-symbol type="bool" name="config_lockscreenWeatherEnabledByDefault" />
+
+ <java-symbol type="bool" name="config_batteryStatsResetOnUnplugHighBatteryLevel" />
+ <java-symbol type="bool" name="config_batteryStatsResetOnUnplugAfterSignificantCharge" />
+
+
+ <java-symbol name="materialColorOnSecondaryFixedVariant" type="attr"/>
+ <java-symbol name="materialColorOnTertiaryFixedVariant" type="attr"/>
+ <java-symbol name="materialColorSurfaceContainerLowest" type="attr"/>
+ <java-symbol name="materialColorOnPrimaryFixedVariant" type="attr"/>
+ <java-symbol name="materialColorOnSecondaryContainer" type="attr"/>
+ <java-symbol name="materialColorOnTertiaryContainer" type="attr"/>
+ <java-symbol name="materialColorSurfaceContainerLow" type="attr"/>
+ <java-symbol name="materialColorOnPrimaryContainer" type="attr"/>
+ <java-symbol name="materialColorSecondaryFixedDim" type="attr"/>
+ <java-symbol name="materialColorOnErrorContainer" type="attr"/>
+ <java-symbol name="materialColorOnSecondaryFixed" type="attr"/>
+ <java-symbol name="materialColorOnSurfaceInverse" type="attr"/>
+ <java-symbol name="materialColorTertiaryFixedDim" type="attr"/>
+ <java-symbol name="materialColorOnTertiaryFixed" type="attr"/>
+ <java-symbol name="materialColorPrimaryFixedDim" type="attr"/>
+ <java-symbol name="materialColorSecondaryContainer" type="attr"/>
+ <java-symbol name="materialColorErrorContainer" type="attr"/>
+ <java-symbol name="materialColorOnPrimaryFixed" type="attr"/>
+ <java-symbol name="materialColorPrimaryInverse" type="attr"/>
+ <java-symbol name="materialColorSecondaryFixed" type="attr"/>
+ <java-symbol name="materialColorSurfaceInverse" type="attr"/>
+ <java-symbol name="materialColorSurfaceVariant" type="attr"/>
+ <java-symbol name="materialColorTertiaryContainer" type="attr"/>
+ <java-symbol name="materialColorTertiaryFixed" type="attr"/>
+ <java-symbol name="materialColorPrimaryContainer" type="attr"/>
+ <java-symbol name="materialColorOnBackground" type="attr"/>
+ <java-symbol name="materialColorPrimaryFixed" type="attr"/>
+ <java-symbol name="materialColorOnSecondary" type="attr"/>
+ <java-symbol name="materialColorOnTertiary" type="attr"/>
+ <java-symbol name="materialColorSurfaceDim" type="attr"/>
+ <java-symbol name="materialColorSurfaceBright" type="attr"/>
+ <java-symbol name="materialColorSecondary" type="attr"/>
+ <java-symbol name="materialColorOnError" type="attr"/>
+ <java-symbol name="materialColorSurface" type="attr"/>
+ <java-symbol name="materialColorSurfaceContainerHigh" type="attr"/>
+ <java-symbol name="materialColorTertiary" type="attr"/>
+ <java-symbol name="materialColorSurfaceContainerHighest" type="attr"/>
+ <java-symbol name="materialColorOnSurfaceVariant" type="attr"/>
+ <java-symbol name="materialColorOutline" type="attr"/>
+ <java-symbol name="materialColorOnPrimary" type="attr"/>
+ <java-symbol name="materialColorOnSurface" type="attr"/>
+ <java-symbol name="materialColorSurfaceContainer" type="attr"/>
+ <java-symbol name="materialColorSurfaceContainer" type="attr"/>
+
</resources>
diff --git a/core/res/res/values/themes_device_defaults.xml b/core/res/res/values/themes_device_defaults.xml
index c603c83e033d..511e734a0994 100644
--- a/core/res/res/values/themes_device_defaults.xml
+++ b/core/res/res/values/themes_device_defaults.xml
@@ -238,6 +238,51 @@ easier.
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_dark</item>
<item name="colorForegroundInverse">@color/foreground_device_default_light</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<style name="Theme.DeviceDefault" parent="Theme.DeviceDefaultBase" />
@@ -288,6 +333,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<!-- Variant of {@link #Theme_DeviceDefault} with no action bar and no status bar. This theme
@@ -337,6 +427,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<!-- Variant of {@link #Theme_DeviceDefault} with no action bar and no status bar and
@@ -388,6 +523,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<!-- Variant of {@link #Theme_DeviceDefault} that has no title bar and translucent
@@ -438,6 +618,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<!-- DeviceDefault theme for dialog windows and activities. This changes the window to be
@@ -496,6 +721,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Dialog} that has a nice minimum width for a
@@ -545,6 +815,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Dialog} without an action bar -->
@@ -593,6 +908,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Dialog_NoActionBar} that has a nice minimum width
@@ -642,6 +1002,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<!-- Variant of Theme.DeviceDefault.Dialog that has a fixed size. -->
@@ -707,6 +1112,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<!-- DeviceDefault theme for a window without an action bar that will be displayed either
@@ -757,6 +1207,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<!-- DeviceDefault theme for a presentation window on a secondary display. -->
@@ -805,6 +1300,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<!-- DeviceDefault theme for panel windows. This removes all extraneous window
@@ -855,6 +1395,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<!-- DeviceDefault theme for windows that want to have the user's selected wallpaper appear
@@ -904,6 +1489,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<!-- DeviceDefault theme for windows that want to have the user's selected wallpaper appear
@@ -953,6 +1583,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<!-- DeviceDefault style for input methods, which is used by the
@@ -1002,6 +1677,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<!-- DeviceDefault style for input methods, which is used by the
@@ -1051,6 +1771,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<style name="Theme.DeviceDefault.Dialog.Alert" parent="Theme.Material.Dialog.Alert">
@@ -1100,6 +1865,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<!-- Theme for the dialog shown when an app crashes or ANRs. -->
@@ -1154,6 +1964,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<style name="Theme.DeviceDefault.Dialog.NoFrame" parent="Theme.Material.Dialog.NoFrame">
@@ -1201,6 +2056,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<!-- Variant of {@link #Theme_DeviceDefault} with a light-colored style -->
@@ -1386,6 +2286,51 @@ easier.
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
<item name="colorPopupBackground">?attr/colorBackgroundFloating</item>
<item name="panelColorBackground">?attr/colorBackgroundFloating</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_light</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_light</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_light</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_light</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_light</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_light</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_light</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_light</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_light</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_light</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_light</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_light</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_light</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_light</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_light</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_light</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_light</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_light</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_light</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_light</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_light</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_light</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_light</item>
+ <item name="materialColorOnBackground">@color/system_on_background_light</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_light</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_light</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_light</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_light</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_light</item>
+ <item name="materialColorSecondary">@color/system_secondary_light</item>
+ <item name="materialColorOnError">@color/system_on_error_light</item>
+ <item name="materialColorSurface">@color/system_surface_light</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_light</item>
+ <item name="materialColorTertiary">@color/system_tertiary_light</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_light</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_light</item>
+ <item name="materialColorOutline">@color/system_outline_light</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_light</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+
</style>
<!-- Variant of the DeviceDefault (light) theme that has a solid (opaque) action bar with an
@@ -1435,6 +2380,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_light</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_light</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_light</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_light</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_light</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_light</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_light</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_light</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_light</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_light</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_light</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_light</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_light</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_light</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_light</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_light</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_light</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_light</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_light</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_light</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_light</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_light</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_light</item>
+ <item name="materialColorOnBackground">@color/system_on_background_light</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_light</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_light</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_light</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_light</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_light</item>
+ <item name="materialColorSecondary">@color/system_secondary_light</item>
+ <item name="materialColorOnError">@color/system_on_error_light</item>
+ <item name="materialColorSurface">@color/system_surface_light</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_light</item>
+ <item name="materialColorTertiary">@color/system_tertiary_light</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_light</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_light</item>
+ <item name="materialColorOutline">@color/system_outline_light</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_light</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Light} with no action bar -->
@@ -1483,6 +2473,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_light</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_light</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_light</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_light</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_light</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_light</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_light</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_light</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_light</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_light</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_light</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_light</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_light</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_light</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_light</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_light</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_light</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_light</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_light</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_light</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_light</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_light</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_light</item>
+ <item name="materialColorOnBackground">@color/system_on_background_light</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_light</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_light</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_light</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_light</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_light</item>
+ <item name="materialColorSecondary">@color/system_secondary_light</item>
+ <item name="materialColorOnError">@color/system_on_error_light</item>
+ <item name="materialColorSurface">@color/system_surface_light</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_light</item>
+ <item name="materialColorTertiary">@color/system_tertiary_light</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_light</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_light</item>
+ <item name="materialColorOutline">@color/system_outline_light</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_light</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Light} with no action bar and no status bar.
@@ -1532,6 +2567,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_light</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_light</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_light</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_light</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_light</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_light</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_light</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_light</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_light</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_light</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_light</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_light</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_light</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_light</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_light</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_light</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_light</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_light</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_light</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_light</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_light</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_light</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_light</item>
+ <item name="materialColorOnBackground">@color/system_on_background_light</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_light</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_light</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_light</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_light</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_light</item>
+ <item name="materialColorSecondary">@color/system_secondary_light</item>
+ <item name="materialColorOnError">@color/system_on_error_light</item>
+ <item name="materialColorSurface">@color/system_surface_light</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_light</item>
+ <item name="materialColorTertiary">@color/system_tertiary_light</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_light</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_light</item>
+ <item name="materialColorOutline">@color/system_outline_light</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_light</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Light} with no action bar and no status bar
@@ -1583,6 +2663,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_light</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_light</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_light</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_light</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_light</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_light</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_light</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_light</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_light</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_light</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_light</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_light</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_light</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_light</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_light</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_light</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_light</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_light</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_light</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_light</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_light</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_light</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_light</item>
+ <item name="materialColorOnBackground">@color/system_on_background_light</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_light</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_light</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_light</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_light</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_light</item>
+ <item name="materialColorSecondary">@color/system_secondary_light</item>
+ <item name="materialColorOnError">@color/system_on_error_light</item>
+ <item name="materialColorSurface">@color/system_surface_light</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_light</item>
+ <item name="materialColorTertiary">@color/system_tertiary_light</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_light</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_light</item>
+ <item name="materialColorOutline">@color/system_outline_light</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_light</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Light} that has no title bar and translucent
@@ -1633,6 +2758,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_light</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_light</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_light</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_light</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_light</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_light</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_light</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_light</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_light</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_light</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_light</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_light</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_light</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_light</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_light</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_light</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_light</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_light</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_light</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_light</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_light</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_light</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_light</item>
+ <item name="materialColorOnBackground">@color/system_on_background_light</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_light</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_light</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_light</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_light</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_light</item>
+ <item name="materialColorSecondary">@color/system_secondary_light</item>
+ <item name="materialColorOnError">@color/system_on_error_light</item>
+ <item name="materialColorSurface">@color/system_surface_light</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_light</item>
+ <item name="materialColorTertiary">@color/system_tertiary_light</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_light</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_light</item>
+ <item name="materialColorOutline">@color/system_outline_light</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_light</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+
</style>
<!-- DeviceDefault light theme for dialog windows and activities. This changes the window to be
@@ -1689,6 +2859,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_light</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_light</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_light</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_light</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_light</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_light</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_light</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_light</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_light</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_light</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_light</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_light</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_light</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_light</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_light</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_light</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_light</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_light</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_light</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_light</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_light</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_light</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_light</item>
+ <item name="materialColorOnBackground">@color/system_on_background_light</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_light</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_light</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_light</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_light</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_light</item>
+ <item name="materialColorSecondary">@color/system_secondary_light</item>
+ <item name="materialColorOnError">@color/system_on_error_light</item>
+ <item name="materialColorSurface">@color/system_surface_light</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_light</item>
+ <item name="materialColorTertiary">@color/system_tertiary_light</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_light</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_light</item>
+ <item name="materialColorOutline">@color/system_outline_light</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_light</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Light_Dialog} that has a nice minimum width for a
@@ -1741,6 +2956,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_light</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_light</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_light</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_light</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_light</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_light</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_light</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_light</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_light</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_light</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_light</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_light</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_light</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_light</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_light</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_light</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_light</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_light</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_light</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_light</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_light</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_light</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_light</item>
+ <item name="materialColorOnBackground">@color/system_on_background_light</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_light</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_light</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_light</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_light</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_light</item>
+ <item name="materialColorSecondary">@color/system_secondary_light</item>
+ <item name="materialColorOnError">@color/system_on_error_light</item>
+ <item name="materialColorSurface">@color/system_surface_light</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_light</item>
+ <item name="materialColorTertiary">@color/system_tertiary_light</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_light</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_light</item>
+ <item name="materialColorOutline">@color/system_outline_light</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_light</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Light_Dialog} without an action bar -->
@@ -1792,6 +3052,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_light</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_light</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_light</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_light</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_light</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_light</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_light</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_light</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_light</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_light</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_light</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_light</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_light</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_light</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_light</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_light</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_light</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_light</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_light</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_light</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_light</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_light</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_light</item>
+ <item name="materialColorOnBackground">@color/system_on_background_light</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_light</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_light</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_light</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_light</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_light</item>
+ <item name="materialColorSecondary">@color/system_secondary_light</item>
+ <item name="materialColorOnError">@color/system_on_error_light</item>
+ <item name="materialColorSurface">@color/system_surface_light</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_light</item>
+ <item name="materialColorTertiary">@color/system_tertiary_light</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_light</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_light</item>
+ <item name="materialColorOutline">@color/system_outline_light</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_light</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Light_Dialog_NoActionBar} that has a nice minimum
@@ -1844,6 +3149,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_light</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_light</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_light</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_light</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_light</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_light</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_light</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_light</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_light</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_light</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_light</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_light</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_light</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_light</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_light</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_light</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_light</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_light</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_light</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_light</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_light</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_light</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_light</item>
+ <item name="materialColorOnBackground">@color/system_on_background_light</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_light</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_light</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_light</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_light</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_light</item>
+ <item name="materialColorSecondary">@color/system_secondary_light</item>
+ <item name="materialColorOnError">@color/system_on_error_light</item>
+ <item name="materialColorSurface">@color/system_surface_light</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_light</item>
+ <item name="materialColorTertiary">@color/system_tertiary_light</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_light</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_light</item>
+ <item name="materialColorOutline">@color/system_outline_light</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_light</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+
</style>
<!-- Variant of Theme.DeviceDefault.Dialog that has a fixed size. -->
@@ -1877,6 +3227,51 @@ easier.
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_light</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_light</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_light</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_light</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_light</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_light</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_light</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_light</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_light</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_light</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_light</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_light</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_light</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_light</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_light</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_light</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_light</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_light</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_light</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_light</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_light</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_light</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_light</item>
+ <item name="materialColorOnBackground">@color/system_on_background_light</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_light</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_light</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_light</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_light</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_light</item>
+ <item name="materialColorSecondary">@color/system_secondary_light</item>
+ <item name="materialColorOnError">@color/system_on_error_light</item>
+ <item name="materialColorSurface">@color/system_surface_light</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_light</item>
+ <item name="materialColorTertiary">@color/system_tertiary_light</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_light</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_light</item>
+ <item name="materialColorOutline">@color/system_outline_light</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_light</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+
</style>
<!-- Variant of Theme.DeviceDefault.Dialog.NoActionBar that has a fixed size. -->
@@ -1910,6 +3305,51 @@ easier.
<item name="textColorOnAccent">@color/text_color_on_accent_device_default</item>
<item name="colorForeground">@color/foreground_device_default_light</item>
<item name="colorForegroundInverse">@color/foreground_device_default_dark</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_light</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_light</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_light</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_light</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_light</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_light</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_light</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_light</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_light</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_light</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_light</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_light</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_light</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_light</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_light</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_light</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_light</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_light</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_light</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_light</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_light</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_light</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_light</item>
+ <item name="materialColorOnBackground">@color/system_on_background_light</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_light</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_light</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_light</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_light</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_light</item>
+ <item name="materialColorSecondary">@color/system_secondary_light</item>
+ <item name="materialColorOnError">@color/system_on_error_light</item>
+ <item name="materialColorSurface">@color/system_surface_light</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_light</item>
+ <item name="materialColorTertiary">@color/system_tertiary_light</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_light</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_light</item>
+ <item name="materialColorOutline">@color/system_outline_light</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_light</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+
</style>
<!-- DeviceDefault light theme for a window that will be displayed either full-screen on smaller
@@ -1962,6 +3402,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_light</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_light</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_light</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_light</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_light</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_light</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_light</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_light</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_light</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_light</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_light</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_light</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_light</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_light</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_light</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_light</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_light</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_light</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_light</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_light</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_light</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_light</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_light</item>
+ <item name="materialColorOnBackground">@color/system_on_background_light</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_light</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_light</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_light</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_light</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_light</item>
+ <item name="materialColorSecondary">@color/system_secondary_light</item>
+ <item name="materialColorOnError">@color/system_on_error_light</item>
+ <item name="materialColorSurface">@color/system_surface_light</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_light</item>
+ <item name="materialColorTertiary">@color/system_tertiary_light</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_light</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_light</item>
+ <item name="materialColorOutline">@color/system_outline_light</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_light</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+
</style>
<!-- DeviceDefault light theme for a window without an action bar that will be displayed either
@@ -2015,6 +3500,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_light</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_light</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_light</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_light</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_light</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_light</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_light</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_light</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_light</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_light</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_light</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_light</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_light</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_light</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_light</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_light</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_light</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_light</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_light</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_light</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_light</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_light</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_light</item>
+ <item name="materialColorOnBackground">@color/system_on_background_light</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_light</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_light</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_light</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_light</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_light</item>
+ <item name="materialColorSecondary">@color/system_secondary_light</item>
+ <item name="materialColorOnError">@color/system_on_error_light</item>
+ <item name="materialColorSurface">@color/system_surface_light</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_light</item>
+ <item name="materialColorTertiary">@color/system_tertiary_light</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_light</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_light</item>
+ <item name="materialColorOutline">@color/system_outline_light</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_light</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+
</style>
<!-- DeviceDefault light theme for a presentation window on a secondary display. -->
@@ -2066,6 +3596,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_light</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_light</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_light</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_light</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_light</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_light</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_light</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_light</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_light</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_light</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_light</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_light</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_light</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_light</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_light</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_light</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_light</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_light</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_light</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_light</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_light</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_light</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_light</item>
+ <item name="materialColorOnBackground">@color/system_on_background_light</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_light</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_light</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_light</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_light</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_light</item>
+ <item name="materialColorSecondary">@color/system_secondary_light</item>
+ <item name="materialColorOnError">@color/system_on_error_light</item>
+ <item name="materialColorSurface">@color/system_surface_light</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_light</item>
+ <item name="materialColorTertiary">@color/system_tertiary_light</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_light</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_light</item>
+ <item name="materialColorOutline">@color/system_outline_light</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_light</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+
</style>
<!-- DeviceDefault light theme for panel windows. This removes all extraneous window
@@ -2116,6 +3691,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_light</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_light</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_light</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_light</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_light</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_light</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_light</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_light</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_light</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_light</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_light</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_light</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_light</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_light</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_light</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_light</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_light</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_light</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_light</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_light</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_light</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_light</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_light</item>
+ <item name="materialColorOnBackground">@color/system_on_background_light</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_light</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_light</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_light</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_light</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_light</item>
+ <item name="materialColorSecondary">@color/system_secondary_light</item>
+ <item name="materialColorOnError">@color/system_on_error_light</item>
+ <item name="materialColorSurface">@color/system_surface_light</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_light</item>
+ <item name="materialColorTertiary">@color/system_tertiary_light</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_light</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_light</item>
+ <item name="materialColorOutline">@color/system_outline_light</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_light</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+
</style>
<style name="Theme.DeviceDefault.Light.Dialog.Alert" parent="Theme.Material.Light.Dialog.Alert">
@@ -2165,6 +3785,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_light</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_light</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_light</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_light</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_light</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_light</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_light</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_light</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_light</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_light</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_light</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_light</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_light</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_light</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_light</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_light</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_light</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_light</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_light</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_light</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_light</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_light</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_light</item>
+ <item name="materialColorOnBackground">@color/system_on_background_light</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_light</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_light</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_light</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_light</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_light</item>
+ <item name="materialColorSecondary">@color/system_secondary_light</item>
+ <item name="materialColorOnError">@color/system_on_error_light</item>
+ <item name="materialColorSurface">@color/system_surface_light</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_light</item>
+ <item name="materialColorTertiary">@color/system_tertiary_light</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_light</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_light</item>
+ <item name="materialColorOutline">@color/system_outline_light</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_light</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+
</style>
<style name="Theme.DeviceDefault.Dialog.Alert.DayNight" parent="Theme.DeviceDefault.Light.Dialog.Alert" />
@@ -2214,6 +3879,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_light</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_light</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_light</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_light</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_light</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_light</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_light</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_light</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_light</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_light</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_light</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_light</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_light</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_light</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_light</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_light</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_light</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_light</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_light</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_light</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_light</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_light</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_light</item>
+ <item name="materialColorOnBackground">@color/system_on_background_light</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_light</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_light</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_light</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_light</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_light</item>
+ <item name="materialColorSecondary">@color/system_secondary_light</item>
+ <item name="materialColorOnError">@color/system_on_error_light</item>
+ <item name="materialColorSurface">@color/system_surface_light</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_light</item>
+ <item name="materialColorTertiary">@color/system_tertiary_light</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_light</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_light</item>
+ <item name="materialColorOutline">@color/system_outline_light</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_light</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+
</style>
<style name="Theme.DeviceDefault.Light.Voice" parent="Theme.Material.Light.Voice">
@@ -2261,6 +3971,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_light</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_light</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_light</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_light</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_light</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_light</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_light</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_light</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_light</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_light</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_light</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_light</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_light</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_light</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_light</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_light</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_light</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_light</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_light</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_light</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_light</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_light</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_light</item>
+ <item name="materialColorOnBackground">@color/system_on_background_light</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_light</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_light</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_light</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_light</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_light</item>
+ <item name="materialColorSecondary">@color/system_secondary_light</item>
+ <item name="materialColorOnError">@color/system_on_error_light</item>
+ <item name="materialColorSurface">@color/system_surface_light</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_light</item>
+ <item name="materialColorTertiary">@color/system_tertiary_light</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_light</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_light</item>
+ <item name="materialColorOutline">@color/system_outline_light</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_light</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+
</style>
<!-- DeviceDefault theme for a window that should look like the Settings app. -->
@@ -2315,6 +4070,51 @@ easier.
<item name="colorListDivider">@color/list_divider_color_light</item>
<item name="opacityListDivider">@color/list_divider_opacity_device_default_light</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<style name="Theme.DeviceDefault.SystemUI" parent="Theme.DeviceDefault.Light">
@@ -2350,6 +4150,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<style name="Theme.DeviceDefault.SystemUI.Dialog" parent="Theme.DeviceDefault.Light.Dialog">
@@ -2377,6 +4222,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<!-- Variant of {@link #Theme_DeviceDefault_Settings_Dark} with no action bar -->
@@ -2426,6 +4316,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<style name="Theme.DeviceDefault.Settings.DialogBase" parent="Theme.Material.Light.BaseDialog">
@@ -2459,6 +4394,51 @@ easier.
<!-- Dialog attributes -->
<item name="alertDialogTheme">@style/Theme.DeviceDefault.Light.Dialog.Alert</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<style name="Theme.DeviceDefault.Settings.Dialog" parent="Theme.DeviceDefault.Settings.DialogBase">
@@ -2532,6 +4512,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<style name="Theme.DeviceDefault.Settings.Dialog.Alert" parent="Theme.Material.Settings.Dialog.Alert">
@@ -2583,6 +4608,51 @@ easier.
<!-- Toolbar attributes -->
<item name="toolbarStyle">@style/Widget.DeviceDefault.Toolbar</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<style name="Theme.DeviceDefault.Settings.Dialog.NoActionBar" parent="Theme.DeviceDefault.Light.Dialog.NoActionBar" />
@@ -2660,6 +4730,51 @@ easier.
<item name="colorAccentPrimary">@color/accent_primary_device_default</item>
<item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
<item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<style name="ThemeOverlay.DeviceDefault.Accent.Light">
@@ -2667,6 +4782,51 @@ easier.
<item name="colorAccentPrimary">@color/accent_primary_device_default</item>
<item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
<item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_light</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_light</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_light</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_light</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_light</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_light</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_light</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_light</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_light</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_light</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_light</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_light</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_light</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_light</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_light</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_light</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_light</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_light</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_light</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_light</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_light</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_light</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_light</item>
+ <item name="materialColorOnBackground">@color/system_on_background_light</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_light</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_light</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_light</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_light</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_light</item>
+ <item name="materialColorSecondary">@color/system_secondary_light</item>
+ <item name="materialColorOnError">@color/system_on_error_light</item>
+ <item name="materialColorSurface">@color/system_surface_light</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_light</item>
+ <item name="materialColorTertiary">@color/system_tertiary_light</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_light</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_light</item>
+ <item name="materialColorOutline">@color/system_outline_light</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_light</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+
</style>
<!-- Theme overlay that replaces colorAccent with the colorAccent from {@link #Theme_DeviceDefault_DayNight}. -->
@@ -2678,6 +4838,51 @@ easier.
<item name="colorAccentPrimary">@color/accent_primary_device_default</item>
<item name="colorAccentSecondary">@color/accent_secondary_device_default</item>
<item name="colorAccentTertiary">@color/accent_tertiary_device_default</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<style name="Theme.DeviceDefault.Light.Dialog.Alert.UserSwitchingDialog" parent="Theme.DeviceDefault.NoActionBar.Fullscreen">
@@ -2685,6 +4890,51 @@ easier.
<item name="colorBackgroundFloating">@color/background_device_default_light</item>
<item name="layout_gravity">center</item>
<item name="windowAnimationStyle">@style/Animation.DeviceDefault.Dialog</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_light</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_light</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_light</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_light</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_light</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_light</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_light</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_light</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_light</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_light</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_light</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_light</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_light</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_light</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_light</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_light</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_light</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_light</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_light</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_light</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_light</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_light</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_light</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_light</item>
+ <item name="materialColorOnBackground">@color/system_on_background_light</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_light</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_light</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_light</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_light</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_light</item>
+ <item name="materialColorSecondary">@color/system_secondary_light</item>
+ <item name="materialColorOnError">@color/system_on_error_light</item>
+ <item name="materialColorSurface">@color/system_surface_light</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_light</item>
+ <item name="materialColorTertiary">@color/system_tertiary_light</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_light</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_light</item>
+ <item name="materialColorOutline">@color/system_outline_light</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_light</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_light</item>
+
</style>
<style name="Theme.DeviceDefault.Notification" parent="@style/Theme.Material.Notification">
@@ -2703,6 +4953,51 @@ easier.
<item name="colorAccentPrimary">@color/system_accent1_100</item>
<item name="textColorPrimary">@color/system_neutral1_900</item>
<item name="textColorSecondary">@color/system_neutral2_700</item>
+
+ <item name="materialColorOnSecondaryFixedVariant">@color/system_on_secondary_fixed_variant_dark</item>
+ <item name="materialColorOnTertiaryFixedVariant">@color/system_on_tertiary_fixed_variant_dark</item>
+ <item name="materialColorSurfaceContainerLowest">@color/system_surface_container_lowest_dark</item>
+ <item name="materialColorOnPrimaryFixedVariant">@color/system_on_primary_fixed_variant_dark</item>
+ <item name="materialColorOnSecondaryContainer">@color/system_on_secondary_container_dark</item>
+ <item name="materialColorOnTertiaryContainer">@color/system_on_tertiary_container_dark</item>
+ <item name="materialColorSurfaceContainerLow">@color/system_surface_container_low_dark</item>
+ <item name="materialColorOnPrimaryContainer">@color/system_on_primary_container_dark</item>
+ <item name="materialColorSecondaryFixedDim">@color/system_secondary_fixed_dim_dark</item>
+ <item name="materialColorOnErrorContainer">@color/system_on_error_container_dark</item>
+ <item name="materialColorOnSecondaryFixed">@color/system_on_secondary_fixed_dark</item>
+ <item name="materialColorOnSurfaceInverse">@color/system_on_surface_dark</item>
+ <item name="materialColorTertiaryFixedDim">@color/system_tertiary_fixed_dim_dark</item>
+ <item name="materialColorOnTertiaryFixed">@color/system_on_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryFixedDim">@color/system_primary_fixed_dim_dark</item>
+ <item name="materialColorSecondaryContainer">@color/system_secondary_container_dark</item>
+ <item name="materialColorErrorContainer">@color/system_error_container_dark</item>
+ <item name="materialColorOnPrimaryFixed">@color/system_on_primary_fixed_dark</item>
+ <item name="materialColorPrimaryInverse">@color/system_primary_dark</item>
+ <item name="materialColorSecondaryFixed">@color/system_secondary_fixed_dark</item>
+ <item name="materialColorSurfaceInverse">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceVariant">@color/system_surface_variant_dark</item>
+ <item name="materialColorTertiaryContainer">@color/system_tertiary_container_dark</item>
+ <item name="materialColorTertiaryFixed">@color/system_tertiary_fixed_dark</item>
+ <item name="materialColorPrimaryContainer">@color/system_primary_container_dark</item>
+ <item name="materialColorOnBackground">@color/system_on_background_dark</item>
+ <item name="materialColorPrimaryFixed">@color/system_primary_fixed_dark</item>
+ <item name="materialColorOnSecondary">@color/system_on_secondary_dark</item>
+ <item name="materialColorOnTertiary">@color/system_on_tertiary_dark</item>
+ <item name="materialColorSurfaceDim">@color/system_surface_dim_dark</item>
+ <item name="materialColorSurfaceBright">@color/system_surface_bright_dark</item>
+ <item name="materialColorSecondary">@color/system_secondary_dark</item>
+ <item name="materialColorOnError">@color/system_on_error_dark</item>
+ <item name="materialColorSurface">@color/system_surface_dark</item>
+ <item name="materialColorSurfaceContainerHigh">@color/system_surface_container_high_dark</item>
+ <item name="materialColorTertiary">@color/system_tertiary_dark</item>
+ <item name="materialColorSurfaceContainerHighest">@color/system_surface_container_highest_dark</item>
+ <item name="materialColorOnSurfaceVariant">@color/system_on_surface_variant_dark</item>
+ <item name="materialColorOutline">@color/system_outline_dark</item>
+ <item name="materialColorOnPrimary">@color/system_on_primary_dark</item>
+ <item name="materialColorOnSurface">@color/system_on_surface_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+ <item name="materialColorSurfaceContainer">@color/system_surface_container_dark</item>
+
</style>
<style name="Theme.DeviceDefault.AutofillHalfScreenDialogList" parent="Theme.DeviceDefault.DayNight">
<item name="colorListDivider">@color/list_divider_opacity_device_default_light</item>
diff --git a/core/tests/companiontests/OWNERS b/core/tests/companiontests/OWNERS
new file mode 100644
index 000000000000..734d8b6c5f43
--- /dev/null
+++ b/core/tests/companiontests/OWNERS
@@ -0,0 +1 @@
+include /core/java/android/companion/OWNERS \ No newline at end of file
diff --git a/core/tests/companiontests/src/android/companion/SystemDataTransportTest.java b/core/tests/companiontests/src/android/companion/SystemDataTransportTest.java
index d63384332400..2b4123af3885 100644
--- a/core/tests/companiontests/src/android/companion/SystemDataTransportTest.java
+++ b/core/tests/companiontests/src/android/companion/SystemDataTransportTest.java
@@ -60,6 +60,7 @@ public class SystemDataTransportTest extends InstrumentationTestCase {
mContext = getInstrumentation().getTargetContext();
mCdm = mContext.getSystemService(CompanionDeviceManager.class);
mAssociationId = createAssociation();
+ mCdm.enableSecureTransport(false);
}
@Override
@@ -67,6 +68,7 @@ public class SystemDataTransportTest extends InstrumentationTestCase {
super.tearDown();
mCdm.disassociate(mAssociationId);
+ mCdm.enableSecureTransport(true);
}
public void testPingHandRolled() {
diff --git a/core/tests/coretests/src/android/hardware/face/FaceManagerTest.java b/core/tests/coretests/src/android/hardware/face/FaceManagerTest.java
new file mode 100644
index 000000000000..9b1f0cd9e8da
--- /dev/null
+++ b/core/tests/coretests/src/android/hardware/face/FaceManagerTest.java
@@ -0,0 +1,151 @@
+/*
+ * 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 android.hardware.face;
+
+import static android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_HW_UNAVAILABLE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.res.Resources;
+import android.os.CancellationSignal;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.test.TestLooper;
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.MockitoRule;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Presubmit
+@RunWith(MockitoJUnitRunner.class)
+public class FaceManagerTest {
+ private static final int USER_ID = 4;
+ private static final String PACKAGE_NAME = "f.m.test";
+ private static final String ATTRIBUTION_TAG = "blue";
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private Resources mResources;
+ @Mock
+ private IFaceService mService;
+ @Mock
+ private FaceManager.AuthenticationCallback mAuthCallback;
+
+ @Captor
+ private ArgumentCaptor<IFaceAuthenticatorsRegisteredCallback> mCaptor;
+ @Captor
+ private ArgumentCaptor<FaceAuthenticateOptions> mOptionsCaptor;
+
+ private List<FaceSensorPropertiesInternal> mProps;
+ private TestLooper mLooper;
+ private Handler mHandler;
+ private FaceManager mFaceManager;
+
+ @Before
+ public void setUp() throws Exception {
+ mLooper = new TestLooper();
+ mHandler = new Handler(mLooper.getLooper());
+
+ when(mContext.getMainLooper()).thenReturn(mLooper.getLooper());
+ when(mContext.getOpPackageName()).thenReturn(PACKAGE_NAME);
+ when(mContext.getAttributionTag()).thenReturn(ATTRIBUTION_TAG);
+ when(mContext.getApplicationInfo()).thenReturn(new ApplicationInfo());
+ when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getString(anyInt())).thenReturn("string");
+
+ mFaceManager = new FaceManager(mContext, mService);
+ mProps = List.of(new FaceSensorPropertiesInternal(
+ 0 /* id */,
+ FaceSensorProperties.STRENGTH_STRONG,
+ 1 /* maxTemplatesAllowed */,
+ new ArrayList<>() /* componentInfo */,
+ FaceSensorProperties.TYPE_UNKNOWN,
+ true /* supportsFaceDetection */,
+ true /* supportsSelfIllumination */,
+ false /* resetLockoutRequiresChallenge */));
+ }
+
+ @Test
+ public void getSensorPropertiesInternal_noBinderCalls() throws RemoteException {
+ verify(mService).addAuthenticatorsRegisteredCallback(mCaptor.capture());
+
+ mCaptor.getValue().onAllAuthenticatorsRegistered(mProps);
+ List<FaceSensorPropertiesInternal> actual = mFaceManager.getSensorPropertiesInternal();
+
+ assertThat(actual).isEqualTo(mProps);
+ verify(mService, never()).getSensorPropertiesInternal(any());
+ }
+
+ @Test
+ public void authenticate_withOptions() throws Exception {
+ mFaceManager.authenticate(null, new CancellationSignal(), mAuthCallback, mHandler,
+ new FaceAuthenticateOptions.Builder()
+ .setUserId(USER_ID)
+ .setOpPackageName("some.thing")
+ .setAttributionTag(null)
+ .build());
+
+ verify(mService).authenticate(any(IBinder.class), eq(0L),
+ any(IFaceServiceReceiver.class), mOptionsCaptor.capture());
+
+ assertThat(mOptionsCaptor.getValue()).isEqualTo(
+ new FaceAuthenticateOptions.Builder()
+ .setUserId(USER_ID)
+ .setOpPackageName(PACKAGE_NAME)
+ .setAttributionTag(ATTRIBUTION_TAG)
+ .build()
+ );
+ }
+
+ @Test
+ public void authenticate_errorWhenUnavailable() throws Exception {
+ when(mService.authenticate(any(), anyLong(), any(), any()))
+ .thenThrow(new RemoteException());
+
+ mFaceManager.authenticate(null, new CancellationSignal(),
+ mAuthCallback, mHandler,
+ new FaceAuthenticateOptions.Builder().build());
+
+ verify(mAuthCallback).onAuthenticationError(eq(FACE_ERROR_HW_UNAVAILABLE), any());
+ }
+}
diff --git a/core/tests/coretests/src/android/hardware/face/OWNERS b/core/tests/coretests/src/android/hardware/face/OWNERS
new file mode 100644
index 000000000000..6a2192a2c7fb
--- /dev/null
+++ b/core/tests/coretests/src/android/hardware/face/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/biometrics/OWNERS
diff --git a/core/tests/coretests/src/android/hardware/fingerprint/FingerprintManagerTest.java b/core/tests/coretests/src/android/hardware/fingerprint/FingerprintManagerTest.java
new file mode 100644
index 000000000000..f31903a73111
--- /dev/null
+++ b/core/tests/coretests/src/android/hardware/fingerprint/FingerprintManagerTest.java
@@ -0,0 +1,152 @@
+/*
+ * 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 android.hardware.fingerprint;
+
+import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_HW_UNAVAILABLE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.res.Resources;
+import android.os.CancellationSignal;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.test.TestLooper;
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.MockitoRule;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Presubmit
+@RunWith(MockitoJUnitRunner.class)
+public class FingerprintManagerTest {
+ private static final int USER_ID = 9;
+ private static final String PACKAGE_NAME = "finger.food.test";
+ private static final String ATTRIBUTION_TAG = "taz";
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private Resources mResources;
+ @Mock
+ private IFingerprintService mService;
+ @Mock
+ private FingerprintManager.AuthenticationCallback mAuthCallback;
+
+ @Captor
+ private ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mCaptor;
+ @Captor
+ private ArgumentCaptor<FingerprintAuthenticateOptions> mOptionsCaptor;
+
+ private List<FingerprintSensorPropertiesInternal> mProps;
+ private TestLooper mLooper;
+ private Handler mHandler;
+ private FingerprintManager mFingerprintManager;
+
+ @Before
+ public void setUp() throws Exception {
+ mLooper = new TestLooper();
+ mHandler = new Handler(mLooper.getLooper());
+
+ when(mContext.getMainLooper()).thenReturn(mLooper.getLooper());
+ when(mContext.getOpPackageName()).thenReturn(PACKAGE_NAME);
+ when(mContext.getAttributionTag()).thenReturn(ATTRIBUTION_TAG);
+ when(mContext.getApplicationInfo()).thenReturn(new ApplicationInfo());
+ when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getString(anyInt())).thenReturn("string");
+
+ mFingerprintManager = new FingerprintManager(mContext, mService);
+ mProps = List.of(new FingerprintSensorPropertiesInternal(
+ 0 /* sensorId */,
+ FingerprintSensorProperties.STRENGTH_STRONG,
+ 1 /* maxEnrollmentsPerUser */,
+ new ArrayList<>() /* componentInfo */,
+ FingerprintSensorProperties.TYPE_UNKNOWN,
+ true /* halControlsIllumination */,
+ true /* resetLockoutRequiresHardwareAuthToken */,
+ new ArrayList<>() /* sensorLocations */));
+ }
+
+ @Test
+ public void getSensorPropertiesInternal_noBinderCalls() throws RemoteException {
+ verify(mService).addAuthenticatorsRegisteredCallback(mCaptor.capture());
+
+ mCaptor.getValue().onAllAuthenticatorsRegistered(mProps);
+ List<FingerprintSensorPropertiesInternal> actual =
+ mFingerprintManager.getSensorPropertiesInternal();
+
+ assertThat(actual).isEqualTo(mProps);
+ verify(mService, never()).getSensorPropertiesInternal(any());
+ }
+
+ @Test
+ public void authenticate_withOptions() throws Exception {
+ mFingerprintManager.authenticate(null, new CancellationSignal(), mAuthCallback, mHandler,
+ new FingerprintAuthenticateOptions.Builder()
+ .setUserId(USER_ID)
+ .setOpPackageName("some.thing")
+ .setAttributionTag(null)
+ .build());
+
+ verify(mService).authenticate(any(IBinder.class), eq(0L),
+ any(IFingerprintServiceReceiver.class), mOptionsCaptor.capture());
+
+ assertThat(mOptionsCaptor.getValue()).isEqualTo(
+ new FingerprintAuthenticateOptions.Builder()
+ .setUserId(USER_ID)
+ .setOpPackageName(PACKAGE_NAME)
+ .setAttributionTag(ATTRIBUTION_TAG)
+ .build()
+ );
+ }
+
+ @Test
+ public void authenticate_errorWhenUnavailable() throws Exception {
+ when(mService.authenticate(any(), anyLong(), any(), any()))
+ .thenThrow(new RemoteException());
+
+ mFingerprintManager.authenticate(null, new CancellationSignal(),
+ mAuthCallback, mHandler,
+ new FingerprintAuthenticateOptions.Builder().build());
+
+ verify(mAuthCallback).onAuthenticationError(eq(FINGERPRINT_ERROR_HW_UNAVAILABLE), any());
+ }
+}
diff --git a/core/tests/coretests/src/android/hardware/fingerprint/OWNERS b/core/tests/coretests/src/android/hardware/fingerprint/OWNERS
new file mode 100644
index 000000000000..6a2192a2c7fb
--- /dev/null
+++ b/core/tests/coretests/src/android/hardware/fingerprint/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/biometrics/OWNERS
diff --git a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java
index eae1bbc930d4..17ed4c478350 100644
--- a/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java
+++ b/core/tests/coretests/src/android/view/contentcapture/ContentCaptureManagerTest.java
@@ -15,6 +15,8 @@
*/
package android.view.contentcapture;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.Mockito.mock;
import static org.testng.Assert.assertThrows;
@@ -54,4 +56,19 @@ public class ContentCaptureManagerTest {
assertThrows(NullPointerException.class, () -> manager.removeData(null));
}
+
+ @Test
+ @SuppressWarnings("GuardedBy")
+ public void testFlushViewTreeAppearingEventDisabled_setAndGet() {
+ final IContentCaptureManager mockService = mock(IContentCaptureManager.class);
+ final ContentCaptureOptions options = new ContentCaptureOptions(null);
+ final ContentCaptureManager manager =
+ new ContentCaptureManager(mMockContext, mockService, options);
+
+ assertThat(manager.getFlushViewTreeAppearingEventDisabled()).isFalse();
+ manager.setFlushViewTreeAppearingEventDisabled(true);
+ assertThat(manager.getFlushViewTreeAppearingEventDisabled()).isTrue();
+ manager.setFlushViewTreeAppearingEventDisabled(false);
+ assertThat(manager.getFlushViewTreeAppearingEventDisabled()).isFalse();
+ }
}
diff --git a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
index a663095aa893..58cfc6625051 100644
--- a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
@@ -16,6 +16,12 @@
package com.android.internal.app;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
@@ -53,6 +59,7 @@ import androidx.test.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
+import com.android.internal.R;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
@@ -140,6 +147,8 @@ public class IntentForwarderActivityTest {
@Test
public void forwardToManagedProfile_canForward_sendIntent() throws Exception {
sComponentName = FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME;
+ sActivityName = "MyTestActivity";
+ sPackageName = "test.package.name";
// Intent can be forwarded.
when(mIPm.canForwardTo(
@@ -160,7 +169,13 @@ public class IntentForwarderActivityTest {
verify(mIPm).canForwardTo(intentCaptor.capture(), eq(TYPE_PLAIN_TEXT), anyInt(), anyInt());
assertEquals(Intent.ACTION_SEND, intentCaptor.getValue().getAction());
- assertEquals(Intent.ACTION_SEND, intentCaptor.getValue().getAction());
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ onView(withId(R.id.icon)).check(matches(isDisplayed()));
+ onView(withId(R.id.open_cross_profile)).check(matches(isDisplayed()));
+ onView(withId(R.id.use_same_profile_browser)).check(matches(isDisplayed()));
+ onView(withId(R.id.button_open)).perform(click());
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
assertNotNull(activity.mStartActivityIntent);
assertEquals(Intent.ACTION_SEND, activity.mStartActivityIntent.getAction());
assertNull(activity.mStartActivityIntent.getPackage());
@@ -250,6 +265,8 @@ public class IntentForwarderActivityTest {
@Test
public void forwardToManagedProfile_canForward_selectorIntent() throws Exception {
sComponentName = FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME;
+ sActivityName = "MyTestActivity";
+ sPackageName = "test.package.name";
// Intent can be forwarded.
when(mIPm.canForwardTo(
@@ -264,6 +281,7 @@ public class IntentForwarderActivityTest {
// Create selector intent.
Intent intent = Intent.makeMainSelectorActivity(
Intent.ACTION_VIEW, Intent.CATEGORY_BROWSABLE);
+
IntentForwarderWrapperActivity activity = mActivityRule.launchActivity(intent);
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
@@ -271,6 +289,13 @@ public class IntentForwarderActivityTest {
intentCaptor.capture(), nullable(String.class), anyInt(), anyInt());
assertEquals(Intent.ACTION_VIEW, intentCaptor.getValue().getAction());
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+ onView(withId(R.id.icon)).check(matches(isDisplayed()));
+ onView(withId(R.id.open_cross_profile)).check(matches(isDisplayed()));
+ onView(withId(R.id.use_same_profile_browser)).check(matches(isDisplayed()));
+ onView(withId(R.id.button_open)).perform(click());
+ InstrumentationRegistry.getInstrumentation().waitForIdleSync();
+
assertNotNull(activity.mStartActivityIntent);
assertEquals(Intent.ACTION_MAIN, activity.mStartActivityIntent.getAction());
assertNull(activity.mStartActivityIntent.getPackage());
@@ -608,7 +633,7 @@ public class IntentForwarderActivityTest {
}
private void setupShouldSkipDisclosureTest() throws RemoteException {
- sComponentName = FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME;
+ sComponentName = FORWARD_TO_PARENT_COMPONENT_NAME;
sActivityName = "MyTestActivity";
sPackageName = "test.package.name";
Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.DEVICE_PROVISIONED,
@@ -619,6 +644,7 @@ public class IntentForwarderActivityTest {
profiles.add(CURRENT_USER_INFO);
profiles.add(MANAGED_PROFILE_INFO);
when(mUserManager.getProfiles(anyInt())).thenReturn(profiles);
+ when(mUserManager.getProfileParent(anyInt())).thenReturn(CURRENT_USER_INFO);
// Intent can be forwarded.
when(mIPm.canForwardTo(
any(Intent.class), nullable(String.class), anyInt(), anyInt())).thenReturn(true);
@@ -654,6 +680,11 @@ public class IntentForwarderActivityTest {
}
@Override
+ public Context createContextAsUser(UserHandle user, int flags) {
+ return this;
+ }
+
+ @Override
protected MetricsLogger getMetricsLogger() {
return mMetricsLogger;
}
diff --git a/data/etc/preinstalled-packages-platform.xml b/data/etc/preinstalled-packages-platform.xml
index ff8d96dd23f2..421bc25d60e9 100644
--- a/data/etc/preinstalled-packages-platform.xml
+++ b/data/etc/preinstalled-packages-platform.xml
@@ -102,11 +102,29 @@ Changes to the whitelist during system updates can result in installing addition
to pre-existing users, but cannot uninstall pre-existing system packages from pre-existing users.
-->
<config>
+ <!-- Bluetooth (com.android.btservices apex) - visible on the sharesheet -->
+ <install-in-user-type package="com.android.bluetooth">
+ <install-in user-type="SYSTEM" />
+ <install-in user-type="FULL" />
+ <install-in user-type="PROFILE" />
+ <do-not-install-in user-type="android.os.usertype.profile.CLONE" />
+ </install-in-user-type>
+
+ <!-- Settings (Settings app) -->
+ <install-in-user-type package="com.android.settings">
+ <install-in user-type="SYSTEM" />
+ <install-in user-type="FULL" />
+ <install-in user-type="PROFILE" />
+ </install-in-user-type>
+
+ <!-- Settings Storage (SettingsProvider) -->
<install-in-user-type package="com.android.providers.settings">
<install-in user-type="SYSTEM" />
<install-in user-type="FULL" />
<install-in user-type="PROFILE" />
</install-in-user-type>
+
+ <!-- WallpaperBackup (WallpaperBackup)-->
<install-in-user-type package="com.android.wallpaperbackup">
<install-in user-type="FULL" />
</install-in-user-type>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index d726b6730f30..71050fa8b233 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -506,6 +506,8 @@ applications that come with the platform
<permission name="android.permission.ACCESS_BROADCAST_RADIO"/>
<!-- Permission required for CTS test - CtsAmbientContextServiceTestCases -->
<permission name="android.permission.ACCESS_AMBIENT_CONTEXT_EVENT"/>
+ <!-- Permission required for CTS test - CtsTelephonyProviderTestCases -->
+ <permission name="android.permission.WRITE_APN_SETTINGS"/>
</privapp-permissions>
<privapp-permissions package="com.android.statementservice">
diff --git a/graphics/java/android/graphics/Gainmap.java b/graphics/java/android/graphics/Gainmap.java
index 470a06c1f1f5..a7c508c75ac9 100644
--- a/graphics/java/android/graphics/Gainmap.java
+++ b/graphics/java/android/graphics/Gainmap.java
@@ -96,8 +96,8 @@ public final class Gainmap implements Parcelable {
throw new RuntimeException("internal error: native gainmap is 0");
}
- mGainmapContents = gainmapContents;
mNativePtr = nativeGainmap;
+ setGainmapContents(gainmapContents);
NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, nativeGainmap);
}
diff --git a/graphics/java/android/graphics/text/LineBreaker.java b/graphics/java/android/graphics/text/LineBreaker.java
index babcfc3815f4..67eb117cb17c 100644
--- a/graphics/java/android/graphics/text/LineBreaker.java
+++ b/graphics/java/android/graphics/text/LineBreaker.java
@@ -22,6 +22,7 @@ import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Px;
+import android.os.Trace;
import dalvik.annotation.optimization.CriticalNative;
import dalvik.annotation.optimization.FastNative;
@@ -475,19 +476,26 @@ public class LineBreaker {
@NonNull MeasuredText measuredPara,
@NonNull ParagraphConstraints constraints,
@IntRange(from = 0) int lineNumber) {
- return new Result(nComputeLineBreaks(
- mNativePtr,
-
- // Inputs
- measuredPara.getChars(),
- measuredPara.getNativePtr(),
- measuredPara.getChars().length,
- constraints.mFirstWidth,
- constraints.mFirstWidthLineCount,
- constraints.mWidth,
- constraints.mVariableTabStops,
- constraints.mDefaultTabStop,
- lineNumber));
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "compute line break");
+ long result = 0;
+ try {
+ result = nComputeLineBreaks(
+ mNativePtr,
+
+ // Inputs
+ measuredPara.getChars(),
+ measuredPara.getNativePtr(),
+ measuredPara.getChars().length,
+ constraints.mFirstWidth,
+ constraints.mFirstWidthLineCount,
+ constraints.mWidth,
+ constraints.mVariableTabStops,
+ constraints.mDefaultTabStop,
+ lineNumber);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
+ return new Result(result);
}
@FastNative
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 2c1ddf7cfcbe..9f3c19b2b545 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -308,7 +308,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
synchronized (mLock) {
final List<TaskFragmentContainer> containers = taskContainer.mContainers;
// Clean up the TaskFragmentContainers by the z-order from the lowest.
- for (int i = 0; i < containers.size() - 1; i++) {
+ for (int i = 0; i < containers.size(); i++) {
final TaskFragmentContainer container = containers.get(i);
if (pendingFinishingContainers.contains(container)) {
// Don't update records here to prevent double invocation.
@@ -318,7 +318,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
}
// Remove container records.
removeContainers(taskContainer, pendingFinishingContainers);
- // Update the change to the client side.
+ // Update the change to the server side.
updateContainersInTaskIfVisible(wct, taskContainer.getTaskId());
}
});
@@ -353,21 +353,25 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
@Override
public void updateSplitAttributes(@NonNull IBinder splitInfoToken,
@NonNull SplitAttributes splitAttributes) {
+ Objects.requireNonNull(splitInfoToken);
+ Objects.requireNonNull(splitAttributes);
synchronized (mLock) {
final SplitContainer splitContainer = getSplitContainer(splitInfoToken);
if (splitContainer == null) {
Log.w(TAG, "Cannot find SplitContainer for token:" + splitInfoToken);
return;
}
- WindowContainerTransaction wct = mTransactionManager.startNewTransaction()
- .getTransaction();
+ // Override the default split Attributes so that it will be applied
+ // if the SplitContainer is not visible currently.
+ splitContainer.updateDefaultSplitAttributes(splitAttributes);
+
+ final TransactionRecord transactionRecord = mTransactionManager.startNewTransaction();
+ final WindowContainerTransaction wct = transactionRecord.getTransaction();
if (updateSplitContainerIfNeeded(splitContainer, wct, splitAttributes)) {
- splitContainer.updateDefaultSplitAttributes(splitAttributes);
- mTransactionManager.getCurrentTransactionRecord()
- .apply(false /* shouldApplyIndependently */);
+ transactionRecord.apply(false /* shouldApplyIndependently */);
} else {
// Abort if the SplitContainer wasn't updated.
- mTransactionManager.getCurrentTransactionRecord().abort();
+ transactionRecord.abort();
}
}
}
@@ -1559,8 +1563,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
*
* @return {@code true} if the update succeed. Otherwise, returns {@code false}.
*/
+ @VisibleForTesting
@GuardedBy("mLock")
- private boolean updateSplitContainerIfNeeded(@NonNull SplitContainer splitContainer,
+ boolean updateSplitContainerIfNeeded(@NonNull SplitContainer splitContainer,
@NonNull WindowContainerTransaction wct, @Nullable SplitAttributes splitAttributes) {
if (!isTopMostSplit(splitContainer)) {
// Skip position update - it isn't the topmost split.
@@ -1904,6 +1909,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
return null;
}
+ @VisibleForTesting
@Nullable
@GuardedBy("mLock")
SplitContainer getSplitContainer(@NonNull IBinder token) {
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
index 17909d4a0763..61cd7485ff1d 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java
@@ -67,6 +67,7 @@ import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import android.annotation.NonNull;
import android.app.Activity;
@@ -82,6 +83,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
+import android.util.ArraySet;
import android.view.WindowInsets;
import android.view.WindowMetrics;
import android.window.TaskFragmentInfo;
@@ -100,12 +102,14 @@ import androidx.window.extensions.layout.WindowLayoutInfo;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Set;
import java.util.function.Consumer;
/**
@@ -1323,6 +1327,125 @@ public class SplitControllerTest {
verify(mTransaction).startActivityInTaskFragment(any(), any(), any(), any());
}
+ @Test
+ public void testFinishActivityStacks_emptySet_earlyReturn() {
+ mSplitController.finishActivityStacks(Collections.emptySet());
+
+ verify(mSplitController, never()).updateContainersInTaskIfVisible(any(), anyInt());
+ }
+
+ @Test
+ public void testFinishActivityStacks_invalidStacks_earlyReturn() {
+ mSplitController.finishActivityStacks(Collections.singleton(new Binder()));
+
+ verify(mSplitController, never()).updateContainersInTaskIfVisible(any(), anyInt());
+ }
+
+ @Test
+ public void testFinishActivityStacks_finishSingleActivityStack() {
+ TaskFragmentContainer tf = mSplitController.newContainer(mActivity, TASK_ID);
+ tf.setInfo(mTransaction, createMockTaskFragmentInfo(tf, mActivity));
+
+ List<TaskFragmentContainer> containers = mSplitController.mTaskContainers.get(TASK_ID)
+ .mContainers;
+
+ assertEquals(containers.get(0), tf);
+
+ mSplitController.finishActivityStacks(Collections.singleton(tf.getTaskFragmentToken()));
+
+ verify(mSplitPresenter).deleteTaskFragment(any(), eq(tf.getTaskFragmentToken()));
+ assertTrue(containers.isEmpty());
+ }
+
+ @Test
+ public void testFinishActivityStacks_finishActivityStacksInOrder() {
+ TaskFragmentContainer bottomTf = mSplitController.newContainer(mActivity, TASK_ID);
+ TaskFragmentContainer topTf = mSplitController.newContainer(mActivity, TASK_ID);
+ bottomTf.setInfo(mTransaction, createMockTaskFragmentInfo(bottomTf, mActivity));
+ topTf.setInfo(mTransaction, createMockTaskFragmentInfo(topTf, createMockActivity()));
+
+ List<TaskFragmentContainer> containers = mSplitController.mTaskContainers.get(TASK_ID)
+ .mContainers;
+
+ assertEquals(containers.size(), 2);
+
+ Set<IBinder> activityStackTokens = new ArraySet<>(new IBinder[]{
+ topTf.getTaskFragmentToken(), bottomTf.getTaskFragmentToken()});
+
+ mSplitController.finishActivityStacks(activityStackTokens);
+
+ ArgumentCaptor<IBinder> argumentCaptor = ArgumentCaptor.forClass(IBinder.class);
+
+ verify(mSplitPresenter, times(2)).deleteTaskFragment(any(), argumentCaptor.capture());
+
+ List<IBinder> fragmentTokens = argumentCaptor.getAllValues();
+ assertEquals("The ActivityStack must be deleted from the lowest z-order "
+ + "regardless of the order in ActivityStack set",
+ bottomTf.getTaskFragmentToken(), fragmentTokens.get(0));
+ assertEquals("The ActivityStack must be deleted from the lowest z-order "
+ + "regardless of the order in ActivityStack set",
+ topTf.getTaskFragmentToken(), fragmentTokens.get(1));
+
+ assertTrue(containers.isEmpty());
+ }
+
+ @Test
+ public void testUpdateSplitAttributes_invalidSplitContainerToken_earlyReturn() {
+ mSplitController.updateSplitAttributes(new Binder(), SPLIT_ATTRIBUTES);
+
+ verify(mTransactionManager, never()).startNewTransaction();
+ }
+
+ @Test
+ public void testUpdateSplitAttributes_nullParams_throwException() {
+ assertThrows(NullPointerException.class,
+ () -> mSplitController.updateSplitAttributes(null, SPLIT_ATTRIBUTES));
+
+ final SplitContainer splitContainer = mock(SplitContainer.class);
+ final IBinder token = new Binder();
+ doReturn(token).when(splitContainer).getToken();
+ doReturn(splitContainer).when(mSplitController).getSplitContainer(eq(token));
+
+ assertThrows(NullPointerException.class,
+ () -> mSplitController.updateSplitAttributes(token, null));
+ }
+
+ @Test
+ public void testUpdateSplitAttributes_doNotNeedToUpdateSplitContainer_doNotApplyTransaction() {
+ final SplitContainer splitContainer = mock(SplitContainer.class);
+ final IBinder token = new Binder();
+ doReturn(token).when(splitContainer).getToken();
+ doReturn(splitContainer).when(mSplitController).getSplitContainer(eq(token));
+ doReturn(false).when(mSplitController).updateSplitContainerIfNeeded(
+ eq(splitContainer), any(), eq(SPLIT_ATTRIBUTES));
+ TransactionManager.TransactionRecord testRecord =
+ mock(TransactionManager.TransactionRecord.class);
+ doReturn(testRecord).when(mTransactionManager).startNewTransaction();
+
+ mSplitController.updateSplitAttributes(token, SPLIT_ATTRIBUTES);
+
+ verify(splitContainer).updateDefaultSplitAttributes(eq(SPLIT_ATTRIBUTES));
+ verify(testRecord).abort();
+ }
+
+ @Test
+ public void testUpdateSplitAttributes_splitContainerUpdated_updateAttrs() {
+ final SplitContainer splitContainer = mock(SplitContainer.class);
+ final IBinder token = new Binder();
+ doReturn(token).when(splitContainer).getToken();
+ doReturn(splitContainer).when(mSplitController).getSplitContainer(eq(token));
+ doReturn(true).when(mSplitController).updateSplitContainerIfNeeded(
+ eq(splitContainer), any(), eq(SPLIT_ATTRIBUTES));
+ TransactionManager.TransactionRecord testRecord =
+ mock(TransactionManager.TransactionRecord.class);
+ doReturn(testRecord).when(mTransactionManager).startNewTransaction();
+
+ mSplitController.updateSplitAttributes(token, SPLIT_ATTRIBUTES);
+
+ verify(splitContainer).updateDefaultSplitAttributes(eq(SPLIT_ATTRIBUTES));
+ verify(testRecord).apply(eq(false));
+ }
+
/** Creates a mock activity in the organizer process. */
private Activity createMockActivity() {
return createMockActivity(TASK_ID);
diff --git a/libs/WindowManager/Shell/Android.bp b/libs/WindowManager/Shell/Android.bp
index 0f4521951e3d..c7c94246b96a 100644
--- a/libs/WindowManager/Shell/Android.bp
+++ b/libs/WindowManager/Shell/Android.bp
@@ -49,6 +49,7 @@ filegroup {
"src/com/android/wm/shell/animation/Interpolators.java",
"src/com/android/wm/shell/pip/PipContentOverlay.java",
"src/com/android/wm/shell/startingsurface/SplashScreenExitAnimationUtils.java",
+ "src/com/android/wm/shell/draganddrop/DragAndDropConstants.java",
],
path: "src",
}
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background.xml
deleted file mode 100644
index 0d8811357c05..000000000000
--- a/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2022 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <solid android:color="@color/letterbox_education_accent_primary"/>
- <corners android:radius="12dp"/>
-</shape> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background_ripple.xml b/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background_ripple.xml
index 42572d64b96f..a2699681e656 100644
--- a/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background_ripple.xml
+++ b/libs/WindowManager/Shell/res/drawable/letterbox_education_dismiss_button_background_ripple.xml
@@ -14,7 +14,30 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="@color/letterbox_education_dismiss_button_background_ripple">
- <item android:drawable="@drawable/letterbox_education_dismiss_button_background"/>
-</ripple> \ No newline at end of file
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ android:insetTop="@dimen/letterbox_education_dialog_vertical_inset"
+ android:insetBottom="@dimen/letterbox_education_dialog_vertical_inset">
+ <ripple android:color="@color/letterbox_education_dismiss_button_background_ripple">
+ <item android:id="@android:id/mask">
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/letterbox_education_dialog_button_radius"/>
+ <solid android:color="@android:color/white"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="@android:color/transparent"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="@color/letterbox_education_accent_primary"/>
+ <corners android:radius="@dimen/letterbox_education_dialog_button_radius"/>
+ <padding android:left="@dimen/letterbox_education_dialog_horizontal_padding"
+ android:top="@dimen/letterbox_education_dialog_vertical_padding"
+ android:right="@dimen/letterbox_education_dialog_horizontal_padding"
+ android:bottom="@dimen/letterbox_education_dialog_vertical_padding"/>
+ </shape>
+ </item>
+ </ripple>
+</inset>
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background.xml b/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background.xml
deleted file mode 100644
index 60f3cfe6dde6..000000000000
--- a/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2023 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- android:shape="rectangle">
- <solid android:color="?androidprv:attr/colorAccentPrimaryVariant"/>
- <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/>
-</shape> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background_ripple.xml b/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background_ripple.xml
index ef97ea19e993..1f125148775d 100644
--- a/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background_ripple.xml
+++ b/libs/WindowManager/Shell/res/drawable/letterbox_restart_button_background_ripple.xml
@@ -14,7 +14,31 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="@color/letterbox_restart_button_background_ripple">
- <item android:drawable="@drawable/letterbox_restart_button_background"/>
-</ripple> \ No newline at end of file
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:insetTop="@dimen/letterbox_restart_dialog_vertical_inset"
+ android:insetBottom="@dimen/letterbox_restart_dialog_vertical_inset">
+ <ripple android:color="@color/letterbox_restart_dismiss_button_background_ripple">
+ <item android:id="@android:id/mask">
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/>
+ <solid android:color="@android:color/white"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="@android:color/transparent"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="?androidprv:attr/colorAccentPrimaryVariant"/>
+ <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/>
+ <padding android:left="@dimen/letterbox_restart_dialog_horizontal_padding"
+ android:top="@dimen/letterbox_restart_dialog_vertical_padding"
+ android:right="@dimen/letterbox_restart_dialog_horizontal_padding"
+ android:bottom="@dimen/letterbox_restart_dialog_vertical_padding"/>
+ </shape>
+ </item>
+ </ripple>
+</inset> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background.xml b/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background.xml
deleted file mode 100644
index af89d41ee6b5..000000000000
--- a/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2023 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
- android:shape="rectangle">
- <stroke android:color="?androidprv:attr/colorAccentPrimaryVariant" android:width="1dp"/>
- <solid android:color="?androidprv:attr/colorSurface" />
- <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/>
-</shape> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background_ripple.xml b/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background_ripple.xml
index e32aefca78ac..3aa0981e45aa 100644
--- a/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background_ripple.xml
+++ b/libs/WindowManager/Shell/res/drawable/letterbox_restart_dismiss_button_background_ripple.xml
@@ -14,7 +14,33 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:color="@color/letterbox_restart_dismiss_button_background_ripple">
- <item android:drawable="@drawable/letterbox_restart_dismiss_button_background"/>
-</ripple> \ No newline at end of file
+<inset xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+ android:insetTop="@dimen/letterbox_restart_dialog_vertical_inset"
+ android:insetBottom="@dimen/letterbox_restart_dialog_vertical_inset">
+ <ripple android:color="@color/letterbox_restart_dismiss_button_background_ripple">
+ <item android:id="@android:id/mask">
+ <shape android:shape="rectangle">
+ <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/>
+ <solid android:color="@android:color/white"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <solid android:color="@android:color/transparent"/>
+ </shape>
+ </item>
+ <item>
+ <shape android:shape="rectangle">
+ <stroke android:color="?androidprv:attr/colorAccentPrimaryVariant"
+ android:width="1dp"/>
+ <solid android:color="?androidprv:attr/colorSurface"/>
+ <corners android:radius="@dimen/letterbox_restart_dialog_button_radius"/>
+ <padding android:left="@dimen/letterbox_restart_dialog_horizontal_padding"
+ android:top="@dimen/letterbox_restart_dialog_vertical_padding"
+ android:right="@dimen/letterbox_restart_dialog_horizontal_padding"
+ android:bottom="@dimen/letterbox_restart_dialog_vertical_padding"/>
+ </shape>
+ </item>
+ </ripple>
+</inset> \ No newline at end of file
diff --git a/libs/WindowManager/Shell/res/layout/compat_mode_hint.xml b/libs/WindowManager/Shell/res/layout/compat_mode_hint.xml
index 44b2f45052ba..3d3c00381164 100644
--- a/libs/WindowManager/Shell/res/layout/compat_mode_hint.xml
+++ b/libs/WindowManager/Shell/res/layout/compat_mode_hint.xml
@@ -29,11 +29,15 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="4sp"
+ android:letterSpacing="0.02"
android:background="@drawable/compat_hint_bubble"
android:padding="16dp"
android:textAlignment="viewStart"
android:textColor="@color/compat_controls_text"
- android:textSize="14sp"/>
+ android:textSize="14sp"
+ android:fontFamily="@*android:string/config_bodyFontFamily"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Subhead"
+ />
<ImageView
android:layout_width="wrap_content"
diff --git a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml
index c65f24d84e37..095576b581df 100644
--- a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_action_layout.xml
@@ -29,6 +29,8 @@
android:layout_marginBottom="20dp"/>
<TextView
+ android:fontFamily="@*android:string/config_bodyFontFamily"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Body2"
android:id="@+id/letterbox_education_dialog_action_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
index 3a44eb9089dd..e8edad15dfc3 100644
--- a/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
+++ b/libs/WindowManager/Shell/res/layout/letterbox_education_dialog_layout.xml
@@ -69,6 +69,8 @@
android:text="@string/letterbox_education_dialog_title"
android:textAlignment="center"
android:textColor="@color/compat_controls_text"
+ android:fontFamily="@*android:string/config_bodyFontFamilyMedium"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Headline"
android:textSize="24sp"/>
<LinearLayout
@@ -95,10 +97,16 @@
</LinearLayout>
<Button
+ android:fontFamily="@*android:string/config_bodyFontFamily"
+ android:fontWeight="500"
+ android:lineHeight="20dp"
+ android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Small"
android:id="@+id/letterbox_education_dialog_dismiss_button"
+ android:textStyle="bold"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_marginTop="40dp"
+ android:textSize="14sp"
android:background=
"@drawable/letterbox_education_dismiss_button_background_ripple"
android:text="@string/letterbox_education_got_it"
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index 6f31d0674246..336c156e831a 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -273,6 +273,18 @@
<!-- The space between two actions in the letterbox education dialog -->
<dimen name="letterbox_education_dialog_space_between_actions">24dp</dimen>
+ <!-- The corner radius of the buttons in the letterbox education dialog -->
+ <dimen name="letterbox_education_dialog_button_radius">12dp</dimen>
+
+ <!-- The horizontal padding for the buttons in the letterbox education dialog -->
+ <dimen name="letterbox_education_dialog_horizontal_padding">16dp</dimen>
+
+ <!-- The vertical padding for the buttons in the letterbox education dialog -->
+ <dimen name="letterbox_education_dialog_vertical_padding">8dp</dimen>
+
+ <!-- The insets for the buttons in the letterbox education dialog -->
+ <dimen name="letterbox_education_dialog_vertical_inset">6dp</dimen>
+
<!-- The margin between the dialog container and its parent. -->
<dimen name="letterbox_restart_dialog_margin">24dp</dimen>
@@ -306,6 +318,15 @@
<!-- The corner radius of the buttons in the restart dialog -->
<dimen name="letterbox_restart_dialog_button_radius">18dp</dimen>
+ <!-- The insets for the buttons in the letterbox restart dialog -->
+ <dimen name="letterbox_restart_dialog_vertical_inset">6dp</dimen>
+
+ <!-- The horizontal padding for the buttons in the letterbox restart dialog -->
+ <dimen name="letterbox_restart_dialog_horizontal_padding">16dp</dimen>
+
+ <!-- The vertical padding for the buttons in the letterbox restart dialog -->
+ <dimen name="letterbox_restart_dialog_vertical_padding">8dp</dimen>
+
<!-- The width of the brand image on staring surface. -->
<dimen name="starting_surface_brand_image_width">200dp</dimen>
@@ -331,30 +352,6 @@
-->
<dimen name="overridable_minimal_size_pip_resizable_task">48dp</dimen>
- <!-- The size of the drag handle / menu shown along with a floating task. -->
- <dimen name="floating_task_menu_size">32dp</dimen>
-
- <!-- The size of menu items in the floating task menu. -->
- <dimen name="floating_task_menu_item_size">24dp</dimen>
-
- <!-- The horizontal margin of menu items in the floating task menu. -->
- <dimen name="floating_task_menu_item_padding">5dp</dimen>
-
- <!-- The width of visible floating view region when stashed. -->
- <dimen name="floating_task_stash_offset">32dp</dimen>
-
- <!-- The amount of elevation for a floating task. -->
- <dimen name="floating_task_elevation">8dp</dimen>
-
- <!-- The amount of padding around the bottom and top of the task. -->
- <dimen name="floating_task_vertical_padding">8dp</dimen>
-
- <!-- The normal size of the dismiss target. -->
- <dimen name="floating_task_dismiss_circle_size">150dp</dimen>
-
- <!-- The smaller size of the dismiss target (shrinks when something is in the target). -->
- <dimen name="floating_dismiss_circle_small">120dp</dimen>
-
<!-- The thickness of shadows of a window that has focus in DIP. -->
<dimen name="freeform_decor_shadow_focused_thickness">20dp</dimen>
diff --git a/libs/WindowManager/Shell/res/values/styles.xml b/libs/WindowManager/Shell/res/values/styles.xml
index bae009a0526f..0a0c49f2d93f 100644
--- a/libs/WindowManager/Shell/res/values/styles.xml
+++ b/libs/WindowManager/Shell/res/values/styles.xml
@@ -87,6 +87,9 @@
<item name="android:textAppearance">
@*android:style/TextAppearance.DeviceDefault.Headline
</item>
+ <item name="android:fontFamily">
+ @*android:string/config_bodyFontFamilyMedium
+ </item>
</style>
<style name="RestartDialogBodyText">
@@ -97,24 +100,44 @@
<item name="android:textAppearance">
@*android:style/TextAppearance.DeviceDefault.Body2
</item>
+ <item name="android:fontFamily">
+ @*android:string/config_bodyFontFamily
+ </item>
</style>
<style name="RestartDialogCheckboxText">
<item name="android:textSize">16sp</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
<item name="android:lineSpacingExtra">4sp</item>
- <item name="android:textAppearance">@*android:style/TextAppearance.DeviceDefault</item>
+ <item name="android:textAppearance">
+ @*android:style/TextAppearance.DeviceDefault.Headline
+ </item>
+ <item name="android:fontFamily">
+ @*android:string/config_bodyFontFamilyMedium
+ </item>
</style>
<style name="RestartDialogDismissButton">
<item name="android:lineSpacingExtra">2sp</item>
<item name="android:textSize">14sp</item>
<item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:textAppearance">
+ @*android:style/TextAppearance.DeviceDefault.Body2
+ </item>
+ <item name="android:fontFamily">
+ @*android:string/config_bodyFontFamily
+ </item>
</style>
<style name="RestartDialogConfirmButton">
<item name="android:lineSpacingExtra">2sp</item>
<item name="android:textSize">14sp</item>
<item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
+ <item name="android:textAppearance">
+ @*android:style/TextAppearance.DeviceDefault.Body2
+ </item>
+ <item name="android:fontFamily">
+ @*android:string/config_bodyFontFamily
+ </item>
</style>
</resources>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ProtoLogController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ProtoLogController.java
index 88525aabe53b..e2012b4e36dc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ProtoLogController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ProtoLogController.java
@@ -16,6 +16,8 @@
package com.android.wm.shell;
+import android.os.Build;
+
import com.android.wm.shell.protolog.ShellProtoLogImpl;
import com.android.wm.shell.sysui.ShellCommandHandler;
import com.android.wm.shell.sysui.ShellInit;
@@ -41,6 +43,9 @@ public class ProtoLogController implements ShellCommandHandler.ShellCommandActio
void onInit() {
mShellCommandHandler.addCommandCallback("protolog", this, this);
+ if (Build.IS_DEBUGGABLE) {
+ mShellProtoLog.startProtoLog(null /* PrintWriter */);
+ }
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskViewTaskController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskViewTaskController.java
index 1f223a6ec5d0..080b171f4d40 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskViewTaskController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskViewTaskController.java
@@ -131,7 +131,7 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
mShellExecutor.execute(() -> {
final WindowContainerTransaction wct = new WindowContainerTransaction();
wct.startShortcut(mContext.getPackageName(), shortcut, options.toBundle());
- mTaskViewTransitions.startTaskView(wct, this);
+ mTaskViewTransitions.startTaskView(wct, this, options.getLaunchCookie());
});
return;
}
@@ -158,7 +158,7 @@ public class TaskViewTaskController implements ShellTaskOrganizer.TaskListener {
mShellExecutor.execute(() -> {
WindowContainerTransaction wct = new WindowContainerTransaction();
wct.sendPendingIntent(pendingIntent, fillInIntent, options.toBundle());
- mTaskViewTransitions.startTaskView(wct, this);
+ mTaskViewTransitions.startTaskView(wct, this, options.getLaunchCookie());
});
return;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskViewTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskViewTransitions.java
index aab257ebe885..04bff97bc4ce 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/TaskViewTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/TaskViewTransitions.java
@@ -57,12 +57,21 @@ public class TaskViewTransitions implements Transitions.TransitionHandler {
final @NonNull TaskViewTaskController mTaskView;
IBinder mClaimed;
+ /**
+ * This is needed because arbitrary activity launches can still "intrude" into any
+ * transition since `startActivity` is a synchronous call. Once that is solved, we can
+ * remove this.
+ */
+ final IBinder mLaunchCookie;
+
PendingTransition(@WindowManager.TransitionType int type,
@Nullable WindowContainerTransaction wct,
- @NonNull TaskViewTaskController taskView) {
+ @NonNull TaskViewTaskController taskView,
+ @Nullable IBinder launchCookie) {
mType = type;
mWct = wct;
mTaskView = taskView;
+ mLaunchCookie = launchCookie;
}
}
@@ -142,7 +151,7 @@ public class TaskViewTransitions implements Transitions.TransitionHandler {
if (!Transitions.isClosingType(request.getType())) return null;
PendingTransition pending = findPending(taskView, true /* closing */, false /* latest */);
if (pending == null) {
- pending = new PendingTransition(request.getType(), null, taskView);
+ pending = new PendingTransition(request.getType(), null, taskView, null /* cookie */);
}
if (pending.mClaimed != null) {
throw new IllegalStateException("Task is closing in 2 collecting transitions?"
@@ -162,8 +171,9 @@ public class TaskViewTransitions implements Transitions.TransitionHandler {
return null;
}
- void startTaskView(WindowContainerTransaction wct, TaskViewTaskController taskView) {
- mPending.add(new PendingTransition(TRANSIT_OPEN, wct, taskView));
+ void startTaskView(@NonNull WindowContainerTransaction wct,
+ @NonNull TaskViewTaskController taskView, @NonNull IBinder launchCookie) {
+ mPending.add(new PendingTransition(TRANSIT_OPEN, wct, taskView, launchCookie));
startNextTransition();
}
@@ -180,7 +190,7 @@ public class TaskViewTransitions implements Transitions.TransitionHandler {
final WindowContainerTransaction wct = new WindowContainerTransaction();
wct.setHidden(taskView.getTaskInfo().token, !visible /* hidden */);
pending = new PendingTransition(
- visible ? TRANSIT_TO_FRONT : TRANSIT_TO_BACK, wct, taskView);
+ visible ? TRANSIT_TO_FRONT : TRANSIT_TO_BACK, wct, taskView, null /* cookie */);
mPending.add(pending);
startNextTransition();
// visibility is reported in transition.
@@ -197,58 +207,92 @@ public class TaskViewTransitions implements Transitions.TransitionHandler {
}
@Override
+ public void onTransitionConsumed(@NonNull IBinder transition, boolean aborted,
+ @NonNull SurfaceControl.Transaction finishTransaction) {
+ if (!aborted) return;
+ final PendingTransition pending = findPending(transition);
+ if (pending == null) return;
+ mPending.remove(pending);
+ startNextTransition();
+ }
+
+ @Override
public boolean startAnimation(@NonNull IBinder transition,
@NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction startTransaction,
@NonNull SurfaceControl.Transaction finishTransaction,
@NonNull Transitions.TransitionFinishCallback finishCallback) {
PendingTransition pending = findPending(transition);
- if (pending == null) return false;
- mPending.remove(pending);
- TaskViewTaskController taskView = pending.mTaskView;
- final ArrayList<TransitionInfo.Change> tasks = new ArrayList<>();
- for (int i = 0; i < info.getChanges().size(); ++i) {
- final TransitionInfo.Change chg = info.getChanges().get(i);
- if (chg.getTaskInfo() == null) continue;
- tasks.add(chg);
+ if (pending != null) {
+ mPending.remove(pending);
}
- if (tasks.isEmpty()) {
- Slog.e(TAG, "Got a TaskView transition with no task.");
+ if (mTaskViews.isEmpty()) {
+ if (pending != null) {
+ Slog.e(TAG, "Pending taskview transition but no task-views");
+ }
return false;
}
+ boolean stillNeedsMatchingLaunch = pending != null && pending.mLaunchCookie != null;
+ int changesHandled = 0;
WindowContainerTransaction wct = null;
- for (int i = 0; i < tasks.size(); ++i) {
- TransitionInfo.Change chg = tasks.get(i);
+ for (int i = 0; i < info.getChanges().size(); ++i) {
+ final TransitionInfo.Change chg = info.getChanges().get(i);
+ if (chg.getTaskInfo() == null) continue;
if (Transitions.isClosingType(chg.getMode())) {
final boolean isHide = chg.getMode() == TRANSIT_TO_BACK;
TaskViewTaskController tv = findTaskView(chg.getTaskInfo());
if (tv == null) {
- throw new IllegalStateException("TaskView transition is closing a "
- + "non-taskview task ");
+ if (pending != null) {
+ Slog.w(TAG, "Found a non-TaskView task in a TaskView Transition. This "
+ + "shouldn't happen, so there may be a visual artifact: "
+ + chg.getTaskInfo().taskId);
+ }
+ continue;
}
if (isHide) {
tv.prepareHideAnimation(finishTransaction);
} else {
tv.prepareCloseAnimation();
}
+ changesHandled++;
} else if (Transitions.isOpeningType(chg.getMode())) {
final boolean taskIsNew = chg.getMode() == TRANSIT_OPEN;
- if (wct == null) wct = new WindowContainerTransaction();
- TaskViewTaskController tv = taskView;
- if (!taskIsNew) {
+ final TaskViewTaskController tv;
+ if (taskIsNew) {
+ if (pending == null
+ || !chg.getTaskInfo().containsLaunchCookie(pending.mLaunchCookie)) {
+ Slog.e(TAG, "Found a launching TaskView in the wrong transition. All "
+ + "TaskView launches should be initiated by shell and in their "
+ + "own transition: " + chg.getTaskInfo().taskId);
+ continue;
+ }
+ stillNeedsMatchingLaunch = false;
+ tv = pending.mTaskView;
+ } else {
tv = findTaskView(chg.getTaskInfo());
if (tv == null) {
- throw new IllegalStateException("TaskView transition is showing a "
- + "non-taskview task ");
+ if (pending != null) {
+ Slog.w(TAG, "Found a non-TaskView task in a TaskView Transition. This "
+ + "shouldn't happen, so there may be a visual artifact: "
+ + chg.getTaskInfo().taskId);
+ }
+ continue;
}
}
+ if (wct == null) wct = new WindowContainerTransaction();
tv.prepareOpenAnimation(taskIsNew, startTransaction, finishTransaction,
chg.getTaskInfo(), chg.getLeash(), wct);
- } else {
- throw new IllegalStateException("Claimed transition isn't an opening or closing"
- + " type: " + chg.getMode());
+ changesHandled++;
}
}
+ if (stillNeedsMatchingLaunch) {
+ throw new IllegalStateException("Expected a TaskView launch in this transition but"
+ + " didn't get one.");
+ }
+ if (wct == null && pending == null && changesHandled != info.getChanges().size()) {
+ // Just some house-keeping, let another handler animate.
+ return false;
+ }
// No animation, just show it immediately.
startTransaction.apply();
finishTransaction.apply();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
index ee5d205498c3..acf17e670041 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/back/BackAnimationController.java
@@ -403,7 +403,7 @@ public class BackAnimationController implements RemoteCallable<BackAnimationCont
InputDevice.SOURCE_KEYBOARD);
ev.setDisplayId(mContext.getDisplay().getDisplayId());
- if (!InputManager.getInstance()
+ if (!mContext.getSystemService(InputManager.class)
.injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC)) {
Log.e(TAG, "Inject input event fail");
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblesNavBarGestureTracker.java b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblesNavBarGestureTracker.java
index e7beeeb06534..3a3a378e00d3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblesNavBarGestureTracker.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/bubbles/BubblesNavBarGestureTracker.java
@@ -64,8 +64,8 @@ class BubblesNavBarGestureTracker {
stopInternal();
- mInputMonitor = InputManager.getInstance().monitorGestureInput(GESTURE_MONITOR,
- mContext.getDisplayId());
+ mInputMonitor = mContext.getSystemService(InputManager.class)
+ .monitorGestureInput(GESTURE_MONITOR, mContext.getDisplayId());
InputChannel inputChannel = mInputMonitor.getInputChannel();
BubblesNavBarMotionEventHandler motionEventHandler =
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DevicePostureController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DevicePostureController.java
new file mode 100644
index 000000000000..22587f4c6456
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DevicePostureController.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.common;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.content.Context;
+import android.hardware.devicestate.DeviceStateManager;
+import android.util.SparseIntArray;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.wm.shell.sysui.ShellInit;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Wrapper class to track the device posture change on Fold-ables.
+ * See also <a
+ * href="https://developer.android.com/guide/topics/large-screens/learn-about-foldables
+ * #foldable_postures">Foldable states and postures</a> for reference.
+ *
+ * Note that most of the implementation here inherits from
+ * {@link com.android.systemui.statusbar.policy.DevicePostureController}.
+ */
+public class DevicePostureController {
+ @IntDef(prefix = {"DEVICE_POSTURE_"}, value = {
+ DEVICE_POSTURE_UNKNOWN,
+ DEVICE_POSTURE_CLOSED,
+ DEVICE_POSTURE_HALF_OPENED,
+ DEVICE_POSTURE_OPENED,
+ DEVICE_POSTURE_FLIPPED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DevicePostureInt {}
+
+ // NOTE: These constants **must** match those defined for Jetpack Sidecar. This is because we
+ // use the Device State -> Jetpack Posture map to translate between the two.
+ public static final int DEVICE_POSTURE_UNKNOWN = 0;
+ public static final int DEVICE_POSTURE_CLOSED = 1;
+ public static final int DEVICE_POSTURE_HALF_OPENED = 2;
+ public static final int DEVICE_POSTURE_OPENED = 3;
+ public static final int DEVICE_POSTURE_FLIPPED = 4;
+
+ private final Context mContext;
+ private final ShellExecutor mMainExecutor;
+ private final List<OnDevicePostureChangedListener> mListeners = new ArrayList<>();
+ private final SparseIntArray mDeviceStateToPostureMap = new SparseIntArray();
+
+ private int mDevicePosture = DEVICE_POSTURE_UNKNOWN;
+
+ public DevicePostureController(
+ Context context, ShellInit shellInit, ShellExecutor mainExecutor) {
+ mContext = context;
+ mMainExecutor = mainExecutor;
+ shellInit.addInitCallback(this::onInit, this);
+ }
+
+ private void onInit() {
+ // Most of this is borrowed from WindowManager/Jetpack/DeviceStateManagerPostureProducer.
+ // Using the sidecar/extension libraries directly brings in a new dependency that it'd be
+ // good to avoid (along with the fact that sidecar is deprecated, and extensions isn't fully
+ // ready yet), and we'd have to make our own layer over the sidecar library anyway to easily
+ // allow the implementation to change, so it was easier to just interface with
+ // DeviceStateManager directly.
+ String[] deviceStatePosturePairs = mContext.getResources()
+ .getStringArray(R.array.config_device_state_postures);
+ for (String deviceStatePosturePair : deviceStatePosturePairs) {
+ String[] deviceStatePostureMapping = deviceStatePosturePair.split(":");
+ if (deviceStatePostureMapping.length != 2) {
+ continue;
+ }
+
+ int deviceState;
+ int posture;
+ try {
+ deviceState = Integer.parseInt(deviceStatePostureMapping[0]);
+ posture = Integer.parseInt(deviceStatePostureMapping[1]);
+ } catch (NumberFormatException e) {
+ continue;
+ }
+
+ mDeviceStateToPostureMap.put(deviceState, posture);
+ }
+
+ final DeviceStateManager deviceStateManager = mContext.getSystemService(
+ DeviceStateManager.class);
+ if (deviceStateManager != null) {
+ deviceStateManager.registerCallback(mMainExecutor, state -> onDevicePostureChanged(
+ mDeviceStateToPostureMap.get(state, DEVICE_POSTURE_UNKNOWN)));
+ }
+ }
+
+ @VisibleForTesting
+ void onDevicePostureChanged(int devicePosture) {
+ if (devicePosture == mDevicePosture) return;
+ mDevicePosture = devicePosture;
+ mListeners.forEach(l -> l.onDevicePostureChanged(mDevicePosture));
+ }
+
+ /**
+ * Register {@link OnDevicePostureChangedListener} for device posture changes.
+ * The listener will receive callback with current device posture upon registration.
+ */
+ public void registerOnDevicePostureChangedListener(
+ @NonNull OnDevicePostureChangedListener listener) {
+ if (mListeners.contains(listener)) return;
+ mListeners.add(listener);
+ listener.onDevicePostureChanged(mDevicePosture);
+ }
+
+ /**
+ * Unregister {@link OnDevicePostureChangedListener} for device posture changes.
+ */
+ public void unregisterOnDevicePostureChangedListener(
+ @NonNull OnDevicePostureChangedListener listener) {
+ mListeners.remove(listener);
+ }
+
+ /**
+ * Listener interface for device posture change.
+ */
+ public interface OnDevicePostureChangedListener {
+ /**
+ * Callback when device posture changes.
+ * See {@link DevicePostureInt} for callback values.
+ */
+ void onDevicePostureChanged(@DevicePostureInt int posture);
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
index eee8ad84d8bd..838022536e43 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java
@@ -42,6 +42,7 @@ import com.android.wm.shell.back.BackAnimationBackground;
import com.android.wm.shell.back.BackAnimationController;
import com.android.wm.shell.bubbles.BubbleController;
import com.android.wm.shell.bubbles.Bubbles;
+import com.android.wm.shell.common.DevicePostureController;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayInsetsController;
@@ -161,6 +162,16 @@ public abstract class WMShellBaseModule {
@WMSingleton
@Provides
+ static DevicePostureController provideDevicePostureController(
+ Context context,
+ ShellInit shellInit,
+ @ShellMainThread ShellExecutor mainExecutor
+ ) {
+ return new DevicePostureController(context, shellInit, mainExecutor);
+ }
+
+ @WMSingleton
+ @Provides
static DragAndDropController provideDragAndDropController(Context context,
ShellInit shellInit,
ShellController shellController,
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 2cdd86fe80cd..d1f439894c47 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
@@ -560,16 +560,18 @@ public abstract class WMShellModule {
static FullscreenUnfoldTaskAnimator provideFullscreenUnfoldTaskAnimator(
Context context,
UnfoldBackgroundController unfoldBackgroundController,
+ ShellController shellController,
DisplayInsetsController displayInsetsController
) {
return new FullscreenUnfoldTaskAnimator(context, unfoldBackgroundController,
- displayInsetsController);
+ shellController, displayInsetsController);
}
@Provides
static SplitTaskUnfoldAnimator provideSplitTaskUnfoldAnimatorBase(
Context context,
UnfoldBackgroundController backgroundController,
+ ShellController shellController,
@ShellMainThread ShellExecutor executor,
Lazy<Optional<SplitScreenController>> splitScreenOptional,
DisplayInsetsController displayInsetsController
@@ -579,7 +581,7 @@ public abstract class WMShellModule {
// controller directly once we refactor ShellTaskOrganizer to not depend on the unfold
// animation controller directly.
return new SplitTaskUnfoldAnimator(context, executor, splitScreenOptional,
- backgroundController, displayInsetsController);
+ shellController, backgroundController, displayInsetsController);
}
@WMSingleton
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropConstants.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropConstants.java
new file mode 100644
index 000000000000..20da54efd286
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropConstants.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.draganddrop;
+
+/** Constants that can be used by both Shell and other users of the library, e.g. Launcher */
+public class DragAndDropConstants {
+
+ /**
+ * An Intent extra that Launcher can use to specify a region of the screen where Shell should
+ * ignore drag events.
+ */
+ public static final String EXTRA_DISALLOW_HIT_REGION = "DISALLOW_HIT_REGION";
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
index d93a9012c8f1..df94b414c092 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
@@ -34,6 +34,7 @@ import static android.content.Intent.EXTRA_USER;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
+import static com.android.wm.shell.draganddrop.DragAndDropConstants.EXTRA_DISALLOW_HIT_REGION;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_FULLSCREEN;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_BOTTOM;
import static com.android.wm.shell.draganddrop.DragAndDropPolicy.Target.TYPE_SPLIT_LEFT;
@@ -53,6 +54,7 @@ import android.content.pm.ActivityInfo;
import android.content.pm.LauncherApps;
import android.graphics.Insets;
import android.graphics.Rect;
+import android.graphics.RectF;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -86,6 +88,7 @@ public class DragAndDropPolicy {
private final Starter mStarter;
private final SplitScreenController mSplitScreen;
private final ArrayList<DragAndDropPolicy.Target> mTargets = new ArrayList<>();
+ private final RectF mDisallowHitRegion = new RectF();
private InstanceId mLoggerSessionId;
private DragSession mSession;
@@ -111,6 +114,12 @@ public class DragAndDropPolicy {
mSession = new DragSession(mActivityTaskManager, displayLayout, data);
// TODO(b/169894807): Also update the session data with task stack changes
mSession.update();
+ RectF disallowHitRegion = (RectF) mSession.dragData.getExtra(EXTRA_DISALLOW_HIT_REGION);
+ if (disallowHitRegion == null) {
+ mDisallowHitRegion.setEmpty();
+ } else {
+ mDisallowHitRegion.set(disallowHitRegion);
+ }
}
/**
@@ -218,6 +227,9 @@ public class DragAndDropPolicy {
*/
@Nullable
Target getTargetAtLocation(int x, int y) {
+ if (mDisallowHitRegion.contains(x, y)) {
+ return null;
+ }
for (int i = mTargets.size() - 1; i >= 0; i--) {
DragAndDropPolicy.Target t = mTargets.get(i);
if (t.hitRegion.contains(x, y)) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
index 3ade1ed9392f..44fd8eec4d06 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
@@ -118,7 +118,7 @@ public class DragLayout extends LinearLayout {
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- mInsets = insets.getInsets(Type.systemBars() | Type.displayCutout());
+ mInsets = insets.getInsets(Type.tappableElement() | Type.displayCutout());
recomputeDropTargets();
final int orientation = getResources().getConfiguration().orientation;
@@ -369,7 +369,9 @@ public class DragLayout extends LinearLayout {
// Start animating the drop UI out with the drag surface
hide(event, dropCompleteCallback);
- hideDragSurface(dragSurface);
+ if (handledDrop) {
+ hideDragSurface(dragSurface);
+ }
return handledDrop;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
index d9ac76e833d8..23f73f614294 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
@@ -209,7 +209,7 @@ public class PipAnimationController {
/**
* Quietly cancel the animator by removing the listeners first.
*/
- static void quietCancel(@NonNull ValueAnimator animator) {
+ public static void quietCancel(@NonNull ValueAnimator animator) {
animator.removeAllUpdateListeners();
animator.removeAllListeners();
animator.cancel();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
index 00ed09445721..a1483a8dedae 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipController.java
@@ -715,6 +715,12 @@ public class PipController implements PipTransitionController.PipTransitionCallb
private void onDisplayChanged(DisplayLayout layout, boolean saveRestoreSnapFraction) {
if (!mPipBoundsState.getDisplayLayout().isSameGeometry(layout)) {
+ PipAnimationController.PipTransitionAnimator animator =
+ mPipAnimationController.getCurrentAnimator();
+ if (animator != null && animator.isRunning()) {
+ // cancel any running animator, as it is using stale display layout information
+ PipAnimationController.quietCancel(animator);
+ }
onDisplayChangedUncheck(layout, saveRestoreSnapFraction);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
index 41ff0b35a035..fee9140d0c2c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipResizeGestureHandler.java
@@ -228,7 +228,7 @@ public class PipResizeGestureHandler {
if (mIsEnabled) {
// Register input event receiver
- mInputMonitor = InputManager.getInstance().monitorGestureInput(
+ mInputMonitor = mContext.getSystemService(InputManager.class).monitorGestureInput(
"pip-resize", mDisplayId);
try {
mMainExecutor.executeBlocking(() -> {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogImpl.java
index 93ffb3dc8115..c59c42dadb9d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/protolog/ShellProtoLogImpl.java
@@ -31,8 +31,7 @@ import java.io.PrintWriter;
*/
public class ShellProtoLogImpl extends BaseProtoLogImpl {
private static final String TAG = "ProtoLogImpl";
- private static final int BUFFER_CAPACITY = 1024 * 1024;
- // TODO: find a proper location to save the protolog message file
+ private static final int BUFFER_CAPACITY = 128 * 1024;
private static final String LOG_FILENAME = "/data/misc/wmtrace/shell_log.winscope";
private static final String VIEWER_CONFIG_FILENAME = "/system_ext/etc/wmshell.protolog.json.gz";
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
index 2b21e77be9c1..520da92fad72 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenTransitions.java
@@ -193,6 +193,8 @@ class SplitScreenTransitions {
mAnimatingTransition = transition;
mFinishTransaction = finishTransaction;
+ startTransaction.apply();
+
final SplitDecorManager topDecor = mPendingDismiss.mDismissTop == STAGE_TYPE_MAIN
? mainDecor : sideDecor;
topDecor.fadeOutDecor(() -> {
@@ -200,8 +202,6 @@ class SplitScreenTransitions {
onFinish(null /* wct */, null /* wctCB */);
});
});
-
- startTransaction.apply();
} else {
playAnimation(transition, info, startTransaction, finishTransaction,
finishCallback, mainRoot, sideRoot, topRoot);
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 19d8cfac559a..7833cfe7df9d 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
@@ -1705,9 +1705,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
}
mSyncQueue.queue(wct);
- mSyncQueue.runInSync(t -> {
- setDividerVisibility(mainStageVisible, t);
- });
+ setDividerVisibility(mainStageVisible, null);
}
private void setDividerVisibility(boolean visible, @Nullable SurfaceControl.Transaction t) {
@@ -1789,6 +1787,10 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
@Override
public void onAnimationEnd(Animator animation) {
+ if (dividerLeash != null && dividerLeash.isValid()) {
+ transaction.setAlpha(dividerLeash, 1);
+ transaction.apply();
+ }
mTransactionPool.release(transaction);
mDividerFadeInAnimator = null;
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
index c2da70595a3d..8e916e63cac6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
@@ -186,7 +186,7 @@ public class DefaultMixedHandler implements Transitions.TransitionHandler {
private boolean isHomeOpening(@NonNull TransitionInfo.Change change) {
return change.getTaskInfo() != null
- && change.getTaskInfo().getActivityType() != ACTIVITY_TYPE_HOME;
+ && change.getTaskInfo().getActivityType() == ACTIVITY_TYPE_HOME;
}
private boolean isWallpaper(@NonNull TransitionInfo.Change change) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 0826fe236d58..0a67477212e9 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -709,15 +709,22 @@ public class Transitions implements RemoteCallable<Transitions> {
for (int iA = activeIdx + 1; iA < mActiveTransitions.size(); ++iA) {
final ActiveTransition toMerge = mActiveTransitions.get(iA);
if (!toMerge.mMerged) break;
- // aborted transitions have no start/finish transactions
- if (mActiveTransitions.get(iA).mStartT == null) break;
- if (fullFinish == null) {
- fullFinish = new SurfaceControl.Transaction();
- }
// Include start. It will be a no-op if it was already applied. Otherwise, we need it
// to maintain consistent state.
- fullFinish.merge(mActiveTransitions.get(iA).mStartT);
- fullFinish.merge(mActiveTransitions.get(iA).mFinishT);
+ if (toMerge.mStartT != null) {
+ if (fullFinish == null) {
+ fullFinish = toMerge.mStartT;
+ } else {
+ fullFinish.merge(toMerge.mStartT);
+ }
+ }
+ if (toMerge.mFinishT != null) {
+ if (fullFinish == null) {
+ fullFinish = toMerge.mFinishT;
+ } else {
+ fullFinish.merge(toMerge.mFinishT);
+ }
+ }
}
if (fullFinish != null) {
fullFinish.apply();
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java
index 87e447bd2010..06a8438a3a25 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/FullscreenUnfoldTaskAnimator.java
@@ -26,8 +26,10 @@ import android.animation.TypeEvaluator;
import android.annotation.NonNull;
import android.app.TaskInfo;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Matrix;
import android.graphics.Rect;
+import android.os.Trace;
import android.util.SparseArray;
import android.view.InsetsSource;
import android.view.InsetsState;
@@ -36,6 +38,8 @@ import android.view.SurfaceControl.Transaction;
import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.wm.shell.common.DisplayInsetsController;
+import com.android.wm.shell.sysui.ConfigurationChangeListener;
+import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.unfold.UnfoldAnimationController;
import com.android.wm.shell.unfold.UnfoldBackgroundController;
@@ -51,7 +55,7 @@ import com.android.wm.shell.unfold.UnfoldBackgroundController;
* instances of FullscreenUnfoldTaskAnimator.
*/
public class FullscreenUnfoldTaskAnimator implements UnfoldTaskAnimator,
- DisplayInsetsController.OnInsetsChangedListener {
+ DisplayInsetsController.OnInsetsChangedListener, ConfigurationChangeListener {
private static final float[] FLOAT_9 = new float[9];
private static final TypeEvaluator<Rect> RECT_EVALUATOR = new RectEvaluator(new Rect());
@@ -63,17 +67,21 @@ public class FullscreenUnfoldTaskAnimator implements UnfoldTaskAnimator,
private final SparseArray<AnimationContext> mAnimationContextByTaskId = new SparseArray<>();
private final int mExpandedTaskBarHeight;
- private final float mWindowCornerRadiusPx;
private final DisplayInsetsController mDisplayInsetsController;
private final UnfoldBackgroundController mBackgroundController;
+ private final Context mContext;
+ private final ShellController mShellController;
private InsetsSource mTaskbarInsetsSource;
+ private float mWindowCornerRadiusPx;
public FullscreenUnfoldTaskAnimator(Context context,
@NonNull UnfoldBackgroundController backgroundController,
- DisplayInsetsController displayInsetsController) {
+ ShellController shellController, DisplayInsetsController displayInsetsController) {
+ mContext = context;
mDisplayInsetsController = displayInsetsController;
mBackgroundController = backgroundController;
+ mShellController = shellController;
mExpandedTaskBarHeight = context.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.taskbar_frame_height);
mWindowCornerRadiusPx = ScreenDecorationsUtils.getWindowCornerRadius(context);
@@ -81,6 +89,14 @@ public class FullscreenUnfoldTaskAnimator implements UnfoldTaskAnimator,
public void init() {
mDisplayInsetsController.addInsetsChangedListener(DEFAULT_DISPLAY, this);
+ mShellController.addConfigurationChangeListener(this);
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfiguration) {
+ Trace.beginSection("FullscreenUnfoldTaskAnimator#onConfigurationChanged");
+ mWindowCornerRadiusPx = ScreenDecorationsUtils.getWindowCornerRadius(mContext);
+ Trace.endSection();
}
@Override
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java
index 8a0fbe328901..f835c7bbd810 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/unfold/animation/SplitTaskUnfoldAnimator.java
@@ -28,8 +28,10 @@ import android.animation.RectEvaluator;
import android.animation.TypeEvaluator;
import android.app.TaskInfo;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Insets;
import android.graphics.Rect;
+import android.os.Trace;
import android.util.SparseArray;
import android.view.InsetsSource;
import android.view.InsetsState;
@@ -42,6 +44,8 @@ import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.splitscreen.SplitScreen.SplitScreenListener;
import com.android.wm.shell.splitscreen.SplitScreenController;
+import com.android.wm.shell.sysui.ConfigurationChangeListener;
+import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.unfold.UnfoldAnimationController;
import com.android.wm.shell.unfold.UnfoldBackgroundController;
@@ -62,16 +66,18 @@ import dagger.Lazy;
* They use independent instances of SplitTaskUnfoldAnimator.
*/
public class SplitTaskUnfoldAnimator implements UnfoldTaskAnimator,
- DisplayInsetsController.OnInsetsChangedListener, SplitScreenListener {
+ DisplayInsetsController.OnInsetsChangedListener, SplitScreenListener,
+ ConfigurationChangeListener {
private static final TypeEvaluator<Rect> RECT_EVALUATOR = new RectEvaluator(new Rect());
private static final float CROPPING_START_MARGIN_FRACTION = 0.05f;
+ private final Context mContext;
private final Executor mExecutor;
private final DisplayInsetsController mDisplayInsetsController;
private final SparseArray<AnimationContext> mAnimationContextByTaskId = new SparseArray<>();
private final int mExpandedTaskBarHeight;
- private final float mWindowCornerRadiusPx;
+ private final ShellController mShellController;
private final Lazy<Optional<SplitScreenController>> mSplitScreenController;
private final UnfoldBackgroundController mUnfoldBackgroundController;
@@ -79,6 +85,7 @@ public class SplitTaskUnfoldAnimator implements UnfoldTaskAnimator,
private final Rect mSideStageBounds = new Rect();
private final Rect mRootStageBounds = new Rect();
+ private float mWindowCornerRadiusPx;
private InsetsSource mTaskbarInsetsSource;
@SplitPosition
@@ -88,10 +95,12 @@ public class SplitTaskUnfoldAnimator implements UnfoldTaskAnimator,
public SplitTaskUnfoldAnimator(Context context, Executor executor,
Lazy<Optional<SplitScreenController>> splitScreenController,
- UnfoldBackgroundController unfoldBackgroundController,
+ ShellController shellController, UnfoldBackgroundController unfoldBackgroundController,
DisplayInsetsController displayInsetsController) {
mDisplayInsetsController = displayInsetsController;
mExecutor = executor;
+ mContext = context;
+ mShellController = shellController;
mUnfoldBackgroundController = unfoldBackgroundController;
mSplitScreenController = splitScreenController;
mExpandedTaskBarHeight = context.getResources().getDimensionPixelSize(
@@ -103,6 +112,14 @@ public class SplitTaskUnfoldAnimator implements UnfoldTaskAnimator,
@Override
public void init() {
mDisplayInsetsController.addInsetsChangedListener(DEFAULT_DISPLAY, this);
+ mShellController.addConfigurationChangeListener(this);
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfiguration) {
+ Trace.beginSection("SplitTaskUnfoldAnimator#onConfigurationChanged");
+ mWindowCornerRadiusPx = ScreenDecorationsUtils.getWindowCornerRadius(mContext);
+ Trace.endSection();
}
/**
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 de5f2f467e99..75bc98555665 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
@@ -505,7 +505,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel {
}
private void createInputChannel(int displayId) {
- final InputManager inputManager = InputManager.getInstance();
+ final InputManager inputManager = mContext.getSystemService(InputManager.class);
final InputMonitor inputMonitor =
mInputMonitorFactory.create(inputManager, mContext);
final EventReceiver eventReceiver = new EventReceiver(inputMonitor,
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 245cc8d7ee87..0779f1d72551 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
@@ -213,6 +213,12 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
final View handle = caption.findViewById(R.id.caption_handle);
handle.setOnTouchListener(mOnCaptionTouchListener);
handle.setOnClickListener(mOnCaptionButtonClickListener);
+ if (DesktopModeStatus.isProto1Enabled()) {
+ final View back = caption.findViewById(R.id.back_button);
+ back.setOnClickListener(mOnCaptionButtonClickListener);
+ final View close = caption.findViewById(R.id.close_window);
+ close.setOnClickListener(mOnCaptionButtonClickListener);
+ }
updateButtonVisibility();
}
@@ -319,6 +325,14 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
final View handle = caption.findViewById(R.id.caption_handle);
final Drawable handleBackground = handle.getBackground();
handleBackground.setTintList(buttonTintColor);
+ if (DesktopModeStatus.isProto1Enabled()) {
+ final View back = caption.findViewById(R.id.back_button);
+ final Drawable backBackground = back.getBackground();
+ backBackground.setTintList(buttonTintColor);
+ final View close = caption.findViewById(R.id.close_window);
+ final Drawable closeBackground = close.getBackground();
+ closeBackground.setTintList(buttonTintColor);
+ }
}
private void closeDragResizeListener() {
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 aea340464304..d0fcd8651481 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
@@ -65,7 +65,7 @@ class TaskOperations {
InputDevice.SOURCE_KEYBOARD);
ev.setDisplayId(mContext.getDisplay().getDisplayId());
- if (!InputManager.getInstance()
+ if (!mContext.getSystemService(InputManager.class)
.injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC)) {
Log.e(TAG, "Inject input event fail");
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DevicePostureControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DevicePostureControllerTest.java
new file mode 100644
index 000000000000..f8ee300e411c
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DevicePostureControllerTest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.wm.shell.common;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import android.content.Context;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.sysui.ShellInit;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class DevicePostureControllerTest {
+ @Mock
+ private Context mContext;
+
+ @Mock
+ private ShellInit mShellInit;
+
+ @Mock
+ private ShellExecutor mMainExecutor;
+
+ @Captor
+ private ArgumentCaptor<Integer> mDevicePostureCaptor;
+
+ @Mock
+ private DevicePostureController.OnDevicePostureChangedListener mOnDevicePostureChangedListener;
+
+ private DevicePostureController mDevicePostureController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mDevicePostureController = new DevicePostureController(mContext, mShellInit, mMainExecutor);
+ }
+
+ @Test
+ public void instantiateController_addInitCallback() {
+ verify(mShellInit, times(1)).addInitCallback(any(), eq(mDevicePostureController));
+ }
+
+ @Test
+ public void registerOnDevicePostureChangedListener_callbackCurrentPosture() {
+ mDevicePostureController.registerOnDevicePostureChangedListener(
+ mOnDevicePostureChangedListener);
+ verify(mOnDevicePostureChangedListener, times(1))
+ .onDevicePostureChanged(anyInt());
+ }
+
+ @Test
+ public void onDevicePostureChanged_differentPosture_callbackListener() {
+ mDevicePostureController.registerOnDevicePostureChangedListener(
+ mOnDevicePostureChangedListener);
+ verify(mOnDevicePostureChangedListener).onDevicePostureChanged(
+ mDevicePostureCaptor.capture());
+ clearInvocations(mOnDevicePostureChangedListener);
+
+ int differentDevicePosture = mDevicePostureCaptor.getValue() + 1;
+ mDevicePostureController.onDevicePostureChanged(differentDevicePosture);
+
+ verify(mOnDevicePostureChangedListener, times(1))
+ .onDevicePostureChanged(differentDevicePosture);
+ }
+
+ @Test
+ public void onDevicePostureChanged_samePosture_doesNotCallbackListener() {
+ mDevicePostureController.registerOnDevicePostureChangedListener(
+ mOnDevicePostureChangedListener);
+ verify(mOnDevicePostureChangedListener).onDevicePostureChanged(
+ mDevicePostureCaptor.capture());
+ clearInvocations(mOnDevicePostureChangedListener);
+
+ int sameDevicePosture = mDevicePostureCaptor.getValue();
+ mDevicePostureController.onDevicePostureChanged(sameDevicePosture);
+
+ verifyZeroInteractions(mOnDevicePostureChangedListener);
+ }
+}
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index cbebae9ed438..ecf6cfc05444 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -464,7 +464,7 @@ bool Bitmap::compress(JavaCompressFormat format, int32_t quality, SkWStream* str
SkBitmap baseBitmap = getSkBitmap();
SkBitmap gainmapBitmap = gainmap()->bitmap->getSkBitmap();
SkJpegEncoder::Options options{.fQuality = quality};
- return SkJpegGainmapEncoder::EncodeJpegR(stream, baseBitmap.pixmap(), options,
+ return SkJpegGainmapEncoder::EncodeHDRGM(stream, baseBitmap.pixmap(), options,
gainmapBitmap.pixmap(), options, gainmap()->info);
}
#endif
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index 40a4858d30ba..d2b21ae19162 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -849,7 +849,7 @@ public class RingtoneManager {
if (ringtoneUri != null) {
final Uri cacheUri = getCacheForType(type, context.getUserId());
try (InputStream in = openRingtone(context, ringtoneUri);
- OutputStream out = resolver.openOutputStream(cacheUri)) {
+ OutputStream out = resolver.openOutputStream(cacheUri, "wt")) {
FileUtils.copy(in, out);
} catch (IOException e) {
Log.w(TAG, "Failed to cache ringtone: " + e);
diff --git a/media/java/android/media/tv/tuner/filter/MediaEvent.java b/media/java/android/media/tv/tuner/filter/MediaEvent.java
index 8f2e7b573b09..4676dffb727f 100644
--- a/media/java/android/media/tv/tuner/filter/MediaEvent.java
+++ b/media/java/android/media/tv/tuner/filter/MediaEvent.java
@@ -224,6 +224,10 @@ public class MediaEvent extends FilterEvent {
/**
* Gets audio presentations.
+ *
+ * <p>The audio presentation order matters. As specified in ETSI EN 300 468 V1.17.1, all the
+ * audio programme components corresponding to the first audio preselection in the loop are
+ * contained in the main NGA stream.
*/
@NonNull
public List<AudioPresentation> getAudioPresentations() {
diff --git a/media/tests/MediaFrameworkTest/AndroidManifest.xml b/media/tests/MediaFrameworkTest/AndroidManifest.xml
index 41ac285e49f5..e88655894156 100644
--- a/media/tests/MediaFrameworkTest/AndroidManifest.xml
+++ b/media/tests/MediaFrameworkTest/AndroidManifest.xml
@@ -41,7 +41,6 @@
</activity>
<activity android:label="Camera2CtsActivity"
android:name="Camera2SurfaceViewActivity"
- android:screenOrientation="landscape"
android:configChanges="keyboardHidden|orientation|screenSize"
android:showWhenLocked="true"
android:turnScreenOn="true"
diff --git a/packages/CarrierDefaultApp/res/values/strings.xml b/packages/CarrierDefaultApp/res/values/strings.xml
index 6e2927d6e80e..720e46dc9b8c 100644
--- a/packages/CarrierDefaultApp/res/values/strings.xml
+++ b/packages/CarrierDefaultApp/res/values/strings.xml
@@ -17,9 +17,9 @@
<!-- Telephony notification channel name for performance boost notifications. -->
<string name="performance_boost_notification_channel">Performance boost</string>
<!-- Notification title text for the performance boost notification. -->
- <string name="performance_boost_notification_title">Improve your 5G experience</string>
+ <string name="performance_boost_notification_title">Improve your app experience</string>
<!-- Notification detail text for the performance boost notification. -->
- <string name="performance_boost_notification_detail">%1$s recommends buying a performance boost plan. Tap to buy through %2$s.</string>
+ <string name="performance_boost_notification_detail">Tap to visit %s\'s website and learn more.</string>
<!-- Notification button text to cancel the performance boost notification. -->
<string name="performance_boost_notification_button_not_now">Not now</string>
<!-- Notification button text to manage the performance boost notification. -->
diff --git a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiver.java b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiver.java
index d4ce5f5471cb..23b976638eef 100644
--- a/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiver.java
+++ b/packages/CarrierDefaultApp/src/com/android/carrierdefaultapp/SlicePurchaseBroadcastReceiver.java
@@ -317,7 +317,7 @@ public class SlicePurchaseBroadcastReceiver extends BroadcastReceiver{
.setContentTitle(res.getString(
R.string.performance_boost_notification_title))
.setContentText(String.format(res.getString(
- R.string.performance_boost_notification_detail), carrier, carrier))
+ R.string.performance_boost_notification_detail), carrier))
.setSmallIcon(R.drawable.ic_performance_boost)
.setContentIntent(createContentIntent(context, intent, 1))
.setDeleteIntent(intent.getParcelableExtra(
diff --git a/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java b/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
index 95b49a8ef335..73f87302dd05 100644
--- a/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
+++ b/packages/LocalTransport/src/com/android/localtransport/LocalTransport.java
@@ -21,7 +21,6 @@ import android.app.backup.BackupAgent;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
import android.app.backup.BackupManagerMonitor;
-import android.app.backup.BackupRestoreEventLogger;
import android.app.backup.BackupRestoreEventLogger.DataTypeResult;
import android.app.backup.BackupTransport;
import android.app.backup.RestoreDescription;
@@ -48,6 +47,7 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
/**
@@ -915,6 +915,7 @@ public class LocalTransport extends BackupTransport {
Log.i(TAG, "\tdataType: " + result.getDataType());
Log.i(TAG, "\tsuccessCount: " + result.getSuccessCount());
Log.i(TAG, "\tfailCount: " + result.getFailCount());
+ Log.i(TAG, "\tmetadataHash: " + Arrays.toString(result.getMetadataHash()));
if (!result.getErrors().isEmpty()) {
Log.i(TAG, "\terrors {");
diff --git a/packages/PackageInstaller/AndroidManifest.xml b/packages/PackageInstaller/AndroidManifest.xml
index 45c4f88fa588..9ee6fbde60a6 100644
--- a/packages/PackageInstaller/AndroidManifest.xml
+++ b/packages/PackageInstaller/AndroidManifest.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
package="com.android.packageinstaller">
<original-package android:name="com.android.packageinstaller" />
@@ -149,6 +150,9 @@
android:authorities="com.google.android.packageinstaller.wear.provider"
android:grantUriPermissions="true"
android:exported="false" />
+
+ <receiver android:name="androidx.profileinstaller.ProfileInstallReceiver"
+ tools:node="remove" />
</application>
</manifest>
diff --git a/packages/PackageInstaller/res/values/strings.xml b/packages/PackageInstaller/res/values/strings.xml
index ab680b063d6d..6669e358eb08 100644
--- a/packages/PackageInstaller/res/values/strings.xml
+++ b/packages/PackageInstaller/res/values/strings.xml
@@ -38,9 +38,6 @@
<!-- Message for updating an existing app [CHAR LIMIT=NONE] -->
<string name="install_confirm_question_update">Do you want to update this app?</string>
<!-- TODO(b/244413073) Revise the description after getting UX input and UXR on this. -->
- <!-- Message for updating an existing app when updating owner changed [DO NOT TRANSLATE][CHAR LIMIT=NONE] -->
- <string name="install_confirm_question_update_owner_changed">Updates to this app are currently managed by <xliff:g id="existing_update_owner">%1$s</xliff:g>.\n\nBy updating, you\'ll get future updates from <xliff:g id="new_update_owner">%2$s</xliff:g> instead.</string>
- <!-- TODO(b/244413073) Revise the description after getting UX input and UXR on this. -->
<!-- Message for updating an existing app with update owner reminder [DO NOT TRANSLATE][CHAR LIMIT=NONE] -->
<string name="install_confirm_question_update_owner_reminder">Updates to this app are currently managed by <xliff:g id="existing_update_owner">%1$s</xliff:g>.\n\nDo you want to install this update from <xliff:g id="new_update_owner">%2$s</xliff:g>?</string>
<!-- [CHAR LIMIT=100] -->
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
index fd41f5fb08a5..d41cfbc2d4ce 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/PackageInstallerActivity.java
@@ -144,18 +144,11 @@ public class PackageInstallerActivity extends AlertActivity {
final CharSequence existingUpdateOwnerLabel = getExistingUpdateOwnerLabel();
final CharSequence requestedUpdateOwnerLabel = getApplicationLabel(mCallingPackage);
- if (!TextUtils.isEmpty(existingUpdateOwnerLabel)) {
- if (mPendingUserActionReason == PackageInstaller.REASON_OWNERSHIP_CHANGED) {
- viewToEnable.setText(
- getString(R.string.install_confirm_question_update_owner_changed,
- existingUpdateOwnerLabel, requestedUpdateOwnerLabel));
- } else if (mPendingUserActionReason == PackageInstaller.REASON_REMIND_OWNERSHIP
- || mPendingUserActionReason
- == PackageInstaller.REASON_CONFIRM_PACKAGE_CHANGE) {
- viewToEnable.setText(
- getString(R.string.install_confirm_question_update_owner_reminder,
- existingUpdateOwnerLabel, requestedUpdateOwnerLabel));
- }
+ if (!TextUtils.isEmpty(existingUpdateOwnerLabel)
+ && mPendingUserActionReason == PackageInstaller.REASON_REMIND_OWNERSHIP) {
+ viewToEnable.setText(
+ getString(R.string.install_confirm_question_update_owner_reminder,
+ existingUpdateOwnerLabel, requestedUpdateOwnerLabel));
}
mOk.setText(R.string.update);
diff --git a/packages/SettingsLib/ActionBarShadow/Android.bp b/packages/SettingsLib/ActionBarShadow/Android.bp
index 9b0e04444d50..bf4c8587722a 100644
--- a/packages/SettingsLib/ActionBarShadow/Android.bp
+++ b/packages/SettingsLib/ActionBarShadow/Android.bp
@@ -22,7 +22,8 @@ android_library {
min_sdk_version: "28",
apex_available: [
"//apex_available:platform",
- "com.android.permission",
"com.android.adservices",
+ "com.android.extservices",
+ "com.android.permission",
],
}
diff --git a/packages/SettingsLib/CollapsingToolbarBaseActivity/Android.bp b/packages/SettingsLib/CollapsingToolbarBaseActivity/Android.bp
index 6330848f6316..e9000a8e4b0f 100644
--- a/packages/SettingsLib/CollapsingToolbarBaseActivity/Android.bp
+++ b/packages/SettingsLib/CollapsingToolbarBaseActivity/Android.bp
@@ -27,6 +27,7 @@ android_library {
"//apex_available:platform",
"com.android.adservices",
"com.android.cellbroadcast",
+ "com.android.extservices",
"com.android.permission",
"com.android.healthfitness",
],
diff --git a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
index 3b902757c43e..37ae2d45e614 100644
--- a/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
+++ b/packages/SettingsLib/IllustrationPreference/src/com/android/settingslib/widget/IllustrationPreference.java
@@ -55,6 +55,7 @@ public class IllustrationPreference extends Preference {
private int mMaxHeight = SIZE_UNSPECIFIED;
private int mImageResId;
+ private boolean mCacheComposition = true;
private boolean mIsAutoScale;
private Uri mImageUri;
private Drawable mImageDrawable;
@@ -133,6 +134,7 @@ public class IllustrationPreference extends Preference {
lp.width = screenWidth < screenHeight ? screenWidth : screenHeight;
illustrationFrame.setLayoutParams(lp);
+ illustrationView.setCacheComposition(mCacheComposition);
handleImageWithAnimation(illustrationView);
handleImageFrameMaxHeight(backgroundView, illustrationView);
@@ -427,6 +429,8 @@ public class IllustrationPreference extends Preference {
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.LottieAnimationView, 0 /*defStyleAttr*/, 0 /*defStyleRes*/);
mImageResId = a.getResourceId(R.styleable.LottieAnimationView_lottie_rawRes, 0);
+ mCacheComposition = a.getBoolean(
+ R.styleable.LottieAnimationView_lottie_cacheComposition, true);
a = context.obtainStyledAttributes(attrs,
R.styleable.IllustrationPreference, 0 /*defStyleAttr*/, 0 /*defStyleRes*/);
diff --git a/packages/SettingsLib/MainSwitchPreference/Android.bp b/packages/SettingsLib/MainSwitchPreference/Android.bp
index 825e6acdf1f9..33aa985b32e8 100644
--- a/packages/SettingsLib/MainSwitchPreference/Android.bp
+++ b/packages/SettingsLib/MainSwitchPreference/Android.bp
@@ -25,6 +25,7 @@ android_library {
"//apex_available:platform",
"com.android.adservices",
"com.android.cellbroadcast",
+ "com.android.extservices",
"com.android.healthfitness",
],
}
diff --git a/packages/SettingsLib/SettingsTheme/Android.bp b/packages/SettingsLib/SettingsTheme/Android.bp
index 09691f19e9ce..d26ad1c77f1b 100644
--- a/packages/SettingsLib/SettingsTheme/Android.bp
+++ b/packages/SettingsLib/SettingsTheme/Android.bp
@@ -9,18 +9,14 @@ package {
android_library {
name: "SettingsLibSettingsTheme",
-
resource_dirs: ["res"],
-
- static_libs: [
- "androidx.preference_preference",
- ],
-
+ static_libs: ["androidx.preference_preference"],
sdk_version: "system_current",
min_sdk_version: "21",
apex_available: [
"//apex_available:platform",
"com.android.cellbroadcast",
+ "com.android.extservices",
"com.android.permission",
"com.android.adservices",
"com.android.healthfitness",
diff --git a/packages/SettingsLib/SettingsTransition/Android.bp b/packages/SettingsLib/SettingsTransition/Android.bp
index 7f9014cecc69..0f9f7816d1dd 100644
--- a/packages/SettingsLib/SettingsTransition/Android.bp
+++ b/packages/SettingsLib/SettingsTransition/Android.bp
@@ -22,6 +22,7 @@ android_library {
"//apex_available:platform",
"com.android.adservices",
"com.android.cellbroadcast",
+ "com.android.extservices",
"com.android.permission",
"com.android.healthfitness",
],
diff --git a/packages/SettingsLib/Utils/Android.bp b/packages/SettingsLib/Utils/Android.bp
index 644e990bf9d9..33ba64ac2cb7 100644
--- a/packages/SettingsLib/Utils/Android.bp
+++ b/packages/SettingsLib/Utils/Android.bp
@@ -24,8 +24,9 @@ android_library {
"//apex_available:platform",
"com.android.adservices",
- "com.android.permission",
"com.android.cellbroadcast",
+ "com.android.extservices",
"com.android.healthfitness",
+ "com.android.permission",
],
}
diff --git a/packages/SettingsLib/res/values/styles.xml b/packages/SettingsLib/res/values/styles.xml
index 5a9e780df8e9..cc60382b48f9 100644
--- a/packages/SettingsLib/res/values/styles.xml
+++ b/packages/SettingsLib/res/values/styles.xml
@@ -14,7 +14,7 @@
~ limitations under the License
-->
-<resources>
+<resources xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
<style name="TextAppearanceSmall">
<item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
</style>
@@ -73,7 +73,7 @@
</style>
<style name="TextAppearanceBroadcastDialogButton" parent="@android:TextAppearance.DeviceDefault.Headline">
- <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:textColor">?androidprv:attr/textColorOnAccent</item>
<item name="android:textSize">@dimen/broadcast_dialog_btn_text_size</item>
</style>
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 0f671249596c..82ca63d1a801 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -819,6 +819,9 @@
<!-- Permission required for CTS test - ActivityCaptureCallbackTests -->
<uses-permission android:name="android.permission.DETECT_SCREEN_CAPTURE" />
+ <!-- Permission required for CTS test - CtsTelephonyProviderTestCases -->
+ <uses-permission android:name="android.permission.WRITE_APN_SETTINGS" />
+
<application android:label="@string/app_label"
android:theme="@android:style/Theme.DeviceDefault.DayNight"
android:defaultToDeviceProtectedStorage="true"
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
index 774255be4007..b98b92219c33 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
@@ -35,8 +35,7 @@ interface LaunchableView {
*
* Note that calls to [View.setTransitionVisibility] shouldn't be blocked.
*
- * @param block whether we should block/postpone all calls to `setVisibility` and
- * `setTransitionVisibility`.
+ * @param block whether we should block/postpone all calls to `setVisibility`.
*/
fun setShouldBlockVisibilityChanges(block: Boolean)
}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableImageView.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableImageView.kt
index a1d9d90523eb..e42b589f05cf 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableImageView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableImageView.kt
@@ -24,7 +24,7 @@ import com.android.systemui.animation.LaunchableView
import com.android.systemui.animation.LaunchableViewDelegate
/** An [ImageView] that also implements [LaunchableView]. */
-class LaunchableImageView : ImageView, LaunchableView {
+open class LaunchableImageView : ImageView, LaunchableView {
private val delegate =
LaunchableViewDelegate(
this,
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableTextView.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableTextView.kt
index 286996dcaeaa..147669528c5e 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableTextView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/view/LaunchableTextView.kt
@@ -24,7 +24,7 @@ import com.android.systemui.animation.LaunchableView
import com.android.systemui.animation.LaunchableViewDelegate
/** A [TextView] that also implements [LaunchableView]. */
-class LaunchableTextView : TextView, LaunchableView {
+open class LaunchableTextView : TextView, LaunchableView {
private val delegate =
LaunchableViewDelegate(
this,
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt
index 442c6fadb7c1..bd91c65ecc6e 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleAnimation.kt
@@ -68,7 +68,7 @@ class RippleAnimation(private val config: RippleAnimationConfig) {
private fun applyConfigToShader() {
with(rippleShader) {
setCenter(config.centerX, config.centerY)
- setMaxSize(config.maxWidth, config.maxHeight)
+ rippleSize.setMaxSize(config.maxWidth, config.maxHeight)
pixelDensity = config.pixelDensity
color = ColorUtils.setAlphaComponent(config.color, config.opacity)
sparkleStrength = config.sparkleStrength
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
index 61ca90a297fe..0b842ad5331c 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleShader.kt
@@ -15,9 +15,10 @@
*/
package com.android.systemui.surfaceeffects.ripple
-import android.graphics.PointF
import android.graphics.RuntimeShader
+import android.util.Log
import android.util.MathUtils
+import androidx.annotation.VisibleForTesting
import com.android.systemui.animation.Interpolators
import com.android.systemui.surfaceeffects.shaderutil.SdfShaderLibrary
import com.android.systemui.surfaceeffects.shaderutil.ShaderUtilLibrary
@@ -44,6 +45,8 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) :
}
// language=AGSL
companion object {
+ private val TAG = RippleShader::class.simpleName
+
// Default fade in/ out values. The value range is [0,1].
const val DEFAULT_FADE_IN_START = 0f
const val DEFAULT_FADE_OUT_END = 1f
@@ -99,7 +102,7 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) :
vec4 main(vec2 p) {
float sparkleRing = soften(roundedBoxRing(p-in_center, in_size, in_cornerRadius,
in_thickness), in_blur);
- float inside = soften(sdRoundedBox(p-in_center, in_size * 1.2, in_cornerRadius),
+ float inside = soften(sdRoundedBox(p-in_center, in_size * 1.25, in_cornerRadius),
in_blur);
float sparkle = sparkles(p - mod(p, in_pixelDensity * 0.8), in_time * 0.00175)
* (1.-sparkleRing) * in_fadeSparkle;
@@ -184,12 +187,17 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) :
setFloatUniform("in_center", x, y)
}
- /** Max width of the ripple. */
- private var maxSize: PointF = PointF()
- fun setMaxSize(width: Float, height: Float) {
- maxSize.x = width
- maxSize.y = height
- }
+ /**
+ * Blur multipliers for the ripple.
+ *
+ * <p>It interpolates from [blurStart] to [blurEnd] based on the [progress]. Increase number to
+ * add more blur.
+ */
+ var blurStart: Float = 1.25f
+ var blurEnd: Float = 0.5f
+
+ /** Size of the ripple. */
+ val rippleSize = RippleSize()
/**
* Linear progress of the ripple. Float value between [0, 1].
@@ -209,15 +217,19 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) :
/** Progress with Standard easing curve applied. */
private var progress: Float = 0.0f
set(value) {
- currentWidth = maxSize.x * value
- currentHeight = maxSize.y * value
- setFloatUniform("in_size", currentWidth, currentHeight)
+ field = value
+
+ rippleSize.update(value)
- setFloatUniform("in_thickness", maxSize.y * value * 0.5f)
- // radius should not exceed width and height values.
- setFloatUniform("in_cornerRadius", Math.min(maxSize.x, maxSize.y) * value)
+ setFloatUniform("in_size", rippleSize.currentWidth, rippleSize.currentHeight)
+ setFloatUniform("in_thickness", rippleSize.currentHeight * 0.5f)
+ // Corner radius is always max of the min between the current width and height.
+ setFloatUniform(
+ "in_cornerRadius",
+ Math.min(rippleSize.currentWidth, rippleSize.currentHeight)
+ )
- setFloatUniform("in_blur", MathUtils.lerp(1.25f, 0.5f, value))
+ setFloatUniform("in_blur", MathUtils.lerp(blurStart, blurEnd, value))
}
/** Play time since the start of the effect. */
@@ -264,12 +276,6 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) :
setFloatUniform("in_pixelDensity", value)
}
- var currentWidth: Float = 0f
- private set
-
- var currentHeight: Float = 0f
- private set
-
/** Parameters that are used to fade in/ out of the sparkle ring. */
val sparkleRingFadeParams =
FadeParams(
@@ -342,4 +348,102 @@ class RippleShader(rippleShape: RippleShape = RippleShape.CIRCLE) :
/** The endpoint of the fade out, given that the animation goes from 0 to 1. */
var fadeOutEnd: Float = DEFAULT_FADE_OUT_END,
)
+
+ /**
+ * Desired size of the ripple at a point t in [progress].
+ *
+ * <p>Note that [progress] is curved and normalized. Below is an example usage:
+ * SizeAtProgress(t= 0f, width= 0f, height= 0f), SizeAtProgress(t= 0.2f, width= 500f, height=
+ * 700f), SizeAtProgress(t= 1f, width= 100f, height= 300f)
+ *
+ * <p>For simple ripple effects, you will want to use [setMaxSize] as it is translated into:
+ * SizeAtProgress(t= 0f, width= 0f, height= 0f), SizeAtProgress(t= 1f, width= maxWidth, height=
+ * maxHeight)
+ */
+ data class SizeAtProgress(
+ /** Time t in [0,1] progress range. */
+ var t: Float,
+ /** Target width size of the ripple at time [t]. */
+ var width: Float,
+ /** Target height size of the ripple at time [t]. */
+ var height: Float
+ )
+
+ /** Updates and stores the ripple size. */
+ inner class RippleSize {
+ @VisibleForTesting var sizes = mutableListOf<SizeAtProgress>()
+ @VisibleForTesting var currentSizeIndex = 0
+ @VisibleForTesting val initialSize = SizeAtProgress(0f, 0f, 0f)
+
+ var currentWidth: Float = 0f
+ private set
+ var currentHeight: Float = 0f
+ private set
+
+ /**
+ * Sets the max size of the ripple.
+ *
+ * <p>Use this if the ripple shape simply changes linearly.
+ */
+ fun setMaxSize(width: Float, height: Float) {
+ setSizeAtProgresses(initialSize, SizeAtProgress(1f, width, height))
+ }
+
+ /**
+ * Sets the list of [sizes].
+ *
+ * <p>Note that setting this clears the existing sizes.
+ */
+ fun setSizeAtProgresses(vararg sizes: SizeAtProgress) {
+ // Reset everything.
+ this.sizes.clear()
+ currentSizeIndex = 0
+
+ this.sizes.addAll(sizes)
+ this.sizes.sortBy { it.t }
+ }
+
+ /**
+ * Updates the current ripple size based on the progress.
+ *
+ * <p>Should be called when progress updates.
+ */
+ fun update(progress: Float) {
+ val targetIndex = updateTargetIndex(progress)
+ val prevIndex = Math.max(targetIndex - 1, 0)
+
+ val targetSize = sizes[targetIndex]
+ val prevSize = sizes[prevIndex]
+
+ val subProgress = subProgress(prevSize.t, targetSize.t, progress)
+
+ currentWidth = targetSize.width * subProgress + prevSize.width
+ currentHeight = targetSize.height * subProgress + prevSize.height
+ }
+
+ private fun updateTargetIndex(progress: Float): Int {
+ if (sizes.isEmpty()) {
+ // It could be empty on init.
+ if (progress > 0f) {
+ Log.e(
+ TAG,
+ "Did you forget to set the ripple size? Use [setMaxSize] or " +
+ "[setSizeAtProgresses] before playing the animation."
+ )
+ }
+ // If there's no size is set, we set everything to 0 and return early.
+ setSizeAtProgresses(initialSize)
+ return currentSizeIndex
+ }
+
+ var candidate = sizes[currentSizeIndex]
+
+ while (progress > candidate.t) {
+ currentSizeIndex = Math.min(currentSizeIndex + 1, sizes.size - 1)
+ candidate = sizes[currentSizeIndex]
+ }
+
+ return currentSizeIndex
+ }
+ }
}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
index 3c9328c82b83..4c7c43548016 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/ripple/RippleView.kt
@@ -45,12 +45,8 @@ open class RippleView(context: Context?, attrs: AttributeSet?) : View(context, a
var duration: Long = 1750
- private var maxWidth: Float = 0.0f
- private var maxHeight: Float = 0.0f
fun setMaxSize(maxWidth: Float, maxHeight: Float) {
- this.maxWidth = maxWidth
- this.maxHeight = maxHeight
- rippleShader.setMaxSize(maxWidth, maxHeight)
+ rippleShader.rippleSize.setMaxSize(maxWidth, maxHeight)
}
private var centerX: Float = 0.0f
@@ -84,6 +80,106 @@ open class RippleView(context: Context?, attrs: AttributeSet?) : View(context, a
ripplePaint.shader = rippleShader
}
+ /**
+ * Sets the fade parameters for the base ring.
+ *
+ * <p>Base ring indicates a blurred ring below the sparkle ring. See
+ * [RippleShader.baseRingFadeParams].
+ */
+ @JvmOverloads
+ fun setBaseRingFadeParams(
+ fadeInStart: Float = rippleShader.baseRingFadeParams.fadeInStart,
+ fadeInEnd: Float = rippleShader.baseRingFadeParams.fadeInEnd,
+ fadeOutStart: Float = rippleShader.baseRingFadeParams.fadeOutStart,
+ fadeOutEnd: Float = rippleShader.baseRingFadeParams.fadeOutEnd
+ ) {
+ setFadeParams(
+ rippleShader.baseRingFadeParams,
+ fadeInStart,
+ fadeInEnd,
+ fadeOutStart,
+ fadeOutEnd
+ )
+ }
+
+ /**
+ * Sets the fade parameters for the sparkle ring.
+ *
+ * <p>Sparkle ring refers to the ring that's drawn on top of the base ring. See
+ * [RippleShader.sparkleRingFadeParams].
+ */
+ @JvmOverloads
+ fun setSparkleRingFadeParams(
+ fadeInStart: Float = rippleShader.sparkleRingFadeParams.fadeInStart,
+ fadeInEnd: Float = rippleShader.sparkleRingFadeParams.fadeInEnd,
+ fadeOutStart: Float = rippleShader.sparkleRingFadeParams.fadeOutStart,
+ fadeOutEnd: Float = rippleShader.sparkleRingFadeParams.fadeOutEnd
+ ) {
+ setFadeParams(
+ rippleShader.sparkleRingFadeParams,
+ fadeInStart,
+ fadeInEnd,
+ fadeOutStart,
+ fadeOutEnd
+ )
+ }
+
+ /**
+ * Sets the fade parameters for the center fill.
+ *
+ * <p>One common use case is set all the params to 1, which completely removes the center fill.
+ * See [RippleShader.centerFillFadeParams].
+ */
+ @JvmOverloads
+ fun setCenterFillFadeParams(
+ fadeInStart: Float = rippleShader.centerFillFadeParams.fadeInStart,
+ fadeInEnd: Float = rippleShader.centerFillFadeParams.fadeInEnd,
+ fadeOutStart: Float = rippleShader.centerFillFadeParams.fadeOutStart,
+ fadeOutEnd: Float = rippleShader.centerFillFadeParams.fadeOutEnd
+ ) {
+ setFadeParams(
+ rippleShader.centerFillFadeParams,
+ fadeInStart,
+ fadeInEnd,
+ fadeOutStart,
+ fadeOutEnd
+ )
+ }
+
+ private fun setFadeParams(
+ fadeParams: RippleShader.FadeParams,
+ fadeInStart: Float,
+ fadeInEnd: Float,
+ fadeOutStart: Float,
+ fadeOutEnd: Float
+ ) {
+ with(fadeParams) {
+ this.fadeInStart = fadeInStart
+ this.fadeInEnd = fadeInEnd
+ this.fadeOutStart = fadeOutStart
+ this.fadeOutEnd = fadeOutEnd
+ }
+ }
+
+ /**
+ * Sets blur multiplier at start and end of the progress.
+ *
+ * <p>It interpolates between [start] and [end]. No need to set it if using default blur.
+ */
+ fun setBlur(start: Float, end: Float) {
+ rippleShader.blurStart = start
+ rippleShader.blurEnd = end
+ }
+
+ /**
+ * Sets the list of [RippleShader.SizeAtProgress].
+ *
+ * <p>Note that this clears the list before it sets with the new data.
+ */
+ fun setSizeAtProgresses(vararg targetSizes: RippleShader.SizeAtProgress) {
+ rippleShader.rippleSize.setSizeAtProgresses(*targetSizes)
+ }
+
@JvmOverloads
fun startRipple(onAnimationEnd: Runnable? = null) {
if (animator.isRunning) {
@@ -133,13 +229,13 @@ open class RippleView(context: Context?, attrs: AttributeSet?) : View(context, a
}
// To reduce overdraw, we mask the effect to a circle or a rectangle that's bigger than the
// active effect area. Values here should be kept in sync with the animation implementation
- // in the ripple shader. (Twice bigger)
+ // in the ripple shader.
if (rippleShape == RippleShape.CIRCLE) {
- val maskRadius = rippleShader.currentWidth
+ val maskRadius = rippleShader.rippleSize.currentWidth
canvas.drawCircle(centerX, centerY, maskRadius, ripplePaint)
- } else {
- val maskWidth = rippleShader.currentWidth * 2
- val maskHeight = rippleShader.currentHeight * 2
+ } else if (rippleShape == RippleShape.ELLIPSE) {
+ val maskWidth = rippleShader.rippleSize.currentWidth * 2
+ val maskHeight = rippleShader.rippleSize.currentHeight * 2
canvas.drawRect(
/* left= */ centerX - maskWidth,
/* top= */ centerY - maskHeight,
@@ -147,6 +243,10 @@ open class RippleView(context: Context?, attrs: AttributeSet?) : View(context, a
/* bottom= */ centerY + maskHeight,
ripplePaint
)
+ } else { // RippleShape.RoundedBox
+ // No masking for the rounded box, as it has more blur which requires larger bounds.
+ // Masking creates sharp bounds even when the masking is 4 times bigger.
+ canvas.drawPaint(ripplePaint)
}
}
}
diff --git a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/SdfShaderLibrary.kt b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/SdfShaderLibrary.kt
index 8b2f46648fef..78898932249b 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/SdfShaderLibrary.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/surfaceeffects/shaderutil/SdfShaderLibrary.kt
@@ -50,9 +50,9 @@ class SdfShaderLibrary {
float roundedBoxRing(vec2 p, vec2 size, float cornerRadius,
float borderThickness) {
- float outerRoundBox = sdRoundedBox(p, size, cornerRadius);
- float innerRoundBox = sdRoundedBox(p, size - vec2(borderThickness),
- cornerRadius - borderThickness);
+ float outerRoundBox = sdRoundedBox(p, size + vec2(borderThickness),
+ cornerRadius + borderThickness);
+ float innerRoundBox = sdRoundedBox(p, size, cornerRadius);
return subtract(outerRoundBox, innerRoundBox);
}
"""
@@ -69,10 +69,13 @@ class SdfShaderLibrary {
vec2 u = wh*p, v = wh*wh;
- float U1 = u.y/2.0; float U5 = 4.0*U1;
- float U2 = v.y-v.x; float U6 = 6.0*U1;
- float U3 = u.x-U2; float U7 = 3.0*U3;
+ float U1 = u.y/2.0;
+ float U2 = v.y-v.x;
+ float U3 = u.x-U2;
float U4 = u.x+U2;
+ float U5 = 4.0*U1;
+ float U6 = 6.0*U1;
+ float U7 = 3.0*U3;
float t = 0.5;
for (int i = 0; i < 3; i ++) {
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
index 1c2f38beb867..ab4aca569bd4 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockProviderPlugin.kt
@@ -113,7 +113,7 @@ interface ClockEvents {
fun onColorPaletteChanged(resources: Resources) {}
/** Call whenever the weather data should update */
- fun onWeatherDataChanged(data: Weather) {}
+ fun onWeatherDataChanged(data: WeatherData) {}
}
/** Methods which trigger various clock animations */
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/Weather.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/Weather.kt
deleted file mode 100644
index 302f17556bc7..000000000000
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/Weather.kt
+++ /dev/null
@@ -1,85 +0,0 @@
-package com.android.systemui.plugins
-
-import android.os.Bundle
-
-class Weather(val conditions: WeatherStateIcon, val temperature: Int, val isCelsius: Boolean) {
- companion object {
- private const val TAG = "Weather"
- private const val WEATHER_STATE_ICON_KEY = "weather_state_icon_extra_key"
- private const val TEMPERATURE_VALUE_KEY = "temperature_value_extra_key"
- private const val TEMPERATURE_UNIT_KEY = "temperature_unit_extra_key"
- private const val INVALID_TEMPERATURE = Int.MIN_VALUE
-
- fun fromBundle(extras: Bundle): Weather? {
- val icon =
- WeatherStateIcon.fromInt(
- extras.getInt(WEATHER_STATE_ICON_KEY, WeatherStateIcon.UNKNOWN_ICON.id)
- )
- if (icon == null || icon == WeatherStateIcon.UNKNOWN_ICON) {
- return null
- }
- val temperature = extras.getInt(TEMPERATURE_VALUE_KEY, INVALID_TEMPERATURE)
- if (temperature == INVALID_TEMPERATURE) {
- return null
- }
- return Weather(icon, temperature, extras.getBoolean(TEMPERATURE_UNIT_KEY))
- }
- }
-
- enum class WeatherStateIcon(val id: Int) {
- UNKNOWN_ICON(0),
-
- // Clear, day & night.
- SUNNY(1),
- CLEAR_NIGHT(2),
-
- // Mostly clear, day & night.
- MOSTLY_SUNNY(3),
- MOSTLY_CLEAR_NIGHT(4),
-
- // Partly cloudy, day & night.
- PARTLY_CLOUDY(5),
- PARTLY_CLOUDY_NIGHT(6),
-
- // Mostly cloudy, day & night.
- MOSTLY_CLOUDY_DAY(7),
- MOSTLY_CLOUDY_NIGHT(8),
- CLOUDY(9),
- HAZE_FOG_DUST_SMOKE(10),
- DRIZZLE(11),
- HEAVY_RAIN(12),
- SHOWERS_RAIN(13),
-
- // Scattered showers, day & night.
- SCATTERED_SHOWERS_DAY(14),
- SCATTERED_SHOWERS_NIGHT(15),
-
- // Isolated scattered thunderstorms, day & night.
- ISOLATED_SCATTERED_TSTORMS_DAY(16),
- ISOLATED_SCATTERED_TSTORMS_NIGHT(17),
- STRONG_TSTORMS(18),
- BLIZZARD(19),
- BLOWING_SNOW(20),
- FLURRIES(21),
- HEAVY_SNOW(22),
-
- // Scattered snow showers, day & night.
- SCATTERED_SNOW_SHOWERS_DAY(23),
- SCATTERED_SNOW_SHOWERS_NIGHT(24),
- SNOW_SHOWERS_SNOW(25),
- MIXED_RAIN_HAIL_RAIN_SLEET(26),
- SLEET_HAIL(27),
- TORNADO(28),
- TROPICAL_STORM_HURRICANE(29),
- WINDY_BREEZY(30),
- WINTRY_MIX_RAIN_SNOW(31);
-
- companion object {
- fun fromInt(value: Int) = values().firstOrNull { it.id == value }
- }
- }
-
- override fun toString(): String {
- return "$conditions $temperature${if (isCelsius) "C" else "F"}"
- }
-}
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/WeatherData.kt b/packages/SystemUI/plugin/src/com/android/systemui/plugins/WeatherData.kt
new file mode 100644
index 000000000000..52dfc55c105d
--- /dev/null
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/WeatherData.kt
@@ -0,0 +1,107 @@
+package com.android.systemui.plugins
+
+import android.os.Bundle
+import androidx.annotation.VisibleForTesting
+
+class WeatherData
+private constructor(
+ val description: String,
+ val state: WeatherStateIcon,
+ val useCelsius: Boolean,
+ val temperature: Int,
+) {
+ companion object {
+ private const val TAG = "WeatherData"
+ @VisibleForTesting const val DESCRIPTION_KEY = "description"
+ @VisibleForTesting const val STATE_KEY = "state"
+ @VisibleForTesting const val USE_CELSIUS_KEY = "use_celsius"
+ @VisibleForTesting const val TEMPERATURE_KEY = "temperature"
+ private const val INVALID_WEATHER_ICON_STATE = -1
+
+ fun fromBundle(extras: Bundle): WeatherData? {
+ val description = extras.getString(DESCRIPTION_KEY)
+ val state =
+ WeatherStateIcon.fromInt(extras.getInt(STATE_KEY, INVALID_WEATHER_ICON_STATE))
+ val temperature = readIntFromBundle(extras, TEMPERATURE_KEY)
+ return if (
+ description == null ||
+ state == null ||
+ !extras.containsKey(USE_CELSIUS_KEY) ||
+ temperature == null
+ )
+ null
+ else
+ WeatherData(
+ description = description,
+ state = state,
+ useCelsius = extras.getBoolean(USE_CELSIUS_KEY),
+ temperature = temperature
+ )
+ }
+
+ private fun readIntFromBundle(extras: Bundle, key: String): Int? =
+ try {
+ extras.getString(key).toInt()
+ } catch (e: Exception) {
+ null
+ }
+ }
+
+ enum class WeatherStateIcon(val id: Int) {
+ UNKNOWN_ICON(0),
+
+ // Clear, day & night.
+ SUNNY(1),
+ CLEAR_NIGHT(2),
+
+ // Mostly clear, day & night.
+ MOSTLY_SUNNY(3),
+ MOSTLY_CLEAR_NIGHT(4),
+
+ // Partly cloudy, day & night.
+ PARTLY_CLOUDY(5),
+ PARTLY_CLOUDY_NIGHT(6),
+
+ // Mostly cloudy, day & night.
+ MOSTLY_CLOUDY_DAY(7),
+ MOSTLY_CLOUDY_NIGHT(8),
+ CLOUDY(9),
+ HAZE_FOG_DUST_SMOKE(10),
+ DRIZZLE(11),
+ HEAVY_RAIN(12),
+ SHOWERS_RAIN(13),
+
+ // Scattered showers, day & night.
+ SCATTERED_SHOWERS_DAY(14),
+ SCATTERED_SHOWERS_NIGHT(15),
+
+ // Isolated scattered thunderstorms, day & night.
+ ISOLATED_SCATTERED_TSTORMS_DAY(16),
+ ISOLATED_SCATTERED_TSTORMS_NIGHT(17),
+ STRONG_TSTORMS(18),
+ BLIZZARD(19),
+ BLOWING_SNOW(20),
+ FLURRIES(21),
+ HEAVY_SNOW(22),
+
+ // Scattered snow showers, day & night.
+ SCATTERED_SNOW_SHOWERS_DAY(23),
+ SCATTERED_SNOW_SHOWERS_NIGHT(24),
+ SNOW_SHOWERS_SNOW(25),
+ MIXED_RAIN_HAIL_RAIN_SLEET(26),
+ SLEET_HAIL(27),
+ TORNADO(28),
+ TROPICAL_STORM_HURRICANE(29),
+ WINDY_BREEZY(30),
+ WINTRY_MIX_RAIN_SNOW(31);
+
+ companion object {
+ fun fromInt(value: Int) = values().firstOrNull { it.id == value }
+ }
+ }
+
+ override fun toString(): String {
+ val unit = if (useCelsius) "C" else "F"
+ return "$state (\"$description\") $temperature°$unit"
+ }
+}
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
index ca4028a666cc..f61df05eb8ca 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
@@ -54,7 +54,7 @@
androidprv:layout_constraintEnd_toEndOf="parent"
androidprv:layout_constraintStart_toStartOf="parent"
androidprv:layout_constraintBottom_toTopOf="@id/key1"
- androidprv:layout_constraintVertical_bias="1.0">
+ androidprv:layout_constraintVertical_bias="0.5">
<com.android.keyguard.PasswordTextView
android:id="@+id/pinEntry"
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index b9c7be204d9d..b6a78f56ec5f 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -71,7 +71,7 @@
<dimen name="password_dot_size">9dp</dimen>
<!-- The size of the shape in the PIN unlock method. -->
- <dimen name="password_shape_size">34dp</dimen>
+ <dimen name="password_shape_size">30dp</dimen>
<!-- The size of PIN text in the PIN unlock method. -->
<integer name="scaled_password_text_size">40</integer>
diff --git a/packages/SystemUI/res/drawable/pin_dot_avd.xml b/packages/SystemUI/res/drawable/pin_dot_avd.xml
index e0cd1fb2e129..1c162511411a 100644
--- a/packages/SystemUI/res/drawable/pin_dot_avd.xml
+++ b/packages/SystemUI/res/drawable/pin_dot_avd.xml
@@ -1,56 +1 @@
-<!--
- ~ 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.
- -->
-
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:aapt="http://schemas.android.com/aapt">
- <target android:name="time_group">
- <aapt:attr name="android:animation">
- <set android:ordering="together">
- <objectAnimator
- android:duration="500"
- android:propertyName="translateX"
- android:startOffset="0"
- android:valueFrom="0"
- android:valueTo="1"
- android:valueType="floatType" />
- </set>
- </aapt:attr>
- </target>
- <aapt:attr name="android:drawable">
- <vector
- android:width="60dp"
- android:height="61dp"
- android:viewportHeight="60"
- android:viewportWidth="60">
- <group android:name="_R_G">
- <group
- android:name="_R_G_L_0_G"
- android:translateX="43.237"
- android:translateY="38.112">
- <path
- android:name="_R_G_L_0_G_D_0_P_0"
- android:pathData=" M-13.24 -12.11 C-11.03,-12.11 -9.24,-10.32 -9.24,-8.11 C-9.24,-5.9 -11.03,-4.11 -13.24,-4.11 C-15.44,-4.11 -17.24,-5.9 -17.24,-8.11 C-17.24,-10.32 -15.44,-12.11 -13.24,-12.11c "
- android:strokeAlpha="1"
- android:strokeColor="#ffffff"
- android:strokeLineCap="round"
- android:strokeLineJoin="round"
- android:strokeWidth="2" />
- </group>
- </group>
- <group android:name="time_group" />
- </vector>
- </aapt:attr>
-</animated-vector> \ No newline at end of file
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="30dp" android:width="30dp" android:viewportHeight="30" android:viewportWidth="30"><group android:name="_R_G"><group android:name="_R_G_L_0_G" android:translateX="28.237000000000002" android:translateY="23.112000000000002"><path android:name="_R_G_L_0_G_D_0_P_0" android:strokeColor="#ffffff" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2" android:strokeAlpha="1" android:pathData=" M-13.24 -12.11 C-11.03,-12.11 -9.24,-10.32 -9.24,-8.11 C-9.24,-5.9 -11.03,-4.11 -13.24,-4.11 C-15.44,-4.11 -17.24,-5.9 -17.24,-8.11 C-17.24,-10.32 -15.44,-12.11 -13.24,-12.11c "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="500" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pin_dot_delete_avd.xml b/packages/SystemUI/res/drawable/pin_dot_delete_avd.xml
index 33f995cfb7b6..0f8703f731fc 100644
--- a/packages/SystemUI/res/drawable/pin_dot_delete_avd.xml
+++ b/packages/SystemUI/res/drawable/pin_dot_delete_avd.xml
@@ -1 +1 @@
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="60dp" android:width="60dp" android:viewportHeight="60" android:viewportWidth="60"><group android:name="_R_G"><group android:name="_R_G_L_0_G" android:translateX="43.54" android:translateY="38.54"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-13.54 -16.54 C-9.12,-16.54 -5.54,-12.96 -5.54,-8.54 C-5.54,-4.12 -9.12,-0.54 -13.54,-0.54 C-17.96,-0.54 -21.54,-4.12 -21.54,-8.54 C-21.54,-12.96 -17.96,-16.54 -13.54,-16.54c "/><path android:name="_R_G_L_0_G_D_1_P_0" android:strokeColor="#ffffff" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="0" android:strokeAlpha="1" android:pathData=" M-13.54 -16.54 C-9.12,-16.54 -5.54,-12.96 -5.54,-8.54 C-5.54,-4.12 -9.12,-0.54 -13.54,-0.54 C-17.96,-0.54 -21.54,-4.12 -21.54,-8.54 C-21.54,-12.96 -17.96,-16.54 -13.54,-16.54c "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="fillAlpha" android:duration="150" android:startOffset="0" android:valueFrom="1" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="fillAlpha" android:duration="200" android:startOffset="150" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="150" android:startOffset="0" android:valueFrom="M-13.54 -16.54 C-9.12,-16.54 -5.54,-12.96 -5.54,-8.54 C-5.54,-4.12 -9.12,-0.54 -13.54,-0.54 C-17.96,-0.54 -21.54,-4.12 -21.54,-8.54 C-21.54,-12.96 -17.96,-16.54 -13.54,-16.54c " android:valueTo="M-13.54 -11.54 C-11.88,-11.54 -10.54,-10.2 -10.54,-8.54 C-10.54,-6.88 -11.88,-5.54 -13.54,-5.54 C-15.2,-5.54 -16.54,-6.88 -16.54,-8.54 C-16.54,-10.2 -15.2,-11.54 -13.54,-11.54c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="200" android:startOffset="150" android:valueFrom="M-13.54 -11.54 C-11.88,-11.54 -10.54,-10.2 -10.54,-8.54 C-10.54,-6.88 -11.88,-5.54 -13.54,-5.54 C-15.2,-5.54 -16.54,-6.88 -16.54,-8.54 C-16.54,-10.2 -15.2,-11.54 -13.54,-11.54c " android:valueTo="M-13.54 -12.54 C-11.33,-12.54 -9.54,-10.75 -9.54,-8.54 C-9.54,-6.33 -11.33,-4.54 -13.54,-4.54 C-15.75,-4.54 -17.54,-6.33 -17.54,-8.54 C-17.54,-10.75 -15.75,-12.54 -13.54,-12.54c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_1_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="strokeWidth" android:duration="150" android:startOffset="0" android:valueFrom="0" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="strokeWidth" android:duration="50" android:startOffset="150" android:valueFrom="0" android:valueTo="2" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_1_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="150" android:startOffset="0" android:valueFrom="M-13.54 -16.54 C-9.12,-16.54 -5.54,-12.96 -5.54,-8.54 C-5.54,-4.12 -9.12,-0.54 -13.54,-0.54 C-17.96,-0.54 -21.54,-4.12 -21.54,-8.54 C-21.54,-12.96 -17.96,-16.54 -13.54,-16.54c " android:valueTo="M-13.54 -11.54 C-11.88,-11.54 -10.54,-10.2 -10.54,-8.54 C-10.54,-6.88 -11.88,-5.54 -13.54,-5.54 C-15.2,-5.54 -16.54,-6.88 -16.54,-8.54 C-16.54,-10.2 -15.2,-11.54 -13.54,-11.54c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="200" android:startOffset="150" android:valueFrom="M-13.54 -11.54 C-11.88,-11.54 -10.54,-10.2 -10.54,-8.54 C-10.54,-6.88 -11.88,-5.54 -13.54,-5.54 C-15.2,-5.54 -16.54,-6.88 -16.54,-8.54 C-16.54,-10.2 -15.2,-11.54 -13.54,-11.54c " android:valueTo="M-13.54 -12.54 C-11.33,-12.54 -9.54,-10.75 -9.54,-8.54 C-9.54,-6.33 -11.33,-4.54 -13.54,-4.54 C-15.75,-4.54 -17.54,-6.33 -17.54,-8.54 C-17.54,-10.75 -15.75,-12.54 -13.54,-12.54c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="500" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector> \ No newline at end of file
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="30dp" android:width="30dp" android:viewportHeight="30" android:viewportWidth="30"><group android:name="_R_G"><group android:name="_R_G_L_0_G" android:translateX="28.54" android:translateY="23.54"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-13.54 -16.54 C-9.12,-16.54 -5.54,-12.96 -5.54,-8.54 C-5.54,-4.12 -9.12,-0.54 -13.54,-0.54 C-17.96,-0.54 -21.54,-4.12 -21.54,-8.54 C-21.54,-12.96 -17.96,-16.54 -13.54,-16.54c "/><path android:name="_R_G_L_0_G_D_1_P_0" android:strokeColor="#ffffff" android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="0" android:strokeAlpha="1" android:pathData=" M-13.54 -16.54 C-9.12,-16.54 -5.54,-12.96 -5.54,-8.54 C-5.54,-4.12 -9.12,-0.54 -13.54,-0.54 C-17.96,-0.54 -21.54,-4.12 -21.54,-8.54 C-21.54,-12.96 -17.96,-16.54 -13.54,-16.54c "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="fillAlpha" android:duration="150" android:startOffset="0" android:valueFrom="1" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="fillAlpha" android:duration="200" android:startOffset="150" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="150" android:startOffset="0" android:valueFrom="M-13.54 -16.54 C-9.12,-16.54 -5.54,-12.96 -5.54,-8.54 C-5.54,-4.12 -9.12,-0.54 -13.54,-0.54 C-17.96,-0.54 -21.54,-4.12 -21.54,-8.54 C-21.54,-12.96 -17.96,-16.54 -13.54,-16.54c " android:valueTo="M-13.54 -11.54 C-11.88,-11.54 -10.54,-10.2 -10.54,-8.54 C-10.54,-6.88 -11.88,-5.54 -13.54,-5.54 C-15.2,-5.54 -16.54,-6.88 -16.54,-8.54 C-16.54,-10.2 -15.2,-11.54 -13.54,-11.54c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="200" android:startOffset="150" android:valueFrom="M-13.54 -11.54 C-11.88,-11.54 -10.54,-10.2 -10.54,-8.54 C-10.54,-6.88 -11.88,-5.54 -13.54,-5.54 C-15.2,-5.54 -16.54,-6.88 -16.54,-8.54 C-16.54,-10.2 -15.2,-11.54 -13.54,-11.54c " android:valueTo="M-13.54 -12.54 C-11.33,-12.54 -9.54,-10.75 -9.54,-8.54 C-9.54,-6.33 -11.33,-4.54 -13.54,-4.54 C-15.75,-4.54 -17.54,-6.33 -17.54,-8.54 C-17.54,-10.75 -15.75,-12.54 -13.54,-12.54c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_1_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="strokeWidth" android:duration="150" android:startOffset="0" android:valueFrom="0" android:valueTo="0" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="strokeWidth" android:duration="50" android:startOffset="150" android:valueFrom="0" android:valueTo="2" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_1_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="150" android:startOffset="0" android:valueFrom="M-13.54 -16.54 C-9.12,-16.54 -5.54,-12.96 -5.54,-8.54 C-5.54,-4.12 -9.12,-0.54 -13.54,-0.54 C-17.96,-0.54 -21.54,-4.12 -21.54,-8.54 C-21.54,-12.96 -17.96,-16.54 -13.54,-16.54c " android:valueTo="M-13.54 -11.54 C-11.88,-11.54 -10.54,-10.2 -10.54,-8.54 C-10.54,-6.88 -11.88,-5.54 -13.54,-5.54 C-15.2,-5.54 -16.54,-6.88 -16.54,-8.54 C-16.54,-10.2 -15.2,-11.54 -13.54,-11.54c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="200" android:startOffset="150" android:valueFrom="M-13.54 -11.54 C-11.88,-11.54 -10.54,-10.2 -10.54,-8.54 C-10.54,-6.88 -11.88,-5.54 -13.54,-5.54 C-15.2,-5.54 -16.54,-6.88 -16.54,-8.54 C-16.54,-10.2 -15.2,-11.54 -13.54,-11.54c " android:valueTo="M-13.54 -12.54 C-11.33,-12.54 -9.54,-10.75 -9.54,-8.54 C-9.54,-6.33 -11.33,-4.54 -13.54,-4.54 C-15.75,-4.54 -17.54,-6.33 -17.54,-8.54 C-17.54,-10.75 -15.75,-12.54 -13.54,-12.54c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="500" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pin_dot_shape_1_avd.xml b/packages/SystemUI/res/drawable/pin_dot_shape_1_avd.xml
index da936a28e34f..f1fb2aaf0a02 100644
--- a/packages/SystemUI/res/drawable/pin_dot_shape_1_avd.xml
+++ b/packages/SystemUI/res/drawable/pin_dot_shape_1_avd.xml
@@ -1 +1 @@
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="60dp" android:width="60dp" android:viewportHeight="60" android:viewportWidth="60"><group android:name="_R_G"><group android:name="_R_G_L_0_G" android:translateX="-187.543" android:translateY="-188.546"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="0" android:fillType="nonZero" android:pathData=" M217.62 214.55 C217.62,214.55 217.68,214.55 217.68,214.55 C217.68,214.55 217.74,214.56 217.74,214.56 C217.74,214.56 217.81,214.56 217.81,214.56 C217.81,214.56 217.87,214.56 217.87,214.56 C217.87,214.56 217.93,214.57 217.93,214.57 C217.93,214.57 218,214.57 218,214.57 C218,214.57 218.06,214.58 218.06,214.58 C218.06,214.58 218.12,214.59 218.12,214.59 C218.12,214.59 218.18,214.6 218.18,214.6 C218.18,214.6 218.24,214.61 218.24,214.61 C218.24,214.61 218.31,214.62 218.31,214.62 C218.31,214.62 218.37,214.63 218.37,214.63 C218.37,214.63 218.43,214.65 218.43,214.65 C218.43,214.65 218.49,214.66 218.49,214.66 C218.49,214.66 218.55,214.68 218.55,214.68 C218.55,214.68 218.61,214.69 218.61,214.69 C218.61,214.69 218.67,214.71 218.67,214.71 C218.67,214.71 218.73,214.73 218.73,214.73 C218.73,214.73 218.79,214.75 218.79,214.75 C218.79,214.75 218.85,214.77 218.85,214.77 C218.85,214.77 218.91,214.79 218.91,214.79 C218.91,214.79 218.97,214.81 218.97,214.81 C218.97,214.81 219.03,214.83 219.03,214.83 C219.03,214.83 219.09,214.85 219.09,214.85 C219.09,214.85 219.15,214.88 219.15,214.88 C219.15,214.88 219.2,214.9 219.2,214.9 C219.2,214.9 219.26,214.93 219.26,214.93 C219.26,214.93 219.32,214.96 219.32,214.96 C219.32,214.96 219.37,214.98 219.37,214.98 C219.37,214.98 219.43,215.01 219.43,215.01 C219.43,215.01 219.48,215.05 219.48,215.05 C219.48,215.05 219.54,215.08 219.54,215.08 C219.54,215.08 219.59,215.11 219.59,215.11 C219.59,215.11 219.65,215.14 219.65,215.14 C219.65,215.14 219.7,215.17 219.7,215.17 C219.7,215.17 219.75,215.21 219.75,215.21 C219.75,215.21 219.81,215.24 219.81,215.24 C219.81,215.24 219.86,215.28 219.86,215.28 C219.86,215.28 219.91,215.32 219.91,215.32 C219.91,215.32 219.96,215.35 219.96,215.35 C219.96,215.35 220.01,215.39 220.01,215.39 C220.01,215.39 220.06,215.43 220.06,215.43 C220.06,215.43 220.11,215.47 220.11,215.47 C220.11,215.47 220.16,215.51 220.16,215.51 C220.16,215.51 220.2,215.55 220.2,215.55 C220.2,215.55 220.25,215.59 220.25,215.59 C220.25,215.59 220.3,215.63 220.3,215.63 C220.3,215.63 220.34,215.68 220.34,215.68 C220.34,215.68 220.39,215.72 220.39,215.72 C220.39,215.72 220.43,215.77 220.43,215.77 C220.43,215.77 220.47,215.81 220.47,215.81 C220.47,215.81 220.52,215.86 220.52,215.86 C220.52,215.86 220.56,215.9 220.56,215.9 C220.56,215.9 220.6,215.95 220.6,215.95 C220.6,215.95 220.64,216 220.64,216 C220.64,216 220.68,216.05 220.68,216.05 C220.68,216.05 220.72,216.1 220.72,216.1 C220.72,216.1 220.76,216.15 220.76,216.15 C220.76,216.15 220.8,216.2 220.8,216.2 C220.8,216.2 220.83,216.25 220.83,216.25 C220.83,216.25 220.87,216.3 220.87,216.3 C220.87,216.3 220.9,216.36 220.9,216.36 C220.9,216.36 220.94,216.41 220.94,216.41 C220.94,216.41 220.97,216.46 220.97,216.46 C220.97,216.46 221,216.51 221,216.51 C221,216.51 221.03,216.57 221.03,216.57 C221.03,216.57 221.06,216.63 221.06,216.63 C221.06,216.63 221.09,216.68 221.09,216.68 C221.09,216.68 221.12,216.74 221.12,216.74 C221.12,216.74 221.15,216.79 221.15,216.79 C221.15,216.79 221.18,216.85 221.18,216.85 C221.18,216.85 221.21,216.91 221.21,216.91 C221.21,216.91 221.23,216.96 221.23,216.96 C221.23,216.96 221.25,217.02 221.25,217.02 C221.25,217.02 221.28,217.08 221.28,217.08 C221.28,217.08 221.3,217.14 221.3,217.14 C221.3,217.14 221.33,217.2 221.33,217.2 C221.33,217.2 221.34,217.26 221.34,217.26 C221.34,217.26 221.36,217.32 221.36,217.32 C221.36,217.32 221.38,217.38 221.38,217.38 C221.38,217.38 221.4,217.44 221.4,217.44 C221.4,217.44 221.42,217.5 221.42,217.5 C221.42,217.5 221.44,217.56 221.44,217.56 C221.44,217.56 221.45,217.62 221.45,217.62 C221.45,217.62 221.46,217.68 221.46,217.68 C221.46,217.68 221.48,217.74 221.48,217.74 C221.48,217.74 221.49,217.8 221.49,217.8 C221.49,217.8 221.5,217.87 221.5,217.87 C221.5,217.87 221.51,217.93 221.51,217.93 C221.51,217.93 221.52,217.99 221.52,217.99 C221.52,217.99 221.53,218.05 221.53,218.05 C221.53,218.05 221.54,218.11 221.54,218.11 C221.54,218.11 221.54,218.18 221.54,218.18 C221.54,218.18 221.55,218.24 221.55,218.24 C221.55,218.24 221.55,218.3 221.55,218.3 C221.55,218.3 221.55,218.37 221.55,218.37 C221.55,218.37 221.56,218.43 221.56,218.43 C221.56,218.43 221.56,218.49 221.56,218.49 C221.56,218.49 221.56,218.55 221.56,218.55 C221.56,218.55 221.56,218.62 221.56,218.62 C221.56,218.62 221.56,218.68 221.56,218.68 C221.56,218.68 221.55,218.74 221.55,218.74 C221.55,218.74 221.55,218.81 221.55,218.81 C221.55,218.81 221.55,218.87 221.55,218.87 C221.55,218.87 221.54,218.93 221.54,218.93 C221.54,218.93 221.54,218.99 221.54,218.99 C221.54,218.99 221.53,219.06 221.53,219.06 C221.53,219.06 221.52,219.12 221.52,219.12 C221.52,219.12 221.51,219.18 221.51,219.18 C221.51,219.18 221.5,219.24 221.5,219.24 C221.5,219.24 221.49,219.3 221.49,219.3 C221.49,219.3 221.48,219.37 221.48,219.37 C221.48,219.37 221.46,219.43 221.46,219.43 C221.46,219.43 221.45,219.49 221.45,219.49 C221.45,219.49 221.43,219.55 221.43,219.55 C221.43,219.55 221.42,219.61 221.42,219.61 C221.42,219.61 221.4,219.67 221.4,219.67 C221.4,219.67 221.39,219.73 221.39,219.73 C221.39,219.73 221.37,219.79 221.37,219.79 C221.37,219.79 221.34,219.85 221.34,219.85 C221.34,219.85 221.32,219.91 221.32,219.91 C221.32,219.91 221.3,219.97 221.3,219.97 C221.3,219.97 221.28,220.03 221.28,220.03 C221.28,220.03 221.26,220.09 221.26,220.09 C221.26,220.09 221.23,220.14 221.23,220.14 C221.23,220.14 221.21,220.2 221.21,220.2 C221.21,220.2 221.18,220.26 221.18,220.26 C221.18,220.26 221.15,220.32 221.15,220.32 C221.15,220.32 221.13,220.37 221.13,220.37 C221.13,220.37 221.1,220.43 221.1,220.43 C221.1,220.43 221.07,220.48 221.07,220.48 C221.07,220.48 221.03,220.54 221.03,220.54 C221.03,220.54 221,220.59 221,220.59 C221,220.59 220.97,220.65 220.97,220.65 C220.97,220.65 220.94,220.7 220.94,220.7 C220.94,220.7 220.9,220.75 220.9,220.75 C220.9,220.75 220.87,220.8 220.87,220.8 C220.87,220.8 220.83,220.86 220.83,220.86 C220.83,220.86 220.8,220.91 220.8,220.91 C220.8,220.91 220.76,220.96 220.76,220.96 C220.76,220.96 220.72,221.01 220.72,221.01 C220.72,221.01 220.68,221.06 220.68,221.06 C220.68,221.06 220.64,221.11 220.64,221.11 C220.64,221.11 220.6,221.15 220.6,221.15 C220.6,221.15 220.56,221.2 220.56,221.2 C220.56,221.2 220.52,221.25 220.52,221.25 C220.52,221.25 220.48,221.3 220.48,221.3 C220.48,221.3 220.43,221.34 220.43,221.34 C220.43,221.34 220.39,221.38 220.39,221.38 C220.39,221.38 220.34,221.43 220.34,221.43 C220.34,221.43 220.3,221.47 220.3,221.47 C220.3,221.47 220.25,221.52 220.25,221.52 C220.25,221.52 220.21,221.56 220.21,221.56 C220.21,221.56 220.16,221.6 220.16,221.6 C220.16,221.6 220.11,221.64 220.11,221.64 C220.11,221.64 220.06,221.68 220.06,221.68 C220.06,221.68 220.01,221.72 220.01,221.72 C220.01,221.72 219.96,221.76 219.96,221.76 C219.96,221.76 219.91,221.8 219.91,221.8 C219.91,221.8 219.86,221.83 219.86,221.83 C219.86,221.83 219.81,221.87 219.81,221.87 C219.81,221.87 219.75,221.9 219.75,221.9 C219.75,221.9 219.7,221.93 219.7,221.93 C219.7,221.93 219.65,221.97 219.65,221.97 C219.65,221.97 219.6,222 219.6,222 C219.6,222 219.54,222.03 219.54,222.03 C219.54,222.03 219.49,222.06 219.49,222.06 C219.49,222.06 219.43,222.09 219.43,222.09 C219.43,222.09 219.37,222.12 219.37,222.12 C219.37,222.12 219.32,222.15 219.32,222.15 C219.32,222.15 219.26,222.18 219.26,222.18 C219.26,222.18 219.21,222.2 219.21,222.2 C219.21,222.2 219.15,222.23 219.15,222.23 C219.15,222.23 219.09,222.25 219.09,222.25 C219.09,222.25 219.03,222.28 219.03,222.28 C219.03,222.28 218.97,222.3 218.97,222.3 C218.97,222.3 218.91,222.32 218.91,222.32 C218.91,222.32 218.85,222.34 218.85,222.34 C218.85,222.34 218.79,222.36 218.79,222.36 C218.79,222.36 218.73,222.38 218.73,222.38 C218.73,222.38 218.67,222.4 218.67,222.4 C218.67,222.4 218.61,222.42 218.61,222.42 C218.61,222.42 218.55,222.44 218.55,222.44 C218.55,222.44 218.49,222.45 218.49,222.45 C218.49,222.45 218.43,222.46 218.43,222.46 C218.43,222.46 218.37,222.47 218.37,222.47 C218.37,222.47 218.31,222.49 218.31,222.49 C218.31,222.49 218.25,222.5 218.25,222.5 C218.25,222.5 218.18,222.51 218.18,222.51 C218.18,222.51 218.12,222.52 218.12,222.52 C218.12,222.52 218.06,222.53 218.06,222.53 C218.06,222.53 218,222.54 218,222.54 C218,222.54 217.93,222.54 217.93,222.54 C217.93,222.54 217.87,222.55 217.87,222.55 C217.87,222.55 217.81,222.55 217.81,222.55 C217.81,222.55 217.75,222.55 217.75,222.55 C217.75,222.55 217.68,222.56 217.68,222.56 C217.68,222.56 217.62,222.56 217.62,222.56 C217.62,222.56 217.56,222.56 217.56,222.56 C217.56,222.56 217.49,222.56 217.49,222.56 C217.49,222.56 217.43,222.56 217.43,222.56 C217.43,222.56 217.37,222.55 217.37,222.55 C217.37,222.55 217.3,222.55 217.3,222.55 C217.3,222.55 217.24,222.55 217.24,222.55 C217.24,222.55 217.18,222.54 217.18,222.54 C217.18,222.54 217.12,222.54 217.12,222.54 C217.12,222.54 217.05,222.53 217.05,222.53 C217.05,222.53 216.99,222.52 216.99,222.52 C216.99,222.52 216.93,222.51 216.93,222.51 C216.93,222.51 216.87,222.5 216.87,222.5 C216.87,222.5 216.81,222.49 216.81,222.49 C216.81,222.49 216.74,222.48 216.74,222.48 C216.74,222.48 216.68,222.46 216.68,222.46 C216.68,222.46 216.62,222.45 216.62,222.45 C216.62,222.45 216.56,222.43 216.56,222.43 C216.56,222.43 216.5,222.42 216.5,222.42 C216.5,222.42 216.44,222.4 216.44,222.4 C216.44,222.4 216.38,222.38 216.38,222.38 C216.38,222.38 216.32,222.36 216.32,222.36 C216.32,222.36 216.26,222.34 216.26,222.34 C216.26,222.34 216.2,222.32 216.2,222.32 C216.2,222.32 216.14,222.3 216.14,222.3 C216.14,222.3 216.08,222.28 216.08,222.28 C216.08,222.28 216.02,222.26 216.02,222.26 C216.02,222.26 215.97,222.23 215.97,222.23 C215.97,222.23 215.91,222.2 215.91,222.2 C215.91,222.2 215.85,222.18 215.85,222.18 C215.85,222.18 215.79,222.15 215.79,222.15 C215.79,222.15 215.74,222.12 215.74,222.12 C215.74,222.12 215.68,222.1 215.68,222.1 C215.68,222.1 215.63,222.06 215.63,222.06 C215.63,222.06 215.57,222.03 215.57,222.03 C215.57,222.03 215.52,222 215.52,222 C215.52,222 215.46,221.97 215.46,221.97 C215.46,221.97 215.41,221.94 215.41,221.94 C215.41,221.94 215.36,221.9 215.36,221.9 C215.36,221.9 215.31,221.87 215.31,221.87 C215.31,221.87 215.25,221.83 215.25,221.83 C215.25,221.83 215.2,221.79 215.2,221.79 C215.2,221.79 215.15,221.76 215.15,221.76 C215.15,221.76 215.1,221.72 215.1,221.72 C215.1,221.72 215.05,221.68 215.05,221.68 C215.05,221.68 215,221.64 215,221.64 C215,221.64 214.96,221.6 214.96,221.6 C214.96,221.6 214.91,221.56 214.91,221.56 C214.91,221.56 214.86,221.52 214.86,221.52 C214.86,221.52 214.81,221.48 214.81,221.48 C214.81,221.48 214.77,221.43 214.77,221.43 C214.77,221.43 214.73,221.39 214.73,221.39 C214.73,221.39 214.68,221.34 214.68,221.34 C214.68,221.34 214.64,221.3 214.64,221.3 C214.64,221.3 214.59,221.25 214.59,221.25 C214.59,221.25 214.55,221.2 214.55,221.2 C214.55,221.2 214.51,221.15 214.51,221.15 C214.51,221.15 214.47,221.11 214.47,221.11 C214.47,221.11 214.43,221.06 214.43,221.06 C214.43,221.06 214.39,221.01 214.39,221.01 C214.39,221.01 214.35,220.96 214.35,220.96 C214.35,220.96 214.31,220.91 214.31,220.91 C214.31,220.91 214.28,220.86 214.28,220.86 C214.28,220.86 214.25,220.81 214.25,220.81 C214.25,220.81 214.21,220.75 214.21,220.75 C214.21,220.75 214.18,220.7 214.18,220.7 C214.18,220.7 214.14,220.65 214.14,220.65 C214.14,220.65 214.11,220.59 214.11,220.59 C214.11,220.59 214.08,220.54 214.08,220.54 C214.08,220.54 214.05,220.48 214.05,220.48 C214.05,220.48 214.02,220.43 214.02,220.43 C214.02,220.43 213.99,220.37 213.99,220.37 C213.99,220.37 213.96,220.32 213.96,220.32 C213.96,220.32 213.93,220.26 213.93,220.26 C213.93,220.26 213.91,220.2 213.91,220.2 C213.91,220.2 213.88,220.14 213.88,220.14 C213.88,220.14 213.86,220.09 213.86,220.09 C213.86,220.09 213.83,220.03 213.83,220.03 C213.83,220.03 213.81,219.97 213.81,219.97 C213.81,219.97 213.79,219.91 213.79,219.91 C213.79,219.91 213.77,219.85 213.77,219.85 C213.77,219.85 213.75,219.79 213.75,219.79 C213.75,219.79 213.73,219.73 213.73,219.73 C213.73,219.73 213.71,219.67 213.71,219.67 C213.71,219.67 213.69,219.61 213.69,219.61 C213.69,219.61 213.68,219.55 213.68,219.55 C213.68,219.55 213.66,219.49 213.66,219.49 C213.66,219.49 213.65,219.43 213.65,219.43 C213.65,219.43 213.64,219.37 213.64,219.37 C213.64,219.37 213.62,219.31 213.62,219.31 C213.62,219.31 213.61,219.24 213.61,219.24 C213.61,219.24 213.6,219.18 213.6,219.18 C213.6,219.18 213.59,219.12 213.59,219.12 C213.59,219.12 213.58,219.06 213.58,219.06 C213.58,219.06 213.57,218.99 213.57,218.99 C213.57,218.99 213.57,218.93 213.57,218.93 C213.57,218.93 213.56,218.87 213.56,218.87 C213.56,218.87 213.56,218.81 213.56,218.81 C213.56,218.81 213.56,218.74 213.56,218.74 C213.56,218.74 213.56,218.68 213.56,218.68 C213.56,218.68 213.55,218.62 213.55,218.62 C213.55,218.62 213.55,218.55 213.55,218.55 C213.55,218.55 213.55,218.49 213.55,218.49 C213.55,218.49 213.56,218.43 213.56,218.43 C213.56,218.43 213.56,218.37 213.56,218.37 C213.56,218.37 213.56,218.3 213.56,218.3 C213.56,218.3 213.56,218.24 213.56,218.24 C213.56,218.24 213.57,218.18 213.57,218.18 C213.57,218.18 213.57,218.12 213.57,218.12 C213.57,218.12 213.58,218.05 213.58,218.05 C213.58,218.05 213.59,217.99 213.59,217.99 C213.59,217.99 213.6,217.93 213.6,217.93 C213.6,217.93 213.61,217.87 213.61,217.87 C213.61,217.87 213.62,217.8 213.62,217.8 C213.62,217.8 213.63,217.74 213.63,217.74 C213.63,217.74 213.65,217.68 213.65,217.68 C213.65,217.68 213.66,217.62 213.66,217.62 C213.66,217.62 213.68,217.56 213.68,217.56 C213.68,217.56 213.69,217.5 213.69,217.5 C213.69,217.5 213.71,217.44 213.71,217.44 C213.71,217.44 213.73,217.38 213.73,217.38 C213.73,217.38 213.75,217.32 213.75,217.32 C213.75,217.32 213.77,217.26 213.77,217.26 C213.77,217.26 213.79,217.2 213.79,217.2 C213.79,217.2 213.81,217.14 213.81,217.14 C213.81,217.14 213.83,217.08 213.83,217.08 C213.83,217.08 213.85,217.02 213.85,217.02 C213.85,217.02 213.88,216.96 213.88,216.96 C213.88,216.96 213.91,216.91 213.91,216.91 C213.91,216.91 213.93,216.85 213.93,216.85 C213.93,216.85 213.96,216.79 213.96,216.79 C213.96,216.79 213.99,216.74 213.99,216.74 C213.99,216.74 214.02,216.68 214.02,216.68 C214.02,216.68 214.05,216.63 214.05,216.63 C214.05,216.63 214.08,216.57 214.08,216.57 C214.08,216.57 214.11,216.52 214.11,216.52 C214.11,216.52 214.14,216.46 214.14,216.46 C214.14,216.46 214.17,216.41 214.17,216.41 C214.17,216.41 214.21,216.36 214.21,216.36 C214.21,216.36 214.24,216.3 214.24,216.3 C214.24,216.3 214.28,216.25 214.28,216.25 C214.28,216.25 214.32,216.2 214.32,216.2 C214.32,216.2 214.35,216.15 214.35,216.15 C214.35,216.15 214.39,216.1 214.39,216.1 C214.39,216.1 214.43,216.05 214.43,216.05 C214.43,216.05 214.47,216 214.47,216 C214.47,216 214.51,215.96 214.51,215.96 C214.51,215.96 214.55,215.91 214.55,215.91 C214.55,215.91 214.59,215.86 214.59,215.86 C214.59,215.86 214.64,215.81 214.64,215.81 C214.64,215.81 214.68,215.77 214.68,215.77 C214.68,215.77 214.73,215.72 214.73,215.72 C214.73,215.72 214.77,215.68 214.77,215.68 C214.77,215.68 214.82,215.64 214.82,215.64 C214.82,215.64 214.86,215.59 214.86,215.59 C214.86,215.59 214.91,215.55 214.91,215.55 C214.91,215.55 214.96,215.51 214.96,215.51 C214.96,215.51 215,215.47 215,215.47 C215,215.47 215.05,215.43 215.05,215.43 C215.05,215.43 215.1,215.39 215.1,215.39 C215.1,215.39 215.15,215.35 215.15,215.35 C215.15,215.35 215.2,215.31 215.2,215.31 C215.2,215.31 215.25,215.28 215.25,215.28 C215.25,215.28 215.31,215.24 215.31,215.24 C215.31,215.24 215.36,215.21 215.36,215.21 C215.36,215.21 215.41,215.17 215.41,215.17 C215.41,215.17 215.46,215.14 215.46,215.14 C215.46,215.14 215.52,215.11 215.52,215.11 C215.52,215.11 215.57,215.08 215.57,215.08 C215.57,215.08 215.63,215.05 215.63,215.05 C215.63,215.05 215.68,215.02 215.68,215.02 C215.68,215.02 215.74,214.99 215.74,214.99 C215.74,214.99 215.79,214.96 215.79,214.96 C215.79,214.96 215.85,214.93 215.85,214.93 C215.85,214.93 215.91,214.9 215.91,214.9 C215.91,214.9 215.97,214.88 215.97,214.88 C215.97,214.88 216.02,214.86 216.02,214.86 C216.02,214.86 216.08,214.83 216.08,214.83 C216.08,214.83 216.14,214.81 216.14,214.81 C216.14,214.81 216.2,214.78 216.2,214.78 C216.2,214.78 216.26,214.77 216.26,214.77 C216.26,214.77 216.32,214.75 216.32,214.75 C216.32,214.75 216.38,214.73 216.38,214.73 C216.38,214.73 216.44,214.71 216.44,214.71 C216.44,214.71 216.5,214.69 216.5,214.69 C216.5,214.69 216.56,214.67 216.56,214.67 C216.56,214.67 216.62,214.66 216.62,214.66 C216.62,214.66 216.68,214.65 216.68,214.65 C216.68,214.65 216.74,214.63 216.74,214.63 C216.74,214.63 216.81,214.62 216.81,214.62 C216.81,214.62 216.87,214.61 216.87,214.61 C216.87,214.61 216.93,214.6 216.93,214.6 C216.93,214.6 216.99,214.59 216.99,214.59 C216.99,214.59 217.05,214.58 217.05,214.58 C217.05,214.58 217.12,214.57 217.12,214.57 C217.12,214.57 217.18,214.57 217.18,214.57 C217.18,214.57 217.24,214.56 217.24,214.56 C217.24,214.56 217.3,214.56 217.3,214.56 C217.3,214.56 217.37,214.56 217.37,214.56 C217.37,214.56 217.43,214.55 217.43,214.55 C217.43,214.55 217.49,214.55 217.49,214.55 C217.49,214.55 217.56,214.55 217.56,214.55 C217.56,214.55 217.62,214.55 217.62,214.55c "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="fillAlpha" android:duration="33" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M217.62 214.55 C217.62,214.55 217.68,214.55 217.68,214.55 C217.68,214.55 217.74,214.56 217.74,214.56 C217.74,214.56 217.81,214.56 217.81,214.56 C217.81,214.56 217.87,214.56 217.87,214.56 C217.87,214.56 217.93,214.57 217.93,214.57 C217.93,214.57 218,214.57 218,214.57 C218,214.57 218.06,214.58 218.06,214.58 C218.06,214.58 218.12,214.59 218.12,214.59 C218.12,214.59 218.18,214.6 218.18,214.6 C218.18,214.6 218.24,214.61 218.24,214.61 C218.24,214.61 218.31,214.62 218.31,214.62 C218.31,214.62 218.37,214.63 218.37,214.63 C218.37,214.63 218.43,214.65 218.43,214.65 C218.43,214.65 218.49,214.66 218.49,214.66 C218.49,214.66 218.55,214.68 218.55,214.68 C218.55,214.68 218.61,214.69 218.61,214.69 C218.61,214.69 218.67,214.71 218.67,214.71 C218.67,214.71 218.73,214.73 218.73,214.73 C218.73,214.73 218.79,214.75 218.79,214.75 C218.79,214.75 218.85,214.77 218.85,214.77 C218.85,214.77 218.91,214.79 218.91,214.79 C218.91,214.79 218.97,214.81 218.97,214.81 C218.97,214.81 219.03,214.83 219.03,214.83 C219.03,214.83 219.09,214.85 219.09,214.85 C219.09,214.85 219.15,214.88 219.15,214.88 C219.15,214.88 219.2,214.9 219.2,214.9 C219.2,214.9 219.26,214.93 219.26,214.93 C219.26,214.93 219.32,214.96 219.32,214.96 C219.32,214.96 219.37,214.98 219.37,214.98 C219.37,214.98 219.43,215.01 219.43,215.01 C219.43,215.01 219.48,215.05 219.48,215.05 C219.48,215.05 219.54,215.08 219.54,215.08 C219.54,215.08 219.59,215.11 219.59,215.11 C219.59,215.11 219.65,215.14 219.65,215.14 C219.65,215.14 219.7,215.17 219.7,215.17 C219.7,215.17 219.75,215.21 219.75,215.21 C219.75,215.21 219.81,215.24 219.81,215.24 C219.81,215.24 219.86,215.28 219.86,215.28 C219.86,215.28 219.91,215.32 219.91,215.32 C219.91,215.32 219.96,215.35 219.96,215.35 C219.96,215.35 220.01,215.39 220.01,215.39 C220.01,215.39 220.06,215.43 220.06,215.43 C220.06,215.43 220.11,215.47 220.11,215.47 C220.11,215.47 220.16,215.51 220.16,215.51 C220.16,215.51 220.2,215.55 220.2,215.55 C220.2,215.55 220.25,215.59 220.25,215.59 C220.25,215.59 220.3,215.63 220.3,215.63 C220.3,215.63 220.34,215.68 220.34,215.68 C220.34,215.68 220.39,215.72 220.39,215.72 C220.39,215.72 220.43,215.77 220.43,215.77 C220.43,215.77 220.47,215.81 220.47,215.81 C220.47,215.81 220.52,215.86 220.52,215.86 C220.52,215.86 220.56,215.9 220.56,215.9 C220.56,215.9 220.6,215.95 220.6,215.95 C220.6,215.95 220.64,216 220.64,216 C220.64,216 220.68,216.05 220.68,216.05 C220.68,216.05 220.72,216.1 220.72,216.1 C220.72,216.1 220.76,216.15 220.76,216.15 C220.76,216.15 220.8,216.2 220.8,216.2 C220.8,216.2 220.83,216.25 220.83,216.25 C220.83,216.25 220.87,216.3 220.87,216.3 C220.87,216.3 220.9,216.36 220.9,216.36 C220.9,216.36 220.94,216.41 220.94,216.41 C220.94,216.41 220.97,216.46 220.97,216.46 C220.97,216.46 221,216.51 221,216.51 C221,216.51 221.03,216.57 221.03,216.57 C221.03,216.57 221.06,216.63 221.06,216.63 C221.06,216.63 221.09,216.68 221.09,216.68 C221.09,216.68 221.12,216.74 221.12,216.74 C221.12,216.74 221.15,216.79 221.15,216.79 C221.15,216.79 221.18,216.85 221.18,216.85 C221.18,216.85 221.21,216.91 221.21,216.91 C221.21,216.91 221.23,216.96 221.23,216.96 C221.23,216.96 221.25,217.02 221.25,217.02 C221.25,217.02 221.28,217.08 221.28,217.08 C221.28,217.08 221.3,217.14 221.3,217.14 C221.3,217.14 221.33,217.2 221.33,217.2 C221.33,217.2 221.34,217.26 221.34,217.26 C221.34,217.26 221.36,217.32 221.36,217.32 C221.36,217.32 221.38,217.38 221.38,217.38 C221.38,217.38 221.4,217.44 221.4,217.44 C221.4,217.44 221.42,217.5 221.42,217.5 C221.42,217.5 221.44,217.56 221.44,217.56 C221.44,217.56 221.45,217.62 221.45,217.62 C221.45,217.62 221.46,217.68 221.46,217.68 C221.46,217.68 221.48,217.74 221.48,217.74 C221.48,217.74 221.49,217.8 221.49,217.8 C221.49,217.8 221.5,217.87 221.5,217.87 C221.5,217.87 221.51,217.93 221.51,217.93 C221.51,217.93 221.52,217.99 221.52,217.99 C221.52,217.99 221.53,218.05 221.53,218.05 C221.53,218.05 221.54,218.11 221.54,218.11 C221.54,218.11 221.54,218.18 221.54,218.18 C221.54,218.18 221.55,218.24 221.55,218.24 C221.55,218.24 221.55,218.3 221.55,218.3 C221.55,218.3 221.55,218.37 221.55,218.37 C221.55,218.37 221.56,218.43 221.56,218.43 C221.56,218.43 221.56,218.49 221.56,218.49 C221.56,218.49 221.56,218.55 221.56,218.55 C221.56,218.55 221.56,218.62 221.56,218.62 C221.56,218.62 221.56,218.68 221.56,218.68 C221.56,218.68 221.55,218.74 221.55,218.74 C221.55,218.74 221.55,218.81 221.55,218.81 C221.55,218.81 221.55,218.87 221.55,218.87 C221.55,218.87 221.54,218.93 221.54,218.93 C221.54,218.93 221.54,218.99 221.54,218.99 C221.54,218.99 221.53,219.06 221.53,219.06 C221.53,219.06 221.52,219.12 221.52,219.12 C221.52,219.12 221.51,219.18 221.51,219.18 C221.51,219.18 221.5,219.24 221.5,219.24 C221.5,219.24 221.49,219.3 221.49,219.3 C221.49,219.3 221.48,219.37 221.48,219.37 C221.48,219.37 221.46,219.43 221.46,219.43 C221.46,219.43 221.45,219.49 221.45,219.49 C221.45,219.49 221.43,219.55 221.43,219.55 C221.43,219.55 221.42,219.61 221.42,219.61 C221.42,219.61 221.4,219.67 221.4,219.67 C221.4,219.67 221.39,219.73 221.39,219.73 C221.39,219.73 221.37,219.79 221.37,219.79 C221.37,219.79 221.34,219.85 221.34,219.85 C221.34,219.85 221.32,219.91 221.32,219.91 C221.32,219.91 221.3,219.97 221.3,219.97 C221.3,219.97 221.28,220.03 221.28,220.03 C221.28,220.03 221.26,220.09 221.26,220.09 C221.26,220.09 221.23,220.14 221.23,220.14 C221.23,220.14 221.21,220.2 221.21,220.2 C221.21,220.2 221.18,220.26 221.18,220.26 C221.18,220.26 221.15,220.32 221.15,220.32 C221.15,220.32 221.13,220.37 221.13,220.37 C221.13,220.37 221.1,220.43 221.1,220.43 C221.1,220.43 221.07,220.48 221.07,220.48 C221.07,220.48 221.03,220.54 221.03,220.54 C221.03,220.54 221,220.59 221,220.59 C221,220.59 220.97,220.65 220.97,220.65 C220.97,220.65 220.94,220.7 220.94,220.7 C220.94,220.7 220.9,220.75 220.9,220.75 C220.9,220.75 220.87,220.8 220.87,220.8 C220.87,220.8 220.83,220.86 220.83,220.86 C220.83,220.86 220.8,220.91 220.8,220.91 C220.8,220.91 220.76,220.96 220.76,220.96 C220.76,220.96 220.72,221.01 220.72,221.01 C220.72,221.01 220.68,221.06 220.68,221.06 C220.68,221.06 220.64,221.11 220.64,221.11 C220.64,221.11 220.6,221.15 220.6,221.15 C220.6,221.15 220.56,221.2 220.56,221.2 C220.56,221.2 220.52,221.25 220.52,221.25 C220.52,221.25 220.48,221.3 220.48,221.3 C220.48,221.3 220.43,221.34 220.43,221.34 C220.43,221.34 220.39,221.38 220.39,221.38 C220.39,221.38 220.34,221.43 220.34,221.43 C220.34,221.43 220.3,221.47 220.3,221.47 C220.3,221.47 220.25,221.52 220.25,221.52 C220.25,221.52 220.21,221.56 220.21,221.56 C220.21,221.56 220.16,221.6 220.16,221.6 C220.16,221.6 220.11,221.64 220.11,221.64 C220.11,221.64 220.06,221.68 220.06,221.68 C220.06,221.68 220.01,221.72 220.01,221.72 C220.01,221.72 219.96,221.76 219.96,221.76 C219.96,221.76 219.91,221.8 219.91,221.8 C219.91,221.8 219.86,221.83 219.86,221.83 C219.86,221.83 219.81,221.87 219.81,221.87 C219.81,221.87 219.75,221.9 219.75,221.9 C219.75,221.9 219.7,221.93 219.7,221.93 C219.7,221.93 219.65,221.97 219.65,221.97 C219.65,221.97 219.6,222 219.6,222 C219.6,222 219.54,222.03 219.54,222.03 C219.54,222.03 219.49,222.06 219.49,222.06 C219.49,222.06 219.43,222.09 219.43,222.09 C219.43,222.09 219.37,222.12 219.37,222.12 C219.37,222.12 219.32,222.15 219.32,222.15 C219.32,222.15 219.26,222.18 219.26,222.18 C219.26,222.18 219.21,222.2 219.21,222.2 C219.21,222.2 219.15,222.23 219.15,222.23 C219.15,222.23 219.09,222.25 219.09,222.25 C219.09,222.25 219.03,222.28 219.03,222.28 C219.03,222.28 218.97,222.3 218.97,222.3 C218.97,222.3 218.91,222.32 218.91,222.32 C218.91,222.32 218.85,222.34 218.85,222.34 C218.85,222.34 218.79,222.36 218.79,222.36 C218.79,222.36 218.73,222.38 218.73,222.38 C218.73,222.38 218.67,222.4 218.67,222.4 C218.67,222.4 218.61,222.42 218.61,222.42 C218.61,222.42 218.55,222.44 218.55,222.44 C218.55,222.44 218.49,222.45 218.49,222.45 C218.49,222.45 218.43,222.46 218.43,222.46 C218.43,222.46 218.37,222.47 218.37,222.47 C218.37,222.47 218.31,222.49 218.31,222.49 C218.31,222.49 218.25,222.5 218.25,222.5 C218.25,222.5 218.18,222.51 218.18,222.51 C218.18,222.51 218.12,222.52 218.12,222.52 C218.12,222.52 218.06,222.53 218.06,222.53 C218.06,222.53 218,222.54 218,222.54 C218,222.54 217.93,222.54 217.93,222.54 C217.93,222.54 217.87,222.55 217.87,222.55 C217.87,222.55 217.81,222.55 217.81,222.55 C217.81,222.55 217.75,222.55 217.75,222.55 C217.75,222.55 217.68,222.56 217.68,222.56 C217.68,222.56 217.62,222.56 217.62,222.56 C217.62,222.56 217.56,222.56 217.56,222.56 C217.56,222.56 217.49,222.56 217.49,222.56 C217.49,222.56 217.43,222.56 217.43,222.56 C217.43,222.56 217.37,222.55 217.37,222.55 C217.37,222.55 217.3,222.55 217.3,222.55 C217.3,222.55 217.24,222.55 217.24,222.55 C217.24,222.55 217.18,222.54 217.18,222.54 C217.18,222.54 217.12,222.54 217.12,222.54 C217.12,222.54 217.05,222.53 217.05,222.53 C217.05,222.53 216.99,222.52 216.99,222.52 C216.99,222.52 216.93,222.51 216.93,222.51 C216.93,222.51 216.87,222.5 216.87,222.5 C216.87,222.5 216.81,222.49 216.81,222.49 C216.81,222.49 216.74,222.48 216.74,222.48 C216.74,222.48 216.68,222.46 216.68,222.46 C216.68,222.46 216.62,222.45 216.62,222.45 C216.62,222.45 216.56,222.43 216.56,222.43 C216.56,222.43 216.5,222.42 216.5,222.42 C216.5,222.42 216.44,222.4 216.44,222.4 C216.44,222.4 216.38,222.38 216.38,222.38 C216.38,222.38 216.32,222.36 216.32,222.36 C216.32,222.36 216.26,222.34 216.26,222.34 C216.26,222.34 216.2,222.32 216.2,222.32 C216.2,222.32 216.14,222.3 216.14,222.3 C216.14,222.3 216.08,222.28 216.08,222.28 C216.08,222.28 216.02,222.26 216.02,222.26 C216.02,222.26 215.97,222.23 215.97,222.23 C215.97,222.23 215.91,222.2 215.91,222.2 C215.91,222.2 215.85,222.18 215.85,222.18 C215.85,222.18 215.79,222.15 215.79,222.15 C215.79,222.15 215.74,222.12 215.74,222.12 C215.74,222.12 215.68,222.1 215.68,222.1 C215.68,222.1 215.63,222.06 215.63,222.06 C215.63,222.06 215.57,222.03 215.57,222.03 C215.57,222.03 215.52,222 215.52,222 C215.52,222 215.46,221.97 215.46,221.97 C215.46,221.97 215.41,221.94 215.41,221.94 C215.41,221.94 215.36,221.9 215.36,221.9 C215.36,221.9 215.31,221.87 215.31,221.87 C215.31,221.87 215.25,221.83 215.25,221.83 C215.25,221.83 215.2,221.79 215.2,221.79 C215.2,221.79 215.15,221.76 215.15,221.76 C215.15,221.76 215.1,221.72 215.1,221.72 C215.1,221.72 215.05,221.68 215.05,221.68 C215.05,221.68 215,221.64 215,221.64 C215,221.64 214.96,221.6 214.96,221.6 C214.96,221.6 214.91,221.56 214.91,221.56 C214.91,221.56 214.86,221.52 214.86,221.52 C214.86,221.52 214.81,221.48 214.81,221.48 C214.81,221.48 214.77,221.43 214.77,221.43 C214.77,221.43 214.73,221.39 214.73,221.39 C214.73,221.39 214.68,221.34 214.68,221.34 C214.68,221.34 214.64,221.3 214.64,221.3 C214.64,221.3 214.59,221.25 214.59,221.25 C214.59,221.25 214.55,221.2 214.55,221.2 C214.55,221.2 214.51,221.15 214.51,221.15 C214.51,221.15 214.47,221.11 214.47,221.11 C214.47,221.11 214.43,221.06 214.43,221.06 C214.43,221.06 214.39,221.01 214.39,221.01 C214.39,221.01 214.35,220.96 214.35,220.96 C214.35,220.96 214.31,220.91 214.31,220.91 C214.31,220.91 214.28,220.86 214.28,220.86 C214.28,220.86 214.25,220.81 214.25,220.81 C214.25,220.81 214.21,220.75 214.21,220.75 C214.21,220.75 214.18,220.7 214.18,220.7 C214.18,220.7 214.14,220.65 214.14,220.65 C214.14,220.65 214.11,220.59 214.11,220.59 C214.11,220.59 214.08,220.54 214.08,220.54 C214.08,220.54 214.05,220.48 214.05,220.48 C214.05,220.48 214.02,220.43 214.02,220.43 C214.02,220.43 213.99,220.37 213.99,220.37 C213.99,220.37 213.96,220.32 213.96,220.32 C213.96,220.32 213.93,220.26 213.93,220.26 C213.93,220.26 213.91,220.2 213.91,220.2 C213.91,220.2 213.88,220.14 213.88,220.14 C213.88,220.14 213.86,220.09 213.86,220.09 C213.86,220.09 213.83,220.03 213.83,220.03 C213.83,220.03 213.81,219.97 213.81,219.97 C213.81,219.97 213.79,219.91 213.79,219.91 C213.79,219.91 213.77,219.85 213.77,219.85 C213.77,219.85 213.75,219.79 213.75,219.79 C213.75,219.79 213.73,219.73 213.73,219.73 C213.73,219.73 213.71,219.67 213.71,219.67 C213.71,219.67 213.69,219.61 213.69,219.61 C213.69,219.61 213.68,219.55 213.68,219.55 C213.68,219.55 213.66,219.49 213.66,219.49 C213.66,219.49 213.65,219.43 213.65,219.43 C213.65,219.43 213.64,219.37 213.64,219.37 C213.64,219.37 213.62,219.31 213.62,219.31 C213.62,219.31 213.61,219.24 213.61,219.24 C213.61,219.24 213.6,219.18 213.6,219.18 C213.6,219.18 213.59,219.12 213.59,219.12 C213.59,219.12 213.58,219.06 213.58,219.06 C213.58,219.06 213.57,218.99 213.57,218.99 C213.57,218.99 213.57,218.93 213.57,218.93 C213.57,218.93 213.56,218.87 213.56,218.87 C213.56,218.87 213.56,218.81 213.56,218.81 C213.56,218.81 213.56,218.74 213.56,218.74 C213.56,218.74 213.56,218.68 213.56,218.68 C213.56,218.68 213.55,218.62 213.55,218.62 C213.55,218.62 213.55,218.55 213.55,218.55 C213.55,218.55 213.55,218.49 213.55,218.49 C213.55,218.49 213.56,218.43 213.56,218.43 C213.56,218.43 213.56,218.37 213.56,218.37 C213.56,218.37 213.56,218.3 213.56,218.3 C213.56,218.3 213.56,218.24 213.56,218.24 C213.56,218.24 213.57,218.18 213.57,218.18 C213.57,218.18 213.57,218.12 213.57,218.12 C213.57,218.12 213.58,218.05 213.58,218.05 C213.58,218.05 213.59,217.99 213.59,217.99 C213.59,217.99 213.6,217.93 213.6,217.93 C213.6,217.93 213.61,217.87 213.61,217.87 C213.61,217.87 213.62,217.8 213.62,217.8 C213.62,217.8 213.63,217.74 213.63,217.74 C213.63,217.74 213.65,217.68 213.65,217.68 C213.65,217.68 213.66,217.62 213.66,217.62 C213.66,217.62 213.68,217.56 213.68,217.56 C213.68,217.56 213.69,217.5 213.69,217.5 C213.69,217.5 213.71,217.44 213.71,217.44 C213.71,217.44 213.73,217.38 213.73,217.38 C213.73,217.38 213.75,217.32 213.75,217.32 C213.75,217.32 213.77,217.26 213.77,217.26 C213.77,217.26 213.79,217.2 213.79,217.2 C213.79,217.2 213.81,217.14 213.81,217.14 C213.81,217.14 213.83,217.08 213.83,217.08 C213.83,217.08 213.85,217.02 213.85,217.02 C213.85,217.02 213.88,216.96 213.88,216.96 C213.88,216.96 213.91,216.91 213.91,216.91 C213.91,216.91 213.93,216.85 213.93,216.85 C213.93,216.85 213.96,216.79 213.96,216.79 C213.96,216.79 213.99,216.74 213.99,216.74 C213.99,216.74 214.02,216.68 214.02,216.68 C214.02,216.68 214.05,216.63 214.05,216.63 C214.05,216.63 214.08,216.57 214.08,216.57 C214.08,216.57 214.11,216.52 214.11,216.52 C214.11,216.52 214.14,216.46 214.14,216.46 C214.14,216.46 214.17,216.41 214.17,216.41 C214.17,216.41 214.21,216.36 214.21,216.36 C214.21,216.36 214.24,216.3 214.24,216.3 C214.24,216.3 214.28,216.25 214.28,216.25 C214.28,216.25 214.32,216.2 214.32,216.2 C214.32,216.2 214.35,216.15 214.35,216.15 C214.35,216.15 214.39,216.1 214.39,216.1 C214.39,216.1 214.43,216.05 214.43,216.05 C214.43,216.05 214.47,216 214.47,216 C214.47,216 214.51,215.96 214.51,215.96 C214.51,215.96 214.55,215.91 214.55,215.91 C214.55,215.91 214.59,215.86 214.59,215.86 C214.59,215.86 214.64,215.81 214.64,215.81 C214.64,215.81 214.68,215.77 214.68,215.77 C214.68,215.77 214.73,215.72 214.73,215.72 C214.73,215.72 214.77,215.68 214.77,215.68 C214.77,215.68 214.82,215.64 214.82,215.64 C214.82,215.64 214.86,215.59 214.86,215.59 C214.86,215.59 214.91,215.55 214.91,215.55 C214.91,215.55 214.96,215.51 214.96,215.51 C214.96,215.51 215,215.47 215,215.47 C215,215.47 215.05,215.43 215.05,215.43 C215.05,215.43 215.1,215.39 215.1,215.39 C215.1,215.39 215.15,215.35 215.15,215.35 C215.15,215.35 215.2,215.31 215.2,215.31 C215.2,215.31 215.25,215.28 215.25,215.28 C215.25,215.28 215.31,215.24 215.31,215.24 C215.31,215.24 215.36,215.21 215.36,215.21 C215.36,215.21 215.41,215.17 215.41,215.17 C215.41,215.17 215.46,215.14 215.46,215.14 C215.46,215.14 215.52,215.11 215.52,215.11 C215.52,215.11 215.57,215.08 215.57,215.08 C215.57,215.08 215.63,215.05 215.63,215.05 C215.63,215.05 215.68,215.02 215.68,215.02 C215.68,215.02 215.74,214.99 215.74,214.99 C215.74,214.99 215.79,214.96 215.79,214.96 C215.79,214.96 215.85,214.93 215.85,214.93 C215.85,214.93 215.91,214.9 215.91,214.9 C215.91,214.9 215.97,214.88 215.97,214.88 C215.97,214.88 216.02,214.86 216.02,214.86 C216.02,214.86 216.08,214.83 216.08,214.83 C216.08,214.83 216.14,214.81 216.14,214.81 C216.14,214.81 216.2,214.78 216.2,214.78 C216.2,214.78 216.26,214.77 216.26,214.77 C216.26,214.77 216.32,214.75 216.32,214.75 C216.32,214.75 216.38,214.73 216.38,214.73 C216.38,214.73 216.44,214.71 216.44,214.71 C216.44,214.71 216.5,214.69 216.5,214.69 C216.5,214.69 216.56,214.67 216.56,214.67 C216.56,214.67 216.62,214.66 216.62,214.66 C216.62,214.66 216.68,214.65 216.68,214.65 C216.68,214.65 216.74,214.63 216.74,214.63 C216.74,214.63 216.81,214.62 216.81,214.62 C216.81,214.62 216.87,214.61 216.87,214.61 C216.87,214.61 216.93,214.6 216.93,214.6 C216.93,214.6 216.99,214.59 216.99,214.59 C216.99,214.59 217.05,214.58 217.05,214.58 C217.05,214.58 217.12,214.57 217.12,214.57 C217.12,214.57 217.18,214.57 217.18,214.57 C217.18,214.57 217.24,214.56 217.24,214.56 C217.24,214.56 217.3,214.56 217.3,214.56 C217.3,214.56 217.37,214.56 217.37,214.56 C217.37,214.56 217.43,214.55 217.43,214.55 C217.43,214.55 217.49,214.55 217.49,214.55 C217.49,214.55 217.56,214.55 217.56,214.55 C217.56,214.55 217.62,214.55 217.62,214.55c " android:valueTo="M217.52 203.54 C217.52,203.54 217.83,203.53 217.83,203.53 C217.83,203.53 218.14,203.52 218.14,203.52 C218.14,203.52 218.44,203.49 218.44,203.49 C218.44,203.49 218.75,203.45 218.75,203.45 C218.75,203.45 219.05,203.41 219.05,203.41 C219.05,203.41 219.36,203.35 219.36,203.35 C219.36,203.35 219.66,203.28 219.66,203.28 C219.66,203.28 219.96,203.21 219.96,203.21 C219.96,203.21 220.25,203.11 220.25,203.11 C220.25,203.11 220.54,203.02 220.54,203.02 C220.54,203.02 220.83,202.9 220.83,202.9 C220.83,202.9 221.11,202.79 221.11,202.79 C221.11,202.79 221.4,202.66 221.4,202.66 C221.4,202.66 221.68,202.54 221.68,202.54 C221.68,202.54 221.96,202.42 221.96,202.42 C221.96,202.42 222.25,202.3 222.25,202.3 C222.25,202.3 222.53,202.19 222.53,202.19 C222.53,202.19 222.82,202.08 222.82,202.08 C222.82,202.08 223.11,201.97 223.11,201.97 C223.11,201.97 223.41,201.89 223.41,201.89 C223.41,201.89 223.71,201.81 223.71,201.81 C223.71,201.81 224,201.73 224,201.73 C224,201.73 224.31,201.68 224.31,201.68 C224.31,201.68 224.61,201.63 224.61,201.63 C224.61,201.63 224.92,201.59 224.92,201.59 C224.92,201.59 225.23,201.57 225.23,201.57 C225.23,201.57 225.53,201.55 225.53,201.55 C225.53,201.55 225.84,201.55 225.84,201.55 C225.84,201.55 226.15,201.56 226.15,201.56 C226.15,201.56 226.46,201.57 226.46,201.57 C226.46,201.57 226.76,201.6 226.76,201.6 C226.76,201.6 227.07,201.65 227.07,201.65 C227.07,201.65 227.37,201.69 227.37,201.69 C227.37,201.69 227.67,201.76 227.67,201.76 C227.67,201.76 227.97,201.84 227.97,201.84 C227.97,201.84 228.27,201.92 228.27,201.92 C228.27,201.92 228.56,202.02 228.56,202.02 C228.56,202.02 228.85,202.12 228.85,202.12 C228.85,202.12 229.14,202.24 229.14,202.24 C229.14,202.24 229.42,202.37 229.42,202.37 C229.42,202.37 229.7,202.5 229.7,202.5 C229.7,202.5 229.97,202.65 229.97,202.65 C229.97,202.65 230.23,202.8 230.23,202.8 C230.23,202.8 230.5,202.96 230.5,202.96 C230.5,202.96 230.75,203.14 230.75,203.14 C230.75,203.14 231,203.32 231,203.32 C231,203.32 231.24,203.51 231.24,203.51 C231.24,203.51 231.48,203.71 231.48,203.71 C231.48,203.71 231.71,203.91 231.71,203.91 C231.71,203.91 231.93,204.13 231.93,204.13 C231.93,204.13 232.15,204.35 232.15,204.35 C232.15,204.35 232.35,204.58 232.35,204.58 C232.35,204.58 232.55,204.81 232.55,204.81 C232.55,204.81 232.75,205.05 232.75,205.05 C232.75,205.05 232.92,205.3 232.92,205.3 C232.92,205.3 233.1,205.56 233.1,205.56 C233.1,205.56 233.27,205.81 233.27,205.81 C233.27,205.81 233.42,206.08 233.42,206.08 C233.42,206.08 233.57,206.35 233.57,206.35 C233.57,206.35 233.7,206.63 233.7,206.63 C233.7,206.63 233.83,206.91 233.83,206.91 C233.83,206.91 233.95,207.19 233.95,207.19 C233.95,207.19 234.05,207.48 234.05,207.48 C234.05,207.48 234.16,207.77 234.16,207.77 C234.16,207.77 234.24,208.07 234.24,208.07 C234.24,208.07 234.31,208.37 234.31,208.37 C234.31,208.37 234.39,208.67 234.39,208.67 C234.39,208.67 234.43,208.97 234.43,208.97 C234.43,208.97 234.48,209.28 234.48,209.28 C234.48,209.28 234.52,209.58 234.52,209.58 C234.52,209.58 234.53,209.89 234.53,209.89 C234.53,209.89 234.54,210.2 234.54,210.2 C234.54,210.2 234.54,210.51 234.54,210.51 C234.54,210.51 234.52,210.82 234.52,210.82 C234.52,210.82 234.5,211.12 234.5,211.12 C234.5,211.12 234.46,211.43 234.46,211.43 C234.46,211.43 234.42,211.73 234.42,211.73 C234.42,211.73 234.37,212.04 234.37,212.04 C234.37,212.04 234.29,212.34 234.29,212.34 C234.29,212.34 234.21,212.64 234.21,212.64 C234.21,212.64 234.13,212.93 234.13,212.93 C234.13,212.93 234.03,213.22 234.03,213.22 C234.03,213.22 233.92,213.51 233.92,213.51 C233.92,213.51 233.81,213.8 233.81,213.8 C233.81,213.8 233.69,214.08 233.69,214.08 C233.69,214.08 233.57,214.37 233.57,214.37 C233.57,214.37 233.44,214.65 233.44,214.65 C233.44,214.65 233.32,214.93 233.32,214.93 C233.32,214.93 233.21,215.22 233.21,215.22 C233.21,215.22 233.1,215.51 233.1,215.51 C233.1,215.51 232.99,215.79 232.99,215.79 C232.99,215.79 232.9,216.09 232.9,216.09 C232.9,216.09 232.82,216.39 232.82,216.39 C232.82,216.39 232.74,216.69 232.74,216.69 C232.74,216.69 232.69,216.99 232.69,216.99 C232.69,216.99 232.64,217.29 232.64,217.29 C232.64,217.29 232.6,217.6 232.6,217.6 C232.6,217.6 232.58,217.91 232.58,217.91 C232.58,217.91 232.56,218.21 232.56,218.21 C232.56,218.21 232.55,218.52 232.55,218.52 C232.55,218.52 232.56,218.83 232.56,218.83 C232.56,218.83 232.57,219.14 232.57,219.14 C232.57,219.14 232.6,219.45 232.6,219.45 C232.6,219.45 232.64,219.75 232.64,219.75 C232.64,219.75 232.68,220.06 232.68,220.06 C232.68,220.06 232.74,220.36 232.74,220.36 C232.74,220.36 232.81,220.66 232.81,220.66 C232.81,220.66 232.88,220.96 232.88,220.96 C232.88,220.96 232.98,221.25 232.98,221.25 C232.98,221.25 233.07,221.54 233.07,221.54 C233.07,221.54 233.19,221.83 233.19,221.83 C233.19,221.83 233.3,222.12 233.3,222.12 C233.3,222.12 233.42,222.4 233.42,222.4 C233.42,222.4 233.55,222.68 233.55,222.68 C233.55,222.68 233.67,222.96 233.67,222.96 C233.67,222.96 233.79,223.25 233.79,223.25 C233.79,223.25 233.9,223.54 233.9,223.54 C233.9,223.54 234.01,223.82 234.01,223.82 C234.01,223.82 234.12,224.11 234.12,224.11 C234.12,224.11 234.2,224.41 234.2,224.41 C234.2,224.41 234.28,224.71 234.28,224.71 C234.28,224.71 234.36,225.01 234.36,225.01 C234.36,225.01 234.41,225.31 234.41,225.31 C234.41,225.31 234.46,225.62 234.46,225.62 C234.46,225.62 234.5,225.92 234.5,225.92 C234.5,225.92 234.52,226.23 234.52,226.23 C234.52,226.23 234.54,226.54 234.54,226.54 C234.54,226.54 234.54,226.84 234.54,226.84 C234.54,226.84 234.53,227.15 234.53,227.15 C234.53,227.15 234.52,227.46 234.52,227.46 C234.52,227.46 234.48,227.77 234.48,227.77 C234.48,227.77 234.44,228.07 234.44,228.07 C234.44,228.07 234.4,228.38 234.4,228.38 C234.4,228.38 234.33,228.68 234.33,228.68 C234.33,228.68 234.25,228.98 234.25,228.98 C234.25,228.98 234.17,229.27 234.17,229.27 C234.17,229.27 234.07,229.56 234.07,229.56 C234.07,229.56 233.97,229.86 233.97,229.86 C233.97,229.86 233.85,230.14 233.85,230.14 C233.85,230.14 233.72,230.42 233.72,230.42 C233.72,230.42 233.59,230.7 233.59,230.7 C233.59,230.7 233.44,230.97 233.44,230.97 C233.44,230.97 233.29,231.24 233.29,231.24 C233.29,231.24 233.13,231.5 233.13,231.5 C233.13,231.5 232.95,231.75 232.95,231.75 C232.95,231.75 232.77,232 232.77,232 C232.77,232 232.58,232.24 232.58,232.24 C232.58,232.24 232.38,232.48 232.38,232.48 C232.38,232.48 232.18,232.71 232.18,232.71 C232.18,232.71 231.96,232.93 231.96,232.93 C231.96,232.93 231.74,233.15 231.74,233.15 C231.74,233.15 231.51,233.35 231.51,233.35 C231.51,233.35 231.28,233.55 231.28,233.55 C231.28,233.55 231.04,233.75 231.04,233.75 C231.04,233.75 230.79,233.92 230.79,233.92 C230.79,233.92 230.53,234.1 230.53,234.1 C230.53,234.1 230.28,234.27 230.28,234.27 C230.28,234.27 230.01,234.42 230.01,234.42 C230.01,234.42 229.74,234.57 229.74,234.57 C229.74,234.57 229.46,234.71 229.46,234.71 C229.46,234.71 229.18,234.83 229.18,234.83 C229.18,234.83 228.9,234.96 228.9,234.96 C228.9,234.96 228.61,235.06 228.61,235.06 C228.61,235.06 228.32,235.16 228.32,235.16 C228.32,235.16 228.02,235.24 228.02,235.24 C228.02,235.24 227.72,235.32 227.72,235.32 C227.72,235.32 227.42,235.39 227.42,235.39 C227.42,235.39 227.12,235.44 227.12,235.44 C227.12,235.44 226.81,235.48 226.81,235.48 C226.81,235.48 226.51,235.52 226.51,235.52 C226.51,235.52 226.2,235.53 226.2,235.53 C226.2,235.53 225.89,235.54 225.89,235.54 C225.89,235.54 225.58,235.54 225.58,235.54 C225.58,235.54 225.27,235.52 225.27,235.52 C225.27,235.52 224.97,235.51 224.97,235.51 C224.97,235.51 224.66,235.47 224.66,235.47 C224.66,235.47 224.36,235.42 224.36,235.42 C224.36,235.42 224.05,235.37 224.05,235.37 C224.05,235.37 223.75,235.3 223.75,235.3 C223.75,235.3 223.45,235.22 223.45,235.22 C223.45,235.22 223.16,235.14 223.16,235.14 C223.16,235.14 222.87,235.03 222.87,235.03 C222.87,235.03 222.58,234.92 222.58,234.92 C222.58,234.92 222.29,234.81 222.29,234.81 C222.29,234.81 222.01,234.69 222.01,234.69 C222.01,234.69 221.72,234.57 221.72,234.57 C221.72,234.57 221.44,234.45 221.44,234.45 C221.44,234.45 221.16,234.32 221.16,234.32 C221.16,234.32 220.87,234.21 220.87,234.21 C220.87,234.21 220.58,234.1 220.58,234.1 C220.58,234.1 220.29,233.99 220.29,233.99 C220.29,233.99 220,233.91 220,233.91 C220,233.91 219.7,233.83 219.7,233.83 C219.7,233.83 219.4,233.75 219.4,233.75 C219.4,233.75 219.1,233.7 219.1,233.7 C219.1,233.7 218.8,233.65 218.8,233.65 C218.8,233.65 218.49,233.6 218.49,233.6 C218.49,233.6 218.18,233.58 218.18,233.58 C218.18,233.58 217.88,233.56 217.88,233.56 C217.88,233.56 217.57,233.55 217.57,233.55 C217.57,233.55 217.26,233.56 217.26,233.56 C217.26,233.56 216.95,233.57 216.95,233.57 C216.95,233.57 216.64,233.6 216.64,233.6 C216.64,233.6 216.34,233.64 216.34,233.64 C216.34,233.64 216.03,233.68 216.03,233.68 C216.03,233.68 215.73,233.74 215.73,233.74 C215.73,233.74 215.43,233.81 215.43,233.81 C215.43,233.81 215.13,233.88 215.13,233.88 C215.13,233.88 214.84,233.98 214.84,233.98 C214.84,233.98 214.55,234.08 214.55,234.08 C214.55,234.08 214.26,234.19 214.26,234.19 C214.26,234.19 213.97,234.3 213.97,234.3 C213.97,234.3 213.69,234.43 213.69,234.43 C213.69,234.43 213.41,234.55 213.41,234.55 C213.41,234.55 213.12,234.67 213.12,234.67 C213.12,234.67 212.84,234.8 212.84,234.8 C212.84,234.8 212.55,234.9 212.55,234.9 C212.55,234.9 212.26,235.01 212.26,235.01 C212.26,235.01 211.98,235.12 211.98,235.12 C211.98,235.12 211.68,235.2 211.68,235.2 C211.68,235.2 211.38,235.28 211.38,235.28 C211.38,235.28 211.08,235.36 211.08,235.36 C211.08,235.36 210.78,235.41 210.78,235.41 C210.78,235.41 210.47,235.46 210.47,235.46 C210.47,235.46 210.17,235.5 210.17,235.5 C210.17,235.5 209.86,235.52 209.86,235.52 C209.86,235.52 209.55,235.54 209.55,235.54 C209.55,235.54 209.25,235.55 209.25,235.55 C209.25,235.55 208.94,235.53 208.94,235.53 C208.94,235.53 208.63,235.52 208.63,235.52 C208.63,235.52 208.32,235.49 208.32,235.49 C208.32,235.49 208.02,235.44 208.02,235.44 C208.02,235.44 207.71,235.4 207.71,235.4 C207.71,235.4 207.41,235.33 207.41,235.33 C207.41,235.33 207.11,235.26 207.11,235.26 C207.11,235.26 206.82,235.17 206.82,235.17 C206.82,235.17 206.53,235.07 206.53,235.07 C206.53,235.07 206.23,234.97 206.23,234.97 C206.23,234.97 205.95,234.85 205.95,234.85 C205.95,234.85 205.67,234.73 205.67,234.73 C205.67,234.73 205.39,234.6 205.39,234.6 C205.39,234.6 205.12,234.44 205.12,234.44 C205.12,234.44 204.85,234.29 204.85,234.29 C204.85,234.29 204.59,234.13 204.59,234.13 C204.59,234.13 204.34,233.95 204.34,233.95 C204.34,233.95 204.09,233.78 204.09,233.78 C204.09,233.78 203.85,233.58 203.85,233.58 C203.85,233.58 203.61,233.39 203.61,233.39 C203.61,233.39 203.38,233.18 203.38,233.18 C203.38,233.18 203.16,232.96 203.16,232.96 C203.16,232.96 202.94,232.75 202.94,232.75 C202.94,232.75 202.74,232.52 202.74,232.52 C202.74,232.52 202.54,232.28 202.54,232.28 C202.54,232.28 202.34,232.04 202.34,232.04 C202.34,232.04 202.16,231.79 202.16,231.79 C202.16,231.79 201.99,231.54 201.99,231.54 C201.99,231.54 201.82,231.28 201.82,231.28 C201.82,231.28 201.67,231.01 201.67,231.01 C201.67,231.01 201.52,230.74 201.52,230.74 C201.52,230.74 201.38,230.46 201.38,230.46 C201.38,230.46 201.26,230.19 201.26,230.19 C201.26,230.19 201.13,229.9 201.13,229.9 C201.13,229.9 201.03,229.61 201.03,229.61 C201.03,229.61 200.93,229.32 200.93,229.32 C200.93,229.32 200.84,229.02 200.84,229.02 C200.84,229.02 200.77,228.72 200.77,228.72 C200.77,228.72 200.7,228.43 200.7,228.43 C200.7,228.43 200.65,228.12 200.65,228.12 C200.65,228.12 200.61,227.82 200.61,227.82 C200.61,227.82 200.57,227.51 200.57,227.51 C200.57,227.51 200.56,227.2 200.56,227.2 C200.56,227.2 200.54,226.89 200.54,226.89 C200.54,226.89 200.55,226.58 200.55,226.58 C200.55,226.58 200.56,226.28 200.56,226.28 C200.56,226.28 200.58,225.97 200.58,225.97 C200.58,225.97 200.62,225.66 200.62,225.66 C200.62,225.66 200.67,225.36 200.67,225.36 C200.67,225.36 200.72,225.06 200.72,225.06 C200.72,225.06 200.79,224.76 200.79,224.76 C200.79,224.76 200.87,224.46 200.87,224.46 C200.87,224.46 200.95,224.16 200.95,224.16 C200.95,224.16 201.06,223.87 201.06,223.87 C201.06,223.87 201.17,223.58 201.17,223.58 C201.17,223.58 201.27,223.29 201.27,223.29 C201.27,223.29 201.4,223.01 201.4,223.01 C201.4,223.01 201.52,222.73 201.52,222.73 C201.52,222.73 201.64,222.45 201.64,222.45 C201.64,222.45 201.76,222.16 201.76,222.16 C201.76,222.16 201.88,221.88 201.88,221.88 C201.88,221.88 201.99,221.59 201.99,221.59 C201.99,221.59 202.1,221.3 202.1,221.3 C202.1,221.3 202.18,221 202.18,221 C202.18,221 202.26,220.71 202.26,220.71 C202.26,220.71 202.34,220.41 202.34,220.41 C202.34,220.41 202.39,220.1 202.39,220.1 C202.39,220.1 202.44,219.8 202.44,219.8 C202.44,219.8 202.49,219.5 202.49,219.5 C202.49,219.5 202.51,219.19 202.51,219.19 C202.51,219.19 202.53,218.88 202.53,218.88 C202.53,218.88 202.54,218.57 202.54,218.57 C202.54,218.57 202.53,218.26 202.53,218.26 C202.53,218.26 202.52,217.96 202.52,217.96 C202.52,217.96 202.49,217.65 202.49,217.65 C202.49,217.65 202.45,217.34 202.45,217.34 C202.45,217.34 202.41,217.04 202.41,217.04 C202.41,217.04 202.34,216.74 202.34,216.74 C202.34,216.74 202.27,216.44 202.27,216.44 C202.27,216.44 202.2,216.14 202.2,216.14 C202.2,216.14 202.11,215.84 202.11,215.84 C202.11,215.84 202.01,215.55 202.01,215.55 C202.01,215.55 201.9,215.26 201.9,215.26 C201.9,215.26 201.78,214.98 201.78,214.98 C201.78,214.98 201.66,214.69 201.66,214.69 C201.66,214.69 201.54,214.41 201.54,214.41 C201.54,214.41 201.42,214.13 201.42,214.13 C201.42,214.13 201.29,213.84 201.29,213.84 C201.29,213.84 201.18,213.55 201.18,213.55 C201.18,213.55 201.07,213.26 201.07,213.26 C201.07,213.26 200.96,212.98 200.96,212.98 C200.96,212.98 200.88,212.68 200.88,212.68 C200.88,212.68 200.8,212.38 200.8,212.38 C200.8,212.38 200.73,212.08 200.73,212.08 C200.73,212.08 200.68,211.78 200.68,211.78 C200.68,211.78 200.63,211.47 200.63,211.47 C200.63,211.47 200.58,211.17 200.58,211.17 C200.58,211.17 200.57,210.86 200.57,210.86 C200.57,210.86 200.55,210.55 200.55,210.55 C200.55,210.55 200.54,210.25 200.54,210.25 C200.54,210.25 200.56,209.94 200.56,209.94 C200.56,209.94 200.57,209.63 200.57,209.63 C200.57,209.63 200.6,209.32 200.6,209.32 C200.6,209.32 200.65,209.02 200.65,209.02 C200.65,209.02 200.69,208.71 200.69,208.71 C200.69,208.71 200.76,208.41 200.76,208.41 C200.76,208.41 200.83,208.11 200.83,208.11 C200.83,208.11 200.92,207.82 200.92,207.82 C200.92,207.82 201.02,207.52 201.02,207.52 C201.02,207.52 201.12,207.23 201.12,207.23 C201.12,207.23 201.24,206.95 201.24,206.95 C201.24,206.95 201.36,206.67 201.36,206.67 C201.36,206.67 201.49,206.39 201.49,206.39 C201.49,206.39 201.65,206.12 201.65,206.12 C201.65,206.12 201.8,205.85 201.8,205.85 C201.8,205.85 201.96,205.59 201.96,205.59 C201.96,205.59 202.14,205.34 202.14,205.34 C202.14,205.34 202.31,205.09 202.31,205.09 C202.31,205.09 202.51,204.85 202.51,204.85 C202.51,204.85 202.71,204.61 202.71,204.61 C202.71,204.61 202.91,204.38 202.91,204.38 C202.91,204.38 203.13,204.16 203.13,204.16 C203.13,204.16 203.34,203.94 203.34,203.94 C203.34,203.94 203.57,203.74 203.57,203.74 C203.57,203.74 203.81,203.54 203.81,203.54 C203.81,203.54 204.05,203.34 204.05,203.34 C204.05,203.34 204.3,203.17 204.3,203.17 C204.3,203.17 204.55,202.99 204.55,202.99 C204.55,202.99 204.81,202.82 204.81,202.82 C204.81,202.82 205.08,202.67 205.08,202.67 C205.08,202.67 205.35,202.52 205.35,202.52 C205.35,202.52 205.63,202.38 205.63,202.38 C205.63,202.38 205.91,202.26 205.91,202.26 C205.91,202.26 206.19,202.13 206.19,202.13 C206.19,202.13 206.48,202.03 206.48,202.03 C206.48,202.03 206.77,201.93 206.77,201.93 C206.77,201.93 207.07,201.85 207.07,201.85 C207.07,201.85 207.37,201.77 207.37,201.77 C207.37,201.77 207.67,201.7 207.67,201.7 C207.67,201.7 207.97,201.65 207.97,201.65 C207.97,201.65 208.28,201.61 208.28,201.61 C208.28,201.61 208.58,201.57 208.58,201.57 C208.58,201.57 208.89,201.56 208.89,201.56 C208.89,201.56 209.2,201.55 209.2,201.55 C209.2,201.55 209.51,201.55 209.51,201.55 C209.51,201.55 209.81,201.57 209.81,201.57 C209.81,201.57 210.12,201.58 210.12,201.58 C210.12,201.58 210.43,201.62 210.43,201.62 C210.43,201.62 210.73,201.67 210.73,201.67 C210.73,201.67 211.04,201.72 211.04,201.72 C211.04,201.72 211.34,201.8 211.34,201.8 C211.34,201.8 211.63,201.88 211.63,201.88 C211.63,201.88 211.93,201.96 211.93,201.96 C211.93,201.96 212.22,202.06 212.22,202.06 C212.22,202.06 212.51,202.17 212.51,202.17 C212.51,202.17 212.8,202.28 212.8,202.28 C212.8,202.28 213.08,202.4 213.08,202.4 C213.08,202.4 213.36,202.52 213.36,202.52 C213.36,202.52 213.65,202.65 213.65,202.65 C213.65,202.65 213.93,202.77 213.93,202.77 C213.93,202.77 214.22,202.88 214.22,202.88 C214.22,202.88 214.5,202.99 214.5,202.99 C214.5,202.99 214.79,203.1 214.79,203.1 C214.79,203.1 215.09,203.19 215.09,203.19 C215.09,203.19 215.39,203.27 215.39,203.27 C215.39,203.27 215.68,203.35 215.68,203.35 C215.68,203.35 215.99,203.4 215.99,203.4 C215.99,203.4 216.29,203.45 216.29,203.45 C216.29,203.45 216.6,203.49 216.6,203.49 C216.6,203.49 216.9,203.51 216.9,203.51 C216.9,203.51 217.21,203.53 217.21,203.53 C217.21,203.53 217.52,203.54 217.52,203.54c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="283" android:startOffset="67" android:valueFrom="M217.52 203.54 C217.52,203.54 217.83,203.53 217.83,203.53 C217.83,203.53 218.14,203.52 218.14,203.52 C218.14,203.52 218.44,203.49 218.44,203.49 C218.44,203.49 218.75,203.45 218.75,203.45 C218.75,203.45 219.05,203.41 219.05,203.41 C219.05,203.41 219.36,203.35 219.36,203.35 C219.36,203.35 219.66,203.28 219.66,203.28 C219.66,203.28 219.96,203.21 219.96,203.21 C219.96,203.21 220.25,203.11 220.25,203.11 C220.25,203.11 220.54,203.02 220.54,203.02 C220.54,203.02 220.83,202.9 220.83,202.9 C220.83,202.9 221.11,202.79 221.11,202.79 C221.11,202.79 221.4,202.66 221.4,202.66 C221.4,202.66 221.68,202.54 221.68,202.54 C221.68,202.54 221.96,202.42 221.96,202.42 C221.96,202.42 222.25,202.3 222.25,202.3 C222.25,202.3 222.53,202.19 222.53,202.19 C222.53,202.19 222.82,202.08 222.82,202.08 C222.82,202.08 223.11,201.97 223.11,201.97 C223.11,201.97 223.41,201.89 223.41,201.89 C223.41,201.89 223.71,201.81 223.71,201.81 C223.71,201.81 224,201.73 224,201.73 C224,201.73 224.31,201.68 224.31,201.68 C224.31,201.68 224.61,201.63 224.61,201.63 C224.61,201.63 224.92,201.59 224.92,201.59 C224.92,201.59 225.23,201.57 225.23,201.57 C225.23,201.57 225.53,201.55 225.53,201.55 C225.53,201.55 225.84,201.55 225.84,201.55 C225.84,201.55 226.15,201.56 226.15,201.56 C226.15,201.56 226.46,201.57 226.46,201.57 C226.46,201.57 226.76,201.6 226.76,201.6 C226.76,201.6 227.07,201.65 227.07,201.65 C227.07,201.65 227.37,201.69 227.37,201.69 C227.37,201.69 227.67,201.76 227.67,201.76 C227.67,201.76 227.97,201.84 227.97,201.84 C227.97,201.84 228.27,201.92 228.27,201.92 C228.27,201.92 228.56,202.02 228.56,202.02 C228.56,202.02 228.85,202.12 228.85,202.12 C228.85,202.12 229.14,202.24 229.14,202.24 C229.14,202.24 229.42,202.37 229.42,202.37 C229.42,202.37 229.7,202.5 229.7,202.5 C229.7,202.5 229.97,202.65 229.97,202.65 C229.97,202.65 230.23,202.8 230.23,202.8 C230.23,202.8 230.5,202.96 230.5,202.96 C230.5,202.96 230.75,203.14 230.75,203.14 C230.75,203.14 231,203.32 231,203.32 C231,203.32 231.24,203.51 231.24,203.51 C231.24,203.51 231.48,203.71 231.48,203.71 C231.48,203.71 231.71,203.91 231.71,203.91 C231.71,203.91 231.93,204.13 231.93,204.13 C231.93,204.13 232.15,204.35 232.15,204.35 C232.15,204.35 232.35,204.58 232.35,204.58 C232.35,204.58 232.55,204.81 232.55,204.81 C232.55,204.81 232.75,205.05 232.75,205.05 C232.75,205.05 232.92,205.3 232.92,205.3 C232.92,205.3 233.1,205.56 233.1,205.56 C233.1,205.56 233.27,205.81 233.27,205.81 C233.27,205.81 233.42,206.08 233.42,206.08 C233.42,206.08 233.57,206.35 233.57,206.35 C233.57,206.35 233.7,206.63 233.7,206.63 C233.7,206.63 233.83,206.91 233.83,206.91 C233.83,206.91 233.95,207.19 233.95,207.19 C233.95,207.19 234.05,207.48 234.05,207.48 C234.05,207.48 234.16,207.77 234.16,207.77 C234.16,207.77 234.24,208.07 234.24,208.07 C234.24,208.07 234.31,208.37 234.31,208.37 C234.31,208.37 234.39,208.67 234.39,208.67 C234.39,208.67 234.43,208.97 234.43,208.97 C234.43,208.97 234.48,209.28 234.48,209.28 C234.48,209.28 234.52,209.58 234.52,209.58 C234.52,209.58 234.53,209.89 234.53,209.89 C234.53,209.89 234.54,210.2 234.54,210.2 C234.54,210.2 234.54,210.51 234.54,210.51 C234.54,210.51 234.52,210.82 234.52,210.82 C234.52,210.82 234.5,211.12 234.5,211.12 C234.5,211.12 234.46,211.43 234.46,211.43 C234.46,211.43 234.42,211.73 234.42,211.73 C234.42,211.73 234.37,212.04 234.37,212.04 C234.37,212.04 234.29,212.34 234.29,212.34 C234.29,212.34 234.21,212.64 234.21,212.64 C234.21,212.64 234.13,212.93 234.13,212.93 C234.13,212.93 234.03,213.22 234.03,213.22 C234.03,213.22 233.92,213.51 233.92,213.51 C233.92,213.51 233.81,213.8 233.81,213.8 C233.81,213.8 233.69,214.08 233.69,214.08 C233.69,214.08 233.57,214.37 233.57,214.37 C233.57,214.37 233.44,214.65 233.44,214.65 C233.44,214.65 233.32,214.93 233.32,214.93 C233.32,214.93 233.21,215.22 233.21,215.22 C233.21,215.22 233.1,215.51 233.1,215.51 C233.1,215.51 232.99,215.79 232.99,215.79 C232.99,215.79 232.9,216.09 232.9,216.09 C232.9,216.09 232.82,216.39 232.82,216.39 C232.82,216.39 232.74,216.69 232.74,216.69 C232.74,216.69 232.69,216.99 232.69,216.99 C232.69,216.99 232.64,217.29 232.64,217.29 C232.64,217.29 232.6,217.6 232.6,217.6 C232.6,217.6 232.58,217.91 232.58,217.91 C232.58,217.91 232.56,218.21 232.56,218.21 C232.56,218.21 232.55,218.52 232.55,218.52 C232.55,218.52 232.56,218.83 232.56,218.83 C232.56,218.83 232.57,219.14 232.57,219.14 C232.57,219.14 232.6,219.45 232.6,219.45 C232.6,219.45 232.64,219.75 232.64,219.75 C232.64,219.75 232.68,220.06 232.68,220.06 C232.68,220.06 232.74,220.36 232.74,220.36 C232.74,220.36 232.81,220.66 232.81,220.66 C232.81,220.66 232.88,220.96 232.88,220.96 C232.88,220.96 232.98,221.25 232.98,221.25 C232.98,221.25 233.07,221.54 233.07,221.54 C233.07,221.54 233.19,221.83 233.19,221.83 C233.19,221.83 233.3,222.12 233.3,222.12 C233.3,222.12 233.42,222.4 233.42,222.4 C233.42,222.4 233.55,222.68 233.55,222.68 C233.55,222.68 233.67,222.96 233.67,222.96 C233.67,222.96 233.79,223.25 233.79,223.25 C233.79,223.25 233.9,223.54 233.9,223.54 C233.9,223.54 234.01,223.82 234.01,223.82 C234.01,223.82 234.12,224.11 234.12,224.11 C234.12,224.11 234.2,224.41 234.2,224.41 C234.2,224.41 234.28,224.71 234.28,224.71 C234.28,224.71 234.36,225.01 234.36,225.01 C234.36,225.01 234.41,225.31 234.41,225.31 C234.41,225.31 234.46,225.62 234.46,225.62 C234.46,225.62 234.5,225.92 234.5,225.92 C234.5,225.92 234.52,226.23 234.52,226.23 C234.52,226.23 234.54,226.54 234.54,226.54 C234.54,226.54 234.54,226.84 234.54,226.84 C234.54,226.84 234.53,227.15 234.53,227.15 C234.53,227.15 234.52,227.46 234.52,227.46 C234.52,227.46 234.48,227.77 234.48,227.77 C234.48,227.77 234.44,228.07 234.44,228.07 C234.44,228.07 234.4,228.38 234.4,228.38 C234.4,228.38 234.33,228.68 234.33,228.68 C234.33,228.68 234.25,228.98 234.25,228.98 C234.25,228.98 234.17,229.27 234.17,229.27 C234.17,229.27 234.07,229.56 234.07,229.56 C234.07,229.56 233.97,229.86 233.97,229.86 C233.97,229.86 233.85,230.14 233.85,230.14 C233.85,230.14 233.72,230.42 233.72,230.42 C233.72,230.42 233.59,230.7 233.59,230.7 C233.59,230.7 233.44,230.97 233.44,230.97 C233.44,230.97 233.29,231.24 233.29,231.24 C233.29,231.24 233.13,231.5 233.13,231.5 C233.13,231.5 232.95,231.75 232.95,231.75 C232.95,231.75 232.77,232 232.77,232 C232.77,232 232.58,232.24 232.58,232.24 C232.58,232.24 232.38,232.48 232.38,232.48 C232.38,232.48 232.18,232.71 232.18,232.71 C232.18,232.71 231.96,232.93 231.96,232.93 C231.96,232.93 231.74,233.15 231.74,233.15 C231.74,233.15 231.51,233.35 231.51,233.35 C231.51,233.35 231.28,233.55 231.28,233.55 C231.28,233.55 231.04,233.75 231.04,233.75 C231.04,233.75 230.79,233.92 230.79,233.92 C230.79,233.92 230.53,234.1 230.53,234.1 C230.53,234.1 230.28,234.27 230.28,234.27 C230.28,234.27 230.01,234.42 230.01,234.42 C230.01,234.42 229.74,234.57 229.74,234.57 C229.74,234.57 229.46,234.71 229.46,234.71 C229.46,234.71 229.18,234.83 229.18,234.83 C229.18,234.83 228.9,234.96 228.9,234.96 C228.9,234.96 228.61,235.06 228.61,235.06 C228.61,235.06 228.32,235.16 228.32,235.16 C228.32,235.16 228.02,235.24 228.02,235.24 C228.02,235.24 227.72,235.32 227.72,235.32 C227.72,235.32 227.42,235.39 227.42,235.39 C227.42,235.39 227.12,235.44 227.12,235.44 C227.12,235.44 226.81,235.48 226.81,235.48 C226.81,235.48 226.51,235.52 226.51,235.52 C226.51,235.52 226.2,235.53 226.2,235.53 C226.2,235.53 225.89,235.54 225.89,235.54 C225.89,235.54 225.58,235.54 225.58,235.54 C225.58,235.54 225.27,235.52 225.27,235.52 C225.27,235.52 224.97,235.51 224.97,235.51 C224.97,235.51 224.66,235.47 224.66,235.47 C224.66,235.47 224.36,235.42 224.36,235.42 C224.36,235.42 224.05,235.37 224.05,235.37 C224.05,235.37 223.75,235.3 223.75,235.3 C223.75,235.3 223.45,235.22 223.45,235.22 C223.45,235.22 223.16,235.14 223.16,235.14 C223.16,235.14 222.87,235.03 222.87,235.03 C222.87,235.03 222.58,234.92 222.58,234.92 C222.58,234.92 222.29,234.81 222.29,234.81 C222.29,234.81 222.01,234.69 222.01,234.69 C222.01,234.69 221.72,234.57 221.72,234.57 C221.72,234.57 221.44,234.45 221.44,234.45 C221.44,234.45 221.16,234.32 221.16,234.32 C221.16,234.32 220.87,234.21 220.87,234.21 C220.87,234.21 220.58,234.1 220.58,234.1 C220.58,234.1 220.29,233.99 220.29,233.99 C220.29,233.99 220,233.91 220,233.91 C220,233.91 219.7,233.83 219.7,233.83 C219.7,233.83 219.4,233.75 219.4,233.75 C219.4,233.75 219.1,233.7 219.1,233.7 C219.1,233.7 218.8,233.65 218.8,233.65 C218.8,233.65 218.49,233.6 218.49,233.6 C218.49,233.6 218.18,233.58 218.18,233.58 C218.18,233.58 217.88,233.56 217.88,233.56 C217.88,233.56 217.57,233.55 217.57,233.55 C217.57,233.55 217.26,233.56 217.26,233.56 C217.26,233.56 216.95,233.57 216.95,233.57 C216.95,233.57 216.64,233.6 216.64,233.6 C216.64,233.6 216.34,233.64 216.34,233.64 C216.34,233.64 216.03,233.68 216.03,233.68 C216.03,233.68 215.73,233.74 215.73,233.74 C215.73,233.74 215.43,233.81 215.43,233.81 C215.43,233.81 215.13,233.88 215.13,233.88 C215.13,233.88 214.84,233.98 214.84,233.98 C214.84,233.98 214.55,234.08 214.55,234.08 C214.55,234.08 214.26,234.19 214.26,234.19 C214.26,234.19 213.97,234.3 213.97,234.3 C213.97,234.3 213.69,234.43 213.69,234.43 C213.69,234.43 213.41,234.55 213.41,234.55 C213.41,234.55 213.12,234.67 213.12,234.67 C213.12,234.67 212.84,234.8 212.84,234.8 C212.84,234.8 212.55,234.9 212.55,234.9 C212.55,234.9 212.26,235.01 212.26,235.01 C212.26,235.01 211.98,235.12 211.98,235.12 C211.98,235.12 211.68,235.2 211.68,235.2 C211.68,235.2 211.38,235.28 211.38,235.28 C211.38,235.28 211.08,235.36 211.08,235.36 C211.08,235.36 210.78,235.41 210.78,235.41 C210.78,235.41 210.47,235.46 210.47,235.46 C210.47,235.46 210.17,235.5 210.17,235.5 C210.17,235.5 209.86,235.52 209.86,235.52 C209.86,235.52 209.55,235.54 209.55,235.54 C209.55,235.54 209.25,235.55 209.25,235.55 C209.25,235.55 208.94,235.53 208.94,235.53 C208.94,235.53 208.63,235.52 208.63,235.52 C208.63,235.52 208.32,235.49 208.32,235.49 C208.32,235.49 208.02,235.44 208.02,235.44 C208.02,235.44 207.71,235.4 207.71,235.4 C207.71,235.4 207.41,235.33 207.41,235.33 C207.41,235.33 207.11,235.26 207.11,235.26 C207.11,235.26 206.82,235.17 206.82,235.17 C206.82,235.17 206.53,235.07 206.53,235.07 C206.53,235.07 206.23,234.97 206.23,234.97 C206.23,234.97 205.95,234.85 205.95,234.85 C205.95,234.85 205.67,234.73 205.67,234.73 C205.67,234.73 205.39,234.6 205.39,234.6 C205.39,234.6 205.12,234.44 205.12,234.44 C205.12,234.44 204.85,234.29 204.85,234.29 C204.85,234.29 204.59,234.13 204.59,234.13 C204.59,234.13 204.34,233.95 204.34,233.95 C204.34,233.95 204.09,233.78 204.09,233.78 C204.09,233.78 203.85,233.58 203.85,233.58 C203.85,233.58 203.61,233.39 203.61,233.39 C203.61,233.39 203.38,233.18 203.38,233.18 C203.38,233.18 203.16,232.96 203.16,232.96 C203.16,232.96 202.94,232.75 202.94,232.75 C202.94,232.75 202.74,232.52 202.74,232.52 C202.74,232.52 202.54,232.28 202.54,232.28 C202.54,232.28 202.34,232.04 202.34,232.04 C202.34,232.04 202.16,231.79 202.16,231.79 C202.16,231.79 201.99,231.54 201.99,231.54 C201.99,231.54 201.82,231.28 201.82,231.28 C201.82,231.28 201.67,231.01 201.67,231.01 C201.67,231.01 201.52,230.74 201.52,230.74 C201.52,230.74 201.38,230.46 201.38,230.46 C201.38,230.46 201.26,230.19 201.26,230.19 C201.26,230.19 201.13,229.9 201.13,229.9 C201.13,229.9 201.03,229.61 201.03,229.61 C201.03,229.61 200.93,229.32 200.93,229.32 C200.93,229.32 200.84,229.02 200.84,229.02 C200.84,229.02 200.77,228.72 200.77,228.72 C200.77,228.72 200.7,228.43 200.7,228.43 C200.7,228.43 200.65,228.12 200.65,228.12 C200.65,228.12 200.61,227.82 200.61,227.82 C200.61,227.82 200.57,227.51 200.57,227.51 C200.57,227.51 200.56,227.2 200.56,227.2 C200.56,227.2 200.54,226.89 200.54,226.89 C200.54,226.89 200.55,226.58 200.55,226.58 C200.55,226.58 200.56,226.28 200.56,226.28 C200.56,226.28 200.58,225.97 200.58,225.97 C200.58,225.97 200.62,225.66 200.62,225.66 C200.62,225.66 200.67,225.36 200.67,225.36 C200.67,225.36 200.72,225.06 200.72,225.06 C200.72,225.06 200.79,224.76 200.79,224.76 C200.79,224.76 200.87,224.46 200.87,224.46 C200.87,224.46 200.95,224.16 200.95,224.16 C200.95,224.16 201.06,223.87 201.06,223.87 C201.06,223.87 201.17,223.58 201.17,223.58 C201.17,223.58 201.27,223.29 201.27,223.29 C201.27,223.29 201.4,223.01 201.4,223.01 C201.4,223.01 201.52,222.73 201.52,222.73 C201.52,222.73 201.64,222.45 201.64,222.45 C201.64,222.45 201.76,222.16 201.76,222.16 C201.76,222.16 201.88,221.88 201.88,221.88 C201.88,221.88 201.99,221.59 201.99,221.59 C201.99,221.59 202.1,221.3 202.1,221.3 C202.1,221.3 202.18,221 202.18,221 C202.18,221 202.26,220.71 202.26,220.71 C202.26,220.71 202.34,220.41 202.34,220.41 C202.34,220.41 202.39,220.1 202.39,220.1 C202.39,220.1 202.44,219.8 202.44,219.8 C202.44,219.8 202.49,219.5 202.49,219.5 C202.49,219.5 202.51,219.19 202.51,219.19 C202.51,219.19 202.53,218.88 202.53,218.88 C202.53,218.88 202.54,218.57 202.54,218.57 C202.54,218.57 202.53,218.26 202.53,218.26 C202.53,218.26 202.52,217.96 202.52,217.96 C202.52,217.96 202.49,217.65 202.49,217.65 C202.49,217.65 202.45,217.34 202.45,217.34 C202.45,217.34 202.41,217.04 202.41,217.04 C202.41,217.04 202.34,216.74 202.34,216.74 C202.34,216.74 202.27,216.44 202.27,216.44 C202.27,216.44 202.2,216.14 202.2,216.14 C202.2,216.14 202.11,215.84 202.11,215.84 C202.11,215.84 202.01,215.55 202.01,215.55 C202.01,215.55 201.9,215.26 201.9,215.26 C201.9,215.26 201.78,214.98 201.78,214.98 C201.78,214.98 201.66,214.69 201.66,214.69 C201.66,214.69 201.54,214.41 201.54,214.41 C201.54,214.41 201.42,214.13 201.42,214.13 C201.42,214.13 201.29,213.84 201.29,213.84 C201.29,213.84 201.18,213.55 201.18,213.55 C201.18,213.55 201.07,213.26 201.07,213.26 C201.07,213.26 200.96,212.98 200.96,212.98 C200.96,212.98 200.88,212.68 200.88,212.68 C200.88,212.68 200.8,212.38 200.8,212.38 C200.8,212.38 200.73,212.08 200.73,212.08 C200.73,212.08 200.68,211.78 200.68,211.78 C200.68,211.78 200.63,211.47 200.63,211.47 C200.63,211.47 200.58,211.17 200.58,211.17 C200.58,211.17 200.57,210.86 200.57,210.86 C200.57,210.86 200.55,210.55 200.55,210.55 C200.55,210.55 200.54,210.25 200.54,210.25 C200.54,210.25 200.56,209.94 200.56,209.94 C200.56,209.94 200.57,209.63 200.57,209.63 C200.57,209.63 200.6,209.32 200.6,209.32 C200.6,209.32 200.65,209.02 200.65,209.02 C200.65,209.02 200.69,208.71 200.69,208.71 C200.69,208.71 200.76,208.41 200.76,208.41 C200.76,208.41 200.83,208.11 200.83,208.11 C200.83,208.11 200.92,207.82 200.92,207.82 C200.92,207.82 201.02,207.52 201.02,207.52 C201.02,207.52 201.12,207.23 201.12,207.23 C201.12,207.23 201.24,206.95 201.24,206.95 C201.24,206.95 201.36,206.67 201.36,206.67 C201.36,206.67 201.49,206.39 201.49,206.39 C201.49,206.39 201.65,206.12 201.65,206.12 C201.65,206.12 201.8,205.85 201.8,205.85 C201.8,205.85 201.96,205.59 201.96,205.59 C201.96,205.59 202.14,205.34 202.14,205.34 C202.14,205.34 202.31,205.09 202.31,205.09 C202.31,205.09 202.51,204.85 202.51,204.85 C202.51,204.85 202.71,204.61 202.71,204.61 C202.71,204.61 202.91,204.38 202.91,204.38 C202.91,204.38 203.13,204.16 203.13,204.16 C203.13,204.16 203.34,203.94 203.34,203.94 C203.34,203.94 203.57,203.74 203.57,203.74 C203.57,203.74 203.81,203.54 203.81,203.54 C203.81,203.54 204.05,203.34 204.05,203.34 C204.05,203.34 204.3,203.17 204.3,203.17 C204.3,203.17 204.55,202.99 204.55,202.99 C204.55,202.99 204.81,202.82 204.81,202.82 C204.81,202.82 205.08,202.67 205.08,202.67 C205.08,202.67 205.35,202.52 205.35,202.52 C205.35,202.52 205.63,202.38 205.63,202.38 C205.63,202.38 205.91,202.26 205.91,202.26 C205.91,202.26 206.19,202.13 206.19,202.13 C206.19,202.13 206.48,202.03 206.48,202.03 C206.48,202.03 206.77,201.93 206.77,201.93 C206.77,201.93 207.07,201.85 207.07,201.85 C207.07,201.85 207.37,201.77 207.37,201.77 C207.37,201.77 207.67,201.7 207.67,201.7 C207.67,201.7 207.97,201.65 207.97,201.65 C207.97,201.65 208.28,201.61 208.28,201.61 C208.28,201.61 208.58,201.57 208.58,201.57 C208.58,201.57 208.89,201.56 208.89,201.56 C208.89,201.56 209.2,201.55 209.2,201.55 C209.2,201.55 209.51,201.55 209.51,201.55 C209.51,201.55 209.81,201.57 209.81,201.57 C209.81,201.57 210.12,201.58 210.12,201.58 C210.12,201.58 210.43,201.62 210.43,201.62 C210.43,201.62 210.73,201.67 210.73,201.67 C210.73,201.67 211.04,201.72 211.04,201.72 C211.04,201.72 211.34,201.8 211.34,201.8 C211.34,201.8 211.63,201.88 211.63,201.88 C211.63,201.88 211.93,201.96 211.93,201.96 C211.93,201.96 212.22,202.06 212.22,202.06 C212.22,202.06 212.51,202.17 212.51,202.17 C212.51,202.17 212.8,202.28 212.8,202.28 C212.8,202.28 213.08,202.4 213.08,202.4 C213.08,202.4 213.36,202.52 213.36,202.52 C213.36,202.52 213.65,202.65 213.65,202.65 C213.65,202.65 213.93,202.77 213.93,202.77 C213.93,202.77 214.22,202.88 214.22,202.88 C214.22,202.88 214.5,202.99 214.5,202.99 C214.5,202.99 214.79,203.1 214.79,203.1 C214.79,203.1 215.09,203.19 215.09,203.19 C215.09,203.19 215.39,203.27 215.39,203.27 C215.39,203.27 215.68,203.35 215.68,203.35 C215.68,203.35 215.99,203.4 215.99,203.4 C215.99,203.4 216.29,203.45 216.29,203.45 C216.29,203.45 216.6,203.49 216.6,203.49 C216.6,203.49 216.9,203.51 216.9,203.51 C216.9,203.51 217.21,203.53 217.21,203.53 C217.21,203.53 217.52,203.54 217.52,203.54c " android:valueTo="M217.68 210.56 C217.68,210.56 217.81,210.57 217.81,210.57 C217.81,210.57 217.93,210.57 217.93,210.57 C217.93,210.57 218.06,210.58 218.06,210.58 C218.06,210.58 218.18,210.59 218.18,210.59 C218.18,210.59 218.31,210.59 218.31,210.59 C218.31,210.59 218.43,210.61 218.43,210.61 C218.43,210.61 218.56,210.63 218.56,210.63 C218.56,210.63 218.68,210.64 218.68,210.64 C218.68,210.64 218.81,210.66 218.81,210.66 C218.81,210.66 218.93,210.68 218.93,210.68 C218.93,210.68 219.05,210.7 219.05,210.7 C219.05,210.7 219.18,210.72 219.18,210.72 C219.18,210.72 219.3,210.75 219.3,210.75 C219.3,210.75 219.42,210.78 219.42,210.78 C219.42,210.78 219.54,210.81 219.54,210.81 C219.54,210.81 219.66,210.84 219.66,210.84 C219.66,210.84 219.79,210.87 219.79,210.87 C219.79,210.87 219.91,210.91 219.91,210.91 C219.91,210.91 220.03,210.95 220.03,210.95 C220.03,210.95 220.14,210.99 220.14,210.99 C220.14,210.99 220.26,211.04 220.26,211.04 C220.26,211.04 220.38,211.08 220.38,211.08 C220.38,211.08 220.5,211.12 220.5,211.12 C220.5,211.12 220.62,211.17 220.62,211.17 C220.62,211.17 220.73,211.22 220.73,211.22 C220.73,211.22 220.84,211.27 220.84,211.27 C220.84,211.27 220.96,211.32 220.96,211.32 C220.96,211.32 221.07,211.38 221.07,211.38 C221.07,211.38 221.19,211.43 221.19,211.43 C221.19,211.43 221.3,211.49 221.3,211.49 C221.3,211.49 221.41,211.55 221.41,211.55 C221.41,211.55 221.51,211.61 221.51,211.61 C221.51,211.61 221.62,211.68 221.62,211.68 C221.62,211.68 221.73,211.74 221.73,211.74 C221.73,211.74 221.84,211.8 221.84,211.8 C221.84,211.8 221.94,211.87 221.94,211.87 C221.94,211.87 222.05,211.94 222.05,211.94 C222.05,211.94 222.15,212.02 222.15,212.02 C222.15,212.02 222.25,212.09 222.25,212.09 C222.25,212.09 222.35,212.16 222.35,212.16 C222.35,212.16 222.46,212.23 222.46,212.23 C222.46,212.23 222.55,212.31 222.55,212.31 C222.55,212.31 222.65,212.4 222.65,212.4 C222.65,212.4 222.74,212.48 222.74,212.48 C222.74,212.48 222.84,212.56 222.84,212.56 C222.84,212.56 222.93,212.64 222.93,212.64 C222.93,212.64 223.03,212.72 223.03,212.72 C223.03,212.72 223.12,212.81 223.12,212.81 C223.12,212.81 223.21,212.9 223.21,212.9 C223.21,212.9 223.29,212.99 223.29,212.99 C223.29,212.99 223.38,213.08 223.38,213.08 C223.38,213.08 223.47,213.17 223.47,213.17 C223.47,213.17 223.55,213.26 223.55,213.26 C223.55,213.26 223.63,213.36 223.63,213.36 C223.63,213.36 223.71,213.46 223.71,213.46 C223.71,213.46 223.79,213.56 223.79,213.56 C223.79,213.56 223.87,213.66 223.87,213.66 C223.87,213.66 223.95,213.75 223.95,213.75 C223.95,213.75 224.03,213.85 224.03,213.85 C224.03,213.85 224.09,213.96 224.09,213.96 C224.09,213.96 224.16,214.06 224.16,214.06 C224.16,214.06 224.23,214.17 224.23,214.17 C224.23,214.17 224.3,214.27 224.3,214.27 C224.3,214.27 224.37,214.38 224.37,214.38 C224.37,214.38 224.44,214.48 224.44,214.48 C224.44,214.48 224.5,214.59 224.5,214.59 C224.5,214.59 224.56,214.7 224.56,214.7 C224.56,214.7 224.62,214.81 224.62,214.81 C224.62,214.81 224.68,214.93 224.68,214.93 C224.68,214.93 224.74,215.04 224.74,215.04 C224.74,215.04 224.79,215.15 224.79,215.15 C224.79,215.15 224.84,215.26 224.84,215.26 C224.84,215.26 224.89,215.38 224.89,215.38 C224.89,215.38 224.94,215.5 224.94,215.5 C224.94,215.5 224.99,215.61 224.99,215.61 C224.99,215.61 225.04,215.73 225.04,215.73 C225.04,215.73 225.08,215.84 225.08,215.84 C225.08,215.84 225.12,215.96 225.12,215.96 C225.12,215.96 225.16,216.08 225.16,216.08 C225.16,216.08 225.19,216.2 225.19,216.2 C225.19,216.2 225.23,216.32 225.23,216.32 C225.23,216.32 225.27,216.44 225.27,216.44 C225.27,216.44 225.3,216.56 225.3,216.56 C225.3,216.56 225.33,216.69 225.33,216.69 C225.33,216.69 225.35,216.81 225.35,216.81 C225.35,216.81 225.38,216.93 225.38,216.93 C225.38,216.93 225.41,217.06 225.41,217.06 C225.41,217.06 225.43,217.18 225.43,217.18 C225.43,217.18 225.46,217.3 225.46,217.3 C225.46,217.3 225.47,217.43 225.47,217.43 C225.47,217.43 225.49,217.55 225.49,217.55 C225.49,217.55 225.5,217.68 225.5,217.68 C225.5,217.68 225.52,217.8 225.52,217.8 C225.52,217.8 225.52,217.93 225.52,217.93 C225.52,217.93 225.53,218.05 225.53,218.05 C225.53,218.05 225.54,218.18 225.54,218.18 C225.54,218.18 225.54,218.3 225.54,218.3 C225.54,218.3 225.55,218.43 225.55,218.43 C225.55,218.43 225.55,218.55 225.55,218.55 C225.55,218.55 225.55,218.68 225.55,218.68 C225.55,218.68 225.54,218.8 225.54,218.8 C225.54,218.8 225.54,218.93 225.54,218.93 C225.54,218.93 225.53,219.05 225.53,219.05 C225.53,219.05 225.52,219.18 225.52,219.18 C225.52,219.18 225.52,219.31 225.52,219.31 C225.52,219.31 225.5,219.43 225.5,219.43 C225.5,219.43 225.48,219.55 225.48,219.55 C225.48,219.55 225.47,219.68 225.47,219.68 C225.47,219.68 225.45,219.8 225.45,219.8 C225.45,219.8 225.43,219.93 225.43,219.93 C225.43,219.93 225.41,220.05 225.41,220.05 C225.41,220.05 225.39,220.17 225.39,220.17 C225.39,220.17 225.36,220.3 225.36,220.3 C225.36,220.3 225.33,220.42 225.33,220.42 C225.33,220.42 225.3,220.54 225.3,220.54 C225.3,220.54 225.27,220.66 225.27,220.66 C225.27,220.66 225.24,220.78 225.24,220.78 C225.24,220.78 225.2,220.9 225.2,220.9 C225.2,220.9 225.16,221.02 225.16,221.02 C225.16,221.02 225.12,221.14 225.12,221.14 C225.12,221.14 225.08,221.26 225.08,221.26 C225.08,221.26 225.03,221.38 225.03,221.38 C225.03,221.38 224.99,221.5 224.99,221.5 C224.99,221.5 224.95,221.61 224.95,221.61 C224.95,221.61 224.89,221.73 224.89,221.73 C224.89,221.73 224.84,221.84 224.84,221.84 C224.84,221.84 224.79,221.96 224.79,221.96 C224.79,221.96 224.73,222.07 224.73,222.07 C224.73,222.07 224.68,222.18 224.68,222.18 C224.68,222.18 224.62,222.29 224.62,222.29 C224.62,222.29 224.56,222.4 224.56,222.4 C224.56,222.4 224.5,222.51 224.5,222.51 C224.5,222.51 224.44,222.62 224.44,222.62 C224.44,222.62 224.37,222.73 224.37,222.73 C224.37,222.73 224.31,222.84 224.31,222.84 C224.31,222.84 224.24,222.94 224.24,222.94 C224.24,222.94 224.17,223.05 224.17,223.05 C224.17,223.05 224.09,223.15 224.09,223.15 C224.09,223.15 224.02,223.25 224.02,223.25 C224.02,223.25 223.95,223.35 223.95,223.35 C223.95,223.35 223.88,223.45 223.88,223.45 C223.88,223.45 223.8,223.55 223.8,223.55 C223.8,223.55 223.71,223.65 223.71,223.65 C223.71,223.65 223.63,223.74 223.63,223.74 C223.63,223.74 223.55,223.84 223.55,223.84 C223.55,223.84 223.47,223.93 223.47,223.93 C223.47,223.93 223.39,224.03 223.39,224.03 C223.39,224.03 223.3,224.12 223.3,224.12 C223.3,224.12 223.21,224.2 223.21,224.2 C223.21,224.2 223.12,224.29 223.12,224.29 C223.12,224.29 223.03,224.38 223.03,224.38 C223.03,224.38 222.94,224.46 222.94,224.46 C222.94,224.46 222.85,224.55 222.85,224.55 C222.85,224.55 222.75,224.63 222.75,224.63 C222.75,224.63 222.65,224.71 222.65,224.71 C222.65,224.71 222.55,224.79 222.55,224.79 C222.55,224.79 222.46,224.87 222.46,224.87 C222.46,224.87 222.36,224.95 222.36,224.95 C222.36,224.95 222.26,225.02 222.26,225.02 C222.26,225.02 222.15,225.09 222.15,225.09 C222.15,225.09 222.05,225.16 222.05,225.16 C222.05,225.16 221.94,225.23 221.94,225.23 C221.94,225.23 221.84,225.3 221.84,225.3 C221.84,225.3 221.74,225.37 221.74,225.37 C221.74,225.37 221.63,225.44 221.63,225.44 C221.63,225.44 221.52,225.5 221.52,225.5 C221.52,225.5 221.41,225.56 221.41,225.56 C221.41,225.56 221.3,225.62 221.3,225.62 C221.3,225.62 221.19,225.68 221.19,225.68 C221.19,225.68 221.08,225.73 221.08,225.73 C221.08,225.73 220.96,225.79 220.96,225.79 C220.96,225.79 220.85,225.84 220.85,225.84 C220.85,225.84 220.73,225.89 220.73,225.89 C220.73,225.89 220.62,225.94 220.62,225.94 C220.62,225.94 220.5,225.99 220.5,225.99 C220.5,225.99 220.38,226.03 220.38,226.03 C220.38,226.03 220.27,226.08 220.27,226.08 C220.27,226.08 220.15,226.12 220.15,226.12 C220.15,226.12 220.03,226.15 220.03,226.15 C220.03,226.15 219.91,226.19 219.91,226.19 C219.91,226.19 219.79,226.23 219.79,226.23 C219.79,226.23 219.67,226.27 219.67,226.27 C219.67,226.27 219.55,226.3 219.55,226.3 C219.55,226.3 219.42,226.33 219.42,226.33 C219.42,226.33 219.3,226.35 219.3,226.35 C219.3,226.35 219.18,226.38 219.18,226.38 C219.18,226.38 219.06,226.4 219.06,226.4 C219.06,226.4 218.93,226.43 218.93,226.43 C218.93,226.43 218.81,226.45 218.81,226.45 C218.81,226.45 218.68,226.47 218.68,226.47 C218.68,226.47 218.56,226.49 218.56,226.49 C218.56,226.49 218.44,226.5 218.44,226.5 C218.44,226.5 218.31,226.52 218.31,226.52 C218.31,226.52 218.19,226.52 218.19,226.52 C218.19,226.52 218.06,226.53 218.06,226.53 C218.06,226.53 217.93,226.53 217.93,226.53 C217.93,226.53 217.81,226.54 217.81,226.54 C217.81,226.54 217.68,226.55 217.68,226.55 C217.68,226.55 217.56,226.55 217.56,226.55 C217.56,226.55 217.43,226.55 217.43,226.55 C217.43,226.55 217.31,226.54 217.31,226.54 C217.31,226.54 217.18,226.53 217.18,226.53 C217.18,226.53 217.05,226.53 217.05,226.53 C217.05,226.53 216.93,226.52 216.93,226.52 C216.93,226.52 216.8,226.52 216.8,226.52 C216.8,226.52 216.68,226.5 216.68,226.5 C216.68,226.5 216.55,226.48 216.55,226.48 C216.55,226.48 216.43,226.46 216.43,226.46 C216.43,226.46 216.31,226.45 216.31,226.45 C216.31,226.45 216.18,226.43 216.18,226.43 C216.18,226.43 216.06,226.41 216.06,226.41 C216.06,226.41 215.93,226.38 215.93,226.38 C215.93,226.38 215.81,226.35 215.81,226.35 C215.81,226.35 215.69,226.32 215.69,226.32 C215.69,226.32 215.57,226.29 215.57,226.29 C215.57,226.29 215.45,226.26 215.45,226.26 C215.45,226.26 215.32,226.23 215.32,226.23 C215.32,226.23 215.2,226.2 215.2,226.2 C215.2,226.2 215.09,226.16 215.09,226.16 C215.09,226.16 214.97,226.12 214.97,226.12 C214.97,226.12 214.85,226.07 214.85,226.07 C214.85,226.07 214.73,226.03 214.73,226.03 C214.73,226.03 214.61,225.99 214.61,225.99 C214.61,225.99 214.5,225.94 214.5,225.94 C214.5,225.94 214.38,225.89 214.38,225.89 C214.38,225.89 214.27,225.84 214.27,225.84 C214.27,225.84 214.15,225.79 214.15,225.79 C214.15,225.79 214.04,225.73 214.04,225.73 C214.04,225.73 213.93,225.68 213.93,225.68 C213.93,225.68 213.81,225.62 213.81,225.62 C213.81,225.62 213.71,225.56 213.71,225.56 C213.71,225.56 213.6,225.5 213.6,225.5 C213.6,225.5 213.49,225.43 213.49,225.43 C213.49,225.43 213.38,225.37 213.38,225.37 C213.38,225.37 213.27,225.31 213.27,225.31 C213.27,225.31 213.17,225.24 213.17,225.24 C213.17,225.24 213.06,225.16 213.06,225.16 C213.06,225.16 212.96,225.09 212.96,225.09 C212.96,225.09 212.86,225.02 212.86,225.02 C212.86,225.02 212.76,224.95 212.76,224.95 C212.76,224.95 212.65,224.87 212.65,224.87 C212.65,224.87 212.56,224.79 212.56,224.79 C212.56,224.79 212.46,224.71 212.46,224.71 C212.46,224.71 212.37,224.63 212.37,224.63 C212.37,224.63 212.27,224.55 212.27,224.55 C212.27,224.55 212.18,224.47 212.18,224.47 C212.18,224.47 212.08,224.38 212.08,224.38 C212.08,224.38 211.99,224.3 211.99,224.3 C211.99,224.3 211.91,224.2 211.91,224.2 C211.91,224.2 211.82,224.11 211.82,224.11 C211.82,224.11 211.73,224.02 211.73,224.02 C211.73,224.02 211.64,223.93 211.64,223.93 C211.64,223.93 211.56,223.84 211.56,223.84 C211.56,223.84 211.48,223.75 211.48,223.75 C211.48,223.75 211.4,223.65 211.4,223.65 C211.4,223.65 211.32,223.55 211.32,223.55 C211.32,223.55 211.24,223.45 211.24,223.45 C211.24,223.45 211.16,223.35 211.16,223.35 C211.16,223.35 211.09,223.26 211.09,223.26 C211.09,223.26 211.02,223.15 211.02,223.15 C211.02,223.15 210.95,223.05 210.95,223.05 C210.95,223.05 210.88,222.94 210.88,222.94 C210.88,222.94 210.81,222.84 210.81,222.84 C210.81,222.84 210.74,222.73 210.74,222.73 C210.74,222.73 210.67,222.63 210.67,222.63 C210.67,222.63 210.61,222.52 210.61,222.52 C210.61,222.52 210.55,222.4 210.55,222.4 C210.55,222.4 210.49,222.29 210.49,222.29 C210.49,222.29 210.43,222.18 210.43,222.18 C210.43,222.18 210.38,222.07 210.38,222.07 C210.38,222.07 210.32,221.96 210.32,221.96 C210.32,221.96 210.27,221.84 210.27,221.84 C210.27,221.84 210.22,221.73 210.22,221.73 C210.22,221.73 210.17,221.61 210.17,221.61 C210.17,221.61 210.12,221.5 210.12,221.5 C210.12,221.5 210.08,221.38 210.08,221.38 C210.08,221.38 210.03,221.26 210.03,221.26 C210.03,221.26 209.99,221.14 209.99,221.14 C209.99,221.14 209.96,221.02 209.96,221.02 C209.96,221.02 209.92,220.9 209.92,220.9 C209.92,220.9 209.88,220.78 209.88,220.78 C209.88,220.78 209.84,220.67 209.84,220.67 C209.84,220.67 209.81,220.54 209.81,220.54 C209.81,220.54 209.78,220.42 209.78,220.42 C209.78,220.42 209.76,220.3 209.76,220.3 C209.76,220.3 209.73,220.18 209.73,220.18 C209.73,220.18 209.71,220.05 209.71,220.05 C209.71,220.05 209.68,219.93 209.68,219.93 C209.68,219.93 209.66,219.81 209.66,219.81 C209.66,219.81 209.64,219.68 209.64,219.68 C209.64,219.68 209.62,219.56 209.62,219.56 C209.62,219.56 209.61,219.43 209.61,219.43 C209.61,219.43 209.59,219.31 209.59,219.31 C209.59,219.31 209.59,219.18 209.59,219.18 C209.59,219.18 209.58,219.06 209.58,219.06 C209.58,219.06 209.58,218.93 209.58,218.93 C209.58,218.93 209.57,218.81 209.57,218.81 C209.57,218.81 209.56,218.68 209.56,218.68 C209.56,218.68 209.56,218.56 209.56,218.56 C209.56,218.56 209.56,218.43 209.56,218.43 C209.56,218.43 209.57,218.3 209.57,218.3 C209.57,218.3 209.58,218.18 209.58,218.18 C209.58,218.18 209.58,218.05 209.58,218.05 C209.58,218.05 209.59,217.93 209.59,217.93 C209.59,217.93 209.59,217.8 209.59,217.8 C209.59,217.8 209.61,217.68 209.61,217.68 C209.61,217.68 209.63,217.55 209.63,217.55 C209.63,217.55 209.65,217.43 209.65,217.43 C209.65,217.43 209.66,217.31 209.66,217.31 C209.66,217.31 209.68,217.18 209.68,217.18 C209.68,217.18 209.7,217.06 209.7,217.06 C209.7,217.06 209.73,216.93 209.73,216.93 C209.73,216.93 209.76,216.81 209.76,216.81 C209.76,216.81 209.79,216.69 209.79,216.69 C209.79,216.69 209.82,216.57 209.82,216.57 C209.82,216.57 209.85,216.45 209.85,216.45 C209.85,216.45 209.88,216.32 209.88,216.32 C209.88,216.32 209.91,216.2 209.91,216.2 C209.91,216.2 209.95,216.08 209.95,216.08 C209.95,216.08 210,215.97 210,215.97 C210,215.97 210.04,215.85 210.04,215.85 C210.04,215.85 210.08,215.73 210.08,215.73 C210.08,215.73 210.12,215.61 210.12,215.61 C210.12,215.61 210.17,215.49 210.17,215.49 C210.17,215.49 210.22,215.38 210.22,215.38 C210.22,215.38 210.27,215.27 210.27,215.27 C210.27,215.27 210.33,215.15 210.33,215.15 C210.33,215.15 210.38,215.04 210.38,215.04 C210.38,215.04 210.43,214.92 210.43,214.92 C210.43,214.92 210.49,214.81 210.49,214.81 C210.49,214.81 210.55,214.7 210.55,214.7 C210.55,214.7 210.61,214.6 210.61,214.6 C210.61,214.6 210.68,214.49 210.68,214.49 C210.68,214.49 210.74,214.38 210.74,214.38 C210.74,214.38 210.8,214.27 210.8,214.27 C210.8,214.27 210.87,214.17 210.87,214.17 C210.87,214.17 210.95,214.06 210.95,214.06 C210.95,214.06 211.02,213.96 211.02,213.96 C211.02,213.96 211.09,213.86 211.09,213.86 C211.09,213.86 211.16,213.76 211.16,213.76 C211.16,213.76 211.24,213.65 211.24,213.65 C211.24,213.65 211.32,213.56 211.32,213.56 C211.32,213.56 211.4,213.46 211.4,213.46 C211.4,213.46 211.48,213.37 211.48,213.37 C211.48,213.37 211.56,213.27 211.56,213.27 C211.56,213.27 211.64,213.18 211.64,213.18 C211.64,213.18 211.73,213.08 211.73,213.08 C211.73,213.08 211.82,212.99 211.82,212.99 C211.82,212.99 211.91,212.9 211.91,212.9 C211.91,212.9 212,212.82 212,212.82 C212,212.82 212.09,212.73 212.09,212.73 C212.09,212.73 212.18,212.64 212.18,212.64 C212.18,212.64 212.27,212.56 212.27,212.56 C212.27,212.56 212.36,212.48 212.36,212.48 C212.36,212.48 212.46,212.4 212.46,212.4 C212.46,212.4 212.56,212.32 212.56,212.32 C212.56,212.32 212.66,212.24 212.66,212.24 C212.66,212.24 212.76,212.16 212.76,212.16 C212.76,212.16 212.85,212.08 212.85,212.08 C212.85,212.08 212.96,212.02 212.96,212.02 C212.96,212.02 213.06,211.95 213.06,211.95 C213.06,211.95 213.17,211.88 213.17,211.88 C213.17,211.88 213.27,211.81 213.27,211.81 C213.27,211.81 213.38,211.74 213.38,211.74 C213.38,211.74 213.48,211.67 213.48,211.67 C213.48,211.67 213.6,211.61 213.6,211.61 C213.6,211.61 213.71,211.55 213.71,211.55 C213.71,211.55 213.82,211.49 213.82,211.49 C213.82,211.49 213.93,211.43 213.93,211.43 C213.93,211.43 214.04,211.37 214.04,211.37 C214.04,211.37 214.15,211.32 214.15,211.32 C214.15,211.32 214.27,211.27 214.27,211.27 C214.27,211.27 214.38,211.22 214.38,211.22 C214.38,211.22 214.5,211.17 214.5,211.17 C214.5,211.17 214.61,211.12 214.61,211.12 C214.61,211.12 214.73,211.07 214.73,211.07 C214.73,211.07 214.85,211.03 214.85,211.03 C214.85,211.03 214.97,210.99 214.97,210.99 C214.97,210.99 215.09,210.95 215.09,210.95 C215.09,210.95 215.21,210.92 215.21,210.92 C215.21,210.92 215.33,210.88 215.33,210.88 C215.33,210.88 215.45,210.84 215.45,210.84 C215.45,210.84 215.57,210.81 215.57,210.81 C215.57,210.81 215.69,210.78 215.69,210.78 C215.69,210.78 215.81,210.76 215.81,210.76 C215.81,210.76 215.93,210.73 215.93,210.73 C215.93,210.73 216.06,210.7 216.06,210.7 C216.06,210.7 216.18,210.68 216.18,210.68 C216.18,210.68 216.3,210.65 216.3,210.65 C216.3,210.65 216.43,210.64 216.43,210.64 C216.43,210.64 216.55,210.62 216.55,210.62 C216.55,210.62 216.68,210.61 216.68,210.61 C216.68,210.61 216.8,210.59 216.8,210.59 C216.8,210.59 216.93,210.59 216.93,210.59 C216.93,210.59 217.05,210.58 217.05,210.58 C217.05,210.58 217.18,210.58 217.18,210.58 C217.18,210.58 217.3,210.57 217.3,210.57 C217.3,210.57 217.43,210.56 217.43,210.56 C217.43,210.56 217.56,210.56 217.56,210.56 C217.56,210.56 217.68,210.56 217.68,210.56c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.8,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="500" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector> \ No newline at end of file
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="30dp" android:width="30dp" android:viewportHeight="30" android:viewportWidth="30"><group android:name="_R_G"><group android:name="_R_G_L_1_G" android:translateX="15.441" android:translateY="15.691" android:scaleY="0"><path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-0.44 -12.06 C13.5,-14.63 13.5,-14.63 10.9,-0.69 C13.5,13.25 13.5,13.25 -0.44,10.53 C-14.38,13.25 -14.38,13.25 -11.86,-0.69 C-14.38,-14.63 -14.38,-14.63 -0.44,-12.06c "/></group><group android:name="_R_G_L_0_G" android:translateX="15" android:translateY="15" android:scaleX="0" android:scaleY="0"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-13.65 -3.95 C-16.31,-10.09 -10.09,-16.31 -3.95,-13.65 C-3.95,-13.65 -2.94,-13.21 -2.94,-13.21 C-1.06,-12.39 1.06,-12.39 2.94,-13.21 C2.94,-13.21 3.95,-13.65 3.95,-13.65 C10.09,-16.31 16.31,-10.09 13.65,-3.95 C13.65,-3.95 13.21,-2.94 13.21,-2.94 C12.39,-1.06 12.39,1.06 13.21,2.94 C13.21,2.94 13.65,3.95 13.65,3.95 C16.31,10.09 10.09,16.31 3.95,13.65 C3.95,13.65 2.94,13.21 2.94,13.21 C1.06,12.39 -1.06,12.39 -2.94,13.21 C-2.94,13.21 -3.95,13.65 -3.95,13.65 C-10.09,16.31 -16.31,10.09 -13.65,3.95 C-13.65,3.95 -13.21,2.94 -13.21,2.94 C-12.39,1.06 -12.39,-1.06 -13.21,-2.94 C-13.21,-2.94 -13.65,-3.95 -13.65,-3.95c "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_1_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M-0.44 -12.06 C13.5,-14.63 13.5,-14.63 10.9,-0.69 C13.5,13.25 13.5,13.25 -0.44,10.53 C-14.38,13.25 -14.38,13.25 -11.86,-0.69 C-14.38,-14.63 -14.38,-14.63 -0.44,-12.06c " android:valueTo="M-0.44 -12.06 C13.5,-14.63 13.5,-14.63 10.9,-0.69 C13.5,13.25 13.5,13.25 -0.44,10.53 C-14.38,13.25 -14.38,13.25 -11.86,-0.69 C-14.38,-14.63 -14.38,-14.63 -0.44,-12.06c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.8,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="283" android:startOffset="67" android:valueFrom="M-0.44 -12.06 C13.5,-14.63 13.5,-14.63 10.9,-0.69 C13.5,13.25 13.5,13.25 -0.44,10.53 C-14.38,13.25 -14.38,13.25 -11.86,-0.69 C-14.38,-14.63 -14.38,-14.63 -0.44,-12.06c " android:valueTo="M-0.44 -8.69 C3.98,-8.69 7.56,-5.11 7.56,-0.69 C7.56,3.73 3.98,7.31 -0.44,7.31 C-4.86,7.31 -8.44,3.73 -8.44,-0.69 C-8.44,-5.11 -4.86,-8.69 -0.44,-8.69c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.8,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_1_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="67" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target><target android:name="_R_G_L_0_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleX" android:duration="67" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="67" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleX" android:duration="283" android:startOffset="67" android:valueFrom="1" android:valueTo="0.3" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.7,0 0.6,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="283" android:startOffset="67" android:valueFrom="1" android:valueTo="0.3" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.7,0 0.6,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target><target android:name="_R_G_L_0_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="367" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="500" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pin_dot_shape_2_avd.xml b/packages/SystemUI/res/drawable/pin_dot_shape_2_avd.xml
index d910990ae248..3717db8383ef 100644
--- a/packages/SystemUI/res/drawable/pin_dot_shape_2_avd.xml
+++ b/packages/SystemUI/res/drawable/pin_dot_shape_2_avd.xml
@@ -1 +1 @@
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="60dp" android:width="60dp" android:viewportHeight="60" android:viewportWidth="60"><group android:name="_R_G"><group android:name="_R_G_L_0_G" android:translateX="-187.543" android:translateY="-188.546"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="0" android:fillType="nonZero" android:pathData=" M217.62 214.55 C217.62,214.55 217.68,214.55 217.68,214.55 C217.68,214.55 217.74,214.56 217.74,214.56 C217.74,214.56 217.81,214.56 217.81,214.56 C217.81,214.56 217.87,214.56 217.87,214.56 C217.87,214.56 217.93,214.57 217.93,214.57 C217.93,214.57 218,214.57 218,214.57 C218,214.57 218.06,214.58 218.06,214.58 C218.06,214.58 218.12,214.59 218.12,214.59 C218.12,214.59 218.18,214.6 218.18,214.6 C218.18,214.6 218.24,214.61 218.24,214.61 C218.24,214.61 218.31,214.62 218.31,214.62 C218.31,214.62 218.37,214.63 218.37,214.63 C218.37,214.63 218.43,214.65 218.43,214.65 C218.43,214.65 218.49,214.66 218.49,214.66 C218.49,214.66 218.55,214.68 218.55,214.68 C218.55,214.68 218.61,214.69 218.61,214.69 C218.61,214.69 218.67,214.71 218.67,214.71 C218.67,214.71 218.73,214.73 218.73,214.73 C218.73,214.73 218.79,214.75 218.79,214.75 C218.79,214.75 218.85,214.77 218.85,214.77 C218.85,214.77 218.91,214.79 218.91,214.79 C218.91,214.79 218.97,214.81 218.97,214.81 C218.97,214.81 219.03,214.83 219.03,214.83 C219.03,214.83 219.09,214.85 219.09,214.85 C219.09,214.85 219.15,214.88 219.15,214.88 C219.15,214.88 219.2,214.9 219.2,214.9 C219.2,214.9 219.26,214.93 219.26,214.93 C219.26,214.93 219.32,214.96 219.32,214.96 C219.32,214.96 219.37,214.98 219.37,214.98 C219.37,214.98 219.43,215.01 219.43,215.01 C219.43,215.01 219.48,215.05 219.48,215.05 C219.48,215.05 219.54,215.08 219.54,215.08 C219.54,215.08 219.59,215.11 219.59,215.11 C219.59,215.11 219.65,215.14 219.65,215.14 C219.65,215.14 219.7,215.17 219.7,215.17 C219.7,215.17 219.75,215.21 219.75,215.21 C219.75,215.21 219.81,215.24 219.81,215.24 C219.81,215.24 219.86,215.28 219.86,215.28 C219.86,215.28 219.91,215.32 219.91,215.32 C219.91,215.32 219.96,215.35 219.96,215.35 C219.96,215.35 220.01,215.39 220.01,215.39 C220.01,215.39 220.06,215.43 220.06,215.43 C220.06,215.43 220.11,215.47 220.11,215.47 C220.11,215.47 220.16,215.51 220.16,215.51 C220.16,215.51 220.2,215.55 220.2,215.55 C220.2,215.55 220.25,215.59 220.25,215.59 C220.25,215.59 220.3,215.63 220.3,215.63 C220.3,215.63 220.34,215.68 220.34,215.68 C220.34,215.68 220.39,215.72 220.39,215.72 C220.39,215.72 220.43,215.77 220.43,215.77 C220.43,215.77 220.47,215.81 220.47,215.81 C220.47,215.81 220.52,215.86 220.52,215.86 C220.52,215.86 220.56,215.9 220.56,215.9 C220.56,215.9 220.6,215.95 220.6,215.95 C220.6,215.95 220.64,216 220.64,216 C220.64,216 220.68,216.05 220.68,216.05 C220.68,216.05 220.72,216.1 220.72,216.1 C220.72,216.1 220.76,216.15 220.76,216.15 C220.76,216.15 220.8,216.2 220.8,216.2 C220.8,216.2 220.83,216.25 220.83,216.25 C220.83,216.25 220.87,216.3 220.87,216.3 C220.87,216.3 220.9,216.36 220.9,216.36 C220.9,216.36 220.94,216.41 220.94,216.41 C220.94,216.41 220.97,216.46 220.97,216.46 C220.97,216.46 221,216.51 221,216.51 C221,216.51 221.03,216.57 221.03,216.57 C221.03,216.57 221.06,216.63 221.06,216.63 C221.06,216.63 221.09,216.68 221.09,216.68 C221.09,216.68 221.12,216.74 221.12,216.74 C221.12,216.74 221.15,216.79 221.15,216.79 C221.15,216.79 221.18,216.85 221.18,216.85 C221.18,216.85 221.21,216.91 221.21,216.91 C221.21,216.91 221.23,216.96 221.23,216.96 C221.23,216.96 221.25,217.02 221.25,217.02 C221.25,217.02 221.28,217.08 221.28,217.08 C221.28,217.08 221.3,217.14 221.3,217.14 C221.3,217.14 221.33,217.2 221.33,217.2 C221.33,217.2 221.34,217.26 221.34,217.26 C221.34,217.26 221.36,217.32 221.36,217.32 C221.36,217.32 221.38,217.38 221.38,217.38 C221.38,217.38 221.4,217.44 221.4,217.44 C221.4,217.44 221.42,217.5 221.42,217.5 C221.42,217.5 221.44,217.56 221.44,217.56 C221.44,217.56 221.45,217.62 221.45,217.62 C221.45,217.62 221.46,217.68 221.46,217.68 C221.46,217.68 221.48,217.74 221.48,217.74 C221.48,217.74 221.49,217.8 221.49,217.8 C221.49,217.8 221.5,217.87 221.5,217.87 C221.5,217.87 221.51,217.93 221.51,217.93 C221.51,217.93 221.52,217.99 221.52,217.99 C221.52,217.99 221.53,218.05 221.53,218.05 C221.53,218.05 221.54,218.11 221.54,218.11 C221.54,218.11 221.54,218.18 221.54,218.18 C221.54,218.18 221.55,218.24 221.55,218.24 C221.55,218.24 221.55,218.3 221.55,218.3 C221.55,218.3 221.55,218.37 221.55,218.37 C221.55,218.37 221.56,218.43 221.56,218.43 C221.56,218.43 221.56,218.49 221.56,218.49 C221.56,218.49 221.56,218.55 221.56,218.55 C221.56,218.55 221.56,218.62 221.56,218.62 C221.56,218.62 221.56,218.68 221.56,218.68 C221.56,218.68 221.55,218.74 221.55,218.74 C221.55,218.74 221.55,218.81 221.55,218.81 C221.55,218.81 221.55,218.87 221.55,218.87 C221.55,218.87 221.54,218.93 221.54,218.93 C221.54,218.93 221.54,218.99 221.54,218.99 C221.54,218.99 221.53,219.06 221.53,219.06 C221.53,219.06 221.52,219.12 221.52,219.12 C221.52,219.12 221.51,219.18 221.51,219.18 C221.51,219.18 221.5,219.24 221.5,219.24 C221.5,219.24 221.49,219.3 221.49,219.3 C221.49,219.3 221.48,219.37 221.48,219.37 C221.48,219.37 221.46,219.43 221.46,219.43 C221.46,219.43 221.45,219.49 221.45,219.49 C221.45,219.49 221.43,219.55 221.43,219.55 C221.43,219.55 221.42,219.61 221.42,219.61 C221.42,219.61 221.4,219.67 221.4,219.67 C221.4,219.67 221.39,219.73 221.39,219.73 C221.39,219.73 221.37,219.79 221.37,219.79 C221.37,219.79 221.34,219.85 221.34,219.85 C221.34,219.85 221.32,219.91 221.32,219.91 C221.32,219.91 221.3,219.97 221.3,219.97 C221.3,219.97 221.28,220.03 221.28,220.03 C221.28,220.03 221.26,220.09 221.26,220.09 C221.26,220.09 221.23,220.14 221.23,220.14 C221.23,220.14 221.21,220.2 221.21,220.2 C221.21,220.2 221.18,220.26 221.18,220.26 C221.18,220.26 221.15,220.32 221.15,220.32 C221.15,220.32 221.13,220.37 221.13,220.37 C221.13,220.37 221.1,220.43 221.1,220.43 C221.1,220.43 221.07,220.48 221.07,220.48 C221.07,220.48 221.03,220.54 221.03,220.54 C221.03,220.54 221,220.59 221,220.59 C221,220.59 220.97,220.65 220.97,220.65 C220.97,220.65 220.94,220.7 220.94,220.7 C220.94,220.7 220.9,220.75 220.9,220.75 C220.9,220.75 220.87,220.8 220.87,220.8 C220.87,220.8 220.83,220.86 220.83,220.86 C220.83,220.86 220.8,220.91 220.8,220.91 C220.8,220.91 220.76,220.96 220.76,220.96 C220.76,220.96 220.72,221.01 220.72,221.01 C220.72,221.01 220.68,221.06 220.68,221.06 C220.68,221.06 220.64,221.11 220.64,221.11 C220.64,221.11 220.6,221.15 220.6,221.15 C220.6,221.15 220.56,221.2 220.56,221.2 C220.56,221.2 220.52,221.25 220.52,221.25 C220.52,221.25 220.48,221.3 220.48,221.3 C220.48,221.3 220.43,221.34 220.43,221.34 C220.43,221.34 220.39,221.38 220.39,221.38 C220.39,221.38 220.34,221.43 220.34,221.43 C220.34,221.43 220.3,221.47 220.3,221.47 C220.3,221.47 220.25,221.52 220.25,221.52 C220.25,221.52 220.21,221.56 220.21,221.56 C220.21,221.56 220.16,221.6 220.16,221.6 C220.16,221.6 220.11,221.64 220.11,221.64 C220.11,221.64 220.06,221.68 220.06,221.68 C220.06,221.68 220.01,221.72 220.01,221.72 C220.01,221.72 219.96,221.76 219.96,221.76 C219.96,221.76 219.91,221.8 219.91,221.8 C219.91,221.8 219.86,221.83 219.86,221.83 C219.86,221.83 219.81,221.87 219.81,221.87 C219.81,221.87 219.75,221.9 219.75,221.9 C219.75,221.9 219.7,221.93 219.7,221.93 C219.7,221.93 219.65,221.97 219.65,221.97 C219.65,221.97 219.6,222 219.6,222 C219.6,222 219.54,222.03 219.54,222.03 C219.54,222.03 219.49,222.06 219.49,222.06 C219.49,222.06 219.43,222.09 219.43,222.09 C219.43,222.09 219.37,222.12 219.37,222.12 C219.37,222.12 219.32,222.15 219.32,222.15 C219.32,222.15 219.26,222.18 219.26,222.18 C219.26,222.18 219.21,222.2 219.21,222.2 C219.21,222.2 219.15,222.23 219.15,222.23 C219.15,222.23 219.09,222.25 219.09,222.25 C219.09,222.25 219.03,222.28 219.03,222.28 C219.03,222.28 218.97,222.3 218.97,222.3 C218.97,222.3 218.91,222.32 218.91,222.32 C218.91,222.32 218.85,222.34 218.85,222.34 C218.85,222.34 218.79,222.36 218.79,222.36 C218.79,222.36 218.73,222.38 218.73,222.38 C218.73,222.38 218.67,222.4 218.67,222.4 C218.67,222.4 218.61,222.42 218.61,222.42 C218.61,222.42 218.55,222.44 218.55,222.44 C218.55,222.44 218.49,222.45 218.49,222.45 C218.49,222.45 218.43,222.46 218.43,222.46 C218.43,222.46 218.37,222.47 218.37,222.47 C218.37,222.47 218.31,222.49 218.31,222.49 C218.31,222.49 218.25,222.5 218.25,222.5 C218.25,222.5 218.18,222.51 218.18,222.51 C218.18,222.51 218.12,222.52 218.12,222.52 C218.12,222.52 218.06,222.53 218.06,222.53 C218.06,222.53 218,222.54 218,222.54 C218,222.54 217.93,222.54 217.93,222.54 C217.93,222.54 217.87,222.55 217.87,222.55 C217.87,222.55 217.81,222.55 217.81,222.55 C217.81,222.55 217.75,222.55 217.75,222.55 C217.75,222.55 217.68,222.56 217.68,222.56 C217.68,222.56 217.62,222.56 217.62,222.56 C217.62,222.56 217.56,222.56 217.56,222.56 C217.56,222.56 217.49,222.56 217.49,222.56 C217.49,222.56 217.43,222.56 217.43,222.56 C217.43,222.56 217.37,222.55 217.37,222.55 C217.37,222.55 217.3,222.55 217.3,222.55 C217.3,222.55 217.24,222.55 217.24,222.55 C217.24,222.55 217.18,222.54 217.18,222.54 C217.18,222.54 217.12,222.54 217.12,222.54 C217.12,222.54 217.05,222.53 217.05,222.53 C217.05,222.53 216.99,222.52 216.99,222.52 C216.99,222.52 216.93,222.51 216.93,222.51 C216.93,222.51 216.87,222.5 216.87,222.5 C216.87,222.5 216.81,222.49 216.81,222.49 C216.81,222.49 216.74,222.48 216.74,222.48 C216.74,222.48 216.68,222.46 216.68,222.46 C216.68,222.46 216.62,222.45 216.62,222.45 C216.62,222.45 216.56,222.43 216.56,222.43 C216.56,222.43 216.5,222.42 216.5,222.42 C216.5,222.42 216.44,222.4 216.44,222.4 C216.44,222.4 216.38,222.38 216.38,222.38 C216.38,222.38 216.32,222.36 216.32,222.36 C216.32,222.36 216.26,222.34 216.26,222.34 C216.26,222.34 216.2,222.32 216.2,222.32 C216.2,222.32 216.14,222.3 216.14,222.3 C216.14,222.3 216.08,222.28 216.08,222.28 C216.08,222.28 216.02,222.26 216.02,222.26 C216.02,222.26 215.97,222.23 215.97,222.23 C215.97,222.23 215.91,222.2 215.91,222.2 C215.91,222.2 215.85,222.18 215.85,222.18 C215.85,222.18 215.79,222.15 215.79,222.15 C215.79,222.15 215.74,222.12 215.74,222.12 C215.74,222.12 215.68,222.1 215.68,222.1 C215.68,222.1 215.63,222.06 215.63,222.06 C215.63,222.06 215.57,222.03 215.57,222.03 C215.57,222.03 215.52,222 215.52,222 C215.52,222 215.46,221.97 215.46,221.97 C215.46,221.97 215.41,221.94 215.41,221.94 C215.41,221.94 215.36,221.9 215.36,221.9 C215.36,221.9 215.31,221.87 215.31,221.87 C215.31,221.87 215.25,221.83 215.25,221.83 C215.25,221.83 215.2,221.79 215.2,221.79 C215.2,221.79 215.15,221.76 215.15,221.76 C215.15,221.76 215.1,221.72 215.1,221.72 C215.1,221.72 215.05,221.68 215.05,221.68 C215.05,221.68 215,221.64 215,221.64 C215,221.64 214.96,221.6 214.96,221.6 C214.96,221.6 214.91,221.56 214.91,221.56 C214.91,221.56 214.86,221.52 214.86,221.52 C214.86,221.52 214.81,221.48 214.81,221.48 C214.81,221.48 214.77,221.43 214.77,221.43 C214.77,221.43 214.73,221.39 214.73,221.39 C214.73,221.39 214.68,221.34 214.68,221.34 C214.68,221.34 214.64,221.3 214.64,221.3 C214.64,221.3 214.59,221.25 214.59,221.25 C214.59,221.25 214.55,221.2 214.55,221.2 C214.55,221.2 214.51,221.15 214.51,221.15 C214.51,221.15 214.47,221.11 214.47,221.11 C214.47,221.11 214.43,221.06 214.43,221.06 C214.43,221.06 214.39,221.01 214.39,221.01 C214.39,221.01 214.35,220.96 214.35,220.96 C214.35,220.96 214.31,220.91 214.31,220.91 C214.31,220.91 214.28,220.86 214.28,220.86 C214.28,220.86 214.25,220.81 214.25,220.81 C214.25,220.81 214.21,220.75 214.21,220.75 C214.21,220.75 214.18,220.7 214.18,220.7 C214.18,220.7 214.14,220.65 214.14,220.65 C214.14,220.65 214.11,220.59 214.11,220.59 C214.11,220.59 214.08,220.54 214.08,220.54 C214.08,220.54 214.05,220.48 214.05,220.48 C214.05,220.48 214.02,220.43 214.02,220.43 C214.02,220.43 213.99,220.37 213.99,220.37 C213.99,220.37 213.96,220.32 213.96,220.32 C213.96,220.32 213.93,220.26 213.93,220.26 C213.93,220.26 213.91,220.2 213.91,220.2 C213.91,220.2 213.88,220.14 213.88,220.14 C213.88,220.14 213.86,220.09 213.86,220.09 C213.86,220.09 213.83,220.03 213.83,220.03 C213.83,220.03 213.81,219.97 213.81,219.97 C213.81,219.97 213.79,219.91 213.79,219.91 C213.79,219.91 213.77,219.85 213.77,219.85 C213.77,219.85 213.75,219.79 213.75,219.79 C213.75,219.79 213.73,219.73 213.73,219.73 C213.73,219.73 213.71,219.67 213.71,219.67 C213.71,219.67 213.69,219.61 213.69,219.61 C213.69,219.61 213.68,219.55 213.68,219.55 C213.68,219.55 213.66,219.49 213.66,219.49 C213.66,219.49 213.65,219.43 213.65,219.43 C213.65,219.43 213.64,219.37 213.64,219.37 C213.64,219.37 213.62,219.31 213.62,219.31 C213.62,219.31 213.61,219.24 213.61,219.24 C213.61,219.24 213.6,219.18 213.6,219.18 C213.6,219.18 213.59,219.12 213.59,219.12 C213.59,219.12 213.58,219.06 213.58,219.06 C213.58,219.06 213.57,218.99 213.57,218.99 C213.57,218.99 213.57,218.93 213.57,218.93 C213.57,218.93 213.56,218.87 213.56,218.87 C213.56,218.87 213.56,218.81 213.56,218.81 C213.56,218.81 213.56,218.74 213.56,218.74 C213.56,218.74 213.56,218.68 213.56,218.68 C213.56,218.68 213.55,218.62 213.55,218.62 C213.55,218.62 213.55,218.55 213.55,218.55 C213.55,218.55 213.55,218.49 213.55,218.49 C213.55,218.49 213.56,218.43 213.56,218.43 C213.56,218.43 213.56,218.37 213.56,218.37 C213.56,218.37 213.56,218.3 213.56,218.3 C213.56,218.3 213.56,218.24 213.56,218.24 C213.56,218.24 213.57,218.18 213.57,218.18 C213.57,218.18 213.57,218.12 213.57,218.12 C213.57,218.12 213.58,218.05 213.58,218.05 C213.58,218.05 213.59,217.99 213.59,217.99 C213.59,217.99 213.6,217.93 213.6,217.93 C213.6,217.93 213.61,217.87 213.61,217.87 C213.61,217.87 213.62,217.8 213.62,217.8 C213.62,217.8 213.63,217.74 213.63,217.74 C213.63,217.74 213.65,217.68 213.65,217.68 C213.65,217.68 213.66,217.62 213.66,217.62 C213.66,217.62 213.68,217.56 213.68,217.56 C213.68,217.56 213.69,217.5 213.69,217.5 C213.69,217.5 213.71,217.44 213.71,217.44 C213.71,217.44 213.73,217.38 213.73,217.38 C213.73,217.38 213.75,217.32 213.75,217.32 C213.75,217.32 213.77,217.26 213.77,217.26 C213.77,217.26 213.79,217.2 213.79,217.2 C213.79,217.2 213.81,217.14 213.81,217.14 C213.81,217.14 213.83,217.08 213.83,217.08 C213.83,217.08 213.85,217.02 213.85,217.02 C213.85,217.02 213.88,216.96 213.88,216.96 C213.88,216.96 213.91,216.91 213.91,216.91 C213.91,216.91 213.93,216.85 213.93,216.85 C213.93,216.85 213.96,216.79 213.96,216.79 C213.96,216.79 213.99,216.74 213.99,216.74 C213.99,216.74 214.02,216.68 214.02,216.68 C214.02,216.68 214.05,216.63 214.05,216.63 C214.05,216.63 214.08,216.57 214.08,216.57 C214.08,216.57 214.11,216.52 214.11,216.52 C214.11,216.52 214.14,216.46 214.14,216.46 C214.14,216.46 214.17,216.41 214.17,216.41 C214.17,216.41 214.21,216.36 214.21,216.36 C214.21,216.36 214.24,216.3 214.24,216.3 C214.24,216.3 214.28,216.25 214.28,216.25 C214.28,216.25 214.32,216.2 214.32,216.2 C214.32,216.2 214.35,216.15 214.35,216.15 C214.35,216.15 214.39,216.1 214.39,216.1 C214.39,216.1 214.43,216.05 214.43,216.05 C214.43,216.05 214.47,216 214.47,216 C214.47,216 214.51,215.96 214.51,215.96 C214.51,215.96 214.55,215.91 214.55,215.91 C214.55,215.91 214.59,215.86 214.59,215.86 C214.59,215.86 214.64,215.81 214.64,215.81 C214.64,215.81 214.68,215.77 214.68,215.77 C214.68,215.77 214.73,215.72 214.73,215.72 C214.73,215.72 214.77,215.68 214.77,215.68 C214.77,215.68 214.82,215.64 214.82,215.64 C214.82,215.64 214.86,215.59 214.86,215.59 C214.86,215.59 214.91,215.55 214.91,215.55 C214.91,215.55 214.96,215.51 214.96,215.51 C214.96,215.51 215,215.47 215,215.47 C215,215.47 215.05,215.43 215.05,215.43 C215.05,215.43 215.1,215.39 215.1,215.39 C215.1,215.39 215.15,215.35 215.15,215.35 C215.15,215.35 215.2,215.31 215.2,215.31 C215.2,215.31 215.25,215.28 215.25,215.28 C215.25,215.28 215.31,215.24 215.31,215.24 C215.31,215.24 215.36,215.21 215.36,215.21 C215.36,215.21 215.41,215.17 215.41,215.17 C215.41,215.17 215.46,215.14 215.46,215.14 C215.46,215.14 215.52,215.11 215.52,215.11 C215.52,215.11 215.57,215.08 215.57,215.08 C215.57,215.08 215.63,215.05 215.63,215.05 C215.63,215.05 215.68,215.02 215.68,215.02 C215.68,215.02 215.74,214.99 215.74,214.99 C215.74,214.99 215.79,214.96 215.79,214.96 C215.79,214.96 215.85,214.93 215.85,214.93 C215.85,214.93 215.91,214.9 215.91,214.9 C215.91,214.9 215.97,214.88 215.97,214.88 C215.97,214.88 216.02,214.86 216.02,214.86 C216.02,214.86 216.08,214.83 216.08,214.83 C216.08,214.83 216.14,214.81 216.14,214.81 C216.14,214.81 216.2,214.78 216.2,214.78 C216.2,214.78 216.26,214.77 216.26,214.77 C216.26,214.77 216.32,214.75 216.32,214.75 C216.32,214.75 216.38,214.73 216.38,214.73 C216.38,214.73 216.44,214.71 216.44,214.71 C216.44,214.71 216.5,214.69 216.5,214.69 C216.5,214.69 216.56,214.67 216.56,214.67 C216.56,214.67 216.62,214.66 216.62,214.66 C216.62,214.66 216.68,214.65 216.68,214.65 C216.68,214.65 216.74,214.63 216.74,214.63 C216.74,214.63 216.81,214.62 216.81,214.62 C216.81,214.62 216.87,214.61 216.87,214.61 C216.87,214.61 216.93,214.6 216.93,214.6 C216.93,214.6 216.99,214.59 216.99,214.59 C216.99,214.59 217.05,214.58 217.05,214.58 C217.05,214.58 217.12,214.57 217.12,214.57 C217.12,214.57 217.18,214.57 217.18,214.57 C217.18,214.57 217.24,214.56 217.24,214.56 C217.24,214.56 217.3,214.56 217.3,214.56 C217.3,214.56 217.37,214.56 217.37,214.56 C217.37,214.56 217.43,214.55 217.43,214.55 C217.43,214.55 217.49,214.55 217.49,214.55 C217.49,214.55 217.56,214.55 217.56,214.55 C217.56,214.55 217.62,214.55 217.62,214.55c "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="fillAlpha" android:duration="33" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M217.62 214.55 C217.62,214.55 217.68,214.55 217.68,214.55 C217.68,214.55 217.74,214.56 217.74,214.56 C217.74,214.56 217.81,214.56 217.81,214.56 C217.81,214.56 217.87,214.56 217.87,214.56 C217.87,214.56 217.93,214.57 217.93,214.57 C217.93,214.57 218,214.57 218,214.57 C218,214.57 218.06,214.58 218.06,214.58 C218.06,214.58 218.12,214.59 218.12,214.59 C218.12,214.59 218.18,214.6 218.18,214.6 C218.18,214.6 218.24,214.61 218.24,214.61 C218.24,214.61 218.31,214.62 218.31,214.62 C218.31,214.62 218.37,214.63 218.37,214.63 C218.37,214.63 218.43,214.65 218.43,214.65 C218.43,214.65 218.49,214.66 218.49,214.66 C218.49,214.66 218.55,214.68 218.55,214.68 C218.55,214.68 218.61,214.69 218.61,214.69 C218.61,214.69 218.67,214.71 218.67,214.71 C218.67,214.71 218.73,214.73 218.73,214.73 C218.73,214.73 218.79,214.75 218.79,214.75 C218.79,214.75 218.85,214.77 218.85,214.77 C218.85,214.77 218.91,214.79 218.91,214.79 C218.91,214.79 218.97,214.81 218.97,214.81 C218.97,214.81 219.03,214.83 219.03,214.83 C219.03,214.83 219.09,214.85 219.09,214.85 C219.09,214.85 219.15,214.88 219.15,214.88 C219.15,214.88 219.2,214.9 219.2,214.9 C219.2,214.9 219.26,214.93 219.26,214.93 C219.26,214.93 219.32,214.96 219.32,214.96 C219.32,214.96 219.37,214.98 219.37,214.98 C219.37,214.98 219.43,215.01 219.43,215.01 C219.43,215.01 219.48,215.05 219.48,215.05 C219.48,215.05 219.54,215.08 219.54,215.08 C219.54,215.08 219.59,215.11 219.59,215.11 C219.59,215.11 219.65,215.14 219.65,215.14 C219.65,215.14 219.7,215.17 219.7,215.17 C219.7,215.17 219.75,215.21 219.75,215.21 C219.75,215.21 219.81,215.24 219.81,215.24 C219.81,215.24 219.86,215.28 219.86,215.28 C219.86,215.28 219.91,215.32 219.91,215.32 C219.91,215.32 219.96,215.35 219.96,215.35 C219.96,215.35 220.01,215.39 220.01,215.39 C220.01,215.39 220.06,215.43 220.06,215.43 C220.06,215.43 220.11,215.47 220.11,215.47 C220.11,215.47 220.16,215.51 220.16,215.51 C220.16,215.51 220.2,215.55 220.2,215.55 C220.2,215.55 220.25,215.59 220.25,215.59 C220.25,215.59 220.3,215.63 220.3,215.63 C220.3,215.63 220.34,215.68 220.34,215.68 C220.34,215.68 220.39,215.72 220.39,215.72 C220.39,215.72 220.43,215.77 220.43,215.77 C220.43,215.77 220.47,215.81 220.47,215.81 C220.47,215.81 220.52,215.86 220.52,215.86 C220.52,215.86 220.56,215.9 220.56,215.9 C220.56,215.9 220.6,215.95 220.6,215.95 C220.6,215.95 220.64,216 220.64,216 C220.64,216 220.68,216.05 220.68,216.05 C220.68,216.05 220.72,216.1 220.72,216.1 C220.72,216.1 220.76,216.15 220.76,216.15 C220.76,216.15 220.8,216.2 220.8,216.2 C220.8,216.2 220.83,216.25 220.83,216.25 C220.83,216.25 220.87,216.3 220.87,216.3 C220.87,216.3 220.9,216.36 220.9,216.36 C220.9,216.36 220.94,216.41 220.94,216.41 C220.94,216.41 220.97,216.46 220.97,216.46 C220.97,216.46 221,216.51 221,216.51 C221,216.51 221.03,216.57 221.03,216.57 C221.03,216.57 221.06,216.63 221.06,216.63 C221.06,216.63 221.09,216.68 221.09,216.68 C221.09,216.68 221.12,216.74 221.12,216.74 C221.12,216.74 221.15,216.79 221.15,216.79 C221.15,216.79 221.18,216.85 221.18,216.85 C221.18,216.85 221.21,216.91 221.21,216.91 C221.21,216.91 221.23,216.96 221.23,216.96 C221.23,216.96 221.25,217.02 221.25,217.02 C221.25,217.02 221.28,217.08 221.28,217.08 C221.28,217.08 221.3,217.14 221.3,217.14 C221.3,217.14 221.33,217.2 221.33,217.2 C221.33,217.2 221.34,217.26 221.34,217.26 C221.34,217.26 221.36,217.32 221.36,217.32 C221.36,217.32 221.38,217.38 221.38,217.38 C221.38,217.38 221.4,217.44 221.4,217.44 C221.4,217.44 221.42,217.5 221.42,217.5 C221.42,217.5 221.44,217.56 221.44,217.56 C221.44,217.56 221.45,217.62 221.45,217.62 C221.45,217.62 221.46,217.68 221.46,217.68 C221.46,217.68 221.48,217.74 221.48,217.74 C221.48,217.74 221.49,217.8 221.49,217.8 C221.49,217.8 221.5,217.87 221.5,217.87 C221.5,217.87 221.51,217.93 221.51,217.93 C221.51,217.93 221.52,217.99 221.52,217.99 C221.52,217.99 221.53,218.05 221.53,218.05 C221.53,218.05 221.54,218.11 221.54,218.11 C221.54,218.11 221.54,218.18 221.54,218.18 C221.54,218.18 221.55,218.24 221.55,218.24 C221.55,218.24 221.55,218.3 221.55,218.3 C221.55,218.3 221.55,218.37 221.55,218.37 C221.55,218.37 221.56,218.43 221.56,218.43 C221.56,218.43 221.56,218.49 221.56,218.49 C221.56,218.49 221.56,218.55 221.56,218.55 C221.56,218.55 221.56,218.62 221.56,218.62 C221.56,218.62 221.56,218.68 221.56,218.68 C221.56,218.68 221.55,218.74 221.55,218.74 C221.55,218.74 221.55,218.81 221.55,218.81 C221.55,218.81 221.55,218.87 221.55,218.87 C221.55,218.87 221.54,218.93 221.54,218.93 C221.54,218.93 221.54,218.99 221.54,218.99 C221.54,218.99 221.53,219.06 221.53,219.06 C221.53,219.06 221.52,219.12 221.52,219.12 C221.52,219.12 221.51,219.18 221.51,219.18 C221.51,219.18 221.5,219.24 221.5,219.24 C221.5,219.24 221.49,219.3 221.49,219.3 C221.49,219.3 221.48,219.37 221.48,219.37 C221.48,219.37 221.46,219.43 221.46,219.43 C221.46,219.43 221.45,219.49 221.45,219.49 C221.45,219.49 221.43,219.55 221.43,219.55 C221.43,219.55 221.42,219.61 221.42,219.61 C221.42,219.61 221.4,219.67 221.4,219.67 C221.4,219.67 221.39,219.73 221.39,219.73 C221.39,219.73 221.37,219.79 221.37,219.79 C221.37,219.79 221.34,219.85 221.34,219.85 C221.34,219.85 221.32,219.91 221.32,219.91 C221.32,219.91 221.3,219.97 221.3,219.97 C221.3,219.97 221.28,220.03 221.28,220.03 C221.28,220.03 221.26,220.09 221.26,220.09 C221.26,220.09 221.23,220.14 221.23,220.14 C221.23,220.14 221.21,220.2 221.21,220.2 C221.21,220.2 221.18,220.26 221.18,220.26 C221.18,220.26 221.15,220.32 221.15,220.32 C221.15,220.32 221.13,220.37 221.13,220.37 C221.13,220.37 221.1,220.43 221.1,220.43 C221.1,220.43 221.07,220.48 221.07,220.48 C221.07,220.48 221.03,220.54 221.03,220.54 C221.03,220.54 221,220.59 221,220.59 C221,220.59 220.97,220.65 220.97,220.65 C220.97,220.65 220.94,220.7 220.94,220.7 C220.94,220.7 220.9,220.75 220.9,220.75 C220.9,220.75 220.87,220.8 220.87,220.8 C220.87,220.8 220.83,220.86 220.83,220.86 C220.83,220.86 220.8,220.91 220.8,220.91 C220.8,220.91 220.76,220.96 220.76,220.96 C220.76,220.96 220.72,221.01 220.72,221.01 C220.72,221.01 220.68,221.06 220.68,221.06 C220.68,221.06 220.64,221.11 220.64,221.11 C220.64,221.11 220.6,221.15 220.6,221.15 C220.6,221.15 220.56,221.2 220.56,221.2 C220.56,221.2 220.52,221.25 220.52,221.25 C220.52,221.25 220.48,221.3 220.48,221.3 C220.48,221.3 220.43,221.34 220.43,221.34 C220.43,221.34 220.39,221.38 220.39,221.38 C220.39,221.38 220.34,221.43 220.34,221.43 C220.34,221.43 220.3,221.47 220.3,221.47 C220.3,221.47 220.25,221.52 220.25,221.52 C220.25,221.52 220.21,221.56 220.21,221.56 C220.21,221.56 220.16,221.6 220.16,221.6 C220.16,221.6 220.11,221.64 220.11,221.64 C220.11,221.64 220.06,221.68 220.06,221.68 C220.06,221.68 220.01,221.72 220.01,221.72 C220.01,221.72 219.96,221.76 219.96,221.76 C219.96,221.76 219.91,221.8 219.91,221.8 C219.91,221.8 219.86,221.83 219.86,221.83 C219.86,221.83 219.81,221.87 219.81,221.87 C219.81,221.87 219.75,221.9 219.75,221.9 C219.75,221.9 219.7,221.93 219.7,221.93 C219.7,221.93 219.65,221.97 219.65,221.97 C219.65,221.97 219.6,222 219.6,222 C219.6,222 219.54,222.03 219.54,222.03 C219.54,222.03 219.49,222.06 219.49,222.06 C219.49,222.06 219.43,222.09 219.43,222.09 C219.43,222.09 219.37,222.12 219.37,222.12 C219.37,222.12 219.32,222.15 219.32,222.15 C219.32,222.15 219.26,222.18 219.26,222.18 C219.26,222.18 219.21,222.2 219.21,222.2 C219.21,222.2 219.15,222.23 219.15,222.23 C219.15,222.23 219.09,222.25 219.09,222.25 C219.09,222.25 219.03,222.28 219.03,222.28 C219.03,222.28 218.97,222.3 218.97,222.3 C218.97,222.3 218.91,222.32 218.91,222.32 C218.91,222.32 218.85,222.34 218.85,222.34 C218.85,222.34 218.79,222.36 218.79,222.36 C218.79,222.36 218.73,222.38 218.73,222.38 C218.73,222.38 218.67,222.4 218.67,222.4 C218.67,222.4 218.61,222.42 218.61,222.42 C218.61,222.42 218.55,222.44 218.55,222.44 C218.55,222.44 218.49,222.45 218.49,222.45 C218.49,222.45 218.43,222.46 218.43,222.46 C218.43,222.46 218.37,222.47 218.37,222.47 C218.37,222.47 218.31,222.49 218.31,222.49 C218.31,222.49 218.25,222.5 218.25,222.5 C218.25,222.5 218.18,222.51 218.18,222.51 C218.18,222.51 218.12,222.52 218.12,222.52 C218.12,222.52 218.06,222.53 218.06,222.53 C218.06,222.53 218,222.54 218,222.54 C218,222.54 217.93,222.54 217.93,222.54 C217.93,222.54 217.87,222.55 217.87,222.55 C217.87,222.55 217.81,222.55 217.81,222.55 C217.81,222.55 217.75,222.55 217.75,222.55 C217.75,222.55 217.68,222.56 217.68,222.56 C217.68,222.56 217.62,222.56 217.62,222.56 C217.62,222.56 217.56,222.56 217.56,222.56 C217.56,222.56 217.49,222.56 217.49,222.56 C217.49,222.56 217.43,222.56 217.43,222.56 C217.43,222.56 217.37,222.55 217.37,222.55 C217.37,222.55 217.3,222.55 217.3,222.55 C217.3,222.55 217.24,222.55 217.24,222.55 C217.24,222.55 217.18,222.54 217.18,222.54 C217.18,222.54 217.12,222.54 217.12,222.54 C217.12,222.54 217.05,222.53 217.05,222.53 C217.05,222.53 216.99,222.52 216.99,222.52 C216.99,222.52 216.93,222.51 216.93,222.51 C216.93,222.51 216.87,222.5 216.87,222.5 C216.87,222.5 216.81,222.49 216.81,222.49 C216.81,222.49 216.74,222.48 216.74,222.48 C216.74,222.48 216.68,222.46 216.68,222.46 C216.68,222.46 216.62,222.45 216.62,222.45 C216.62,222.45 216.56,222.43 216.56,222.43 C216.56,222.43 216.5,222.42 216.5,222.42 C216.5,222.42 216.44,222.4 216.44,222.4 C216.44,222.4 216.38,222.38 216.38,222.38 C216.38,222.38 216.32,222.36 216.32,222.36 C216.32,222.36 216.26,222.34 216.26,222.34 C216.26,222.34 216.2,222.32 216.2,222.32 C216.2,222.32 216.14,222.3 216.14,222.3 C216.14,222.3 216.08,222.28 216.08,222.28 C216.08,222.28 216.02,222.26 216.02,222.26 C216.02,222.26 215.97,222.23 215.97,222.23 C215.97,222.23 215.91,222.2 215.91,222.2 C215.91,222.2 215.85,222.18 215.85,222.18 C215.85,222.18 215.79,222.15 215.79,222.15 C215.79,222.15 215.74,222.12 215.74,222.12 C215.74,222.12 215.68,222.1 215.68,222.1 C215.68,222.1 215.63,222.06 215.63,222.06 C215.63,222.06 215.57,222.03 215.57,222.03 C215.57,222.03 215.52,222 215.52,222 C215.52,222 215.46,221.97 215.46,221.97 C215.46,221.97 215.41,221.94 215.41,221.94 C215.41,221.94 215.36,221.9 215.36,221.9 C215.36,221.9 215.31,221.87 215.31,221.87 C215.31,221.87 215.25,221.83 215.25,221.83 C215.25,221.83 215.2,221.79 215.2,221.79 C215.2,221.79 215.15,221.76 215.15,221.76 C215.15,221.76 215.1,221.72 215.1,221.72 C215.1,221.72 215.05,221.68 215.05,221.68 C215.05,221.68 215,221.64 215,221.64 C215,221.64 214.96,221.6 214.96,221.6 C214.96,221.6 214.91,221.56 214.91,221.56 C214.91,221.56 214.86,221.52 214.86,221.52 C214.86,221.52 214.81,221.48 214.81,221.48 C214.81,221.48 214.77,221.43 214.77,221.43 C214.77,221.43 214.73,221.39 214.73,221.39 C214.73,221.39 214.68,221.34 214.68,221.34 C214.68,221.34 214.64,221.3 214.64,221.3 C214.64,221.3 214.59,221.25 214.59,221.25 C214.59,221.25 214.55,221.2 214.55,221.2 C214.55,221.2 214.51,221.15 214.51,221.15 C214.51,221.15 214.47,221.11 214.47,221.11 C214.47,221.11 214.43,221.06 214.43,221.06 C214.43,221.06 214.39,221.01 214.39,221.01 C214.39,221.01 214.35,220.96 214.35,220.96 C214.35,220.96 214.31,220.91 214.31,220.91 C214.31,220.91 214.28,220.86 214.28,220.86 C214.28,220.86 214.25,220.81 214.25,220.81 C214.25,220.81 214.21,220.75 214.21,220.75 C214.21,220.75 214.18,220.7 214.18,220.7 C214.18,220.7 214.14,220.65 214.14,220.65 C214.14,220.65 214.11,220.59 214.11,220.59 C214.11,220.59 214.08,220.54 214.08,220.54 C214.08,220.54 214.05,220.48 214.05,220.48 C214.05,220.48 214.02,220.43 214.02,220.43 C214.02,220.43 213.99,220.37 213.99,220.37 C213.99,220.37 213.96,220.32 213.96,220.32 C213.96,220.32 213.93,220.26 213.93,220.26 C213.93,220.26 213.91,220.2 213.91,220.2 C213.91,220.2 213.88,220.14 213.88,220.14 C213.88,220.14 213.86,220.09 213.86,220.09 C213.86,220.09 213.83,220.03 213.83,220.03 C213.83,220.03 213.81,219.97 213.81,219.97 C213.81,219.97 213.79,219.91 213.79,219.91 C213.79,219.91 213.77,219.85 213.77,219.85 C213.77,219.85 213.75,219.79 213.75,219.79 C213.75,219.79 213.73,219.73 213.73,219.73 C213.73,219.73 213.71,219.67 213.71,219.67 C213.71,219.67 213.69,219.61 213.69,219.61 C213.69,219.61 213.68,219.55 213.68,219.55 C213.68,219.55 213.66,219.49 213.66,219.49 C213.66,219.49 213.65,219.43 213.65,219.43 C213.65,219.43 213.64,219.37 213.64,219.37 C213.64,219.37 213.62,219.31 213.62,219.31 C213.62,219.31 213.61,219.24 213.61,219.24 C213.61,219.24 213.6,219.18 213.6,219.18 C213.6,219.18 213.59,219.12 213.59,219.12 C213.59,219.12 213.58,219.06 213.58,219.06 C213.58,219.06 213.57,218.99 213.57,218.99 C213.57,218.99 213.57,218.93 213.57,218.93 C213.57,218.93 213.56,218.87 213.56,218.87 C213.56,218.87 213.56,218.81 213.56,218.81 C213.56,218.81 213.56,218.74 213.56,218.74 C213.56,218.74 213.56,218.68 213.56,218.68 C213.56,218.68 213.55,218.62 213.55,218.62 C213.55,218.62 213.55,218.55 213.55,218.55 C213.55,218.55 213.55,218.49 213.55,218.49 C213.55,218.49 213.56,218.43 213.56,218.43 C213.56,218.43 213.56,218.37 213.56,218.37 C213.56,218.37 213.56,218.3 213.56,218.3 C213.56,218.3 213.56,218.24 213.56,218.24 C213.56,218.24 213.57,218.18 213.57,218.18 C213.57,218.18 213.57,218.12 213.57,218.12 C213.57,218.12 213.58,218.05 213.58,218.05 C213.58,218.05 213.59,217.99 213.59,217.99 C213.59,217.99 213.6,217.93 213.6,217.93 C213.6,217.93 213.61,217.87 213.61,217.87 C213.61,217.87 213.62,217.8 213.62,217.8 C213.62,217.8 213.63,217.74 213.63,217.74 C213.63,217.74 213.65,217.68 213.65,217.68 C213.65,217.68 213.66,217.62 213.66,217.62 C213.66,217.62 213.68,217.56 213.68,217.56 C213.68,217.56 213.69,217.5 213.69,217.5 C213.69,217.5 213.71,217.44 213.71,217.44 C213.71,217.44 213.73,217.38 213.73,217.38 C213.73,217.38 213.75,217.32 213.75,217.32 C213.75,217.32 213.77,217.26 213.77,217.26 C213.77,217.26 213.79,217.2 213.79,217.2 C213.79,217.2 213.81,217.14 213.81,217.14 C213.81,217.14 213.83,217.08 213.83,217.08 C213.83,217.08 213.85,217.02 213.85,217.02 C213.85,217.02 213.88,216.96 213.88,216.96 C213.88,216.96 213.91,216.91 213.91,216.91 C213.91,216.91 213.93,216.85 213.93,216.85 C213.93,216.85 213.96,216.79 213.96,216.79 C213.96,216.79 213.99,216.74 213.99,216.74 C213.99,216.74 214.02,216.68 214.02,216.68 C214.02,216.68 214.05,216.63 214.05,216.63 C214.05,216.63 214.08,216.57 214.08,216.57 C214.08,216.57 214.11,216.52 214.11,216.52 C214.11,216.52 214.14,216.46 214.14,216.46 C214.14,216.46 214.17,216.41 214.17,216.41 C214.17,216.41 214.21,216.36 214.21,216.36 C214.21,216.36 214.24,216.3 214.24,216.3 C214.24,216.3 214.28,216.25 214.28,216.25 C214.28,216.25 214.32,216.2 214.32,216.2 C214.32,216.2 214.35,216.15 214.35,216.15 C214.35,216.15 214.39,216.1 214.39,216.1 C214.39,216.1 214.43,216.05 214.43,216.05 C214.43,216.05 214.47,216 214.47,216 C214.47,216 214.51,215.96 214.51,215.96 C214.51,215.96 214.55,215.91 214.55,215.91 C214.55,215.91 214.59,215.86 214.59,215.86 C214.59,215.86 214.64,215.81 214.64,215.81 C214.64,215.81 214.68,215.77 214.68,215.77 C214.68,215.77 214.73,215.72 214.73,215.72 C214.73,215.72 214.77,215.68 214.77,215.68 C214.77,215.68 214.82,215.64 214.82,215.64 C214.82,215.64 214.86,215.59 214.86,215.59 C214.86,215.59 214.91,215.55 214.91,215.55 C214.91,215.55 214.96,215.51 214.96,215.51 C214.96,215.51 215,215.47 215,215.47 C215,215.47 215.05,215.43 215.05,215.43 C215.05,215.43 215.1,215.39 215.1,215.39 C215.1,215.39 215.15,215.35 215.15,215.35 C215.15,215.35 215.2,215.31 215.2,215.31 C215.2,215.31 215.25,215.28 215.25,215.28 C215.25,215.28 215.31,215.24 215.31,215.24 C215.31,215.24 215.36,215.21 215.36,215.21 C215.36,215.21 215.41,215.17 215.41,215.17 C215.41,215.17 215.46,215.14 215.46,215.14 C215.46,215.14 215.52,215.11 215.52,215.11 C215.52,215.11 215.57,215.08 215.57,215.08 C215.57,215.08 215.63,215.05 215.63,215.05 C215.63,215.05 215.68,215.02 215.68,215.02 C215.68,215.02 215.74,214.99 215.74,214.99 C215.74,214.99 215.79,214.96 215.79,214.96 C215.79,214.96 215.85,214.93 215.85,214.93 C215.85,214.93 215.91,214.9 215.91,214.9 C215.91,214.9 215.97,214.88 215.97,214.88 C215.97,214.88 216.02,214.86 216.02,214.86 C216.02,214.86 216.08,214.83 216.08,214.83 C216.08,214.83 216.14,214.81 216.14,214.81 C216.14,214.81 216.2,214.78 216.2,214.78 C216.2,214.78 216.26,214.77 216.26,214.77 C216.26,214.77 216.32,214.75 216.32,214.75 C216.32,214.75 216.38,214.73 216.38,214.73 C216.38,214.73 216.44,214.71 216.44,214.71 C216.44,214.71 216.5,214.69 216.5,214.69 C216.5,214.69 216.56,214.67 216.56,214.67 C216.56,214.67 216.62,214.66 216.62,214.66 C216.62,214.66 216.68,214.65 216.68,214.65 C216.68,214.65 216.74,214.63 216.74,214.63 C216.74,214.63 216.81,214.62 216.81,214.62 C216.81,214.62 216.87,214.61 216.87,214.61 C216.87,214.61 216.93,214.6 216.93,214.6 C216.93,214.6 216.99,214.59 216.99,214.59 C216.99,214.59 217.05,214.58 217.05,214.58 C217.05,214.58 217.12,214.57 217.12,214.57 C217.12,214.57 217.18,214.57 217.18,214.57 C217.18,214.57 217.24,214.56 217.24,214.56 C217.24,214.56 217.3,214.56 217.3,214.56 C217.3,214.56 217.37,214.56 217.37,214.56 C217.37,214.56 217.43,214.55 217.43,214.55 C217.43,214.55 217.49,214.55 217.49,214.55 C217.49,214.55 217.56,214.55 217.56,214.55 C217.56,214.55 217.62,214.55 217.62,214.55c " android:valueTo="M217.78 201.61 C217.78,201.61 218.06,201.63 218.06,201.63 C218.06,201.63 218.33,201.65 218.33,201.65 C218.33,201.65 218.6,201.68 218.6,201.68 C218.6,201.68 218.87,201.73 218.87,201.73 C218.87,201.73 219.14,201.78 219.14,201.78 C219.14,201.78 219.41,201.84 219.41,201.84 C219.41,201.84 219.67,201.93 219.67,201.93 C219.67,201.93 219.93,202.01 219.93,202.01 C219.93,202.01 220.19,202.09 220.19,202.09 C220.19,202.09 220.44,202.21 220.44,202.21 C220.44,202.21 220.69,202.32 220.69,202.32 C220.69,202.32 220.93,202.45 220.93,202.45 C220.93,202.45 221.17,202.58 221.17,202.58 C221.17,202.58 221.4,202.73 221.4,202.73 C221.4,202.73 221.62,202.88 221.62,202.88 C221.62,202.88 221.85,203.04 221.85,203.04 C221.85,203.04 222.06,203.22 222.06,203.22 C222.06,203.22 222.27,203.39 222.27,203.39 C222.27,203.39 222.46,203.59 222.46,203.59 C222.46,203.59 222.65,203.78 222.65,203.78 C222.65,203.78 222.83,203.99 222.83,203.99 C222.83,203.99 223.01,204.2 223.01,204.2 C223.01,204.2 223.18,204.41 223.18,204.41 C223.18,204.41 223.33,204.64 223.33,204.64 C223.33,204.64 223.48,204.87 223.48,204.87 C223.48,204.87 223.62,205.11 223.62,205.11 C223.62,205.11 223.75,205.34 223.75,205.34 C223.75,205.34 223.88,205.59 223.88,205.59 C223.88,205.59 224,205.83 224,205.83 C224,205.83 224.12,206.08 224.12,206.08 C224.12,206.08 224.24,206.32 224.24,206.32 C224.24,206.32 224.37,206.57 224.37,206.57 C224.37,206.57 224.49,206.81 224.49,206.81 C224.49,206.81 224.61,207.06 224.61,207.06 C224.61,207.06 224.73,207.3 224.73,207.3 C224.73,207.3 224.86,207.55 224.86,207.55 C224.86,207.55 224.98,207.79 224.98,207.79 C224.98,207.79 225.1,208.04 225.1,208.04 C225.1,208.04 225.22,208.28 225.22,208.28 C225.22,208.28 225.35,208.53 225.35,208.53 C225.35,208.53 225.47,208.77 225.47,208.77 C225.47,208.77 225.59,209.02 225.59,209.02 C225.59,209.02 225.71,209.26 225.71,209.26 C225.71,209.26 225.84,209.51 225.84,209.51 C225.84,209.51 225.96,209.75 225.96,209.75 C225.96,209.75 226.08,210 226.08,210 C226.08,210 226.2,210.24 226.2,210.24 C226.2,210.24 226.33,210.49 226.33,210.49 C226.33,210.49 226.45,210.73 226.45,210.73 C226.45,210.73 226.57,210.98 226.57,210.98 C226.57,210.98 226.69,211.22 226.69,211.22 C226.69,211.22 226.82,211.47 226.82,211.47 C226.82,211.47 226.94,211.71 226.94,211.71 C226.94,211.71 227.06,211.96 227.06,211.96 C227.06,211.96 227.18,212.2 227.18,212.2 C227.18,212.2 227.3,212.45 227.3,212.45 C227.3,212.45 227.43,212.69 227.43,212.69 C227.43,212.69 227.55,212.94 227.55,212.94 C227.55,212.94 227.67,213.18 227.67,213.18 C227.67,213.18 227.79,213.43 227.79,213.43 C227.79,213.43 227.92,213.67 227.92,213.67 C227.92,213.67 228.04,213.92 228.04,213.92 C228.04,213.92 228.16,214.16 228.16,214.16 C228.16,214.16 228.28,214.41 228.28,214.41 C228.28,214.41 228.41,214.65 228.41,214.65 C228.41,214.65 228.53,214.9 228.53,214.9 C228.53,214.9 228.65,215.14 228.65,215.14 C228.65,215.14 228.77,215.39 228.77,215.39 C228.77,215.39 228.9,215.63 228.9,215.63 C228.9,215.63 229.02,215.88 229.02,215.88 C229.02,215.88 229.14,216.12 229.14,216.12 C229.14,216.12 229.26,216.37 229.26,216.37 C229.26,216.37 229.39,216.61 229.39,216.61 C229.39,216.61 229.51,216.86 229.51,216.86 C229.51,216.86 229.63,217.1 229.63,217.1 C229.63,217.1 229.75,217.35 229.75,217.35 C229.75,217.35 229.87,217.59 229.87,217.59 C229.87,217.59 230,217.84 230,217.84 C230,217.84 230.12,218.08 230.12,218.08 C230.12,218.08 230.24,218.33 230.24,218.33 C230.24,218.33 230.36,218.57 230.36,218.57 C230.36,218.57 230.49,218.82 230.49,218.82 C230.49,218.82 230.61,219.06 230.61,219.06 C230.61,219.06 230.73,219.31 230.73,219.31 C230.73,219.31 230.85,219.55 230.85,219.55 C230.85,219.55 230.98,219.8 230.98,219.8 C230.98,219.8 231.1,220.04 231.1,220.04 C231.1,220.04 231.22,220.29 231.22,220.29 C231.22,220.29 231.34,220.53 231.34,220.53 C231.34,220.53 231.47,220.78 231.47,220.78 C231.47,220.78 231.59,221.02 231.59,221.02 C231.59,221.02 231.71,221.27 231.71,221.27 C231.71,221.27 231.83,221.51 231.83,221.51 C231.83,221.51 231.96,221.76 231.96,221.76 C231.96,221.76 232.08,222 232.08,222 C232.08,222 232.2,222.25 232.2,222.25 C232.2,222.25 232.32,222.49 232.32,222.49 C232.32,222.49 232.44,222.74 232.44,222.74 C232.44,222.74 232.57,222.98 232.57,222.98 C232.57,222.98 232.69,223.23 232.69,223.23 C232.69,223.23 232.81,223.47 232.81,223.47 C232.81,223.47 232.93,223.71 232.93,223.71 C232.93,223.71 233.06,223.96 233.06,223.96 C233.06,223.96 233.18,224.21 233.18,224.21 C233.18,224.21 233.3,224.45 233.3,224.45 C233.3,224.45 233.42,224.7 233.42,224.7 C233.42,224.7 233.55,224.94 233.55,224.94 C233.55,224.94 233.67,225.19 233.67,225.19 C233.67,225.19 233.79,225.43 233.79,225.43 C233.79,225.43 233.9,225.69 233.9,225.69 C233.9,225.69 234.01,225.94 234.01,225.94 C234.01,225.94 234.12,226.19 234.12,226.19 C234.12,226.19 234.2,226.45 234.2,226.45 C234.2,226.45 234.28,226.71 234.28,226.71 C234.28,226.71 234.35,226.98 234.35,226.98 C234.35,226.98 234.41,227.24 234.41,227.24 C234.41,227.24 234.47,227.51 234.47,227.51 C234.47,227.51 234.5,227.78 234.5,227.78 C234.5,227.78 234.52,228.06 234.52,228.06 C234.52,228.06 234.54,228.33 234.54,228.33 C234.54,228.33 234.54,228.6 234.54,228.6 C234.54,228.6 234.54,228.88 234.54,228.88 C234.54,228.88 234.52,229.15 234.52,229.15 C234.52,229.15 234.49,229.42 234.49,229.42 C234.49,229.42 234.45,229.69 234.45,229.69 C234.45,229.69 234.4,229.96 234.4,229.96 C234.4,229.96 234.34,230.23 234.34,230.23 C234.34,230.23 234.26,230.49 234.26,230.49 C234.26,230.49 234.18,230.75 234.18,230.75 C234.18,230.75 234.08,231.01 234.08,231.01 C234.08,231.01 233.98,231.26 233.98,231.26 C233.98,231.26 233.87,231.51 233.87,231.51 C233.87,231.51 233.74,231.75 233.74,231.75 C233.74,231.75 233.61,232 233.61,232 C233.61,232 233.46,232.23 233.46,232.23 C233.46,232.23 233.31,232.46 233.31,232.46 C233.31,232.46 233.16,232.68 233.16,232.68 C233.16,232.68 232.98,232.89 232.98,232.89 C232.98,232.89 232.81,233.11 232.81,233.11 C232.81,233.11 232.62,233.3 232.62,233.3 C232.62,233.3 232.44,233.5 232.44,233.5 C232.44,233.5 232.24,233.69 232.24,233.69 C232.24,233.69 232.03,233.87 232.03,233.87 C232.03,233.87 231.82,234.04 231.82,234.04 C231.82,234.04 231.6,234.2 231.6,234.2 C231.6,234.2 231.37,234.37 231.37,234.37 C231.37,234.37 231.14,234.51 231.14,234.51 C231.14,234.51 230.91,234.65 230.91,234.65 C230.91,234.65 230.66,234.78 230.66,234.78 C230.66,234.78 230.42,234.89 230.42,234.89 C230.42,234.89 230.17,235.01 230.17,235.01 C230.17,235.01 229.91,235.1 229.91,235.1 C229.91,235.1 229.65,235.19 229.65,235.19 C229.65,235.19 229.39,235.27 229.39,235.27 C229.39,235.27 229.12,235.33 229.12,235.33 C229.12,235.33 228.86,235.4 228.86,235.4 C228.86,235.4 228.59,235.44 228.59,235.44 C228.59,235.44 228.32,235.48 228.32,235.48 C228.32,235.48 228.04,235.49 228.04,235.49 C228.04,235.49 227.77,235.51 227.77,235.51 C227.77,235.51 227.5,235.51 227.5,235.51 C227.5,235.51 227.22,235.49 227.22,235.49 C227.22,235.49 226.95,235.48 226.95,235.48 C226.95,235.48 226.68,235.44 226.68,235.44 C226.68,235.44 226.41,235.4 226.41,235.4 C226.41,235.4 226.14,235.35 226.14,235.35 C226.14,235.35 225.87,235.27 225.87,235.27 C225.87,235.27 225.61,235.2 225.61,235.2 C225.61,235.2 225.35,235.12 225.35,235.12 C225.35,235.12 225.09,235.02 225.09,235.02 C225.09,235.02 224.84,234.92 224.84,234.92 C224.84,234.92 224.59,234.81 224.59,234.81 C224.59,234.81 224.34,234.7 224.34,234.7 C224.34,234.7 224.09,234.59 224.09,234.59 C224.09,234.59 223.84,234.48 223.84,234.48 C223.84,234.48 223.59,234.36 223.59,234.36 C223.59,234.36 223.34,234.25 223.34,234.25 C223.34,234.25 223.09,234.14 223.09,234.14 C223.09,234.14 222.84,234.02 222.84,234.02 C222.84,234.02 222.59,233.91 222.59,233.91 C222.59,233.91 222.34,233.8 222.34,233.8 C222.34,233.8 222.09,233.69 222.09,233.69 C222.09,233.69 221.84,233.58 221.84,233.58 C221.84,233.58 221.59,233.46 221.59,233.46 C221.59,233.46 221.34,233.35 221.34,233.35 C221.34,233.35 221.09,233.24 221.09,233.24 C221.09,233.24 220.84,233.13 220.84,233.13 C220.84,233.13 220.59,233.01 220.59,233.01 C220.59,233.01 220.34,232.9 220.34,232.9 C220.34,232.9 220.09,232.8 220.09,232.8 C220.09,232.8 219.83,232.71 219.83,232.71 C219.83,232.71 219.57,232.62 219.57,232.62 C219.57,232.62 219.3,232.56 219.3,232.56 C219.3,232.56 219.04,232.49 219.04,232.49 C219.04,232.49 218.77,232.44 218.77,232.44 C218.77,232.44 218.5,232.4 218.5,232.4 C218.5,232.4 218.23,232.37 218.23,232.37 C218.23,232.37 217.95,232.35 217.95,232.35 C217.95,232.35 217.68,232.34 217.68,232.34 C217.68,232.34 217.41,232.34 217.41,232.34 C217.41,232.34 217.13,232.36 217.13,232.36 C217.13,232.36 216.86,232.38 216.86,232.38 C216.86,232.38 216.59,232.42 216.59,232.42 C216.59,232.42 216.32,232.46 216.32,232.46 C216.32,232.46 216.05,232.51 216.05,232.51 C216.05,232.51 215.79,232.58 215.79,232.58 C215.79,232.58 215.52,232.66 215.52,232.66 C215.52,232.66 215.26,232.75 215.26,232.75 C215.26,232.75 215.01,232.84 215.01,232.84 C215.01,232.84 214.75,232.94 214.75,232.94 C214.75,232.94 214.5,233.06 214.5,233.06 C214.5,233.06 214.25,233.17 214.25,233.17 C214.25,233.17 214,233.28 214,233.28 C214,233.28 213.75,233.39 213.75,233.39 C213.75,233.39 213.5,233.51 213.5,233.51 C213.5,233.51 213.25,233.62 213.25,233.62 C213.25,233.62 213,233.73 213,233.73 C213,233.73 212.75,233.84 212.75,233.84 C212.75,233.84 212.5,233.96 212.5,233.96 C212.5,233.96 212.26,234.07 212.26,234.07 C212.26,234.07 212.01,234.18 212.01,234.18 C212.01,234.18 211.76,234.29 211.76,234.29 C211.76,234.29 211.51,234.4 211.51,234.4 C211.51,234.4 211.26,234.52 211.26,234.52 C211.26,234.52 211.01,234.63 211.01,234.63 C211.01,234.63 210.76,234.74 210.76,234.74 C210.76,234.74 210.51,234.86 210.51,234.86 C210.51,234.86 210.25,234.96 210.25,234.96 C210.25,234.96 210,235.06 210,235.06 C210,235.06 209.74,235.16 209.74,235.16 C209.74,235.16 209.48,235.23 209.48,235.23 C209.48,235.23 209.22,235.3 209.22,235.3 C209.22,235.3 208.95,235.37 208.95,235.37 C208.95,235.37 208.68,235.41 208.68,235.41 C208.68,235.41 208.41,235.46 208.41,235.46 C208.41,235.46 208.14,235.48 208.14,235.48 C208.14,235.48 207.86,235.5 207.86,235.5 C207.86,235.5 207.59,235.51 207.59,235.51 C207.59,235.51 207.32,235.5 207.32,235.5 C207.32,235.5 207.04,235.49 207.04,235.49 C207.04,235.49 206.77,235.46 206.77,235.46 C206.77,235.46 206.5,235.42 206.5,235.42 C206.5,235.42 206.23,235.38 206.23,235.38 C206.23,235.38 205.96,235.31 205.96,235.31 C205.96,235.31 205.7,235.24 205.7,235.24 C205.7,235.24 205.44,235.16 205.44,235.16 C205.44,235.16 205.18,235.06 205.18,235.06 C205.18,235.06 204.93,234.96 204.93,234.96 C204.93,234.96 204.68,234.85 204.68,234.85 C204.68,234.85 204.43,234.73 204.43,234.73 C204.43,234.73 204.19,234.59 204.19,234.59 C204.19,234.59 203.96,234.45 203.96,234.45 C203.96,234.45 203.73,234.3 203.73,234.3 C203.73,234.3 203.51,234.14 203.51,234.14 C203.51,234.14 203.29,233.98 203.29,233.98 C203.29,233.98 203.08,233.8 203.08,233.8 C203.08,233.8 202.88,233.62 202.88,233.62 C202.88,233.62 202.68,233.43 202.68,233.43 C202.68,233.43 202.49,233.23 202.49,233.23 C202.49,233.23 202.31,233.02 202.31,233.02 C202.31,233.02 202.14,232.81 202.14,232.81 C202.14,232.81 201.97,232.6 201.97,232.6 C201.97,232.6 201.82,232.37 201.82,232.37 C201.82,232.37 201.67,232.14 201.67,232.14 C201.67,232.14 201.53,231.9 201.53,231.9 C201.53,231.9 201.4,231.66 201.4,231.66 C201.4,231.66 201.28,231.42 201.28,231.42 C201.28,231.42 201.17,231.16 201.17,231.16 C201.17,231.16 201.07,230.91 201.07,230.91 C201.07,230.91 200.98,230.65 200.98,230.65 C200.98,230.65 200.9,230.39 200.9,230.39 C200.9,230.39 200.83,230.13 200.83,230.13 C200.83,230.13 200.77,229.86 200.77,229.86 C200.77,229.86 200.72,229.59 200.72,229.59 C200.72,229.59 200.69,229.32 200.69,229.32 C200.69,229.32 200.66,229.04 200.66,229.04 C200.66,229.04 200.65,228.77 200.65,228.77 C200.65,228.77 200.65,228.5 200.65,228.5 C200.65,228.5 200.65,228.22 200.65,228.22 C200.65,228.22 200.68,227.95 200.68,227.95 C200.68,227.95 200.7,227.68 200.7,227.68 C200.7,227.68 200.75,227.41 200.75,227.41 C200.75,227.41 200.8,227.14 200.8,227.14 C200.8,227.14 200.86,226.87 200.86,226.87 C200.86,226.87 200.94,226.61 200.94,226.61 C200.94,226.61 201.02,226.35 201.02,226.35 C201.02,226.35 201.11,226.09 201.11,226.09 C201.11,226.09 201.22,225.84 201.22,225.84 C201.22,225.84 201.33,225.59 201.33,225.59 C201.33,225.59 201.44,225.34 201.44,225.34 C201.44,225.34 201.57,225.1 201.57,225.1 C201.57,225.1 201.69,224.85 201.69,224.85 C201.69,224.85 201.81,224.61 201.81,224.61 C201.81,224.61 201.93,224.36 201.93,224.36 C201.93,224.36 202.06,224.12 202.06,224.12 C202.06,224.12 202.18,223.87 202.18,223.87 C202.18,223.87 202.3,223.63 202.3,223.63 C202.3,223.63 202.42,223.38 202.42,223.38 C202.42,223.38 202.55,223.14 202.55,223.14 C202.55,223.14 202.67,222.89 202.67,222.89 C202.67,222.89 202.79,222.65 202.79,222.65 C202.79,222.65 202.91,222.4 202.91,222.4 C202.91,222.4 203.04,222.16 203.04,222.16 C203.04,222.16 203.16,221.91 203.16,221.91 C203.16,221.91 203.28,221.67 203.28,221.67 C203.28,221.67 203.4,221.42 203.4,221.42 C203.4,221.42 203.52,221.18 203.52,221.18 C203.52,221.18 203.65,220.93 203.65,220.93 C203.65,220.93 203.77,220.69 203.77,220.69 C203.77,220.69 203.89,220.44 203.89,220.44 C203.89,220.44 204.01,220.2 204.01,220.2 C204.01,220.2 204.14,219.95 204.14,219.95 C204.14,219.95 204.26,219.71 204.26,219.71 C204.26,219.71 204.38,219.46 204.38,219.46 C204.38,219.46 204.5,219.22 204.5,219.22 C204.5,219.22 204.63,218.97 204.63,218.97 C204.63,218.97 204.75,218.73 204.75,218.73 C204.75,218.73 204.87,218.48 204.87,218.48 C204.87,218.48 204.99,218.24 204.99,218.24 C204.99,218.24 205.12,217.99 205.12,217.99 C205.12,217.99 205.24,217.75 205.24,217.75 C205.24,217.75 205.36,217.5 205.36,217.5 C205.36,217.5 205.48,217.26 205.48,217.26 C205.48,217.26 205.61,217.01 205.61,217.01 C205.61,217.01 205.73,216.77 205.73,216.77 C205.73,216.77 205.85,216.52 205.85,216.52 C205.85,216.52 205.97,216.28 205.97,216.28 C205.97,216.28 206.09,216.03 206.09,216.03 C206.09,216.03 206.22,215.79 206.22,215.79 C206.22,215.79 206.34,215.54 206.34,215.54 C206.34,215.54 206.46,215.3 206.46,215.3 C206.46,215.3 206.58,215.05 206.58,215.05 C206.58,215.05 206.71,214.81 206.71,214.81 C206.71,214.81 206.83,214.56 206.83,214.56 C206.83,214.56 206.95,214.32 206.95,214.32 C206.95,214.32 207.07,214.07 207.07,214.07 C207.07,214.07 207.2,213.83 207.2,213.83 C207.2,213.83 207.32,213.58 207.32,213.58 C207.32,213.58 207.44,213.34 207.44,213.34 C207.44,213.34 207.56,213.09 207.56,213.09 C207.56,213.09 207.69,212.85 207.69,212.85 C207.69,212.85 207.81,212.6 207.81,212.6 C207.81,212.6 207.93,212.36 207.93,212.36 C207.93,212.36 208.05,212.11 208.05,212.11 C208.05,212.11 208.18,211.87 208.18,211.87 C208.18,211.87 208.3,211.62 208.3,211.62 C208.3,211.62 208.42,211.38 208.42,211.38 C208.42,211.38 208.54,211.13 208.54,211.13 C208.54,211.13 208.66,210.89 208.66,210.89 C208.66,210.89 208.79,210.64 208.79,210.64 C208.79,210.64 208.91,210.4 208.91,210.4 C208.91,210.4 209.03,210.15 209.03,210.15 C209.03,210.15 209.15,209.91 209.15,209.91 C209.15,209.91 209.28,209.66 209.28,209.66 C209.28,209.66 209.4,209.42 209.4,209.42 C209.4,209.42 209.52,209.17 209.52,209.17 C209.52,209.17 209.64,208.93 209.64,208.93 C209.64,208.93 209.77,208.68 209.77,208.68 C209.77,208.68 209.89,208.44 209.89,208.44 C209.89,208.44 210.01,208.19 210.01,208.19 C210.01,208.19 210.13,207.95 210.13,207.95 C210.13,207.95 210.26,207.7 210.26,207.7 C210.26,207.7 210.38,207.46 210.38,207.46 C210.38,207.46 210.5,207.21 210.5,207.21 C210.5,207.21 210.62,206.97 210.62,206.97 C210.62,206.97 210.75,206.72 210.75,206.72 C210.75,206.72 210.87,206.48 210.87,206.48 C210.87,206.48 210.99,206.23 210.99,206.23 C210.99,206.23 211.11,205.99 211.11,205.99 C211.11,205.99 211.24,205.74 211.24,205.74 C211.24,205.74 211.36,205.5 211.36,205.5 C211.36,205.5 211.49,205.26 211.49,205.26 C211.49,205.26 211.62,205.02 211.62,205.02 C211.62,205.02 211.76,204.78 211.76,204.78 C211.76,204.78 211.92,204.56 211.92,204.56 C211.92,204.56 212.07,204.33 212.07,204.33 C212.07,204.33 212.25,204.12 212.25,204.12 C212.25,204.12 212.42,203.91 212.42,203.91 C212.42,203.91 212.61,203.71 212.61,203.71 C212.61,203.71 212.8,203.52 212.8,203.52 C212.8,203.52 213,203.33 213,203.33 C213,203.33 213.21,203.15 213.21,203.15 C213.21,203.15 213.42,202.98 213.42,202.98 C213.42,202.98 213.65,202.82 213.65,202.82 C213.65,202.82 213.87,202.67 213.87,202.67 C213.87,202.67 214.11,202.53 214.11,202.53 C214.11,202.53 214.35,202.4 214.35,202.4 C214.35,202.4 214.6,202.28 214.6,202.28 C214.6,202.28 214.85,202.16 214.85,202.16 C214.85,202.16 215.1,202.06 215.1,202.06 C215.1,202.06 215.36,201.98 215.36,201.98 C215.36,201.98 215.62,201.89 215.62,201.89 C215.62,201.89 215.88,201.81 215.88,201.81 C215.88,201.81 216.15,201.76 216.15,201.76 C216.15,201.76 216.42,201.71 216.42,201.71 C216.42,201.71 216.69,201.66 216.69,201.66 C216.69,201.66 216.96,201.64 216.96,201.64 C216.96,201.64 217.24,201.62 217.24,201.62 C217.24,201.62 217.51,201.61 217.51,201.61 C217.51,201.61 217.78,201.61 217.78,201.61c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="283" android:startOffset="67" android:valueFrom="M217.78 201.61 C217.78,201.61 218.06,201.63 218.06,201.63 C218.06,201.63 218.33,201.65 218.33,201.65 C218.33,201.65 218.6,201.68 218.6,201.68 C218.6,201.68 218.87,201.73 218.87,201.73 C218.87,201.73 219.14,201.78 219.14,201.78 C219.14,201.78 219.41,201.84 219.41,201.84 C219.41,201.84 219.67,201.93 219.67,201.93 C219.67,201.93 219.93,202.01 219.93,202.01 C219.93,202.01 220.19,202.09 220.19,202.09 C220.19,202.09 220.44,202.21 220.44,202.21 C220.44,202.21 220.69,202.32 220.69,202.32 C220.69,202.32 220.93,202.45 220.93,202.45 C220.93,202.45 221.17,202.58 221.17,202.58 C221.17,202.58 221.4,202.73 221.4,202.73 C221.4,202.73 221.62,202.88 221.62,202.88 C221.62,202.88 221.85,203.04 221.85,203.04 C221.85,203.04 222.06,203.22 222.06,203.22 C222.06,203.22 222.27,203.39 222.27,203.39 C222.27,203.39 222.46,203.59 222.46,203.59 C222.46,203.59 222.65,203.78 222.65,203.78 C222.65,203.78 222.83,203.99 222.83,203.99 C222.83,203.99 223.01,204.2 223.01,204.2 C223.01,204.2 223.18,204.41 223.18,204.41 C223.18,204.41 223.33,204.64 223.33,204.64 C223.33,204.64 223.48,204.87 223.48,204.87 C223.48,204.87 223.62,205.11 223.62,205.11 C223.62,205.11 223.75,205.34 223.75,205.34 C223.75,205.34 223.88,205.59 223.88,205.59 C223.88,205.59 224,205.83 224,205.83 C224,205.83 224.12,206.08 224.12,206.08 C224.12,206.08 224.24,206.32 224.24,206.32 C224.24,206.32 224.37,206.57 224.37,206.57 C224.37,206.57 224.49,206.81 224.49,206.81 C224.49,206.81 224.61,207.06 224.61,207.06 C224.61,207.06 224.73,207.3 224.73,207.3 C224.73,207.3 224.86,207.55 224.86,207.55 C224.86,207.55 224.98,207.79 224.98,207.79 C224.98,207.79 225.1,208.04 225.1,208.04 C225.1,208.04 225.22,208.28 225.22,208.28 C225.22,208.28 225.35,208.53 225.35,208.53 C225.35,208.53 225.47,208.77 225.47,208.77 C225.47,208.77 225.59,209.02 225.59,209.02 C225.59,209.02 225.71,209.26 225.71,209.26 C225.71,209.26 225.84,209.51 225.84,209.51 C225.84,209.51 225.96,209.75 225.96,209.75 C225.96,209.75 226.08,210 226.08,210 C226.08,210 226.2,210.24 226.2,210.24 C226.2,210.24 226.33,210.49 226.33,210.49 C226.33,210.49 226.45,210.73 226.45,210.73 C226.45,210.73 226.57,210.98 226.57,210.98 C226.57,210.98 226.69,211.22 226.69,211.22 C226.69,211.22 226.82,211.47 226.82,211.47 C226.82,211.47 226.94,211.71 226.94,211.71 C226.94,211.71 227.06,211.96 227.06,211.96 C227.06,211.96 227.18,212.2 227.18,212.2 C227.18,212.2 227.3,212.45 227.3,212.45 C227.3,212.45 227.43,212.69 227.43,212.69 C227.43,212.69 227.55,212.94 227.55,212.94 C227.55,212.94 227.67,213.18 227.67,213.18 C227.67,213.18 227.79,213.43 227.79,213.43 C227.79,213.43 227.92,213.67 227.92,213.67 C227.92,213.67 228.04,213.92 228.04,213.92 C228.04,213.92 228.16,214.16 228.16,214.16 C228.16,214.16 228.28,214.41 228.28,214.41 C228.28,214.41 228.41,214.65 228.41,214.65 C228.41,214.65 228.53,214.9 228.53,214.9 C228.53,214.9 228.65,215.14 228.65,215.14 C228.65,215.14 228.77,215.39 228.77,215.39 C228.77,215.39 228.9,215.63 228.9,215.63 C228.9,215.63 229.02,215.88 229.02,215.88 C229.02,215.88 229.14,216.12 229.14,216.12 C229.14,216.12 229.26,216.37 229.26,216.37 C229.26,216.37 229.39,216.61 229.39,216.61 C229.39,216.61 229.51,216.86 229.51,216.86 C229.51,216.86 229.63,217.1 229.63,217.1 C229.63,217.1 229.75,217.35 229.75,217.35 C229.75,217.35 229.87,217.59 229.87,217.59 C229.87,217.59 230,217.84 230,217.84 C230,217.84 230.12,218.08 230.12,218.08 C230.12,218.08 230.24,218.33 230.24,218.33 C230.24,218.33 230.36,218.57 230.36,218.57 C230.36,218.57 230.49,218.82 230.49,218.82 C230.49,218.82 230.61,219.06 230.61,219.06 C230.61,219.06 230.73,219.31 230.73,219.31 C230.73,219.31 230.85,219.55 230.85,219.55 C230.85,219.55 230.98,219.8 230.98,219.8 C230.98,219.8 231.1,220.04 231.1,220.04 C231.1,220.04 231.22,220.29 231.22,220.29 C231.22,220.29 231.34,220.53 231.34,220.53 C231.34,220.53 231.47,220.78 231.47,220.78 C231.47,220.78 231.59,221.02 231.59,221.02 C231.59,221.02 231.71,221.27 231.71,221.27 C231.71,221.27 231.83,221.51 231.83,221.51 C231.83,221.51 231.96,221.76 231.96,221.76 C231.96,221.76 232.08,222 232.08,222 C232.08,222 232.2,222.25 232.2,222.25 C232.2,222.25 232.32,222.49 232.32,222.49 C232.32,222.49 232.44,222.74 232.44,222.74 C232.44,222.74 232.57,222.98 232.57,222.98 C232.57,222.98 232.69,223.23 232.69,223.23 C232.69,223.23 232.81,223.47 232.81,223.47 C232.81,223.47 232.93,223.71 232.93,223.71 C232.93,223.71 233.06,223.96 233.06,223.96 C233.06,223.96 233.18,224.21 233.18,224.21 C233.18,224.21 233.3,224.45 233.3,224.45 C233.3,224.45 233.42,224.7 233.42,224.7 C233.42,224.7 233.55,224.94 233.55,224.94 C233.55,224.94 233.67,225.19 233.67,225.19 C233.67,225.19 233.79,225.43 233.79,225.43 C233.79,225.43 233.9,225.69 233.9,225.69 C233.9,225.69 234.01,225.94 234.01,225.94 C234.01,225.94 234.12,226.19 234.12,226.19 C234.12,226.19 234.2,226.45 234.2,226.45 C234.2,226.45 234.28,226.71 234.28,226.71 C234.28,226.71 234.35,226.98 234.35,226.98 C234.35,226.98 234.41,227.24 234.41,227.24 C234.41,227.24 234.47,227.51 234.47,227.51 C234.47,227.51 234.5,227.78 234.5,227.78 C234.5,227.78 234.52,228.06 234.52,228.06 C234.52,228.06 234.54,228.33 234.54,228.33 C234.54,228.33 234.54,228.6 234.54,228.6 C234.54,228.6 234.54,228.88 234.54,228.88 C234.54,228.88 234.52,229.15 234.52,229.15 C234.52,229.15 234.49,229.42 234.49,229.42 C234.49,229.42 234.45,229.69 234.45,229.69 C234.45,229.69 234.4,229.96 234.4,229.96 C234.4,229.96 234.34,230.23 234.34,230.23 C234.34,230.23 234.26,230.49 234.26,230.49 C234.26,230.49 234.18,230.75 234.18,230.75 C234.18,230.75 234.08,231.01 234.08,231.01 C234.08,231.01 233.98,231.26 233.98,231.26 C233.98,231.26 233.87,231.51 233.87,231.51 C233.87,231.51 233.74,231.75 233.74,231.75 C233.74,231.75 233.61,232 233.61,232 C233.61,232 233.46,232.23 233.46,232.23 C233.46,232.23 233.31,232.46 233.31,232.46 C233.31,232.46 233.16,232.68 233.16,232.68 C233.16,232.68 232.98,232.89 232.98,232.89 C232.98,232.89 232.81,233.11 232.81,233.11 C232.81,233.11 232.62,233.3 232.62,233.3 C232.62,233.3 232.44,233.5 232.44,233.5 C232.44,233.5 232.24,233.69 232.24,233.69 C232.24,233.69 232.03,233.87 232.03,233.87 C232.03,233.87 231.82,234.04 231.82,234.04 C231.82,234.04 231.6,234.2 231.6,234.2 C231.6,234.2 231.37,234.37 231.37,234.37 C231.37,234.37 231.14,234.51 231.14,234.51 C231.14,234.51 230.91,234.65 230.91,234.65 C230.91,234.65 230.66,234.78 230.66,234.78 C230.66,234.78 230.42,234.89 230.42,234.89 C230.42,234.89 230.17,235.01 230.17,235.01 C230.17,235.01 229.91,235.1 229.91,235.1 C229.91,235.1 229.65,235.19 229.65,235.19 C229.65,235.19 229.39,235.27 229.39,235.27 C229.39,235.27 229.12,235.33 229.12,235.33 C229.12,235.33 228.86,235.4 228.86,235.4 C228.86,235.4 228.59,235.44 228.59,235.44 C228.59,235.44 228.32,235.48 228.32,235.48 C228.32,235.48 228.04,235.49 228.04,235.49 C228.04,235.49 227.77,235.51 227.77,235.51 C227.77,235.51 227.5,235.51 227.5,235.51 C227.5,235.51 227.22,235.49 227.22,235.49 C227.22,235.49 226.95,235.48 226.95,235.48 C226.95,235.48 226.68,235.44 226.68,235.44 C226.68,235.44 226.41,235.4 226.41,235.4 C226.41,235.4 226.14,235.35 226.14,235.35 C226.14,235.35 225.87,235.27 225.87,235.27 C225.87,235.27 225.61,235.2 225.61,235.2 C225.61,235.2 225.35,235.12 225.35,235.12 C225.35,235.12 225.09,235.02 225.09,235.02 C225.09,235.02 224.84,234.92 224.84,234.92 C224.84,234.92 224.59,234.81 224.59,234.81 C224.59,234.81 224.34,234.7 224.34,234.7 C224.34,234.7 224.09,234.59 224.09,234.59 C224.09,234.59 223.84,234.48 223.84,234.48 C223.84,234.48 223.59,234.36 223.59,234.36 C223.59,234.36 223.34,234.25 223.34,234.25 C223.34,234.25 223.09,234.14 223.09,234.14 C223.09,234.14 222.84,234.02 222.84,234.02 C222.84,234.02 222.59,233.91 222.59,233.91 C222.59,233.91 222.34,233.8 222.34,233.8 C222.34,233.8 222.09,233.69 222.09,233.69 C222.09,233.69 221.84,233.58 221.84,233.58 C221.84,233.58 221.59,233.46 221.59,233.46 C221.59,233.46 221.34,233.35 221.34,233.35 C221.34,233.35 221.09,233.24 221.09,233.24 C221.09,233.24 220.84,233.13 220.84,233.13 C220.84,233.13 220.59,233.01 220.59,233.01 C220.59,233.01 220.34,232.9 220.34,232.9 C220.34,232.9 220.09,232.8 220.09,232.8 C220.09,232.8 219.83,232.71 219.83,232.71 C219.83,232.71 219.57,232.62 219.57,232.62 C219.57,232.62 219.3,232.56 219.3,232.56 C219.3,232.56 219.04,232.49 219.04,232.49 C219.04,232.49 218.77,232.44 218.77,232.44 C218.77,232.44 218.5,232.4 218.5,232.4 C218.5,232.4 218.23,232.37 218.23,232.37 C218.23,232.37 217.95,232.35 217.95,232.35 C217.95,232.35 217.68,232.34 217.68,232.34 C217.68,232.34 217.41,232.34 217.41,232.34 C217.41,232.34 217.13,232.36 217.13,232.36 C217.13,232.36 216.86,232.38 216.86,232.38 C216.86,232.38 216.59,232.42 216.59,232.42 C216.59,232.42 216.32,232.46 216.32,232.46 C216.32,232.46 216.05,232.51 216.05,232.51 C216.05,232.51 215.79,232.58 215.79,232.58 C215.79,232.58 215.52,232.66 215.52,232.66 C215.52,232.66 215.26,232.75 215.26,232.75 C215.26,232.75 215.01,232.84 215.01,232.84 C215.01,232.84 214.75,232.94 214.75,232.94 C214.75,232.94 214.5,233.06 214.5,233.06 C214.5,233.06 214.25,233.17 214.25,233.17 C214.25,233.17 214,233.28 214,233.28 C214,233.28 213.75,233.39 213.75,233.39 C213.75,233.39 213.5,233.51 213.5,233.51 C213.5,233.51 213.25,233.62 213.25,233.62 C213.25,233.62 213,233.73 213,233.73 C213,233.73 212.75,233.84 212.75,233.84 C212.75,233.84 212.5,233.96 212.5,233.96 C212.5,233.96 212.26,234.07 212.26,234.07 C212.26,234.07 212.01,234.18 212.01,234.18 C212.01,234.18 211.76,234.29 211.76,234.29 C211.76,234.29 211.51,234.4 211.51,234.4 C211.51,234.4 211.26,234.52 211.26,234.52 C211.26,234.52 211.01,234.63 211.01,234.63 C211.01,234.63 210.76,234.74 210.76,234.74 C210.76,234.74 210.51,234.86 210.51,234.86 C210.51,234.86 210.25,234.96 210.25,234.96 C210.25,234.96 210,235.06 210,235.06 C210,235.06 209.74,235.16 209.74,235.16 C209.74,235.16 209.48,235.23 209.48,235.23 C209.48,235.23 209.22,235.3 209.22,235.3 C209.22,235.3 208.95,235.37 208.95,235.37 C208.95,235.37 208.68,235.41 208.68,235.41 C208.68,235.41 208.41,235.46 208.41,235.46 C208.41,235.46 208.14,235.48 208.14,235.48 C208.14,235.48 207.86,235.5 207.86,235.5 C207.86,235.5 207.59,235.51 207.59,235.51 C207.59,235.51 207.32,235.5 207.32,235.5 C207.32,235.5 207.04,235.49 207.04,235.49 C207.04,235.49 206.77,235.46 206.77,235.46 C206.77,235.46 206.5,235.42 206.5,235.42 C206.5,235.42 206.23,235.38 206.23,235.38 C206.23,235.38 205.96,235.31 205.96,235.31 C205.96,235.31 205.7,235.24 205.7,235.24 C205.7,235.24 205.44,235.16 205.44,235.16 C205.44,235.16 205.18,235.06 205.18,235.06 C205.18,235.06 204.93,234.96 204.93,234.96 C204.93,234.96 204.68,234.85 204.68,234.85 C204.68,234.85 204.43,234.73 204.43,234.73 C204.43,234.73 204.19,234.59 204.19,234.59 C204.19,234.59 203.96,234.45 203.96,234.45 C203.96,234.45 203.73,234.3 203.73,234.3 C203.73,234.3 203.51,234.14 203.51,234.14 C203.51,234.14 203.29,233.98 203.29,233.98 C203.29,233.98 203.08,233.8 203.08,233.8 C203.08,233.8 202.88,233.62 202.88,233.62 C202.88,233.62 202.68,233.43 202.68,233.43 C202.68,233.43 202.49,233.23 202.49,233.23 C202.49,233.23 202.31,233.02 202.31,233.02 C202.31,233.02 202.14,232.81 202.14,232.81 C202.14,232.81 201.97,232.6 201.97,232.6 C201.97,232.6 201.82,232.37 201.82,232.37 C201.82,232.37 201.67,232.14 201.67,232.14 C201.67,232.14 201.53,231.9 201.53,231.9 C201.53,231.9 201.4,231.66 201.4,231.66 C201.4,231.66 201.28,231.42 201.28,231.42 C201.28,231.42 201.17,231.16 201.17,231.16 C201.17,231.16 201.07,230.91 201.07,230.91 C201.07,230.91 200.98,230.65 200.98,230.65 C200.98,230.65 200.9,230.39 200.9,230.39 C200.9,230.39 200.83,230.13 200.83,230.13 C200.83,230.13 200.77,229.86 200.77,229.86 C200.77,229.86 200.72,229.59 200.72,229.59 C200.72,229.59 200.69,229.32 200.69,229.32 C200.69,229.32 200.66,229.04 200.66,229.04 C200.66,229.04 200.65,228.77 200.65,228.77 C200.65,228.77 200.65,228.5 200.65,228.5 C200.65,228.5 200.65,228.22 200.65,228.22 C200.65,228.22 200.68,227.95 200.68,227.95 C200.68,227.95 200.7,227.68 200.7,227.68 C200.7,227.68 200.75,227.41 200.75,227.41 C200.75,227.41 200.8,227.14 200.8,227.14 C200.8,227.14 200.86,226.87 200.86,226.87 C200.86,226.87 200.94,226.61 200.94,226.61 C200.94,226.61 201.02,226.35 201.02,226.35 C201.02,226.35 201.11,226.09 201.11,226.09 C201.11,226.09 201.22,225.84 201.22,225.84 C201.22,225.84 201.33,225.59 201.33,225.59 C201.33,225.59 201.44,225.34 201.44,225.34 C201.44,225.34 201.57,225.1 201.57,225.1 C201.57,225.1 201.69,224.85 201.69,224.85 C201.69,224.85 201.81,224.61 201.81,224.61 C201.81,224.61 201.93,224.36 201.93,224.36 C201.93,224.36 202.06,224.12 202.06,224.12 C202.06,224.12 202.18,223.87 202.18,223.87 C202.18,223.87 202.3,223.63 202.3,223.63 C202.3,223.63 202.42,223.38 202.42,223.38 C202.42,223.38 202.55,223.14 202.55,223.14 C202.55,223.14 202.67,222.89 202.67,222.89 C202.67,222.89 202.79,222.65 202.79,222.65 C202.79,222.65 202.91,222.4 202.91,222.4 C202.91,222.4 203.04,222.16 203.04,222.16 C203.04,222.16 203.16,221.91 203.16,221.91 C203.16,221.91 203.28,221.67 203.28,221.67 C203.28,221.67 203.4,221.42 203.4,221.42 C203.4,221.42 203.52,221.18 203.52,221.18 C203.52,221.18 203.65,220.93 203.65,220.93 C203.65,220.93 203.77,220.69 203.77,220.69 C203.77,220.69 203.89,220.44 203.89,220.44 C203.89,220.44 204.01,220.2 204.01,220.2 C204.01,220.2 204.14,219.95 204.14,219.95 C204.14,219.95 204.26,219.71 204.26,219.71 C204.26,219.71 204.38,219.46 204.38,219.46 C204.38,219.46 204.5,219.22 204.5,219.22 C204.5,219.22 204.63,218.97 204.63,218.97 C204.63,218.97 204.75,218.73 204.75,218.73 C204.75,218.73 204.87,218.48 204.87,218.48 C204.87,218.48 204.99,218.24 204.99,218.24 C204.99,218.24 205.12,217.99 205.12,217.99 C205.12,217.99 205.24,217.75 205.24,217.75 C205.24,217.75 205.36,217.5 205.36,217.5 C205.36,217.5 205.48,217.26 205.48,217.26 C205.48,217.26 205.61,217.01 205.61,217.01 C205.61,217.01 205.73,216.77 205.73,216.77 C205.73,216.77 205.85,216.52 205.85,216.52 C205.85,216.52 205.97,216.28 205.97,216.28 C205.97,216.28 206.09,216.03 206.09,216.03 C206.09,216.03 206.22,215.79 206.22,215.79 C206.22,215.79 206.34,215.54 206.34,215.54 C206.34,215.54 206.46,215.3 206.46,215.3 C206.46,215.3 206.58,215.05 206.58,215.05 C206.58,215.05 206.71,214.81 206.71,214.81 C206.71,214.81 206.83,214.56 206.83,214.56 C206.83,214.56 206.95,214.32 206.95,214.32 C206.95,214.32 207.07,214.07 207.07,214.07 C207.07,214.07 207.2,213.83 207.2,213.83 C207.2,213.83 207.32,213.58 207.32,213.58 C207.32,213.58 207.44,213.34 207.44,213.34 C207.44,213.34 207.56,213.09 207.56,213.09 C207.56,213.09 207.69,212.85 207.69,212.85 C207.69,212.85 207.81,212.6 207.81,212.6 C207.81,212.6 207.93,212.36 207.93,212.36 C207.93,212.36 208.05,212.11 208.05,212.11 C208.05,212.11 208.18,211.87 208.18,211.87 C208.18,211.87 208.3,211.62 208.3,211.62 C208.3,211.62 208.42,211.38 208.42,211.38 C208.42,211.38 208.54,211.13 208.54,211.13 C208.54,211.13 208.66,210.89 208.66,210.89 C208.66,210.89 208.79,210.64 208.79,210.64 C208.79,210.64 208.91,210.4 208.91,210.4 C208.91,210.4 209.03,210.15 209.03,210.15 C209.03,210.15 209.15,209.91 209.15,209.91 C209.15,209.91 209.28,209.66 209.28,209.66 C209.28,209.66 209.4,209.42 209.4,209.42 C209.4,209.42 209.52,209.17 209.52,209.17 C209.52,209.17 209.64,208.93 209.64,208.93 C209.64,208.93 209.77,208.68 209.77,208.68 C209.77,208.68 209.89,208.44 209.89,208.44 C209.89,208.44 210.01,208.19 210.01,208.19 C210.01,208.19 210.13,207.95 210.13,207.95 C210.13,207.95 210.26,207.7 210.26,207.7 C210.26,207.7 210.38,207.46 210.38,207.46 C210.38,207.46 210.5,207.21 210.5,207.21 C210.5,207.21 210.62,206.97 210.62,206.97 C210.62,206.97 210.75,206.72 210.75,206.72 C210.75,206.72 210.87,206.48 210.87,206.48 C210.87,206.48 210.99,206.23 210.99,206.23 C210.99,206.23 211.11,205.99 211.11,205.99 C211.11,205.99 211.24,205.74 211.24,205.74 C211.24,205.74 211.36,205.5 211.36,205.5 C211.36,205.5 211.49,205.26 211.49,205.26 C211.49,205.26 211.62,205.02 211.62,205.02 C211.62,205.02 211.76,204.78 211.76,204.78 C211.76,204.78 211.92,204.56 211.92,204.56 C211.92,204.56 212.07,204.33 212.07,204.33 C212.07,204.33 212.25,204.12 212.25,204.12 C212.25,204.12 212.42,203.91 212.42,203.91 C212.42,203.91 212.61,203.71 212.61,203.71 C212.61,203.71 212.8,203.52 212.8,203.52 C212.8,203.52 213,203.33 213,203.33 C213,203.33 213.21,203.15 213.21,203.15 C213.21,203.15 213.42,202.98 213.42,202.98 C213.42,202.98 213.65,202.82 213.65,202.82 C213.65,202.82 213.87,202.67 213.87,202.67 C213.87,202.67 214.11,202.53 214.11,202.53 C214.11,202.53 214.35,202.4 214.35,202.4 C214.35,202.4 214.6,202.28 214.6,202.28 C214.6,202.28 214.85,202.16 214.85,202.16 C214.85,202.16 215.1,202.06 215.1,202.06 C215.1,202.06 215.36,201.98 215.36,201.98 C215.36,201.98 215.62,201.89 215.62,201.89 C215.62,201.89 215.88,201.81 215.88,201.81 C215.88,201.81 216.15,201.76 216.15,201.76 C216.15,201.76 216.42,201.71 216.42,201.71 C216.42,201.71 216.69,201.66 216.69,201.66 C216.69,201.66 216.96,201.64 216.96,201.64 C216.96,201.64 217.24,201.62 217.24,201.62 C217.24,201.62 217.51,201.61 217.51,201.61 C217.51,201.61 217.78,201.61 217.78,201.61c " android:valueTo="M217.68 210.56 C217.68,210.56 217.81,210.57 217.81,210.57 C217.81,210.57 217.93,210.57 217.93,210.57 C217.93,210.57 218.06,210.58 218.06,210.58 C218.06,210.58 218.18,210.59 218.18,210.59 C218.18,210.59 218.31,210.59 218.31,210.59 C218.31,210.59 218.43,210.61 218.43,210.61 C218.43,210.61 218.56,210.63 218.56,210.63 C218.56,210.63 218.68,210.64 218.68,210.64 C218.68,210.64 218.81,210.66 218.81,210.66 C218.81,210.66 218.93,210.68 218.93,210.68 C218.93,210.68 219.05,210.7 219.05,210.7 C219.05,210.7 219.18,210.72 219.18,210.72 C219.18,210.72 219.3,210.75 219.3,210.75 C219.3,210.75 219.42,210.78 219.42,210.78 C219.42,210.78 219.54,210.81 219.54,210.81 C219.54,210.81 219.66,210.84 219.66,210.84 C219.66,210.84 219.79,210.87 219.79,210.87 C219.79,210.87 219.91,210.91 219.91,210.91 C219.91,210.91 220.03,210.95 220.03,210.95 C220.03,210.95 220.14,210.99 220.14,210.99 C220.14,210.99 220.26,211.04 220.26,211.04 C220.26,211.04 220.38,211.08 220.38,211.08 C220.38,211.08 220.5,211.12 220.5,211.12 C220.5,211.12 220.62,211.17 220.62,211.17 C220.62,211.17 220.73,211.22 220.73,211.22 C220.73,211.22 220.84,211.27 220.84,211.27 C220.84,211.27 220.96,211.32 220.96,211.32 C220.96,211.32 221.07,211.38 221.07,211.38 C221.07,211.38 221.19,211.43 221.19,211.43 C221.19,211.43 221.3,211.49 221.3,211.49 C221.3,211.49 221.41,211.55 221.41,211.55 C221.41,211.55 221.51,211.61 221.51,211.61 C221.51,211.61 221.62,211.68 221.62,211.68 C221.62,211.68 221.73,211.74 221.73,211.74 C221.73,211.74 221.84,211.8 221.84,211.8 C221.84,211.8 221.94,211.87 221.94,211.87 C221.94,211.87 222.05,211.94 222.05,211.94 C222.05,211.94 222.15,212.02 222.15,212.02 C222.15,212.02 222.25,212.09 222.25,212.09 C222.25,212.09 222.35,212.16 222.35,212.16 C222.35,212.16 222.46,212.23 222.46,212.23 C222.46,212.23 222.55,212.31 222.55,212.31 C222.55,212.31 222.65,212.4 222.65,212.4 C222.65,212.4 222.74,212.48 222.74,212.48 C222.74,212.48 222.84,212.56 222.84,212.56 C222.84,212.56 222.93,212.64 222.93,212.64 C222.93,212.64 223.03,212.72 223.03,212.72 C223.03,212.72 223.12,212.81 223.12,212.81 C223.12,212.81 223.21,212.9 223.21,212.9 C223.21,212.9 223.29,212.99 223.29,212.99 C223.29,212.99 223.38,213.08 223.38,213.08 C223.38,213.08 223.47,213.17 223.47,213.17 C223.47,213.17 223.55,213.26 223.55,213.26 C223.55,213.26 223.63,213.36 223.63,213.36 C223.63,213.36 223.71,213.46 223.71,213.46 C223.71,213.46 223.79,213.56 223.79,213.56 C223.79,213.56 223.87,213.66 223.87,213.66 C223.87,213.66 223.95,213.75 223.95,213.75 C223.95,213.75 224.03,213.85 224.03,213.85 C224.03,213.85 224.09,213.96 224.09,213.96 C224.09,213.96 224.16,214.06 224.16,214.06 C224.16,214.06 224.23,214.17 224.23,214.17 C224.23,214.17 224.3,214.27 224.3,214.27 C224.3,214.27 224.37,214.38 224.37,214.38 C224.37,214.38 224.44,214.48 224.44,214.48 C224.44,214.48 224.5,214.59 224.5,214.59 C224.5,214.59 224.56,214.7 224.56,214.7 C224.56,214.7 224.62,214.81 224.62,214.81 C224.62,214.81 224.68,214.93 224.68,214.93 C224.68,214.93 224.74,215.04 224.74,215.04 C224.74,215.04 224.79,215.15 224.79,215.15 C224.79,215.15 224.84,215.26 224.84,215.26 C224.84,215.26 224.89,215.38 224.89,215.38 C224.89,215.38 224.94,215.5 224.94,215.5 C224.94,215.5 224.99,215.61 224.99,215.61 C224.99,215.61 225.04,215.73 225.04,215.73 C225.04,215.73 225.08,215.84 225.08,215.84 C225.08,215.84 225.12,215.96 225.12,215.96 C225.12,215.96 225.16,216.08 225.16,216.08 C225.16,216.08 225.19,216.2 225.19,216.2 C225.19,216.2 225.23,216.32 225.23,216.32 C225.23,216.32 225.27,216.44 225.27,216.44 C225.27,216.44 225.3,216.56 225.3,216.56 C225.3,216.56 225.33,216.69 225.33,216.69 C225.33,216.69 225.35,216.81 225.35,216.81 C225.35,216.81 225.38,216.93 225.38,216.93 C225.38,216.93 225.41,217.06 225.41,217.06 C225.41,217.06 225.43,217.18 225.43,217.18 C225.43,217.18 225.46,217.3 225.46,217.3 C225.46,217.3 225.47,217.43 225.47,217.43 C225.47,217.43 225.49,217.55 225.49,217.55 C225.49,217.55 225.5,217.68 225.5,217.68 C225.5,217.68 225.52,217.8 225.52,217.8 C225.52,217.8 225.52,217.93 225.52,217.93 C225.52,217.93 225.53,218.05 225.53,218.05 C225.53,218.05 225.54,218.18 225.54,218.18 C225.54,218.18 225.54,218.3 225.54,218.3 C225.54,218.3 225.55,218.43 225.55,218.43 C225.55,218.43 225.55,218.55 225.55,218.55 C225.55,218.55 225.55,218.68 225.55,218.68 C225.55,218.68 225.54,218.8 225.54,218.8 C225.54,218.8 225.54,218.93 225.54,218.93 C225.54,218.93 225.53,219.05 225.53,219.05 C225.53,219.05 225.52,219.18 225.52,219.18 C225.52,219.18 225.52,219.31 225.52,219.31 C225.52,219.31 225.5,219.43 225.5,219.43 C225.5,219.43 225.48,219.55 225.48,219.55 C225.48,219.55 225.47,219.68 225.47,219.68 C225.47,219.68 225.45,219.8 225.45,219.8 C225.45,219.8 225.43,219.93 225.43,219.93 C225.43,219.93 225.41,220.05 225.41,220.05 C225.41,220.05 225.39,220.17 225.39,220.17 C225.39,220.17 225.36,220.3 225.36,220.3 C225.36,220.3 225.33,220.42 225.33,220.42 C225.33,220.42 225.3,220.54 225.3,220.54 C225.3,220.54 225.27,220.66 225.27,220.66 C225.27,220.66 225.24,220.78 225.24,220.78 C225.24,220.78 225.2,220.9 225.2,220.9 C225.2,220.9 225.16,221.02 225.16,221.02 C225.16,221.02 225.12,221.14 225.12,221.14 C225.12,221.14 225.08,221.26 225.08,221.26 C225.08,221.26 225.03,221.38 225.03,221.38 C225.03,221.38 224.99,221.5 224.99,221.5 C224.99,221.5 224.95,221.61 224.95,221.61 C224.95,221.61 224.89,221.73 224.89,221.73 C224.89,221.73 224.84,221.84 224.84,221.84 C224.84,221.84 224.79,221.96 224.79,221.96 C224.79,221.96 224.73,222.07 224.73,222.07 C224.73,222.07 224.68,222.18 224.68,222.18 C224.68,222.18 224.62,222.29 224.62,222.29 C224.62,222.29 224.56,222.4 224.56,222.4 C224.56,222.4 224.5,222.51 224.5,222.51 C224.5,222.51 224.44,222.62 224.44,222.62 C224.44,222.62 224.37,222.73 224.37,222.73 C224.37,222.73 224.31,222.84 224.31,222.84 C224.31,222.84 224.24,222.94 224.24,222.94 C224.24,222.94 224.17,223.05 224.17,223.05 C224.17,223.05 224.09,223.15 224.09,223.15 C224.09,223.15 224.02,223.25 224.02,223.25 C224.02,223.25 223.95,223.35 223.95,223.35 C223.95,223.35 223.88,223.45 223.88,223.45 C223.88,223.45 223.8,223.55 223.8,223.55 C223.8,223.55 223.71,223.65 223.71,223.65 C223.71,223.65 223.63,223.74 223.63,223.74 C223.63,223.74 223.55,223.84 223.55,223.84 C223.55,223.84 223.47,223.93 223.47,223.93 C223.47,223.93 223.39,224.03 223.39,224.03 C223.39,224.03 223.3,224.12 223.3,224.12 C223.3,224.12 223.21,224.2 223.21,224.2 C223.21,224.2 223.12,224.29 223.12,224.29 C223.12,224.29 223.03,224.38 223.03,224.38 C223.03,224.38 222.94,224.46 222.94,224.46 C222.94,224.46 222.85,224.55 222.85,224.55 C222.85,224.55 222.75,224.63 222.75,224.63 C222.75,224.63 222.65,224.71 222.65,224.71 C222.65,224.71 222.55,224.79 222.55,224.79 C222.55,224.79 222.46,224.87 222.46,224.87 C222.46,224.87 222.36,224.95 222.36,224.95 C222.36,224.95 222.26,225.02 222.26,225.02 C222.26,225.02 222.15,225.09 222.15,225.09 C222.15,225.09 222.05,225.16 222.05,225.16 C222.05,225.16 221.94,225.23 221.94,225.23 C221.94,225.23 221.84,225.3 221.84,225.3 C221.84,225.3 221.74,225.37 221.74,225.37 C221.74,225.37 221.63,225.44 221.63,225.44 C221.63,225.44 221.52,225.5 221.52,225.5 C221.52,225.5 221.41,225.56 221.41,225.56 C221.41,225.56 221.3,225.62 221.3,225.62 C221.3,225.62 221.19,225.68 221.19,225.68 C221.19,225.68 221.08,225.73 221.08,225.73 C221.08,225.73 220.96,225.79 220.96,225.79 C220.96,225.79 220.85,225.84 220.85,225.84 C220.85,225.84 220.73,225.89 220.73,225.89 C220.73,225.89 220.62,225.94 220.62,225.94 C220.62,225.94 220.5,225.99 220.5,225.99 C220.5,225.99 220.38,226.03 220.38,226.03 C220.38,226.03 220.27,226.08 220.27,226.08 C220.27,226.08 220.15,226.12 220.15,226.12 C220.15,226.12 220.03,226.15 220.03,226.15 C220.03,226.15 219.91,226.19 219.91,226.19 C219.91,226.19 219.79,226.23 219.79,226.23 C219.79,226.23 219.67,226.27 219.67,226.27 C219.67,226.27 219.55,226.3 219.55,226.3 C219.55,226.3 219.42,226.33 219.42,226.33 C219.42,226.33 219.3,226.35 219.3,226.35 C219.3,226.35 219.18,226.38 219.18,226.38 C219.18,226.38 219.06,226.4 219.06,226.4 C219.06,226.4 218.93,226.43 218.93,226.43 C218.93,226.43 218.81,226.45 218.81,226.45 C218.81,226.45 218.68,226.47 218.68,226.47 C218.68,226.47 218.56,226.49 218.56,226.49 C218.56,226.49 218.44,226.5 218.44,226.5 C218.44,226.5 218.31,226.52 218.31,226.52 C218.31,226.52 218.19,226.52 218.19,226.52 C218.19,226.52 218.06,226.53 218.06,226.53 C218.06,226.53 217.93,226.53 217.93,226.53 C217.93,226.53 217.81,226.54 217.81,226.54 C217.81,226.54 217.68,226.55 217.68,226.55 C217.68,226.55 217.56,226.55 217.56,226.55 C217.56,226.55 217.43,226.55 217.43,226.55 C217.43,226.55 217.31,226.54 217.31,226.54 C217.31,226.54 217.18,226.53 217.18,226.53 C217.18,226.53 217.05,226.53 217.05,226.53 C217.05,226.53 216.93,226.52 216.93,226.52 C216.93,226.52 216.8,226.52 216.8,226.52 C216.8,226.52 216.68,226.5 216.68,226.5 C216.68,226.5 216.55,226.48 216.55,226.48 C216.55,226.48 216.43,226.46 216.43,226.46 C216.43,226.46 216.31,226.45 216.31,226.45 C216.31,226.45 216.18,226.43 216.18,226.43 C216.18,226.43 216.06,226.41 216.06,226.41 C216.06,226.41 215.93,226.38 215.93,226.38 C215.93,226.38 215.81,226.35 215.81,226.35 C215.81,226.35 215.69,226.32 215.69,226.32 C215.69,226.32 215.57,226.29 215.57,226.29 C215.57,226.29 215.45,226.26 215.45,226.26 C215.45,226.26 215.32,226.23 215.32,226.23 C215.32,226.23 215.2,226.2 215.2,226.2 C215.2,226.2 215.09,226.16 215.09,226.16 C215.09,226.16 214.97,226.12 214.97,226.12 C214.97,226.12 214.85,226.07 214.85,226.07 C214.85,226.07 214.73,226.03 214.73,226.03 C214.73,226.03 214.61,225.99 214.61,225.99 C214.61,225.99 214.5,225.94 214.5,225.94 C214.5,225.94 214.38,225.89 214.38,225.89 C214.38,225.89 214.27,225.84 214.27,225.84 C214.27,225.84 214.15,225.79 214.15,225.79 C214.15,225.79 214.04,225.73 214.04,225.73 C214.04,225.73 213.93,225.68 213.93,225.68 C213.93,225.68 213.81,225.62 213.81,225.62 C213.81,225.62 213.71,225.56 213.71,225.56 C213.71,225.56 213.6,225.5 213.6,225.5 C213.6,225.5 213.49,225.43 213.49,225.43 C213.49,225.43 213.38,225.37 213.38,225.37 C213.38,225.37 213.27,225.31 213.27,225.31 C213.27,225.31 213.17,225.24 213.17,225.24 C213.17,225.24 213.06,225.16 213.06,225.16 C213.06,225.16 212.96,225.09 212.96,225.09 C212.96,225.09 212.86,225.02 212.86,225.02 C212.86,225.02 212.76,224.95 212.76,224.95 C212.76,224.95 212.65,224.87 212.65,224.87 C212.65,224.87 212.56,224.79 212.56,224.79 C212.56,224.79 212.46,224.71 212.46,224.71 C212.46,224.71 212.37,224.63 212.37,224.63 C212.37,224.63 212.27,224.55 212.27,224.55 C212.27,224.55 212.18,224.47 212.18,224.47 C212.18,224.47 212.08,224.38 212.08,224.38 C212.08,224.38 211.99,224.3 211.99,224.3 C211.99,224.3 211.91,224.2 211.91,224.2 C211.91,224.2 211.82,224.11 211.82,224.11 C211.82,224.11 211.73,224.02 211.73,224.02 C211.73,224.02 211.64,223.93 211.64,223.93 C211.64,223.93 211.56,223.84 211.56,223.84 C211.56,223.84 211.48,223.75 211.48,223.75 C211.48,223.75 211.4,223.65 211.4,223.65 C211.4,223.65 211.32,223.55 211.32,223.55 C211.32,223.55 211.24,223.45 211.24,223.45 C211.24,223.45 211.16,223.35 211.16,223.35 C211.16,223.35 211.09,223.26 211.09,223.26 C211.09,223.26 211.02,223.15 211.02,223.15 C211.02,223.15 210.95,223.05 210.95,223.05 C210.95,223.05 210.88,222.94 210.88,222.94 C210.88,222.94 210.81,222.84 210.81,222.84 C210.81,222.84 210.74,222.73 210.74,222.73 C210.74,222.73 210.67,222.63 210.67,222.63 C210.67,222.63 210.61,222.52 210.61,222.52 C210.61,222.52 210.55,222.4 210.55,222.4 C210.55,222.4 210.49,222.29 210.49,222.29 C210.49,222.29 210.43,222.18 210.43,222.18 C210.43,222.18 210.38,222.07 210.38,222.07 C210.38,222.07 210.32,221.96 210.32,221.96 C210.32,221.96 210.27,221.84 210.27,221.84 C210.27,221.84 210.22,221.73 210.22,221.73 C210.22,221.73 210.17,221.61 210.17,221.61 C210.17,221.61 210.12,221.5 210.12,221.5 C210.12,221.5 210.08,221.38 210.08,221.38 C210.08,221.38 210.03,221.26 210.03,221.26 C210.03,221.26 209.99,221.14 209.99,221.14 C209.99,221.14 209.96,221.02 209.96,221.02 C209.96,221.02 209.92,220.9 209.92,220.9 C209.92,220.9 209.88,220.78 209.88,220.78 C209.88,220.78 209.84,220.67 209.84,220.67 C209.84,220.67 209.81,220.54 209.81,220.54 C209.81,220.54 209.78,220.42 209.78,220.42 C209.78,220.42 209.76,220.3 209.76,220.3 C209.76,220.3 209.73,220.18 209.73,220.18 C209.73,220.18 209.71,220.05 209.71,220.05 C209.71,220.05 209.68,219.93 209.68,219.93 C209.68,219.93 209.66,219.81 209.66,219.81 C209.66,219.81 209.64,219.68 209.64,219.68 C209.64,219.68 209.62,219.56 209.62,219.56 C209.62,219.56 209.61,219.43 209.61,219.43 C209.61,219.43 209.59,219.31 209.59,219.31 C209.59,219.31 209.59,219.18 209.59,219.18 C209.59,219.18 209.58,219.06 209.58,219.06 C209.58,219.06 209.58,218.93 209.58,218.93 C209.58,218.93 209.57,218.81 209.57,218.81 C209.57,218.81 209.56,218.68 209.56,218.68 C209.56,218.68 209.56,218.56 209.56,218.56 C209.56,218.56 209.56,218.43 209.56,218.43 C209.56,218.43 209.57,218.3 209.57,218.3 C209.57,218.3 209.58,218.18 209.58,218.18 C209.58,218.18 209.58,218.05 209.58,218.05 C209.58,218.05 209.59,217.93 209.59,217.93 C209.59,217.93 209.59,217.8 209.59,217.8 C209.59,217.8 209.61,217.68 209.61,217.68 C209.61,217.68 209.63,217.55 209.63,217.55 C209.63,217.55 209.65,217.43 209.65,217.43 C209.65,217.43 209.66,217.31 209.66,217.31 C209.66,217.31 209.68,217.18 209.68,217.18 C209.68,217.18 209.7,217.06 209.7,217.06 C209.7,217.06 209.73,216.93 209.73,216.93 C209.73,216.93 209.76,216.81 209.76,216.81 C209.76,216.81 209.79,216.69 209.79,216.69 C209.79,216.69 209.82,216.57 209.82,216.57 C209.82,216.57 209.85,216.45 209.85,216.45 C209.85,216.45 209.88,216.32 209.88,216.32 C209.88,216.32 209.91,216.2 209.91,216.2 C209.91,216.2 209.95,216.08 209.95,216.08 C209.95,216.08 210,215.97 210,215.97 C210,215.97 210.04,215.85 210.04,215.85 C210.04,215.85 210.08,215.73 210.08,215.73 C210.08,215.73 210.12,215.61 210.12,215.61 C210.12,215.61 210.17,215.49 210.17,215.49 C210.17,215.49 210.22,215.38 210.22,215.38 C210.22,215.38 210.27,215.27 210.27,215.27 C210.27,215.27 210.33,215.15 210.33,215.15 C210.33,215.15 210.38,215.04 210.38,215.04 C210.38,215.04 210.43,214.92 210.43,214.92 C210.43,214.92 210.49,214.81 210.49,214.81 C210.49,214.81 210.55,214.7 210.55,214.7 C210.55,214.7 210.61,214.6 210.61,214.6 C210.61,214.6 210.68,214.49 210.68,214.49 C210.68,214.49 210.74,214.38 210.74,214.38 C210.74,214.38 210.8,214.27 210.8,214.27 C210.8,214.27 210.87,214.17 210.87,214.17 C210.87,214.17 210.95,214.06 210.95,214.06 C210.95,214.06 211.02,213.96 211.02,213.96 C211.02,213.96 211.09,213.86 211.09,213.86 C211.09,213.86 211.16,213.76 211.16,213.76 C211.16,213.76 211.24,213.65 211.24,213.65 C211.24,213.65 211.32,213.56 211.32,213.56 C211.32,213.56 211.4,213.46 211.4,213.46 C211.4,213.46 211.48,213.37 211.48,213.37 C211.48,213.37 211.56,213.27 211.56,213.27 C211.56,213.27 211.64,213.18 211.64,213.18 C211.64,213.18 211.73,213.08 211.73,213.08 C211.73,213.08 211.82,212.99 211.82,212.99 C211.82,212.99 211.91,212.9 211.91,212.9 C211.91,212.9 212,212.82 212,212.82 C212,212.82 212.09,212.73 212.09,212.73 C212.09,212.73 212.18,212.64 212.18,212.64 C212.18,212.64 212.27,212.56 212.27,212.56 C212.27,212.56 212.36,212.48 212.36,212.48 C212.36,212.48 212.46,212.4 212.46,212.4 C212.46,212.4 212.56,212.32 212.56,212.32 C212.56,212.32 212.66,212.24 212.66,212.24 C212.66,212.24 212.76,212.16 212.76,212.16 C212.76,212.16 212.85,212.08 212.85,212.08 C212.85,212.08 212.96,212.02 212.96,212.02 C212.96,212.02 213.06,211.95 213.06,211.95 C213.06,211.95 213.17,211.88 213.17,211.88 C213.17,211.88 213.27,211.81 213.27,211.81 C213.27,211.81 213.38,211.74 213.38,211.74 C213.38,211.74 213.48,211.67 213.48,211.67 C213.48,211.67 213.6,211.61 213.6,211.61 C213.6,211.61 213.71,211.55 213.71,211.55 C213.71,211.55 213.82,211.49 213.82,211.49 C213.82,211.49 213.93,211.43 213.93,211.43 C213.93,211.43 214.04,211.37 214.04,211.37 C214.04,211.37 214.15,211.32 214.15,211.32 C214.15,211.32 214.27,211.27 214.27,211.27 C214.27,211.27 214.38,211.22 214.38,211.22 C214.38,211.22 214.5,211.17 214.5,211.17 C214.5,211.17 214.61,211.12 214.61,211.12 C214.61,211.12 214.73,211.07 214.73,211.07 C214.73,211.07 214.85,211.03 214.85,211.03 C214.85,211.03 214.97,210.99 214.97,210.99 C214.97,210.99 215.09,210.95 215.09,210.95 C215.09,210.95 215.21,210.92 215.21,210.92 C215.21,210.92 215.33,210.88 215.33,210.88 C215.33,210.88 215.45,210.84 215.45,210.84 C215.45,210.84 215.57,210.81 215.57,210.81 C215.57,210.81 215.69,210.78 215.69,210.78 C215.69,210.78 215.81,210.76 215.81,210.76 C215.81,210.76 215.93,210.73 215.93,210.73 C215.93,210.73 216.06,210.7 216.06,210.7 C216.06,210.7 216.18,210.68 216.18,210.68 C216.18,210.68 216.3,210.65 216.3,210.65 C216.3,210.65 216.43,210.64 216.43,210.64 C216.43,210.64 216.55,210.62 216.55,210.62 C216.55,210.62 216.68,210.61 216.68,210.61 C216.68,210.61 216.8,210.59 216.8,210.59 C216.8,210.59 216.93,210.59 216.93,210.59 C216.93,210.59 217.05,210.58 217.05,210.58 C217.05,210.58 217.18,210.58 217.18,210.58 C217.18,210.58 217.3,210.57 217.3,210.57 C217.3,210.57 217.43,210.56 217.43,210.56 C217.43,210.56 217.56,210.56 217.56,210.56 C217.56,210.56 217.68,210.56 217.68,210.56c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.8,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="500" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector> \ No newline at end of file
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="30dp" android:width="30dp" android:viewportHeight="30" android:viewportWidth="30"><group android:name="_R_G"><group android:name="_R_G_L_1_G" android:translateX="15.397" android:translateY="15.691" android:scaleY="0"><path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-0.56 -14.03 C3.65,-13.99 14.58,7.64 11.51,10.42 C8.45,13.2 5.92,9.56 -0.46,9.61 C-6.85,9.65 -9.27,12.76 -12.33,10.46 C-15.39,8.15 -4.77,-14.07 -0.56,-14.03c "/></group><group android:name="_R_G_L_0_G" android:translateX="15" android:translateY="13.205" android:pivotY="1.795" android:scaleX="0" android:scaleY="0"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M12.78 7.57 C12.78,7.57 4.72,-8.55 4.72,-8.55 C2.77,-12.44 -2.77,-12.44 -4.72,-8.55 C-4.72,-8.55 -12.78,7.57 -12.78,7.57 C-15,12.01 -10.42,16.78 -5.89,14.74 C-5.89,14.74 -2.17,13.07 -2.17,13.07 C-0.79,12.45 0.79,12.45 2.17,13.07 C2.17,13.07 5.9,14.74 5.9,14.74 C10.42,16.78 15,12.01 12.78,7.57c "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_1_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M-0.56 -14.03 C3.65,-13.99 14.58,7.64 11.51,10.42 C8.45,13.2 5.92,9.56 -0.46,9.61 C-6.85,9.65 -9.27,12.76 -12.33,10.46 C-15.39,8.15 -4.77,-14.07 -0.56,-14.03c " android:valueTo="M-0.56 -14.03 C3.65,-13.99 14.58,7.64 11.51,10.42 C8.45,13.2 5.92,9.56 -0.46,9.61 C-6.85,9.65 -9.27,12.76 -12.33,10.46 C-15.39,8.15 -4.77,-14.07 -0.56,-14.03c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.8,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="283" android:startOffset="67" android:valueFrom="M-0.56 -14.03 C3.65,-13.99 14.58,7.64 11.51,10.42 C8.45,13.2 5.92,9.56 -0.46,9.61 C-6.85,9.65 -9.27,12.76 -12.33,10.46 C-15.39,8.15 -4.77,-14.07 -0.56,-14.03c " android:valueTo="M-0.44 -8.69 C3.98,-8.69 7.56,-5.11 7.56,-0.69 C7.56,3.73 3.98,7.31 -0.44,7.31 C-4.86,7.31 -8.44,3.73 -8.44,-0.69 C-8.44,-5.11 -4.86,-8.69 -0.44,-8.69c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.8,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_1_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="67" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M12.78 7.57 C12.78,7.57 4.72,-8.55 4.72,-8.55 C2.77,-12.44 -2.77,-12.44 -4.72,-8.55 C-4.72,-8.55 -12.78,7.57 -12.78,7.57 C-15,12.01 -10.42,16.78 -5.89,14.74 C-5.89,14.74 -2.17,13.07 -2.17,13.07 C-0.79,12.45 0.79,12.45 2.17,13.07 C2.17,13.07 5.9,14.74 5.9,14.74 C10.42,16.78 15,12.01 12.78,7.57c " android:valueTo="M12.78 7.57 C12.78,7.57 4.72,-8.55 4.72,-8.55 C2.77,-12.44 -2.77,-12.44 -4.72,-8.55 C-4.72,-8.55 -12.78,7.57 -12.78,7.57 C-15,12.01 -10.42,16.78 -5.89,14.74 C-5.89,14.74 -2.17,13.07 -2.17,13.07 C-0.79,12.45 0.79,12.45 2.17,13.07 C2.17,13.07 5.9,14.74 5.9,14.74 C10.42,16.78 15,12.01 12.78,7.57c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.833,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="283" android:startOffset="67" android:valueFrom="M12.78 7.57 C12.78,7.57 4.72,-8.55 4.72,-8.55 C2.77,-12.44 -2.77,-12.44 -4.72,-8.55 C-4.72,-8.55 -12.78,7.57 -12.78,7.57 C-15,12.01 -10.42,16.78 -5.89,14.74 C-5.89,14.74 -2.17,13.07 -2.17,13.07 C-0.79,12.45 0.79,12.45 2.17,13.07 C2.17,13.07 5.9,14.74 5.9,14.74 C10.42,16.78 15,12.01 12.78,7.57c " android:valueTo="M6.12 0.21 C6.12,0.21 2.27,-4.35 2.27,-4.35 C1.34,-6.2 -1.3,-6.2 -2.23,-4.35 C-2.23,-4.35 -6.06,0.21 -6.06,0.21 C-7.12,2.33 -5.46,5.79 -4.03,6.54 C-2.28,7.45 -1.01,7.48 -1.01,7.48 C-1.01,7.48 1.05,7.48 1.05,7.48 C1.05,7.48 3.28,7.36 4.23,6.66 C4.92,6.15 7.18,2.33 6.12,0.21c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.833,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleX" android:duration="67" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="67" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target><target android:name="_R_G_L_0_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="367" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="500" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pin_dot_shape_3_avd.xml b/packages/SystemUI/res/drawable/pin_dot_shape_3_avd.xml
index cf0889997970..95b804431b4a 100644
--- a/packages/SystemUI/res/drawable/pin_dot_shape_3_avd.xml
+++ b/packages/SystemUI/res/drawable/pin_dot_shape_3_avd.xml
@@ -1 +1 @@
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="60dp" android:width="60dp" android:viewportHeight="60" android:viewportWidth="60"><group android:name="_R_G"><group android:name="_R_G_L_0_G" android:translateX="-187.543" android:translateY="-188.546"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="0" android:fillType="nonZero" android:pathData=" M217.62 214.55 C217.62,214.55 217.68,214.55 217.68,214.55 C217.68,214.55 217.74,214.56 217.74,214.56 C217.74,214.56 217.81,214.56 217.81,214.56 C217.81,214.56 217.87,214.56 217.87,214.56 C217.87,214.56 217.93,214.57 217.93,214.57 C217.93,214.57 218,214.57 218,214.57 C218,214.57 218.06,214.58 218.06,214.58 C218.06,214.58 218.12,214.59 218.12,214.59 C218.12,214.59 218.18,214.6 218.18,214.6 C218.18,214.6 218.24,214.61 218.24,214.61 C218.24,214.61 218.31,214.62 218.31,214.62 C218.31,214.62 218.37,214.63 218.37,214.63 C218.37,214.63 218.43,214.65 218.43,214.65 C218.43,214.65 218.49,214.66 218.49,214.66 C218.49,214.66 218.55,214.68 218.55,214.68 C218.55,214.68 218.61,214.69 218.61,214.69 C218.61,214.69 218.67,214.71 218.67,214.71 C218.67,214.71 218.73,214.73 218.73,214.73 C218.73,214.73 218.79,214.75 218.79,214.75 C218.79,214.75 218.85,214.77 218.85,214.77 C218.85,214.77 218.91,214.79 218.91,214.79 C218.91,214.79 218.97,214.81 218.97,214.81 C218.97,214.81 219.03,214.83 219.03,214.83 C219.03,214.83 219.09,214.85 219.09,214.85 C219.09,214.85 219.15,214.88 219.15,214.88 C219.15,214.88 219.2,214.9 219.2,214.9 C219.2,214.9 219.26,214.93 219.26,214.93 C219.26,214.93 219.32,214.96 219.32,214.96 C219.32,214.96 219.37,214.98 219.37,214.98 C219.37,214.98 219.43,215.01 219.43,215.01 C219.43,215.01 219.48,215.05 219.48,215.05 C219.48,215.05 219.54,215.08 219.54,215.08 C219.54,215.08 219.59,215.11 219.59,215.11 C219.59,215.11 219.65,215.14 219.65,215.14 C219.65,215.14 219.7,215.17 219.7,215.17 C219.7,215.17 219.75,215.21 219.75,215.21 C219.75,215.21 219.81,215.24 219.81,215.24 C219.81,215.24 219.86,215.28 219.86,215.28 C219.86,215.28 219.91,215.32 219.91,215.32 C219.91,215.32 219.96,215.35 219.96,215.35 C219.96,215.35 220.01,215.39 220.01,215.39 C220.01,215.39 220.06,215.43 220.06,215.43 C220.06,215.43 220.11,215.47 220.11,215.47 C220.11,215.47 220.16,215.51 220.16,215.51 C220.16,215.51 220.2,215.55 220.2,215.55 C220.2,215.55 220.25,215.59 220.25,215.59 C220.25,215.59 220.3,215.63 220.3,215.63 C220.3,215.63 220.34,215.68 220.34,215.68 C220.34,215.68 220.39,215.72 220.39,215.72 C220.39,215.72 220.43,215.77 220.43,215.77 C220.43,215.77 220.47,215.81 220.47,215.81 C220.47,215.81 220.52,215.86 220.52,215.86 C220.52,215.86 220.56,215.9 220.56,215.9 C220.56,215.9 220.6,215.95 220.6,215.95 C220.6,215.95 220.64,216 220.64,216 C220.64,216 220.68,216.05 220.68,216.05 C220.68,216.05 220.72,216.1 220.72,216.1 C220.72,216.1 220.76,216.15 220.76,216.15 C220.76,216.15 220.8,216.2 220.8,216.2 C220.8,216.2 220.83,216.25 220.83,216.25 C220.83,216.25 220.87,216.3 220.87,216.3 C220.87,216.3 220.9,216.36 220.9,216.36 C220.9,216.36 220.94,216.41 220.94,216.41 C220.94,216.41 220.97,216.46 220.97,216.46 C220.97,216.46 221,216.51 221,216.51 C221,216.51 221.03,216.57 221.03,216.57 C221.03,216.57 221.06,216.63 221.06,216.63 C221.06,216.63 221.09,216.68 221.09,216.68 C221.09,216.68 221.12,216.74 221.12,216.74 C221.12,216.74 221.15,216.79 221.15,216.79 C221.15,216.79 221.18,216.85 221.18,216.85 C221.18,216.85 221.21,216.91 221.21,216.91 C221.21,216.91 221.23,216.96 221.23,216.96 C221.23,216.96 221.25,217.02 221.25,217.02 C221.25,217.02 221.28,217.08 221.28,217.08 C221.28,217.08 221.3,217.14 221.3,217.14 C221.3,217.14 221.33,217.2 221.33,217.2 C221.33,217.2 221.34,217.26 221.34,217.26 C221.34,217.26 221.36,217.32 221.36,217.32 C221.36,217.32 221.38,217.38 221.38,217.38 C221.38,217.38 221.4,217.44 221.4,217.44 C221.4,217.44 221.42,217.5 221.42,217.5 C221.42,217.5 221.44,217.56 221.44,217.56 C221.44,217.56 221.45,217.62 221.45,217.62 C221.45,217.62 221.46,217.68 221.46,217.68 C221.46,217.68 221.48,217.74 221.48,217.74 C221.48,217.74 221.49,217.8 221.49,217.8 C221.49,217.8 221.5,217.87 221.5,217.87 C221.5,217.87 221.51,217.93 221.51,217.93 C221.51,217.93 221.52,217.99 221.52,217.99 C221.52,217.99 221.53,218.05 221.53,218.05 C221.53,218.05 221.54,218.11 221.54,218.11 C221.54,218.11 221.54,218.18 221.54,218.18 C221.54,218.18 221.55,218.24 221.55,218.24 C221.55,218.24 221.55,218.3 221.55,218.3 C221.55,218.3 221.55,218.37 221.55,218.37 C221.55,218.37 221.56,218.43 221.56,218.43 C221.56,218.43 221.56,218.49 221.56,218.49 C221.56,218.49 221.56,218.55 221.56,218.55 C221.56,218.55 221.56,218.62 221.56,218.62 C221.56,218.62 221.56,218.68 221.56,218.68 C221.56,218.68 221.55,218.74 221.55,218.74 C221.55,218.74 221.55,218.81 221.55,218.81 C221.55,218.81 221.55,218.87 221.55,218.87 C221.55,218.87 221.54,218.93 221.54,218.93 C221.54,218.93 221.54,218.99 221.54,218.99 C221.54,218.99 221.53,219.06 221.53,219.06 C221.53,219.06 221.52,219.12 221.52,219.12 C221.52,219.12 221.51,219.18 221.51,219.18 C221.51,219.18 221.5,219.24 221.5,219.24 C221.5,219.24 221.49,219.3 221.49,219.3 C221.49,219.3 221.48,219.37 221.48,219.37 C221.48,219.37 221.46,219.43 221.46,219.43 C221.46,219.43 221.45,219.49 221.45,219.49 C221.45,219.49 221.43,219.55 221.43,219.55 C221.43,219.55 221.42,219.61 221.42,219.61 C221.42,219.61 221.4,219.67 221.4,219.67 C221.4,219.67 221.39,219.73 221.39,219.73 C221.39,219.73 221.37,219.79 221.37,219.79 C221.37,219.79 221.34,219.85 221.34,219.85 C221.34,219.85 221.32,219.91 221.32,219.91 C221.32,219.91 221.3,219.97 221.3,219.97 C221.3,219.97 221.28,220.03 221.28,220.03 C221.28,220.03 221.26,220.09 221.26,220.09 C221.26,220.09 221.23,220.14 221.23,220.14 C221.23,220.14 221.21,220.2 221.21,220.2 C221.21,220.2 221.18,220.26 221.18,220.26 C221.18,220.26 221.15,220.32 221.15,220.32 C221.15,220.32 221.13,220.37 221.13,220.37 C221.13,220.37 221.1,220.43 221.1,220.43 C221.1,220.43 221.07,220.48 221.07,220.48 C221.07,220.48 221.03,220.54 221.03,220.54 C221.03,220.54 221,220.59 221,220.59 C221,220.59 220.97,220.65 220.97,220.65 C220.97,220.65 220.94,220.7 220.94,220.7 C220.94,220.7 220.9,220.75 220.9,220.75 C220.9,220.75 220.87,220.8 220.87,220.8 C220.87,220.8 220.83,220.86 220.83,220.86 C220.83,220.86 220.8,220.91 220.8,220.91 C220.8,220.91 220.76,220.96 220.76,220.96 C220.76,220.96 220.72,221.01 220.72,221.01 C220.72,221.01 220.68,221.06 220.68,221.06 C220.68,221.06 220.64,221.11 220.64,221.11 C220.64,221.11 220.6,221.15 220.6,221.15 C220.6,221.15 220.56,221.2 220.56,221.2 C220.56,221.2 220.52,221.25 220.52,221.25 C220.52,221.25 220.48,221.3 220.48,221.3 C220.48,221.3 220.43,221.34 220.43,221.34 C220.43,221.34 220.39,221.38 220.39,221.38 C220.39,221.38 220.34,221.43 220.34,221.43 C220.34,221.43 220.3,221.47 220.3,221.47 C220.3,221.47 220.25,221.52 220.25,221.52 C220.25,221.52 220.21,221.56 220.21,221.56 C220.21,221.56 220.16,221.6 220.16,221.6 C220.16,221.6 220.11,221.64 220.11,221.64 C220.11,221.64 220.06,221.68 220.06,221.68 C220.06,221.68 220.01,221.72 220.01,221.72 C220.01,221.72 219.96,221.76 219.96,221.76 C219.96,221.76 219.91,221.8 219.91,221.8 C219.91,221.8 219.86,221.83 219.86,221.83 C219.86,221.83 219.81,221.87 219.81,221.87 C219.81,221.87 219.75,221.9 219.75,221.9 C219.75,221.9 219.7,221.93 219.7,221.93 C219.7,221.93 219.65,221.97 219.65,221.97 C219.65,221.97 219.6,222 219.6,222 C219.6,222 219.54,222.03 219.54,222.03 C219.54,222.03 219.49,222.06 219.49,222.06 C219.49,222.06 219.43,222.09 219.43,222.09 C219.43,222.09 219.37,222.12 219.37,222.12 C219.37,222.12 219.32,222.15 219.32,222.15 C219.32,222.15 219.26,222.18 219.26,222.18 C219.26,222.18 219.21,222.2 219.21,222.2 C219.21,222.2 219.15,222.23 219.15,222.23 C219.15,222.23 219.09,222.25 219.09,222.25 C219.09,222.25 219.03,222.28 219.03,222.28 C219.03,222.28 218.97,222.3 218.97,222.3 C218.97,222.3 218.91,222.32 218.91,222.32 C218.91,222.32 218.85,222.34 218.85,222.34 C218.85,222.34 218.79,222.36 218.79,222.36 C218.79,222.36 218.73,222.38 218.73,222.38 C218.73,222.38 218.67,222.4 218.67,222.4 C218.67,222.4 218.61,222.42 218.61,222.42 C218.61,222.42 218.55,222.44 218.55,222.44 C218.55,222.44 218.49,222.45 218.49,222.45 C218.49,222.45 218.43,222.46 218.43,222.46 C218.43,222.46 218.37,222.47 218.37,222.47 C218.37,222.47 218.31,222.49 218.31,222.49 C218.31,222.49 218.25,222.5 218.25,222.5 C218.25,222.5 218.18,222.51 218.18,222.51 C218.18,222.51 218.12,222.52 218.12,222.52 C218.12,222.52 218.06,222.53 218.06,222.53 C218.06,222.53 218,222.54 218,222.54 C218,222.54 217.93,222.54 217.93,222.54 C217.93,222.54 217.87,222.55 217.87,222.55 C217.87,222.55 217.81,222.55 217.81,222.55 C217.81,222.55 217.75,222.55 217.75,222.55 C217.75,222.55 217.68,222.56 217.68,222.56 C217.68,222.56 217.62,222.56 217.62,222.56 C217.62,222.56 217.56,222.56 217.56,222.56 C217.56,222.56 217.49,222.56 217.49,222.56 C217.49,222.56 217.43,222.56 217.43,222.56 C217.43,222.56 217.37,222.55 217.37,222.55 C217.37,222.55 217.3,222.55 217.3,222.55 C217.3,222.55 217.24,222.55 217.24,222.55 C217.24,222.55 217.18,222.54 217.18,222.54 C217.18,222.54 217.12,222.54 217.12,222.54 C217.12,222.54 217.05,222.53 217.05,222.53 C217.05,222.53 216.99,222.52 216.99,222.52 C216.99,222.52 216.93,222.51 216.93,222.51 C216.93,222.51 216.87,222.5 216.87,222.5 C216.87,222.5 216.81,222.49 216.81,222.49 C216.81,222.49 216.74,222.48 216.74,222.48 C216.74,222.48 216.68,222.46 216.68,222.46 C216.68,222.46 216.62,222.45 216.62,222.45 C216.62,222.45 216.56,222.43 216.56,222.43 C216.56,222.43 216.5,222.42 216.5,222.42 C216.5,222.42 216.44,222.4 216.44,222.4 C216.44,222.4 216.38,222.38 216.38,222.38 C216.38,222.38 216.32,222.36 216.32,222.36 C216.32,222.36 216.26,222.34 216.26,222.34 C216.26,222.34 216.2,222.32 216.2,222.32 C216.2,222.32 216.14,222.3 216.14,222.3 C216.14,222.3 216.08,222.28 216.08,222.28 C216.08,222.28 216.02,222.26 216.02,222.26 C216.02,222.26 215.97,222.23 215.97,222.23 C215.97,222.23 215.91,222.2 215.91,222.2 C215.91,222.2 215.85,222.18 215.85,222.18 C215.85,222.18 215.79,222.15 215.79,222.15 C215.79,222.15 215.74,222.12 215.74,222.12 C215.74,222.12 215.68,222.1 215.68,222.1 C215.68,222.1 215.63,222.06 215.63,222.06 C215.63,222.06 215.57,222.03 215.57,222.03 C215.57,222.03 215.52,222 215.52,222 C215.52,222 215.46,221.97 215.46,221.97 C215.46,221.97 215.41,221.94 215.41,221.94 C215.41,221.94 215.36,221.9 215.36,221.9 C215.36,221.9 215.31,221.87 215.31,221.87 C215.31,221.87 215.25,221.83 215.25,221.83 C215.25,221.83 215.2,221.79 215.2,221.79 C215.2,221.79 215.15,221.76 215.15,221.76 C215.15,221.76 215.1,221.72 215.1,221.72 C215.1,221.72 215.05,221.68 215.05,221.68 C215.05,221.68 215,221.64 215,221.64 C215,221.64 214.96,221.6 214.96,221.6 C214.96,221.6 214.91,221.56 214.91,221.56 C214.91,221.56 214.86,221.52 214.86,221.52 C214.86,221.52 214.81,221.48 214.81,221.48 C214.81,221.48 214.77,221.43 214.77,221.43 C214.77,221.43 214.73,221.39 214.73,221.39 C214.73,221.39 214.68,221.34 214.68,221.34 C214.68,221.34 214.64,221.3 214.64,221.3 C214.64,221.3 214.59,221.25 214.59,221.25 C214.59,221.25 214.55,221.2 214.55,221.2 C214.55,221.2 214.51,221.15 214.51,221.15 C214.51,221.15 214.47,221.11 214.47,221.11 C214.47,221.11 214.43,221.06 214.43,221.06 C214.43,221.06 214.39,221.01 214.39,221.01 C214.39,221.01 214.35,220.96 214.35,220.96 C214.35,220.96 214.31,220.91 214.31,220.91 C214.31,220.91 214.28,220.86 214.28,220.86 C214.28,220.86 214.25,220.81 214.25,220.81 C214.25,220.81 214.21,220.75 214.21,220.75 C214.21,220.75 214.18,220.7 214.18,220.7 C214.18,220.7 214.14,220.65 214.14,220.65 C214.14,220.65 214.11,220.59 214.11,220.59 C214.11,220.59 214.08,220.54 214.08,220.54 C214.08,220.54 214.05,220.48 214.05,220.48 C214.05,220.48 214.02,220.43 214.02,220.43 C214.02,220.43 213.99,220.37 213.99,220.37 C213.99,220.37 213.96,220.32 213.96,220.32 C213.96,220.32 213.93,220.26 213.93,220.26 C213.93,220.26 213.91,220.2 213.91,220.2 C213.91,220.2 213.88,220.14 213.88,220.14 C213.88,220.14 213.86,220.09 213.86,220.09 C213.86,220.09 213.83,220.03 213.83,220.03 C213.83,220.03 213.81,219.97 213.81,219.97 C213.81,219.97 213.79,219.91 213.79,219.91 C213.79,219.91 213.77,219.85 213.77,219.85 C213.77,219.85 213.75,219.79 213.75,219.79 C213.75,219.79 213.73,219.73 213.73,219.73 C213.73,219.73 213.71,219.67 213.71,219.67 C213.71,219.67 213.69,219.61 213.69,219.61 C213.69,219.61 213.68,219.55 213.68,219.55 C213.68,219.55 213.66,219.49 213.66,219.49 C213.66,219.49 213.65,219.43 213.65,219.43 C213.65,219.43 213.64,219.37 213.64,219.37 C213.64,219.37 213.62,219.31 213.62,219.31 C213.62,219.31 213.61,219.24 213.61,219.24 C213.61,219.24 213.6,219.18 213.6,219.18 C213.6,219.18 213.59,219.12 213.59,219.12 C213.59,219.12 213.58,219.06 213.58,219.06 C213.58,219.06 213.57,218.99 213.57,218.99 C213.57,218.99 213.57,218.93 213.57,218.93 C213.57,218.93 213.56,218.87 213.56,218.87 C213.56,218.87 213.56,218.81 213.56,218.81 C213.56,218.81 213.56,218.74 213.56,218.74 C213.56,218.74 213.56,218.68 213.56,218.68 C213.56,218.68 213.55,218.62 213.55,218.62 C213.55,218.62 213.55,218.55 213.55,218.55 C213.55,218.55 213.55,218.49 213.55,218.49 C213.55,218.49 213.56,218.43 213.56,218.43 C213.56,218.43 213.56,218.37 213.56,218.37 C213.56,218.37 213.56,218.3 213.56,218.3 C213.56,218.3 213.56,218.24 213.56,218.24 C213.56,218.24 213.57,218.18 213.57,218.18 C213.57,218.18 213.57,218.12 213.57,218.12 C213.57,218.12 213.58,218.05 213.58,218.05 C213.58,218.05 213.59,217.99 213.59,217.99 C213.59,217.99 213.6,217.93 213.6,217.93 C213.6,217.93 213.61,217.87 213.61,217.87 C213.61,217.87 213.62,217.8 213.62,217.8 C213.62,217.8 213.63,217.74 213.63,217.74 C213.63,217.74 213.65,217.68 213.65,217.68 C213.65,217.68 213.66,217.62 213.66,217.62 C213.66,217.62 213.68,217.56 213.68,217.56 C213.68,217.56 213.69,217.5 213.69,217.5 C213.69,217.5 213.71,217.44 213.71,217.44 C213.71,217.44 213.73,217.38 213.73,217.38 C213.73,217.38 213.75,217.32 213.75,217.32 C213.75,217.32 213.77,217.26 213.77,217.26 C213.77,217.26 213.79,217.2 213.79,217.2 C213.79,217.2 213.81,217.14 213.81,217.14 C213.81,217.14 213.83,217.08 213.83,217.08 C213.83,217.08 213.85,217.02 213.85,217.02 C213.85,217.02 213.88,216.96 213.88,216.96 C213.88,216.96 213.91,216.91 213.91,216.91 C213.91,216.91 213.93,216.85 213.93,216.85 C213.93,216.85 213.96,216.79 213.96,216.79 C213.96,216.79 213.99,216.74 213.99,216.74 C213.99,216.74 214.02,216.68 214.02,216.68 C214.02,216.68 214.05,216.63 214.05,216.63 C214.05,216.63 214.08,216.57 214.08,216.57 C214.08,216.57 214.11,216.52 214.11,216.52 C214.11,216.52 214.14,216.46 214.14,216.46 C214.14,216.46 214.17,216.41 214.17,216.41 C214.17,216.41 214.21,216.36 214.21,216.36 C214.21,216.36 214.24,216.3 214.24,216.3 C214.24,216.3 214.28,216.25 214.28,216.25 C214.28,216.25 214.32,216.2 214.32,216.2 C214.32,216.2 214.35,216.15 214.35,216.15 C214.35,216.15 214.39,216.1 214.39,216.1 C214.39,216.1 214.43,216.05 214.43,216.05 C214.43,216.05 214.47,216 214.47,216 C214.47,216 214.51,215.96 214.51,215.96 C214.51,215.96 214.55,215.91 214.55,215.91 C214.55,215.91 214.59,215.86 214.59,215.86 C214.59,215.86 214.64,215.81 214.64,215.81 C214.64,215.81 214.68,215.77 214.68,215.77 C214.68,215.77 214.73,215.72 214.73,215.72 C214.73,215.72 214.77,215.68 214.77,215.68 C214.77,215.68 214.82,215.64 214.82,215.64 C214.82,215.64 214.86,215.59 214.86,215.59 C214.86,215.59 214.91,215.55 214.91,215.55 C214.91,215.55 214.96,215.51 214.96,215.51 C214.96,215.51 215,215.47 215,215.47 C215,215.47 215.05,215.43 215.05,215.43 C215.05,215.43 215.1,215.39 215.1,215.39 C215.1,215.39 215.15,215.35 215.15,215.35 C215.15,215.35 215.2,215.31 215.2,215.31 C215.2,215.31 215.25,215.28 215.25,215.28 C215.25,215.28 215.31,215.24 215.31,215.24 C215.31,215.24 215.36,215.21 215.36,215.21 C215.36,215.21 215.41,215.17 215.41,215.17 C215.41,215.17 215.46,215.14 215.46,215.14 C215.46,215.14 215.52,215.11 215.52,215.11 C215.52,215.11 215.57,215.08 215.57,215.08 C215.57,215.08 215.63,215.05 215.63,215.05 C215.63,215.05 215.68,215.02 215.68,215.02 C215.68,215.02 215.74,214.99 215.74,214.99 C215.74,214.99 215.79,214.96 215.79,214.96 C215.79,214.96 215.85,214.93 215.85,214.93 C215.85,214.93 215.91,214.9 215.91,214.9 C215.91,214.9 215.97,214.88 215.97,214.88 C215.97,214.88 216.02,214.86 216.02,214.86 C216.02,214.86 216.08,214.83 216.08,214.83 C216.08,214.83 216.14,214.81 216.14,214.81 C216.14,214.81 216.2,214.78 216.2,214.78 C216.2,214.78 216.26,214.77 216.26,214.77 C216.26,214.77 216.32,214.75 216.32,214.75 C216.32,214.75 216.38,214.73 216.38,214.73 C216.38,214.73 216.44,214.71 216.44,214.71 C216.44,214.71 216.5,214.69 216.5,214.69 C216.5,214.69 216.56,214.67 216.56,214.67 C216.56,214.67 216.62,214.66 216.62,214.66 C216.62,214.66 216.68,214.65 216.68,214.65 C216.68,214.65 216.74,214.63 216.74,214.63 C216.74,214.63 216.81,214.62 216.81,214.62 C216.81,214.62 216.87,214.61 216.87,214.61 C216.87,214.61 216.93,214.6 216.93,214.6 C216.93,214.6 216.99,214.59 216.99,214.59 C216.99,214.59 217.05,214.58 217.05,214.58 C217.05,214.58 217.12,214.57 217.12,214.57 C217.12,214.57 217.18,214.57 217.18,214.57 C217.18,214.57 217.24,214.56 217.24,214.56 C217.24,214.56 217.3,214.56 217.3,214.56 C217.3,214.56 217.37,214.56 217.37,214.56 C217.37,214.56 217.43,214.55 217.43,214.55 C217.43,214.55 217.49,214.55 217.49,214.55 C217.49,214.55 217.56,214.55 217.56,214.55 C217.56,214.55 217.62,214.55 217.62,214.55c "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="fillAlpha" android:duration="33" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M217.62 214.55 C217.62,214.55 217.68,214.55 217.68,214.55 C217.68,214.55 217.74,214.56 217.74,214.56 C217.74,214.56 217.81,214.56 217.81,214.56 C217.81,214.56 217.87,214.56 217.87,214.56 C217.87,214.56 217.93,214.57 217.93,214.57 C217.93,214.57 218,214.57 218,214.57 C218,214.57 218.06,214.58 218.06,214.58 C218.06,214.58 218.12,214.59 218.12,214.59 C218.12,214.59 218.18,214.6 218.18,214.6 C218.18,214.6 218.24,214.61 218.24,214.61 C218.24,214.61 218.31,214.62 218.31,214.62 C218.31,214.62 218.37,214.63 218.37,214.63 C218.37,214.63 218.43,214.65 218.43,214.65 C218.43,214.65 218.49,214.66 218.49,214.66 C218.49,214.66 218.55,214.68 218.55,214.68 C218.55,214.68 218.61,214.69 218.61,214.69 C218.61,214.69 218.67,214.71 218.67,214.71 C218.67,214.71 218.73,214.73 218.73,214.73 C218.73,214.73 218.79,214.75 218.79,214.75 C218.79,214.75 218.85,214.77 218.85,214.77 C218.85,214.77 218.91,214.79 218.91,214.79 C218.91,214.79 218.97,214.81 218.97,214.81 C218.97,214.81 219.03,214.83 219.03,214.83 C219.03,214.83 219.09,214.85 219.09,214.85 C219.09,214.85 219.15,214.88 219.15,214.88 C219.15,214.88 219.2,214.9 219.2,214.9 C219.2,214.9 219.26,214.93 219.26,214.93 C219.26,214.93 219.32,214.96 219.32,214.96 C219.32,214.96 219.37,214.98 219.37,214.98 C219.37,214.98 219.43,215.01 219.43,215.01 C219.43,215.01 219.48,215.05 219.48,215.05 C219.48,215.05 219.54,215.08 219.54,215.08 C219.54,215.08 219.59,215.11 219.59,215.11 C219.59,215.11 219.65,215.14 219.65,215.14 C219.65,215.14 219.7,215.17 219.7,215.17 C219.7,215.17 219.75,215.21 219.75,215.21 C219.75,215.21 219.81,215.24 219.81,215.24 C219.81,215.24 219.86,215.28 219.86,215.28 C219.86,215.28 219.91,215.32 219.91,215.32 C219.91,215.32 219.96,215.35 219.96,215.35 C219.96,215.35 220.01,215.39 220.01,215.39 C220.01,215.39 220.06,215.43 220.06,215.43 C220.06,215.43 220.11,215.47 220.11,215.47 C220.11,215.47 220.16,215.51 220.16,215.51 C220.16,215.51 220.2,215.55 220.2,215.55 C220.2,215.55 220.25,215.59 220.25,215.59 C220.25,215.59 220.3,215.63 220.3,215.63 C220.3,215.63 220.34,215.68 220.34,215.68 C220.34,215.68 220.39,215.72 220.39,215.72 C220.39,215.72 220.43,215.77 220.43,215.77 C220.43,215.77 220.47,215.81 220.47,215.81 C220.47,215.81 220.52,215.86 220.52,215.86 C220.52,215.86 220.56,215.9 220.56,215.9 C220.56,215.9 220.6,215.95 220.6,215.95 C220.6,215.95 220.64,216 220.64,216 C220.64,216 220.68,216.05 220.68,216.05 C220.68,216.05 220.72,216.1 220.72,216.1 C220.72,216.1 220.76,216.15 220.76,216.15 C220.76,216.15 220.8,216.2 220.8,216.2 C220.8,216.2 220.83,216.25 220.83,216.25 C220.83,216.25 220.87,216.3 220.87,216.3 C220.87,216.3 220.9,216.36 220.9,216.36 C220.9,216.36 220.94,216.41 220.94,216.41 C220.94,216.41 220.97,216.46 220.97,216.46 C220.97,216.46 221,216.51 221,216.51 C221,216.51 221.03,216.57 221.03,216.57 C221.03,216.57 221.06,216.63 221.06,216.63 C221.06,216.63 221.09,216.68 221.09,216.68 C221.09,216.68 221.12,216.74 221.12,216.74 C221.12,216.74 221.15,216.79 221.15,216.79 C221.15,216.79 221.18,216.85 221.18,216.85 C221.18,216.85 221.21,216.91 221.21,216.91 C221.21,216.91 221.23,216.96 221.23,216.96 C221.23,216.96 221.25,217.02 221.25,217.02 C221.25,217.02 221.28,217.08 221.28,217.08 C221.28,217.08 221.3,217.14 221.3,217.14 C221.3,217.14 221.33,217.2 221.33,217.2 C221.33,217.2 221.34,217.26 221.34,217.26 C221.34,217.26 221.36,217.32 221.36,217.32 C221.36,217.32 221.38,217.38 221.38,217.38 C221.38,217.38 221.4,217.44 221.4,217.44 C221.4,217.44 221.42,217.5 221.42,217.5 C221.42,217.5 221.44,217.56 221.44,217.56 C221.44,217.56 221.45,217.62 221.45,217.62 C221.45,217.62 221.46,217.68 221.46,217.68 C221.46,217.68 221.48,217.74 221.48,217.74 C221.48,217.74 221.49,217.8 221.49,217.8 C221.49,217.8 221.5,217.87 221.5,217.87 C221.5,217.87 221.51,217.93 221.51,217.93 C221.51,217.93 221.52,217.99 221.52,217.99 C221.52,217.99 221.53,218.05 221.53,218.05 C221.53,218.05 221.54,218.11 221.54,218.11 C221.54,218.11 221.54,218.18 221.54,218.18 C221.54,218.18 221.55,218.24 221.55,218.24 C221.55,218.24 221.55,218.3 221.55,218.3 C221.55,218.3 221.55,218.37 221.55,218.37 C221.55,218.37 221.56,218.43 221.56,218.43 C221.56,218.43 221.56,218.49 221.56,218.49 C221.56,218.49 221.56,218.55 221.56,218.55 C221.56,218.55 221.56,218.62 221.56,218.62 C221.56,218.62 221.56,218.68 221.56,218.68 C221.56,218.68 221.55,218.74 221.55,218.74 C221.55,218.74 221.55,218.81 221.55,218.81 C221.55,218.81 221.55,218.87 221.55,218.87 C221.55,218.87 221.54,218.93 221.54,218.93 C221.54,218.93 221.54,218.99 221.54,218.99 C221.54,218.99 221.53,219.06 221.53,219.06 C221.53,219.06 221.52,219.12 221.52,219.12 C221.52,219.12 221.51,219.18 221.51,219.18 C221.51,219.18 221.5,219.24 221.5,219.24 C221.5,219.24 221.49,219.3 221.49,219.3 C221.49,219.3 221.48,219.37 221.48,219.37 C221.48,219.37 221.46,219.43 221.46,219.43 C221.46,219.43 221.45,219.49 221.45,219.49 C221.45,219.49 221.43,219.55 221.43,219.55 C221.43,219.55 221.42,219.61 221.42,219.61 C221.42,219.61 221.4,219.67 221.4,219.67 C221.4,219.67 221.39,219.73 221.39,219.73 C221.39,219.73 221.37,219.79 221.37,219.79 C221.37,219.79 221.34,219.85 221.34,219.85 C221.34,219.85 221.32,219.91 221.32,219.91 C221.32,219.91 221.3,219.97 221.3,219.97 C221.3,219.97 221.28,220.03 221.28,220.03 C221.28,220.03 221.26,220.09 221.26,220.09 C221.26,220.09 221.23,220.14 221.23,220.14 C221.23,220.14 221.21,220.2 221.21,220.2 C221.21,220.2 221.18,220.26 221.18,220.26 C221.18,220.26 221.15,220.32 221.15,220.32 C221.15,220.32 221.13,220.37 221.13,220.37 C221.13,220.37 221.1,220.43 221.1,220.43 C221.1,220.43 221.07,220.48 221.07,220.48 C221.07,220.48 221.03,220.54 221.03,220.54 C221.03,220.54 221,220.59 221,220.59 C221,220.59 220.97,220.65 220.97,220.65 C220.97,220.65 220.94,220.7 220.94,220.7 C220.94,220.7 220.9,220.75 220.9,220.75 C220.9,220.75 220.87,220.8 220.87,220.8 C220.87,220.8 220.83,220.86 220.83,220.86 C220.83,220.86 220.8,220.91 220.8,220.91 C220.8,220.91 220.76,220.96 220.76,220.96 C220.76,220.96 220.72,221.01 220.72,221.01 C220.72,221.01 220.68,221.06 220.68,221.06 C220.68,221.06 220.64,221.11 220.64,221.11 C220.64,221.11 220.6,221.15 220.6,221.15 C220.6,221.15 220.56,221.2 220.56,221.2 C220.56,221.2 220.52,221.25 220.52,221.25 C220.52,221.25 220.48,221.3 220.48,221.3 C220.48,221.3 220.43,221.34 220.43,221.34 C220.43,221.34 220.39,221.38 220.39,221.38 C220.39,221.38 220.34,221.43 220.34,221.43 C220.34,221.43 220.3,221.47 220.3,221.47 C220.3,221.47 220.25,221.52 220.25,221.52 C220.25,221.52 220.21,221.56 220.21,221.56 C220.21,221.56 220.16,221.6 220.16,221.6 C220.16,221.6 220.11,221.64 220.11,221.64 C220.11,221.64 220.06,221.68 220.06,221.68 C220.06,221.68 220.01,221.72 220.01,221.72 C220.01,221.72 219.96,221.76 219.96,221.76 C219.96,221.76 219.91,221.8 219.91,221.8 C219.91,221.8 219.86,221.83 219.86,221.83 C219.86,221.83 219.81,221.87 219.81,221.87 C219.81,221.87 219.75,221.9 219.75,221.9 C219.75,221.9 219.7,221.93 219.7,221.93 C219.7,221.93 219.65,221.97 219.65,221.97 C219.65,221.97 219.6,222 219.6,222 C219.6,222 219.54,222.03 219.54,222.03 C219.54,222.03 219.49,222.06 219.49,222.06 C219.49,222.06 219.43,222.09 219.43,222.09 C219.43,222.09 219.37,222.12 219.37,222.12 C219.37,222.12 219.32,222.15 219.32,222.15 C219.32,222.15 219.26,222.18 219.26,222.18 C219.26,222.18 219.21,222.2 219.21,222.2 C219.21,222.2 219.15,222.23 219.15,222.23 C219.15,222.23 219.09,222.25 219.09,222.25 C219.09,222.25 219.03,222.28 219.03,222.28 C219.03,222.28 218.97,222.3 218.97,222.3 C218.97,222.3 218.91,222.32 218.91,222.32 C218.91,222.32 218.85,222.34 218.85,222.34 C218.85,222.34 218.79,222.36 218.79,222.36 C218.79,222.36 218.73,222.38 218.73,222.38 C218.73,222.38 218.67,222.4 218.67,222.4 C218.67,222.4 218.61,222.42 218.61,222.42 C218.61,222.42 218.55,222.44 218.55,222.44 C218.55,222.44 218.49,222.45 218.49,222.45 C218.49,222.45 218.43,222.46 218.43,222.46 C218.43,222.46 218.37,222.47 218.37,222.47 C218.37,222.47 218.31,222.49 218.31,222.49 C218.31,222.49 218.25,222.5 218.25,222.5 C218.25,222.5 218.18,222.51 218.18,222.51 C218.18,222.51 218.12,222.52 218.12,222.52 C218.12,222.52 218.06,222.53 218.06,222.53 C218.06,222.53 218,222.54 218,222.54 C218,222.54 217.93,222.54 217.93,222.54 C217.93,222.54 217.87,222.55 217.87,222.55 C217.87,222.55 217.81,222.55 217.81,222.55 C217.81,222.55 217.75,222.55 217.75,222.55 C217.75,222.55 217.68,222.56 217.68,222.56 C217.68,222.56 217.62,222.56 217.62,222.56 C217.62,222.56 217.56,222.56 217.56,222.56 C217.56,222.56 217.49,222.56 217.49,222.56 C217.49,222.56 217.43,222.56 217.43,222.56 C217.43,222.56 217.37,222.55 217.37,222.55 C217.37,222.55 217.3,222.55 217.3,222.55 C217.3,222.55 217.24,222.55 217.24,222.55 C217.24,222.55 217.18,222.54 217.18,222.54 C217.18,222.54 217.12,222.54 217.12,222.54 C217.12,222.54 217.05,222.53 217.05,222.53 C217.05,222.53 216.99,222.52 216.99,222.52 C216.99,222.52 216.93,222.51 216.93,222.51 C216.93,222.51 216.87,222.5 216.87,222.5 C216.87,222.5 216.81,222.49 216.81,222.49 C216.81,222.49 216.74,222.48 216.74,222.48 C216.74,222.48 216.68,222.46 216.68,222.46 C216.68,222.46 216.62,222.45 216.62,222.45 C216.62,222.45 216.56,222.43 216.56,222.43 C216.56,222.43 216.5,222.42 216.5,222.42 C216.5,222.42 216.44,222.4 216.44,222.4 C216.44,222.4 216.38,222.38 216.38,222.38 C216.38,222.38 216.32,222.36 216.32,222.36 C216.32,222.36 216.26,222.34 216.26,222.34 C216.26,222.34 216.2,222.32 216.2,222.32 C216.2,222.32 216.14,222.3 216.14,222.3 C216.14,222.3 216.08,222.28 216.08,222.28 C216.08,222.28 216.02,222.26 216.02,222.26 C216.02,222.26 215.97,222.23 215.97,222.23 C215.97,222.23 215.91,222.2 215.91,222.2 C215.91,222.2 215.85,222.18 215.85,222.18 C215.85,222.18 215.79,222.15 215.79,222.15 C215.79,222.15 215.74,222.12 215.74,222.12 C215.74,222.12 215.68,222.1 215.68,222.1 C215.68,222.1 215.63,222.06 215.63,222.06 C215.63,222.06 215.57,222.03 215.57,222.03 C215.57,222.03 215.52,222 215.52,222 C215.52,222 215.46,221.97 215.46,221.97 C215.46,221.97 215.41,221.94 215.41,221.94 C215.41,221.94 215.36,221.9 215.36,221.9 C215.36,221.9 215.31,221.87 215.31,221.87 C215.31,221.87 215.25,221.83 215.25,221.83 C215.25,221.83 215.2,221.79 215.2,221.79 C215.2,221.79 215.15,221.76 215.15,221.76 C215.15,221.76 215.1,221.72 215.1,221.72 C215.1,221.72 215.05,221.68 215.05,221.68 C215.05,221.68 215,221.64 215,221.64 C215,221.64 214.96,221.6 214.96,221.6 C214.96,221.6 214.91,221.56 214.91,221.56 C214.91,221.56 214.86,221.52 214.86,221.52 C214.86,221.52 214.81,221.48 214.81,221.48 C214.81,221.48 214.77,221.43 214.77,221.43 C214.77,221.43 214.73,221.39 214.73,221.39 C214.73,221.39 214.68,221.34 214.68,221.34 C214.68,221.34 214.64,221.3 214.64,221.3 C214.64,221.3 214.59,221.25 214.59,221.25 C214.59,221.25 214.55,221.2 214.55,221.2 C214.55,221.2 214.51,221.15 214.51,221.15 C214.51,221.15 214.47,221.11 214.47,221.11 C214.47,221.11 214.43,221.06 214.43,221.06 C214.43,221.06 214.39,221.01 214.39,221.01 C214.39,221.01 214.35,220.96 214.35,220.96 C214.35,220.96 214.31,220.91 214.31,220.91 C214.31,220.91 214.28,220.86 214.28,220.86 C214.28,220.86 214.25,220.81 214.25,220.81 C214.25,220.81 214.21,220.75 214.21,220.75 C214.21,220.75 214.18,220.7 214.18,220.7 C214.18,220.7 214.14,220.65 214.14,220.65 C214.14,220.65 214.11,220.59 214.11,220.59 C214.11,220.59 214.08,220.54 214.08,220.54 C214.08,220.54 214.05,220.48 214.05,220.48 C214.05,220.48 214.02,220.43 214.02,220.43 C214.02,220.43 213.99,220.37 213.99,220.37 C213.99,220.37 213.96,220.32 213.96,220.32 C213.96,220.32 213.93,220.26 213.93,220.26 C213.93,220.26 213.91,220.2 213.91,220.2 C213.91,220.2 213.88,220.14 213.88,220.14 C213.88,220.14 213.86,220.09 213.86,220.09 C213.86,220.09 213.83,220.03 213.83,220.03 C213.83,220.03 213.81,219.97 213.81,219.97 C213.81,219.97 213.79,219.91 213.79,219.91 C213.79,219.91 213.77,219.85 213.77,219.85 C213.77,219.85 213.75,219.79 213.75,219.79 C213.75,219.79 213.73,219.73 213.73,219.73 C213.73,219.73 213.71,219.67 213.71,219.67 C213.71,219.67 213.69,219.61 213.69,219.61 C213.69,219.61 213.68,219.55 213.68,219.55 C213.68,219.55 213.66,219.49 213.66,219.49 C213.66,219.49 213.65,219.43 213.65,219.43 C213.65,219.43 213.64,219.37 213.64,219.37 C213.64,219.37 213.62,219.31 213.62,219.31 C213.62,219.31 213.61,219.24 213.61,219.24 C213.61,219.24 213.6,219.18 213.6,219.18 C213.6,219.18 213.59,219.12 213.59,219.12 C213.59,219.12 213.58,219.06 213.58,219.06 C213.58,219.06 213.57,218.99 213.57,218.99 C213.57,218.99 213.57,218.93 213.57,218.93 C213.57,218.93 213.56,218.87 213.56,218.87 C213.56,218.87 213.56,218.81 213.56,218.81 C213.56,218.81 213.56,218.74 213.56,218.74 C213.56,218.74 213.56,218.68 213.56,218.68 C213.56,218.68 213.55,218.62 213.55,218.62 C213.55,218.62 213.55,218.55 213.55,218.55 C213.55,218.55 213.55,218.49 213.55,218.49 C213.55,218.49 213.56,218.43 213.56,218.43 C213.56,218.43 213.56,218.37 213.56,218.37 C213.56,218.37 213.56,218.3 213.56,218.3 C213.56,218.3 213.56,218.24 213.56,218.24 C213.56,218.24 213.57,218.18 213.57,218.18 C213.57,218.18 213.57,218.12 213.57,218.12 C213.57,218.12 213.58,218.05 213.58,218.05 C213.58,218.05 213.59,217.99 213.59,217.99 C213.59,217.99 213.6,217.93 213.6,217.93 C213.6,217.93 213.61,217.87 213.61,217.87 C213.61,217.87 213.62,217.8 213.62,217.8 C213.62,217.8 213.63,217.74 213.63,217.74 C213.63,217.74 213.65,217.68 213.65,217.68 C213.65,217.68 213.66,217.62 213.66,217.62 C213.66,217.62 213.68,217.56 213.68,217.56 C213.68,217.56 213.69,217.5 213.69,217.5 C213.69,217.5 213.71,217.44 213.71,217.44 C213.71,217.44 213.73,217.38 213.73,217.38 C213.73,217.38 213.75,217.32 213.75,217.32 C213.75,217.32 213.77,217.26 213.77,217.26 C213.77,217.26 213.79,217.2 213.79,217.2 C213.79,217.2 213.81,217.14 213.81,217.14 C213.81,217.14 213.83,217.08 213.83,217.08 C213.83,217.08 213.85,217.02 213.85,217.02 C213.85,217.02 213.88,216.96 213.88,216.96 C213.88,216.96 213.91,216.91 213.91,216.91 C213.91,216.91 213.93,216.85 213.93,216.85 C213.93,216.85 213.96,216.79 213.96,216.79 C213.96,216.79 213.99,216.74 213.99,216.74 C213.99,216.74 214.02,216.68 214.02,216.68 C214.02,216.68 214.05,216.63 214.05,216.63 C214.05,216.63 214.08,216.57 214.08,216.57 C214.08,216.57 214.11,216.52 214.11,216.52 C214.11,216.52 214.14,216.46 214.14,216.46 C214.14,216.46 214.17,216.41 214.17,216.41 C214.17,216.41 214.21,216.36 214.21,216.36 C214.21,216.36 214.24,216.3 214.24,216.3 C214.24,216.3 214.28,216.25 214.28,216.25 C214.28,216.25 214.32,216.2 214.32,216.2 C214.32,216.2 214.35,216.15 214.35,216.15 C214.35,216.15 214.39,216.1 214.39,216.1 C214.39,216.1 214.43,216.05 214.43,216.05 C214.43,216.05 214.47,216 214.47,216 C214.47,216 214.51,215.96 214.51,215.96 C214.51,215.96 214.55,215.91 214.55,215.91 C214.55,215.91 214.59,215.86 214.59,215.86 C214.59,215.86 214.64,215.81 214.64,215.81 C214.64,215.81 214.68,215.77 214.68,215.77 C214.68,215.77 214.73,215.72 214.73,215.72 C214.73,215.72 214.77,215.68 214.77,215.68 C214.77,215.68 214.82,215.64 214.82,215.64 C214.82,215.64 214.86,215.59 214.86,215.59 C214.86,215.59 214.91,215.55 214.91,215.55 C214.91,215.55 214.96,215.51 214.96,215.51 C214.96,215.51 215,215.47 215,215.47 C215,215.47 215.05,215.43 215.05,215.43 C215.05,215.43 215.1,215.39 215.1,215.39 C215.1,215.39 215.15,215.35 215.15,215.35 C215.15,215.35 215.2,215.31 215.2,215.31 C215.2,215.31 215.25,215.28 215.25,215.28 C215.25,215.28 215.31,215.24 215.31,215.24 C215.31,215.24 215.36,215.21 215.36,215.21 C215.36,215.21 215.41,215.17 215.41,215.17 C215.41,215.17 215.46,215.14 215.46,215.14 C215.46,215.14 215.52,215.11 215.52,215.11 C215.52,215.11 215.57,215.08 215.57,215.08 C215.57,215.08 215.63,215.05 215.63,215.05 C215.63,215.05 215.68,215.02 215.68,215.02 C215.68,215.02 215.74,214.99 215.74,214.99 C215.74,214.99 215.79,214.96 215.79,214.96 C215.79,214.96 215.85,214.93 215.85,214.93 C215.85,214.93 215.91,214.9 215.91,214.9 C215.91,214.9 215.97,214.88 215.97,214.88 C215.97,214.88 216.02,214.86 216.02,214.86 C216.02,214.86 216.08,214.83 216.08,214.83 C216.08,214.83 216.14,214.81 216.14,214.81 C216.14,214.81 216.2,214.78 216.2,214.78 C216.2,214.78 216.26,214.77 216.26,214.77 C216.26,214.77 216.32,214.75 216.32,214.75 C216.32,214.75 216.38,214.73 216.38,214.73 C216.38,214.73 216.44,214.71 216.44,214.71 C216.44,214.71 216.5,214.69 216.5,214.69 C216.5,214.69 216.56,214.67 216.56,214.67 C216.56,214.67 216.62,214.66 216.62,214.66 C216.62,214.66 216.68,214.65 216.68,214.65 C216.68,214.65 216.74,214.63 216.74,214.63 C216.74,214.63 216.81,214.62 216.81,214.62 C216.81,214.62 216.87,214.61 216.87,214.61 C216.87,214.61 216.93,214.6 216.93,214.6 C216.93,214.6 216.99,214.59 216.99,214.59 C216.99,214.59 217.05,214.58 217.05,214.58 C217.05,214.58 217.12,214.57 217.12,214.57 C217.12,214.57 217.18,214.57 217.18,214.57 C217.18,214.57 217.24,214.56 217.24,214.56 C217.24,214.56 217.3,214.56 217.3,214.56 C217.3,214.56 217.37,214.56 217.37,214.56 C217.37,214.56 217.43,214.55 217.43,214.55 C217.43,214.55 217.49,214.55 217.49,214.55 C217.49,214.55 217.56,214.55 217.56,214.55 C217.56,214.55 217.62,214.55 217.62,214.55c " android:valueTo="M217.57 201.76 C217.57,201.76 217.82,201.81 217.82,201.81 C217.82,201.81 218.08,201.86 218.08,201.86 C218.08,201.86 218.34,201.92 218.34,201.92 C218.34,201.92 218.6,201.97 218.6,201.97 C218.6,201.97 218.85,202.04 218.85,202.04 C218.85,202.04 219.11,202.12 219.11,202.12 C219.11,202.12 219.36,202.19 219.36,202.19 C219.36,202.19 219.61,202.27 219.61,202.27 C219.61,202.27 219.86,202.34 219.86,202.34 C219.86,202.34 220.11,202.44 220.11,202.44 C220.11,202.44 220.35,202.54 220.35,202.54 C220.35,202.54 220.6,202.64 220.6,202.64 C220.6,202.64 220.84,202.73 220.84,202.73 C220.84,202.73 221.09,202.83 221.09,202.83 C221.09,202.83 221.32,202.94 221.32,202.94 C221.32,202.94 221.56,203.07 221.56,203.07 C221.56,203.07 221.79,203.19 221.79,203.19 C221.79,203.19 222.03,203.31 222.03,203.31 C222.03,203.31 222.26,203.43 222.26,203.43 C222.26,203.43 222.49,203.56 222.49,203.56 C222.49,203.56 222.71,203.7 222.71,203.7 C222.71,203.7 222.93,203.85 222.93,203.85 C222.93,203.85 223.15,203.99 223.15,203.99 C223.15,203.99 223.37,204.13 223.37,204.13 C223.37,204.13 223.59,204.28 223.59,204.28 C223.59,204.28 223.8,204.44 223.8,204.44 C223.8,204.44 224.01,204.6 224.01,204.6 C224.01,204.6 224.22,204.76 224.22,204.76 C224.22,204.76 224.42,204.93 224.42,204.93 C224.42,204.93 224.62,205.1 224.62,205.1 C224.62,205.1 224.81,205.28 224.81,205.28 C224.81,205.28 225.01,205.46 225.01,205.46 C225.01,205.46 225.2,205.64 225.2,205.64 C225.2,205.64 225.4,205.81 225.4,205.81 C225.4,205.81 225.59,206 225.59,206 C225.59,206 225.77,206.19 225.77,206.19 C225.77,206.19 225.96,206.37 225.96,206.37 C225.96,206.37 226.15,206.56 226.15,206.56 C226.15,206.56 226.33,206.74 226.33,206.74 C226.33,206.74 226.52,206.93 226.52,206.93 C226.52,206.93 226.7,207.12 226.7,207.12 C226.7,207.12 226.89,207.3 226.89,207.3 C226.89,207.3 227.08,207.49 227.08,207.49 C227.08,207.49 227.26,207.68 227.26,207.68 C227.26,207.68 227.45,207.86 227.45,207.86 C227.45,207.86 227.64,208.05 227.64,208.05 C227.64,208.05 227.82,208.24 227.82,208.24 C227.82,208.24 228.01,208.42 228.01,208.42 C228.01,208.42 228.2,208.61 228.2,208.61 C228.2,208.61 228.38,208.79 228.38,208.79 C228.38,208.79 228.57,208.98 228.57,208.98 C228.57,208.98 228.75,209.17 228.75,209.17 C228.75,209.17 228.94,209.35 228.94,209.35 C228.94,209.35 229.13,209.54 229.13,209.54 C229.13,209.54 229.31,209.73 229.31,209.73 C229.31,209.73 229.5,209.91 229.5,209.91 C229.5,209.91 229.69,210.1 229.69,210.1 C229.69,210.1 229.87,210.29 229.87,210.29 C229.87,210.29 230.06,210.47 230.06,210.47 C230.06,210.47 230.25,210.66 230.25,210.66 C230.25,210.66 230.42,210.85 230.42,210.85 C230.42,210.85 230.6,211.05 230.6,211.05 C230.6,211.05 230.78,211.24 230.78,211.24 C230.78,211.24 230.95,211.44 230.95,211.44 C230.95,211.44 231.13,211.63 231.13,211.63 C231.13,211.63 231.3,211.84 231.3,211.84 C231.3,211.84 231.45,212.05 231.45,212.05 C231.45,212.05 231.61,212.26 231.61,212.26 C231.61,212.26 231.77,212.47 231.77,212.47 C231.77,212.47 231.93,212.68 231.93,212.68 C231.93,212.68 232.08,212.9 232.08,212.9 C232.08,212.9 232.22,213.12 232.22,213.12 C232.22,213.12 232.35,213.35 232.35,213.35 C232.35,213.35 232.49,213.57 232.49,213.57 C232.49,213.57 232.63,213.8 232.63,213.8 C232.63,213.8 232.76,214.02 232.76,214.02 C232.76,214.02 232.88,214.26 232.88,214.26 C232.88,214.26 232.99,214.5 232.99,214.5 C232.99,214.5 233.11,214.74 233.11,214.74 C233.11,214.74 233.22,214.97 233.22,214.97 C233.22,214.97 233.33,215.21 233.33,215.21 C233.33,215.21 233.43,215.46 233.43,215.46 C233.43,215.46 233.52,215.7 233.52,215.7 C233.52,215.7 233.62,215.95 233.62,215.95 C233.62,215.95 233.71,216.2 233.71,216.2 C233.71,216.2 233.8,216.45 233.8,216.45 C233.8,216.45 233.88,216.7 233.88,216.7 C233.88,216.7 233.94,216.95 233.94,216.95 C233.94,216.95 234.01,217.21 234.01,217.21 C234.01,217.21 234.08,217.46 234.08,217.46 C234.08,217.46 234.15,217.71 234.15,217.71 C234.15,217.71 234.21,217.97 234.21,217.97 C234.21,217.97 234.25,218.23 234.25,218.23 C234.25,218.23 234.3,218.49 234.3,218.49 C234.3,218.49 234.34,218.75 234.34,218.75 C234.34,218.75 234.38,219.01 234.38,219.01 C234.38,219.01 234.42,219.27 234.42,219.27 C234.42,219.27 234.44,219.53 234.44,219.53 C234.44,219.53 234.46,219.8 234.46,219.8 C234.46,219.8 234.48,220.06 234.48,220.06 C234.48,220.06 234.5,220.32 234.5,220.32 C234.5,220.32 234.52,220.58 234.52,220.58 C234.52,220.58 234.51,220.85 234.51,220.85 C234.51,220.85 234.51,221.11 234.51,221.11 C234.51,221.11 234.5,221.38 234.5,221.38 C234.5,221.38 234.5,221.64 234.5,221.64 C234.5,221.64 234.49,221.9 234.49,221.9 C234.49,221.9 234.47,222.17 234.47,222.17 C234.47,222.17 234.44,222.43 234.44,222.43 C234.44,222.43 234.41,222.69 234.41,222.69 C234.41,222.69 234.38,222.95 234.38,222.95 C234.38,222.95 234.35,223.21 234.35,223.21 C234.35,223.21 234.3,223.47 234.3,223.47 C234.3,223.47 234.25,223.73 234.25,223.73 C234.25,223.73 234.2,223.99 234.2,223.99 C234.2,223.99 234.15,224.25 234.15,224.25 C234.15,224.25 234.09,224.51 234.09,224.51 C234.09,224.51 234.02,224.76 234.02,224.76 C234.02,224.76 233.95,225.01 233.95,225.01 C233.95,225.01 233.87,225.26 233.87,225.26 C233.87,225.26 233.79,225.52 233.79,225.52 C233.79,225.52 233.72,225.77 233.72,225.77 C233.72,225.77 233.63,226.01 233.63,226.01 C233.63,226.01 233.53,226.26 233.53,226.26 C233.53,226.26 233.43,226.5 233.43,226.5 C233.43,226.5 233.33,226.75 233.33,226.75 C233.33,226.75 233.23,226.99 233.23,226.99 C233.23,226.99 233.12,227.23 233.12,227.23 C233.12,227.23 233,227.46 233,227.46 C233,227.46 232.88,227.7 232.88,227.7 C232.88,227.7 232.75,227.93 232.75,227.93 C232.75,227.93 232.63,228.17 232.63,228.17 C232.63,228.17 232.5,228.4 232.5,228.4 C232.5,228.4 232.36,228.62 232.36,228.62 C232.36,228.62 232.22,228.84 232.22,228.84 C232.22,228.84 232.07,229.06 232.07,229.06 C232.07,229.06 231.93,229.28 231.93,229.28 C231.93,229.28 231.79,229.5 231.79,229.5 C231.79,229.5 231.63,229.71 231.63,229.71 C231.63,229.71 231.46,229.92 231.46,229.92 C231.46,229.92 231.3,230.13 231.3,230.13 C231.3,230.13 231.14,230.33 231.14,230.33 C231.14,230.33 230.96,230.52 230.96,230.52 C230.96,230.52 230.78,230.72 230.78,230.72 C230.78,230.72 230.6,230.92 230.6,230.92 C230.6,230.92 230.43,231.11 230.43,231.11 C230.43,231.11 230.25,231.31 230.25,231.31 C230.25,231.31 230.05,231.49 230.05,231.49 C230.05,231.49 229.86,231.66 229.86,231.66 C229.86,231.66 229.66,231.84 229.66,231.84 C229.66,231.84 229.47,232.02 229.47,232.02 C229.47,232.02 229.27,232.19 229.27,232.19 C229.27,232.19 229.07,232.36 229.07,232.36 C229.07,232.36 228.86,232.52 228.86,232.52 C228.86,232.52 228.64,232.68 228.64,232.68 C228.64,232.68 228.43,232.83 228.43,232.83 C228.43,232.83 228.22,232.99 228.22,232.99 C228.22,232.99 228.01,233.14 228.01,233.14 C228.01,233.14 227.78,233.28 227.78,233.28 C227.78,233.28 227.56,233.42 227.56,233.42 C227.56,233.42 227.33,233.55 227.33,233.55 C227.33,233.55 227.11,233.69 227.11,233.69 C227.11,233.69 226.88,233.83 226.88,233.83 C226.88,233.83 226.64,233.94 226.64,233.94 C226.64,233.94 226.41,234.06 226.41,234.06 C226.41,234.06 226.17,234.17 226.17,234.17 C226.17,234.17 225.93,234.28 225.93,234.28 C225.93,234.28 225.69,234.4 225.69,234.4 C225.69,234.4 225.45,234.5 225.45,234.5 C225.45,234.5 225.2,234.59 225.2,234.59 C225.2,234.59 224.95,234.68 224.95,234.68 C224.95,234.68 224.71,234.77 224.71,234.77 C224.71,234.77 224.46,234.86 224.46,234.86 C224.46,234.86 224.21,234.94 224.21,234.94 C224.21,234.94 223.95,235.01 223.95,235.01 C223.95,235.01 223.7,235.08 223.7,235.08 C223.7,235.08 223.44,235.14 223.44,235.14 C223.44,235.14 223.19,235.21 223.19,235.21 C223.19,235.21 222.93,235.27 222.93,235.27 C222.93,235.27 222.67,235.31 222.67,235.31 C222.67,235.31 222.41,235.36 222.41,235.36 C222.41,235.36 222.15,235.4 222.15,235.4 C222.15,235.4 221.89,235.45 221.89,235.45 C221.89,235.45 221.63,235.48 221.63,235.48 C221.63,235.48 221.37,235.5 221.37,235.5 C221.37,235.5 221.11,235.52 221.11,235.52 C221.11,235.52 220.84,235.54 220.84,235.54 C220.84,235.54 220.58,235.56 220.58,235.56 C220.58,235.56 220.32,235.58 220.32,235.58 C220.32,235.58 220.06,235.57 220.06,235.57 C220.06,235.57 219.79,235.57 219.79,235.57 C219.79,235.57 219.53,235.57 219.53,235.57 C219.53,235.57 219.26,235.56 219.26,235.56 C219.26,235.56 219,235.56 219,235.56 C219,235.56 218.74,235.53 218.74,235.53 C218.74,235.53 218.48,235.5 218.48,235.5 C218.48,235.5 218.22,235.47 218.22,235.47 C218.22,235.47 217.95,235.44 217.95,235.44 C217.95,235.44 217.69,235.41 217.69,235.41 C217.69,235.41 217.43,235.36 217.43,235.36 C217.43,235.36 217.17,235.31 217.17,235.31 C217.17,235.31 216.92,235.26 216.92,235.26 C216.92,235.26 216.66,235.21 216.66,235.21 C216.66,235.21 216.4,235.15 216.4,235.15 C216.4,235.15 216.15,235.08 216.15,235.08 C216.15,235.08 215.89,235.01 215.89,235.01 C215.89,235.01 215.64,234.93 215.64,234.93 C215.64,234.93 215.39,234.85 215.39,234.85 C215.39,234.85 215.14,234.78 215.14,234.78 C215.14,234.78 214.89,234.69 214.89,234.69 C214.89,234.69 214.65,234.59 214.65,234.59 C214.65,234.59 214.4,234.49 214.4,234.49 C214.4,234.49 214.16,234.39 214.16,234.39 C214.16,234.39 213.91,234.29 213.91,234.29 C213.91,234.29 213.67,234.18 213.67,234.18 C213.67,234.18 213.44,234.06 213.44,234.06 C213.44,234.06 213.21,233.94 213.21,233.94 C213.21,233.94 212.97,233.81 212.97,233.81 C212.97,233.81 212.74,233.69 212.74,233.69 C212.74,233.69 212.51,233.56 212.51,233.56 C212.51,233.56 212.29,233.42 212.29,233.42 C212.29,233.42 212.07,233.28 212.07,233.28 C212.07,233.28 211.85,233.13 211.85,233.13 C211.85,233.13 211.63,232.99 211.63,232.99 C211.63,232.99 211.4,232.85 211.4,232.85 C211.4,232.85 211.2,232.69 211.2,232.69 C211.2,232.69 210.99,232.52 210.99,232.52 C210.99,232.52 210.78,232.36 210.78,232.36 C210.78,232.36 210.58,232.2 210.58,232.2 C210.58,232.2 210.38,232.02 210.38,232.02 C210.38,232.02 210.18,231.84 210.18,231.84 C210.18,231.84 209.99,231.66 209.99,231.66 C209.99,231.66 209.79,231.49 209.79,231.49 C209.79,231.49 209.6,231.31 209.6,231.31 C209.6,231.31 209.41,231.12 209.41,231.12 C209.41,231.12 209.23,230.94 209.23,230.94 C209.23,230.94 209.04,230.75 209.04,230.75 C209.04,230.75 208.85,230.56 208.85,230.56 C208.85,230.56 208.67,230.38 208.67,230.38 C208.67,230.38 208.48,230.19 208.48,230.19 C208.48,230.19 208.29,230.01 208.29,230.01 C208.29,230.01 208.11,229.82 208.11,229.82 C208.11,229.82 207.92,229.63 207.92,229.63 C207.92,229.63 207.74,229.45 207.74,229.45 C207.74,229.45 207.55,229.26 207.55,229.26 C207.55,229.26 207.36,229.07 207.36,229.07 C207.36,229.07 207.18,228.89 207.18,228.89 C207.18,228.89 206.99,228.7 206.99,228.7 C206.99,228.7 206.8,228.51 206.8,228.51 C206.8,228.51 206.62,228.33 206.62,228.33 C206.62,228.33 206.43,228.14 206.43,228.14 C206.43,228.14 206.24,227.96 206.24,227.96 C206.24,227.96 206.06,227.77 206.06,227.77 C206.06,227.77 205.87,227.58 205.87,227.58 C205.87,227.58 205.69,227.4 205.69,227.4 C205.69,227.4 205.5,227.21 205.5,227.21 C205.5,227.21 205.31,227.02 205.31,227.02 C205.31,227.02 205.13,226.84 205.13,226.84 C205.13,226.84 204.94,226.65 204.94,226.65 C204.94,226.65 204.75,226.46 204.75,226.46 C204.75,226.46 204.58,226.27 204.58,226.27 C204.58,226.27 204.4,226.07 204.4,226.07 C204.4,226.07 204.22,225.88 204.22,225.88 C204.22,225.88 204.05,225.68 204.05,225.68 C204.05,225.68 203.87,225.49 203.87,225.49 C203.87,225.49 203.7,225.28 203.7,225.28 C203.7,225.28 203.54,225.07 203.54,225.07 C203.54,225.07 203.39,224.86 203.39,224.86 C203.39,224.86 203.23,224.65 203.23,224.65 C203.23,224.65 203.07,224.44 203.07,224.44 C203.07,224.44 202.92,224.22 202.92,224.22 C202.92,224.22 202.78,224 202.78,224 C202.78,224 202.65,223.77 202.65,223.77 C202.65,223.77 202.51,223.55 202.51,223.55 C202.51,223.55 202.37,223.32 202.37,223.32 C202.37,223.32 202.24,223.1 202.24,223.1 C202.24,223.1 202.12,222.86 202.12,222.86 C202.12,222.86 202.01,222.62 202.01,222.62 C202.01,222.62 201.89,222.39 201.89,222.39 C201.89,222.39 201.78,222.15 201.78,222.15 C201.78,222.15 201.67,221.91 201.67,221.91 C201.67,221.91 201.57,221.67 201.57,221.67 C201.57,221.67 201.48,221.42 201.48,221.42 C201.48,221.42 201.38,221.17 201.38,221.17 C201.38,221.17 201.29,220.92 201.29,220.92 C201.29,220.92 201.2,220.68 201.2,220.68 C201.2,220.68 201.12,220.43 201.12,220.43 C201.12,220.43 201.06,220.17 201.06,220.17 C201.06,220.17 200.99,219.92 200.99,219.92 C200.99,219.92 200.92,219.66 200.92,219.66 C200.92,219.66 200.85,219.41 200.85,219.41 C200.85,219.41 200.79,219.15 200.79,219.15 C200.79,219.15 200.75,218.89 200.75,218.89 C200.75,218.89 200.71,218.63 200.71,218.63 C200.71,218.63 200.66,218.37 200.66,218.37 C200.66,218.37 200.62,218.11 200.62,218.11 C200.62,218.11 200.58,217.85 200.58,217.85 C200.58,217.85 200.56,217.59 200.56,217.59 C200.56,217.59 200.54,217.32 200.54,217.32 C200.54,217.32 200.52,217.06 200.52,217.06 C200.52,217.06 200.5,216.8 200.5,216.8 C200.5,216.8 200.48,216.54 200.48,216.54 C200.48,216.54 200.49,216.27 200.49,216.27 C200.49,216.27 200.49,216.01 200.49,216.01 C200.49,216.01 200.5,215.75 200.5,215.75 C200.5,215.75 200.5,215.48 200.5,215.48 C200.5,215.48 200.51,215.22 200.51,215.22 C200.51,215.22 200.53,214.96 200.53,214.96 C200.53,214.96 200.56,214.69 200.56,214.69 C200.56,214.69 200.59,214.43 200.59,214.43 C200.59,214.43 200.62,214.17 200.62,214.17 C200.62,214.17 200.65,213.91 200.65,213.91 C200.65,213.91 200.7,213.65 200.7,213.65 C200.7,213.65 200.75,213.39 200.75,213.39 C200.75,213.39 200.8,213.13 200.8,213.13 C200.8,213.13 200.86,212.88 200.86,212.88 C200.86,212.88 200.91,212.62 200.91,212.62 C200.91,212.62 200.98,212.36 200.98,212.36 C200.98,212.36 201.06,212.11 201.06,212.11 C201.06,212.11 201.13,211.86 201.13,211.86 C201.13,211.86 201.21,211.61 201.21,211.61 C201.21,211.61 201.28,211.35 201.28,211.35 C201.28,211.35 201.38,211.11 201.38,211.11 C201.38,211.11 201.47,210.86 201.47,210.86 C201.47,210.86 201.57,210.62 201.57,210.62 C201.57,210.62 201.67,210.37 201.67,210.37 C201.67,210.37 201.77,210.13 201.77,210.13 C201.77,210.13 201.88,209.89 201.88,209.89 C201.88,209.89 202,209.66 202,209.66 C202,209.66 202.13,209.42 202.13,209.42 C202.13,209.42 202.25,209.19 202.25,209.19 C202.25,209.19 202.37,208.96 202.37,208.96 C202.37,208.96 202.5,208.73 202.5,208.73 C202.5,208.73 202.64,208.51 202.64,208.51 C202.64,208.51 202.79,208.28 202.79,208.28 C202.79,208.28 202.93,208.06 202.93,208.06 C202.93,208.06 203.07,207.84 203.07,207.84 C203.07,207.84 203.22,207.62 203.22,207.62 C203.22,207.62 203.38,207.41 203.38,207.41 C203.38,207.41 203.54,207.2 203.54,207.2 C203.54,207.2 203.7,207 203.7,207 C203.7,207 203.87,206.79 203.87,206.79 C203.87,206.79 204.04,206.6 204.04,206.6 C204.04,206.6 204.22,206.4 204.22,206.4 C204.22,206.4 204.4,206.21 204.4,206.21 C204.4,206.21 204.57,206.01 204.57,206.01 C204.57,206.01 204.75,205.82 204.75,205.82 C204.75,205.82 204.95,205.64 204.95,205.64 C204.95,205.64 205.14,205.46 205.14,205.46 C205.14,205.46 205.34,205.29 205.34,205.29 C205.34,205.29 205.53,205.11 205.53,205.11 C205.53,205.11 205.73,204.93 205.73,204.93 C205.73,204.93 205.93,204.76 205.93,204.76 C205.93,204.76 206.14,204.61 206.14,204.61 C206.14,204.61 206.35,204.45 206.35,204.45 C206.35,204.45 206.57,204.29 206.57,204.29 C206.57,204.29 206.78,204.13 206.78,204.13 C206.78,204.13 206.99,203.98 206.99,203.98 C206.99,203.98 207.22,203.85 207.22,203.85 C207.22,203.85 207.44,203.71 207.44,203.71 C207.44,203.71 207.67,203.57 207.67,203.57 C207.67,203.57 207.89,203.44 207.89,203.44 C207.89,203.44 208.12,203.3 208.12,203.3 C208.12,203.3 208.36,203.18 208.36,203.18 C208.36,203.18 208.59,203.07 208.59,203.07 C208.59,203.07 208.83,202.96 208.83,202.96 C208.83,202.96 209.07,202.84 209.07,202.84 C209.07,202.84 209.31,202.73 209.31,202.73 C209.31,202.73 209.55,202.63 209.55,202.63 C209.55,202.63 209.8,202.54 209.8,202.54 C209.8,202.54 210.04,202.45 210.04,202.45 C210.04,202.45 210.29,202.36 210.29,202.36 C210.29,202.36 210.54,202.26 210.54,202.26 C210.54,202.26 210.79,202.19 210.79,202.19 C210.79,202.19 211.05,202.12 211.05,202.12 C211.05,202.12 211.3,202.05 211.3,202.05 C211.3,202.05 211.55,201.98 211.55,201.98 C211.55,201.98 211.81,201.91 211.81,201.91 C211.81,201.91 212.07,201.86 212.07,201.86 C212.07,201.86 212.33,201.81 212.33,201.81 C212.33,201.81 212.59,201.77 212.59,201.77 C212.59,201.77 212.85,201.72 212.85,201.72 C212.85,201.72 213.11,201.68 213.11,201.68 C213.11,201.68 213.37,201.64 213.37,201.64 C213.37,201.64 213.63,201.62 213.63,201.62 C213.63,201.62 213.89,201.6 213.89,201.6 C213.89,201.6 214.15,201.58 214.15,201.58 C214.15,201.58 214.42,201.56 214.42,201.56 C214.42,201.56 214.68,201.55 214.68,201.55 C214.68,201.55 214.94,201.55 214.94,201.55 C214.94,201.55 215.21,201.55 215.21,201.55 C215.21,201.55 215.47,201.56 215.47,201.56 C215.47,201.56 215.73,201.56 215.73,201.56 C215.73,201.56 216,201.57 216,201.57 C216,201.57 216.26,201.6 216.26,201.6 C216.26,201.6 216.52,201.62 216.52,201.62 C216.52,201.62 216.78,201.65 216.78,201.65 C216.78,201.65 217.05,201.68 217.05,201.68 C217.05,201.68 217.31,201.71 217.31,201.71 C217.31,201.71 217.57,201.76 217.57,201.76c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="283" android:startOffset="67" android:valueFrom="M217.57 201.76 C217.57,201.76 217.82,201.81 217.82,201.81 C217.82,201.81 218.08,201.86 218.08,201.86 C218.08,201.86 218.34,201.92 218.34,201.92 C218.34,201.92 218.6,201.97 218.6,201.97 C218.6,201.97 218.85,202.04 218.85,202.04 C218.85,202.04 219.11,202.12 219.11,202.12 C219.11,202.12 219.36,202.19 219.36,202.19 C219.36,202.19 219.61,202.27 219.61,202.27 C219.61,202.27 219.86,202.34 219.86,202.34 C219.86,202.34 220.11,202.44 220.11,202.44 C220.11,202.44 220.35,202.54 220.35,202.54 C220.35,202.54 220.6,202.64 220.6,202.64 C220.6,202.64 220.84,202.73 220.84,202.73 C220.84,202.73 221.09,202.83 221.09,202.83 C221.09,202.83 221.32,202.94 221.32,202.94 C221.32,202.94 221.56,203.07 221.56,203.07 C221.56,203.07 221.79,203.19 221.79,203.19 C221.79,203.19 222.03,203.31 222.03,203.31 C222.03,203.31 222.26,203.43 222.26,203.43 C222.26,203.43 222.49,203.56 222.49,203.56 C222.49,203.56 222.71,203.7 222.71,203.7 C222.71,203.7 222.93,203.85 222.93,203.85 C222.93,203.85 223.15,203.99 223.15,203.99 C223.15,203.99 223.37,204.13 223.37,204.13 C223.37,204.13 223.59,204.28 223.59,204.28 C223.59,204.28 223.8,204.44 223.8,204.44 C223.8,204.44 224.01,204.6 224.01,204.6 C224.01,204.6 224.22,204.76 224.22,204.76 C224.22,204.76 224.42,204.93 224.42,204.93 C224.42,204.93 224.62,205.1 224.62,205.1 C224.62,205.1 224.81,205.28 224.81,205.28 C224.81,205.28 225.01,205.46 225.01,205.46 C225.01,205.46 225.2,205.64 225.2,205.64 C225.2,205.64 225.4,205.81 225.4,205.81 C225.4,205.81 225.59,206 225.59,206 C225.59,206 225.77,206.19 225.77,206.19 C225.77,206.19 225.96,206.37 225.96,206.37 C225.96,206.37 226.15,206.56 226.15,206.56 C226.15,206.56 226.33,206.74 226.33,206.74 C226.33,206.74 226.52,206.93 226.52,206.93 C226.52,206.93 226.7,207.12 226.7,207.12 C226.7,207.12 226.89,207.3 226.89,207.3 C226.89,207.3 227.08,207.49 227.08,207.49 C227.08,207.49 227.26,207.68 227.26,207.68 C227.26,207.68 227.45,207.86 227.45,207.86 C227.45,207.86 227.64,208.05 227.64,208.05 C227.64,208.05 227.82,208.24 227.82,208.24 C227.82,208.24 228.01,208.42 228.01,208.42 C228.01,208.42 228.2,208.61 228.2,208.61 C228.2,208.61 228.38,208.79 228.38,208.79 C228.38,208.79 228.57,208.98 228.57,208.98 C228.57,208.98 228.75,209.17 228.75,209.17 C228.75,209.17 228.94,209.35 228.94,209.35 C228.94,209.35 229.13,209.54 229.13,209.54 C229.13,209.54 229.31,209.73 229.31,209.73 C229.31,209.73 229.5,209.91 229.5,209.91 C229.5,209.91 229.69,210.1 229.69,210.1 C229.69,210.1 229.87,210.29 229.87,210.29 C229.87,210.29 230.06,210.47 230.06,210.47 C230.06,210.47 230.25,210.66 230.25,210.66 C230.25,210.66 230.42,210.85 230.42,210.85 C230.42,210.85 230.6,211.05 230.6,211.05 C230.6,211.05 230.78,211.24 230.78,211.24 C230.78,211.24 230.95,211.44 230.95,211.44 C230.95,211.44 231.13,211.63 231.13,211.63 C231.13,211.63 231.3,211.84 231.3,211.84 C231.3,211.84 231.45,212.05 231.45,212.05 C231.45,212.05 231.61,212.26 231.61,212.26 C231.61,212.26 231.77,212.47 231.77,212.47 C231.77,212.47 231.93,212.68 231.93,212.68 C231.93,212.68 232.08,212.9 232.08,212.9 C232.08,212.9 232.22,213.12 232.22,213.12 C232.22,213.12 232.35,213.35 232.35,213.35 C232.35,213.35 232.49,213.57 232.49,213.57 C232.49,213.57 232.63,213.8 232.63,213.8 C232.63,213.8 232.76,214.02 232.76,214.02 C232.76,214.02 232.88,214.26 232.88,214.26 C232.88,214.26 232.99,214.5 232.99,214.5 C232.99,214.5 233.11,214.74 233.11,214.74 C233.11,214.74 233.22,214.97 233.22,214.97 C233.22,214.97 233.33,215.21 233.33,215.21 C233.33,215.21 233.43,215.46 233.43,215.46 C233.43,215.46 233.52,215.7 233.52,215.7 C233.52,215.7 233.62,215.95 233.62,215.95 C233.62,215.95 233.71,216.2 233.71,216.2 C233.71,216.2 233.8,216.45 233.8,216.45 C233.8,216.45 233.88,216.7 233.88,216.7 C233.88,216.7 233.94,216.95 233.94,216.95 C233.94,216.95 234.01,217.21 234.01,217.21 C234.01,217.21 234.08,217.46 234.08,217.46 C234.08,217.46 234.15,217.71 234.15,217.71 C234.15,217.71 234.21,217.97 234.21,217.97 C234.21,217.97 234.25,218.23 234.25,218.23 C234.25,218.23 234.3,218.49 234.3,218.49 C234.3,218.49 234.34,218.75 234.34,218.75 C234.34,218.75 234.38,219.01 234.38,219.01 C234.38,219.01 234.42,219.27 234.42,219.27 C234.42,219.27 234.44,219.53 234.44,219.53 C234.44,219.53 234.46,219.8 234.46,219.8 C234.46,219.8 234.48,220.06 234.48,220.06 C234.48,220.06 234.5,220.32 234.5,220.32 C234.5,220.32 234.52,220.58 234.52,220.58 C234.52,220.58 234.51,220.85 234.51,220.85 C234.51,220.85 234.51,221.11 234.51,221.11 C234.51,221.11 234.5,221.38 234.5,221.38 C234.5,221.38 234.5,221.64 234.5,221.64 C234.5,221.64 234.49,221.9 234.49,221.9 C234.49,221.9 234.47,222.17 234.47,222.17 C234.47,222.17 234.44,222.43 234.44,222.43 C234.44,222.43 234.41,222.69 234.41,222.69 C234.41,222.69 234.38,222.95 234.38,222.95 C234.38,222.95 234.35,223.21 234.35,223.21 C234.35,223.21 234.3,223.47 234.3,223.47 C234.3,223.47 234.25,223.73 234.25,223.73 C234.25,223.73 234.2,223.99 234.2,223.99 C234.2,223.99 234.15,224.25 234.15,224.25 C234.15,224.25 234.09,224.51 234.09,224.51 C234.09,224.51 234.02,224.76 234.02,224.76 C234.02,224.76 233.95,225.01 233.95,225.01 C233.95,225.01 233.87,225.26 233.87,225.26 C233.87,225.26 233.79,225.52 233.79,225.52 C233.79,225.52 233.72,225.77 233.72,225.77 C233.72,225.77 233.63,226.01 233.63,226.01 C233.63,226.01 233.53,226.26 233.53,226.26 C233.53,226.26 233.43,226.5 233.43,226.5 C233.43,226.5 233.33,226.75 233.33,226.75 C233.33,226.75 233.23,226.99 233.23,226.99 C233.23,226.99 233.12,227.23 233.12,227.23 C233.12,227.23 233,227.46 233,227.46 C233,227.46 232.88,227.7 232.88,227.7 C232.88,227.7 232.75,227.93 232.75,227.93 C232.75,227.93 232.63,228.17 232.63,228.17 C232.63,228.17 232.5,228.4 232.5,228.4 C232.5,228.4 232.36,228.62 232.36,228.62 C232.36,228.62 232.22,228.84 232.22,228.84 C232.22,228.84 232.07,229.06 232.07,229.06 C232.07,229.06 231.93,229.28 231.93,229.28 C231.93,229.28 231.79,229.5 231.79,229.5 C231.79,229.5 231.63,229.71 231.63,229.71 C231.63,229.71 231.46,229.92 231.46,229.92 C231.46,229.92 231.3,230.13 231.3,230.13 C231.3,230.13 231.14,230.33 231.14,230.33 C231.14,230.33 230.96,230.52 230.96,230.52 C230.96,230.52 230.78,230.72 230.78,230.72 C230.78,230.72 230.6,230.92 230.6,230.92 C230.6,230.92 230.43,231.11 230.43,231.11 C230.43,231.11 230.25,231.31 230.25,231.31 C230.25,231.31 230.05,231.49 230.05,231.49 C230.05,231.49 229.86,231.66 229.86,231.66 C229.86,231.66 229.66,231.84 229.66,231.84 C229.66,231.84 229.47,232.02 229.47,232.02 C229.47,232.02 229.27,232.19 229.27,232.19 C229.27,232.19 229.07,232.36 229.07,232.36 C229.07,232.36 228.86,232.52 228.86,232.52 C228.86,232.52 228.64,232.68 228.64,232.68 C228.64,232.68 228.43,232.83 228.43,232.83 C228.43,232.83 228.22,232.99 228.22,232.99 C228.22,232.99 228.01,233.14 228.01,233.14 C228.01,233.14 227.78,233.28 227.78,233.28 C227.78,233.28 227.56,233.42 227.56,233.42 C227.56,233.42 227.33,233.55 227.33,233.55 C227.33,233.55 227.11,233.69 227.11,233.69 C227.11,233.69 226.88,233.83 226.88,233.83 C226.88,233.83 226.64,233.94 226.64,233.94 C226.64,233.94 226.41,234.06 226.41,234.06 C226.41,234.06 226.17,234.17 226.17,234.17 C226.17,234.17 225.93,234.28 225.93,234.28 C225.93,234.28 225.69,234.4 225.69,234.4 C225.69,234.4 225.45,234.5 225.45,234.5 C225.45,234.5 225.2,234.59 225.2,234.59 C225.2,234.59 224.95,234.68 224.95,234.68 C224.95,234.68 224.71,234.77 224.71,234.77 C224.71,234.77 224.46,234.86 224.46,234.86 C224.46,234.86 224.21,234.94 224.21,234.94 C224.21,234.94 223.95,235.01 223.95,235.01 C223.95,235.01 223.7,235.08 223.7,235.08 C223.7,235.08 223.44,235.14 223.44,235.14 C223.44,235.14 223.19,235.21 223.19,235.21 C223.19,235.21 222.93,235.27 222.93,235.27 C222.93,235.27 222.67,235.31 222.67,235.31 C222.67,235.31 222.41,235.36 222.41,235.36 C222.41,235.36 222.15,235.4 222.15,235.4 C222.15,235.4 221.89,235.45 221.89,235.45 C221.89,235.45 221.63,235.48 221.63,235.48 C221.63,235.48 221.37,235.5 221.37,235.5 C221.37,235.5 221.11,235.52 221.11,235.52 C221.11,235.52 220.84,235.54 220.84,235.54 C220.84,235.54 220.58,235.56 220.58,235.56 C220.58,235.56 220.32,235.58 220.32,235.58 C220.32,235.58 220.06,235.57 220.06,235.57 C220.06,235.57 219.79,235.57 219.79,235.57 C219.79,235.57 219.53,235.57 219.53,235.57 C219.53,235.57 219.26,235.56 219.26,235.56 C219.26,235.56 219,235.56 219,235.56 C219,235.56 218.74,235.53 218.74,235.53 C218.74,235.53 218.48,235.5 218.48,235.5 C218.48,235.5 218.22,235.47 218.22,235.47 C218.22,235.47 217.95,235.44 217.95,235.44 C217.95,235.44 217.69,235.41 217.69,235.41 C217.69,235.41 217.43,235.36 217.43,235.36 C217.43,235.36 217.17,235.31 217.17,235.31 C217.17,235.31 216.92,235.26 216.92,235.26 C216.92,235.26 216.66,235.21 216.66,235.21 C216.66,235.21 216.4,235.15 216.4,235.15 C216.4,235.15 216.15,235.08 216.15,235.08 C216.15,235.08 215.89,235.01 215.89,235.01 C215.89,235.01 215.64,234.93 215.64,234.93 C215.64,234.93 215.39,234.85 215.39,234.85 C215.39,234.85 215.14,234.78 215.14,234.78 C215.14,234.78 214.89,234.69 214.89,234.69 C214.89,234.69 214.65,234.59 214.65,234.59 C214.65,234.59 214.4,234.49 214.4,234.49 C214.4,234.49 214.16,234.39 214.16,234.39 C214.16,234.39 213.91,234.29 213.91,234.29 C213.91,234.29 213.67,234.18 213.67,234.18 C213.67,234.18 213.44,234.06 213.44,234.06 C213.44,234.06 213.21,233.94 213.21,233.94 C213.21,233.94 212.97,233.81 212.97,233.81 C212.97,233.81 212.74,233.69 212.74,233.69 C212.74,233.69 212.51,233.56 212.51,233.56 C212.51,233.56 212.29,233.42 212.29,233.42 C212.29,233.42 212.07,233.28 212.07,233.28 C212.07,233.28 211.85,233.13 211.85,233.13 C211.85,233.13 211.63,232.99 211.63,232.99 C211.63,232.99 211.4,232.85 211.4,232.85 C211.4,232.85 211.2,232.69 211.2,232.69 C211.2,232.69 210.99,232.52 210.99,232.52 C210.99,232.52 210.78,232.36 210.78,232.36 C210.78,232.36 210.58,232.2 210.58,232.2 C210.58,232.2 210.38,232.02 210.38,232.02 C210.38,232.02 210.18,231.84 210.18,231.84 C210.18,231.84 209.99,231.66 209.99,231.66 C209.99,231.66 209.79,231.49 209.79,231.49 C209.79,231.49 209.6,231.31 209.6,231.31 C209.6,231.31 209.41,231.12 209.41,231.12 C209.41,231.12 209.23,230.94 209.23,230.94 C209.23,230.94 209.04,230.75 209.04,230.75 C209.04,230.75 208.85,230.56 208.85,230.56 C208.85,230.56 208.67,230.38 208.67,230.38 C208.67,230.38 208.48,230.19 208.48,230.19 C208.48,230.19 208.29,230.01 208.29,230.01 C208.29,230.01 208.11,229.82 208.11,229.82 C208.11,229.82 207.92,229.63 207.92,229.63 C207.92,229.63 207.74,229.45 207.74,229.45 C207.74,229.45 207.55,229.26 207.55,229.26 C207.55,229.26 207.36,229.07 207.36,229.07 C207.36,229.07 207.18,228.89 207.18,228.89 C207.18,228.89 206.99,228.7 206.99,228.7 C206.99,228.7 206.8,228.51 206.8,228.51 C206.8,228.51 206.62,228.33 206.62,228.33 C206.62,228.33 206.43,228.14 206.43,228.14 C206.43,228.14 206.24,227.96 206.24,227.96 C206.24,227.96 206.06,227.77 206.06,227.77 C206.06,227.77 205.87,227.58 205.87,227.58 C205.87,227.58 205.69,227.4 205.69,227.4 C205.69,227.4 205.5,227.21 205.5,227.21 C205.5,227.21 205.31,227.02 205.31,227.02 C205.31,227.02 205.13,226.84 205.13,226.84 C205.13,226.84 204.94,226.65 204.94,226.65 C204.94,226.65 204.75,226.46 204.75,226.46 C204.75,226.46 204.58,226.27 204.58,226.27 C204.58,226.27 204.4,226.07 204.4,226.07 C204.4,226.07 204.22,225.88 204.22,225.88 C204.22,225.88 204.05,225.68 204.05,225.68 C204.05,225.68 203.87,225.49 203.87,225.49 C203.87,225.49 203.7,225.28 203.7,225.28 C203.7,225.28 203.54,225.07 203.54,225.07 C203.54,225.07 203.39,224.86 203.39,224.86 C203.39,224.86 203.23,224.65 203.23,224.65 C203.23,224.65 203.07,224.44 203.07,224.44 C203.07,224.44 202.92,224.22 202.92,224.22 C202.92,224.22 202.78,224 202.78,224 C202.78,224 202.65,223.77 202.65,223.77 C202.65,223.77 202.51,223.55 202.51,223.55 C202.51,223.55 202.37,223.32 202.37,223.32 C202.37,223.32 202.24,223.1 202.24,223.1 C202.24,223.1 202.12,222.86 202.12,222.86 C202.12,222.86 202.01,222.62 202.01,222.62 C202.01,222.62 201.89,222.39 201.89,222.39 C201.89,222.39 201.78,222.15 201.78,222.15 C201.78,222.15 201.67,221.91 201.67,221.91 C201.67,221.91 201.57,221.67 201.57,221.67 C201.57,221.67 201.48,221.42 201.48,221.42 C201.48,221.42 201.38,221.17 201.38,221.17 C201.38,221.17 201.29,220.92 201.29,220.92 C201.29,220.92 201.2,220.68 201.2,220.68 C201.2,220.68 201.12,220.43 201.12,220.43 C201.12,220.43 201.06,220.17 201.06,220.17 C201.06,220.17 200.99,219.92 200.99,219.92 C200.99,219.92 200.92,219.66 200.92,219.66 C200.92,219.66 200.85,219.41 200.85,219.41 C200.85,219.41 200.79,219.15 200.79,219.15 C200.79,219.15 200.75,218.89 200.75,218.89 C200.75,218.89 200.71,218.63 200.71,218.63 C200.71,218.63 200.66,218.37 200.66,218.37 C200.66,218.37 200.62,218.11 200.62,218.11 C200.62,218.11 200.58,217.85 200.58,217.85 C200.58,217.85 200.56,217.59 200.56,217.59 C200.56,217.59 200.54,217.32 200.54,217.32 C200.54,217.32 200.52,217.06 200.52,217.06 C200.52,217.06 200.5,216.8 200.5,216.8 C200.5,216.8 200.48,216.54 200.48,216.54 C200.48,216.54 200.49,216.27 200.49,216.27 C200.49,216.27 200.49,216.01 200.49,216.01 C200.49,216.01 200.5,215.75 200.5,215.75 C200.5,215.75 200.5,215.48 200.5,215.48 C200.5,215.48 200.51,215.22 200.51,215.22 C200.51,215.22 200.53,214.96 200.53,214.96 C200.53,214.96 200.56,214.69 200.56,214.69 C200.56,214.69 200.59,214.43 200.59,214.43 C200.59,214.43 200.62,214.17 200.62,214.17 C200.62,214.17 200.65,213.91 200.65,213.91 C200.65,213.91 200.7,213.65 200.7,213.65 C200.7,213.65 200.75,213.39 200.75,213.39 C200.75,213.39 200.8,213.13 200.8,213.13 C200.8,213.13 200.86,212.88 200.86,212.88 C200.86,212.88 200.91,212.62 200.91,212.62 C200.91,212.62 200.98,212.36 200.98,212.36 C200.98,212.36 201.06,212.11 201.06,212.11 C201.06,212.11 201.13,211.86 201.13,211.86 C201.13,211.86 201.21,211.61 201.21,211.61 C201.21,211.61 201.28,211.35 201.28,211.35 C201.28,211.35 201.38,211.11 201.38,211.11 C201.38,211.11 201.47,210.86 201.47,210.86 C201.47,210.86 201.57,210.62 201.57,210.62 C201.57,210.62 201.67,210.37 201.67,210.37 C201.67,210.37 201.77,210.13 201.77,210.13 C201.77,210.13 201.88,209.89 201.88,209.89 C201.88,209.89 202,209.66 202,209.66 C202,209.66 202.13,209.42 202.13,209.42 C202.13,209.42 202.25,209.19 202.25,209.19 C202.25,209.19 202.37,208.96 202.37,208.96 C202.37,208.96 202.5,208.73 202.5,208.73 C202.5,208.73 202.64,208.51 202.64,208.51 C202.64,208.51 202.79,208.28 202.79,208.28 C202.79,208.28 202.93,208.06 202.93,208.06 C202.93,208.06 203.07,207.84 203.07,207.84 C203.07,207.84 203.22,207.62 203.22,207.62 C203.22,207.62 203.38,207.41 203.38,207.41 C203.38,207.41 203.54,207.2 203.54,207.2 C203.54,207.2 203.7,207 203.7,207 C203.7,207 203.87,206.79 203.87,206.79 C203.87,206.79 204.04,206.6 204.04,206.6 C204.04,206.6 204.22,206.4 204.22,206.4 C204.22,206.4 204.4,206.21 204.4,206.21 C204.4,206.21 204.57,206.01 204.57,206.01 C204.57,206.01 204.75,205.82 204.75,205.82 C204.75,205.82 204.95,205.64 204.95,205.64 C204.95,205.64 205.14,205.46 205.14,205.46 C205.14,205.46 205.34,205.29 205.34,205.29 C205.34,205.29 205.53,205.11 205.53,205.11 C205.53,205.11 205.73,204.93 205.73,204.93 C205.73,204.93 205.93,204.76 205.93,204.76 C205.93,204.76 206.14,204.61 206.14,204.61 C206.14,204.61 206.35,204.45 206.35,204.45 C206.35,204.45 206.57,204.29 206.57,204.29 C206.57,204.29 206.78,204.13 206.78,204.13 C206.78,204.13 206.99,203.98 206.99,203.98 C206.99,203.98 207.22,203.85 207.22,203.85 C207.22,203.85 207.44,203.71 207.44,203.71 C207.44,203.71 207.67,203.57 207.67,203.57 C207.67,203.57 207.89,203.44 207.89,203.44 C207.89,203.44 208.12,203.3 208.12,203.3 C208.12,203.3 208.36,203.18 208.36,203.18 C208.36,203.18 208.59,203.07 208.59,203.07 C208.59,203.07 208.83,202.96 208.83,202.96 C208.83,202.96 209.07,202.84 209.07,202.84 C209.07,202.84 209.31,202.73 209.31,202.73 C209.31,202.73 209.55,202.63 209.55,202.63 C209.55,202.63 209.8,202.54 209.8,202.54 C209.8,202.54 210.04,202.45 210.04,202.45 C210.04,202.45 210.29,202.36 210.29,202.36 C210.29,202.36 210.54,202.26 210.54,202.26 C210.54,202.26 210.79,202.19 210.79,202.19 C210.79,202.19 211.05,202.12 211.05,202.12 C211.05,202.12 211.3,202.05 211.3,202.05 C211.3,202.05 211.55,201.98 211.55,201.98 C211.55,201.98 211.81,201.91 211.81,201.91 C211.81,201.91 212.07,201.86 212.07,201.86 C212.07,201.86 212.33,201.81 212.33,201.81 C212.33,201.81 212.59,201.77 212.59,201.77 C212.59,201.77 212.85,201.72 212.85,201.72 C212.85,201.72 213.11,201.68 213.11,201.68 C213.11,201.68 213.37,201.64 213.37,201.64 C213.37,201.64 213.63,201.62 213.63,201.62 C213.63,201.62 213.89,201.6 213.89,201.6 C213.89,201.6 214.15,201.58 214.15,201.58 C214.15,201.58 214.42,201.56 214.42,201.56 C214.42,201.56 214.68,201.55 214.68,201.55 C214.68,201.55 214.94,201.55 214.94,201.55 C214.94,201.55 215.21,201.55 215.21,201.55 C215.21,201.55 215.47,201.56 215.47,201.56 C215.47,201.56 215.73,201.56 215.73,201.56 C215.73,201.56 216,201.57 216,201.57 C216,201.57 216.26,201.6 216.26,201.6 C216.26,201.6 216.52,201.62 216.52,201.62 C216.52,201.62 216.78,201.65 216.78,201.65 C216.78,201.65 217.05,201.68 217.05,201.68 C217.05,201.68 217.31,201.71 217.31,201.71 C217.31,201.71 217.57,201.76 217.57,201.76c " android:valueTo="M217.68 210.56 C217.68,210.56 217.81,210.57 217.81,210.57 C217.81,210.57 217.93,210.57 217.93,210.57 C217.93,210.57 218.06,210.58 218.06,210.58 C218.06,210.58 218.18,210.59 218.18,210.59 C218.18,210.59 218.31,210.59 218.31,210.59 C218.31,210.59 218.43,210.61 218.43,210.61 C218.43,210.61 218.56,210.63 218.56,210.63 C218.56,210.63 218.68,210.64 218.68,210.64 C218.68,210.64 218.81,210.66 218.81,210.66 C218.81,210.66 218.93,210.68 218.93,210.68 C218.93,210.68 219.05,210.7 219.05,210.7 C219.05,210.7 219.18,210.72 219.18,210.72 C219.18,210.72 219.3,210.75 219.3,210.75 C219.3,210.75 219.42,210.78 219.42,210.78 C219.42,210.78 219.54,210.81 219.54,210.81 C219.54,210.81 219.66,210.84 219.66,210.84 C219.66,210.84 219.79,210.87 219.79,210.87 C219.79,210.87 219.91,210.91 219.91,210.91 C219.91,210.91 220.03,210.95 220.03,210.95 C220.03,210.95 220.14,210.99 220.14,210.99 C220.14,210.99 220.26,211.04 220.26,211.04 C220.26,211.04 220.38,211.08 220.38,211.08 C220.38,211.08 220.5,211.12 220.5,211.12 C220.5,211.12 220.62,211.17 220.62,211.17 C220.62,211.17 220.73,211.22 220.73,211.22 C220.73,211.22 220.84,211.27 220.84,211.27 C220.84,211.27 220.96,211.32 220.96,211.32 C220.96,211.32 221.07,211.38 221.07,211.38 C221.07,211.38 221.19,211.43 221.19,211.43 C221.19,211.43 221.3,211.49 221.3,211.49 C221.3,211.49 221.41,211.55 221.41,211.55 C221.41,211.55 221.51,211.61 221.51,211.61 C221.51,211.61 221.62,211.68 221.62,211.68 C221.62,211.68 221.73,211.74 221.73,211.74 C221.73,211.74 221.84,211.8 221.84,211.8 C221.84,211.8 221.94,211.87 221.94,211.87 C221.94,211.87 222.05,211.94 222.05,211.94 C222.05,211.94 222.15,212.02 222.15,212.02 C222.15,212.02 222.25,212.09 222.25,212.09 C222.25,212.09 222.35,212.16 222.35,212.16 C222.35,212.16 222.46,212.23 222.46,212.23 C222.46,212.23 222.55,212.31 222.55,212.31 C222.55,212.31 222.65,212.4 222.65,212.4 C222.65,212.4 222.74,212.48 222.74,212.48 C222.74,212.48 222.84,212.56 222.84,212.56 C222.84,212.56 222.93,212.64 222.93,212.64 C222.93,212.64 223.03,212.72 223.03,212.72 C223.03,212.72 223.12,212.81 223.12,212.81 C223.12,212.81 223.21,212.9 223.21,212.9 C223.21,212.9 223.29,212.99 223.29,212.99 C223.29,212.99 223.38,213.08 223.38,213.08 C223.38,213.08 223.47,213.17 223.47,213.17 C223.47,213.17 223.55,213.26 223.55,213.26 C223.55,213.26 223.63,213.36 223.63,213.36 C223.63,213.36 223.71,213.46 223.71,213.46 C223.71,213.46 223.79,213.56 223.79,213.56 C223.79,213.56 223.87,213.66 223.87,213.66 C223.87,213.66 223.95,213.75 223.95,213.75 C223.95,213.75 224.03,213.85 224.03,213.85 C224.03,213.85 224.09,213.96 224.09,213.96 C224.09,213.96 224.16,214.06 224.16,214.06 C224.16,214.06 224.23,214.17 224.23,214.17 C224.23,214.17 224.3,214.27 224.3,214.27 C224.3,214.27 224.37,214.38 224.37,214.38 C224.37,214.38 224.44,214.48 224.44,214.48 C224.44,214.48 224.5,214.59 224.5,214.59 C224.5,214.59 224.56,214.7 224.56,214.7 C224.56,214.7 224.62,214.81 224.62,214.81 C224.62,214.81 224.68,214.93 224.68,214.93 C224.68,214.93 224.74,215.04 224.74,215.04 C224.74,215.04 224.79,215.15 224.79,215.15 C224.79,215.15 224.84,215.26 224.84,215.26 C224.84,215.26 224.89,215.38 224.89,215.38 C224.89,215.38 224.94,215.5 224.94,215.5 C224.94,215.5 224.99,215.61 224.99,215.61 C224.99,215.61 225.04,215.73 225.04,215.73 C225.04,215.73 225.08,215.84 225.08,215.84 C225.08,215.84 225.12,215.96 225.12,215.96 C225.12,215.96 225.16,216.08 225.16,216.08 C225.16,216.08 225.19,216.2 225.19,216.2 C225.19,216.2 225.23,216.32 225.23,216.32 C225.23,216.32 225.27,216.44 225.27,216.44 C225.27,216.44 225.3,216.56 225.3,216.56 C225.3,216.56 225.33,216.69 225.33,216.69 C225.33,216.69 225.35,216.81 225.35,216.81 C225.35,216.81 225.38,216.93 225.38,216.93 C225.38,216.93 225.41,217.06 225.41,217.06 C225.41,217.06 225.43,217.18 225.43,217.18 C225.43,217.18 225.46,217.3 225.46,217.3 C225.46,217.3 225.47,217.43 225.47,217.43 C225.47,217.43 225.49,217.55 225.49,217.55 C225.49,217.55 225.5,217.68 225.5,217.68 C225.5,217.68 225.52,217.8 225.52,217.8 C225.52,217.8 225.52,217.93 225.52,217.93 C225.52,217.93 225.53,218.05 225.53,218.05 C225.53,218.05 225.54,218.18 225.54,218.18 C225.54,218.18 225.54,218.3 225.54,218.3 C225.54,218.3 225.55,218.43 225.55,218.43 C225.55,218.43 225.55,218.55 225.55,218.55 C225.55,218.55 225.55,218.68 225.55,218.68 C225.55,218.68 225.54,218.8 225.54,218.8 C225.54,218.8 225.54,218.93 225.54,218.93 C225.54,218.93 225.53,219.05 225.53,219.05 C225.53,219.05 225.52,219.18 225.52,219.18 C225.52,219.18 225.52,219.31 225.52,219.31 C225.52,219.31 225.5,219.43 225.5,219.43 C225.5,219.43 225.48,219.55 225.48,219.55 C225.48,219.55 225.47,219.68 225.47,219.68 C225.47,219.68 225.45,219.8 225.45,219.8 C225.45,219.8 225.43,219.93 225.43,219.93 C225.43,219.93 225.41,220.05 225.41,220.05 C225.41,220.05 225.39,220.17 225.39,220.17 C225.39,220.17 225.36,220.3 225.36,220.3 C225.36,220.3 225.33,220.42 225.33,220.42 C225.33,220.42 225.3,220.54 225.3,220.54 C225.3,220.54 225.27,220.66 225.27,220.66 C225.27,220.66 225.24,220.78 225.24,220.78 C225.24,220.78 225.2,220.9 225.2,220.9 C225.2,220.9 225.16,221.02 225.16,221.02 C225.16,221.02 225.12,221.14 225.12,221.14 C225.12,221.14 225.08,221.26 225.08,221.26 C225.08,221.26 225.03,221.38 225.03,221.38 C225.03,221.38 224.99,221.5 224.99,221.5 C224.99,221.5 224.95,221.61 224.95,221.61 C224.95,221.61 224.89,221.73 224.89,221.73 C224.89,221.73 224.84,221.84 224.84,221.84 C224.84,221.84 224.79,221.96 224.79,221.96 C224.79,221.96 224.73,222.07 224.73,222.07 C224.73,222.07 224.68,222.18 224.68,222.18 C224.68,222.18 224.62,222.29 224.62,222.29 C224.62,222.29 224.56,222.4 224.56,222.4 C224.56,222.4 224.5,222.51 224.5,222.51 C224.5,222.51 224.44,222.62 224.44,222.62 C224.44,222.62 224.37,222.73 224.37,222.73 C224.37,222.73 224.31,222.84 224.31,222.84 C224.31,222.84 224.24,222.94 224.24,222.94 C224.24,222.94 224.17,223.05 224.17,223.05 C224.17,223.05 224.09,223.15 224.09,223.15 C224.09,223.15 224.02,223.25 224.02,223.25 C224.02,223.25 223.95,223.35 223.95,223.35 C223.95,223.35 223.88,223.45 223.88,223.45 C223.88,223.45 223.8,223.55 223.8,223.55 C223.8,223.55 223.71,223.65 223.71,223.65 C223.71,223.65 223.63,223.74 223.63,223.74 C223.63,223.74 223.55,223.84 223.55,223.84 C223.55,223.84 223.47,223.93 223.47,223.93 C223.47,223.93 223.39,224.03 223.39,224.03 C223.39,224.03 223.3,224.12 223.3,224.12 C223.3,224.12 223.21,224.2 223.21,224.2 C223.21,224.2 223.12,224.29 223.12,224.29 C223.12,224.29 223.03,224.38 223.03,224.38 C223.03,224.38 222.94,224.46 222.94,224.46 C222.94,224.46 222.85,224.55 222.85,224.55 C222.85,224.55 222.75,224.63 222.75,224.63 C222.75,224.63 222.65,224.71 222.65,224.71 C222.65,224.71 222.55,224.79 222.55,224.79 C222.55,224.79 222.46,224.87 222.46,224.87 C222.46,224.87 222.36,224.95 222.36,224.95 C222.36,224.95 222.26,225.02 222.26,225.02 C222.26,225.02 222.15,225.09 222.15,225.09 C222.15,225.09 222.05,225.16 222.05,225.16 C222.05,225.16 221.94,225.23 221.94,225.23 C221.94,225.23 221.84,225.3 221.84,225.3 C221.84,225.3 221.74,225.37 221.74,225.37 C221.74,225.37 221.63,225.44 221.63,225.44 C221.63,225.44 221.52,225.5 221.52,225.5 C221.52,225.5 221.41,225.56 221.41,225.56 C221.41,225.56 221.3,225.62 221.3,225.62 C221.3,225.62 221.19,225.68 221.19,225.68 C221.19,225.68 221.08,225.73 221.08,225.73 C221.08,225.73 220.96,225.79 220.96,225.79 C220.96,225.79 220.85,225.84 220.85,225.84 C220.85,225.84 220.73,225.89 220.73,225.89 C220.73,225.89 220.62,225.94 220.62,225.94 C220.62,225.94 220.5,225.99 220.5,225.99 C220.5,225.99 220.38,226.03 220.38,226.03 C220.38,226.03 220.27,226.08 220.27,226.08 C220.27,226.08 220.15,226.12 220.15,226.12 C220.15,226.12 220.03,226.15 220.03,226.15 C220.03,226.15 219.91,226.19 219.91,226.19 C219.91,226.19 219.79,226.23 219.79,226.23 C219.79,226.23 219.67,226.27 219.67,226.27 C219.67,226.27 219.55,226.3 219.55,226.3 C219.55,226.3 219.42,226.33 219.42,226.33 C219.42,226.33 219.3,226.35 219.3,226.35 C219.3,226.35 219.18,226.38 219.18,226.38 C219.18,226.38 219.06,226.4 219.06,226.4 C219.06,226.4 218.93,226.43 218.93,226.43 C218.93,226.43 218.81,226.45 218.81,226.45 C218.81,226.45 218.68,226.47 218.68,226.47 C218.68,226.47 218.56,226.49 218.56,226.49 C218.56,226.49 218.44,226.5 218.44,226.5 C218.44,226.5 218.31,226.52 218.31,226.52 C218.31,226.52 218.19,226.52 218.19,226.52 C218.19,226.52 218.06,226.53 218.06,226.53 C218.06,226.53 217.93,226.53 217.93,226.53 C217.93,226.53 217.81,226.54 217.81,226.54 C217.81,226.54 217.68,226.55 217.68,226.55 C217.68,226.55 217.56,226.55 217.56,226.55 C217.56,226.55 217.43,226.55 217.43,226.55 C217.43,226.55 217.31,226.54 217.31,226.54 C217.31,226.54 217.18,226.53 217.18,226.53 C217.18,226.53 217.05,226.53 217.05,226.53 C217.05,226.53 216.93,226.52 216.93,226.52 C216.93,226.52 216.8,226.52 216.8,226.52 C216.8,226.52 216.68,226.5 216.68,226.5 C216.68,226.5 216.55,226.48 216.55,226.48 C216.55,226.48 216.43,226.46 216.43,226.46 C216.43,226.46 216.31,226.45 216.31,226.45 C216.31,226.45 216.18,226.43 216.18,226.43 C216.18,226.43 216.06,226.41 216.06,226.41 C216.06,226.41 215.93,226.38 215.93,226.38 C215.93,226.38 215.81,226.35 215.81,226.35 C215.81,226.35 215.69,226.32 215.69,226.32 C215.69,226.32 215.57,226.29 215.57,226.29 C215.57,226.29 215.45,226.26 215.45,226.26 C215.45,226.26 215.32,226.23 215.32,226.23 C215.32,226.23 215.2,226.2 215.2,226.2 C215.2,226.2 215.09,226.16 215.09,226.16 C215.09,226.16 214.97,226.12 214.97,226.12 C214.97,226.12 214.85,226.07 214.85,226.07 C214.85,226.07 214.73,226.03 214.73,226.03 C214.73,226.03 214.61,225.99 214.61,225.99 C214.61,225.99 214.5,225.94 214.5,225.94 C214.5,225.94 214.38,225.89 214.38,225.89 C214.38,225.89 214.27,225.84 214.27,225.84 C214.27,225.84 214.15,225.79 214.15,225.79 C214.15,225.79 214.04,225.73 214.04,225.73 C214.04,225.73 213.93,225.68 213.93,225.68 C213.93,225.68 213.81,225.62 213.81,225.62 C213.81,225.62 213.71,225.56 213.71,225.56 C213.71,225.56 213.6,225.5 213.6,225.5 C213.6,225.5 213.49,225.43 213.49,225.43 C213.49,225.43 213.38,225.37 213.38,225.37 C213.38,225.37 213.27,225.31 213.27,225.31 C213.27,225.31 213.17,225.24 213.17,225.24 C213.17,225.24 213.06,225.16 213.06,225.16 C213.06,225.16 212.96,225.09 212.96,225.09 C212.96,225.09 212.86,225.02 212.86,225.02 C212.86,225.02 212.76,224.95 212.76,224.95 C212.76,224.95 212.65,224.87 212.65,224.87 C212.65,224.87 212.56,224.79 212.56,224.79 C212.56,224.79 212.46,224.71 212.46,224.71 C212.46,224.71 212.37,224.63 212.37,224.63 C212.37,224.63 212.27,224.55 212.27,224.55 C212.27,224.55 212.18,224.47 212.18,224.47 C212.18,224.47 212.08,224.38 212.08,224.38 C212.08,224.38 211.99,224.3 211.99,224.3 C211.99,224.3 211.91,224.2 211.91,224.2 C211.91,224.2 211.82,224.11 211.82,224.11 C211.82,224.11 211.73,224.02 211.73,224.02 C211.73,224.02 211.64,223.93 211.64,223.93 C211.64,223.93 211.56,223.84 211.56,223.84 C211.56,223.84 211.48,223.75 211.48,223.75 C211.48,223.75 211.4,223.65 211.4,223.65 C211.4,223.65 211.32,223.55 211.32,223.55 C211.32,223.55 211.24,223.45 211.24,223.45 C211.24,223.45 211.16,223.35 211.16,223.35 C211.16,223.35 211.09,223.26 211.09,223.26 C211.09,223.26 211.02,223.15 211.02,223.15 C211.02,223.15 210.95,223.05 210.95,223.05 C210.95,223.05 210.88,222.94 210.88,222.94 C210.88,222.94 210.81,222.84 210.81,222.84 C210.81,222.84 210.74,222.73 210.74,222.73 C210.74,222.73 210.67,222.63 210.67,222.63 C210.67,222.63 210.61,222.52 210.61,222.52 C210.61,222.52 210.55,222.4 210.55,222.4 C210.55,222.4 210.49,222.29 210.49,222.29 C210.49,222.29 210.43,222.18 210.43,222.18 C210.43,222.18 210.38,222.07 210.38,222.07 C210.38,222.07 210.32,221.96 210.32,221.96 C210.32,221.96 210.27,221.84 210.27,221.84 C210.27,221.84 210.22,221.73 210.22,221.73 C210.22,221.73 210.17,221.61 210.17,221.61 C210.17,221.61 210.12,221.5 210.12,221.5 C210.12,221.5 210.08,221.38 210.08,221.38 C210.08,221.38 210.03,221.26 210.03,221.26 C210.03,221.26 209.99,221.14 209.99,221.14 C209.99,221.14 209.96,221.02 209.96,221.02 C209.96,221.02 209.92,220.9 209.92,220.9 C209.92,220.9 209.88,220.78 209.88,220.78 C209.88,220.78 209.84,220.67 209.84,220.67 C209.84,220.67 209.81,220.54 209.81,220.54 C209.81,220.54 209.78,220.42 209.78,220.42 C209.78,220.42 209.76,220.3 209.76,220.3 C209.76,220.3 209.73,220.18 209.73,220.18 C209.73,220.18 209.71,220.05 209.71,220.05 C209.71,220.05 209.68,219.93 209.68,219.93 C209.68,219.93 209.66,219.81 209.66,219.81 C209.66,219.81 209.64,219.68 209.64,219.68 C209.64,219.68 209.62,219.56 209.62,219.56 C209.62,219.56 209.61,219.43 209.61,219.43 C209.61,219.43 209.59,219.31 209.59,219.31 C209.59,219.31 209.59,219.18 209.59,219.18 C209.59,219.18 209.58,219.06 209.58,219.06 C209.58,219.06 209.58,218.93 209.58,218.93 C209.58,218.93 209.57,218.81 209.57,218.81 C209.57,218.81 209.56,218.68 209.56,218.68 C209.56,218.68 209.56,218.56 209.56,218.56 C209.56,218.56 209.56,218.43 209.56,218.43 C209.56,218.43 209.57,218.3 209.57,218.3 C209.57,218.3 209.58,218.18 209.58,218.18 C209.58,218.18 209.58,218.05 209.58,218.05 C209.58,218.05 209.59,217.93 209.59,217.93 C209.59,217.93 209.59,217.8 209.59,217.8 C209.59,217.8 209.61,217.68 209.61,217.68 C209.61,217.68 209.63,217.55 209.63,217.55 C209.63,217.55 209.65,217.43 209.65,217.43 C209.65,217.43 209.66,217.31 209.66,217.31 C209.66,217.31 209.68,217.18 209.68,217.18 C209.68,217.18 209.7,217.06 209.7,217.06 C209.7,217.06 209.73,216.93 209.73,216.93 C209.73,216.93 209.76,216.81 209.76,216.81 C209.76,216.81 209.79,216.69 209.79,216.69 C209.79,216.69 209.82,216.57 209.82,216.57 C209.82,216.57 209.85,216.45 209.85,216.45 C209.85,216.45 209.88,216.32 209.88,216.32 C209.88,216.32 209.91,216.2 209.91,216.2 C209.91,216.2 209.95,216.08 209.95,216.08 C209.95,216.08 210,215.97 210,215.97 C210,215.97 210.04,215.85 210.04,215.85 C210.04,215.85 210.08,215.73 210.08,215.73 C210.08,215.73 210.12,215.61 210.12,215.61 C210.12,215.61 210.17,215.49 210.17,215.49 C210.17,215.49 210.22,215.38 210.22,215.38 C210.22,215.38 210.27,215.27 210.27,215.27 C210.27,215.27 210.33,215.15 210.33,215.15 C210.33,215.15 210.38,215.04 210.38,215.04 C210.38,215.04 210.43,214.92 210.43,214.92 C210.43,214.92 210.49,214.81 210.49,214.81 C210.49,214.81 210.55,214.7 210.55,214.7 C210.55,214.7 210.61,214.6 210.61,214.6 C210.61,214.6 210.68,214.49 210.68,214.49 C210.68,214.49 210.74,214.38 210.74,214.38 C210.74,214.38 210.8,214.27 210.8,214.27 C210.8,214.27 210.87,214.17 210.87,214.17 C210.87,214.17 210.95,214.06 210.95,214.06 C210.95,214.06 211.02,213.96 211.02,213.96 C211.02,213.96 211.09,213.86 211.09,213.86 C211.09,213.86 211.16,213.76 211.16,213.76 C211.16,213.76 211.24,213.65 211.24,213.65 C211.24,213.65 211.32,213.56 211.32,213.56 C211.32,213.56 211.4,213.46 211.4,213.46 C211.4,213.46 211.48,213.37 211.48,213.37 C211.48,213.37 211.56,213.27 211.56,213.27 C211.56,213.27 211.64,213.18 211.64,213.18 C211.64,213.18 211.73,213.08 211.73,213.08 C211.73,213.08 211.82,212.99 211.82,212.99 C211.82,212.99 211.91,212.9 211.91,212.9 C211.91,212.9 212,212.82 212,212.82 C212,212.82 212.09,212.73 212.09,212.73 C212.09,212.73 212.18,212.64 212.18,212.64 C212.18,212.64 212.27,212.56 212.27,212.56 C212.27,212.56 212.36,212.48 212.36,212.48 C212.36,212.48 212.46,212.4 212.46,212.4 C212.46,212.4 212.56,212.32 212.56,212.32 C212.56,212.32 212.66,212.24 212.66,212.24 C212.66,212.24 212.76,212.16 212.76,212.16 C212.76,212.16 212.85,212.08 212.85,212.08 C212.85,212.08 212.96,212.02 212.96,212.02 C212.96,212.02 213.06,211.95 213.06,211.95 C213.06,211.95 213.17,211.88 213.17,211.88 C213.17,211.88 213.27,211.81 213.27,211.81 C213.27,211.81 213.38,211.74 213.38,211.74 C213.38,211.74 213.48,211.67 213.48,211.67 C213.48,211.67 213.6,211.61 213.6,211.61 C213.6,211.61 213.71,211.55 213.71,211.55 C213.71,211.55 213.82,211.49 213.82,211.49 C213.82,211.49 213.93,211.43 213.93,211.43 C213.93,211.43 214.04,211.37 214.04,211.37 C214.04,211.37 214.15,211.32 214.15,211.32 C214.15,211.32 214.27,211.27 214.27,211.27 C214.27,211.27 214.38,211.22 214.38,211.22 C214.38,211.22 214.5,211.17 214.5,211.17 C214.5,211.17 214.61,211.12 214.61,211.12 C214.61,211.12 214.73,211.07 214.73,211.07 C214.73,211.07 214.85,211.03 214.85,211.03 C214.85,211.03 214.97,210.99 214.97,210.99 C214.97,210.99 215.09,210.95 215.09,210.95 C215.09,210.95 215.21,210.92 215.21,210.92 C215.21,210.92 215.33,210.88 215.33,210.88 C215.33,210.88 215.45,210.84 215.45,210.84 C215.45,210.84 215.57,210.81 215.57,210.81 C215.57,210.81 215.69,210.78 215.69,210.78 C215.69,210.78 215.81,210.76 215.81,210.76 C215.81,210.76 215.93,210.73 215.93,210.73 C215.93,210.73 216.06,210.7 216.06,210.7 C216.06,210.7 216.18,210.68 216.18,210.68 C216.18,210.68 216.3,210.65 216.3,210.65 C216.3,210.65 216.43,210.64 216.43,210.64 C216.43,210.64 216.55,210.62 216.55,210.62 C216.55,210.62 216.68,210.61 216.68,210.61 C216.68,210.61 216.8,210.59 216.8,210.59 C216.8,210.59 216.93,210.59 216.93,210.59 C216.93,210.59 217.05,210.58 217.05,210.58 C217.05,210.58 217.18,210.58 217.18,210.58 C217.18,210.58 217.3,210.57 217.3,210.57 C217.3,210.57 217.43,210.56 217.43,210.56 C217.43,210.56 217.56,210.56 217.56,210.56 C217.56,210.56 217.68,210.56 217.68,210.56c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.8,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="500" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector> \ No newline at end of file
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="30dp" android:width="30dp" android:viewportHeight="30" android:viewportWidth="30"><group android:name="_R_G"><group android:name="_R_G_L_1_G" android:translateX="15.441" android:translateY="15.691" android:scaleY="0"><path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-10.2 -11.16 C-1.58,-18.94 4.25,-12.72 8.06,-8.64 C11.88,-4.57 17.93,1.89 9.39,9.74 C0.85,17.6 -5.06,11.3 -8.87,7.22 C-12.69,3.14 -18.81,-3.39 -10.2,-11.16c "/></group><group android:name="_R_G_L_0_G" android:translateX="15" android:translateY="15" android:scaleX="0" android:scaleY="0"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M10.71 10.71 C5.92,15.5 -1.85,15.5 -6.64,10.71 C-6.64,10.71 -10.71,6.64 -10.71,6.64 C-15.5,1.85 -15.5,-5.92 -10.71,-10.71 C-5.92,-15.5 1.85,-15.5 6.64,-10.71 C6.64,-10.71 10.71,-6.64 10.71,-6.64 C15.5,-1.85 15.5,5.92 10.71,10.71c "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_1_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M-10.2 -11.16 C-1.58,-18.94 4.25,-12.72 8.06,-8.64 C11.88,-4.57 17.93,1.89 9.39,9.74 C0.85,17.6 -5.06,11.3 -8.87,7.22 C-12.69,3.14 -18.81,-3.39 -10.2,-11.16c " android:valueTo="M-10.2 -11.16 C-1.58,-18.94 4.25,-12.72 8.06,-8.64 C11.88,-4.57 17.93,1.89 9.39,9.74 C0.85,17.6 -5.06,11.3 -8.87,7.22 C-12.69,3.14 -18.81,-3.39 -10.2,-11.16c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.8,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="283" android:startOffset="67" android:valueFrom="M-10.2 -11.16 C-1.58,-18.94 4.25,-12.72 8.06,-8.64 C11.88,-4.57 17.93,1.89 9.39,9.74 C0.85,17.6 -5.06,11.3 -8.87,7.22 C-12.69,3.14 -18.81,-3.39 -10.2,-11.16c " android:valueTo="M-0.44 -8.69 C3.98,-8.69 7.56,-5.11 7.56,-0.69 C7.56,3.73 3.98,7.31 -0.44,7.31 C-4.86,7.31 -8.44,3.73 -8.44,-0.69 C-8.44,-5.11 -4.86,-8.69 -0.44,-8.69c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.8,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_1_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="67" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target><target android:name="_R_G_L_0_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleX" android:duration="67" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="67" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleX" android:duration="283" android:startOffset="67" android:valueFrom="1" android:valueTo="0.4" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.7,0 0.6,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="283" android:startOffset="67" android:valueFrom="1" android:valueTo="0.4" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.7,0 0.6,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target><target android:name="_R_G_L_0_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="367" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="500" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pin_dot_shape_4_avd.xml b/packages/SystemUI/res/drawable/pin_dot_shape_4_avd.xml
index 76ee65b0060c..8ea8f857c71f 100644
--- a/packages/SystemUI/res/drawable/pin_dot_shape_4_avd.xml
+++ b/packages/SystemUI/res/drawable/pin_dot_shape_4_avd.xml
@@ -1 +1 @@
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="60dp" android:width="60dp" android:viewportHeight="60" android:viewportWidth="60"><group android:name="_R_G"><group android:name="_R_G_L_0_G" android:translateX="-187.543" android:translateY="-188.546"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="0" android:fillType="nonZero" android:pathData=" M217.62 214.55 C217.62,214.55 217.68,214.55 217.68,214.55 C217.68,214.55 217.74,214.56 217.74,214.56 C217.74,214.56 217.81,214.56 217.81,214.56 C217.81,214.56 217.87,214.56 217.87,214.56 C217.87,214.56 217.93,214.57 217.93,214.57 C217.93,214.57 218,214.57 218,214.57 C218,214.57 218.06,214.58 218.06,214.58 C218.06,214.58 218.12,214.59 218.12,214.59 C218.12,214.59 218.18,214.6 218.18,214.6 C218.18,214.6 218.24,214.61 218.24,214.61 C218.24,214.61 218.31,214.62 218.31,214.62 C218.31,214.62 218.37,214.63 218.37,214.63 C218.37,214.63 218.43,214.65 218.43,214.65 C218.43,214.65 218.49,214.66 218.49,214.66 C218.49,214.66 218.55,214.68 218.55,214.68 C218.55,214.68 218.61,214.69 218.61,214.69 C218.61,214.69 218.67,214.71 218.67,214.71 C218.67,214.71 218.73,214.73 218.73,214.73 C218.73,214.73 218.79,214.75 218.79,214.75 C218.79,214.75 218.85,214.77 218.85,214.77 C218.85,214.77 218.91,214.79 218.91,214.79 C218.91,214.79 218.97,214.81 218.97,214.81 C218.97,214.81 219.03,214.83 219.03,214.83 C219.03,214.83 219.09,214.85 219.09,214.85 C219.09,214.85 219.15,214.88 219.15,214.88 C219.15,214.88 219.2,214.9 219.2,214.9 C219.2,214.9 219.26,214.93 219.26,214.93 C219.26,214.93 219.32,214.96 219.32,214.96 C219.32,214.96 219.37,214.98 219.37,214.98 C219.37,214.98 219.43,215.01 219.43,215.01 C219.43,215.01 219.48,215.05 219.48,215.05 C219.48,215.05 219.54,215.08 219.54,215.08 C219.54,215.08 219.59,215.11 219.59,215.11 C219.59,215.11 219.65,215.14 219.65,215.14 C219.65,215.14 219.7,215.17 219.7,215.17 C219.7,215.17 219.75,215.21 219.75,215.21 C219.75,215.21 219.81,215.24 219.81,215.24 C219.81,215.24 219.86,215.28 219.86,215.28 C219.86,215.28 219.91,215.32 219.91,215.32 C219.91,215.32 219.96,215.35 219.96,215.35 C219.96,215.35 220.01,215.39 220.01,215.39 C220.01,215.39 220.06,215.43 220.06,215.43 C220.06,215.43 220.11,215.47 220.11,215.47 C220.11,215.47 220.16,215.51 220.16,215.51 C220.16,215.51 220.2,215.55 220.2,215.55 C220.2,215.55 220.25,215.59 220.25,215.59 C220.25,215.59 220.3,215.63 220.3,215.63 C220.3,215.63 220.34,215.68 220.34,215.68 C220.34,215.68 220.39,215.72 220.39,215.72 C220.39,215.72 220.43,215.77 220.43,215.77 C220.43,215.77 220.47,215.81 220.47,215.81 C220.47,215.81 220.52,215.86 220.52,215.86 C220.52,215.86 220.56,215.9 220.56,215.9 C220.56,215.9 220.6,215.95 220.6,215.95 C220.6,215.95 220.64,216 220.64,216 C220.64,216 220.68,216.05 220.68,216.05 C220.68,216.05 220.72,216.1 220.72,216.1 C220.72,216.1 220.76,216.15 220.76,216.15 C220.76,216.15 220.8,216.2 220.8,216.2 C220.8,216.2 220.83,216.25 220.83,216.25 C220.83,216.25 220.87,216.3 220.87,216.3 C220.87,216.3 220.9,216.36 220.9,216.36 C220.9,216.36 220.94,216.41 220.94,216.41 C220.94,216.41 220.97,216.46 220.97,216.46 C220.97,216.46 221,216.51 221,216.51 C221,216.51 221.03,216.57 221.03,216.57 C221.03,216.57 221.06,216.63 221.06,216.63 C221.06,216.63 221.09,216.68 221.09,216.68 C221.09,216.68 221.12,216.74 221.12,216.74 C221.12,216.74 221.15,216.79 221.15,216.79 C221.15,216.79 221.18,216.85 221.18,216.85 C221.18,216.85 221.21,216.91 221.21,216.91 C221.21,216.91 221.23,216.96 221.23,216.96 C221.23,216.96 221.25,217.02 221.25,217.02 C221.25,217.02 221.28,217.08 221.28,217.08 C221.28,217.08 221.3,217.14 221.3,217.14 C221.3,217.14 221.33,217.2 221.33,217.2 C221.33,217.2 221.34,217.26 221.34,217.26 C221.34,217.26 221.36,217.32 221.36,217.32 C221.36,217.32 221.38,217.38 221.38,217.38 C221.38,217.38 221.4,217.44 221.4,217.44 C221.4,217.44 221.42,217.5 221.42,217.5 C221.42,217.5 221.44,217.56 221.44,217.56 C221.44,217.56 221.45,217.62 221.45,217.62 C221.45,217.62 221.46,217.68 221.46,217.68 C221.46,217.68 221.48,217.74 221.48,217.74 C221.48,217.74 221.49,217.8 221.49,217.8 C221.49,217.8 221.5,217.87 221.5,217.87 C221.5,217.87 221.51,217.93 221.51,217.93 C221.51,217.93 221.52,217.99 221.52,217.99 C221.52,217.99 221.53,218.05 221.53,218.05 C221.53,218.05 221.54,218.11 221.54,218.11 C221.54,218.11 221.54,218.18 221.54,218.18 C221.54,218.18 221.55,218.24 221.55,218.24 C221.55,218.24 221.55,218.3 221.55,218.3 C221.55,218.3 221.55,218.37 221.55,218.37 C221.55,218.37 221.56,218.43 221.56,218.43 C221.56,218.43 221.56,218.49 221.56,218.49 C221.56,218.49 221.56,218.55 221.56,218.55 C221.56,218.55 221.56,218.62 221.56,218.62 C221.56,218.62 221.56,218.68 221.56,218.68 C221.56,218.68 221.55,218.74 221.55,218.74 C221.55,218.74 221.55,218.81 221.55,218.81 C221.55,218.81 221.55,218.87 221.55,218.87 C221.55,218.87 221.54,218.93 221.54,218.93 C221.54,218.93 221.54,218.99 221.54,218.99 C221.54,218.99 221.53,219.06 221.53,219.06 C221.53,219.06 221.52,219.12 221.52,219.12 C221.52,219.12 221.51,219.18 221.51,219.18 C221.51,219.18 221.5,219.24 221.5,219.24 C221.5,219.24 221.49,219.3 221.49,219.3 C221.49,219.3 221.48,219.37 221.48,219.37 C221.48,219.37 221.46,219.43 221.46,219.43 C221.46,219.43 221.45,219.49 221.45,219.49 C221.45,219.49 221.43,219.55 221.43,219.55 C221.43,219.55 221.42,219.61 221.42,219.61 C221.42,219.61 221.4,219.67 221.4,219.67 C221.4,219.67 221.39,219.73 221.39,219.73 C221.39,219.73 221.37,219.79 221.37,219.79 C221.37,219.79 221.34,219.85 221.34,219.85 C221.34,219.85 221.32,219.91 221.32,219.91 C221.32,219.91 221.3,219.97 221.3,219.97 C221.3,219.97 221.28,220.03 221.28,220.03 C221.28,220.03 221.26,220.09 221.26,220.09 C221.26,220.09 221.23,220.14 221.23,220.14 C221.23,220.14 221.21,220.2 221.21,220.2 C221.21,220.2 221.18,220.26 221.18,220.26 C221.18,220.26 221.15,220.32 221.15,220.32 C221.15,220.32 221.13,220.37 221.13,220.37 C221.13,220.37 221.1,220.43 221.1,220.43 C221.1,220.43 221.07,220.48 221.07,220.48 C221.07,220.48 221.03,220.54 221.03,220.54 C221.03,220.54 221,220.59 221,220.59 C221,220.59 220.97,220.65 220.97,220.65 C220.97,220.65 220.94,220.7 220.94,220.7 C220.94,220.7 220.9,220.75 220.9,220.75 C220.9,220.75 220.87,220.8 220.87,220.8 C220.87,220.8 220.83,220.86 220.83,220.86 C220.83,220.86 220.8,220.91 220.8,220.91 C220.8,220.91 220.76,220.96 220.76,220.96 C220.76,220.96 220.72,221.01 220.72,221.01 C220.72,221.01 220.68,221.06 220.68,221.06 C220.68,221.06 220.64,221.11 220.64,221.11 C220.64,221.11 220.6,221.15 220.6,221.15 C220.6,221.15 220.56,221.2 220.56,221.2 C220.56,221.2 220.52,221.25 220.52,221.25 C220.52,221.25 220.48,221.3 220.48,221.3 C220.48,221.3 220.43,221.34 220.43,221.34 C220.43,221.34 220.39,221.38 220.39,221.38 C220.39,221.38 220.34,221.43 220.34,221.43 C220.34,221.43 220.3,221.47 220.3,221.47 C220.3,221.47 220.25,221.52 220.25,221.52 C220.25,221.52 220.21,221.56 220.21,221.56 C220.21,221.56 220.16,221.6 220.16,221.6 C220.16,221.6 220.11,221.64 220.11,221.64 C220.11,221.64 220.06,221.68 220.06,221.68 C220.06,221.68 220.01,221.72 220.01,221.72 C220.01,221.72 219.96,221.76 219.96,221.76 C219.96,221.76 219.91,221.8 219.91,221.8 C219.91,221.8 219.86,221.83 219.86,221.83 C219.86,221.83 219.81,221.87 219.81,221.87 C219.81,221.87 219.75,221.9 219.75,221.9 C219.75,221.9 219.7,221.93 219.7,221.93 C219.7,221.93 219.65,221.97 219.65,221.97 C219.65,221.97 219.6,222 219.6,222 C219.6,222 219.54,222.03 219.54,222.03 C219.54,222.03 219.49,222.06 219.49,222.06 C219.49,222.06 219.43,222.09 219.43,222.09 C219.43,222.09 219.37,222.12 219.37,222.12 C219.37,222.12 219.32,222.15 219.32,222.15 C219.32,222.15 219.26,222.18 219.26,222.18 C219.26,222.18 219.21,222.2 219.21,222.2 C219.21,222.2 219.15,222.23 219.15,222.23 C219.15,222.23 219.09,222.25 219.09,222.25 C219.09,222.25 219.03,222.28 219.03,222.28 C219.03,222.28 218.97,222.3 218.97,222.3 C218.97,222.3 218.91,222.32 218.91,222.32 C218.91,222.32 218.85,222.34 218.85,222.34 C218.85,222.34 218.79,222.36 218.79,222.36 C218.79,222.36 218.73,222.38 218.73,222.38 C218.73,222.38 218.67,222.4 218.67,222.4 C218.67,222.4 218.61,222.42 218.61,222.42 C218.61,222.42 218.55,222.44 218.55,222.44 C218.55,222.44 218.49,222.45 218.49,222.45 C218.49,222.45 218.43,222.46 218.43,222.46 C218.43,222.46 218.37,222.47 218.37,222.47 C218.37,222.47 218.31,222.49 218.31,222.49 C218.31,222.49 218.25,222.5 218.25,222.5 C218.25,222.5 218.18,222.51 218.18,222.51 C218.18,222.51 218.12,222.52 218.12,222.52 C218.12,222.52 218.06,222.53 218.06,222.53 C218.06,222.53 218,222.54 218,222.54 C218,222.54 217.93,222.54 217.93,222.54 C217.93,222.54 217.87,222.55 217.87,222.55 C217.87,222.55 217.81,222.55 217.81,222.55 C217.81,222.55 217.75,222.55 217.75,222.55 C217.75,222.55 217.68,222.56 217.68,222.56 C217.68,222.56 217.62,222.56 217.62,222.56 C217.62,222.56 217.56,222.56 217.56,222.56 C217.56,222.56 217.49,222.56 217.49,222.56 C217.49,222.56 217.43,222.56 217.43,222.56 C217.43,222.56 217.37,222.55 217.37,222.55 C217.37,222.55 217.3,222.55 217.3,222.55 C217.3,222.55 217.24,222.55 217.24,222.55 C217.24,222.55 217.18,222.54 217.18,222.54 C217.18,222.54 217.12,222.54 217.12,222.54 C217.12,222.54 217.05,222.53 217.05,222.53 C217.05,222.53 216.99,222.52 216.99,222.52 C216.99,222.52 216.93,222.51 216.93,222.51 C216.93,222.51 216.87,222.5 216.87,222.5 C216.87,222.5 216.81,222.49 216.81,222.49 C216.81,222.49 216.74,222.48 216.74,222.48 C216.74,222.48 216.68,222.46 216.68,222.46 C216.68,222.46 216.62,222.45 216.62,222.45 C216.62,222.45 216.56,222.43 216.56,222.43 C216.56,222.43 216.5,222.42 216.5,222.42 C216.5,222.42 216.44,222.4 216.44,222.4 C216.44,222.4 216.38,222.38 216.38,222.38 C216.38,222.38 216.32,222.36 216.32,222.36 C216.32,222.36 216.26,222.34 216.26,222.34 C216.26,222.34 216.2,222.32 216.2,222.32 C216.2,222.32 216.14,222.3 216.14,222.3 C216.14,222.3 216.08,222.28 216.08,222.28 C216.08,222.28 216.02,222.26 216.02,222.26 C216.02,222.26 215.97,222.23 215.97,222.23 C215.97,222.23 215.91,222.2 215.91,222.2 C215.91,222.2 215.85,222.18 215.85,222.18 C215.85,222.18 215.79,222.15 215.79,222.15 C215.79,222.15 215.74,222.12 215.74,222.12 C215.74,222.12 215.68,222.1 215.68,222.1 C215.68,222.1 215.63,222.06 215.63,222.06 C215.63,222.06 215.57,222.03 215.57,222.03 C215.57,222.03 215.52,222 215.52,222 C215.52,222 215.46,221.97 215.46,221.97 C215.46,221.97 215.41,221.94 215.41,221.94 C215.41,221.94 215.36,221.9 215.36,221.9 C215.36,221.9 215.31,221.87 215.31,221.87 C215.31,221.87 215.25,221.83 215.25,221.83 C215.25,221.83 215.2,221.79 215.2,221.79 C215.2,221.79 215.15,221.76 215.15,221.76 C215.15,221.76 215.1,221.72 215.1,221.72 C215.1,221.72 215.05,221.68 215.05,221.68 C215.05,221.68 215,221.64 215,221.64 C215,221.64 214.96,221.6 214.96,221.6 C214.96,221.6 214.91,221.56 214.91,221.56 C214.91,221.56 214.86,221.52 214.86,221.52 C214.86,221.52 214.81,221.48 214.81,221.48 C214.81,221.48 214.77,221.43 214.77,221.43 C214.77,221.43 214.73,221.39 214.73,221.39 C214.73,221.39 214.68,221.34 214.68,221.34 C214.68,221.34 214.64,221.3 214.64,221.3 C214.64,221.3 214.59,221.25 214.59,221.25 C214.59,221.25 214.55,221.2 214.55,221.2 C214.55,221.2 214.51,221.15 214.51,221.15 C214.51,221.15 214.47,221.11 214.47,221.11 C214.47,221.11 214.43,221.06 214.43,221.06 C214.43,221.06 214.39,221.01 214.39,221.01 C214.39,221.01 214.35,220.96 214.35,220.96 C214.35,220.96 214.31,220.91 214.31,220.91 C214.31,220.91 214.28,220.86 214.28,220.86 C214.28,220.86 214.25,220.81 214.25,220.81 C214.25,220.81 214.21,220.75 214.21,220.75 C214.21,220.75 214.18,220.7 214.18,220.7 C214.18,220.7 214.14,220.65 214.14,220.65 C214.14,220.65 214.11,220.59 214.11,220.59 C214.11,220.59 214.08,220.54 214.08,220.54 C214.08,220.54 214.05,220.48 214.05,220.48 C214.05,220.48 214.02,220.43 214.02,220.43 C214.02,220.43 213.99,220.37 213.99,220.37 C213.99,220.37 213.96,220.32 213.96,220.32 C213.96,220.32 213.93,220.26 213.93,220.26 C213.93,220.26 213.91,220.2 213.91,220.2 C213.91,220.2 213.88,220.14 213.88,220.14 C213.88,220.14 213.86,220.09 213.86,220.09 C213.86,220.09 213.83,220.03 213.83,220.03 C213.83,220.03 213.81,219.97 213.81,219.97 C213.81,219.97 213.79,219.91 213.79,219.91 C213.79,219.91 213.77,219.85 213.77,219.85 C213.77,219.85 213.75,219.79 213.75,219.79 C213.75,219.79 213.73,219.73 213.73,219.73 C213.73,219.73 213.71,219.67 213.71,219.67 C213.71,219.67 213.69,219.61 213.69,219.61 C213.69,219.61 213.68,219.55 213.68,219.55 C213.68,219.55 213.66,219.49 213.66,219.49 C213.66,219.49 213.65,219.43 213.65,219.43 C213.65,219.43 213.64,219.37 213.64,219.37 C213.64,219.37 213.62,219.31 213.62,219.31 C213.62,219.31 213.61,219.24 213.61,219.24 C213.61,219.24 213.6,219.18 213.6,219.18 C213.6,219.18 213.59,219.12 213.59,219.12 C213.59,219.12 213.58,219.06 213.58,219.06 C213.58,219.06 213.57,218.99 213.57,218.99 C213.57,218.99 213.57,218.93 213.57,218.93 C213.57,218.93 213.56,218.87 213.56,218.87 C213.56,218.87 213.56,218.81 213.56,218.81 C213.56,218.81 213.56,218.74 213.56,218.74 C213.56,218.74 213.56,218.68 213.56,218.68 C213.56,218.68 213.55,218.62 213.55,218.62 C213.55,218.62 213.55,218.55 213.55,218.55 C213.55,218.55 213.55,218.49 213.55,218.49 C213.55,218.49 213.56,218.43 213.56,218.43 C213.56,218.43 213.56,218.37 213.56,218.37 C213.56,218.37 213.56,218.3 213.56,218.3 C213.56,218.3 213.56,218.24 213.56,218.24 C213.56,218.24 213.57,218.18 213.57,218.18 C213.57,218.18 213.57,218.12 213.57,218.12 C213.57,218.12 213.58,218.05 213.58,218.05 C213.58,218.05 213.59,217.99 213.59,217.99 C213.59,217.99 213.6,217.93 213.6,217.93 C213.6,217.93 213.61,217.87 213.61,217.87 C213.61,217.87 213.62,217.8 213.62,217.8 C213.62,217.8 213.63,217.74 213.63,217.74 C213.63,217.74 213.65,217.68 213.65,217.68 C213.65,217.68 213.66,217.62 213.66,217.62 C213.66,217.62 213.68,217.56 213.68,217.56 C213.68,217.56 213.69,217.5 213.69,217.5 C213.69,217.5 213.71,217.44 213.71,217.44 C213.71,217.44 213.73,217.38 213.73,217.38 C213.73,217.38 213.75,217.32 213.75,217.32 C213.75,217.32 213.77,217.26 213.77,217.26 C213.77,217.26 213.79,217.2 213.79,217.2 C213.79,217.2 213.81,217.14 213.81,217.14 C213.81,217.14 213.83,217.08 213.83,217.08 C213.83,217.08 213.85,217.02 213.85,217.02 C213.85,217.02 213.88,216.96 213.88,216.96 C213.88,216.96 213.91,216.91 213.91,216.91 C213.91,216.91 213.93,216.85 213.93,216.85 C213.93,216.85 213.96,216.79 213.96,216.79 C213.96,216.79 213.99,216.74 213.99,216.74 C213.99,216.74 214.02,216.68 214.02,216.68 C214.02,216.68 214.05,216.63 214.05,216.63 C214.05,216.63 214.08,216.57 214.08,216.57 C214.08,216.57 214.11,216.52 214.11,216.52 C214.11,216.52 214.14,216.46 214.14,216.46 C214.14,216.46 214.17,216.41 214.17,216.41 C214.17,216.41 214.21,216.36 214.21,216.36 C214.21,216.36 214.24,216.3 214.24,216.3 C214.24,216.3 214.28,216.25 214.28,216.25 C214.28,216.25 214.32,216.2 214.32,216.2 C214.32,216.2 214.35,216.15 214.35,216.15 C214.35,216.15 214.39,216.1 214.39,216.1 C214.39,216.1 214.43,216.05 214.43,216.05 C214.43,216.05 214.47,216 214.47,216 C214.47,216 214.51,215.96 214.51,215.96 C214.51,215.96 214.55,215.91 214.55,215.91 C214.55,215.91 214.59,215.86 214.59,215.86 C214.59,215.86 214.64,215.81 214.64,215.81 C214.64,215.81 214.68,215.77 214.68,215.77 C214.68,215.77 214.73,215.72 214.73,215.72 C214.73,215.72 214.77,215.68 214.77,215.68 C214.77,215.68 214.82,215.64 214.82,215.64 C214.82,215.64 214.86,215.59 214.86,215.59 C214.86,215.59 214.91,215.55 214.91,215.55 C214.91,215.55 214.96,215.51 214.96,215.51 C214.96,215.51 215,215.47 215,215.47 C215,215.47 215.05,215.43 215.05,215.43 C215.05,215.43 215.1,215.39 215.1,215.39 C215.1,215.39 215.15,215.35 215.15,215.35 C215.15,215.35 215.2,215.31 215.2,215.31 C215.2,215.31 215.25,215.28 215.25,215.28 C215.25,215.28 215.31,215.24 215.31,215.24 C215.31,215.24 215.36,215.21 215.36,215.21 C215.36,215.21 215.41,215.17 215.41,215.17 C215.41,215.17 215.46,215.14 215.46,215.14 C215.46,215.14 215.52,215.11 215.52,215.11 C215.52,215.11 215.57,215.08 215.57,215.08 C215.57,215.08 215.63,215.05 215.63,215.05 C215.63,215.05 215.68,215.02 215.68,215.02 C215.68,215.02 215.74,214.99 215.74,214.99 C215.74,214.99 215.79,214.96 215.79,214.96 C215.79,214.96 215.85,214.93 215.85,214.93 C215.85,214.93 215.91,214.9 215.91,214.9 C215.91,214.9 215.97,214.88 215.97,214.88 C215.97,214.88 216.02,214.86 216.02,214.86 C216.02,214.86 216.08,214.83 216.08,214.83 C216.08,214.83 216.14,214.81 216.14,214.81 C216.14,214.81 216.2,214.78 216.2,214.78 C216.2,214.78 216.26,214.77 216.26,214.77 C216.26,214.77 216.32,214.75 216.32,214.75 C216.32,214.75 216.38,214.73 216.38,214.73 C216.38,214.73 216.44,214.71 216.44,214.71 C216.44,214.71 216.5,214.69 216.5,214.69 C216.5,214.69 216.56,214.67 216.56,214.67 C216.56,214.67 216.62,214.66 216.62,214.66 C216.62,214.66 216.68,214.65 216.68,214.65 C216.68,214.65 216.74,214.63 216.74,214.63 C216.74,214.63 216.81,214.62 216.81,214.62 C216.81,214.62 216.87,214.61 216.87,214.61 C216.87,214.61 216.93,214.6 216.93,214.6 C216.93,214.6 216.99,214.59 216.99,214.59 C216.99,214.59 217.05,214.58 217.05,214.58 C217.05,214.58 217.12,214.57 217.12,214.57 C217.12,214.57 217.18,214.57 217.18,214.57 C217.18,214.57 217.24,214.56 217.24,214.56 C217.24,214.56 217.3,214.56 217.3,214.56 C217.3,214.56 217.37,214.56 217.37,214.56 C217.37,214.56 217.43,214.55 217.43,214.55 C217.43,214.55 217.49,214.55 217.49,214.55 C217.49,214.55 217.56,214.55 217.56,214.55 C217.56,214.55 217.62,214.55 217.62,214.55c "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="fillAlpha" android:duration="33" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M217.62 214.55 C217.62,214.55 217.68,214.55 217.68,214.55 C217.68,214.55 217.74,214.56 217.74,214.56 C217.74,214.56 217.81,214.56 217.81,214.56 C217.81,214.56 217.87,214.56 217.87,214.56 C217.87,214.56 217.93,214.57 217.93,214.57 C217.93,214.57 218,214.57 218,214.57 C218,214.57 218.06,214.58 218.06,214.58 C218.06,214.58 218.12,214.59 218.12,214.59 C218.12,214.59 218.18,214.6 218.18,214.6 C218.18,214.6 218.24,214.61 218.24,214.61 C218.24,214.61 218.31,214.62 218.31,214.62 C218.31,214.62 218.37,214.63 218.37,214.63 C218.37,214.63 218.43,214.65 218.43,214.65 C218.43,214.65 218.49,214.66 218.49,214.66 C218.49,214.66 218.55,214.68 218.55,214.68 C218.55,214.68 218.61,214.69 218.61,214.69 C218.61,214.69 218.67,214.71 218.67,214.71 C218.67,214.71 218.73,214.73 218.73,214.73 C218.73,214.73 218.79,214.75 218.79,214.75 C218.79,214.75 218.85,214.77 218.85,214.77 C218.85,214.77 218.91,214.79 218.91,214.79 C218.91,214.79 218.97,214.81 218.97,214.81 C218.97,214.81 219.03,214.83 219.03,214.83 C219.03,214.83 219.09,214.85 219.09,214.85 C219.09,214.85 219.15,214.88 219.15,214.88 C219.15,214.88 219.2,214.9 219.2,214.9 C219.2,214.9 219.26,214.93 219.26,214.93 C219.26,214.93 219.32,214.96 219.32,214.96 C219.32,214.96 219.37,214.98 219.37,214.98 C219.37,214.98 219.43,215.01 219.43,215.01 C219.43,215.01 219.48,215.05 219.48,215.05 C219.48,215.05 219.54,215.08 219.54,215.08 C219.54,215.08 219.59,215.11 219.59,215.11 C219.59,215.11 219.65,215.14 219.65,215.14 C219.65,215.14 219.7,215.17 219.7,215.17 C219.7,215.17 219.75,215.21 219.75,215.21 C219.75,215.21 219.81,215.24 219.81,215.24 C219.81,215.24 219.86,215.28 219.86,215.28 C219.86,215.28 219.91,215.32 219.91,215.32 C219.91,215.32 219.96,215.35 219.96,215.35 C219.96,215.35 220.01,215.39 220.01,215.39 C220.01,215.39 220.06,215.43 220.06,215.43 C220.06,215.43 220.11,215.47 220.11,215.47 C220.11,215.47 220.16,215.51 220.16,215.51 C220.16,215.51 220.2,215.55 220.2,215.55 C220.2,215.55 220.25,215.59 220.25,215.59 C220.25,215.59 220.3,215.63 220.3,215.63 C220.3,215.63 220.34,215.68 220.34,215.68 C220.34,215.68 220.39,215.72 220.39,215.72 C220.39,215.72 220.43,215.77 220.43,215.77 C220.43,215.77 220.47,215.81 220.47,215.81 C220.47,215.81 220.52,215.86 220.52,215.86 C220.52,215.86 220.56,215.9 220.56,215.9 C220.56,215.9 220.6,215.95 220.6,215.95 C220.6,215.95 220.64,216 220.64,216 C220.64,216 220.68,216.05 220.68,216.05 C220.68,216.05 220.72,216.1 220.72,216.1 C220.72,216.1 220.76,216.15 220.76,216.15 C220.76,216.15 220.8,216.2 220.8,216.2 C220.8,216.2 220.83,216.25 220.83,216.25 C220.83,216.25 220.87,216.3 220.87,216.3 C220.87,216.3 220.9,216.36 220.9,216.36 C220.9,216.36 220.94,216.41 220.94,216.41 C220.94,216.41 220.97,216.46 220.97,216.46 C220.97,216.46 221,216.51 221,216.51 C221,216.51 221.03,216.57 221.03,216.57 C221.03,216.57 221.06,216.63 221.06,216.63 C221.06,216.63 221.09,216.68 221.09,216.68 C221.09,216.68 221.12,216.74 221.12,216.74 C221.12,216.74 221.15,216.79 221.15,216.79 C221.15,216.79 221.18,216.85 221.18,216.85 C221.18,216.85 221.21,216.91 221.21,216.91 C221.21,216.91 221.23,216.96 221.23,216.96 C221.23,216.96 221.25,217.02 221.25,217.02 C221.25,217.02 221.28,217.08 221.28,217.08 C221.28,217.08 221.3,217.14 221.3,217.14 C221.3,217.14 221.33,217.2 221.33,217.2 C221.33,217.2 221.34,217.26 221.34,217.26 C221.34,217.26 221.36,217.32 221.36,217.32 C221.36,217.32 221.38,217.38 221.38,217.38 C221.38,217.38 221.4,217.44 221.4,217.44 C221.4,217.44 221.42,217.5 221.42,217.5 C221.42,217.5 221.44,217.56 221.44,217.56 C221.44,217.56 221.45,217.62 221.45,217.62 C221.45,217.62 221.46,217.68 221.46,217.68 C221.46,217.68 221.48,217.74 221.48,217.74 C221.48,217.74 221.49,217.8 221.49,217.8 C221.49,217.8 221.5,217.87 221.5,217.87 C221.5,217.87 221.51,217.93 221.51,217.93 C221.51,217.93 221.52,217.99 221.52,217.99 C221.52,217.99 221.53,218.05 221.53,218.05 C221.53,218.05 221.54,218.11 221.54,218.11 C221.54,218.11 221.54,218.18 221.54,218.18 C221.54,218.18 221.55,218.24 221.55,218.24 C221.55,218.24 221.55,218.3 221.55,218.3 C221.55,218.3 221.55,218.37 221.55,218.37 C221.55,218.37 221.56,218.43 221.56,218.43 C221.56,218.43 221.56,218.49 221.56,218.49 C221.56,218.49 221.56,218.55 221.56,218.55 C221.56,218.55 221.56,218.62 221.56,218.62 C221.56,218.62 221.56,218.68 221.56,218.68 C221.56,218.68 221.55,218.74 221.55,218.74 C221.55,218.74 221.55,218.81 221.55,218.81 C221.55,218.81 221.55,218.87 221.55,218.87 C221.55,218.87 221.54,218.93 221.54,218.93 C221.54,218.93 221.54,218.99 221.54,218.99 C221.54,218.99 221.53,219.06 221.53,219.06 C221.53,219.06 221.52,219.12 221.52,219.12 C221.52,219.12 221.51,219.18 221.51,219.18 C221.51,219.18 221.5,219.24 221.5,219.24 C221.5,219.24 221.49,219.3 221.49,219.3 C221.49,219.3 221.48,219.37 221.48,219.37 C221.48,219.37 221.46,219.43 221.46,219.43 C221.46,219.43 221.45,219.49 221.45,219.49 C221.45,219.49 221.43,219.55 221.43,219.55 C221.43,219.55 221.42,219.61 221.42,219.61 C221.42,219.61 221.4,219.67 221.4,219.67 C221.4,219.67 221.39,219.73 221.39,219.73 C221.39,219.73 221.37,219.79 221.37,219.79 C221.37,219.79 221.34,219.85 221.34,219.85 C221.34,219.85 221.32,219.91 221.32,219.91 C221.32,219.91 221.3,219.97 221.3,219.97 C221.3,219.97 221.28,220.03 221.28,220.03 C221.28,220.03 221.26,220.09 221.26,220.09 C221.26,220.09 221.23,220.14 221.23,220.14 C221.23,220.14 221.21,220.2 221.21,220.2 C221.21,220.2 221.18,220.26 221.18,220.26 C221.18,220.26 221.15,220.32 221.15,220.32 C221.15,220.32 221.13,220.37 221.13,220.37 C221.13,220.37 221.1,220.43 221.1,220.43 C221.1,220.43 221.07,220.48 221.07,220.48 C221.07,220.48 221.03,220.54 221.03,220.54 C221.03,220.54 221,220.59 221,220.59 C221,220.59 220.97,220.65 220.97,220.65 C220.97,220.65 220.94,220.7 220.94,220.7 C220.94,220.7 220.9,220.75 220.9,220.75 C220.9,220.75 220.87,220.8 220.87,220.8 C220.87,220.8 220.83,220.86 220.83,220.86 C220.83,220.86 220.8,220.91 220.8,220.91 C220.8,220.91 220.76,220.96 220.76,220.96 C220.76,220.96 220.72,221.01 220.72,221.01 C220.72,221.01 220.68,221.06 220.68,221.06 C220.68,221.06 220.64,221.11 220.64,221.11 C220.64,221.11 220.6,221.15 220.6,221.15 C220.6,221.15 220.56,221.2 220.56,221.2 C220.56,221.2 220.52,221.25 220.52,221.25 C220.52,221.25 220.48,221.3 220.48,221.3 C220.48,221.3 220.43,221.34 220.43,221.34 C220.43,221.34 220.39,221.38 220.39,221.38 C220.39,221.38 220.34,221.43 220.34,221.43 C220.34,221.43 220.3,221.47 220.3,221.47 C220.3,221.47 220.25,221.52 220.25,221.52 C220.25,221.52 220.21,221.56 220.21,221.56 C220.21,221.56 220.16,221.6 220.16,221.6 C220.16,221.6 220.11,221.64 220.11,221.64 C220.11,221.64 220.06,221.68 220.06,221.68 C220.06,221.68 220.01,221.72 220.01,221.72 C220.01,221.72 219.96,221.76 219.96,221.76 C219.96,221.76 219.91,221.8 219.91,221.8 C219.91,221.8 219.86,221.83 219.86,221.83 C219.86,221.83 219.81,221.87 219.81,221.87 C219.81,221.87 219.75,221.9 219.75,221.9 C219.75,221.9 219.7,221.93 219.7,221.93 C219.7,221.93 219.65,221.97 219.65,221.97 C219.65,221.97 219.6,222 219.6,222 C219.6,222 219.54,222.03 219.54,222.03 C219.54,222.03 219.49,222.06 219.49,222.06 C219.49,222.06 219.43,222.09 219.43,222.09 C219.43,222.09 219.37,222.12 219.37,222.12 C219.37,222.12 219.32,222.15 219.32,222.15 C219.32,222.15 219.26,222.18 219.26,222.18 C219.26,222.18 219.21,222.2 219.21,222.2 C219.21,222.2 219.15,222.23 219.15,222.23 C219.15,222.23 219.09,222.25 219.09,222.25 C219.09,222.25 219.03,222.28 219.03,222.28 C219.03,222.28 218.97,222.3 218.97,222.3 C218.97,222.3 218.91,222.32 218.91,222.32 C218.91,222.32 218.85,222.34 218.85,222.34 C218.85,222.34 218.79,222.36 218.79,222.36 C218.79,222.36 218.73,222.38 218.73,222.38 C218.73,222.38 218.67,222.4 218.67,222.4 C218.67,222.4 218.61,222.42 218.61,222.42 C218.61,222.42 218.55,222.44 218.55,222.44 C218.55,222.44 218.49,222.45 218.49,222.45 C218.49,222.45 218.43,222.46 218.43,222.46 C218.43,222.46 218.37,222.47 218.37,222.47 C218.37,222.47 218.31,222.49 218.31,222.49 C218.31,222.49 218.25,222.5 218.25,222.5 C218.25,222.5 218.18,222.51 218.18,222.51 C218.18,222.51 218.12,222.52 218.12,222.52 C218.12,222.52 218.06,222.53 218.06,222.53 C218.06,222.53 218,222.54 218,222.54 C218,222.54 217.93,222.54 217.93,222.54 C217.93,222.54 217.87,222.55 217.87,222.55 C217.87,222.55 217.81,222.55 217.81,222.55 C217.81,222.55 217.75,222.55 217.75,222.55 C217.75,222.55 217.68,222.56 217.68,222.56 C217.68,222.56 217.62,222.56 217.62,222.56 C217.62,222.56 217.56,222.56 217.56,222.56 C217.56,222.56 217.49,222.56 217.49,222.56 C217.49,222.56 217.43,222.56 217.43,222.56 C217.43,222.56 217.37,222.55 217.37,222.55 C217.37,222.55 217.3,222.55 217.3,222.55 C217.3,222.55 217.24,222.55 217.24,222.55 C217.24,222.55 217.18,222.54 217.18,222.54 C217.18,222.54 217.12,222.54 217.12,222.54 C217.12,222.54 217.05,222.53 217.05,222.53 C217.05,222.53 216.99,222.52 216.99,222.52 C216.99,222.52 216.93,222.51 216.93,222.51 C216.93,222.51 216.87,222.5 216.87,222.5 C216.87,222.5 216.81,222.49 216.81,222.49 C216.81,222.49 216.74,222.48 216.74,222.48 C216.74,222.48 216.68,222.46 216.68,222.46 C216.68,222.46 216.62,222.45 216.62,222.45 C216.62,222.45 216.56,222.43 216.56,222.43 C216.56,222.43 216.5,222.42 216.5,222.42 C216.5,222.42 216.44,222.4 216.44,222.4 C216.44,222.4 216.38,222.38 216.38,222.38 C216.38,222.38 216.32,222.36 216.32,222.36 C216.32,222.36 216.26,222.34 216.26,222.34 C216.26,222.34 216.2,222.32 216.2,222.32 C216.2,222.32 216.14,222.3 216.14,222.3 C216.14,222.3 216.08,222.28 216.08,222.28 C216.08,222.28 216.02,222.26 216.02,222.26 C216.02,222.26 215.97,222.23 215.97,222.23 C215.97,222.23 215.91,222.2 215.91,222.2 C215.91,222.2 215.85,222.18 215.85,222.18 C215.85,222.18 215.79,222.15 215.79,222.15 C215.79,222.15 215.74,222.12 215.74,222.12 C215.74,222.12 215.68,222.1 215.68,222.1 C215.68,222.1 215.63,222.06 215.63,222.06 C215.63,222.06 215.57,222.03 215.57,222.03 C215.57,222.03 215.52,222 215.52,222 C215.52,222 215.46,221.97 215.46,221.97 C215.46,221.97 215.41,221.94 215.41,221.94 C215.41,221.94 215.36,221.9 215.36,221.9 C215.36,221.9 215.31,221.87 215.31,221.87 C215.31,221.87 215.25,221.83 215.25,221.83 C215.25,221.83 215.2,221.79 215.2,221.79 C215.2,221.79 215.15,221.76 215.15,221.76 C215.15,221.76 215.1,221.72 215.1,221.72 C215.1,221.72 215.05,221.68 215.05,221.68 C215.05,221.68 215,221.64 215,221.64 C215,221.64 214.96,221.6 214.96,221.6 C214.96,221.6 214.91,221.56 214.91,221.56 C214.91,221.56 214.86,221.52 214.86,221.52 C214.86,221.52 214.81,221.48 214.81,221.48 C214.81,221.48 214.77,221.43 214.77,221.43 C214.77,221.43 214.73,221.39 214.73,221.39 C214.73,221.39 214.68,221.34 214.68,221.34 C214.68,221.34 214.64,221.3 214.64,221.3 C214.64,221.3 214.59,221.25 214.59,221.25 C214.59,221.25 214.55,221.2 214.55,221.2 C214.55,221.2 214.51,221.15 214.51,221.15 C214.51,221.15 214.47,221.11 214.47,221.11 C214.47,221.11 214.43,221.06 214.43,221.06 C214.43,221.06 214.39,221.01 214.39,221.01 C214.39,221.01 214.35,220.96 214.35,220.96 C214.35,220.96 214.31,220.91 214.31,220.91 C214.31,220.91 214.28,220.86 214.28,220.86 C214.28,220.86 214.25,220.81 214.25,220.81 C214.25,220.81 214.21,220.75 214.21,220.75 C214.21,220.75 214.18,220.7 214.18,220.7 C214.18,220.7 214.14,220.65 214.14,220.65 C214.14,220.65 214.11,220.59 214.11,220.59 C214.11,220.59 214.08,220.54 214.08,220.54 C214.08,220.54 214.05,220.48 214.05,220.48 C214.05,220.48 214.02,220.43 214.02,220.43 C214.02,220.43 213.99,220.37 213.99,220.37 C213.99,220.37 213.96,220.32 213.96,220.32 C213.96,220.32 213.93,220.26 213.93,220.26 C213.93,220.26 213.91,220.2 213.91,220.2 C213.91,220.2 213.88,220.14 213.88,220.14 C213.88,220.14 213.86,220.09 213.86,220.09 C213.86,220.09 213.83,220.03 213.83,220.03 C213.83,220.03 213.81,219.97 213.81,219.97 C213.81,219.97 213.79,219.91 213.79,219.91 C213.79,219.91 213.77,219.85 213.77,219.85 C213.77,219.85 213.75,219.79 213.75,219.79 C213.75,219.79 213.73,219.73 213.73,219.73 C213.73,219.73 213.71,219.67 213.71,219.67 C213.71,219.67 213.69,219.61 213.69,219.61 C213.69,219.61 213.68,219.55 213.68,219.55 C213.68,219.55 213.66,219.49 213.66,219.49 C213.66,219.49 213.65,219.43 213.65,219.43 C213.65,219.43 213.64,219.37 213.64,219.37 C213.64,219.37 213.62,219.31 213.62,219.31 C213.62,219.31 213.61,219.24 213.61,219.24 C213.61,219.24 213.6,219.18 213.6,219.18 C213.6,219.18 213.59,219.12 213.59,219.12 C213.59,219.12 213.58,219.06 213.58,219.06 C213.58,219.06 213.57,218.99 213.57,218.99 C213.57,218.99 213.57,218.93 213.57,218.93 C213.57,218.93 213.56,218.87 213.56,218.87 C213.56,218.87 213.56,218.81 213.56,218.81 C213.56,218.81 213.56,218.74 213.56,218.74 C213.56,218.74 213.56,218.68 213.56,218.68 C213.56,218.68 213.55,218.62 213.55,218.62 C213.55,218.62 213.55,218.55 213.55,218.55 C213.55,218.55 213.55,218.49 213.55,218.49 C213.55,218.49 213.56,218.43 213.56,218.43 C213.56,218.43 213.56,218.37 213.56,218.37 C213.56,218.37 213.56,218.3 213.56,218.3 C213.56,218.3 213.56,218.24 213.56,218.24 C213.56,218.24 213.57,218.18 213.57,218.18 C213.57,218.18 213.57,218.12 213.57,218.12 C213.57,218.12 213.58,218.05 213.58,218.05 C213.58,218.05 213.59,217.99 213.59,217.99 C213.59,217.99 213.6,217.93 213.6,217.93 C213.6,217.93 213.61,217.87 213.61,217.87 C213.61,217.87 213.62,217.8 213.62,217.8 C213.62,217.8 213.63,217.74 213.63,217.74 C213.63,217.74 213.65,217.68 213.65,217.68 C213.65,217.68 213.66,217.62 213.66,217.62 C213.66,217.62 213.68,217.56 213.68,217.56 C213.68,217.56 213.69,217.5 213.69,217.5 C213.69,217.5 213.71,217.44 213.71,217.44 C213.71,217.44 213.73,217.38 213.73,217.38 C213.73,217.38 213.75,217.32 213.75,217.32 C213.75,217.32 213.77,217.26 213.77,217.26 C213.77,217.26 213.79,217.2 213.79,217.2 C213.79,217.2 213.81,217.14 213.81,217.14 C213.81,217.14 213.83,217.08 213.83,217.08 C213.83,217.08 213.85,217.02 213.85,217.02 C213.85,217.02 213.88,216.96 213.88,216.96 C213.88,216.96 213.91,216.91 213.91,216.91 C213.91,216.91 213.93,216.85 213.93,216.85 C213.93,216.85 213.96,216.79 213.96,216.79 C213.96,216.79 213.99,216.74 213.99,216.74 C213.99,216.74 214.02,216.68 214.02,216.68 C214.02,216.68 214.05,216.63 214.05,216.63 C214.05,216.63 214.08,216.57 214.08,216.57 C214.08,216.57 214.11,216.52 214.11,216.52 C214.11,216.52 214.14,216.46 214.14,216.46 C214.14,216.46 214.17,216.41 214.17,216.41 C214.17,216.41 214.21,216.36 214.21,216.36 C214.21,216.36 214.24,216.3 214.24,216.3 C214.24,216.3 214.28,216.25 214.28,216.25 C214.28,216.25 214.32,216.2 214.32,216.2 C214.32,216.2 214.35,216.15 214.35,216.15 C214.35,216.15 214.39,216.1 214.39,216.1 C214.39,216.1 214.43,216.05 214.43,216.05 C214.43,216.05 214.47,216 214.47,216 C214.47,216 214.51,215.96 214.51,215.96 C214.51,215.96 214.55,215.91 214.55,215.91 C214.55,215.91 214.59,215.86 214.59,215.86 C214.59,215.86 214.64,215.81 214.64,215.81 C214.64,215.81 214.68,215.77 214.68,215.77 C214.68,215.77 214.73,215.72 214.73,215.72 C214.73,215.72 214.77,215.68 214.77,215.68 C214.77,215.68 214.82,215.64 214.82,215.64 C214.82,215.64 214.86,215.59 214.86,215.59 C214.86,215.59 214.91,215.55 214.91,215.55 C214.91,215.55 214.96,215.51 214.96,215.51 C214.96,215.51 215,215.47 215,215.47 C215,215.47 215.05,215.43 215.05,215.43 C215.05,215.43 215.1,215.39 215.1,215.39 C215.1,215.39 215.15,215.35 215.15,215.35 C215.15,215.35 215.2,215.31 215.2,215.31 C215.2,215.31 215.25,215.28 215.25,215.28 C215.25,215.28 215.31,215.24 215.31,215.24 C215.31,215.24 215.36,215.21 215.36,215.21 C215.36,215.21 215.41,215.17 215.41,215.17 C215.41,215.17 215.46,215.14 215.46,215.14 C215.46,215.14 215.52,215.11 215.52,215.11 C215.52,215.11 215.57,215.08 215.57,215.08 C215.57,215.08 215.63,215.05 215.63,215.05 C215.63,215.05 215.68,215.02 215.68,215.02 C215.68,215.02 215.74,214.99 215.74,214.99 C215.74,214.99 215.79,214.96 215.79,214.96 C215.79,214.96 215.85,214.93 215.85,214.93 C215.85,214.93 215.91,214.9 215.91,214.9 C215.91,214.9 215.97,214.88 215.97,214.88 C215.97,214.88 216.02,214.86 216.02,214.86 C216.02,214.86 216.08,214.83 216.08,214.83 C216.08,214.83 216.14,214.81 216.14,214.81 C216.14,214.81 216.2,214.78 216.2,214.78 C216.2,214.78 216.26,214.77 216.26,214.77 C216.26,214.77 216.32,214.75 216.32,214.75 C216.32,214.75 216.38,214.73 216.38,214.73 C216.38,214.73 216.44,214.71 216.44,214.71 C216.44,214.71 216.5,214.69 216.5,214.69 C216.5,214.69 216.56,214.67 216.56,214.67 C216.56,214.67 216.62,214.66 216.62,214.66 C216.62,214.66 216.68,214.65 216.68,214.65 C216.68,214.65 216.74,214.63 216.74,214.63 C216.74,214.63 216.81,214.62 216.81,214.62 C216.81,214.62 216.87,214.61 216.87,214.61 C216.87,214.61 216.93,214.6 216.93,214.6 C216.93,214.6 216.99,214.59 216.99,214.59 C216.99,214.59 217.05,214.58 217.05,214.58 C217.05,214.58 217.12,214.57 217.12,214.57 C217.12,214.57 217.18,214.57 217.18,214.57 C217.18,214.57 217.24,214.56 217.24,214.56 C217.24,214.56 217.3,214.56 217.3,214.56 C217.3,214.56 217.37,214.56 217.37,214.56 C217.37,214.56 217.43,214.55 217.43,214.55 C217.43,214.55 217.49,214.55 217.49,214.55 C217.49,214.55 217.56,214.55 217.56,214.55 C217.56,214.55 217.62,214.55 217.62,214.55c " android:valueTo="M217.78 201.58 C217.78,201.58 218.07,201.62 218.07,201.62 C218.07,201.62 218.35,201.69 218.35,201.69 C218.35,201.69 218.63,201.78 218.63,201.78 C218.63,201.78 218.89,201.9 218.89,201.9 C218.89,201.9 219.14,202.04 219.14,202.04 C219.14,202.04 219.38,202.21 219.38,202.21 C219.38,202.21 219.59,202.41 219.59,202.41 C219.59,202.41 219.78,202.62 219.78,202.62 C219.78,202.62 219.95,202.86 219.95,202.86 C219.95,202.86 220.11,203.1 220.11,203.1 C220.11,203.1 220.26,203.35 220.26,203.35 C220.26,203.35 220.41,203.6 220.41,203.6 C220.41,203.6 220.55,203.85 220.55,203.85 C220.55,203.85 220.7,204.1 220.7,204.1 C220.7,204.1 220.85,204.35 220.85,204.35 C220.85,204.35 221,204.59 221,204.59 C221,204.59 221.15,204.84 221.15,204.84 C221.15,204.84 221.3,205.09 221.3,205.09 C221.3,205.09 221.46,205.33 221.46,205.33 C221.46,205.33 221.65,205.55 221.65,205.55 C221.65,205.55 221.86,205.75 221.86,205.75 C221.86,205.75 222.09,205.93 222.09,205.93 C222.09,205.93 222.33,206.09 222.33,206.09 C222.33,206.09 222.59,206.22 222.59,206.22 C222.59,206.22 222.86,206.32 222.86,206.32 C222.86,206.32 223.14,206.4 223.14,206.4 C223.14,206.4 223.42,206.45 223.42,206.45 C223.42,206.45 223.71,206.46 223.71,206.46 C223.71,206.46 224,206.45 224,206.45 C224,206.45 224.29,206.41 224.29,206.41 C224.29,206.41 224.57,206.35 224.57,206.35 C224.57,206.35 224.85,206.28 224.85,206.28 C224.85,206.28 225.13,206.21 225.13,206.21 C225.13,206.21 225.41,206.14 225.41,206.14 C225.41,206.14 225.7,206.07 225.7,206.07 C225.7,206.07 225.98,206 225.98,206 C225.98,206 226.26,205.93 226.26,205.93 C226.26,205.93 226.54,205.86 226.54,205.86 C226.54,205.86 226.82,205.78 226.82,205.78 C226.82,205.78 227.1,205.73 227.1,205.73 C227.1,205.73 227.39,205.71 227.39,205.71 C227.39,205.71 227.68,205.7 227.68,205.7 C227.68,205.7 227.97,205.73 227.97,205.73 C227.97,205.73 228.25,205.79 228.25,205.79 C228.25,205.79 228.53,205.88 228.53,205.88 C228.53,205.88 228.79,206 228.79,206 C228.79,206 229.04,206.14 229.04,206.14 C229.04,206.14 229.28,206.31 229.28,206.31 C229.28,206.31 229.5,206.49 229.5,206.49 C229.5,206.49 229.7,206.7 229.7,206.7 C229.7,206.7 229.88,206.93 229.88,206.93 C229.88,206.93 230.03,207.18 230.03,207.18 C230.03,207.18 230.16,207.44 230.16,207.44 C230.16,207.44 230.26,207.71 230.26,207.71 C230.26,207.71 230.34,207.99 230.34,207.99 C230.34,207.99 230.38,208.27 230.38,208.27 C230.38,208.27 230.39,208.56 230.39,208.56 C230.39,208.56 230.38,208.85 230.38,208.85 C230.38,208.85 230.33,209.14 230.33,209.14 C230.33,209.14 230.27,209.42 230.27,209.42 C230.27,209.42 230.2,209.7 230.2,209.7 C230.2,209.7 230.13,209.98 230.13,209.98 C230.13,209.98 230.06,210.26 230.06,210.26 C230.06,210.26 229.99,210.55 229.99,210.55 C229.99,210.55 229.92,210.83 229.92,210.83 C229.92,210.83 229.85,211.11 229.85,211.11 C229.85,211.11 229.78,211.39 229.78,211.39 C229.78,211.39 229.71,211.67 229.71,211.67 C229.71,211.67 229.66,211.95 229.66,211.95 C229.66,211.95 229.63,212.24 229.63,212.24 C229.63,212.24 229.64,212.53 229.64,212.53 C229.64,212.53 229.67,212.82 229.67,212.82 C229.67,212.82 229.73,213.1 229.73,213.1 C229.73,213.1 229.82,213.38 229.82,213.38 C229.82,213.38 229.94,213.64 229.94,213.64 C229.94,213.64 230.08,213.89 230.08,213.89 C230.08,213.89 230.25,214.13 230.25,214.13 C230.25,214.13 230.44,214.35 230.44,214.35 C230.44,214.35 230.66,214.54 230.66,214.54 C230.66,214.54 230.89,214.72 230.89,214.72 C230.89,214.72 231.13,214.87 231.13,214.87 C231.13,214.87 231.38,215.02 231.38,215.02 C231.38,215.02 231.63,215.17 231.63,215.17 C231.63,215.17 231.88,215.32 231.88,215.32 C231.88,215.32 232.13,215.47 232.13,215.47 C232.13,215.47 232.38,215.62 232.38,215.62 C232.38,215.62 232.62,215.77 232.62,215.77 C232.62,215.77 232.87,215.91 232.87,215.91 C232.87,215.91 233.12,216.06 233.12,216.06 C233.12,216.06 233.36,216.23 233.36,216.23 C233.36,216.23 233.58,216.41 233.58,216.41 C233.58,216.41 233.79,216.62 233.79,216.62 C233.79,216.62 233.97,216.84 233.97,216.84 C233.97,216.84 234.13,217.08 234.13,217.08 C234.13,217.08 234.26,217.34 234.26,217.34 C234.26,217.34 234.36,217.61 234.36,217.61 C234.36,217.61 234.44,217.89 234.44,217.89 C234.44,217.89 234.49,218.17 234.49,218.17 C234.49,218.17 234.52,218.46 234.52,218.46 C234.52,218.46 234.51,218.75 234.51,218.75 C234.51,218.75 234.47,219.04 234.47,219.04 C234.47,219.04 234.41,219.32 234.41,219.32 C234.41,219.32 234.31,219.59 234.31,219.59 C234.31,219.59 234.19,219.86 234.19,219.86 C234.19,219.86 234.05,220.11 234.05,220.11 C234.05,220.11 233.88,220.34 233.88,220.34 C233.88,220.34 233.68,220.56 233.68,220.56 C233.68,220.56 233.47,220.75 233.47,220.75 C233.47,220.75 233.23,220.92 233.23,220.92 C233.23,220.92 232.99,221.08 232.99,221.08 C232.99,221.08 232.74,221.22 232.74,221.22 C232.74,221.22 232.49,221.37 232.49,221.37 C232.49,221.37 232.25,221.52 232.25,221.52 C232.25,221.52 232,221.67 232,221.67 C232,221.67 231.75,221.82 231.75,221.82 C231.75,221.82 231.5,221.97 231.5,221.97 C231.5,221.97 231.25,222.12 231.25,222.12 C231.25,222.12 231,222.27 231,222.27 C231,222.27 230.76,222.43 230.76,222.43 C230.76,222.43 230.54,222.62 230.54,222.62 C230.54,222.62 230.34,222.83 230.34,222.83 C230.34,222.83 230.16,223.05 230.16,223.05 C230.16,223.05 230.01,223.3 230.01,223.3 C230.01,223.3 229.87,223.56 229.87,223.56 C229.87,223.56 229.77,223.83 229.77,223.83 C229.77,223.83 229.7,224.11 229.7,224.11 C229.7,224.11 229.65,224.39 229.65,224.39 C229.65,224.39 229.63,224.68 229.63,224.68 C229.63,224.68 229.64,224.97 229.64,224.97 C229.64,224.97 229.68,225.26 229.68,225.26 C229.68,225.26 229.75,225.54 229.75,225.54 C229.75,225.54 229.82,225.82 229.82,225.82 C229.82,225.82 229.89,226.1 229.89,226.1 C229.89,226.1 229.96,226.38 229.96,226.38 C229.96,226.38 230.03,226.66 230.03,226.66 C230.03,226.66 230.1,226.94 230.1,226.94 C230.1,226.94 230.17,227.22 230.17,227.22 C230.17,227.22 230.24,227.51 230.24,227.51 C230.24,227.51 230.31,227.79 230.31,227.79 C230.31,227.79 230.36,228.07 230.36,228.07 C230.36,228.07 230.39,228.36 230.39,228.36 C230.39,228.36 230.39,228.65 230.39,228.65 C230.39,228.65 230.36,228.94 230.36,228.94 C230.36,228.94 230.3,229.22 230.3,229.22 C230.3,229.22 230.21,229.5 230.21,229.5 C230.21,229.5 230.1,229.76 230.1,229.76 C230.1,229.76 229.95,230.01 229.95,230.01 C229.95,230.01 229.79,230.25 229.79,230.25 C229.79,230.25 229.6,230.47 229.6,230.47 C229.6,230.47 229.39,230.67 229.39,230.67 C229.39,230.67 229.16,230.85 229.16,230.85 C229.16,230.85 228.91,231 228.91,231 C228.91,231 228.66,231.13 228.66,231.13 C228.66,231.13 228.38,231.23 228.38,231.23 C228.38,231.23 228.11,231.3 228.11,231.3 C228.11,231.3 227.82,231.35 227.82,231.35 C227.82,231.35 227.53,231.36 227.53,231.36 C227.53,231.36 227.24,231.35 227.24,231.35 C227.24,231.35 226.96,231.3 226.96,231.3 C226.96,231.3 226.67,231.24 226.67,231.24 C226.67,231.24 226.39,231.17 226.39,231.17 C226.39,231.17 226.11,231.1 226.11,231.1 C226.11,231.1 225.83,231.03 225.83,231.03 C225.83,231.03 225.55,230.96 225.55,230.96 C225.55,230.96 225.27,230.89 225.27,230.89 C225.27,230.89 224.99,230.82 224.99,230.82 C224.99,230.82 224.71,230.75 224.71,230.75 C224.71,230.75 224.42,230.68 224.42,230.68 C224.42,230.68 224.14,230.62 224.14,230.62 C224.14,230.62 223.85,230.6 223.85,230.6 C223.85,230.6 223.56,230.6 223.56,230.6 C223.56,230.6 223.27,230.64 223.27,230.64 C223.27,230.64 222.99,230.7 222.99,230.7 C222.99,230.7 222.72,230.79 222.72,230.79 C222.72,230.79 222.45,230.91 222.45,230.91 C222.45,230.91 222.2,231.05 222.2,231.05 C222.2,231.05 221.96,231.22 221.96,231.22 C221.96,231.22 221.75,231.41 221.75,231.41 C221.75,231.41 221.55,231.62 221.55,231.62 C221.55,231.62 221.38,231.85 221.38,231.85 C221.38,231.85 221.22,232.1 221.22,232.1 C221.22,232.1 221.07,232.35 221.07,232.35 C221.07,232.35 220.92,232.6 220.92,232.6 C220.92,232.6 220.77,232.85 220.77,232.85 C220.77,232.85 220.63,233.09 220.63,233.09 C220.63,233.09 220.48,233.34 220.48,233.34 C220.48,233.34 220.33,233.59 220.33,233.59 C220.33,233.59 220.18,233.84 220.18,233.84 C220.18,233.84 220.03,234.09 220.03,234.09 C220.03,234.09 219.87,234.33 219.87,234.33 C219.87,234.33 219.68,234.55 219.68,234.55 C219.68,234.55 219.48,234.75 219.48,234.75 C219.48,234.75 219.25,234.94 219.25,234.94 C219.25,234.94 219.01,235.1 219.01,235.1 C219.01,235.1 218.75,235.23 218.75,235.23 C218.75,235.23 218.48,235.33 218.48,235.33 C218.48,235.33 218.21,235.41 218.21,235.41 C218.21,235.41 217.92,235.46 217.92,235.46 C217.92,235.46 217.63,235.48 217.63,235.48 C217.63,235.48 217.34,235.48 217.34,235.48 C217.34,235.48 217.06,235.44 217.06,235.44 C217.06,235.44 216.77,235.37 216.77,235.37 C216.77,235.37 216.5,235.28 216.5,235.28 C216.5,235.28 216.24,235.16 216.24,235.16 C216.24,235.16 215.99,235.02 215.99,235.02 C215.99,235.02 215.75,234.85 215.75,234.85 C215.75,234.85 215.54,234.65 215.54,234.65 C215.54,234.65 215.34,234.44 215.34,234.44 C215.34,234.44 215.17,234.2 215.17,234.2 C215.17,234.2 215.02,233.96 215.02,233.96 C215.02,233.96 214.87,233.71 214.87,233.71 C214.87,233.71 214.72,233.46 214.72,233.46 C214.72,233.46 214.57,233.21 214.57,233.21 C214.57,233.21 214.42,232.96 214.42,232.96 C214.42,232.96 214.27,232.72 214.27,232.72 C214.27,232.72 214.12,232.47 214.12,232.47 C214.12,232.47 213.98,232.22 213.98,232.22 C213.98,232.22 213.83,231.97 213.83,231.97 C213.83,231.97 213.66,231.73 213.66,231.73 C213.66,231.73 213.48,231.51 213.48,231.51 C213.48,231.51 213.27,231.31 213.27,231.31 C213.27,231.31 213.04,231.13 213.04,231.13 C213.04,231.13 212.8,230.97 212.8,230.97 C212.8,230.97 212.54,230.84 212.54,230.84 C212.54,230.84 212.27,230.74 212.27,230.74 C212.27,230.74 211.99,230.66 211.99,230.66 C211.99,230.66 211.7,230.62 211.7,230.62 C211.7,230.62 211.41,230.6 211.41,230.6 C211.41,230.6 211.12,230.61 211.12,230.61 C211.12,230.61 210.84,230.65 210.84,230.65 C210.84,230.65 210.56,230.71 210.56,230.71 C210.56,230.71 210.27,230.78 210.27,230.78 C210.27,230.78 209.99,230.85 209.99,230.85 C209.99,230.85 209.71,230.92 209.71,230.92 C209.71,230.92 209.43,230.99 209.43,230.99 C209.43,230.99 209.15,231.06 209.15,231.06 C209.15,231.06 208.87,231.14 208.87,231.14 C208.87,231.14 208.59,231.21 208.59,231.21 C208.59,231.21 208.31,231.28 208.31,231.28 C208.31,231.28 208.02,231.33 208.02,231.33 C208.02,231.33 207.73,231.36 207.73,231.36 C207.73,231.36 207.45,231.36 207.45,231.36 C207.45,231.36 207.16,231.33 207.16,231.33 C207.16,231.33 206.87,231.27 206.87,231.27 C206.87,231.27 206.6,231.18 206.6,231.18 C206.6,231.18 206.33,231.06 206.33,231.06 C206.33,231.06 206.08,230.92 206.08,230.92 C206.08,230.92 205.85,230.76 205.85,230.76 C205.85,230.76 205.62,230.57 205.62,230.57 C205.62,230.57 205.42,230.36 205.42,230.36 C205.42,230.36 205.25,230.13 205.25,230.13 C205.25,230.13 205.1,229.88 205.1,229.88 C205.1,229.88 204.97,229.62 204.97,229.62 C204.97,229.62 204.87,229.35 204.87,229.35 C204.87,229.35 204.79,229.07 204.79,229.07 C204.79,229.07 204.74,228.79 204.74,228.79 C204.74,228.79 204.73,228.5 204.73,228.5 C204.73,228.5 204.74,228.21 204.74,228.21 C204.74,228.21 204.79,227.92 204.79,227.92 C204.79,227.92 204.85,227.64 204.85,227.64 C204.85,227.64 204.92,227.36 204.92,227.36 C204.92,227.36 204.99,227.08 204.99,227.08 C204.99,227.08 205.06,226.8 205.06,226.8 C205.06,226.8 205.13,226.52 205.13,226.52 C205.13,226.52 205.21,226.24 205.21,226.24 C205.21,226.24 205.28,225.96 205.28,225.96 C205.28,225.96 205.35,225.68 205.35,225.68 C205.35,225.68 205.42,225.39 205.42,225.39 C205.42,225.39 205.47,225.11 205.47,225.11 C205.47,225.11 205.49,224.82 205.49,224.82 C205.49,224.82 205.49,224.53 205.49,224.53 C205.49,224.53 205.46,224.24 205.46,224.24 C205.46,224.24 205.39,223.96 205.39,223.96 C205.39,223.96 205.3,223.69 205.3,223.69 C205.3,223.69 205.19,223.42 205.19,223.42 C205.19,223.42 205.04,223.17 205.04,223.17 C205.04,223.17 204.87,222.93 204.87,222.93 C204.87,222.93 204.68,222.71 204.68,222.71 C204.68,222.71 204.47,222.52 204.47,222.52 C204.47,222.52 204.24,222.34 204.24,222.34 C204.24,222.34 203.99,222.19 203.99,222.19 C203.99,222.19 203.75,222.04 203.75,222.04 C203.75,222.04 203.5,221.89 203.5,221.89 C203.5,221.89 203.25,221.74 203.25,221.74 C203.25,221.74 203,221.59 203,221.59 C203,221.59 202.75,221.45 202.75,221.45 C202.75,221.45 202.5,221.3 202.5,221.3 C202.5,221.3 202.25,221.15 202.25,221.15 C202.25,221.15 202.01,221 202.01,221 C202.01,221 201.77,220.83 201.77,220.83 C201.77,220.83 201.54,220.65 201.54,220.65 C201.54,220.65 201.34,220.45 201.34,220.45 C201.34,220.45 201.16,220.22 201.16,220.22 C201.16,220.22 201,219.98 201,219.98 C201,219.98 200.87,219.72 200.87,219.72 C200.87,219.72 200.76,219.45 200.76,219.45 C200.76,219.45 200.68,219.18 200.68,219.18 C200.68,219.18 200.63,218.89 200.63,218.89 C200.63,218.89 200.61,218.6 200.61,218.6 C200.61,218.6 200.61,218.31 200.61,218.31 C200.61,218.31 200.65,218.02 200.65,218.02 C200.65,218.02 200.72,217.74 200.72,217.74 C200.72,217.74 200.81,217.47 200.81,217.47 C200.81,217.47 200.93,217.21 200.93,217.21 C200.93,217.21 201.07,216.96 201.07,216.96 C201.07,216.96 201.24,216.72 201.24,216.72 C201.24,216.72 201.44,216.51 201.44,216.51 C201.44,216.51 201.65,216.31 201.65,216.31 C201.65,216.31 201.89,216.14 201.89,216.14 C201.89,216.14 202.13,215.99 202.13,215.99 C202.13,215.99 202.38,215.84 202.38,215.84 C202.38,215.84 202.63,215.69 202.63,215.69 C202.63,215.69 202.88,215.54 202.88,215.54 C202.88,215.54 203.13,215.39 203.13,215.39 C203.13,215.39 203.37,215.24 203.37,215.24 C203.37,215.24 203.62,215.09 203.62,215.09 C203.62,215.09 203.87,214.94 203.87,214.94 C203.87,214.94 204.12,214.79 204.12,214.79 C204.12,214.79 204.36,214.63 204.36,214.63 C204.36,214.63 204.58,214.45 204.58,214.45 C204.58,214.45 204.78,214.24 204.78,214.24 C204.78,214.24 204.96,214.01 204.96,214.01 C204.96,214.01 205.12,213.77 205.12,213.77 C205.12,213.77 205.25,213.51 205.25,213.51 C205.25,213.51 205.35,213.24 205.35,213.24 C205.35,213.24 205.43,212.96 205.43,212.96 C205.43,212.96 205.48,212.67 205.48,212.67 C205.48,212.67 205.5,212.38 205.5,212.38 C205.5,212.38 205.49,212.09 205.49,212.09 C205.49,212.09 205.44,211.81 205.44,211.81 C205.44,211.81 205.38,211.52 205.38,211.52 C205.38,211.52 205.31,211.24 205.31,211.24 C205.31,211.24 205.24,210.96 205.24,210.96 C205.24,210.96 205.17,210.68 205.17,210.68 C205.17,210.68 205.1,210.4 205.1,210.4 C205.1,210.4 205.03,210.12 205.03,210.12 C205.03,210.12 204.96,209.84 204.96,209.84 C204.96,209.84 204.89,209.56 204.89,209.56 C204.89,209.56 204.82,209.28 204.82,209.28 C204.82,209.28 204.76,208.99 204.76,208.99 C204.76,208.99 204.74,208.7 204.74,208.7 C204.74,208.7 204.74,208.42 204.74,208.42 C204.74,208.42 204.76,208.13 204.76,208.13 C204.76,208.13 204.82,207.84 204.82,207.84 C204.82,207.84 204.91,207.57 204.91,207.57 C204.91,207.57 205.03,207.3 205.03,207.3 C205.03,207.3 205.17,207.05 205.17,207.05 C205.17,207.05 205.34,206.81 205.34,206.81 C205.34,206.81 205.52,206.59 205.52,206.59 C205.52,206.59 205.73,206.39 205.73,206.39 C205.73,206.39 205.96,206.22 205.96,206.22 C205.96,206.22 206.21,206.06 206.21,206.06 C206.21,206.06 206.47,205.94 206.47,205.94 C206.47,205.94 206.74,205.83 206.74,205.83 C206.74,205.83 207.02,205.76 207.02,205.76 C207.02,205.76 207.3,205.71 207.3,205.71 C207.3,205.71 207.59,205.7 207.59,205.7 C207.59,205.7 207.88,205.71 207.88,205.71 C207.88,205.71 208.17,205.76 208.17,205.76 C208.17,205.76 208.45,205.82 208.45,205.82 C208.45,205.82 208.73,205.89 208.73,205.89 C208.73,205.89 209.01,205.96 209.01,205.96 C209.01,205.96 209.29,206.03 209.29,206.03 C209.29,206.03 209.57,206.1 209.57,206.1 C209.57,206.1 209.85,206.17 209.85,206.17 C209.85,206.17 210.14,206.24 210.14,206.24 C210.14,206.24 210.42,206.31 210.42,206.31 C210.42,206.31 210.7,206.38 210.7,206.38 C210.7,206.38 210.98,206.44 210.98,206.44 C210.98,206.44 211.27,206.46 211.27,206.46 C211.27,206.46 211.56,206.46 211.56,206.46 C211.56,206.46 211.85,206.43 211.85,206.43 C211.85,206.43 212.13,206.36 212.13,206.36 C212.13,206.36 212.41,206.27 212.41,206.27 C212.41,206.27 212.67,206.15 212.67,206.15 C212.67,206.15 212.92,206.01 212.92,206.01 C212.92,206.01 213.16,205.84 213.16,205.84 C213.16,205.84 213.38,205.65 213.38,205.65 C213.38,205.65 213.57,205.44 213.57,205.44 C213.57,205.44 213.75,205.21 213.75,205.21 C213.75,205.21 213.9,204.96 213.9,204.96 C213.9,204.96 214.05,204.71 214.05,204.71 C214.05,204.71 214.2,204.47 214.2,204.47 C214.2,204.47 214.35,204.22 214.35,204.22 C214.35,204.22 214.5,203.97 214.5,203.97 C214.5,203.97 214.65,203.72 214.65,203.72 C214.65,203.72 214.8,203.47 214.8,203.47 C214.8,203.47 214.94,203.22 214.94,203.22 C214.94,203.22 215.1,202.97 215.1,202.97 C215.1,202.97 215.26,202.73 215.26,202.73 C215.26,202.73 215.44,202.51 215.44,202.51 C215.44,202.51 215.65,202.31 215.65,202.31 C215.65,202.31 215.87,202.12 215.87,202.12 C215.87,202.12 216.11,201.96 216.11,201.96 C216.11,201.96 216.37,201.83 216.37,201.83 C216.37,201.83 216.64,201.73 216.64,201.73 C216.64,201.73 216.92,201.65 216.92,201.65 C216.92,201.65 217.21,201.6 217.21,201.6 C217.21,201.6 217.49,201.58 217.49,201.58 C217.49,201.58 217.78,201.58 217.78,201.58c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="283" android:startOffset="67" android:valueFrom="M217.78 201.58 C217.78,201.58 218.07,201.62 218.07,201.62 C218.07,201.62 218.35,201.69 218.35,201.69 C218.35,201.69 218.63,201.78 218.63,201.78 C218.63,201.78 218.89,201.9 218.89,201.9 C218.89,201.9 219.14,202.04 219.14,202.04 C219.14,202.04 219.38,202.21 219.38,202.21 C219.38,202.21 219.59,202.41 219.59,202.41 C219.59,202.41 219.78,202.62 219.78,202.62 C219.78,202.62 219.95,202.86 219.95,202.86 C219.95,202.86 220.11,203.1 220.11,203.1 C220.11,203.1 220.26,203.35 220.26,203.35 C220.26,203.35 220.41,203.6 220.41,203.6 C220.41,203.6 220.55,203.85 220.55,203.85 C220.55,203.85 220.7,204.1 220.7,204.1 C220.7,204.1 220.85,204.35 220.85,204.35 C220.85,204.35 221,204.59 221,204.59 C221,204.59 221.15,204.84 221.15,204.84 C221.15,204.84 221.3,205.09 221.3,205.09 C221.3,205.09 221.46,205.33 221.46,205.33 C221.46,205.33 221.65,205.55 221.65,205.55 C221.65,205.55 221.86,205.75 221.86,205.75 C221.86,205.75 222.09,205.93 222.09,205.93 C222.09,205.93 222.33,206.09 222.33,206.09 C222.33,206.09 222.59,206.22 222.59,206.22 C222.59,206.22 222.86,206.32 222.86,206.32 C222.86,206.32 223.14,206.4 223.14,206.4 C223.14,206.4 223.42,206.45 223.42,206.45 C223.42,206.45 223.71,206.46 223.71,206.46 C223.71,206.46 224,206.45 224,206.45 C224,206.45 224.29,206.41 224.29,206.41 C224.29,206.41 224.57,206.35 224.57,206.35 C224.57,206.35 224.85,206.28 224.85,206.28 C224.85,206.28 225.13,206.21 225.13,206.21 C225.13,206.21 225.41,206.14 225.41,206.14 C225.41,206.14 225.7,206.07 225.7,206.07 C225.7,206.07 225.98,206 225.98,206 C225.98,206 226.26,205.93 226.26,205.93 C226.26,205.93 226.54,205.86 226.54,205.86 C226.54,205.86 226.82,205.78 226.82,205.78 C226.82,205.78 227.1,205.73 227.1,205.73 C227.1,205.73 227.39,205.71 227.39,205.71 C227.39,205.71 227.68,205.7 227.68,205.7 C227.68,205.7 227.97,205.73 227.97,205.73 C227.97,205.73 228.25,205.79 228.25,205.79 C228.25,205.79 228.53,205.88 228.53,205.88 C228.53,205.88 228.79,206 228.79,206 C228.79,206 229.04,206.14 229.04,206.14 C229.04,206.14 229.28,206.31 229.28,206.31 C229.28,206.31 229.5,206.49 229.5,206.49 C229.5,206.49 229.7,206.7 229.7,206.7 C229.7,206.7 229.88,206.93 229.88,206.93 C229.88,206.93 230.03,207.18 230.03,207.18 C230.03,207.18 230.16,207.44 230.16,207.44 C230.16,207.44 230.26,207.71 230.26,207.71 C230.26,207.71 230.34,207.99 230.34,207.99 C230.34,207.99 230.38,208.27 230.38,208.27 C230.38,208.27 230.39,208.56 230.39,208.56 C230.39,208.56 230.38,208.85 230.38,208.85 C230.38,208.85 230.33,209.14 230.33,209.14 C230.33,209.14 230.27,209.42 230.27,209.42 C230.27,209.42 230.2,209.7 230.2,209.7 C230.2,209.7 230.13,209.98 230.13,209.98 C230.13,209.98 230.06,210.26 230.06,210.26 C230.06,210.26 229.99,210.55 229.99,210.55 C229.99,210.55 229.92,210.83 229.92,210.83 C229.92,210.83 229.85,211.11 229.85,211.11 C229.85,211.11 229.78,211.39 229.78,211.39 C229.78,211.39 229.71,211.67 229.71,211.67 C229.71,211.67 229.66,211.95 229.66,211.95 C229.66,211.95 229.63,212.24 229.63,212.24 C229.63,212.24 229.64,212.53 229.64,212.53 C229.64,212.53 229.67,212.82 229.67,212.82 C229.67,212.82 229.73,213.1 229.73,213.1 C229.73,213.1 229.82,213.38 229.82,213.38 C229.82,213.38 229.94,213.64 229.94,213.64 C229.94,213.64 230.08,213.89 230.08,213.89 C230.08,213.89 230.25,214.13 230.25,214.13 C230.25,214.13 230.44,214.35 230.44,214.35 C230.44,214.35 230.66,214.54 230.66,214.54 C230.66,214.54 230.89,214.72 230.89,214.72 C230.89,214.72 231.13,214.87 231.13,214.87 C231.13,214.87 231.38,215.02 231.38,215.02 C231.38,215.02 231.63,215.17 231.63,215.17 C231.63,215.17 231.88,215.32 231.88,215.32 C231.88,215.32 232.13,215.47 232.13,215.47 C232.13,215.47 232.38,215.62 232.38,215.62 C232.38,215.62 232.62,215.77 232.62,215.77 C232.62,215.77 232.87,215.91 232.87,215.91 C232.87,215.91 233.12,216.06 233.12,216.06 C233.12,216.06 233.36,216.23 233.36,216.23 C233.36,216.23 233.58,216.41 233.58,216.41 C233.58,216.41 233.79,216.62 233.79,216.62 C233.79,216.62 233.97,216.84 233.97,216.84 C233.97,216.84 234.13,217.08 234.13,217.08 C234.13,217.08 234.26,217.34 234.26,217.34 C234.26,217.34 234.36,217.61 234.36,217.61 C234.36,217.61 234.44,217.89 234.44,217.89 C234.44,217.89 234.49,218.17 234.49,218.17 C234.49,218.17 234.52,218.46 234.52,218.46 C234.52,218.46 234.51,218.75 234.51,218.75 C234.51,218.75 234.47,219.04 234.47,219.04 C234.47,219.04 234.41,219.32 234.41,219.32 C234.41,219.32 234.31,219.59 234.31,219.59 C234.31,219.59 234.19,219.86 234.19,219.86 C234.19,219.86 234.05,220.11 234.05,220.11 C234.05,220.11 233.88,220.34 233.88,220.34 C233.88,220.34 233.68,220.56 233.68,220.56 C233.68,220.56 233.47,220.75 233.47,220.75 C233.47,220.75 233.23,220.92 233.23,220.92 C233.23,220.92 232.99,221.08 232.99,221.08 C232.99,221.08 232.74,221.22 232.74,221.22 C232.74,221.22 232.49,221.37 232.49,221.37 C232.49,221.37 232.25,221.52 232.25,221.52 C232.25,221.52 232,221.67 232,221.67 C232,221.67 231.75,221.82 231.75,221.82 C231.75,221.82 231.5,221.97 231.5,221.97 C231.5,221.97 231.25,222.12 231.25,222.12 C231.25,222.12 231,222.27 231,222.27 C231,222.27 230.76,222.43 230.76,222.43 C230.76,222.43 230.54,222.62 230.54,222.62 C230.54,222.62 230.34,222.83 230.34,222.83 C230.34,222.83 230.16,223.05 230.16,223.05 C230.16,223.05 230.01,223.3 230.01,223.3 C230.01,223.3 229.87,223.56 229.87,223.56 C229.87,223.56 229.77,223.83 229.77,223.83 C229.77,223.83 229.7,224.11 229.7,224.11 C229.7,224.11 229.65,224.39 229.65,224.39 C229.65,224.39 229.63,224.68 229.63,224.68 C229.63,224.68 229.64,224.97 229.64,224.97 C229.64,224.97 229.68,225.26 229.68,225.26 C229.68,225.26 229.75,225.54 229.75,225.54 C229.75,225.54 229.82,225.82 229.82,225.82 C229.82,225.82 229.89,226.1 229.89,226.1 C229.89,226.1 229.96,226.38 229.96,226.38 C229.96,226.38 230.03,226.66 230.03,226.66 C230.03,226.66 230.1,226.94 230.1,226.94 C230.1,226.94 230.17,227.22 230.17,227.22 C230.17,227.22 230.24,227.51 230.24,227.51 C230.24,227.51 230.31,227.79 230.31,227.79 C230.31,227.79 230.36,228.07 230.36,228.07 C230.36,228.07 230.39,228.36 230.39,228.36 C230.39,228.36 230.39,228.65 230.39,228.65 C230.39,228.65 230.36,228.94 230.36,228.94 C230.36,228.94 230.3,229.22 230.3,229.22 C230.3,229.22 230.21,229.5 230.21,229.5 C230.21,229.5 230.1,229.76 230.1,229.76 C230.1,229.76 229.95,230.01 229.95,230.01 C229.95,230.01 229.79,230.25 229.79,230.25 C229.79,230.25 229.6,230.47 229.6,230.47 C229.6,230.47 229.39,230.67 229.39,230.67 C229.39,230.67 229.16,230.85 229.16,230.85 C229.16,230.85 228.91,231 228.91,231 C228.91,231 228.66,231.13 228.66,231.13 C228.66,231.13 228.38,231.23 228.38,231.23 C228.38,231.23 228.11,231.3 228.11,231.3 C228.11,231.3 227.82,231.35 227.82,231.35 C227.82,231.35 227.53,231.36 227.53,231.36 C227.53,231.36 227.24,231.35 227.24,231.35 C227.24,231.35 226.96,231.3 226.96,231.3 C226.96,231.3 226.67,231.24 226.67,231.24 C226.67,231.24 226.39,231.17 226.39,231.17 C226.39,231.17 226.11,231.1 226.11,231.1 C226.11,231.1 225.83,231.03 225.83,231.03 C225.83,231.03 225.55,230.96 225.55,230.96 C225.55,230.96 225.27,230.89 225.27,230.89 C225.27,230.89 224.99,230.82 224.99,230.82 C224.99,230.82 224.71,230.75 224.71,230.75 C224.71,230.75 224.42,230.68 224.42,230.68 C224.42,230.68 224.14,230.62 224.14,230.62 C224.14,230.62 223.85,230.6 223.85,230.6 C223.85,230.6 223.56,230.6 223.56,230.6 C223.56,230.6 223.27,230.64 223.27,230.64 C223.27,230.64 222.99,230.7 222.99,230.7 C222.99,230.7 222.72,230.79 222.72,230.79 C222.72,230.79 222.45,230.91 222.45,230.91 C222.45,230.91 222.2,231.05 222.2,231.05 C222.2,231.05 221.96,231.22 221.96,231.22 C221.96,231.22 221.75,231.41 221.75,231.41 C221.75,231.41 221.55,231.62 221.55,231.62 C221.55,231.62 221.38,231.85 221.38,231.85 C221.38,231.85 221.22,232.1 221.22,232.1 C221.22,232.1 221.07,232.35 221.07,232.35 C221.07,232.35 220.92,232.6 220.92,232.6 C220.92,232.6 220.77,232.85 220.77,232.85 C220.77,232.85 220.63,233.09 220.63,233.09 C220.63,233.09 220.48,233.34 220.48,233.34 C220.48,233.34 220.33,233.59 220.33,233.59 C220.33,233.59 220.18,233.84 220.18,233.84 C220.18,233.84 220.03,234.09 220.03,234.09 C220.03,234.09 219.87,234.33 219.87,234.33 C219.87,234.33 219.68,234.55 219.68,234.55 C219.68,234.55 219.48,234.75 219.48,234.75 C219.48,234.75 219.25,234.94 219.25,234.94 C219.25,234.94 219.01,235.1 219.01,235.1 C219.01,235.1 218.75,235.23 218.75,235.23 C218.75,235.23 218.48,235.33 218.48,235.33 C218.48,235.33 218.21,235.41 218.21,235.41 C218.21,235.41 217.92,235.46 217.92,235.46 C217.92,235.46 217.63,235.48 217.63,235.48 C217.63,235.48 217.34,235.48 217.34,235.48 C217.34,235.48 217.06,235.44 217.06,235.44 C217.06,235.44 216.77,235.37 216.77,235.37 C216.77,235.37 216.5,235.28 216.5,235.28 C216.5,235.28 216.24,235.16 216.24,235.16 C216.24,235.16 215.99,235.02 215.99,235.02 C215.99,235.02 215.75,234.85 215.75,234.85 C215.75,234.85 215.54,234.65 215.54,234.65 C215.54,234.65 215.34,234.44 215.34,234.44 C215.34,234.44 215.17,234.2 215.17,234.2 C215.17,234.2 215.02,233.96 215.02,233.96 C215.02,233.96 214.87,233.71 214.87,233.71 C214.87,233.71 214.72,233.46 214.72,233.46 C214.72,233.46 214.57,233.21 214.57,233.21 C214.57,233.21 214.42,232.96 214.42,232.96 C214.42,232.96 214.27,232.72 214.27,232.72 C214.27,232.72 214.12,232.47 214.12,232.47 C214.12,232.47 213.98,232.22 213.98,232.22 C213.98,232.22 213.83,231.97 213.83,231.97 C213.83,231.97 213.66,231.73 213.66,231.73 C213.66,231.73 213.48,231.51 213.48,231.51 C213.48,231.51 213.27,231.31 213.27,231.31 C213.27,231.31 213.04,231.13 213.04,231.13 C213.04,231.13 212.8,230.97 212.8,230.97 C212.8,230.97 212.54,230.84 212.54,230.84 C212.54,230.84 212.27,230.74 212.27,230.74 C212.27,230.74 211.99,230.66 211.99,230.66 C211.99,230.66 211.7,230.62 211.7,230.62 C211.7,230.62 211.41,230.6 211.41,230.6 C211.41,230.6 211.12,230.61 211.12,230.61 C211.12,230.61 210.84,230.65 210.84,230.65 C210.84,230.65 210.56,230.71 210.56,230.71 C210.56,230.71 210.27,230.78 210.27,230.78 C210.27,230.78 209.99,230.85 209.99,230.85 C209.99,230.85 209.71,230.92 209.71,230.92 C209.71,230.92 209.43,230.99 209.43,230.99 C209.43,230.99 209.15,231.06 209.15,231.06 C209.15,231.06 208.87,231.14 208.87,231.14 C208.87,231.14 208.59,231.21 208.59,231.21 C208.59,231.21 208.31,231.28 208.31,231.28 C208.31,231.28 208.02,231.33 208.02,231.33 C208.02,231.33 207.73,231.36 207.73,231.36 C207.73,231.36 207.45,231.36 207.45,231.36 C207.45,231.36 207.16,231.33 207.16,231.33 C207.16,231.33 206.87,231.27 206.87,231.27 C206.87,231.27 206.6,231.18 206.6,231.18 C206.6,231.18 206.33,231.06 206.33,231.06 C206.33,231.06 206.08,230.92 206.08,230.92 C206.08,230.92 205.85,230.76 205.85,230.76 C205.85,230.76 205.62,230.57 205.62,230.57 C205.62,230.57 205.42,230.36 205.42,230.36 C205.42,230.36 205.25,230.13 205.25,230.13 C205.25,230.13 205.1,229.88 205.1,229.88 C205.1,229.88 204.97,229.62 204.97,229.62 C204.97,229.62 204.87,229.35 204.87,229.35 C204.87,229.35 204.79,229.07 204.79,229.07 C204.79,229.07 204.74,228.79 204.74,228.79 C204.74,228.79 204.73,228.5 204.73,228.5 C204.73,228.5 204.74,228.21 204.74,228.21 C204.74,228.21 204.79,227.92 204.79,227.92 C204.79,227.92 204.85,227.64 204.85,227.64 C204.85,227.64 204.92,227.36 204.92,227.36 C204.92,227.36 204.99,227.08 204.99,227.08 C204.99,227.08 205.06,226.8 205.06,226.8 C205.06,226.8 205.13,226.52 205.13,226.52 C205.13,226.52 205.21,226.24 205.21,226.24 C205.21,226.24 205.28,225.96 205.28,225.96 C205.28,225.96 205.35,225.68 205.35,225.68 C205.35,225.68 205.42,225.39 205.42,225.39 C205.42,225.39 205.47,225.11 205.47,225.11 C205.47,225.11 205.49,224.82 205.49,224.82 C205.49,224.82 205.49,224.53 205.49,224.53 C205.49,224.53 205.46,224.24 205.46,224.24 C205.46,224.24 205.39,223.96 205.39,223.96 C205.39,223.96 205.3,223.69 205.3,223.69 C205.3,223.69 205.19,223.42 205.19,223.42 C205.19,223.42 205.04,223.17 205.04,223.17 C205.04,223.17 204.87,222.93 204.87,222.93 C204.87,222.93 204.68,222.71 204.68,222.71 C204.68,222.71 204.47,222.52 204.47,222.52 C204.47,222.52 204.24,222.34 204.24,222.34 C204.24,222.34 203.99,222.19 203.99,222.19 C203.99,222.19 203.75,222.04 203.75,222.04 C203.75,222.04 203.5,221.89 203.5,221.89 C203.5,221.89 203.25,221.74 203.25,221.74 C203.25,221.74 203,221.59 203,221.59 C203,221.59 202.75,221.45 202.75,221.45 C202.75,221.45 202.5,221.3 202.5,221.3 C202.5,221.3 202.25,221.15 202.25,221.15 C202.25,221.15 202.01,221 202.01,221 C202.01,221 201.77,220.83 201.77,220.83 C201.77,220.83 201.54,220.65 201.54,220.65 C201.54,220.65 201.34,220.45 201.34,220.45 C201.34,220.45 201.16,220.22 201.16,220.22 C201.16,220.22 201,219.98 201,219.98 C201,219.98 200.87,219.72 200.87,219.72 C200.87,219.72 200.76,219.45 200.76,219.45 C200.76,219.45 200.68,219.18 200.68,219.18 C200.68,219.18 200.63,218.89 200.63,218.89 C200.63,218.89 200.61,218.6 200.61,218.6 C200.61,218.6 200.61,218.31 200.61,218.31 C200.61,218.31 200.65,218.02 200.65,218.02 C200.65,218.02 200.72,217.74 200.72,217.74 C200.72,217.74 200.81,217.47 200.81,217.47 C200.81,217.47 200.93,217.21 200.93,217.21 C200.93,217.21 201.07,216.96 201.07,216.96 C201.07,216.96 201.24,216.72 201.24,216.72 C201.24,216.72 201.44,216.51 201.44,216.51 C201.44,216.51 201.65,216.31 201.65,216.31 C201.65,216.31 201.89,216.14 201.89,216.14 C201.89,216.14 202.13,215.99 202.13,215.99 C202.13,215.99 202.38,215.84 202.38,215.84 C202.38,215.84 202.63,215.69 202.63,215.69 C202.63,215.69 202.88,215.54 202.88,215.54 C202.88,215.54 203.13,215.39 203.13,215.39 C203.13,215.39 203.37,215.24 203.37,215.24 C203.37,215.24 203.62,215.09 203.62,215.09 C203.62,215.09 203.87,214.94 203.87,214.94 C203.87,214.94 204.12,214.79 204.12,214.79 C204.12,214.79 204.36,214.63 204.36,214.63 C204.36,214.63 204.58,214.45 204.58,214.45 C204.58,214.45 204.78,214.24 204.78,214.24 C204.78,214.24 204.96,214.01 204.96,214.01 C204.96,214.01 205.12,213.77 205.12,213.77 C205.12,213.77 205.25,213.51 205.25,213.51 C205.25,213.51 205.35,213.24 205.35,213.24 C205.35,213.24 205.43,212.96 205.43,212.96 C205.43,212.96 205.48,212.67 205.48,212.67 C205.48,212.67 205.5,212.38 205.5,212.38 C205.5,212.38 205.49,212.09 205.49,212.09 C205.49,212.09 205.44,211.81 205.44,211.81 C205.44,211.81 205.38,211.52 205.38,211.52 C205.38,211.52 205.31,211.24 205.31,211.24 C205.31,211.24 205.24,210.96 205.24,210.96 C205.24,210.96 205.17,210.68 205.17,210.68 C205.17,210.68 205.1,210.4 205.1,210.4 C205.1,210.4 205.03,210.12 205.03,210.12 C205.03,210.12 204.96,209.84 204.96,209.84 C204.96,209.84 204.89,209.56 204.89,209.56 C204.89,209.56 204.82,209.28 204.82,209.28 C204.82,209.28 204.76,208.99 204.76,208.99 C204.76,208.99 204.74,208.7 204.74,208.7 C204.74,208.7 204.74,208.42 204.74,208.42 C204.74,208.42 204.76,208.13 204.76,208.13 C204.76,208.13 204.82,207.84 204.82,207.84 C204.82,207.84 204.91,207.57 204.91,207.57 C204.91,207.57 205.03,207.3 205.03,207.3 C205.03,207.3 205.17,207.05 205.17,207.05 C205.17,207.05 205.34,206.81 205.34,206.81 C205.34,206.81 205.52,206.59 205.52,206.59 C205.52,206.59 205.73,206.39 205.73,206.39 C205.73,206.39 205.96,206.22 205.96,206.22 C205.96,206.22 206.21,206.06 206.21,206.06 C206.21,206.06 206.47,205.94 206.47,205.94 C206.47,205.94 206.74,205.83 206.74,205.83 C206.74,205.83 207.02,205.76 207.02,205.76 C207.02,205.76 207.3,205.71 207.3,205.71 C207.3,205.71 207.59,205.7 207.59,205.7 C207.59,205.7 207.88,205.71 207.88,205.71 C207.88,205.71 208.17,205.76 208.17,205.76 C208.17,205.76 208.45,205.82 208.45,205.82 C208.45,205.82 208.73,205.89 208.73,205.89 C208.73,205.89 209.01,205.96 209.01,205.96 C209.01,205.96 209.29,206.03 209.29,206.03 C209.29,206.03 209.57,206.1 209.57,206.1 C209.57,206.1 209.85,206.17 209.85,206.17 C209.85,206.17 210.14,206.24 210.14,206.24 C210.14,206.24 210.42,206.31 210.42,206.31 C210.42,206.31 210.7,206.38 210.7,206.38 C210.7,206.38 210.98,206.44 210.98,206.44 C210.98,206.44 211.27,206.46 211.27,206.46 C211.27,206.46 211.56,206.46 211.56,206.46 C211.56,206.46 211.85,206.43 211.85,206.43 C211.85,206.43 212.13,206.36 212.13,206.36 C212.13,206.36 212.41,206.27 212.41,206.27 C212.41,206.27 212.67,206.15 212.67,206.15 C212.67,206.15 212.92,206.01 212.92,206.01 C212.92,206.01 213.16,205.84 213.16,205.84 C213.16,205.84 213.38,205.65 213.38,205.65 C213.38,205.65 213.57,205.44 213.57,205.44 C213.57,205.44 213.75,205.21 213.75,205.21 C213.75,205.21 213.9,204.96 213.9,204.96 C213.9,204.96 214.05,204.71 214.05,204.71 C214.05,204.71 214.2,204.47 214.2,204.47 C214.2,204.47 214.35,204.22 214.35,204.22 C214.35,204.22 214.5,203.97 214.5,203.97 C214.5,203.97 214.65,203.72 214.65,203.72 C214.65,203.72 214.8,203.47 214.8,203.47 C214.8,203.47 214.94,203.22 214.94,203.22 C214.94,203.22 215.1,202.97 215.1,202.97 C215.1,202.97 215.26,202.73 215.26,202.73 C215.26,202.73 215.44,202.51 215.44,202.51 C215.44,202.51 215.65,202.31 215.65,202.31 C215.65,202.31 215.87,202.12 215.87,202.12 C215.87,202.12 216.11,201.96 216.11,201.96 C216.11,201.96 216.37,201.83 216.37,201.83 C216.37,201.83 216.64,201.73 216.64,201.73 C216.64,201.73 216.92,201.65 216.92,201.65 C216.92,201.65 217.21,201.6 217.21,201.6 C217.21,201.6 217.49,201.58 217.49,201.58 C217.49,201.58 217.78,201.58 217.78,201.58c " android:valueTo="M217.68 210.56 C217.68,210.56 217.81,210.57 217.81,210.57 C217.81,210.57 217.93,210.57 217.93,210.57 C217.93,210.57 218.06,210.58 218.06,210.58 C218.06,210.58 218.18,210.59 218.18,210.59 C218.18,210.59 218.31,210.59 218.31,210.59 C218.31,210.59 218.43,210.61 218.43,210.61 C218.43,210.61 218.56,210.63 218.56,210.63 C218.56,210.63 218.68,210.64 218.68,210.64 C218.68,210.64 218.81,210.66 218.81,210.66 C218.81,210.66 218.93,210.68 218.93,210.68 C218.93,210.68 219.05,210.7 219.05,210.7 C219.05,210.7 219.18,210.72 219.18,210.72 C219.18,210.72 219.3,210.75 219.3,210.75 C219.3,210.75 219.42,210.78 219.42,210.78 C219.42,210.78 219.54,210.81 219.54,210.81 C219.54,210.81 219.66,210.84 219.66,210.84 C219.66,210.84 219.79,210.87 219.79,210.87 C219.79,210.87 219.91,210.91 219.91,210.91 C219.91,210.91 220.03,210.95 220.03,210.95 C220.03,210.95 220.14,210.99 220.14,210.99 C220.14,210.99 220.26,211.04 220.26,211.04 C220.26,211.04 220.38,211.08 220.38,211.08 C220.38,211.08 220.5,211.12 220.5,211.12 C220.5,211.12 220.62,211.17 220.62,211.17 C220.62,211.17 220.73,211.22 220.73,211.22 C220.73,211.22 220.84,211.27 220.84,211.27 C220.84,211.27 220.96,211.32 220.96,211.32 C220.96,211.32 221.07,211.38 221.07,211.38 C221.07,211.38 221.19,211.43 221.19,211.43 C221.19,211.43 221.3,211.49 221.3,211.49 C221.3,211.49 221.41,211.55 221.41,211.55 C221.41,211.55 221.51,211.61 221.51,211.61 C221.51,211.61 221.62,211.68 221.62,211.68 C221.62,211.68 221.73,211.74 221.73,211.74 C221.73,211.74 221.84,211.8 221.84,211.8 C221.84,211.8 221.94,211.87 221.94,211.87 C221.94,211.87 222.05,211.94 222.05,211.94 C222.05,211.94 222.15,212.02 222.15,212.02 C222.15,212.02 222.25,212.09 222.25,212.09 C222.25,212.09 222.35,212.16 222.35,212.16 C222.35,212.16 222.46,212.23 222.46,212.23 C222.46,212.23 222.55,212.31 222.55,212.31 C222.55,212.31 222.65,212.4 222.65,212.4 C222.65,212.4 222.74,212.48 222.74,212.48 C222.74,212.48 222.84,212.56 222.84,212.56 C222.84,212.56 222.93,212.64 222.93,212.64 C222.93,212.64 223.03,212.72 223.03,212.72 C223.03,212.72 223.12,212.81 223.12,212.81 C223.12,212.81 223.21,212.9 223.21,212.9 C223.21,212.9 223.29,212.99 223.29,212.99 C223.29,212.99 223.38,213.08 223.38,213.08 C223.38,213.08 223.47,213.17 223.47,213.17 C223.47,213.17 223.55,213.26 223.55,213.26 C223.55,213.26 223.63,213.36 223.63,213.36 C223.63,213.36 223.71,213.46 223.71,213.46 C223.71,213.46 223.79,213.56 223.79,213.56 C223.79,213.56 223.87,213.66 223.87,213.66 C223.87,213.66 223.95,213.75 223.95,213.75 C223.95,213.75 224.03,213.85 224.03,213.85 C224.03,213.85 224.09,213.96 224.09,213.96 C224.09,213.96 224.16,214.06 224.16,214.06 C224.16,214.06 224.23,214.17 224.23,214.17 C224.23,214.17 224.3,214.27 224.3,214.27 C224.3,214.27 224.37,214.38 224.37,214.38 C224.37,214.38 224.44,214.48 224.44,214.48 C224.44,214.48 224.5,214.59 224.5,214.59 C224.5,214.59 224.56,214.7 224.56,214.7 C224.56,214.7 224.62,214.81 224.62,214.81 C224.62,214.81 224.68,214.93 224.68,214.93 C224.68,214.93 224.74,215.04 224.74,215.04 C224.74,215.04 224.79,215.15 224.79,215.15 C224.79,215.15 224.84,215.26 224.84,215.26 C224.84,215.26 224.89,215.38 224.89,215.38 C224.89,215.38 224.94,215.5 224.94,215.5 C224.94,215.5 224.99,215.61 224.99,215.61 C224.99,215.61 225.04,215.73 225.04,215.73 C225.04,215.73 225.08,215.84 225.08,215.84 C225.08,215.84 225.12,215.96 225.12,215.96 C225.12,215.96 225.16,216.08 225.16,216.08 C225.16,216.08 225.19,216.2 225.19,216.2 C225.19,216.2 225.23,216.32 225.23,216.32 C225.23,216.32 225.27,216.44 225.27,216.44 C225.27,216.44 225.3,216.56 225.3,216.56 C225.3,216.56 225.33,216.69 225.33,216.69 C225.33,216.69 225.35,216.81 225.35,216.81 C225.35,216.81 225.38,216.93 225.38,216.93 C225.38,216.93 225.41,217.06 225.41,217.06 C225.41,217.06 225.43,217.18 225.43,217.18 C225.43,217.18 225.46,217.3 225.46,217.3 C225.46,217.3 225.47,217.43 225.47,217.43 C225.47,217.43 225.49,217.55 225.49,217.55 C225.49,217.55 225.5,217.68 225.5,217.68 C225.5,217.68 225.52,217.8 225.52,217.8 C225.52,217.8 225.52,217.93 225.52,217.93 C225.52,217.93 225.53,218.05 225.53,218.05 C225.53,218.05 225.54,218.18 225.54,218.18 C225.54,218.18 225.54,218.3 225.54,218.3 C225.54,218.3 225.55,218.43 225.55,218.43 C225.55,218.43 225.55,218.55 225.55,218.55 C225.55,218.55 225.55,218.68 225.55,218.68 C225.55,218.68 225.54,218.8 225.54,218.8 C225.54,218.8 225.54,218.93 225.54,218.93 C225.54,218.93 225.53,219.05 225.53,219.05 C225.53,219.05 225.52,219.18 225.52,219.18 C225.52,219.18 225.52,219.31 225.52,219.31 C225.52,219.31 225.5,219.43 225.5,219.43 C225.5,219.43 225.48,219.55 225.48,219.55 C225.48,219.55 225.47,219.68 225.47,219.68 C225.47,219.68 225.45,219.8 225.45,219.8 C225.45,219.8 225.43,219.93 225.43,219.93 C225.43,219.93 225.41,220.05 225.41,220.05 C225.41,220.05 225.39,220.17 225.39,220.17 C225.39,220.17 225.36,220.3 225.36,220.3 C225.36,220.3 225.33,220.42 225.33,220.42 C225.33,220.42 225.3,220.54 225.3,220.54 C225.3,220.54 225.27,220.66 225.27,220.66 C225.27,220.66 225.24,220.78 225.24,220.78 C225.24,220.78 225.2,220.9 225.2,220.9 C225.2,220.9 225.16,221.02 225.16,221.02 C225.16,221.02 225.12,221.14 225.12,221.14 C225.12,221.14 225.08,221.26 225.08,221.26 C225.08,221.26 225.03,221.38 225.03,221.38 C225.03,221.38 224.99,221.5 224.99,221.5 C224.99,221.5 224.95,221.61 224.95,221.61 C224.95,221.61 224.89,221.73 224.89,221.73 C224.89,221.73 224.84,221.84 224.84,221.84 C224.84,221.84 224.79,221.96 224.79,221.96 C224.79,221.96 224.73,222.07 224.73,222.07 C224.73,222.07 224.68,222.18 224.68,222.18 C224.68,222.18 224.62,222.29 224.62,222.29 C224.62,222.29 224.56,222.4 224.56,222.4 C224.56,222.4 224.5,222.51 224.5,222.51 C224.5,222.51 224.44,222.62 224.44,222.62 C224.44,222.62 224.37,222.73 224.37,222.73 C224.37,222.73 224.31,222.84 224.31,222.84 C224.31,222.84 224.24,222.94 224.24,222.94 C224.24,222.94 224.17,223.05 224.17,223.05 C224.17,223.05 224.09,223.15 224.09,223.15 C224.09,223.15 224.02,223.25 224.02,223.25 C224.02,223.25 223.95,223.35 223.95,223.35 C223.95,223.35 223.88,223.45 223.88,223.45 C223.88,223.45 223.8,223.55 223.8,223.55 C223.8,223.55 223.71,223.65 223.71,223.65 C223.71,223.65 223.63,223.74 223.63,223.74 C223.63,223.74 223.55,223.84 223.55,223.84 C223.55,223.84 223.47,223.93 223.47,223.93 C223.47,223.93 223.39,224.03 223.39,224.03 C223.39,224.03 223.3,224.12 223.3,224.12 C223.3,224.12 223.21,224.2 223.21,224.2 C223.21,224.2 223.12,224.29 223.12,224.29 C223.12,224.29 223.03,224.38 223.03,224.38 C223.03,224.38 222.94,224.46 222.94,224.46 C222.94,224.46 222.85,224.55 222.85,224.55 C222.85,224.55 222.75,224.63 222.75,224.63 C222.75,224.63 222.65,224.71 222.65,224.71 C222.65,224.71 222.55,224.79 222.55,224.79 C222.55,224.79 222.46,224.87 222.46,224.87 C222.46,224.87 222.36,224.95 222.36,224.95 C222.36,224.95 222.26,225.02 222.26,225.02 C222.26,225.02 222.15,225.09 222.15,225.09 C222.15,225.09 222.05,225.16 222.05,225.16 C222.05,225.16 221.94,225.23 221.94,225.23 C221.94,225.23 221.84,225.3 221.84,225.3 C221.84,225.3 221.74,225.37 221.74,225.37 C221.74,225.37 221.63,225.44 221.63,225.44 C221.63,225.44 221.52,225.5 221.52,225.5 C221.52,225.5 221.41,225.56 221.41,225.56 C221.41,225.56 221.3,225.62 221.3,225.62 C221.3,225.62 221.19,225.68 221.19,225.68 C221.19,225.68 221.08,225.73 221.08,225.73 C221.08,225.73 220.96,225.79 220.96,225.79 C220.96,225.79 220.85,225.84 220.85,225.84 C220.85,225.84 220.73,225.89 220.73,225.89 C220.73,225.89 220.62,225.94 220.62,225.94 C220.62,225.94 220.5,225.99 220.5,225.99 C220.5,225.99 220.38,226.03 220.38,226.03 C220.38,226.03 220.27,226.08 220.27,226.08 C220.27,226.08 220.15,226.12 220.15,226.12 C220.15,226.12 220.03,226.15 220.03,226.15 C220.03,226.15 219.91,226.19 219.91,226.19 C219.91,226.19 219.79,226.23 219.79,226.23 C219.79,226.23 219.67,226.27 219.67,226.27 C219.67,226.27 219.55,226.3 219.55,226.3 C219.55,226.3 219.42,226.33 219.42,226.33 C219.42,226.33 219.3,226.35 219.3,226.35 C219.3,226.35 219.18,226.38 219.18,226.38 C219.18,226.38 219.06,226.4 219.06,226.4 C219.06,226.4 218.93,226.43 218.93,226.43 C218.93,226.43 218.81,226.45 218.81,226.45 C218.81,226.45 218.68,226.47 218.68,226.47 C218.68,226.47 218.56,226.49 218.56,226.49 C218.56,226.49 218.44,226.5 218.44,226.5 C218.44,226.5 218.31,226.52 218.31,226.52 C218.31,226.52 218.19,226.52 218.19,226.52 C218.19,226.52 218.06,226.53 218.06,226.53 C218.06,226.53 217.93,226.53 217.93,226.53 C217.93,226.53 217.81,226.54 217.81,226.54 C217.81,226.54 217.68,226.55 217.68,226.55 C217.68,226.55 217.56,226.55 217.56,226.55 C217.56,226.55 217.43,226.55 217.43,226.55 C217.43,226.55 217.31,226.54 217.31,226.54 C217.31,226.54 217.18,226.53 217.18,226.53 C217.18,226.53 217.05,226.53 217.05,226.53 C217.05,226.53 216.93,226.52 216.93,226.52 C216.93,226.52 216.8,226.52 216.8,226.52 C216.8,226.52 216.68,226.5 216.68,226.5 C216.68,226.5 216.55,226.48 216.55,226.48 C216.55,226.48 216.43,226.46 216.43,226.46 C216.43,226.46 216.31,226.45 216.31,226.45 C216.31,226.45 216.18,226.43 216.18,226.43 C216.18,226.43 216.06,226.41 216.06,226.41 C216.06,226.41 215.93,226.38 215.93,226.38 C215.93,226.38 215.81,226.35 215.81,226.35 C215.81,226.35 215.69,226.32 215.69,226.32 C215.69,226.32 215.57,226.29 215.57,226.29 C215.57,226.29 215.45,226.26 215.45,226.26 C215.45,226.26 215.32,226.23 215.32,226.23 C215.32,226.23 215.2,226.2 215.2,226.2 C215.2,226.2 215.09,226.16 215.09,226.16 C215.09,226.16 214.97,226.12 214.97,226.12 C214.97,226.12 214.85,226.07 214.85,226.07 C214.85,226.07 214.73,226.03 214.73,226.03 C214.73,226.03 214.61,225.99 214.61,225.99 C214.61,225.99 214.5,225.94 214.5,225.94 C214.5,225.94 214.38,225.89 214.38,225.89 C214.38,225.89 214.27,225.84 214.27,225.84 C214.27,225.84 214.15,225.79 214.15,225.79 C214.15,225.79 214.04,225.73 214.04,225.73 C214.04,225.73 213.93,225.68 213.93,225.68 C213.93,225.68 213.81,225.62 213.81,225.62 C213.81,225.62 213.71,225.56 213.71,225.56 C213.71,225.56 213.6,225.5 213.6,225.5 C213.6,225.5 213.49,225.43 213.49,225.43 C213.49,225.43 213.38,225.37 213.38,225.37 C213.38,225.37 213.27,225.31 213.27,225.31 C213.27,225.31 213.17,225.24 213.17,225.24 C213.17,225.24 213.06,225.16 213.06,225.16 C213.06,225.16 212.96,225.09 212.96,225.09 C212.96,225.09 212.86,225.02 212.86,225.02 C212.86,225.02 212.76,224.95 212.76,224.95 C212.76,224.95 212.65,224.87 212.65,224.87 C212.65,224.87 212.56,224.79 212.56,224.79 C212.56,224.79 212.46,224.71 212.46,224.71 C212.46,224.71 212.37,224.63 212.37,224.63 C212.37,224.63 212.27,224.55 212.27,224.55 C212.27,224.55 212.18,224.47 212.18,224.47 C212.18,224.47 212.08,224.38 212.08,224.38 C212.08,224.38 211.99,224.3 211.99,224.3 C211.99,224.3 211.91,224.2 211.91,224.2 C211.91,224.2 211.82,224.11 211.82,224.11 C211.82,224.11 211.73,224.02 211.73,224.02 C211.73,224.02 211.64,223.93 211.64,223.93 C211.64,223.93 211.56,223.84 211.56,223.84 C211.56,223.84 211.48,223.75 211.48,223.75 C211.48,223.75 211.4,223.65 211.4,223.65 C211.4,223.65 211.32,223.55 211.32,223.55 C211.32,223.55 211.24,223.45 211.24,223.45 C211.24,223.45 211.16,223.35 211.16,223.35 C211.16,223.35 211.09,223.26 211.09,223.26 C211.09,223.26 211.02,223.15 211.02,223.15 C211.02,223.15 210.95,223.05 210.95,223.05 C210.95,223.05 210.88,222.94 210.88,222.94 C210.88,222.94 210.81,222.84 210.81,222.84 C210.81,222.84 210.74,222.73 210.74,222.73 C210.74,222.73 210.67,222.63 210.67,222.63 C210.67,222.63 210.61,222.52 210.61,222.52 C210.61,222.52 210.55,222.4 210.55,222.4 C210.55,222.4 210.49,222.29 210.49,222.29 C210.49,222.29 210.43,222.18 210.43,222.18 C210.43,222.18 210.38,222.07 210.38,222.07 C210.38,222.07 210.32,221.96 210.32,221.96 C210.32,221.96 210.27,221.84 210.27,221.84 C210.27,221.84 210.22,221.73 210.22,221.73 C210.22,221.73 210.17,221.61 210.17,221.61 C210.17,221.61 210.12,221.5 210.12,221.5 C210.12,221.5 210.08,221.38 210.08,221.38 C210.08,221.38 210.03,221.26 210.03,221.26 C210.03,221.26 209.99,221.14 209.99,221.14 C209.99,221.14 209.96,221.02 209.96,221.02 C209.96,221.02 209.92,220.9 209.92,220.9 C209.92,220.9 209.88,220.78 209.88,220.78 C209.88,220.78 209.84,220.67 209.84,220.67 C209.84,220.67 209.81,220.54 209.81,220.54 C209.81,220.54 209.78,220.42 209.78,220.42 C209.78,220.42 209.76,220.3 209.76,220.3 C209.76,220.3 209.73,220.18 209.73,220.18 C209.73,220.18 209.71,220.05 209.71,220.05 C209.71,220.05 209.68,219.93 209.68,219.93 C209.68,219.93 209.66,219.81 209.66,219.81 C209.66,219.81 209.64,219.68 209.64,219.68 C209.64,219.68 209.62,219.56 209.62,219.56 C209.62,219.56 209.61,219.43 209.61,219.43 C209.61,219.43 209.59,219.31 209.59,219.31 C209.59,219.31 209.59,219.18 209.59,219.18 C209.59,219.18 209.58,219.06 209.58,219.06 C209.58,219.06 209.58,218.93 209.58,218.93 C209.58,218.93 209.57,218.81 209.57,218.81 C209.57,218.81 209.56,218.68 209.56,218.68 C209.56,218.68 209.56,218.56 209.56,218.56 C209.56,218.56 209.56,218.43 209.56,218.43 C209.56,218.43 209.57,218.3 209.57,218.3 C209.57,218.3 209.58,218.18 209.58,218.18 C209.58,218.18 209.58,218.05 209.58,218.05 C209.58,218.05 209.59,217.93 209.59,217.93 C209.59,217.93 209.59,217.8 209.59,217.8 C209.59,217.8 209.61,217.68 209.61,217.68 C209.61,217.68 209.63,217.55 209.63,217.55 C209.63,217.55 209.65,217.43 209.65,217.43 C209.65,217.43 209.66,217.31 209.66,217.31 C209.66,217.31 209.68,217.18 209.68,217.18 C209.68,217.18 209.7,217.06 209.7,217.06 C209.7,217.06 209.73,216.93 209.73,216.93 C209.73,216.93 209.76,216.81 209.76,216.81 C209.76,216.81 209.79,216.69 209.79,216.69 C209.79,216.69 209.82,216.57 209.82,216.57 C209.82,216.57 209.85,216.45 209.85,216.45 C209.85,216.45 209.88,216.32 209.88,216.32 C209.88,216.32 209.91,216.2 209.91,216.2 C209.91,216.2 209.95,216.08 209.95,216.08 C209.95,216.08 210,215.97 210,215.97 C210,215.97 210.04,215.85 210.04,215.85 C210.04,215.85 210.08,215.73 210.08,215.73 C210.08,215.73 210.12,215.61 210.12,215.61 C210.12,215.61 210.17,215.49 210.17,215.49 C210.17,215.49 210.22,215.38 210.22,215.38 C210.22,215.38 210.27,215.27 210.27,215.27 C210.27,215.27 210.33,215.15 210.33,215.15 C210.33,215.15 210.38,215.04 210.38,215.04 C210.38,215.04 210.43,214.92 210.43,214.92 C210.43,214.92 210.49,214.81 210.49,214.81 C210.49,214.81 210.55,214.7 210.55,214.7 C210.55,214.7 210.61,214.6 210.61,214.6 C210.61,214.6 210.68,214.49 210.68,214.49 C210.68,214.49 210.74,214.38 210.74,214.38 C210.74,214.38 210.8,214.27 210.8,214.27 C210.8,214.27 210.87,214.17 210.87,214.17 C210.87,214.17 210.95,214.06 210.95,214.06 C210.95,214.06 211.02,213.96 211.02,213.96 C211.02,213.96 211.09,213.86 211.09,213.86 C211.09,213.86 211.16,213.76 211.16,213.76 C211.16,213.76 211.24,213.65 211.24,213.65 C211.24,213.65 211.32,213.56 211.32,213.56 C211.32,213.56 211.4,213.46 211.4,213.46 C211.4,213.46 211.48,213.37 211.48,213.37 C211.48,213.37 211.56,213.27 211.56,213.27 C211.56,213.27 211.64,213.18 211.64,213.18 C211.64,213.18 211.73,213.08 211.73,213.08 C211.73,213.08 211.82,212.99 211.82,212.99 C211.82,212.99 211.91,212.9 211.91,212.9 C211.91,212.9 212,212.82 212,212.82 C212,212.82 212.09,212.73 212.09,212.73 C212.09,212.73 212.18,212.64 212.18,212.64 C212.18,212.64 212.27,212.56 212.27,212.56 C212.27,212.56 212.36,212.48 212.36,212.48 C212.36,212.48 212.46,212.4 212.46,212.4 C212.46,212.4 212.56,212.32 212.56,212.32 C212.56,212.32 212.66,212.24 212.66,212.24 C212.66,212.24 212.76,212.16 212.76,212.16 C212.76,212.16 212.85,212.08 212.85,212.08 C212.85,212.08 212.96,212.02 212.96,212.02 C212.96,212.02 213.06,211.95 213.06,211.95 C213.06,211.95 213.17,211.88 213.17,211.88 C213.17,211.88 213.27,211.81 213.27,211.81 C213.27,211.81 213.38,211.74 213.38,211.74 C213.38,211.74 213.48,211.67 213.48,211.67 C213.48,211.67 213.6,211.61 213.6,211.61 C213.6,211.61 213.71,211.55 213.71,211.55 C213.71,211.55 213.82,211.49 213.82,211.49 C213.82,211.49 213.93,211.43 213.93,211.43 C213.93,211.43 214.04,211.37 214.04,211.37 C214.04,211.37 214.15,211.32 214.15,211.32 C214.15,211.32 214.27,211.27 214.27,211.27 C214.27,211.27 214.38,211.22 214.38,211.22 C214.38,211.22 214.5,211.17 214.5,211.17 C214.5,211.17 214.61,211.12 214.61,211.12 C214.61,211.12 214.73,211.07 214.73,211.07 C214.73,211.07 214.85,211.03 214.85,211.03 C214.85,211.03 214.97,210.99 214.97,210.99 C214.97,210.99 215.09,210.95 215.09,210.95 C215.09,210.95 215.21,210.92 215.21,210.92 C215.21,210.92 215.33,210.88 215.33,210.88 C215.33,210.88 215.45,210.84 215.45,210.84 C215.45,210.84 215.57,210.81 215.57,210.81 C215.57,210.81 215.69,210.78 215.69,210.78 C215.69,210.78 215.81,210.76 215.81,210.76 C215.81,210.76 215.93,210.73 215.93,210.73 C215.93,210.73 216.06,210.7 216.06,210.7 C216.06,210.7 216.18,210.68 216.18,210.68 C216.18,210.68 216.3,210.65 216.3,210.65 C216.3,210.65 216.43,210.64 216.43,210.64 C216.43,210.64 216.55,210.62 216.55,210.62 C216.55,210.62 216.68,210.61 216.68,210.61 C216.68,210.61 216.8,210.59 216.8,210.59 C216.8,210.59 216.93,210.59 216.93,210.59 C216.93,210.59 217.05,210.58 217.05,210.58 C217.05,210.58 217.18,210.58 217.18,210.58 C217.18,210.58 217.3,210.57 217.3,210.57 C217.3,210.57 217.43,210.56 217.43,210.56 C217.43,210.56 217.56,210.56 217.56,210.56 C217.56,210.56 217.68,210.56 217.68,210.56c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.8,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="500" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector> \ No newline at end of file
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="30dp" android:width="30dp" android:viewportHeight="30" android:viewportWidth="30"><group android:name="_R_G"><group android:name="_R_G_L_1_G" android:translateX="15.441" android:translateY="15.691" android:scaleY="0"><path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-0.44 -8.69 C3.97,-8.69 7.56,-5.11 7.56,-0.69 C7.56,3.72 3.97,7.31 -0.44,7.31 C-4.86,7.31 -8.44,3.72 -8.44,-0.69 C-8.44,-5.11 -4.86,-8.69 -0.44,-8.69c "/></group><group android:name="_R_G_L_0_G" android:translateX="15" android:translateY="15" android:scaleX="0" android:scaleY="0"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M8 0 C8,-1.35 7.97,-1.94 7.41,-3.02 C6.85,-4.09 6.61,-4.79 5.66,-5.66 C4.7,-6.52 4.2,-6.97 3.15,-7.36 C2.09,-7.74 1.39,-8 0,-8 C-1.39,-8 -2.18,-7.78 -3.12,-7.37 C-4.07,-6.96 -4.67,-6.63 -5.66,-5.66 C-6.64,-4.68 -6.98,-4.1 -7.37,-3.13 C-7.78,-2.08 -8,-1.39 -8,0 C-8,1.4 -7.86,1.98 -7.47,2.87 C-7.08,3.76 -6.68,4.66 -5.66,5.66 C-4.63,6.65 -4,6.96 -3.12,7.37 C-2.25,7.78 -1.32,8 0,8 C1.32,8 1.86,7.88 2.9,7.46 C3.95,7.03 4.85,6.63 5.66,5.66 C6.46,4.69 6.78,4.45 7.29,3.29 C7.81,2.14 8,1.35 8,0c "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_1_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="67" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M8 0 C8,-1.35 7.97,-1.94 7.41,-3.02 C6.85,-4.09 6.61,-4.79 5.66,-5.66 C4.7,-6.52 4.2,-6.97 3.15,-7.36 C2.09,-7.74 1.39,-8 0,-8 C-1.39,-8 -2.18,-7.78 -3.12,-7.37 C-4.07,-6.96 -4.67,-6.63 -5.66,-5.66 C-6.64,-4.68 -6.98,-4.1 -7.37,-3.13 C-7.78,-2.08 -8,-1.39 -8,0 C-8,1.4 -7.86,1.98 -7.47,2.87 C-7.08,3.76 -6.68,4.66 -5.66,5.66 C-4.63,6.65 -4,6.96 -3.12,7.37 C-2.25,7.78 -1.32,8 0,8 C1.32,8 1.86,7.88 2.9,7.46 C3.95,7.03 4.85,6.63 5.66,5.66 C6.46,4.69 6.78,4.45 7.29,3.29 C7.81,2.14 8,1.35 8,0c " android:valueTo="M15 0 C15,-2.52 11.99,-2.3 10.94,-4.32 C9.89,-6.33 12.4,-8.98 10.61,-10.61 C8.82,-12.23 6.44,-10.15 4.46,-10.86 C2.48,-11.58 2.61,-15 0,-15 C-2.61,-15 -2.68,-11.61 -4.46,-10.84 C-6.23,-10.08 -8.76,-12.44 -10.61,-10.61 C-12.45,-8.78 -10.31,-6.69 -10.87,-4.64 C-11.43,-2.61 -15,-2.61 -15,0 C-15,2.62 -11.67,2.75 -10.94,4.42 C-10.21,6.08 -12.53,8.74 -10.61,10.61 C-8.68,12.47 -6.18,10.19 -4.54,10.96 C-2.89,11.72 -2.48,15 0,15 C2.48,15 2.49,11.78 4.45,10.99 C6.4,10.19 9.09,12.43 10.61,10.61 C12.12,8.79 10,6.52 10.97,4.36 C11.94,2.2 15,2.52 15,0c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0 0.833,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="283" android:startOffset="67" android:valueFrom="M15 0 C15,-2.52 11.99,-2.3 10.94,-4.32 C9.89,-6.33 12.4,-8.98 10.61,-10.61 C8.82,-12.23 6.44,-10.15 4.46,-10.86 C2.48,-11.58 2.61,-15 0,-15 C-2.61,-15 -2.68,-11.61 -4.46,-10.84 C-6.23,-10.08 -8.76,-12.44 -10.61,-10.61 C-12.45,-8.78 -10.31,-6.69 -10.87,-4.64 C-11.43,-2.61 -15,-2.61 -15,0 C-15,2.62 -11.67,2.75 -10.94,4.42 C-10.21,6.08 -12.53,8.74 -10.61,10.61 C-8.68,12.47 -6.18,10.19 -4.54,10.96 C-2.89,11.72 -2.48,15 0,15 C2.48,15 2.49,11.78 4.45,10.99 C6.4,10.19 9.09,12.43 10.61,10.61 C12.12,8.79 10,6.52 10.97,4.36 C11.94,2.2 15,2.52 15,0c " android:valueTo="M7.73 0 C7.73,-1.3 7.71,-1.88 7.16,-2.92 C6.62,-3.95 6.39,-4.63 5.47,-5.47 C4.55,-6.31 4.06,-6.74 3.04,-7.11 C2.02,-7.48 1.35,-7.73 0,-7.73 C-1.34,-7.73 -2.1,-7.52 -3.02,-7.12 C-3.93,-6.73 -4.52,-6.41 -5.47,-5.47 C-6.42,-4.53 -6.75,-3.96 -7.12,-3.02 C-7.52,-2.01 -7.73,-1.35 -7.73,0 C-7.73,1.35 -7.6,1.91 -7.22,2.77 C-6.85,3.63 -6.46,4.51 -5.47,5.47 C-4.48,6.43 -3.87,6.73 -3.02,7.12 C-2.17,7.52 -1.28,7.73 0,7.73 C1.28,7.73 1.8,7.62 2.81,7.21 C3.81,6.8 4.69,6.41 5.47,5.47 C6.25,4.53 6.55,4.3 7.05,3.19 C7.55,2.07 7.73,1.3 7.73,0c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.7,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleX" android:duration="67" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="67" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target><target android:name="_R_G_L_0_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="367" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="500" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pin_dot_shape_5_avd.xml b/packages/SystemUI/res/drawable/pin_dot_shape_5_avd.xml
index de2a7db4ab0a..3779c805136e 100644
--- a/packages/SystemUI/res/drawable/pin_dot_shape_5_avd.xml
+++ b/packages/SystemUI/res/drawable/pin_dot_shape_5_avd.xml
@@ -1 +1 @@
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="60dp" android:width="60dp" android:viewportHeight="60" android:viewportWidth="60"><group android:name="_R_G"><group android:name="_R_G_L_0_G" android:translateX="-187.543" android:translateY="-188.546"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="0" android:fillType="nonZero" android:pathData=" M217.62 214.55 C217.62,214.55 217.68,214.55 217.68,214.55 C217.68,214.55 217.74,214.56 217.74,214.56 C217.74,214.56 217.81,214.56 217.81,214.56 C217.81,214.56 217.87,214.56 217.87,214.56 C217.87,214.56 217.93,214.57 217.93,214.57 C217.93,214.57 218,214.57 218,214.57 C218,214.57 218.06,214.58 218.06,214.58 C218.06,214.58 218.12,214.59 218.12,214.59 C218.12,214.59 218.18,214.6 218.18,214.6 C218.18,214.6 218.24,214.61 218.24,214.61 C218.24,214.61 218.31,214.62 218.31,214.62 C218.31,214.62 218.37,214.63 218.37,214.63 C218.37,214.63 218.43,214.65 218.43,214.65 C218.43,214.65 218.49,214.66 218.49,214.66 C218.49,214.66 218.55,214.68 218.55,214.68 C218.55,214.68 218.61,214.69 218.61,214.69 C218.61,214.69 218.67,214.71 218.67,214.71 C218.67,214.71 218.73,214.73 218.73,214.73 C218.73,214.73 218.79,214.75 218.79,214.75 C218.79,214.75 218.85,214.77 218.85,214.77 C218.85,214.77 218.91,214.79 218.91,214.79 C218.91,214.79 218.97,214.81 218.97,214.81 C218.97,214.81 219.03,214.83 219.03,214.83 C219.03,214.83 219.09,214.85 219.09,214.85 C219.09,214.85 219.15,214.88 219.15,214.88 C219.15,214.88 219.2,214.9 219.2,214.9 C219.2,214.9 219.26,214.93 219.26,214.93 C219.26,214.93 219.32,214.96 219.32,214.96 C219.32,214.96 219.37,214.98 219.37,214.98 C219.37,214.98 219.43,215.01 219.43,215.01 C219.43,215.01 219.48,215.05 219.48,215.05 C219.48,215.05 219.54,215.08 219.54,215.08 C219.54,215.08 219.59,215.11 219.59,215.11 C219.59,215.11 219.65,215.14 219.65,215.14 C219.65,215.14 219.7,215.17 219.7,215.17 C219.7,215.17 219.75,215.21 219.75,215.21 C219.75,215.21 219.81,215.24 219.81,215.24 C219.81,215.24 219.86,215.28 219.86,215.28 C219.86,215.28 219.91,215.32 219.91,215.32 C219.91,215.32 219.96,215.35 219.96,215.35 C219.96,215.35 220.01,215.39 220.01,215.39 C220.01,215.39 220.06,215.43 220.06,215.43 C220.06,215.43 220.11,215.47 220.11,215.47 C220.11,215.47 220.16,215.51 220.16,215.51 C220.16,215.51 220.2,215.55 220.2,215.55 C220.2,215.55 220.25,215.59 220.25,215.59 C220.25,215.59 220.3,215.63 220.3,215.63 C220.3,215.63 220.34,215.68 220.34,215.68 C220.34,215.68 220.39,215.72 220.39,215.72 C220.39,215.72 220.43,215.77 220.43,215.77 C220.43,215.77 220.47,215.81 220.47,215.81 C220.47,215.81 220.52,215.86 220.52,215.86 C220.52,215.86 220.56,215.9 220.56,215.9 C220.56,215.9 220.6,215.95 220.6,215.95 C220.6,215.95 220.64,216 220.64,216 C220.64,216 220.68,216.05 220.68,216.05 C220.68,216.05 220.72,216.1 220.72,216.1 C220.72,216.1 220.76,216.15 220.76,216.15 C220.76,216.15 220.8,216.2 220.8,216.2 C220.8,216.2 220.83,216.25 220.83,216.25 C220.83,216.25 220.87,216.3 220.87,216.3 C220.87,216.3 220.9,216.36 220.9,216.36 C220.9,216.36 220.94,216.41 220.94,216.41 C220.94,216.41 220.97,216.46 220.97,216.46 C220.97,216.46 221,216.51 221,216.51 C221,216.51 221.03,216.57 221.03,216.57 C221.03,216.57 221.06,216.63 221.06,216.63 C221.06,216.63 221.09,216.68 221.09,216.68 C221.09,216.68 221.12,216.74 221.12,216.74 C221.12,216.74 221.15,216.79 221.15,216.79 C221.15,216.79 221.18,216.85 221.18,216.85 C221.18,216.85 221.21,216.91 221.21,216.91 C221.21,216.91 221.23,216.96 221.23,216.96 C221.23,216.96 221.25,217.02 221.25,217.02 C221.25,217.02 221.28,217.08 221.28,217.08 C221.28,217.08 221.3,217.14 221.3,217.14 C221.3,217.14 221.33,217.2 221.33,217.2 C221.33,217.2 221.34,217.26 221.34,217.26 C221.34,217.26 221.36,217.32 221.36,217.32 C221.36,217.32 221.38,217.38 221.38,217.38 C221.38,217.38 221.4,217.44 221.4,217.44 C221.4,217.44 221.42,217.5 221.42,217.5 C221.42,217.5 221.44,217.56 221.44,217.56 C221.44,217.56 221.45,217.62 221.45,217.62 C221.45,217.62 221.46,217.68 221.46,217.68 C221.46,217.68 221.48,217.74 221.48,217.74 C221.48,217.74 221.49,217.8 221.49,217.8 C221.49,217.8 221.5,217.87 221.5,217.87 C221.5,217.87 221.51,217.93 221.51,217.93 C221.51,217.93 221.52,217.99 221.52,217.99 C221.52,217.99 221.53,218.05 221.53,218.05 C221.53,218.05 221.54,218.11 221.54,218.11 C221.54,218.11 221.54,218.18 221.54,218.18 C221.54,218.18 221.55,218.24 221.55,218.24 C221.55,218.24 221.55,218.3 221.55,218.3 C221.55,218.3 221.55,218.37 221.55,218.37 C221.55,218.37 221.56,218.43 221.56,218.43 C221.56,218.43 221.56,218.49 221.56,218.49 C221.56,218.49 221.56,218.55 221.56,218.55 C221.56,218.55 221.56,218.62 221.56,218.62 C221.56,218.62 221.56,218.68 221.56,218.68 C221.56,218.68 221.55,218.74 221.55,218.74 C221.55,218.74 221.55,218.81 221.55,218.81 C221.55,218.81 221.55,218.87 221.55,218.87 C221.55,218.87 221.54,218.93 221.54,218.93 C221.54,218.93 221.54,218.99 221.54,218.99 C221.54,218.99 221.53,219.06 221.53,219.06 C221.53,219.06 221.52,219.12 221.52,219.12 C221.52,219.12 221.51,219.18 221.51,219.18 C221.51,219.18 221.5,219.24 221.5,219.24 C221.5,219.24 221.49,219.3 221.49,219.3 C221.49,219.3 221.48,219.37 221.48,219.37 C221.48,219.37 221.46,219.43 221.46,219.43 C221.46,219.43 221.45,219.49 221.45,219.49 C221.45,219.49 221.43,219.55 221.43,219.55 C221.43,219.55 221.42,219.61 221.42,219.61 C221.42,219.61 221.4,219.67 221.4,219.67 C221.4,219.67 221.39,219.73 221.39,219.73 C221.39,219.73 221.37,219.79 221.37,219.79 C221.37,219.79 221.34,219.85 221.34,219.85 C221.34,219.85 221.32,219.91 221.32,219.91 C221.32,219.91 221.3,219.97 221.3,219.97 C221.3,219.97 221.28,220.03 221.28,220.03 C221.28,220.03 221.26,220.09 221.26,220.09 C221.26,220.09 221.23,220.14 221.23,220.14 C221.23,220.14 221.21,220.2 221.21,220.2 C221.21,220.2 221.18,220.26 221.18,220.26 C221.18,220.26 221.15,220.32 221.15,220.32 C221.15,220.32 221.13,220.37 221.13,220.37 C221.13,220.37 221.1,220.43 221.1,220.43 C221.1,220.43 221.07,220.48 221.07,220.48 C221.07,220.48 221.03,220.54 221.03,220.54 C221.03,220.54 221,220.59 221,220.59 C221,220.59 220.97,220.65 220.97,220.65 C220.97,220.65 220.94,220.7 220.94,220.7 C220.94,220.7 220.9,220.75 220.9,220.75 C220.9,220.75 220.87,220.8 220.87,220.8 C220.87,220.8 220.83,220.86 220.83,220.86 C220.83,220.86 220.8,220.91 220.8,220.91 C220.8,220.91 220.76,220.96 220.76,220.96 C220.76,220.96 220.72,221.01 220.72,221.01 C220.72,221.01 220.68,221.06 220.68,221.06 C220.68,221.06 220.64,221.11 220.64,221.11 C220.64,221.11 220.6,221.15 220.6,221.15 C220.6,221.15 220.56,221.2 220.56,221.2 C220.56,221.2 220.52,221.25 220.52,221.25 C220.52,221.25 220.48,221.3 220.48,221.3 C220.48,221.3 220.43,221.34 220.43,221.34 C220.43,221.34 220.39,221.38 220.39,221.38 C220.39,221.38 220.34,221.43 220.34,221.43 C220.34,221.43 220.3,221.47 220.3,221.47 C220.3,221.47 220.25,221.52 220.25,221.52 C220.25,221.52 220.21,221.56 220.21,221.56 C220.21,221.56 220.16,221.6 220.16,221.6 C220.16,221.6 220.11,221.64 220.11,221.64 C220.11,221.64 220.06,221.68 220.06,221.68 C220.06,221.68 220.01,221.72 220.01,221.72 C220.01,221.72 219.96,221.76 219.96,221.76 C219.96,221.76 219.91,221.8 219.91,221.8 C219.91,221.8 219.86,221.83 219.86,221.83 C219.86,221.83 219.81,221.87 219.81,221.87 C219.81,221.87 219.75,221.9 219.75,221.9 C219.75,221.9 219.7,221.93 219.7,221.93 C219.7,221.93 219.65,221.97 219.65,221.97 C219.65,221.97 219.6,222 219.6,222 C219.6,222 219.54,222.03 219.54,222.03 C219.54,222.03 219.49,222.06 219.49,222.06 C219.49,222.06 219.43,222.09 219.43,222.09 C219.43,222.09 219.37,222.12 219.37,222.12 C219.37,222.12 219.32,222.15 219.32,222.15 C219.32,222.15 219.26,222.18 219.26,222.18 C219.26,222.18 219.21,222.2 219.21,222.2 C219.21,222.2 219.15,222.23 219.15,222.23 C219.15,222.23 219.09,222.25 219.09,222.25 C219.09,222.25 219.03,222.28 219.03,222.28 C219.03,222.28 218.97,222.3 218.97,222.3 C218.97,222.3 218.91,222.32 218.91,222.32 C218.91,222.32 218.85,222.34 218.85,222.34 C218.85,222.34 218.79,222.36 218.79,222.36 C218.79,222.36 218.73,222.38 218.73,222.38 C218.73,222.38 218.67,222.4 218.67,222.4 C218.67,222.4 218.61,222.42 218.61,222.42 C218.61,222.42 218.55,222.44 218.55,222.44 C218.55,222.44 218.49,222.45 218.49,222.45 C218.49,222.45 218.43,222.46 218.43,222.46 C218.43,222.46 218.37,222.47 218.37,222.47 C218.37,222.47 218.31,222.49 218.31,222.49 C218.31,222.49 218.25,222.5 218.25,222.5 C218.25,222.5 218.18,222.51 218.18,222.51 C218.18,222.51 218.12,222.52 218.12,222.52 C218.12,222.52 218.06,222.53 218.06,222.53 C218.06,222.53 218,222.54 218,222.54 C218,222.54 217.93,222.54 217.93,222.54 C217.93,222.54 217.87,222.55 217.87,222.55 C217.87,222.55 217.81,222.55 217.81,222.55 C217.81,222.55 217.75,222.55 217.75,222.55 C217.75,222.55 217.68,222.56 217.68,222.56 C217.68,222.56 217.62,222.56 217.62,222.56 C217.62,222.56 217.56,222.56 217.56,222.56 C217.56,222.56 217.49,222.56 217.49,222.56 C217.49,222.56 217.43,222.56 217.43,222.56 C217.43,222.56 217.37,222.55 217.37,222.55 C217.37,222.55 217.3,222.55 217.3,222.55 C217.3,222.55 217.24,222.55 217.24,222.55 C217.24,222.55 217.18,222.54 217.18,222.54 C217.18,222.54 217.12,222.54 217.12,222.54 C217.12,222.54 217.05,222.53 217.05,222.53 C217.05,222.53 216.99,222.52 216.99,222.52 C216.99,222.52 216.93,222.51 216.93,222.51 C216.93,222.51 216.87,222.5 216.87,222.5 C216.87,222.5 216.81,222.49 216.81,222.49 C216.81,222.49 216.74,222.48 216.74,222.48 C216.74,222.48 216.68,222.46 216.68,222.46 C216.68,222.46 216.62,222.45 216.62,222.45 C216.62,222.45 216.56,222.43 216.56,222.43 C216.56,222.43 216.5,222.42 216.5,222.42 C216.5,222.42 216.44,222.4 216.44,222.4 C216.44,222.4 216.38,222.38 216.38,222.38 C216.38,222.38 216.32,222.36 216.32,222.36 C216.32,222.36 216.26,222.34 216.26,222.34 C216.26,222.34 216.2,222.32 216.2,222.32 C216.2,222.32 216.14,222.3 216.14,222.3 C216.14,222.3 216.08,222.28 216.08,222.28 C216.08,222.28 216.02,222.26 216.02,222.26 C216.02,222.26 215.97,222.23 215.97,222.23 C215.97,222.23 215.91,222.2 215.91,222.2 C215.91,222.2 215.85,222.18 215.85,222.18 C215.85,222.18 215.79,222.15 215.79,222.15 C215.79,222.15 215.74,222.12 215.74,222.12 C215.74,222.12 215.68,222.1 215.68,222.1 C215.68,222.1 215.63,222.06 215.63,222.06 C215.63,222.06 215.57,222.03 215.57,222.03 C215.57,222.03 215.52,222 215.52,222 C215.52,222 215.46,221.97 215.46,221.97 C215.46,221.97 215.41,221.94 215.41,221.94 C215.41,221.94 215.36,221.9 215.36,221.9 C215.36,221.9 215.31,221.87 215.31,221.87 C215.31,221.87 215.25,221.83 215.25,221.83 C215.25,221.83 215.2,221.79 215.2,221.79 C215.2,221.79 215.15,221.76 215.15,221.76 C215.15,221.76 215.1,221.72 215.1,221.72 C215.1,221.72 215.05,221.68 215.05,221.68 C215.05,221.68 215,221.64 215,221.64 C215,221.64 214.96,221.6 214.96,221.6 C214.96,221.6 214.91,221.56 214.91,221.56 C214.91,221.56 214.86,221.52 214.86,221.52 C214.86,221.52 214.81,221.48 214.81,221.48 C214.81,221.48 214.77,221.43 214.77,221.43 C214.77,221.43 214.73,221.39 214.73,221.39 C214.73,221.39 214.68,221.34 214.68,221.34 C214.68,221.34 214.64,221.3 214.64,221.3 C214.64,221.3 214.59,221.25 214.59,221.25 C214.59,221.25 214.55,221.2 214.55,221.2 C214.55,221.2 214.51,221.15 214.51,221.15 C214.51,221.15 214.47,221.11 214.47,221.11 C214.47,221.11 214.43,221.06 214.43,221.06 C214.43,221.06 214.39,221.01 214.39,221.01 C214.39,221.01 214.35,220.96 214.35,220.96 C214.35,220.96 214.31,220.91 214.31,220.91 C214.31,220.91 214.28,220.86 214.28,220.86 C214.28,220.86 214.25,220.81 214.25,220.81 C214.25,220.81 214.21,220.75 214.21,220.75 C214.21,220.75 214.18,220.7 214.18,220.7 C214.18,220.7 214.14,220.65 214.14,220.65 C214.14,220.65 214.11,220.59 214.11,220.59 C214.11,220.59 214.08,220.54 214.08,220.54 C214.08,220.54 214.05,220.48 214.05,220.48 C214.05,220.48 214.02,220.43 214.02,220.43 C214.02,220.43 213.99,220.37 213.99,220.37 C213.99,220.37 213.96,220.32 213.96,220.32 C213.96,220.32 213.93,220.26 213.93,220.26 C213.93,220.26 213.91,220.2 213.91,220.2 C213.91,220.2 213.88,220.14 213.88,220.14 C213.88,220.14 213.86,220.09 213.86,220.09 C213.86,220.09 213.83,220.03 213.83,220.03 C213.83,220.03 213.81,219.97 213.81,219.97 C213.81,219.97 213.79,219.91 213.79,219.91 C213.79,219.91 213.77,219.85 213.77,219.85 C213.77,219.85 213.75,219.79 213.75,219.79 C213.75,219.79 213.73,219.73 213.73,219.73 C213.73,219.73 213.71,219.67 213.71,219.67 C213.71,219.67 213.69,219.61 213.69,219.61 C213.69,219.61 213.68,219.55 213.68,219.55 C213.68,219.55 213.66,219.49 213.66,219.49 C213.66,219.49 213.65,219.43 213.65,219.43 C213.65,219.43 213.64,219.37 213.64,219.37 C213.64,219.37 213.62,219.31 213.62,219.31 C213.62,219.31 213.61,219.24 213.61,219.24 C213.61,219.24 213.6,219.18 213.6,219.18 C213.6,219.18 213.59,219.12 213.59,219.12 C213.59,219.12 213.58,219.06 213.58,219.06 C213.58,219.06 213.57,218.99 213.57,218.99 C213.57,218.99 213.57,218.93 213.57,218.93 C213.57,218.93 213.56,218.87 213.56,218.87 C213.56,218.87 213.56,218.81 213.56,218.81 C213.56,218.81 213.56,218.74 213.56,218.74 C213.56,218.74 213.56,218.68 213.56,218.68 C213.56,218.68 213.55,218.62 213.55,218.62 C213.55,218.62 213.55,218.55 213.55,218.55 C213.55,218.55 213.55,218.49 213.55,218.49 C213.55,218.49 213.56,218.43 213.56,218.43 C213.56,218.43 213.56,218.37 213.56,218.37 C213.56,218.37 213.56,218.3 213.56,218.3 C213.56,218.3 213.56,218.24 213.56,218.24 C213.56,218.24 213.57,218.18 213.57,218.18 C213.57,218.18 213.57,218.12 213.57,218.12 C213.57,218.12 213.58,218.05 213.58,218.05 C213.58,218.05 213.59,217.99 213.59,217.99 C213.59,217.99 213.6,217.93 213.6,217.93 C213.6,217.93 213.61,217.87 213.61,217.87 C213.61,217.87 213.62,217.8 213.62,217.8 C213.62,217.8 213.63,217.74 213.63,217.74 C213.63,217.74 213.65,217.68 213.65,217.68 C213.65,217.68 213.66,217.62 213.66,217.62 C213.66,217.62 213.68,217.56 213.68,217.56 C213.68,217.56 213.69,217.5 213.69,217.5 C213.69,217.5 213.71,217.44 213.71,217.44 C213.71,217.44 213.73,217.38 213.73,217.38 C213.73,217.38 213.75,217.32 213.75,217.32 C213.75,217.32 213.77,217.26 213.77,217.26 C213.77,217.26 213.79,217.2 213.79,217.2 C213.79,217.2 213.81,217.14 213.81,217.14 C213.81,217.14 213.83,217.08 213.83,217.08 C213.83,217.08 213.85,217.02 213.85,217.02 C213.85,217.02 213.88,216.96 213.88,216.96 C213.88,216.96 213.91,216.91 213.91,216.91 C213.91,216.91 213.93,216.85 213.93,216.85 C213.93,216.85 213.96,216.79 213.96,216.79 C213.96,216.79 213.99,216.74 213.99,216.74 C213.99,216.74 214.02,216.68 214.02,216.68 C214.02,216.68 214.05,216.63 214.05,216.63 C214.05,216.63 214.08,216.57 214.08,216.57 C214.08,216.57 214.11,216.52 214.11,216.52 C214.11,216.52 214.14,216.46 214.14,216.46 C214.14,216.46 214.17,216.41 214.17,216.41 C214.17,216.41 214.21,216.36 214.21,216.36 C214.21,216.36 214.24,216.3 214.24,216.3 C214.24,216.3 214.28,216.25 214.28,216.25 C214.28,216.25 214.32,216.2 214.32,216.2 C214.32,216.2 214.35,216.15 214.35,216.15 C214.35,216.15 214.39,216.1 214.39,216.1 C214.39,216.1 214.43,216.05 214.43,216.05 C214.43,216.05 214.47,216 214.47,216 C214.47,216 214.51,215.96 214.51,215.96 C214.51,215.96 214.55,215.91 214.55,215.91 C214.55,215.91 214.59,215.86 214.59,215.86 C214.59,215.86 214.64,215.81 214.64,215.81 C214.64,215.81 214.68,215.77 214.68,215.77 C214.68,215.77 214.73,215.72 214.73,215.72 C214.73,215.72 214.77,215.68 214.77,215.68 C214.77,215.68 214.82,215.64 214.82,215.64 C214.82,215.64 214.86,215.59 214.86,215.59 C214.86,215.59 214.91,215.55 214.91,215.55 C214.91,215.55 214.96,215.51 214.96,215.51 C214.96,215.51 215,215.47 215,215.47 C215,215.47 215.05,215.43 215.05,215.43 C215.05,215.43 215.1,215.39 215.1,215.39 C215.1,215.39 215.15,215.35 215.15,215.35 C215.15,215.35 215.2,215.31 215.2,215.31 C215.2,215.31 215.25,215.28 215.25,215.28 C215.25,215.28 215.31,215.24 215.31,215.24 C215.31,215.24 215.36,215.21 215.36,215.21 C215.36,215.21 215.41,215.17 215.41,215.17 C215.41,215.17 215.46,215.14 215.46,215.14 C215.46,215.14 215.52,215.11 215.52,215.11 C215.52,215.11 215.57,215.08 215.57,215.08 C215.57,215.08 215.63,215.05 215.63,215.05 C215.63,215.05 215.68,215.02 215.68,215.02 C215.68,215.02 215.74,214.99 215.74,214.99 C215.74,214.99 215.79,214.96 215.79,214.96 C215.79,214.96 215.85,214.93 215.85,214.93 C215.85,214.93 215.91,214.9 215.91,214.9 C215.91,214.9 215.97,214.88 215.97,214.88 C215.97,214.88 216.02,214.86 216.02,214.86 C216.02,214.86 216.08,214.83 216.08,214.83 C216.08,214.83 216.14,214.81 216.14,214.81 C216.14,214.81 216.2,214.78 216.2,214.78 C216.2,214.78 216.26,214.77 216.26,214.77 C216.26,214.77 216.32,214.75 216.32,214.75 C216.32,214.75 216.38,214.73 216.38,214.73 C216.38,214.73 216.44,214.71 216.44,214.71 C216.44,214.71 216.5,214.69 216.5,214.69 C216.5,214.69 216.56,214.67 216.56,214.67 C216.56,214.67 216.62,214.66 216.62,214.66 C216.62,214.66 216.68,214.65 216.68,214.65 C216.68,214.65 216.74,214.63 216.74,214.63 C216.74,214.63 216.81,214.62 216.81,214.62 C216.81,214.62 216.87,214.61 216.87,214.61 C216.87,214.61 216.93,214.6 216.93,214.6 C216.93,214.6 216.99,214.59 216.99,214.59 C216.99,214.59 217.05,214.58 217.05,214.58 C217.05,214.58 217.12,214.57 217.12,214.57 C217.12,214.57 217.18,214.57 217.18,214.57 C217.18,214.57 217.24,214.56 217.24,214.56 C217.24,214.56 217.3,214.56 217.3,214.56 C217.3,214.56 217.37,214.56 217.37,214.56 C217.37,214.56 217.43,214.55 217.43,214.55 C217.43,214.55 217.49,214.55 217.49,214.55 C217.49,214.55 217.56,214.55 217.56,214.55 C217.56,214.55 217.62,214.55 217.62,214.55c "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="fillAlpha" android:duration="33" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M217.62 214.55 C217.62,214.55 217.68,214.55 217.68,214.55 C217.68,214.55 217.74,214.56 217.74,214.56 C217.74,214.56 217.81,214.56 217.81,214.56 C217.81,214.56 217.87,214.56 217.87,214.56 C217.87,214.56 217.93,214.57 217.93,214.57 C217.93,214.57 218,214.57 218,214.57 C218,214.57 218.06,214.58 218.06,214.58 C218.06,214.58 218.12,214.59 218.12,214.59 C218.12,214.59 218.18,214.6 218.18,214.6 C218.18,214.6 218.24,214.61 218.24,214.61 C218.24,214.61 218.31,214.62 218.31,214.62 C218.31,214.62 218.37,214.63 218.37,214.63 C218.37,214.63 218.43,214.65 218.43,214.65 C218.43,214.65 218.49,214.66 218.49,214.66 C218.49,214.66 218.55,214.68 218.55,214.68 C218.55,214.68 218.61,214.69 218.61,214.69 C218.61,214.69 218.67,214.71 218.67,214.71 C218.67,214.71 218.73,214.73 218.73,214.73 C218.73,214.73 218.79,214.75 218.79,214.75 C218.79,214.75 218.85,214.77 218.85,214.77 C218.85,214.77 218.91,214.79 218.91,214.79 C218.91,214.79 218.97,214.81 218.97,214.81 C218.97,214.81 219.03,214.83 219.03,214.83 C219.03,214.83 219.09,214.85 219.09,214.85 C219.09,214.85 219.15,214.88 219.15,214.88 C219.15,214.88 219.2,214.9 219.2,214.9 C219.2,214.9 219.26,214.93 219.26,214.93 C219.26,214.93 219.32,214.96 219.32,214.96 C219.32,214.96 219.37,214.98 219.37,214.98 C219.37,214.98 219.43,215.01 219.43,215.01 C219.43,215.01 219.48,215.05 219.48,215.05 C219.48,215.05 219.54,215.08 219.54,215.08 C219.54,215.08 219.59,215.11 219.59,215.11 C219.59,215.11 219.65,215.14 219.65,215.14 C219.65,215.14 219.7,215.17 219.7,215.17 C219.7,215.17 219.75,215.21 219.75,215.21 C219.75,215.21 219.81,215.24 219.81,215.24 C219.81,215.24 219.86,215.28 219.86,215.28 C219.86,215.28 219.91,215.32 219.91,215.32 C219.91,215.32 219.96,215.35 219.96,215.35 C219.96,215.35 220.01,215.39 220.01,215.39 C220.01,215.39 220.06,215.43 220.06,215.43 C220.06,215.43 220.11,215.47 220.11,215.47 C220.11,215.47 220.16,215.51 220.16,215.51 C220.16,215.51 220.2,215.55 220.2,215.55 C220.2,215.55 220.25,215.59 220.25,215.59 C220.25,215.59 220.3,215.63 220.3,215.63 C220.3,215.63 220.34,215.68 220.34,215.68 C220.34,215.68 220.39,215.72 220.39,215.72 C220.39,215.72 220.43,215.77 220.43,215.77 C220.43,215.77 220.47,215.81 220.47,215.81 C220.47,215.81 220.52,215.86 220.52,215.86 C220.52,215.86 220.56,215.9 220.56,215.9 C220.56,215.9 220.6,215.95 220.6,215.95 C220.6,215.95 220.64,216 220.64,216 C220.64,216 220.68,216.05 220.68,216.05 C220.68,216.05 220.72,216.1 220.72,216.1 C220.72,216.1 220.76,216.15 220.76,216.15 C220.76,216.15 220.8,216.2 220.8,216.2 C220.8,216.2 220.83,216.25 220.83,216.25 C220.83,216.25 220.87,216.3 220.87,216.3 C220.87,216.3 220.9,216.36 220.9,216.36 C220.9,216.36 220.94,216.41 220.94,216.41 C220.94,216.41 220.97,216.46 220.97,216.46 C220.97,216.46 221,216.51 221,216.51 C221,216.51 221.03,216.57 221.03,216.57 C221.03,216.57 221.06,216.63 221.06,216.63 C221.06,216.63 221.09,216.68 221.09,216.68 C221.09,216.68 221.12,216.74 221.12,216.74 C221.12,216.74 221.15,216.79 221.15,216.79 C221.15,216.79 221.18,216.85 221.18,216.85 C221.18,216.85 221.21,216.91 221.21,216.91 C221.21,216.91 221.23,216.96 221.23,216.96 C221.23,216.96 221.25,217.02 221.25,217.02 C221.25,217.02 221.28,217.08 221.28,217.08 C221.28,217.08 221.3,217.14 221.3,217.14 C221.3,217.14 221.33,217.2 221.33,217.2 C221.33,217.2 221.34,217.26 221.34,217.26 C221.34,217.26 221.36,217.32 221.36,217.32 C221.36,217.32 221.38,217.38 221.38,217.38 C221.38,217.38 221.4,217.44 221.4,217.44 C221.4,217.44 221.42,217.5 221.42,217.5 C221.42,217.5 221.44,217.56 221.44,217.56 C221.44,217.56 221.45,217.62 221.45,217.62 C221.45,217.62 221.46,217.68 221.46,217.68 C221.46,217.68 221.48,217.74 221.48,217.74 C221.48,217.74 221.49,217.8 221.49,217.8 C221.49,217.8 221.5,217.87 221.5,217.87 C221.5,217.87 221.51,217.93 221.51,217.93 C221.51,217.93 221.52,217.99 221.52,217.99 C221.52,217.99 221.53,218.05 221.53,218.05 C221.53,218.05 221.54,218.11 221.54,218.11 C221.54,218.11 221.54,218.18 221.54,218.18 C221.54,218.18 221.55,218.24 221.55,218.24 C221.55,218.24 221.55,218.3 221.55,218.3 C221.55,218.3 221.55,218.37 221.55,218.37 C221.55,218.37 221.56,218.43 221.56,218.43 C221.56,218.43 221.56,218.49 221.56,218.49 C221.56,218.49 221.56,218.55 221.56,218.55 C221.56,218.55 221.56,218.62 221.56,218.62 C221.56,218.62 221.56,218.68 221.56,218.68 C221.56,218.68 221.55,218.74 221.55,218.74 C221.55,218.74 221.55,218.81 221.55,218.81 C221.55,218.81 221.55,218.87 221.55,218.87 C221.55,218.87 221.54,218.93 221.54,218.93 C221.54,218.93 221.54,218.99 221.54,218.99 C221.54,218.99 221.53,219.06 221.53,219.06 C221.53,219.06 221.52,219.12 221.52,219.12 C221.52,219.12 221.51,219.18 221.51,219.18 C221.51,219.18 221.5,219.24 221.5,219.24 C221.5,219.24 221.49,219.3 221.49,219.3 C221.49,219.3 221.48,219.37 221.48,219.37 C221.48,219.37 221.46,219.43 221.46,219.43 C221.46,219.43 221.45,219.49 221.45,219.49 C221.45,219.49 221.43,219.55 221.43,219.55 C221.43,219.55 221.42,219.61 221.42,219.61 C221.42,219.61 221.4,219.67 221.4,219.67 C221.4,219.67 221.39,219.73 221.39,219.73 C221.39,219.73 221.37,219.79 221.37,219.79 C221.37,219.79 221.34,219.85 221.34,219.85 C221.34,219.85 221.32,219.91 221.32,219.91 C221.32,219.91 221.3,219.97 221.3,219.97 C221.3,219.97 221.28,220.03 221.28,220.03 C221.28,220.03 221.26,220.09 221.26,220.09 C221.26,220.09 221.23,220.14 221.23,220.14 C221.23,220.14 221.21,220.2 221.21,220.2 C221.21,220.2 221.18,220.26 221.18,220.26 C221.18,220.26 221.15,220.32 221.15,220.32 C221.15,220.32 221.13,220.37 221.13,220.37 C221.13,220.37 221.1,220.43 221.1,220.43 C221.1,220.43 221.07,220.48 221.07,220.48 C221.07,220.48 221.03,220.54 221.03,220.54 C221.03,220.54 221,220.59 221,220.59 C221,220.59 220.97,220.65 220.97,220.65 C220.97,220.65 220.94,220.7 220.94,220.7 C220.94,220.7 220.9,220.75 220.9,220.75 C220.9,220.75 220.87,220.8 220.87,220.8 C220.87,220.8 220.83,220.86 220.83,220.86 C220.83,220.86 220.8,220.91 220.8,220.91 C220.8,220.91 220.76,220.96 220.76,220.96 C220.76,220.96 220.72,221.01 220.72,221.01 C220.72,221.01 220.68,221.06 220.68,221.06 C220.68,221.06 220.64,221.11 220.64,221.11 C220.64,221.11 220.6,221.15 220.6,221.15 C220.6,221.15 220.56,221.2 220.56,221.2 C220.56,221.2 220.52,221.25 220.52,221.25 C220.52,221.25 220.48,221.3 220.48,221.3 C220.48,221.3 220.43,221.34 220.43,221.34 C220.43,221.34 220.39,221.38 220.39,221.38 C220.39,221.38 220.34,221.43 220.34,221.43 C220.34,221.43 220.3,221.47 220.3,221.47 C220.3,221.47 220.25,221.52 220.25,221.52 C220.25,221.52 220.21,221.56 220.21,221.56 C220.21,221.56 220.16,221.6 220.16,221.6 C220.16,221.6 220.11,221.64 220.11,221.64 C220.11,221.64 220.06,221.68 220.06,221.68 C220.06,221.68 220.01,221.72 220.01,221.72 C220.01,221.72 219.96,221.76 219.96,221.76 C219.96,221.76 219.91,221.8 219.91,221.8 C219.91,221.8 219.86,221.83 219.86,221.83 C219.86,221.83 219.81,221.87 219.81,221.87 C219.81,221.87 219.75,221.9 219.75,221.9 C219.75,221.9 219.7,221.93 219.7,221.93 C219.7,221.93 219.65,221.97 219.65,221.97 C219.65,221.97 219.6,222 219.6,222 C219.6,222 219.54,222.03 219.54,222.03 C219.54,222.03 219.49,222.06 219.49,222.06 C219.49,222.06 219.43,222.09 219.43,222.09 C219.43,222.09 219.37,222.12 219.37,222.12 C219.37,222.12 219.32,222.15 219.32,222.15 C219.32,222.15 219.26,222.18 219.26,222.18 C219.26,222.18 219.21,222.2 219.21,222.2 C219.21,222.2 219.15,222.23 219.15,222.23 C219.15,222.23 219.09,222.25 219.09,222.25 C219.09,222.25 219.03,222.28 219.03,222.28 C219.03,222.28 218.97,222.3 218.97,222.3 C218.97,222.3 218.91,222.32 218.91,222.32 C218.91,222.32 218.85,222.34 218.85,222.34 C218.85,222.34 218.79,222.36 218.79,222.36 C218.79,222.36 218.73,222.38 218.73,222.38 C218.73,222.38 218.67,222.4 218.67,222.4 C218.67,222.4 218.61,222.42 218.61,222.42 C218.61,222.42 218.55,222.44 218.55,222.44 C218.55,222.44 218.49,222.45 218.49,222.45 C218.49,222.45 218.43,222.46 218.43,222.46 C218.43,222.46 218.37,222.47 218.37,222.47 C218.37,222.47 218.31,222.49 218.31,222.49 C218.31,222.49 218.25,222.5 218.25,222.5 C218.25,222.5 218.18,222.51 218.18,222.51 C218.18,222.51 218.12,222.52 218.12,222.52 C218.12,222.52 218.06,222.53 218.06,222.53 C218.06,222.53 218,222.54 218,222.54 C218,222.54 217.93,222.54 217.93,222.54 C217.93,222.54 217.87,222.55 217.87,222.55 C217.87,222.55 217.81,222.55 217.81,222.55 C217.81,222.55 217.75,222.55 217.75,222.55 C217.75,222.55 217.68,222.56 217.68,222.56 C217.68,222.56 217.62,222.56 217.62,222.56 C217.62,222.56 217.56,222.56 217.56,222.56 C217.56,222.56 217.49,222.56 217.49,222.56 C217.49,222.56 217.43,222.56 217.43,222.56 C217.43,222.56 217.37,222.55 217.37,222.55 C217.37,222.55 217.3,222.55 217.3,222.55 C217.3,222.55 217.24,222.55 217.24,222.55 C217.24,222.55 217.18,222.54 217.18,222.54 C217.18,222.54 217.12,222.54 217.12,222.54 C217.12,222.54 217.05,222.53 217.05,222.53 C217.05,222.53 216.99,222.52 216.99,222.52 C216.99,222.52 216.93,222.51 216.93,222.51 C216.93,222.51 216.87,222.5 216.87,222.5 C216.87,222.5 216.81,222.49 216.81,222.49 C216.81,222.49 216.74,222.48 216.74,222.48 C216.74,222.48 216.68,222.46 216.68,222.46 C216.68,222.46 216.62,222.45 216.62,222.45 C216.62,222.45 216.56,222.43 216.56,222.43 C216.56,222.43 216.5,222.42 216.5,222.42 C216.5,222.42 216.44,222.4 216.44,222.4 C216.44,222.4 216.38,222.38 216.38,222.38 C216.38,222.38 216.32,222.36 216.32,222.36 C216.32,222.36 216.26,222.34 216.26,222.34 C216.26,222.34 216.2,222.32 216.2,222.32 C216.2,222.32 216.14,222.3 216.14,222.3 C216.14,222.3 216.08,222.28 216.08,222.28 C216.08,222.28 216.02,222.26 216.02,222.26 C216.02,222.26 215.97,222.23 215.97,222.23 C215.97,222.23 215.91,222.2 215.91,222.2 C215.91,222.2 215.85,222.18 215.85,222.18 C215.85,222.18 215.79,222.15 215.79,222.15 C215.79,222.15 215.74,222.12 215.74,222.12 C215.74,222.12 215.68,222.1 215.68,222.1 C215.68,222.1 215.63,222.06 215.63,222.06 C215.63,222.06 215.57,222.03 215.57,222.03 C215.57,222.03 215.52,222 215.52,222 C215.52,222 215.46,221.97 215.46,221.97 C215.46,221.97 215.41,221.94 215.41,221.94 C215.41,221.94 215.36,221.9 215.36,221.9 C215.36,221.9 215.31,221.87 215.31,221.87 C215.31,221.87 215.25,221.83 215.25,221.83 C215.25,221.83 215.2,221.79 215.2,221.79 C215.2,221.79 215.15,221.76 215.15,221.76 C215.15,221.76 215.1,221.72 215.1,221.72 C215.1,221.72 215.05,221.68 215.05,221.68 C215.05,221.68 215,221.64 215,221.64 C215,221.64 214.96,221.6 214.96,221.6 C214.96,221.6 214.91,221.56 214.91,221.56 C214.91,221.56 214.86,221.52 214.86,221.52 C214.86,221.52 214.81,221.48 214.81,221.48 C214.81,221.48 214.77,221.43 214.77,221.43 C214.77,221.43 214.73,221.39 214.73,221.39 C214.73,221.39 214.68,221.34 214.68,221.34 C214.68,221.34 214.64,221.3 214.64,221.3 C214.64,221.3 214.59,221.25 214.59,221.25 C214.59,221.25 214.55,221.2 214.55,221.2 C214.55,221.2 214.51,221.15 214.51,221.15 C214.51,221.15 214.47,221.11 214.47,221.11 C214.47,221.11 214.43,221.06 214.43,221.06 C214.43,221.06 214.39,221.01 214.39,221.01 C214.39,221.01 214.35,220.96 214.35,220.96 C214.35,220.96 214.31,220.91 214.31,220.91 C214.31,220.91 214.28,220.86 214.28,220.86 C214.28,220.86 214.25,220.81 214.25,220.81 C214.25,220.81 214.21,220.75 214.21,220.75 C214.21,220.75 214.18,220.7 214.18,220.7 C214.18,220.7 214.14,220.65 214.14,220.65 C214.14,220.65 214.11,220.59 214.11,220.59 C214.11,220.59 214.08,220.54 214.08,220.54 C214.08,220.54 214.05,220.48 214.05,220.48 C214.05,220.48 214.02,220.43 214.02,220.43 C214.02,220.43 213.99,220.37 213.99,220.37 C213.99,220.37 213.96,220.32 213.96,220.32 C213.96,220.32 213.93,220.26 213.93,220.26 C213.93,220.26 213.91,220.2 213.91,220.2 C213.91,220.2 213.88,220.14 213.88,220.14 C213.88,220.14 213.86,220.09 213.86,220.09 C213.86,220.09 213.83,220.03 213.83,220.03 C213.83,220.03 213.81,219.97 213.81,219.97 C213.81,219.97 213.79,219.91 213.79,219.91 C213.79,219.91 213.77,219.85 213.77,219.85 C213.77,219.85 213.75,219.79 213.75,219.79 C213.75,219.79 213.73,219.73 213.73,219.73 C213.73,219.73 213.71,219.67 213.71,219.67 C213.71,219.67 213.69,219.61 213.69,219.61 C213.69,219.61 213.68,219.55 213.68,219.55 C213.68,219.55 213.66,219.49 213.66,219.49 C213.66,219.49 213.65,219.43 213.65,219.43 C213.65,219.43 213.64,219.37 213.64,219.37 C213.64,219.37 213.62,219.31 213.62,219.31 C213.62,219.31 213.61,219.24 213.61,219.24 C213.61,219.24 213.6,219.18 213.6,219.18 C213.6,219.18 213.59,219.12 213.59,219.12 C213.59,219.12 213.58,219.06 213.58,219.06 C213.58,219.06 213.57,218.99 213.57,218.99 C213.57,218.99 213.57,218.93 213.57,218.93 C213.57,218.93 213.56,218.87 213.56,218.87 C213.56,218.87 213.56,218.81 213.56,218.81 C213.56,218.81 213.56,218.74 213.56,218.74 C213.56,218.74 213.56,218.68 213.56,218.68 C213.56,218.68 213.55,218.62 213.55,218.62 C213.55,218.62 213.55,218.55 213.55,218.55 C213.55,218.55 213.55,218.49 213.55,218.49 C213.55,218.49 213.56,218.43 213.56,218.43 C213.56,218.43 213.56,218.37 213.56,218.37 C213.56,218.37 213.56,218.3 213.56,218.3 C213.56,218.3 213.56,218.24 213.56,218.24 C213.56,218.24 213.57,218.18 213.57,218.18 C213.57,218.18 213.57,218.12 213.57,218.12 C213.57,218.12 213.58,218.05 213.58,218.05 C213.58,218.05 213.59,217.99 213.59,217.99 C213.59,217.99 213.6,217.93 213.6,217.93 C213.6,217.93 213.61,217.87 213.61,217.87 C213.61,217.87 213.62,217.8 213.62,217.8 C213.62,217.8 213.63,217.74 213.63,217.74 C213.63,217.74 213.65,217.68 213.65,217.68 C213.65,217.68 213.66,217.62 213.66,217.62 C213.66,217.62 213.68,217.56 213.68,217.56 C213.68,217.56 213.69,217.5 213.69,217.5 C213.69,217.5 213.71,217.44 213.71,217.44 C213.71,217.44 213.73,217.38 213.73,217.38 C213.73,217.38 213.75,217.32 213.75,217.32 C213.75,217.32 213.77,217.26 213.77,217.26 C213.77,217.26 213.79,217.2 213.79,217.2 C213.79,217.2 213.81,217.14 213.81,217.14 C213.81,217.14 213.83,217.08 213.83,217.08 C213.83,217.08 213.85,217.02 213.85,217.02 C213.85,217.02 213.88,216.96 213.88,216.96 C213.88,216.96 213.91,216.91 213.91,216.91 C213.91,216.91 213.93,216.85 213.93,216.85 C213.93,216.85 213.96,216.79 213.96,216.79 C213.96,216.79 213.99,216.74 213.99,216.74 C213.99,216.74 214.02,216.68 214.02,216.68 C214.02,216.68 214.05,216.63 214.05,216.63 C214.05,216.63 214.08,216.57 214.08,216.57 C214.08,216.57 214.11,216.52 214.11,216.52 C214.11,216.52 214.14,216.46 214.14,216.46 C214.14,216.46 214.17,216.41 214.17,216.41 C214.17,216.41 214.21,216.36 214.21,216.36 C214.21,216.36 214.24,216.3 214.24,216.3 C214.24,216.3 214.28,216.25 214.28,216.25 C214.28,216.25 214.32,216.2 214.32,216.2 C214.32,216.2 214.35,216.15 214.35,216.15 C214.35,216.15 214.39,216.1 214.39,216.1 C214.39,216.1 214.43,216.05 214.43,216.05 C214.43,216.05 214.47,216 214.47,216 C214.47,216 214.51,215.96 214.51,215.96 C214.51,215.96 214.55,215.91 214.55,215.91 C214.55,215.91 214.59,215.86 214.59,215.86 C214.59,215.86 214.64,215.81 214.64,215.81 C214.64,215.81 214.68,215.77 214.68,215.77 C214.68,215.77 214.73,215.72 214.73,215.72 C214.73,215.72 214.77,215.68 214.77,215.68 C214.77,215.68 214.82,215.64 214.82,215.64 C214.82,215.64 214.86,215.59 214.86,215.59 C214.86,215.59 214.91,215.55 214.91,215.55 C214.91,215.55 214.96,215.51 214.96,215.51 C214.96,215.51 215,215.47 215,215.47 C215,215.47 215.05,215.43 215.05,215.43 C215.05,215.43 215.1,215.39 215.1,215.39 C215.1,215.39 215.15,215.35 215.15,215.35 C215.15,215.35 215.2,215.31 215.2,215.31 C215.2,215.31 215.25,215.28 215.25,215.28 C215.25,215.28 215.31,215.24 215.31,215.24 C215.31,215.24 215.36,215.21 215.36,215.21 C215.36,215.21 215.41,215.17 215.41,215.17 C215.41,215.17 215.46,215.14 215.46,215.14 C215.46,215.14 215.52,215.11 215.52,215.11 C215.52,215.11 215.57,215.08 215.57,215.08 C215.57,215.08 215.63,215.05 215.63,215.05 C215.63,215.05 215.68,215.02 215.68,215.02 C215.68,215.02 215.74,214.99 215.74,214.99 C215.74,214.99 215.79,214.96 215.79,214.96 C215.79,214.96 215.85,214.93 215.85,214.93 C215.85,214.93 215.91,214.9 215.91,214.9 C215.91,214.9 215.97,214.88 215.97,214.88 C215.97,214.88 216.02,214.86 216.02,214.86 C216.02,214.86 216.08,214.83 216.08,214.83 C216.08,214.83 216.14,214.81 216.14,214.81 C216.14,214.81 216.2,214.78 216.2,214.78 C216.2,214.78 216.26,214.77 216.26,214.77 C216.26,214.77 216.32,214.75 216.32,214.75 C216.32,214.75 216.38,214.73 216.38,214.73 C216.38,214.73 216.44,214.71 216.44,214.71 C216.44,214.71 216.5,214.69 216.5,214.69 C216.5,214.69 216.56,214.67 216.56,214.67 C216.56,214.67 216.62,214.66 216.62,214.66 C216.62,214.66 216.68,214.65 216.68,214.65 C216.68,214.65 216.74,214.63 216.74,214.63 C216.74,214.63 216.81,214.62 216.81,214.62 C216.81,214.62 216.87,214.61 216.87,214.61 C216.87,214.61 216.93,214.6 216.93,214.6 C216.93,214.6 216.99,214.59 216.99,214.59 C216.99,214.59 217.05,214.58 217.05,214.58 C217.05,214.58 217.12,214.57 217.12,214.57 C217.12,214.57 217.18,214.57 217.18,214.57 C217.18,214.57 217.24,214.56 217.24,214.56 C217.24,214.56 217.3,214.56 217.3,214.56 C217.3,214.56 217.37,214.56 217.37,214.56 C217.37,214.56 217.43,214.55 217.43,214.55 C217.43,214.55 217.49,214.55 217.49,214.55 C217.49,214.55 217.56,214.55 217.56,214.55 C217.56,214.55 217.62,214.55 217.62,214.55c " android:valueTo="M217.59 202.73 C217.59,202.73 217.85,202.75 217.85,202.75 C217.85,202.75 218.11,202.76 218.11,202.76 C218.11,202.76 218.37,202.79 218.37,202.79 C218.37,202.79 218.63,202.83 218.63,202.83 C218.63,202.83 218.88,202.88 218.88,202.88 C218.88,202.88 219.14,202.93 219.14,202.93 C219.14,202.93 219.39,203.01 219.39,203.01 C219.39,203.01 219.64,203.09 219.64,203.09 C219.64,203.09 219.88,203.18 219.88,203.18 C219.88,203.18 220.12,203.28 220.12,203.28 C220.12,203.28 220.36,203.39 220.36,203.39 C220.36,203.39 220.59,203.51 220.59,203.51 C220.59,203.51 220.82,203.64 220.82,203.64 C220.82,203.64 221.04,203.78 221.04,203.78 C221.04,203.78 221.26,203.92 221.26,203.92 C221.26,203.92 221.46,204.09 221.46,204.09 C221.46,204.09 221.66,204.25 221.66,204.25 C221.66,204.25 221.87,204.42 221.87,204.42 C221.87,204.42 222.05,204.61 222.05,204.61 C222.05,204.61 222.23,204.79 222.23,204.79 C222.23,204.79 222.4,204.99 222.4,204.99 C222.4,204.99 222.57,205.19 222.57,205.19 C222.57,205.19 222.72,205.41 222.72,205.41 C222.72,205.41 222.86,205.62 222.86,205.62 C222.86,205.62 223.01,205.84 223.01,205.84 C223.01,205.84 223.14,206.06 223.14,206.06 C223.14,206.06 223.27,206.29 223.27,206.29 C223.27,206.29 223.4,206.52 223.4,206.52 C223.4,206.52 223.53,206.75 223.53,206.75 C223.53,206.75 223.66,206.97 223.66,206.97 C223.66,206.97 223.79,207.2 223.79,207.2 C223.79,207.2 223.92,207.43 223.92,207.43 C223.92,207.43 224.05,207.65 224.05,207.65 C224.05,207.65 224.18,207.88 224.18,207.88 C224.18,207.88 224.31,208.11 224.31,208.11 C224.31,208.11 224.44,208.34 224.44,208.34 C224.44,208.34 224.56,208.56 224.56,208.56 C224.56,208.56 224.69,208.79 224.69,208.79 C224.69,208.79 224.82,209.02 224.82,209.02 C224.82,209.02 224.95,209.25 224.95,209.25 C224.95,209.25 225.08,209.47 225.08,209.47 C225.08,209.47 225.21,209.7 225.21,209.7 C225.21,209.7 225.34,209.93 225.34,209.93 C225.34,209.93 225.47,210.15 225.47,210.15 C225.47,210.15 225.6,210.38 225.6,210.38 C225.6,210.38 225.73,210.61 225.73,210.61 C225.73,210.61 225.86,210.84 225.86,210.84 C225.86,210.84 225.99,211.06 225.99,211.06 C225.99,211.06 226.11,211.29 226.11,211.29 C226.11,211.29 226.24,211.52 226.24,211.52 C226.24,211.52 226.37,211.75 226.37,211.75 C226.37,211.75 226.5,211.97 226.5,211.97 C226.5,211.97 226.63,212.2 226.63,212.2 C226.63,212.2 226.76,212.43 226.76,212.43 C226.76,212.43 226.89,212.65 226.89,212.65 C226.89,212.65 227.02,212.88 227.02,212.88 C227.02,212.88 227.15,213.11 227.15,213.11 C227.15,213.11 227.28,213.34 227.28,213.34 C227.28,213.34 227.41,213.56 227.41,213.56 C227.41,213.56 227.54,213.79 227.54,213.79 C227.54,213.79 227.66,214.02 227.66,214.02 C227.66,214.02 227.79,214.25 227.79,214.25 C227.79,214.25 227.92,214.47 227.92,214.47 C227.92,214.47 228.05,214.7 228.05,214.7 C228.05,214.7 228.18,214.93 228.18,214.93 C228.18,214.93 228.31,215.15 228.31,215.15 C228.31,215.15 228.44,215.38 228.44,215.38 C228.44,215.38 228.57,215.61 228.57,215.61 C228.57,215.61 228.7,215.83 228.7,215.83 C228.7,215.83 228.83,216.06 228.83,216.06 C228.83,216.06 228.96,216.29 228.96,216.29 C228.96,216.29 229.09,216.52 229.09,216.52 C229.09,216.52 229.21,216.74 229.21,216.74 C229.21,216.74 229.34,216.97 229.34,216.97 C229.34,216.97 229.47,217.2 229.47,217.2 C229.47,217.2 229.6,217.43 229.6,217.43 C229.6,217.43 229.73,217.65 229.73,217.65 C229.73,217.65 229.86,217.88 229.86,217.88 C229.86,217.88 229.99,218.11 229.99,218.11 C229.99,218.11 230.12,218.33 230.12,218.33 C230.12,218.33 230.25,218.56 230.25,218.56 C230.25,218.56 230.38,218.79 230.38,218.79 C230.38,218.79 230.51,219.02 230.51,219.02 C230.51,219.02 230.64,219.24 230.64,219.24 C230.64,219.24 230.76,219.47 230.76,219.47 C230.76,219.47 230.89,219.7 230.89,219.7 C230.89,219.7 231.02,219.93 231.02,219.93 C231.02,219.93 231.15,220.15 231.15,220.15 C231.15,220.15 231.28,220.38 231.28,220.38 C231.28,220.38 231.41,220.61 231.41,220.61 C231.41,220.61 231.54,220.83 231.54,220.83 C231.54,220.83 231.67,221.06 231.67,221.06 C231.67,221.06 231.8,221.29 231.8,221.29 C231.8,221.29 231.93,221.52 231.93,221.52 C231.93,221.52 232.06,221.74 232.06,221.74 C232.06,221.74 232.19,221.97 232.19,221.97 C232.19,221.97 232.31,222.2 232.31,222.2 C232.31,222.2 232.44,222.43 232.44,222.43 C232.44,222.43 232.57,222.65 232.57,222.65 C232.57,222.65 232.7,222.88 232.7,222.88 C232.7,222.88 232.83,223.11 232.83,223.11 C232.83,223.11 232.96,223.33 232.96,223.33 C232.96,223.33 233.09,223.56 233.09,223.56 C233.09,223.56 233.22,223.79 233.22,223.79 C233.22,223.79 233.35,224.02 233.35,224.02 C233.35,224.02 233.48,224.24 233.48,224.24 C233.48,224.24 233.61,224.47 233.61,224.47 C233.61,224.47 233.73,224.7 233.73,224.7 C233.73,224.7 233.84,224.94 233.84,224.94 C233.84,224.94 233.96,225.17 233.96,225.17 C233.96,225.17 234.07,225.41 234.07,225.41 C234.07,225.41 234.16,225.65 234.16,225.65 C234.16,225.65 234.24,225.9 234.24,225.9 C234.24,225.9 234.32,226.15 234.32,226.15 C234.32,226.15 234.38,226.4 234.38,226.4 C234.38,226.4 234.43,226.66 234.43,226.66 C234.43,226.66 234.48,226.92 234.48,226.92 C234.48,226.92 234.51,227.18 234.51,227.18 C234.51,227.18 234.53,227.44 234.53,227.44 C234.53,227.44 234.54,227.7 234.54,227.7 C234.54,227.7 234.54,227.96 234.54,227.96 C234.54,227.96 234.53,228.22 234.53,228.22 C234.53,228.22 234.51,228.48 234.51,228.48 C234.51,228.48 234.48,228.74 234.48,228.74 C234.48,228.74 234.43,229 234.43,229 C234.43,229 234.39,229.25 234.39,229.25 C234.39,229.25 234.32,229.51 234.32,229.51 C234.32,229.51 234.25,229.76 234.25,229.76 C234.25,229.76 234.17,230.01 234.17,230.01 C234.17,230.01 234.08,230.25 234.08,230.25 C234.08,230.25 233.97,230.49 233.97,230.49 C233.97,230.49 233.86,230.73 233.86,230.73 C233.86,230.73 233.75,230.96 233.75,230.96 C233.75,230.96 233.61,231.18 233.61,231.18 C233.61,231.18 233.48,231.41 233.48,231.41 C233.48,231.41 233.33,231.63 233.33,231.63 C233.33,231.63 233.17,231.83 233.17,231.83 C233.17,231.83 233.01,232.04 233.01,232.04 C233.01,232.04 232.84,232.24 232.84,232.24 C232.84,232.24 232.66,232.42 232.66,232.42 C232.66,232.42 232.47,232.61 232.47,232.61 C232.47,232.61 232.28,232.78 232.28,232.78 C232.28,232.78 232.08,232.95 232.08,232.95 C232.08,232.95 231.87,233.11 231.87,233.11 C231.87,233.11 231.66,233.26 231.66,233.26 C231.66,233.26 231.43,233.39 231.43,233.39 C231.43,233.39 231.21,233.53 231.21,233.53 C231.21,233.53 230.98,233.65 230.98,233.65 C230.98,233.65 230.74,233.76 230.74,233.76 C230.74,233.76 230.5,233.87 230.5,233.87 C230.5,233.87 230.26,233.96 230.26,233.96 C230.26,233.96 230.01,234.04 230.01,234.04 C230.01,234.04 229.76,234.12 229.76,234.12 C229.76,234.12 229.51,234.17 229.51,234.17 C229.51,234.17 229.25,234.23 229.25,234.23 C229.25,234.23 228.99,234.26 228.99,234.26 C228.99,234.26 228.73,234.3 228.73,234.3 C228.73,234.3 228.47,234.31 228.47,234.31 C228.47,234.31 228.21,234.32 228.21,234.32 C228.21,234.32 227.95,234.32 227.95,234.32 C227.95,234.32 227.69,234.32 227.69,234.32 C227.69,234.32 227.43,234.32 227.43,234.32 C227.43,234.32 227.16,234.32 227.16,234.32 C227.16,234.32 226.9,234.32 226.9,234.32 C226.9,234.32 226.64,234.32 226.64,234.32 C226.64,234.32 226.38,234.32 226.38,234.32 C226.38,234.32 226.12,234.32 226.12,234.32 C226.12,234.32 225.86,234.32 225.86,234.32 C225.86,234.32 225.6,234.32 225.6,234.32 C225.6,234.32 225.33,234.32 225.33,234.32 C225.33,234.32 225.07,234.32 225.07,234.32 C225.07,234.32 224.81,234.32 224.81,234.32 C224.81,234.32 224.55,234.32 224.55,234.32 C224.55,234.32 224.29,234.32 224.29,234.32 C224.29,234.32 224.03,234.32 224.03,234.32 C224.03,234.32 223.77,234.32 223.77,234.32 C223.77,234.32 223.5,234.32 223.5,234.32 C223.5,234.32 223.24,234.32 223.24,234.32 C223.24,234.32 222.98,234.32 222.98,234.32 C222.98,234.32 222.72,234.32 222.72,234.32 C222.72,234.32 222.46,234.32 222.46,234.32 C222.46,234.32 222.2,234.32 222.2,234.32 C222.2,234.32 221.94,234.32 221.94,234.32 C221.94,234.32 221.68,234.32 221.68,234.32 C221.68,234.32 221.41,234.32 221.41,234.32 C221.41,234.32 221.15,234.32 221.15,234.32 C221.15,234.32 220.89,234.32 220.89,234.32 C220.89,234.32 220.63,234.32 220.63,234.32 C220.63,234.32 220.37,234.32 220.37,234.32 C220.37,234.32 220.11,234.32 220.11,234.32 C220.11,234.32 219.85,234.32 219.85,234.32 C219.85,234.32 219.58,234.32 219.58,234.32 C219.58,234.32 219.32,234.32 219.32,234.32 C219.32,234.32 219.06,234.32 219.06,234.32 C219.06,234.32 218.8,234.32 218.8,234.32 C218.8,234.32 218.54,234.32 218.54,234.32 C218.54,234.32 218.28,234.32 218.28,234.32 C218.28,234.32 218.02,234.32 218.02,234.32 C218.02,234.32 217.75,234.32 217.75,234.32 C217.75,234.32 217.49,234.32 217.49,234.32 C217.49,234.32 217.23,234.32 217.23,234.32 C217.23,234.32 216.97,234.32 216.97,234.32 C216.97,234.32 216.71,234.32 216.71,234.32 C216.71,234.32 216.45,234.32 216.45,234.32 C216.45,234.32 216.19,234.32 216.19,234.32 C216.19,234.32 215.92,234.32 215.92,234.32 C215.92,234.32 215.66,234.32 215.66,234.32 C215.66,234.32 215.4,234.32 215.4,234.32 C215.4,234.32 215.14,234.32 215.14,234.32 C215.14,234.32 214.88,234.32 214.88,234.32 C214.88,234.32 214.62,234.32 214.62,234.32 C214.62,234.32 214.36,234.32 214.36,234.32 C214.36,234.32 214.1,234.32 214.1,234.32 C214.1,234.32 213.83,234.32 213.83,234.32 C213.83,234.32 213.57,234.32 213.57,234.32 C213.57,234.32 213.31,234.32 213.31,234.32 C213.31,234.32 213.05,234.32 213.05,234.32 C213.05,234.32 212.79,234.32 212.79,234.32 C212.79,234.32 212.53,234.32 212.53,234.32 C212.53,234.32 212.27,234.32 212.27,234.32 C212.27,234.32 212,234.32 212,234.32 C212,234.32 211.74,234.32 211.74,234.32 C211.74,234.32 211.48,234.32 211.48,234.32 C211.48,234.32 211.22,234.32 211.22,234.32 C211.22,234.32 210.96,234.32 210.96,234.32 C210.96,234.32 210.7,234.32 210.7,234.32 C210.7,234.32 210.44,234.32 210.44,234.32 C210.44,234.32 210.17,234.32 210.17,234.32 C210.17,234.32 209.91,234.32 209.91,234.32 C209.91,234.32 209.65,234.32 209.65,234.32 C209.65,234.32 209.39,234.32 209.39,234.32 C209.39,234.32 209.13,234.32 209.13,234.32 C209.13,234.32 208.87,234.32 208.87,234.32 C208.87,234.32 208.61,234.32 208.61,234.32 C208.61,234.32 208.34,234.32 208.34,234.32 C208.34,234.32 208.08,234.32 208.08,234.32 C208.08,234.32 207.82,234.32 207.82,234.32 C207.82,234.32 207.56,234.32 207.56,234.32 C207.56,234.32 207.3,234.32 207.3,234.32 C207.3,234.32 207.04,234.32 207.04,234.32 C207.04,234.32 206.78,234.32 206.78,234.32 C206.78,234.32 206.52,234.3 206.52,234.3 C206.52,234.3 206.26,234.28 206.26,234.28 C206.26,234.28 206,234.25 206,234.25 C206,234.25 205.74,234.21 205.74,234.21 C205.74,234.21 205.48,234.15 205.48,234.15 C205.48,234.15 205.23,234.09 205.23,234.09 C205.23,234.09 204.98,234.01 204.98,234.01 C204.98,234.01 204.73,233.93 204.73,233.93 C204.73,233.93 204.49,233.83 204.49,233.83 C204.49,233.83 204.25,233.72 204.25,233.72 C204.25,233.72 204.01,233.62 204.01,233.62 C204.01,233.62 203.79,233.48 203.79,233.48 C203.79,233.48 203.57,233.35 203.57,233.35 C203.57,233.35 203.34,233.21 203.34,233.21 C203.34,233.21 203.14,233.05 203.14,233.05 C203.14,233.05 202.93,232.89 202.93,232.89 C202.93,232.89 202.73,232.73 202.73,232.73 C202.73,232.73 202.54,232.54 202.54,232.54 C202.54,232.54 202.36,232.36 202.36,232.36 C202.36,232.36 202.17,232.17 202.17,232.17 C202.17,232.17 202.01,231.97 202.01,231.97 C202.01,231.97 201.85,231.76 201.85,231.76 C201.85,231.76 201.69,231.55 201.69,231.55 C201.69,231.55 201.55,231.33 201.55,231.33 C201.55,231.33 201.42,231.11 201.42,231.11 C201.42,231.11 201.29,230.88 201.29,230.88 C201.29,230.88 201.18,230.64 201.18,230.64 C201.18,230.64 201.07,230.4 201.07,230.4 C201.07,230.4 200.96,230.17 200.96,230.17 C200.96,230.17 200.88,229.92 200.88,229.92 C200.88,229.92 200.8,229.67 200.8,229.67 C200.8,229.67 200.73,229.42 200.73,229.42 C200.73,229.42 200.68,229.16 200.68,229.16 C200.68,229.16 200.63,228.91 200.63,228.91 C200.63,228.91 200.58,228.65 200.58,228.65 C200.58,228.65 200.56,228.39 200.56,228.39 C200.56,228.39 200.55,228.13 200.55,228.13 C200.55,228.13 200.53,227.87 200.53,227.87 C200.53,227.87 200.54,227.61 200.54,227.61 C200.54,227.61 200.56,227.35 200.56,227.35 C200.56,227.35 200.58,227.08 200.58,227.08 C200.58,227.08 200.62,226.83 200.62,226.83 C200.62,226.83 200.67,226.57 200.67,226.57 C200.67,226.57 200.72,226.31 200.72,226.31 C200.72,226.31 200.79,226.06 200.79,226.06 C200.79,226.06 200.87,225.81 200.87,225.81 C200.87,225.81 200.95,225.57 200.95,225.57 C200.95,225.57 201.05,225.32 201.05,225.32 C201.05,225.32 201.16,225.09 201.16,225.09 C201.16,225.09 201.27,224.85 201.27,224.85 C201.27,224.85 201.39,224.62 201.39,224.62 C201.39,224.62 201.52,224.39 201.52,224.39 C201.52,224.39 201.65,224.16 201.65,224.16 C201.65,224.16 201.78,223.94 201.78,223.94 C201.78,223.94 201.91,223.71 201.91,223.71 C201.91,223.71 202.03,223.48 202.03,223.48 C202.03,223.48 202.16,223.25 202.16,223.25 C202.16,223.25 202.29,223.03 202.29,223.03 C202.29,223.03 202.42,222.8 202.42,222.8 C202.42,222.8 202.55,222.57 202.55,222.57 C202.55,222.57 202.68,222.35 202.68,222.35 C202.68,222.35 202.81,222.12 202.81,222.12 C202.81,222.12 202.94,221.89 202.94,221.89 C202.94,221.89 203.07,221.66 203.07,221.66 C203.07,221.66 203.2,221.44 203.2,221.44 C203.2,221.44 203.33,221.21 203.33,221.21 C203.33,221.21 203.46,220.98 203.46,220.98 C203.46,220.98 203.58,220.76 203.58,220.76 C203.58,220.76 203.71,220.53 203.71,220.53 C203.71,220.53 203.84,220.3 203.84,220.3 C203.84,220.3 203.97,220.07 203.97,220.07 C203.97,220.07 204.1,219.85 204.1,219.85 C204.1,219.85 204.23,219.62 204.23,219.62 C204.23,219.62 204.36,219.39 204.36,219.39 C204.36,219.39 204.49,219.16 204.49,219.16 C204.49,219.16 204.62,218.94 204.62,218.94 C204.62,218.94 204.75,218.71 204.75,218.71 C204.75,218.71 204.88,218.48 204.88,218.48 C204.88,218.48 205.01,218.26 205.01,218.26 C205.01,218.26 205.13,218.03 205.13,218.03 C205.13,218.03 205.26,217.8 205.26,217.8 C205.26,217.8 205.39,217.57 205.39,217.57 C205.39,217.57 205.52,217.35 205.52,217.35 C205.52,217.35 205.65,217.12 205.65,217.12 C205.65,217.12 205.78,216.89 205.78,216.89 C205.78,216.89 205.91,216.66 205.91,216.66 C205.91,216.66 206.04,216.44 206.04,216.44 C206.04,216.44 206.17,216.21 206.17,216.21 C206.17,216.21 206.3,215.98 206.3,215.98 C206.3,215.98 206.43,215.76 206.43,215.76 C206.43,215.76 206.56,215.53 206.56,215.53 C206.56,215.53 206.68,215.3 206.68,215.3 C206.68,215.3 206.81,215.07 206.81,215.07 C206.81,215.07 206.94,214.85 206.94,214.85 C206.94,214.85 207.07,214.62 207.07,214.62 C207.07,214.62 207.2,214.39 207.2,214.39 C207.2,214.39 207.33,214.17 207.33,214.17 C207.33,214.17 207.46,213.94 207.46,213.94 C207.46,213.94 207.59,213.71 207.59,213.71 C207.59,213.71 207.72,213.48 207.72,213.48 C207.72,213.48 207.85,213.26 207.85,213.26 C207.85,213.26 207.98,213.03 207.98,213.03 C207.98,213.03 208.11,212.8 208.11,212.8 C208.11,212.8 208.23,212.57 208.23,212.57 C208.23,212.57 208.36,212.35 208.36,212.35 C208.36,212.35 208.49,212.12 208.49,212.12 C208.49,212.12 208.62,211.89 208.62,211.89 C208.62,211.89 208.75,211.67 208.75,211.67 C208.75,211.67 208.88,211.44 208.88,211.44 C208.88,211.44 209.01,211.21 209.01,211.21 C209.01,211.21 209.14,210.98 209.14,210.98 C209.14,210.98 209.27,210.76 209.27,210.76 C209.27,210.76 209.4,210.53 209.4,210.53 C209.4,210.53 209.53,210.3 209.53,210.3 C209.53,210.3 209.66,210.08 209.66,210.08 C209.66,210.08 209.78,209.85 209.78,209.85 C209.78,209.85 209.91,209.62 209.91,209.62 C209.91,209.62 210.04,209.39 210.04,209.39 C210.04,209.39 210.17,209.17 210.17,209.17 C210.17,209.17 210.3,208.94 210.3,208.94 C210.3,208.94 210.43,208.71 210.43,208.71 C210.43,208.71 210.56,208.48 210.56,208.48 C210.56,208.48 210.69,208.26 210.69,208.26 C210.69,208.26 210.82,208.03 210.82,208.03 C210.82,208.03 210.95,207.8 210.95,207.8 C210.95,207.8 211.08,207.58 211.08,207.58 C211.08,207.58 211.21,207.35 211.21,207.35 C211.21,207.35 211.33,207.12 211.33,207.12 C211.33,207.12 211.46,206.89 211.46,206.89 C211.46,206.89 211.59,206.67 211.59,206.67 C211.59,206.67 211.72,206.44 211.72,206.44 C211.72,206.44 211.85,206.21 211.85,206.21 C211.85,206.21 211.98,205.98 211.98,205.98 C211.98,205.98 212.13,205.76 212.13,205.76 C212.13,205.76 212.27,205.54 212.27,205.54 C212.27,205.54 212.41,205.33 212.41,205.33 C212.41,205.33 212.57,205.12 212.57,205.12 C212.57,205.12 212.74,204.92 212.74,204.92 C212.74,204.92 212.91,204.72 212.91,204.72 C212.91,204.72 213.1,204.54 213.1,204.54 C213.1,204.54 213.29,204.36 213.29,204.36 C213.29,204.36 213.49,204.19 213.49,204.19 C213.49,204.19 213.69,204.03 213.69,204.03 C213.69,204.03 213.9,203.87 213.9,203.87 C213.9,203.87 214.12,203.73 214.12,203.73 C214.12,203.73 214.34,203.59 214.34,203.59 C214.34,203.59 214.57,203.46 214.57,203.46 C214.57,203.46 214.81,203.35 214.81,203.35 C214.81,203.35 215.04,203.24 215.04,203.24 C215.04,203.24 215.28,203.14 215.28,203.14 C215.28,203.14 215.53,203.06 215.53,203.06 C215.53,203.06 215.78,202.98 215.78,202.98 C215.78,202.98 216.03,202.91 216.03,202.91 C216.03,202.91 216.29,202.86 216.29,202.86 C216.29,202.86 216.55,202.82 216.55,202.82 C216.55,202.82 216.8,202.77 216.8,202.77 C216.8,202.77 217.07,202.76 217.07,202.76 C217.07,202.76 217.33,202.74 217.33,202.74 C217.33,202.74 217.59,202.73 217.59,202.73c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="283" android:startOffset="67" android:valueFrom="M217.59 202.73 C217.59,202.73 217.85,202.75 217.85,202.75 C217.85,202.75 218.11,202.76 218.11,202.76 C218.11,202.76 218.37,202.79 218.37,202.79 C218.37,202.79 218.63,202.83 218.63,202.83 C218.63,202.83 218.88,202.88 218.88,202.88 C218.88,202.88 219.14,202.93 219.14,202.93 C219.14,202.93 219.39,203.01 219.39,203.01 C219.39,203.01 219.64,203.09 219.64,203.09 C219.64,203.09 219.88,203.18 219.88,203.18 C219.88,203.18 220.12,203.28 220.12,203.28 C220.12,203.28 220.36,203.39 220.36,203.39 C220.36,203.39 220.59,203.51 220.59,203.51 C220.59,203.51 220.82,203.64 220.82,203.64 C220.82,203.64 221.04,203.78 221.04,203.78 C221.04,203.78 221.26,203.92 221.26,203.92 C221.26,203.92 221.46,204.09 221.46,204.09 C221.46,204.09 221.66,204.25 221.66,204.25 C221.66,204.25 221.87,204.42 221.87,204.42 C221.87,204.42 222.05,204.61 222.05,204.61 C222.05,204.61 222.23,204.79 222.23,204.79 C222.23,204.79 222.4,204.99 222.4,204.99 C222.4,204.99 222.57,205.19 222.57,205.19 C222.57,205.19 222.72,205.41 222.72,205.41 C222.72,205.41 222.86,205.62 222.86,205.62 C222.86,205.62 223.01,205.84 223.01,205.84 C223.01,205.84 223.14,206.06 223.14,206.06 C223.14,206.06 223.27,206.29 223.27,206.29 C223.27,206.29 223.4,206.52 223.4,206.52 C223.4,206.52 223.53,206.75 223.53,206.75 C223.53,206.75 223.66,206.97 223.66,206.97 C223.66,206.97 223.79,207.2 223.79,207.2 C223.79,207.2 223.92,207.43 223.92,207.43 C223.92,207.43 224.05,207.65 224.05,207.65 C224.05,207.65 224.18,207.88 224.18,207.88 C224.18,207.88 224.31,208.11 224.31,208.11 C224.31,208.11 224.44,208.34 224.44,208.34 C224.44,208.34 224.56,208.56 224.56,208.56 C224.56,208.56 224.69,208.79 224.69,208.79 C224.69,208.79 224.82,209.02 224.82,209.02 C224.82,209.02 224.95,209.25 224.95,209.25 C224.95,209.25 225.08,209.47 225.08,209.47 C225.08,209.47 225.21,209.7 225.21,209.7 C225.21,209.7 225.34,209.93 225.34,209.93 C225.34,209.93 225.47,210.15 225.47,210.15 C225.47,210.15 225.6,210.38 225.6,210.38 C225.6,210.38 225.73,210.61 225.73,210.61 C225.73,210.61 225.86,210.84 225.86,210.84 C225.86,210.84 225.99,211.06 225.99,211.06 C225.99,211.06 226.11,211.29 226.11,211.29 C226.11,211.29 226.24,211.52 226.24,211.52 C226.24,211.52 226.37,211.75 226.37,211.75 C226.37,211.75 226.5,211.97 226.5,211.97 C226.5,211.97 226.63,212.2 226.63,212.2 C226.63,212.2 226.76,212.43 226.76,212.43 C226.76,212.43 226.89,212.65 226.89,212.65 C226.89,212.65 227.02,212.88 227.02,212.88 C227.02,212.88 227.15,213.11 227.15,213.11 C227.15,213.11 227.28,213.34 227.28,213.34 C227.28,213.34 227.41,213.56 227.41,213.56 C227.41,213.56 227.54,213.79 227.54,213.79 C227.54,213.79 227.66,214.02 227.66,214.02 C227.66,214.02 227.79,214.25 227.79,214.25 C227.79,214.25 227.92,214.47 227.92,214.47 C227.92,214.47 228.05,214.7 228.05,214.7 C228.05,214.7 228.18,214.93 228.18,214.93 C228.18,214.93 228.31,215.15 228.31,215.15 C228.31,215.15 228.44,215.38 228.44,215.38 C228.44,215.38 228.57,215.61 228.57,215.61 C228.57,215.61 228.7,215.83 228.7,215.83 C228.7,215.83 228.83,216.06 228.83,216.06 C228.83,216.06 228.96,216.29 228.96,216.29 C228.96,216.29 229.09,216.52 229.09,216.52 C229.09,216.52 229.21,216.74 229.21,216.74 C229.21,216.74 229.34,216.97 229.34,216.97 C229.34,216.97 229.47,217.2 229.47,217.2 C229.47,217.2 229.6,217.43 229.6,217.43 C229.6,217.43 229.73,217.65 229.73,217.65 C229.73,217.65 229.86,217.88 229.86,217.88 C229.86,217.88 229.99,218.11 229.99,218.11 C229.99,218.11 230.12,218.33 230.12,218.33 C230.12,218.33 230.25,218.56 230.25,218.56 C230.25,218.56 230.38,218.79 230.38,218.79 C230.38,218.79 230.51,219.02 230.51,219.02 C230.51,219.02 230.64,219.24 230.64,219.24 C230.64,219.24 230.76,219.47 230.76,219.47 C230.76,219.47 230.89,219.7 230.89,219.7 C230.89,219.7 231.02,219.93 231.02,219.93 C231.02,219.93 231.15,220.15 231.15,220.15 C231.15,220.15 231.28,220.38 231.28,220.38 C231.28,220.38 231.41,220.61 231.41,220.61 C231.41,220.61 231.54,220.83 231.54,220.83 C231.54,220.83 231.67,221.06 231.67,221.06 C231.67,221.06 231.8,221.29 231.8,221.29 C231.8,221.29 231.93,221.52 231.93,221.52 C231.93,221.52 232.06,221.74 232.06,221.74 C232.06,221.74 232.19,221.97 232.19,221.97 C232.19,221.97 232.31,222.2 232.31,222.2 C232.31,222.2 232.44,222.43 232.44,222.43 C232.44,222.43 232.57,222.65 232.57,222.65 C232.57,222.65 232.7,222.88 232.7,222.88 C232.7,222.88 232.83,223.11 232.83,223.11 C232.83,223.11 232.96,223.33 232.96,223.33 C232.96,223.33 233.09,223.56 233.09,223.56 C233.09,223.56 233.22,223.79 233.22,223.79 C233.22,223.79 233.35,224.02 233.35,224.02 C233.35,224.02 233.48,224.24 233.48,224.24 C233.48,224.24 233.61,224.47 233.61,224.47 C233.61,224.47 233.73,224.7 233.73,224.7 C233.73,224.7 233.84,224.94 233.84,224.94 C233.84,224.94 233.96,225.17 233.96,225.17 C233.96,225.17 234.07,225.41 234.07,225.41 C234.07,225.41 234.16,225.65 234.16,225.65 C234.16,225.65 234.24,225.9 234.24,225.9 C234.24,225.9 234.32,226.15 234.32,226.15 C234.32,226.15 234.38,226.4 234.38,226.4 C234.38,226.4 234.43,226.66 234.43,226.66 C234.43,226.66 234.48,226.92 234.48,226.92 C234.48,226.92 234.51,227.18 234.51,227.18 C234.51,227.18 234.53,227.44 234.53,227.44 C234.53,227.44 234.54,227.7 234.54,227.7 C234.54,227.7 234.54,227.96 234.54,227.96 C234.54,227.96 234.53,228.22 234.53,228.22 C234.53,228.22 234.51,228.48 234.51,228.48 C234.51,228.48 234.48,228.74 234.48,228.74 C234.48,228.74 234.43,229 234.43,229 C234.43,229 234.39,229.25 234.39,229.25 C234.39,229.25 234.32,229.51 234.32,229.51 C234.32,229.51 234.25,229.76 234.25,229.76 C234.25,229.76 234.17,230.01 234.17,230.01 C234.17,230.01 234.08,230.25 234.08,230.25 C234.08,230.25 233.97,230.49 233.97,230.49 C233.97,230.49 233.86,230.73 233.86,230.73 C233.86,230.73 233.75,230.96 233.75,230.96 C233.75,230.96 233.61,231.18 233.61,231.18 C233.61,231.18 233.48,231.41 233.48,231.41 C233.48,231.41 233.33,231.63 233.33,231.63 C233.33,231.63 233.17,231.83 233.17,231.83 C233.17,231.83 233.01,232.04 233.01,232.04 C233.01,232.04 232.84,232.24 232.84,232.24 C232.84,232.24 232.66,232.42 232.66,232.42 C232.66,232.42 232.47,232.61 232.47,232.61 C232.47,232.61 232.28,232.78 232.28,232.78 C232.28,232.78 232.08,232.95 232.08,232.95 C232.08,232.95 231.87,233.11 231.87,233.11 C231.87,233.11 231.66,233.26 231.66,233.26 C231.66,233.26 231.43,233.39 231.43,233.39 C231.43,233.39 231.21,233.53 231.21,233.53 C231.21,233.53 230.98,233.65 230.98,233.65 C230.98,233.65 230.74,233.76 230.74,233.76 C230.74,233.76 230.5,233.87 230.5,233.87 C230.5,233.87 230.26,233.96 230.26,233.96 C230.26,233.96 230.01,234.04 230.01,234.04 C230.01,234.04 229.76,234.12 229.76,234.12 C229.76,234.12 229.51,234.17 229.51,234.17 C229.51,234.17 229.25,234.23 229.25,234.23 C229.25,234.23 228.99,234.26 228.99,234.26 C228.99,234.26 228.73,234.3 228.73,234.3 C228.73,234.3 228.47,234.31 228.47,234.31 C228.47,234.31 228.21,234.32 228.21,234.32 C228.21,234.32 227.95,234.32 227.95,234.32 C227.95,234.32 227.69,234.32 227.69,234.32 C227.69,234.32 227.43,234.32 227.43,234.32 C227.43,234.32 227.16,234.32 227.16,234.32 C227.16,234.32 226.9,234.32 226.9,234.32 C226.9,234.32 226.64,234.32 226.64,234.32 C226.64,234.32 226.38,234.32 226.38,234.32 C226.38,234.32 226.12,234.32 226.12,234.32 C226.12,234.32 225.86,234.32 225.86,234.32 C225.86,234.32 225.6,234.32 225.6,234.32 C225.6,234.32 225.33,234.32 225.33,234.32 C225.33,234.32 225.07,234.32 225.07,234.32 C225.07,234.32 224.81,234.32 224.81,234.32 C224.81,234.32 224.55,234.32 224.55,234.32 C224.55,234.32 224.29,234.32 224.29,234.32 C224.29,234.32 224.03,234.32 224.03,234.32 C224.03,234.32 223.77,234.32 223.77,234.32 C223.77,234.32 223.5,234.32 223.5,234.32 C223.5,234.32 223.24,234.32 223.24,234.32 C223.24,234.32 222.98,234.32 222.98,234.32 C222.98,234.32 222.72,234.32 222.72,234.32 C222.72,234.32 222.46,234.32 222.46,234.32 C222.46,234.32 222.2,234.32 222.2,234.32 C222.2,234.32 221.94,234.32 221.94,234.32 C221.94,234.32 221.68,234.32 221.68,234.32 C221.68,234.32 221.41,234.32 221.41,234.32 C221.41,234.32 221.15,234.32 221.15,234.32 C221.15,234.32 220.89,234.32 220.89,234.32 C220.89,234.32 220.63,234.32 220.63,234.32 C220.63,234.32 220.37,234.32 220.37,234.32 C220.37,234.32 220.11,234.32 220.11,234.32 C220.11,234.32 219.85,234.32 219.85,234.32 C219.85,234.32 219.58,234.32 219.58,234.32 C219.58,234.32 219.32,234.32 219.32,234.32 C219.32,234.32 219.06,234.32 219.06,234.32 C219.06,234.32 218.8,234.32 218.8,234.32 C218.8,234.32 218.54,234.32 218.54,234.32 C218.54,234.32 218.28,234.32 218.28,234.32 C218.28,234.32 218.02,234.32 218.02,234.32 C218.02,234.32 217.75,234.32 217.75,234.32 C217.75,234.32 217.49,234.32 217.49,234.32 C217.49,234.32 217.23,234.32 217.23,234.32 C217.23,234.32 216.97,234.32 216.97,234.32 C216.97,234.32 216.71,234.32 216.71,234.32 C216.71,234.32 216.45,234.32 216.45,234.32 C216.45,234.32 216.19,234.32 216.19,234.32 C216.19,234.32 215.92,234.32 215.92,234.32 C215.92,234.32 215.66,234.32 215.66,234.32 C215.66,234.32 215.4,234.32 215.4,234.32 C215.4,234.32 215.14,234.32 215.14,234.32 C215.14,234.32 214.88,234.32 214.88,234.32 C214.88,234.32 214.62,234.32 214.62,234.32 C214.62,234.32 214.36,234.32 214.36,234.32 C214.36,234.32 214.1,234.32 214.1,234.32 C214.1,234.32 213.83,234.32 213.83,234.32 C213.83,234.32 213.57,234.32 213.57,234.32 C213.57,234.32 213.31,234.32 213.31,234.32 C213.31,234.32 213.05,234.32 213.05,234.32 C213.05,234.32 212.79,234.32 212.79,234.32 C212.79,234.32 212.53,234.32 212.53,234.32 C212.53,234.32 212.27,234.32 212.27,234.32 C212.27,234.32 212,234.32 212,234.32 C212,234.32 211.74,234.32 211.74,234.32 C211.74,234.32 211.48,234.32 211.48,234.32 C211.48,234.32 211.22,234.32 211.22,234.32 C211.22,234.32 210.96,234.32 210.96,234.32 C210.96,234.32 210.7,234.32 210.7,234.32 C210.7,234.32 210.44,234.32 210.44,234.32 C210.44,234.32 210.17,234.32 210.17,234.32 C210.17,234.32 209.91,234.32 209.91,234.32 C209.91,234.32 209.65,234.32 209.65,234.32 C209.65,234.32 209.39,234.32 209.39,234.32 C209.39,234.32 209.13,234.32 209.13,234.32 C209.13,234.32 208.87,234.32 208.87,234.32 C208.87,234.32 208.61,234.32 208.61,234.32 C208.61,234.32 208.34,234.32 208.34,234.32 C208.34,234.32 208.08,234.32 208.08,234.32 C208.08,234.32 207.82,234.32 207.82,234.32 C207.82,234.32 207.56,234.32 207.56,234.32 C207.56,234.32 207.3,234.32 207.3,234.32 C207.3,234.32 207.04,234.32 207.04,234.32 C207.04,234.32 206.78,234.32 206.78,234.32 C206.78,234.32 206.52,234.3 206.52,234.3 C206.52,234.3 206.26,234.28 206.26,234.28 C206.26,234.28 206,234.25 206,234.25 C206,234.25 205.74,234.21 205.74,234.21 C205.74,234.21 205.48,234.15 205.48,234.15 C205.48,234.15 205.23,234.09 205.23,234.09 C205.23,234.09 204.98,234.01 204.98,234.01 C204.98,234.01 204.73,233.93 204.73,233.93 C204.73,233.93 204.49,233.83 204.49,233.83 C204.49,233.83 204.25,233.72 204.25,233.72 C204.25,233.72 204.01,233.62 204.01,233.62 C204.01,233.62 203.79,233.48 203.79,233.48 C203.79,233.48 203.57,233.35 203.57,233.35 C203.57,233.35 203.34,233.21 203.34,233.21 C203.34,233.21 203.14,233.05 203.14,233.05 C203.14,233.05 202.93,232.89 202.93,232.89 C202.93,232.89 202.73,232.73 202.73,232.73 C202.73,232.73 202.54,232.54 202.54,232.54 C202.54,232.54 202.36,232.36 202.36,232.36 C202.36,232.36 202.17,232.17 202.17,232.17 C202.17,232.17 202.01,231.97 202.01,231.97 C202.01,231.97 201.85,231.76 201.85,231.76 C201.85,231.76 201.69,231.55 201.69,231.55 C201.69,231.55 201.55,231.33 201.55,231.33 C201.55,231.33 201.42,231.11 201.42,231.11 C201.42,231.11 201.29,230.88 201.29,230.88 C201.29,230.88 201.18,230.64 201.18,230.64 C201.18,230.64 201.07,230.4 201.07,230.4 C201.07,230.4 200.96,230.17 200.96,230.17 C200.96,230.17 200.88,229.92 200.88,229.92 C200.88,229.92 200.8,229.67 200.8,229.67 C200.8,229.67 200.73,229.42 200.73,229.42 C200.73,229.42 200.68,229.16 200.68,229.16 C200.68,229.16 200.63,228.91 200.63,228.91 C200.63,228.91 200.58,228.65 200.58,228.65 C200.58,228.65 200.56,228.39 200.56,228.39 C200.56,228.39 200.55,228.13 200.55,228.13 C200.55,228.13 200.53,227.87 200.53,227.87 C200.53,227.87 200.54,227.61 200.54,227.61 C200.54,227.61 200.56,227.35 200.56,227.35 C200.56,227.35 200.58,227.08 200.58,227.08 C200.58,227.08 200.62,226.83 200.62,226.83 C200.62,226.83 200.67,226.57 200.67,226.57 C200.67,226.57 200.72,226.31 200.72,226.31 C200.72,226.31 200.79,226.06 200.79,226.06 C200.79,226.06 200.87,225.81 200.87,225.81 C200.87,225.81 200.95,225.57 200.95,225.57 C200.95,225.57 201.05,225.32 201.05,225.32 C201.05,225.32 201.16,225.09 201.16,225.09 C201.16,225.09 201.27,224.85 201.27,224.85 C201.27,224.85 201.39,224.62 201.39,224.62 C201.39,224.62 201.52,224.39 201.52,224.39 C201.52,224.39 201.65,224.16 201.65,224.16 C201.65,224.16 201.78,223.94 201.78,223.94 C201.78,223.94 201.91,223.71 201.91,223.71 C201.91,223.71 202.03,223.48 202.03,223.48 C202.03,223.48 202.16,223.25 202.16,223.25 C202.16,223.25 202.29,223.03 202.29,223.03 C202.29,223.03 202.42,222.8 202.42,222.8 C202.42,222.8 202.55,222.57 202.55,222.57 C202.55,222.57 202.68,222.35 202.68,222.35 C202.68,222.35 202.81,222.12 202.81,222.12 C202.81,222.12 202.94,221.89 202.94,221.89 C202.94,221.89 203.07,221.66 203.07,221.66 C203.07,221.66 203.2,221.44 203.2,221.44 C203.2,221.44 203.33,221.21 203.33,221.21 C203.33,221.21 203.46,220.98 203.46,220.98 C203.46,220.98 203.58,220.76 203.58,220.76 C203.58,220.76 203.71,220.53 203.71,220.53 C203.71,220.53 203.84,220.3 203.84,220.3 C203.84,220.3 203.97,220.07 203.97,220.07 C203.97,220.07 204.1,219.85 204.1,219.85 C204.1,219.85 204.23,219.62 204.23,219.62 C204.23,219.62 204.36,219.39 204.36,219.39 C204.36,219.39 204.49,219.16 204.49,219.16 C204.49,219.16 204.62,218.94 204.62,218.94 C204.62,218.94 204.75,218.71 204.75,218.71 C204.75,218.71 204.88,218.48 204.88,218.48 C204.88,218.48 205.01,218.26 205.01,218.26 C205.01,218.26 205.13,218.03 205.13,218.03 C205.13,218.03 205.26,217.8 205.26,217.8 C205.26,217.8 205.39,217.57 205.39,217.57 C205.39,217.57 205.52,217.35 205.52,217.35 C205.52,217.35 205.65,217.12 205.65,217.12 C205.65,217.12 205.78,216.89 205.78,216.89 C205.78,216.89 205.91,216.66 205.91,216.66 C205.91,216.66 206.04,216.44 206.04,216.44 C206.04,216.44 206.17,216.21 206.17,216.21 C206.17,216.21 206.3,215.98 206.3,215.98 C206.3,215.98 206.43,215.76 206.43,215.76 C206.43,215.76 206.56,215.53 206.56,215.53 C206.56,215.53 206.68,215.3 206.68,215.3 C206.68,215.3 206.81,215.07 206.81,215.07 C206.81,215.07 206.94,214.85 206.94,214.85 C206.94,214.85 207.07,214.62 207.07,214.62 C207.07,214.62 207.2,214.39 207.2,214.39 C207.2,214.39 207.33,214.17 207.33,214.17 C207.33,214.17 207.46,213.94 207.46,213.94 C207.46,213.94 207.59,213.71 207.59,213.71 C207.59,213.71 207.72,213.48 207.72,213.48 C207.72,213.48 207.85,213.26 207.85,213.26 C207.85,213.26 207.98,213.03 207.98,213.03 C207.98,213.03 208.11,212.8 208.11,212.8 C208.11,212.8 208.23,212.57 208.23,212.57 C208.23,212.57 208.36,212.35 208.36,212.35 C208.36,212.35 208.49,212.12 208.49,212.12 C208.49,212.12 208.62,211.89 208.62,211.89 C208.62,211.89 208.75,211.67 208.75,211.67 C208.75,211.67 208.88,211.44 208.88,211.44 C208.88,211.44 209.01,211.21 209.01,211.21 C209.01,211.21 209.14,210.98 209.14,210.98 C209.14,210.98 209.27,210.76 209.27,210.76 C209.27,210.76 209.4,210.53 209.4,210.53 C209.4,210.53 209.53,210.3 209.53,210.3 C209.53,210.3 209.66,210.08 209.66,210.08 C209.66,210.08 209.78,209.85 209.78,209.85 C209.78,209.85 209.91,209.62 209.91,209.62 C209.91,209.62 210.04,209.39 210.04,209.39 C210.04,209.39 210.17,209.17 210.17,209.17 C210.17,209.17 210.3,208.94 210.3,208.94 C210.3,208.94 210.43,208.71 210.43,208.71 C210.43,208.71 210.56,208.48 210.56,208.48 C210.56,208.48 210.69,208.26 210.69,208.26 C210.69,208.26 210.82,208.03 210.82,208.03 C210.82,208.03 210.95,207.8 210.95,207.8 C210.95,207.8 211.08,207.58 211.08,207.58 C211.08,207.58 211.21,207.35 211.21,207.35 C211.21,207.35 211.33,207.12 211.33,207.12 C211.33,207.12 211.46,206.89 211.46,206.89 C211.46,206.89 211.59,206.67 211.59,206.67 C211.59,206.67 211.72,206.44 211.72,206.44 C211.72,206.44 211.85,206.21 211.85,206.21 C211.85,206.21 211.98,205.98 211.98,205.98 C211.98,205.98 212.13,205.76 212.13,205.76 C212.13,205.76 212.27,205.54 212.27,205.54 C212.27,205.54 212.41,205.33 212.41,205.33 C212.41,205.33 212.57,205.12 212.57,205.12 C212.57,205.12 212.74,204.92 212.74,204.92 C212.74,204.92 212.91,204.72 212.91,204.72 C212.91,204.72 213.1,204.54 213.1,204.54 C213.1,204.54 213.29,204.36 213.29,204.36 C213.29,204.36 213.49,204.19 213.49,204.19 C213.49,204.19 213.69,204.03 213.69,204.03 C213.69,204.03 213.9,203.87 213.9,203.87 C213.9,203.87 214.12,203.73 214.12,203.73 C214.12,203.73 214.34,203.59 214.34,203.59 C214.34,203.59 214.57,203.46 214.57,203.46 C214.57,203.46 214.81,203.35 214.81,203.35 C214.81,203.35 215.04,203.24 215.04,203.24 C215.04,203.24 215.28,203.14 215.28,203.14 C215.28,203.14 215.53,203.06 215.53,203.06 C215.53,203.06 215.78,202.98 215.78,202.98 C215.78,202.98 216.03,202.91 216.03,202.91 C216.03,202.91 216.29,202.86 216.29,202.86 C216.29,202.86 216.55,202.82 216.55,202.82 C216.55,202.82 216.8,202.77 216.8,202.77 C216.8,202.77 217.07,202.76 217.07,202.76 C217.07,202.76 217.33,202.74 217.33,202.74 C217.33,202.74 217.59,202.73 217.59,202.73c " android:valueTo="M217.68 210.56 C217.68,210.56 217.81,210.57 217.81,210.57 C217.81,210.57 217.93,210.57 217.93,210.57 C217.93,210.57 218.06,210.58 218.06,210.58 C218.06,210.58 218.18,210.59 218.18,210.59 C218.18,210.59 218.31,210.59 218.31,210.59 C218.31,210.59 218.43,210.61 218.43,210.61 C218.43,210.61 218.56,210.63 218.56,210.63 C218.56,210.63 218.68,210.64 218.68,210.64 C218.68,210.64 218.81,210.66 218.81,210.66 C218.81,210.66 218.93,210.68 218.93,210.68 C218.93,210.68 219.05,210.7 219.05,210.7 C219.05,210.7 219.18,210.72 219.18,210.72 C219.18,210.72 219.3,210.75 219.3,210.75 C219.3,210.75 219.42,210.78 219.42,210.78 C219.42,210.78 219.54,210.81 219.54,210.81 C219.54,210.81 219.66,210.84 219.66,210.84 C219.66,210.84 219.79,210.87 219.79,210.87 C219.79,210.87 219.91,210.91 219.91,210.91 C219.91,210.91 220.03,210.95 220.03,210.95 C220.03,210.95 220.14,210.99 220.14,210.99 C220.14,210.99 220.26,211.04 220.26,211.04 C220.26,211.04 220.38,211.08 220.38,211.08 C220.38,211.08 220.5,211.12 220.5,211.12 C220.5,211.12 220.62,211.17 220.62,211.17 C220.62,211.17 220.73,211.22 220.73,211.22 C220.73,211.22 220.84,211.27 220.84,211.27 C220.84,211.27 220.96,211.32 220.96,211.32 C220.96,211.32 221.07,211.38 221.07,211.38 C221.07,211.38 221.19,211.43 221.19,211.43 C221.19,211.43 221.3,211.49 221.3,211.49 C221.3,211.49 221.41,211.55 221.41,211.55 C221.41,211.55 221.51,211.61 221.51,211.61 C221.51,211.61 221.62,211.68 221.62,211.68 C221.62,211.68 221.73,211.74 221.73,211.74 C221.73,211.74 221.84,211.8 221.84,211.8 C221.84,211.8 221.94,211.87 221.94,211.87 C221.94,211.87 222.05,211.94 222.05,211.94 C222.05,211.94 222.15,212.02 222.15,212.02 C222.15,212.02 222.25,212.09 222.25,212.09 C222.25,212.09 222.35,212.16 222.35,212.16 C222.35,212.16 222.46,212.23 222.46,212.23 C222.46,212.23 222.55,212.31 222.55,212.31 C222.55,212.31 222.65,212.4 222.65,212.4 C222.65,212.4 222.74,212.48 222.74,212.48 C222.74,212.48 222.84,212.56 222.84,212.56 C222.84,212.56 222.93,212.64 222.93,212.64 C222.93,212.64 223.03,212.72 223.03,212.72 C223.03,212.72 223.12,212.81 223.12,212.81 C223.12,212.81 223.21,212.9 223.21,212.9 C223.21,212.9 223.29,212.99 223.29,212.99 C223.29,212.99 223.38,213.08 223.38,213.08 C223.38,213.08 223.47,213.17 223.47,213.17 C223.47,213.17 223.55,213.26 223.55,213.26 C223.55,213.26 223.63,213.36 223.63,213.36 C223.63,213.36 223.71,213.46 223.71,213.46 C223.71,213.46 223.79,213.56 223.79,213.56 C223.79,213.56 223.87,213.66 223.87,213.66 C223.87,213.66 223.95,213.75 223.95,213.75 C223.95,213.75 224.03,213.85 224.03,213.85 C224.03,213.85 224.09,213.96 224.09,213.96 C224.09,213.96 224.16,214.06 224.16,214.06 C224.16,214.06 224.23,214.17 224.23,214.17 C224.23,214.17 224.3,214.27 224.3,214.27 C224.3,214.27 224.37,214.38 224.37,214.38 C224.37,214.38 224.44,214.48 224.44,214.48 C224.44,214.48 224.5,214.59 224.5,214.59 C224.5,214.59 224.56,214.7 224.56,214.7 C224.56,214.7 224.62,214.81 224.62,214.81 C224.62,214.81 224.68,214.93 224.68,214.93 C224.68,214.93 224.74,215.04 224.74,215.04 C224.74,215.04 224.79,215.15 224.79,215.15 C224.79,215.15 224.84,215.26 224.84,215.26 C224.84,215.26 224.89,215.38 224.89,215.38 C224.89,215.38 224.94,215.5 224.94,215.5 C224.94,215.5 224.99,215.61 224.99,215.61 C224.99,215.61 225.04,215.73 225.04,215.73 C225.04,215.73 225.08,215.84 225.08,215.84 C225.08,215.84 225.12,215.96 225.12,215.96 C225.12,215.96 225.16,216.08 225.16,216.08 C225.16,216.08 225.19,216.2 225.19,216.2 C225.19,216.2 225.23,216.32 225.23,216.32 C225.23,216.32 225.27,216.44 225.27,216.44 C225.27,216.44 225.3,216.56 225.3,216.56 C225.3,216.56 225.33,216.69 225.33,216.69 C225.33,216.69 225.35,216.81 225.35,216.81 C225.35,216.81 225.38,216.93 225.38,216.93 C225.38,216.93 225.41,217.06 225.41,217.06 C225.41,217.06 225.43,217.18 225.43,217.18 C225.43,217.18 225.46,217.3 225.46,217.3 C225.46,217.3 225.47,217.43 225.47,217.43 C225.47,217.43 225.49,217.55 225.49,217.55 C225.49,217.55 225.5,217.68 225.5,217.68 C225.5,217.68 225.52,217.8 225.52,217.8 C225.52,217.8 225.52,217.93 225.52,217.93 C225.52,217.93 225.53,218.05 225.53,218.05 C225.53,218.05 225.54,218.18 225.54,218.18 C225.54,218.18 225.54,218.3 225.54,218.3 C225.54,218.3 225.55,218.43 225.55,218.43 C225.55,218.43 225.55,218.55 225.55,218.55 C225.55,218.55 225.55,218.68 225.55,218.68 C225.55,218.68 225.54,218.8 225.54,218.8 C225.54,218.8 225.54,218.93 225.54,218.93 C225.54,218.93 225.53,219.05 225.53,219.05 C225.53,219.05 225.52,219.18 225.52,219.18 C225.52,219.18 225.52,219.31 225.52,219.31 C225.52,219.31 225.5,219.43 225.5,219.43 C225.5,219.43 225.48,219.55 225.48,219.55 C225.48,219.55 225.47,219.68 225.47,219.68 C225.47,219.68 225.45,219.8 225.45,219.8 C225.45,219.8 225.43,219.93 225.43,219.93 C225.43,219.93 225.41,220.05 225.41,220.05 C225.41,220.05 225.39,220.17 225.39,220.17 C225.39,220.17 225.36,220.3 225.36,220.3 C225.36,220.3 225.33,220.42 225.33,220.42 C225.33,220.42 225.3,220.54 225.3,220.54 C225.3,220.54 225.27,220.66 225.27,220.66 C225.27,220.66 225.24,220.78 225.24,220.78 C225.24,220.78 225.2,220.9 225.2,220.9 C225.2,220.9 225.16,221.02 225.16,221.02 C225.16,221.02 225.12,221.14 225.12,221.14 C225.12,221.14 225.08,221.26 225.08,221.26 C225.08,221.26 225.03,221.38 225.03,221.38 C225.03,221.38 224.99,221.5 224.99,221.5 C224.99,221.5 224.95,221.61 224.95,221.61 C224.95,221.61 224.89,221.73 224.89,221.73 C224.89,221.73 224.84,221.84 224.84,221.84 C224.84,221.84 224.79,221.96 224.79,221.96 C224.79,221.96 224.73,222.07 224.73,222.07 C224.73,222.07 224.68,222.18 224.68,222.18 C224.68,222.18 224.62,222.29 224.62,222.29 C224.62,222.29 224.56,222.4 224.56,222.4 C224.56,222.4 224.5,222.51 224.5,222.51 C224.5,222.51 224.44,222.62 224.44,222.62 C224.44,222.62 224.37,222.73 224.37,222.73 C224.37,222.73 224.31,222.84 224.31,222.84 C224.31,222.84 224.24,222.94 224.24,222.94 C224.24,222.94 224.17,223.05 224.17,223.05 C224.17,223.05 224.09,223.15 224.09,223.15 C224.09,223.15 224.02,223.25 224.02,223.25 C224.02,223.25 223.95,223.35 223.95,223.35 C223.95,223.35 223.88,223.45 223.88,223.45 C223.88,223.45 223.8,223.55 223.8,223.55 C223.8,223.55 223.71,223.65 223.71,223.65 C223.71,223.65 223.63,223.74 223.63,223.74 C223.63,223.74 223.55,223.84 223.55,223.84 C223.55,223.84 223.47,223.93 223.47,223.93 C223.47,223.93 223.39,224.03 223.39,224.03 C223.39,224.03 223.3,224.12 223.3,224.12 C223.3,224.12 223.21,224.2 223.21,224.2 C223.21,224.2 223.12,224.29 223.12,224.29 C223.12,224.29 223.03,224.38 223.03,224.38 C223.03,224.38 222.94,224.46 222.94,224.46 C222.94,224.46 222.85,224.55 222.85,224.55 C222.85,224.55 222.75,224.63 222.75,224.63 C222.75,224.63 222.65,224.71 222.65,224.71 C222.65,224.71 222.55,224.79 222.55,224.79 C222.55,224.79 222.46,224.87 222.46,224.87 C222.46,224.87 222.36,224.95 222.36,224.95 C222.36,224.95 222.26,225.02 222.26,225.02 C222.26,225.02 222.15,225.09 222.15,225.09 C222.15,225.09 222.05,225.16 222.05,225.16 C222.05,225.16 221.94,225.23 221.94,225.23 C221.94,225.23 221.84,225.3 221.84,225.3 C221.84,225.3 221.74,225.37 221.74,225.37 C221.74,225.37 221.63,225.44 221.63,225.44 C221.63,225.44 221.52,225.5 221.52,225.5 C221.52,225.5 221.41,225.56 221.41,225.56 C221.41,225.56 221.3,225.62 221.3,225.62 C221.3,225.62 221.19,225.68 221.19,225.68 C221.19,225.68 221.08,225.73 221.08,225.73 C221.08,225.73 220.96,225.79 220.96,225.79 C220.96,225.79 220.85,225.84 220.85,225.84 C220.85,225.84 220.73,225.89 220.73,225.89 C220.73,225.89 220.62,225.94 220.62,225.94 C220.62,225.94 220.5,225.99 220.5,225.99 C220.5,225.99 220.38,226.03 220.38,226.03 C220.38,226.03 220.27,226.08 220.27,226.08 C220.27,226.08 220.15,226.12 220.15,226.12 C220.15,226.12 220.03,226.15 220.03,226.15 C220.03,226.15 219.91,226.19 219.91,226.19 C219.91,226.19 219.79,226.23 219.79,226.23 C219.79,226.23 219.67,226.27 219.67,226.27 C219.67,226.27 219.55,226.3 219.55,226.3 C219.55,226.3 219.42,226.33 219.42,226.33 C219.42,226.33 219.3,226.35 219.3,226.35 C219.3,226.35 219.18,226.38 219.18,226.38 C219.18,226.38 219.06,226.4 219.06,226.4 C219.06,226.4 218.93,226.43 218.93,226.43 C218.93,226.43 218.81,226.45 218.81,226.45 C218.81,226.45 218.68,226.47 218.68,226.47 C218.68,226.47 218.56,226.49 218.56,226.49 C218.56,226.49 218.44,226.5 218.44,226.5 C218.44,226.5 218.31,226.52 218.31,226.52 C218.31,226.52 218.19,226.52 218.19,226.52 C218.19,226.52 218.06,226.53 218.06,226.53 C218.06,226.53 217.93,226.53 217.93,226.53 C217.93,226.53 217.81,226.54 217.81,226.54 C217.81,226.54 217.68,226.55 217.68,226.55 C217.68,226.55 217.56,226.55 217.56,226.55 C217.56,226.55 217.43,226.55 217.43,226.55 C217.43,226.55 217.31,226.54 217.31,226.54 C217.31,226.54 217.18,226.53 217.18,226.53 C217.18,226.53 217.05,226.53 217.05,226.53 C217.05,226.53 216.93,226.52 216.93,226.52 C216.93,226.52 216.8,226.52 216.8,226.52 C216.8,226.52 216.68,226.5 216.68,226.5 C216.68,226.5 216.55,226.48 216.55,226.48 C216.55,226.48 216.43,226.46 216.43,226.46 C216.43,226.46 216.31,226.45 216.31,226.45 C216.31,226.45 216.18,226.43 216.18,226.43 C216.18,226.43 216.06,226.41 216.06,226.41 C216.06,226.41 215.93,226.38 215.93,226.38 C215.93,226.38 215.81,226.35 215.81,226.35 C215.81,226.35 215.69,226.32 215.69,226.32 C215.69,226.32 215.57,226.29 215.57,226.29 C215.57,226.29 215.45,226.26 215.45,226.26 C215.45,226.26 215.32,226.23 215.32,226.23 C215.32,226.23 215.2,226.2 215.2,226.2 C215.2,226.2 215.09,226.16 215.09,226.16 C215.09,226.16 214.97,226.12 214.97,226.12 C214.97,226.12 214.85,226.07 214.85,226.07 C214.85,226.07 214.73,226.03 214.73,226.03 C214.73,226.03 214.61,225.99 214.61,225.99 C214.61,225.99 214.5,225.94 214.5,225.94 C214.5,225.94 214.38,225.89 214.38,225.89 C214.38,225.89 214.27,225.84 214.27,225.84 C214.27,225.84 214.15,225.79 214.15,225.79 C214.15,225.79 214.04,225.73 214.04,225.73 C214.04,225.73 213.93,225.68 213.93,225.68 C213.93,225.68 213.81,225.62 213.81,225.62 C213.81,225.62 213.71,225.56 213.71,225.56 C213.71,225.56 213.6,225.5 213.6,225.5 C213.6,225.5 213.49,225.43 213.49,225.43 C213.49,225.43 213.38,225.37 213.38,225.37 C213.38,225.37 213.27,225.31 213.27,225.31 C213.27,225.31 213.17,225.24 213.17,225.24 C213.17,225.24 213.06,225.16 213.06,225.16 C213.06,225.16 212.96,225.09 212.96,225.09 C212.96,225.09 212.86,225.02 212.86,225.02 C212.86,225.02 212.76,224.95 212.76,224.95 C212.76,224.95 212.65,224.87 212.65,224.87 C212.65,224.87 212.56,224.79 212.56,224.79 C212.56,224.79 212.46,224.71 212.46,224.71 C212.46,224.71 212.37,224.63 212.37,224.63 C212.37,224.63 212.27,224.55 212.27,224.55 C212.27,224.55 212.18,224.47 212.18,224.47 C212.18,224.47 212.08,224.38 212.08,224.38 C212.08,224.38 211.99,224.3 211.99,224.3 C211.99,224.3 211.91,224.2 211.91,224.2 C211.91,224.2 211.82,224.11 211.82,224.11 C211.82,224.11 211.73,224.02 211.73,224.02 C211.73,224.02 211.64,223.93 211.64,223.93 C211.64,223.93 211.56,223.84 211.56,223.84 C211.56,223.84 211.48,223.75 211.48,223.75 C211.48,223.75 211.4,223.65 211.4,223.65 C211.4,223.65 211.32,223.55 211.32,223.55 C211.32,223.55 211.24,223.45 211.24,223.45 C211.24,223.45 211.16,223.35 211.16,223.35 C211.16,223.35 211.09,223.26 211.09,223.26 C211.09,223.26 211.02,223.15 211.02,223.15 C211.02,223.15 210.95,223.05 210.95,223.05 C210.95,223.05 210.88,222.94 210.88,222.94 C210.88,222.94 210.81,222.84 210.81,222.84 C210.81,222.84 210.74,222.73 210.74,222.73 C210.74,222.73 210.67,222.63 210.67,222.63 C210.67,222.63 210.61,222.52 210.61,222.52 C210.61,222.52 210.55,222.4 210.55,222.4 C210.55,222.4 210.49,222.29 210.49,222.29 C210.49,222.29 210.43,222.18 210.43,222.18 C210.43,222.18 210.38,222.07 210.38,222.07 C210.38,222.07 210.32,221.96 210.32,221.96 C210.32,221.96 210.27,221.84 210.27,221.84 C210.27,221.84 210.22,221.73 210.22,221.73 C210.22,221.73 210.17,221.61 210.17,221.61 C210.17,221.61 210.12,221.5 210.12,221.5 C210.12,221.5 210.08,221.38 210.08,221.38 C210.08,221.38 210.03,221.26 210.03,221.26 C210.03,221.26 209.99,221.14 209.99,221.14 C209.99,221.14 209.96,221.02 209.96,221.02 C209.96,221.02 209.92,220.9 209.92,220.9 C209.92,220.9 209.88,220.78 209.88,220.78 C209.88,220.78 209.84,220.67 209.84,220.67 C209.84,220.67 209.81,220.54 209.81,220.54 C209.81,220.54 209.78,220.42 209.78,220.42 C209.78,220.42 209.76,220.3 209.76,220.3 C209.76,220.3 209.73,220.18 209.73,220.18 C209.73,220.18 209.71,220.05 209.71,220.05 C209.71,220.05 209.68,219.93 209.68,219.93 C209.68,219.93 209.66,219.81 209.66,219.81 C209.66,219.81 209.64,219.68 209.64,219.68 C209.64,219.68 209.62,219.56 209.62,219.56 C209.62,219.56 209.61,219.43 209.61,219.43 C209.61,219.43 209.59,219.31 209.59,219.31 C209.59,219.31 209.59,219.18 209.59,219.18 C209.59,219.18 209.58,219.06 209.58,219.06 C209.58,219.06 209.58,218.93 209.58,218.93 C209.58,218.93 209.57,218.81 209.57,218.81 C209.57,218.81 209.56,218.68 209.56,218.68 C209.56,218.68 209.56,218.56 209.56,218.56 C209.56,218.56 209.56,218.43 209.56,218.43 C209.56,218.43 209.57,218.3 209.57,218.3 C209.57,218.3 209.58,218.18 209.58,218.18 C209.58,218.18 209.58,218.05 209.58,218.05 C209.58,218.05 209.59,217.93 209.59,217.93 C209.59,217.93 209.59,217.8 209.59,217.8 C209.59,217.8 209.61,217.68 209.61,217.68 C209.61,217.68 209.63,217.55 209.63,217.55 C209.63,217.55 209.65,217.43 209.65,217.43 C209.65,217.43 209.66,217.31 209.66,217.31 C209.66,217.31 209.68,217.18 209.68,217.18 C209.68,217.18 209.7,217.06 209.7,217.06 C209.7,217.06 209.73,216.93 209.73,216.93 C209.73,216.93 209.76,216.81 209.76,216.81 C209.76,216.81 209.79,216.69 209.79,216.69 C209.79,216.69 209.82,216.57 209.82,216.57 C209.82,216.57 209.85,216.45 209.85,216.45 C209.85,216.45 209.88,216.32 209.88,216.32 C209.88,216.32 209.91,216.2 209.91,216.2 C209.91,216.2 209.95,216.08 209.95,216.08 C209.95,216.08 210,215.97 210,215.97 C210,215.97 210.04,215.85 210.04,215.85 C210.04,215.85 210.08,215.73 210.08,215.73 C210.08,215.73 210.12,215.61 210.12,215.61 C210.12,215.61 210.17,215.49 210.17,215.49 C210.17,215.49 210.22,215.38 210.22,215.38 C210.22,215.38 210.27,215.27 210.27,215.27 C210.27,215.27 210.33,215.15 210.33,215.15 C210.33,215.15 210.38,215.04 210.38,215.04 C210.38,215.04 210.43,214.92 210.43,214.92 C210.43,214.92 210.49,214.81 210.49,214.81 C210.49,214.81 210.55,214.7 210.55,214.7 C210.55,214.7 210.61,214.6 210.61,214.6 C210.61,214.6 210.68,214.49 210.68,214.49 C210.68,214.49 210.74,214.38 210.74,214.38 C210.74,214.38 210.8,214.27 210.8,214.27 C210.8,214.27 210.87,214.17 210.87,214.17 C210.87,214.17 210.95,214.06 210.95,214.06 C210.95,214.06 211.02,213.96 211.02,213.96 C211.02,213.96 211.09,213.86 211.09,213.86 C211.09,213.86 211.16,213.76 211.16,213.76 C211.16,213.76 211.24,213.65 211.24,213.65 C211.24,213.65 211.32,213.56 211.32,213.56 C211.32,213.56 211.4,213.46 211.4,213.46 C211.4,213.46 211.48,213.37 211.48,213.37 C211.48,213.37 211.56,213.27 211.56,213.27 C211.56,213.27 211.64,213.18 211.64,213.18 C211.64,213.18 211.73,213.08 211.73,213.08 C211.73,213.08 211.82,212.99 211.82,212.99 C211.82,212.99 211.91,212.9 211.91,212.9 C211.91,212.9 212,212.82 212,212.82 C212,212.82 212.09,212.73 212.09,212.73 C212.09,212.73 212.18,212.64 212.18,212.64 C212.18,212.64 212.27,212.56 212.27,212.56 C212.27,212.56 212.36,212.48 212.36,212.48 C212.36,212.48 212.46,212.4 212.46,212.4 C212.46,212.4 212.56,212.32 212.56,212.32 C212.56,212.32 212.66,212.24 212.66,212.24 C212.66,212.24 212.76,212.16 212.76,212.16 C212.76,212.16 212.85,212.08 212.85,212.08 C212.85,212.08 212.96,212.02 212.96,212.02 C212.96,212.02 213.06,211.95 213.06,211.95 C213.06,211.95 213.17,211.88 213.17,211.88 C213.17,211.88 213.27,211.81 213.27,211.81 C213.27,211.81 213.38,211.74 213.38,211.74 C213.38,211.74 213.48,211.67 213.48,211.67 C213.48,211.67 213.6,211.61 213.6,211.61 C213.6,211.61 213.71,211.55 213.71,211.55 C213.71,211.55 213.82,211.49 213.82,211.49 C213.82,211.49 213.93,211.43 213.93,211.43 C213.93,211.43 214.04,211.37 214.04,211.37 C214.04,211.37 214.15,211.32 214.15,211.32 C214.15,211.32 214.27,211.27 214.27,211.27 C214.27,211.27 214.38,211.22 214.38,211.22 C214.38,211.22 214.5,211.17 214.5,211.17 C214.5,211.17 214.61,211.12 214.61,211.12 C214.61,211.12 214.73,211.07 214.73,211.07 C214.73,211.07 214.85,211.03 214.85,211.03 C214.85,211.03 214.97,210.99 214.97,210.99 C214.97,210.99 215.09,210.95 215.09,210.95 C215.09,210.95 215.21,210.92 215.21,210.92 C215.21,210.92 215.33,210.88 215.33,210.88 C215.33,210.88 215.45,210.84 215.45,210.84 C215.45,210.84 215.57,210.81 215.57,210.81 C215.57,210.81 215.69,210.78 215.69,210.78 C215.69,210.78 215.81,210.76 215.81,210.76 C215.81,210.76 215.93,210.73 215.93,210.73 C215.93,210.73 216.06,210.7 216.06,210.7 C216.06,210.7 216.18,210.68 216.18,210.68 C216.18,210.68 216.3,210.65 216.3,210.65 C216.3,210.65 216.43,210.64 216.43,210.64 C216.43,210.64 216.55,210.62 216.55,210.62 C216.55,210.62 216.68,210.61 216.68,210.61 C216.68,210.61 216.8,210.59 216.8,210.59 C216.8,210.59 216.93,210.59 216.93,210.59 C216.93,210.59 217.05,210.58 217.05,210.58 C217.05,210.58 217.18,210.58 217.18,210.58 C217.18,210.58 217.3,210.57 217.3,210.57 C217.3,210.57 217.43,210.56 217.43,210.56 C217.43,210.56 217.56,210.56 217.56,210.56 C217.56,210.56 217.68,210.56 217.68,210.56c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.8,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="500" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector> \ No newline at end of file
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="30dp" android:width="30dp" android:viewportHeight="30" android:viewportWidth="30"><group android:name="_R_G"><group android:name="_R_G_L_1_G" android:translateX="15.397" android:translateY="15.691" android:scaleY="0"><path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-0.48 -12.86 C2.96,-12.87 14.59,5.93 11.98,9.12 C9.42,12.26 5.76,11.36 -0.48,11.41 C-6.72,11.45 -10.24,11.91 -12.78,9.16 C-15.4,6.32 -3.91,-12.85 -0.48,-12.86c "/></group><group android:name="_R_G_L_0_G" android:translateX="15" android:translateY="17.64" android:pivotY="-2.64" android:scaleX="0" android:scaleY="0"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-4.68 -13.34 C-2.59,-17.01 2.64,-17 4.72,-13.33 C4.72,-13.33 13.65,2.45 13.65,2.45 C15.72,6.11 13.11,10.66 8.94,10.65 C8.94,10.65 -8.98,10.62 -8.98,10.62 C-13.15,10.61 -15.75,6.05 -13.67,2.4 C-13.67,2.4 -4.68,-13.34 -4.68,-13.34c "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_1_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M-0.48 -12.86 C2.96,-12.87 14.59,5.93 11.98,9.12 C9.42,12.26 5.76,11.36 -0.48,11.41 C-6.72,11.45 -10.24,11.91 -12.78,9.16 C-15.4,6.32 -3.91,-12.85 -0.48,-12.86c " android:valueTo="M-0.48 -12.86 C2.96,-12.87 14.59,5.93 11.98,9.12 C9.42,12.26 5.76,11.36 -0.48,11.41 C-6.72,11.45 -10.24,11.91 -12.78,9.16 C-15.4,6.32 -3.91,-12.85 -0.48,-12.86c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.7,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="283" android:startOffset="67" android:valueFrom="M-0.48 -12.86 C2.96,-12.87 14.59,5.93 11.98,9.12 C9.42,12.26 5.76,11.36 -0.48,11.41 C-6.72,11.45 -10.24,11.91 -12.78,9.16 C-15.4,6.32 -3.91,-12.85 -0.48,-12.86c " android:valueTo="M-0.44 -8.69 C3.98,-8.69 7.56,-5.11 7.56,-0.69 C7.56,3.73 3.98,7.31 -0.44,7.31 C-4.86,7.31 -8.44,3.73 -8.44,-0.69 C-8.44,-5.11 -4.86,-8.69 -0.44,-8.69c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.7,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_1_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="67" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M-4.68 -13.34 C-2.59,-17.01 2.64,-17 4.72,-13.33 C4.72,-13.33 13.65,2.45 13.65,2.45 C15.72,6.11 13.11,10.66 8.94,10.65 C8.94,10.65 -8.98,10.62 -8.98,10.62 C-13.15,10.61 -15.75,6.05 -13.67,2.4 C-13.67,2.4 -4.68,-13.34 -4.68,-13.34c " android:valueTo="M-4.68 -13.34 C-2.59,-17.01 2.64,-17 4.72,-13.33 C4.72,-13.33 13.65,2.45 13.65,2.45 C15.72,6.11 13.11,10.66 8.94,10.65 C8.94,10.65 -8.98,10.62 -8.98,10.62 C-13.15,10.61 -15.75,6.05 -13.67,2.4 C-13.67,2.4 -4.68,-13.34 -4.68,-13.34c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.7,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="283" android:startOffset="67" android:valueFrom="M-4.68 -13.34 C-2.59,-17.01 2.64,-17 4.72,-13.33 C4.72,-13.33 13.65,2.45 13.65,2.45 C15.72,6.11 13.11,10.66 8.94,10.65 C8.94,10.65 -8.98,10.62 -8.98,10.62 C-13.15,10.61 -15.75,6.05 -13.67,2.4 C-13.67,2.4 -4.68,-13.34 -4.68,-13.34c " android:valueTo="M-2.99 -8.52 C-1.33,-9.83 1.52,-9.34 3.25,-8.28 C4.98,-7.22 6.77,-5.88 6.7,-2.4 C6.64,1.08 4.48,2.26 3.2,3.05 C1.92,3.83 -1.1,3.72 -3.03,2.76 C-4.97,1.79 -6.38,0.3 -6.37,-2.59 C-6.36,-5.49 -4.65,-7.2 -2.99,-8.52c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.7,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleX" android:duration="67" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="67" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target><target android:name="_R_G_L_0_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="367" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="500" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/pin_dot_shape_6_avd.xml b/packages/SystemUI/res/drawable/pin_dot_shape_6_avd.xml
index e7ce4267fc32..ddda94a4edcc 100644
--- a/packages/SystemUI/res/drawable/pin_dot_shape_6_avd.xml
+++ b/packages/SystemUI/res/drawable/pin_dot_shape_6_avd.xml
@@ -1 +1 @@
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="60dp" android:width="60dp" android:viewportHeight="60" android:viewportWidth="60"><group android:name="_R_G"><group android:name="_R_G_L_0_G" android:translateX="-187.543" android:translateY="-188.546"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="0" android:fillType="nonZero" android:pathData=" M217.62 214.55 C217.62,214.55 217.68,214.55 217.68,214.55 C217.68,214.55 217.74,214.56 217.74,214.56 C217.74,214.56 217.81,214.56 217.81,214.56 C217.81,214.56 217.87,214.56 217.87,214.56 C217.87,214.56 217.93,214.57 217.93,214.57 C217.93,214.57 218,214.57 218,214.57 C218,214.57 218.06,214.58 218.06,214.58 C218.06,214.58 218.12,214.59 218.12,214.59 C218.12,214.59 218.18,214.6 218.18,214.6 C218.18,214.6 218.24,214.61 218.24,214.61 C218.24,214.61 218.31,214.62 218.31,214.62 C218.31,214.62 218.37,214.63 218.37,214.63 C218.37,214.63 218.43,214.65 218.43,214.65 C218.43,214.65 218.49,214.66 218.49,214.66 C218.49,214.66 218.55,214.68 218.55,214.68 C218.55,214.68 218.61,214.69 218.61,214.69 C218.61,214.69 218.67,214.71 218.67,214.71 C218.67,214.71 218.73,214.73 218.73,214.73 C218.73,214.73 218.79,214.75 218.79,214.75 C218.79,214.75 218.85,214.77 218.85,214.77 C218.85,214.77 218.91,214.79 218.91,214.79 C218.91,214.79 218.97,214.81 218.97,214.81 C218.97,214.81 219.03,214.83 219.03,214.83 C219.03,214.83 219.09,214.85 219.09,214.85 C219.09,214.85 219.15,214.88 219.15,214.88 C219.15,214.88 219.2,214.9 219.2,214.9 C219.2,214.9 219.26,214.93 219.26,214.93 C219.26,214.93 219.32,214.96 219.32,214.96 C219.32,214.96 219.37,214.98 219.37,214.98 C219.37,214.98 219.43,215.01 219.43,215.01 C219.43,215.01 219.48,215.05 219.48,215.05 C219.48,215.05 219.54,215.08 219.54,215.08 C219.54,215.08 219.59,215.11 219.59,215.11 C219.59,215.11 219.65,215.14 219.65,215.14 C219.65,215.14 219.7,215.17 219.7,215.17 C219.7,215.17 219.75,215.21 219.75,215.21 C219.75,215.21 219.81,215.24 219.81,215.24 C219.81,215.24 219.86,215.28 219.86,215.28 C219.86,215.28 219.91,215.32 219.91,215.32 C219.91,215.32 219.96,215.35 219.96,215.35 C219.96,215.35 220.01,215.39 220.01,215.39 C220.01,215.39 220.06,215.43 220.06,215.43 C220.06,215.43 220.11,215.47 220.11,215.47 C220.11,215.47 220.16,215.51 220.16,215.51 C220.16,215.51 220.2,215.55 220.2,215.55 C220.2,215.55 220.25,215.59 220.25,215.59 C220.25,215.59 220.3,215.63 220.3,215.63 C220.3,215.63 220.34,215.68 220.34,215.68 C220.34,215.68 220.39,215.72 220.39,215.72 C220.39,215.72 220.43,215.77 220.43,215.77 C220.43,215.77 220.47,215.81 220.47,215.81 C220.47,215.81 220.52,215.86 220.52,215.86 C220.52,215.86 220.56,215.9 220.56,215.9 C220.56,215.9 220.6,215.95 220.6,215.95 C220.6,215.95 220.64,216 220.64,216 C220.64,216 220.68,216.05 220.68,216.05 C220.68,216.05 220.72,216.1 220.72,216.1 C220.72,216.1 220.76,216.15 220.76,216.15 C220.76,216.15 220.8,216.2 220.8,216.2 C220.8,216.2 220.83,216.25 220.83,216.25 C220.83,216.25 220.87,216.3 220.87,216.3 C220.87,216.3 220.9,216.36 220.9,216.36 C220.9,216.36 220.94,216.41 220.94,216.41 C220.94,216.41 220.97,216.46 220.97,216.46 C220.97,216.46 221,216.51 221,216.51 C221,216.51 221.03,216.57 221.03,216.57 C221.03,216.57 221.06,216.63 221.06,216.63 C221.06,216.63 221.09,216.68 221.09,216.68 C221.09,216.68 221.12,216.74 221.12,216.74 C221.12,216.74 221.15,216.79 221.15,216.79 C221.15,216.79 221.18,216.85 221.18,216.85 C221.18,216.85 221.21,216.91 221.21,216.91 C221.21,216.91 221.23,216.96 221.23,216.96 C221.23,216.96 221.25,217.02 221.25,217.02 C221.25,217.02 221.28,217.08 221.28,217.08 C221.28,217.08 221.3,217.14 221.3,217.14 C221.3,217.14 221.33,217.2 221.33,217.2 C221.33,217.2 221.34,217.26 221.34,217.26 C221.34,217.26 221.36,217.32 221.36,217.32 C221.36,217.32 221.38,217.38 221.38,217.38 C221.38,217.38 221.4,217.44 221.4,217.44 C221.4,217.44 221.42,217.5 221.42,217.5 C221.42,217.5 221.44,217.56 221.44,217.56 C221.44,217.56 221.45,217.62 221.45,217.62 C221.45,217.62 221.46,217.68 221.46,217.68 C221.46,217.68 221.48,217.74 221.48,217.74 C221.48,217.74 221.49,217.8 221.49,217.8 C221.49,217.8 221.5,217.87 221.5,217.87 C221.5,217.87 221.51,217.93 221.51,217.93 C221.51,217.93 221.52,217.99 221.52,217.99 C221.52,217.99 221.53,218.05 221.53,218.05 C221.53,218.05 221.54,218.11 221.54,218.11 C221.54,218.11 221.54,218.18 221.54,218.18 C221.54,218.18 221.55,218.24 221.55,218.24 C221.55,218.24 221.55,218.3 221.55,218.3 C221.55,218.3 221.55,218.37 221.55,218.37 C221.55,218.37 221.56,218.43 221.56,218.43 C221.56,218.43 221.56,218.49 221.56,218.49 C221.56,218.49 221.56,218.55 221.56,218.55 C221.56,218.55 221.56,218.62 221.56,218.62 C221.56,218.62 221.56,218.68 221.56,218.68 C221.56,218.68 221.55,218.74 221.55,218.74 C221.55,218.74 221.55,218.81 221.55,218.81 C221.55,218.81 221.55,218.87 221.55,218.87 C221.55,218.87 221.54,218.93 221.54,218.93 C221.54,218.93 221.54,218.99 221.54,218.99 C221.54,218.99 221.53,219.06 221.53,219.06 C221.53,219.06 221.52,219.12 221.52,219.12 C221.52,219.12 221.51,219.18 221.51,219.18 C221.51,219.18 221.5,219.24 221.5,219.24 C221.5,219.24 221.49,219.3 221.49,219.3 C221.49,219.3 221.48,219.37 221.48,219.37 C221.48,219.37 221.46,219.43 221.46,219.43 C221.46,219.43 221.45,219.49 221.45,219.49 C221.45,219.49 221.43,219.55 221.43,219.55 C221.43,219.55 221.42,219.61 221.42,219.61 C221.42,219.61 221.4,219.67 221.4,219.67 C221.4,219.67 221.39,219.73 221.39,219.73 C221.39,219.73 221.37,219.79 221.37,219.79 C221.37,219.79 221.34,219.85 221.34,219.85 C221.34,219.85 221.32,219.91 221.32,219.91 C221.32,219.91 221.3,219.97 221.3,219.97 C221.3,219.97 221.28,220.03 221.28,220.03 C221.28,220.03 221.26,220.09 221.26,220.09 C221.26,220.09 221.23,220.14 221.23,220.14 C221.23,220.14 221.21,220.2 221.21,220.2 C221.21,220.2 221.18,220.26 221.18,220.26 C221.18,220.26 221.15,220.32 221.15,220.32 C221.15,220.32 221.13,220.37 221.13,220.37 C221.13,220.37 221.1,220.43 221.1,220.43 C221.1,220.43 221.07,220.48 221.07,220.48 C221.07,220.48 221.03,220.54 221.03,220.54 C221.03,220.54 221,220.59 221,220.59 C221,220.59 220.97,220.65 220.97,220.65 C220.97,220.65 220.94,220.7 220.94,220.7 C220.94,220.7 220.9,220.75 220.9,220.75 C220.9,220.75 220.87,220.8 220.87,220.8 C220.87,220.8 220.83,220.86 220.83,220.86 C220.83,220.86 220.8,220.91 220.8,220.91 C220.8,220.91 220.76,220.96 220.76,220.96 C220.76,220.96 220.72,221.01 220.72,221.01 C220.72,221.01 220.68,221.06 220.68,221.06 C220.68,221.06 220.64,221.11 220.64,221.11 C220.64,221.11 220.6,221.15 220.6,221.15 C220.6,221.15 220.56,221.2 220.56,221.2 C220.56,221.2 220.52,221.25 220.52,221.25 C220.52,221.25 220.48,221.3 220.48,221.3 C220.48,221.3 220.43,221.34 220.43,221.34 C220.43,221.34 220.39,221.38 220.39,221.38 C220.39,221.38 220.34,221.43 220.34,221.43 C220.34,221.43 220.3,221.47 220.3,221.47 C220.3,221.47 220.25,221.52 220.25,221.52 C220.25,221.52 220.21,221.56 220.21,221.56 C220.21,221.56 220.16,221.6 220.16,221.6 C220.16,221.6 220.11,221.64 220.11,221.64 C220.11,221.64 220.06,221.68 220.06,221.68 C220.06,221.68 220.01,221.72 220.01,221.72 C220.01,221.72 219.96,221.76 219.96,221.76 C219.96,221.76 219.91,221.8 219.91,221.8 C219.91,221.8 219.86,221.83 219.86,221.83 C219.86,221.83 219.81,221.87 219.81,221.87 C219.81,221.87 219.75,221.9 219.75,221.9 C219.75,221.9 219.7,221.93 219.7,221.93 C219.7,221.93 219.65,221.97 219.65,221.97 C219.65,221.97 219.6,222 219.6,222 C219.6,222 219.54,222.03 219.54,222.03 C219.54,222.03 219.49,222.06 219.49,222.06 C219.49,222.06 219.43,222.09 219.43,222.09 C219.43,222.09 219.37,222.12 219.37,222.12 C219.37,222.12 219.32,222.15 219.32,222.15 C219.32,222.15 219.26,222.18 219.26,222.18 C219.26,222.18 219.21,222.2 219.21,222.2 C219.21,222.2 219.15,222.23 219.15,222.23 C219.15,222.23 219.09,222.25 219.09,222.25 C219.09,222.25 219.03,222.28 219.03,222.28 C219.03,222.28 218.97,222.3 218.97,222.3 C218.97,222.3 218.91,222.32 218.91,222.32 C218.91,222.32 218.85,222.34 218.85,222.34 C218.85,222.34 218.79,222.36 218.79,222.36 C218.79,222.36 218.73,222.38 218.73,222.38 C218.73,222.38 218.67,222.4 218.67,222.4 C218.67,222.4 218.61,222.42 218.61,222.42 C218.61,222.42 218.55,222.44 218.55,222.44 C218.55,222.44 218.49,222.45 218.49,222.45 C218.49,222.45 218.43,222.46 218.43,222.46 C218.43,222.46 218.37,222.47 218.37,222.47 C218.37,222.47 218.31,222.49 218.31,222.49 C218.31,222.49 218.25,222.5 218.25,222.5 C218.25,222.5 218.18,222.51 218.18,222.51 C218.18,222.51 218.12,222.52 218.12,222.52 C218.12,222.52 218.06,222.53 218.06,222.53 C218.06,222.53 218,222.54 218,222.54 C218,222.54 217.93,222.54 217.93,222.54 C217.93,222.54 217.87,222.55 217.87,222.55 C217.87,222.55 217.81,222.55 217.81,222.55 C217.81,222.55 217.75,222.55 217.75,222.55 C217.75,222.55 217.68,222.56 217.68,222.56 C217.68,222.56 217.62,222.56 217.62,222.56 C217.62,222.56 217.56,222.56 217.56,222.56 C217.56,222.56 217.49,222.56 217.49,222.56 C217.49,222.56 217.43,222.56 217.43,222.56 C217.43,222.56 217.37,222.55 217.37,222.55 C217.37,222.55 217.3,222.55 217.3,222.55 C217.3,222.55 217.24,222.55 217.24,222.55 C217.24,222.55 217.18,222.54 217.18,222.54 C217.18,222.54 217.12,222.54 217.12,222.54 C217.12,222.54 217.05,222.53 217.05,222.53 C217.05,222.53 216.99,222.52 216.99,222.52 C216.99,222.52 216.93,222.51 216.93,222.51 C216.93,222.51 216.87,222.5 216.87,222.5 C216.87,222.5 216.81,222.49 216.81,222.49 C216.81,222.49 216.74,222.48 216.74,222.48 C216.74,222.48 216.68,222.46 216.68,222.46 C216.68,222.46 216.62,222.45 216.62,222.45 C216.62,222.45 216.56,222.43 216.56,222.43 C216.56,222.43 216.5,222.42 216.5,222.42 C216.5,222.42 216.44,222.4 216.44,222.4 C216.44,222.4 216.38,222.38 216.38,222.38 C216.38,222.38 216.32,222.36 216.32,222.36 C216.32,222.36 216.26,222.34 216.26,222.34 C216.26,222.34 216.2,222.32 216.2,222.32 C216.2,222.32 216.14,222.3 216.14,222.3 C216.14,222.3 216.08,222.28 216.08,222.28 C216.08,222.28 216.02,222.26 216.02,222.26 C216.02,222.26 215.97,222.23 215.97,222.23 C215.97,222.23 215.91,222.2 215.91,222.2 C215.91,222.2 215.85,222.18 215.85,222.18 C215.85,222.18 215.79,222.15 215.79,222.15 C215.79,222.15 215.74,222.12 215.74,222.12 C215.74,222.12 215.68,222.1 215.68,222.1 C215.68,222.1 215.63,222.06 215.63,222.06 C215.63,222.06 215.57,222.03 215.57,222.03 C215.57,222.03 215.52,222 215.52,222 C215.52,222 215.46,221.97 215.46,221.97 C215.46,221.97 215.41,221.94 215.41,221.94 C215.41,221.94 215.36,221.9 215.36,221.9 C215.36,221.9 215.31,221.87 215.31,221.87 C215.31,221.87 215.25,221.83 215.25,221.83 C215.25,221.83 215.2,221.79 215.2,221.79 C215.2,221.79 215.15,221.76 215.15,221.76 C215.15,221.76 215.1,221.72 215.1,221.72 C215.1,221.72 215.05,221.68 215.05,221.68 C215.05,221.68 215,221.64 215,221.64 C215,221.64 214.96,221.6 214.96,221.6 C214.96,221.6 214.91,221.56 214.91,221.56 C214.91,221.56 214.86,221.52 214.86,221.52 C214.86,221.52 214.81,221.48 214.81,221.48 C214.81,221.48 214.77,221.43 214.77,221.43 C214.77,221.43 214.73,221.39 214.73,221.39 C214.73,221.39 214.68,221.34 214.68,221.34 C214.68,221.34 214.64,221.3 214.64,221.3 C214.64,221.3 214.59,221.25 214.59,221.25 C214.59,221.25 214.55,221.2 214.55,221.2 C214.55,221.2 214.51,221.15 214.51,221.15 C214.51,221.15 214.47,221.11 214.47,221.11 C214.47,221.11 214.43,221.06 214.43,221.06 C214.43,221.06 214.39,221.01 214.39,221.01 C214.39,221.01 214.35,220.96 214.35,220.96 C214.35,220.96 214.31,220.91 214.31,220.91 C214.31,220.91 214.28,220.86 214.28,220.86 C214.28,220.86 214.25,220.81 214.25,220.81 C214.25,220.81 214.21,220.75 214.21,220.75 C214.21,220.75 214.18,220.7 214.18,220.7 C214.18,220.7 214.14,220.65 214.14,220.65 C214.14,220.65 214.11,220.59 214.11,220.59 C214.11,220.59 214.08,220.54 214.08,220.54 C214.08,220.54 214.05,220.48 214.05,220.48 C214.05,220.48 214.02,220.43 214.02,220.43 C214.02,220.43 213.99,220.37 213.99,220.37 C213.99,220.37 213.96,220.32 213.96,220.32 C213.96,220.32 213.93,220.26 213.93,220.26 C213.93,220.26 213.91,220.2 213.91,220.2 C213.91,220.2 213.88,220.14 213.88,220.14 C213.88,220.14 213.86,220.09 213.86,220.09 C213.86,220.09 213.83,220.03 213.83,220.03 C213.83,220.03 213.81,219.97 213.81,219.97 C213.81,219.97 213.79,219.91 213.79,219.91 C213.79,219.91 213.77,219.85 213.77,219.85 C213.77,219.85 213.75,219.79 213.75,219.79 C213.75,219.79 213.73,219.73 213.73,219.73 C213.73,219.73 213.71,219.67 213.71,219.67 C213.71,219.67 213.69,219.61 213.69,219.61 C213.69,219.61 213.68,219.55 213.68,219.55 C213.68,219.55 213.66,219.49 213.66,219.49 C213.66,219.49 213.65,219.43 213.65,219.43 C213.65,219.43 213.64,219.37 213.64,219.37 C213.64,219.37 213.62,219.31 213.62,219.31 C213.62,219.31 213.61,219.24 213.61,219.24 C213.61,219.24 213.6,219.18 213.6,219.18 C213.6,219.18 213.59,219.12 213.59,219.12 C213.59,219.12 213.58,219.06 213.58,219.06 C213.58,219.06 213.57,218.99 213.57,218.99 C213.57,218.99 213.57,218.93 213.57,218.93 C213.57,218.93 213.56,218.87 213.56,218.87 C213.56,218.87 213.56,218.81 213.56,218.81 C213.56,218.81 213.56,218.74 213.56,218.74 C213.56,218.74 213.56,218.68 213.56,218.68 C213.56,218.68 213.55,218.62 213.55,218.62 C213.55,218.62 213.55,218.55 213.55,218.55 C213.55,218.55 213.55,218.49 213.55,218.49 C213.55,218.49 213.56,218.43 213.56,218.43 C213.56,218.43 213.56,218.37 213.56,218.37 C213.56,218.37 213.56,218.3 213.56,218.3 C213.56,218.3 213.56,218.24 213.56,218.24 C213.56,218.24 213.57,218.18 213.57,218.18 C213.57,218.18 213.57,218.12 213.57,218.12 C213.57,218.12 213.58,218.05 213.58,218.05 C213.58,218.05 213.59,217.99 213.59,217.99 C213.59,217.99 213.6,217.93 213.6,217.93 C213.6,217.93 213.61,217.87 213.61,217.87 C213.61,217.87 213.62,217.8 213.62,217.8 C213.62,217.8 213.63,217.74 213.63,217.74 C213.63,217.74 213.65,217.68 213.65,217.68 C213.65,217.68 213.66,217.62 213.66,217.62 C213.66,217.62 213.68,217.56 213.68,217.56 C213.68,217.56 213.69,217.5 213.69,217.5 C213.69,217.5 213.71,217.44 213.71,217.44 C213.71,217.44 213.73,217.38 213.73,217.38 C213.73,217.38 213.75,217.32 213.75,217.32 C213.75,217.32 213.77,217.26 213.77,217.26 C213.77,217.26 213.79,217.2 213.79,217.2 C213.79,217.2 213.81,217.14 213.81,217.14 C213.81,217.14 213.83,217.08 213.83,217.08 C213.83,217.08 213.85,217.02 213.85,217.02 C213.85,217.02 213.88,216.96 213.88,216.96 C213.88,216.96 213.91,216.91 213.91,216.91 C213.91,216.91 213.93,216.85 213.93,216.85 C213.93,216.85 213.96,216.79 213.96,216.79 C213.96,216.79 213.99,216.74 213.99,216.74 C213.99,216.74 214.02,216.68 214.02,216.68 C214.02,216.68 214.05,216.63 214.05,216.63 C214.05,216.63 214.08,216.57 214.08,216.57 C214.08,216.57 214.11,216.52 214.11,216.52 C214.11,216.52 214.14,216.46 214.14,216.46 C214.14,216.46 214.17,216.41 214.17,216.41 C214.17,216.41 214.21,216.36 214.21,216.36 C214.21,216.36 214.24,216.3 214.24,216.3 C214.24,216.3 214.28,216.25 214.28,216.25 C214.28,216.25 214.32,216.2 214.32,216.2 C214.32,216.2 214.35,216.15 214.35,216.15 C214.35,216.15 214.39,216.1 214.39,216.1 C214.39,216.1 214.43,216.05 214.43,216.05 C214.43,216.05 214.47,216 214.47,216 C214.47,216 214.51,215.96 214.51,215.96 C214.51,215.96 214.55,215.91 214.55,215.91 C214.55,215.91 214.59,215.86 214.59,215.86 C214.59,215.86 214.64,215.81 214.64,215.81 C214.64,215.81 214.68,215.77 214.68,215.77 C214.68,215.77 214.73,215.72 214.73,215.72 C214.73,215.72 214.77,215.68 214.77,215.68 C214.77,215.68 214.82,215.64 214.82,215.64 C214.82,215.64 214.86,215.59 214.86,215.59 C214.86,215.59 214.91,215.55 214.91,215.55 C214.91,215.55 214.96,215.51 214.96,215.51 C214.96,215.51 215,215.47 215,215.47 C215,215.47 215.05,215.43 215.05,215.43 C215.05,215.43 215.1,215.39 215.1,215.39 C215.1,215.39 215.15,215.35 215.15,215.35 C215.15,215.35 215.2,215.31 215.2,215.31 C215.2,215.31 215.25,215.28 215.25,215.28 C215.25,215.28 215.31,215.24 215.31,215.24 C215.31,215.24 215.36,215.21 215.36,215.21 C215.36,215.21 215.41,215.17 215.41,215.17 C215.41,215.17 215.46,215.14 215.46,215.14 C215.46,215.14 215.52,215.11 215.52,215.11 C215.52,215.11 215.57,215.08 215.57,215.08 C215.57,215.08 215.63,215.05 215.63,215.05 C215.63,215.05 215.68,215.02 215.68,215.02 C215.68,215.02 215.74,214.99 215.74,214.99 C215.74,214.99 215.79,214.96 215.79,214.96 C215.79,214.96 215.85,214.93 215.85,214.93 C215.85,214.93 215.91,214.9 215.91,214.9 C215.91,214.9 215.97,214.88 215.97,214.88 C215.97,214.88 216.02,214.86 216.02,214.86 C216.02,214.86 216.08,214.83 216.08,214.83 C216.08,214.83 216.14,214.81 216.14,214.81 C216.14,214.81 216.2,214.78 216.2,214.78 C216.2,214.78 216.26,214.77 216.26,214.77 C216.26,214.77 216.32,214.75 216.32,214.75 C216.32,214.75 216.38,214.73 216.38,214.73 C216.38,214.73 216.44,214.71 216.44,214.71 C216.44,214.71 216.5,214.69 216.5,214.69 C216.5,214.69 216.56,214.67 216.56,214.67 C216.56,214.67 216.62,214.66 216.62,214.66 C216.62,214.66 216.68,214.65 216.68,214.65 C216.68,214.65 216.74,214.63 216.74,214.63 C216.74,214.63 216.81,214.62 216.81,214.62 C216.81,214.62 216.87,214.61 216.87,214.61 C216.87,214.61 216.93,214.6 216.93,214.6 C216.93,214.6 216.99,214.59 216.99,214.59 C216.99,214.59 217.05,214.58 217.05,214.58 C217.05,214.58 217.12,214.57 217.12,214.57 C217.12,214.57 217.18,214.57 217.18,214.57 C217.18,214.57 217.24,214.56 217.24,214.56 C217.24,214.56 217.3,214.56 217.3,214.56 C217.3,214.56 217.37,214.56 217.37,214.56 C217.37,214.56 217.43,214.55 217.43,214.55 C217.43,214.55 217.49,214.55 217.49,214.55 C217.49,214.55 217.56,214.55 217.56,214.55 C217.56,214.55 217.62,214.55 217.62,214.55c "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="fillAlpha" android:duration="33" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M217.62 214.55 C217.62,214.55 217.68,214.55 217.68,214.55 C217.68,214.55 217.74,214.56 217.74,214.56 C217.74,214.56 217.81,214.56 217.81,214.56 C217.81,214.56 217.87,214.56 217.87,214.56 C217.87,214.56 217.93,214.57 217.93,214.57 C217.93,214.57 218,214.57 218,214.57 C218,214.57 218.06,214.58 218.06,214.58 C218.06,214.58 218.12,214.59 218.12,214.59 C218.12,214.59 218.18,214.6 218.18,214.6 C218.18,214.6 218.24,214.61 218.24,214.61 C218.24,214.61 218.31,214.62 218.31,214.62 C218.31,214.62 218.37,214.63 218.37,214.63 C218.37,214.63 218.43,214.65 218.43,214.65 C218.43,214.65 218.49,214.66 218.49,214.66 C218.49,214.66 218.55,214.68 218.55,214.68 C218.55,214.68 218.61,214.69 218.61,214.69 C218.61,214.69 218.67,214.71 218.67,214.71 C218.67,214.71 218.73,214.73 218.73,214.73 C218.73,214.73 218.79,214.75 218.79,214.75 C218.79,214.75 218.85,214.77 218.85,214.77 C218.85,214.77 218.91,214.79 218.91,214.79 C218.91,214.79 218.97,214.81 218.97,214.81 C218.97,214.81 219.03,214.83 219.03,214.83 C219.03,214.83 219.09,214.85 219.09,214.85 C219.09,214.85 219.15,214.88 219.15,214.88 C219.15,214.88 219.2,214.9 219.2,214.9 C219.2,214.9 219.26,214.93 219.26,214.93 C219.26,214.93 219.32,214.96 219.32,214.96 C219.32,214.96 219.37,214.98 219.37,214.98 C219.37,214.98 219.43,215.01 219.43,215.01 C219.43,215.01 219.48,215.05 219.48,215.05 C219.48,215.05 219.54,215.08 219.54,215.08 C219.54,215.08 219.59,215.11 219.59,215.11 C219.59,215.11 219.65,215.14 219.65,215.14 C219.65,215.14 219.7,215.17 219.7,215.17 C219.7,215.17 219.75,215.21 219.75,215.21 C219.75,215.21 219.81,215.24 219.81,215.24 C219.81,215.24 219.86,215.28 219.86,215.28 C219.86,215.28 219.91,215.32 219.91,215.32 C219.91,215.32 219.96,215.35 219.96,215.35 C219.96,215.35 220.01,215.39 220.01,215.39 C220.01,215.39 220.06,215.43 220.06,215.43 C220.06,215.43 220.11,215.47 220.11,215.47 C220.11,215.47 220.16,215.51 220.16,215.51 C220.16,215.51 220.2,215.55 220.2,215.55 C220.2,215.55 220.25,215.59 220.25,215.59 C220.25,215.59 220.3,215.63 220.3,215.63 C220.3,215.63 220.34,215.68 220.34,215.68 C220.34,215.68 220.39,215.72 220.39,215.72 C220.39,215.72 220.43,215.77 220.43,215.77 C220.43,215.77 220.47,215.81 220.47,215.81 C220.47,215.81 220.52,215.86 220.52,215.86 C220.52,215.86 220.56,215.9 220.56,215.9 C220.56,215.9 220.6,215.95 220.6,215.95 C220.6,215.95 220.64,216 220.64,216 C220.64,216 220.68,216.05 220.68,216.05 C220.68,216.05 220.72,216.1 220.72,216.1 C220.72,216.1 220.76,216.15 220.76,216.15 C220.76,216.15 220.8,216.2 220.8,216.2 C220.8,216.2 220.83,216.25 220.83,216.25 C220.83,216.25 220.87,216.3 220.87,216.3 C220.87,216.3 220.9,216.36 220.9,216.36 C220.9,216.36 220.94,216.41 220.94,216.41 C220.94,216.41 220.97,216.46 220.97,216.46 C220.97,216.46 221,216.51 221,216.51 C221,216.51 221.03,216.57 221.03,216.57 C221.03,216.57 221.06,216.63 221.06,216.63 C221.06,216.63 221.09,216.68 221.09,216.68 C221.09,216.68 221.12,216.74 221.12,216.74 C221.12,216.74 221.15,216.79 221.15,216.79 C221.15,216.79 221.18,216.85 221.18,216.85 C221.18,216.85 221.21,216.91 221.21,216.91 C221.21,216.91 221.23,216.96 221.23,216.96 C221.23,216.96 221.25,217.02 221.25,217.02 C221.25,217.02 221.28,217.08 221.28,217.08 C221.28,217.08 221.3,217.14 221.3,217.14 C221.3,217.14 221.33,217.2 221.33,217.2 C221.33,217.2 221.34,217.26 221.34,217.26 C221.34,217.26 221.36,217.32 221.36,217.32 C221.36,217.32 221.38,217.38 221.38,217.38 C221.38,217.38 221.4,217.44 221.4,217.44 C221.4,217.44 221.42,217.5 221.42,217.5 C221.42,217.5 221.44,217.56 221.44,217.56 C221.44,217.56 221.45,217.62 221.45,217.62 C221.45,217.62 221.46,217.68 221.46,217.68 C221.46,217.68 221.48,217.74 221.48,217.74 C221.48,217.74 221.49,217.8 221.49,217.8 C221.49,217.8 221.5,217.87 221.5,217.87 C221.5,217.87 221.51,217.93 221.51,217.93 C221.51,217.93 221.52,217.99 221.52,217.99 C221.52,217.99 221.53,218.05 221.53,218.05 C221.53,218.05 221.54,218.11 221.54,218.11 C221.54,218.11 221.54,218.18 221.54,218.18 C221.54,218.18 221.55,218.24 221.55,218.24 C221.55,218.24 221.55,218.3 221.55,218.3 C221.55,218.3 221.55,218.37 221.55,218.37 C221.55,218.37 221.56,218.43 221.56,218.43 C221.56,218.43 221.56,218.49 221.56,218.49 C221.56,218.49 221.56,218.55 221.56,218.55 C221.56,218.55 221.56,218.62 221.56,218.62 C221.56,218.62 221.56,218.68 221.56,218.68 C221.56,218.68 221.55,218.74 221.55,218.74 C221.55,218.74 221.55,218.81 221.55,218.81 C221.55,218.81 221.55,218.87 221.55,218.87 C221.55,218.87 221.54,218.93 221.54,218.93 C221.54,218.93 221.54,218.99 221.54,218.99 C221.54,218.99 221.53,219.06 221.53,219.06 C221.53,219.06 221.52,219.12 221.52,219.12 C221.52,219.12 221.51,219.18 221.51,219.18 C221.51,219.18 221.5,219.24 221.5,219.24 C221.5,219.24 221.49,219.3 221.49,219.3 C221.49,219.3 221.48,219.37 221.48,219.37 C221.48,219.37 221.46,219.43 221.46,219.43 C221.46,219.43 221.45,219.49 221.45,219.49 C221.45,219.49 221.43,219.55 221.43,219.55 C221.43,219.55 221.42,219.61 221.42,219.61 C221.42,219.61 221.4,219.67 221.4,219.67 C221.4,219.67 221.39,219.73 221.39,219.73 C221.39,219.73 221.37,219.79 221.37,219.79 C221.37,219.79 221.34,219.85 221.34,219.85 C221.34,219.85 221.32,219.91 221.32,219.91 C221.32,219.91 221.3,219.97 221.3,219.97 C221.3,219.97 221.28,220.03 221.28,220.03 C221.28,220.03 221.26,220.09 221.26,220.09 C221.26,220.09 221.23,220.14 221.23,220.14 C221.23,220.14 221.21,220.2 221.21,220.2 C221.21,220.2 221.18,220.26 221.18,220.26 C221.18,220.26 221.15,220.32 221.15,220.32 C221.15,220.32 221.13,220.37 221.13,220.37 C221.13,220.37 221.1,220.43 221.1,220.43 C221.1,220.43 221.07,220.48 221.07,220.48 C221.07,220.48 221.03,220.54 221.03,220.54 C221.03,220.54 221,220.59 221,220.59 C221,220.59 220.97,220.65 220.97,220.65 C220.97,220.65 220.94,220.7 220.94,220.7 C220.94,220.7 220.9,220.75 220.9,220.75 C220.9,220.75 220.87,220.8 220.87,220.8 C220.87,220.8 220.83,220.86 220.83,220.86 C220.83,220.86 220.8,220.91 220.8,220.91 C220.8,220.91 220.76,220.96 220.76,220.96 C220.76,220.96 220.72,221.01 220.72,221.01 C220.72,221.01 220.68,221.06 220.68,221.06 C220.68,221.06 220.64,221.11 220.64,221.11 C220.64,221.11 220.6,221.15 220.6,221.15 C220.6,221.15 220.56,221.2 220.56,221.2 C220.56,221.2 220.52,221.25 220.52,221.25 C220.52,221.25 220.48,221.3 220.48,221.3 C220.48,221.3 220.43,221.34 220.43,221.34 C220.43,221.34 220.39,221.38 220.39,221.38 C220.39,221.38 220.34,221.43 220.34,221.43 C220.34,221.43 220.3,221.47 220.3,221.47 C220.3,221.47 220.25,221.52 220.25,221.52 C220.25,221.52 220.21,221.56 220.21,221.56 C220.21,221.56 220.16,221.6 220.16,221.6 C220.16,221.6 220.11,221.64 220.11,221.64 C220.11,221.64 220.06,221.68 220.06,221.68 C220.06,221.68 220.01,221.72 220.01,221.72 C220.01,221.72 219.96,221.76 219.96,221.76 C219.96,221.76 219.91,221.8 219.91,221.8 C219.91,221.8 219.86,221.83 219.86,221.83 C219.86,221.83 219.81,221.87 219.81,221.87 C219.81,221.87 219.75,221.9 219.75,221.9 C219.75,221.9 219.7,221.93 219.7,221.93 C219.7,221.93 219.65,221.97 219.65,221.97 C219.65,221.97 219.6,222 219.6,222 C219.6,222 219.54,222.03 219.54,222.03 C219.54,222.03 219.49,222.06 219.49,222.06 C219.49,222.06 219.43,222.09 219.43,222.09 C219.43,222.09 219.37,222.12 219.37,222.12 C219.37,222.12 219.32,222.15 219.32,222.15 C219.32,222.15 219.26,222.18 219.26,222.18 C219.26,222.18 219.21,222.2 219.21,222.2 C219.21,222.2 219.15,222.23 219.15,222.23 C219.15,222.23 219.09,222.25 219.09,222.25 C219.09,222.25 219.03,222.28 219.03,222.28 C219.03,222.28 218.97,222.3 218.97,222.3 C218.97,222.3 218.91,222.32 218.91,222.32 C218.91,222.32 218.85,222.34 218.85,222.34 C218.85,222.34 218.79,222.36 218.79,222.36 C218.79,222.36 218.73,222.38 218.73,222.38 C218.73,222.38 218.67,222.4 218.67,222.4 C218.67,222.4 218.61,222.42 218.61,222.42 C218.61,222.42 218.55,222.44 218.55,222.44 C218.55,222.44 218.49,222.45 218.49,222.45 C218.49,222.45 218.43,222.46 218.43,222.46 C218.43,222.46 218.37,222.47 218.37,222.47 C218.37,222.47 218.31,222.49 218.31,222.49 C218.31,222.49 218.25,222.5 218.25,222.5 C218.25,222.5 218.18,222.51 218.18,222.51 C218.18,222.51 218.12,222.52 218.12,222.52 C218.12,222.52 218.06,222.53 218.06,222.53 C218.06,222.53 218,222.54 218,222.54 C218,222.54 217.93,222.54 217.93,222.54 C217.93,222.54 217.87,222.55 217.87,222.55 C217.87,222.55 217.81,222.55 217.81,222.55 C217.81,222.55 217.75,222.55 217.75,222.55 C217.75,222.55 217.68,222.56 217.68,222.56 C217.68,222.56 217.62,222.56 217.62,222.56 C217.62,222.56 217.56,222.56 217.56,222.56 C217.56,222.56 217.49,222.56 217.49,222.56 C217.49,222.56 217.43,222.56 217.43,222.56 C217.43,222.56 217.37,222.55 217.37,222.55 C217.37,222.55 217.3,222.55 217.3,222.55 C217.3,222.55 217.24,222.55 217.24,222.55 C217.24,222.55 217.18,222.54 217.18,222.54 C217.18,222.54 217.12,222.54 217.12,222.54 C217.12,222.54 217.05,222.53 217.05,222.53 C217.05,222.53 216.99,222.52 216.99,222.52 C216.99,222.52 216.93,222.51 216.93,222.51 C216.93,222.51 216.87,222.5 216.87,222.5 C216.87,222.5 216.81,222.49 216.81,222.49 C216.81,222.49 216.74,222.48 216.74,222.48 C216.74,222.48 216.68,222.46 216.68,222.46 C216.68,222.46 216.62,222.45 216.62,222.45 C216.62,222.45 216.56,222.43 216.56,222.43 C216.56,222.43 216.5,222.42 216.5,222.42 C216.5,222.42 216.44,222.4 216.44,222.4 C216.44,222.4 216.38,222.38 216.38,222.38 C216.38,222.38 216.32,222.36 216.32,222.36 C216.32,222.36 216.26,222.34 216.26,222.34 C216.26,222.34 216.2,222.32 216.2,222.32 C216.2,222.32 216.14,222.3 216.14,222.3 C216.14,222.3 216.08,222.28 216.08,222.28 C216.08,222.28 216.02,222.26 216.02,222.26 C216.02,222.26 215.97,222.23 215.97,222.23 C215.97,222.23 215.91,222.2 215.91,222.2 C215.91,222.2 215.85,222.18 215.85,222.18 C215.85,222.18 215.79,222.15 215.79,222.15 C215.79,222.15 215.74,222.12 215.74,222.12 C215.74,222.12 215.68,222.1 215.68,222.1 C215.68,222.1 215.63,222.06 215.63,222.06 C215.63,222.06 215.57,222.03 215.57,222.03 C215.57,222.03 215.52,222 215.52,222 C215.52,222 215.46,221.97 215.46,221.97 C215.46,221.97 215.41,221.94 215.41,221.94 C215.41,221.94 215.36,221.9 215.36,221.9 C215.36,221.9 215.31,221.87 215.31,221.87 C215.31,221.87 215.25,221.83 215.25,221.83 C215.25,221.83 215.2,221.79 215.2,221.79 C215.2,221.79 215.15,221.76 215.15,221.76 C215.15,221.76 215.1,221.72 215.1,221.72 C215.1,221.72 215.05,221.68 215.05,221.68 C215.05,221.68 215,221.64 215,221.64 C215,221.64 214.96,221.6 214.96,221.6 C214.96,221.6 214.91,221.56 214.91,221.56 C214.91,221.56 214.86,221.52 214.86,221.52 C214.86,221.52 214.81,221.48 214.81,221.48 C214.81,221.48 214.77,221.43 214.77,221.43 C214.77,221.43 214.73,221.39 214.73,221.39 C214.73,221.39 214.68,221.34 214.68,221.34 C214.68,221.34 214.64,221.3 214.64,221.3 C214.64,221.3 214.59,221.25 214.59,221.25 C214.59,221.25 214.55,221.2 214.55,221.2 C214.55,221.2 214.51,221.15 214.51,221.15 C214.51,221.15 214.47,221.11 214.47,221.11 C214.47,221.11 214.43,221.06 214.43,221.06 C214.43,221.06 214.39,221.01 214.39,221.01 C214.39,221.01 214.35,220.96 214.35,220.96 C214.35,220.96 214.31,220.91 214.31,220.91 C214.31,220.91 214.28,220.86 214.28,220.86 C214.28,220.86 214.25,220.81 214.25,220.81 C214.25,220.81 214.21,220.75 214.21,220.75 C214.21,220.75 214.18,220.7 214.18,220.7 C214.18,220.7 214.14,220.65 214.14,220.65 C214.14,220.65 214.11,220.59 214.11,220.59 C214.11,220.59 214.08,220.54 214.08,220.54 C214.08,220.54 214.05,220.48 214.05,220.48 C214.05,220.48 214.02,220.43 214.02,220.43 C214.02,220.43 213.99,220.37 213.99,220.37 C213.99,220.37 213.96,220.32 213.96,220.32 C213.96,220.32 213.93,220.26 213.93,220.26 C213.93,220.26 213.91,220.2 213.91,220.2 C213.91,220.2 213.88,220.14 213.88,220.14 C213.88,220.14 213.86,220.09 213.86,220.09 C213.86,220.09 213.83,220.03 213.83,220.03 C213.83,220.03 213.81,219.97 213.81,219.97 C213.81,219.97 213.79,219.91 213.79,219.91 C213.79,219.91 213.77,219.85 213.77,219.85 C213.77,219.85 213.75,219.79 213.75,219.79 C213.75,219.79 213.73,219.73 213.73,219.73 C213.73,219.73 213.71,219.67 213.71,219.67 C213.71,219.67 213.69,219.61 213.69,219.61 C213.69,219.61 213.68,219.55 213.68,219.55 C213.68,219.55 213.66,219.49 213.66,219.49 C213.66,219.49 213.65,219.43 213.65,219.43 C213.65,219.43 213.64,219.37 213.64,219.37 C213.64,219.37 213.62,219.31 213.62,219.31 C213.62,219.31 213.61,219.24 213.61,219.24 C213.61,219.24 213.6,219.18 213.6,219.18 C213.6,219.18 213.59,219.12 213.59,219.12 C213.59,219.12 213.58,219.06 213.58,219.06 C213.58,219.06 213.57,218.99 213.57,218.99 C213.57,218.99 213.57,218.93 213.57,218.93 C213.57,218.93 213.56,218.87 213.56,218.87 C213.56,218.87 213.56,218.81 213.56,218.81 C213.56,218.81 213.56,218.74 213.56,218.74 C213.56,218.74 213.56,218.68 213.56,218.68 C213.56,218.68 213.55,218.62 213.55,218.62 C213.55,218.62 213.55,218.55 213.55,218.55 C213.55,218.55 213.55,218.49 213.55,218.49 C213.55,218.49 213.56,218.43 213.56,218.43 C213.56,218.43 213.56,218.37 213.56,218.37 C213.56,218.37 213.56,218.3 213.56,218.3 C213.56,218.3 213.56,218.24 213.56,218.24 C213.56,218.24 213.57,218.18 213.57,218.18 C213.57,218.18 213.57,218.12 213.57,218.12 C213.57,218.12 213.58,218.05 213.58,218.05 C213.58,218.05 213.59,217.99 213.59,217.99 C213.59,217.99 213.6,217.93 213.6,217.93 C213.6,217.93 213.61,217.87 213.61,217.87 C213.61,217.87 213.62,217.8 213.62,217.8 C213.62,217.8 213.63,217.74 213.63,217.74 C213.63,217.74 213.65,217.68 213.65,217.68 C213.65,217.68 213.66,217.62 213.66,217.62 C213.66,217.62 213.68,217.56 213.68,217.56 C213.68,217.56 213.69,217.5 213.69,217.5 C213.69,217.5 213.71,217.44 213.71,217.44 C213.71,217.44 213.73,217.38 213.73,217.38 C213.73,217.38 213.75,217.32 213.75,217.32 C213.75,217.32 213.77,217.26 213.77,217.26 C213.77,217.26 213.79,217.2 213.79,217.2 C213.79,217.2 213.81,217.14 213.81,217.14 C213.81,217.14 213.83,217.08 213.83,217.08 C213.83,217.08 213.85,217.02 213.85,217.02 C213.85,217.02 213.88,216.96 213.88,216.96 C213.88,216.96 213.91,216.91 213.91,216.91 C213.91,216.91 213.93,216.85 213.93,216.85 C213.93,216.85 213.96,216.79 213.96,216.79 C213.96,216.79 213.99,216.74 213.99,216.74 C213.99,216.74 214.02,216.68 214.02,216.68 C214.02,216.68 214.05,216.63 214.05,216.63 C214.05,216.63 214.08,216.57 214.08,216.57 C214.08,216.57 214.11,216.52 214.11,216.52 C214.11,216.52 214.14,216.46 214.14,216.46 C214.14,216.46 214.17,216.41 214.17,216.41 C214.17,216.41 214.21,216.36 214.21,216.36 C214.21,216.36 214.24,216.3 214.24,216.3 C214.24,216.3 214.28,216.25 214.28,216.25 C214.28,216.25 214.32,216.2 214.32,216.2 C214.32,216.2 214.35,216.15 214.35,216.15 C214.35,216.15 214.39,216.1 214.39,216.1 C214.39,216.1 214.43,216.05 214.43,216.05 C214.43,216.05 214.47,216 214.47,216 C214.47,216 214.51,215.96 214.51,215.96 C214.51,215.96 214.55,215.91 214.55,215.91 C214.55,215.91 214.59,215.86 214.59,215.86 C214.59,215.86 214.64,215.81 214.64,215.81 C214.64,215.81 214.68,215.77 214.68,215.77 C214.68,215.77 214.73,215.72 214.73,215.72 C214.73,215.72 214.77,215.68 214.77,215.68 C214.77,215.68 214.82,215.64 214.82,215.64 C214.82,215.64 214.86,215.59 214.86,215.59 C214.86,215.59 214.91,215.55 214.91,215.55 C214.91,215.55 214.96,215.51 214.96,215.51 C214.96,215.51 215,215.47 215,215.47 C215,215.47 215.05,215.43 215.05,215.43 C215.05,215.43 215.1,215.39 215.1,215.39 C215.1,215.39 215.15,215.35 215.15,215.35 C215.15,215.35 215.2,215.31 215.2,215.31 C215.2,215.31 215.25,215.28 215.25,215.28 C215.25,215.28 215.31,215.24 215.31,215.24 C215.31,215.24 215.36,215.21 215.36,215.21 C215.36,215.21 215.41,215.17 215.41,215.17 C215.41,215.17 215.46,215.14 215.46,215.14 C215.46,215.14 215.52,215.11 215.52,215.11 C215.52,215.11 215.57,215.08 215.57,215.08 C215.57,215.08 215.63,215.05 215.63,215.05 C215.63,215.05 215.68,215.02 215.68,215.02 C215.68,215.02 215.74,214.99 215.74,214.99 C215.74,214.99 215.79,214.96 215.79,214.96 C215.79,214.96 215.85,214.93 215.85,214.93 C215.85,214.93 215.91,214.9 215.91,214.9 C215.91,214.9 215.97,214.88 215.97,214.88 C215.97,214.88 216.02,214.86 216.02,214.86 C216.02,214.86 216.08,214.83 216.08,214.83 C216.08,214.83 216.14,214.81 216.14,214.81 C216.14,214.81 216.2,214.78 216.2,214.78 C216.2,214.78 216.26,214.77 216.26,214.77 C216.26,214.77 216.32,214.75 216.32,214.75 C216.32,214.75 216.38,214.73 216.38,214.73 C216.38,214.73 216.44,214.71 216.44,214.71 C216.44,214.71 216.5,214.69 216.5,214.69 C216.5,214.69 216.56,214.67 216.56,214.67 C216.56,214.67 216.62,214.66 216.62,214.66 C216.62,214.66 216.68,214.65 216.68,214.65 C216.68,214.65 216.74,214.63 216.74,214.63 C216.74,214.63 216.81,214.62 216.81,214.62 C216.81,214.62 216.87,214.61 216.87,214.61 C216.87,214.61 216.93,214.6 216.93,214.6 C216.93,214.6 216.99,214.59 216.99,214.59 C216.99,214.59 217.05,214.58 217.05,214.58 C217.05,214.58 217.12,214.57 217.12,214.57 C217.12,214.57 217.18,214.57 217.18,214.57 C217.18,214.57 217.24,214.56 217.24,214.56 C217.24,214.56 217.3,214.56 217.3,214.56 C217.3,214.56 217.37,214.56 217.37,214.56 C217.37,214.56 217.43,214.55 217.43,214.55 C217.43,214.55 217.49,214.55 217.49,214.55 C217.49,214.55 217.56,214.55 217.56,214.55 C217.56,214.55 217.62,214.55 217.62,214.55c " android:valueTo="M217.7 202.08 C217.7,202.08 217.97,202.09 217.97,202.09 C217.97,202.09 218.23,202.13 218.23,202.13 C218.23,202.13 218.49,202.16 218.49,202.16 C218.49,202.16 218.75,202.22 218.75,202.22 C218.75,202.22 219.01,202.28 219.01,202.28 C219.01,202.28 219.26,202.36 219.26,202.36 C219.26,202.36 219.51,202.44 219.51,202.44 C219.51,202.44 219.75,202.54 219.75,202.54 C219.75,202.54 219.99,202.65 219.99,202.65 C219.99,202.65 220.23,202.77 220.23,202.77 C220.23,202.77 220.46,202.9 220.46,202.9 C220.46,202.9 220.68,203.05 220.68,203.05 C220.68,203.05 220.9,203.2 220.9,203.2 C220.9,203.2 221.11,203.35 221.11,203.35 C221.11,203.35 221.33,203.51 221.33,203.51 C221.33,203.51 221.54,203.66 221.54,203.66 C221.54,203.66 221.75,203.82 221.75,203.82 C221.75,203.82 221.97,203.97 221.97,203.97 C221.97,203.97 222.18,204.13 222.18,204.13 C222.18,204.13 222.4,204.28 222.4,204.28 C222.4,204.28 222.61,204.44 222.61,204.44 C222.61,204.44 222.83,204.59 222.83,204.59 C222.83,204.59 223.04,204.75 223.04,204.75 C223.04,204.75 223.25,204.9 223.25,204.9 C223.25,204.9 223.47,205.06 223.47,205.06 C223.47,205.06 223.68,205.21 223.68,205.21 C223.68,205.21 223.9,205.37 223.9,205.37 C223.9,205.37 224.11,205.52 224.11,205.52 C224.11,205.52 224.33,205.68 224.33,205.68 C224.33,205.68 224.54,205.83 224.54,205.83 C224.54,205.83 224.75,205.98 224.75,205.98 C224.75,205.98 224.97,206.14 224.97,206.14 C224.97,206.14 225.18,206.29 225.18,206.29 C225.18,206.29 225.4,206.45 225.4,206.45 C225.4,206.45 225.61,206.6 225.61,206.6 C225.61,206.6 225.83,206.76 225.83,206.76 C225.83,206.76 226.04,206.91 226.04,206.91 C226.04,206.91 226.25,207.07 226.25,207.07 C226.25,207.07 226.47,207.22 226.47,207.22 C226.47,207.22 226.68,207.38 226.68,207.38 C226.68,207.38 226.9,207.53 226.9,207.53 C226.9,207.53 227.11,207.69 227.11,207.69 C227.11,207.69 227.32,207.84 227.32,207.84 C227.32,207.84 227.54,208 227.54,208 C227.54,208 227.75,208.15 227.75,208.15 C227.75,208.15 227.96,208.31 227.96,208.31 C227.96,208.31 228.18,208.46 228.18,208.46 C228.18,208.46 228.39,208.62 228.39,208.62 C228.39,208.62 228.61,208.78 228.61,208.78 C228.61,208.78 228.82,208.93 228.82,208.93 C228.82,208.93 229.03,209.09 229.03,209.09 C229.03,209.09 229.25,209.24 229.25,209.24 C229.25,209.24 229.46,209.4 229.46,209.4 C229.46,209.4 229.67,209.55 229.67,209.55 C229.67,209.55 229.89,209.71 229.89,209.71 C229.89,209.71 230.1,209.86 230.1,209.86 C230.1,209.86 230.32,210.02 230.32,210.02 C230.32,210.02 230.53,210.17 230.53,210.17 C230.53,210.17 230.74,210.33 230.74,210.33 C230.74,210.33 230.96,210.49 230.96,210.49 C230.96,210.49 231.17,210.64 231.17,210.64 C231.17,210.64 231.38,210.8 231.38,210.8 C231.38,210.8 231.6,210.95 231.6,210.95 C231.6,210.95 231.81,211.11 231.81,211.11 C231.81,211.11 232.03,211.26 232.03,211.26 C232.03,211.26 232.24,211.42 232.24,211.42 C232.24,211.42 232.44,211.59 232.44,211.59 C232.44,211.59 232.65,211.75 232.65,211.75 C232.65,211.75 232.84,211.94 232.84,211.94 C232.84,211.94 233.03,212.12 233.03,212.12 C233.03,212.12 233.2,212.32 233.2,212.32 C233.2,212.32 233.37,212.53 233.37,212.53 C233.37,212.53 233.52,212.74 233.52,212.74 C233.52,212.74 233.67,212.96 233.67,212.96 C233.67,212.96 233.8,213.19 233.8,213.19 C233.8,213.19 233.93,213.42 233.93,213.42 C233.93,213.42 234.04,213.66 234.04,213.66 C234.04,213.66 234.14,213.9 234.14,213.9 C234.14,213.9 234.24,214.15 234.24,214.15 C234.24,214.15 234.31,214.4 234.31,214.4 C234.31,214.4 234.39,214.66 234.39,214.66 C234.39,214.66 234.44,214.92 234.44,214.92 C234.44,214.92 234.49,215.18 234.49,215.18 C234.49,215.18 234.51,215.44 234.51,215.44 C234.51,215.44 234.54,215.7 234.54,215.7 C234.54,215.7 234.54,215.96 234.54,215.96 C234.54,215.96 234.54,216.23 234.54,216.23 C234.54,216.23 234.52,216.49 234.52,216.49 C234.52,216.49 234.49,216.76 234.49,216.76 C234.49,216.76 234.46,217.02 234.46,217.02 C234.46,217.02 234.4,217.28 234.4,217.28 C234.4,217.28 234.34,217.53 234.34,217.53 C234.34,217.53 234.26,217.79 234.26,217.79 C234.26,217.79 234.18,218.04 234.18,218.04 C234.18,218.04 234.1,218.29 234.1,218.29 C234.1,218.29 234.02,218.54 234.02,218.54 C234.02,218.54 233.94,218.79 233.94,218.79 C233.94,218.79 233.86,219.04 233.86,219.04 C233.86,219.04 233.78,219.29 233.78,219.29 C233.78,219.29 233.69,219.55 233.69,219.55 C233.69,219.55 233.61,219.8 233.61,219.8 C233.61,219.8 233.53,220.05 233.53,220.05 C233.53,220.05 233.45,220.3 233.45,220.3 C233.45,220.3 233.37,220.55 233.37,220.55 C233.37,220.55 233.29,220.8 233.29,220.8 C233.29,220.8 233.21,221.05 233.21,221.05 C233.21,221.05 233.12,221.31 233.12,221.31 C233.12,221.31 233.04,221.56 233.04,221.56 C233.04,221.56 232.96,221.81 232.96,221.81 C232.96,221.81 232.88,222.06 232.88,222.06 C232.88,222.06 232.8,222.31 232.8,222.31 C232.8,222.31 232.72,222.56 232.72,222.56 C232.72,222.56 232.64,222.81 232.64,222.81 C232.64,222.81 232.55,223.07 232.55,223.07 C232.55,223.07 232.47,223.32 232.47,223.32 C232.47,223.32 232.39,223.57 232.39,223.57 C232.39,223.57 232.31,223.82 232.31,223.82 C232.31,223.82 232.23,224.07 232.23,224.07 C232.23,224.07 232.15,224.32 232.15,224.32 C232.15,224.32 232.06,224.57 232.06,224.57 C232.06,224.57 231.98,224.83 231.98,224.83 C231.98,224.83 231.9,225.08 231.9,225.08 C231.9,225.08 231.82,225.33 231.82,225.33 C231.82,225.33 231.74,225.58 231.74,225.58 C231.74,225.58 231.65,225.83 231.65,225.83 C231.65,225.83 231.57,226.08 231.57,226.08 C231.57,226.08 231.49,226.33 231.49,226.33 C231.49,226.33 231.41,226.58 231.41,226.58 C231.41,226.58 231.32,226.83 231.32,226.83 C231.32,226.83 231.24,227.08 231.24,227.08 C231.24,227.08 231.16,227.34 231.16,227.34 C231.16,227.34 231.08,227.59 231.08,227.59 C231.08,227.59 230.99,227.84 230.99,227.84 C230.99,227.84 230.91,228.09 230.91,228.09 C230.91,228.09 230.83,228.34 230.83,228.34 C230.83,228.34 230.75,228.59 230.75,228.59 C230.75,228.59 230.67,228.84 230.67,228.84 C230.67,228.84 230.58,229.09 230.58,229.09 C230.58,229.09 230.5,229.35 230.5,229.35 C230.5,229.35 230.42,229.6 230.42,229.6 C230.42,229.6 230.34,229.85 230.34,229.85 C230.34,229.85 230.25,230.1 230.25,230.1 C230.25,230.1 230.17,230.35 230.17,230.35 C230.17,230.35 230.09,230.6 230.09,230.6 C230.09,230.6 230.01,230.85 230.01,230.85 C230.01,230.85 229.92,231.1 229.92,231.1 C229.92,231.1 229.83,231.35 229.83,231.35 C229.83,231.35 229.73,231.6 229.73,231.6 C229.73,231.6 229.61,231.83 229.61,231.83 C229.61,231.83 229.49,232.07 229.49,232.07 C229.49,232.07 229.36,232.29 229.36,232.29 C229.36,232.29 229.21,232.52 229.21,232.52 C229.21,232.52 229.06,232.73 229.06,232.73 C229.06,232.73 228.89,232.94 228.89,232.94 C228.89,232.94 228.72,233.13 228.72,233.13 C228.72,233.13 228.54,233.32 228.54,233.32 C228.54,233.32 228.34,233.51 228.34,233.51 C228.34,233.51 228.14,233.68 228.14,233.68 C228.14,233.68 227.94,233.84 227.94,233.84 C227.94,233.84 227.72,233.99 227.72,233.99 C227.72,233.99 227.5,234.14 227.5,234.14 C227.5,234.14 227.27,234.27 227.27,234.27 C227.27,234.27 227.04,234.39 227.04,234.39 C227.04,234.39 226.79,234.5 226.79,234.5 C226.79,234.5 226.55,234.6 226.55,234.6 C226.55,234.6 226.3,234.68 226.3,234.68 C226.3,234.68 226.05,234.76 226.05,234.76 C226.05,234.76 225.79,234.82 225.79,234.82 C225.79,234.82 225.53,234.88 225.53,234.88 C225.53,234.88 225.27,234.92 225.27,234.92 C225.27,234.92 225.01,234.95 225.01,234.95 C225.01,234.95 224.74,234.96 224.74,234.96 C224.74,234.96 224.48,234.96 224.48,234.96 C224.48,234.96 224.22,234.96 224.22,234.96 C224.22,234.96 223.95,234.96 223.95,234.96 C223.95,234.96 223.69,234.96 223.69,234.96 C223.69,234.96 223.42,234.96 223.42,234.96 C223.42,234.96 223.16,234.96 223.16,234.96 C223.16,234.96 222.89,234.96 222.89,234.96 C222.89,234.96 222.63,234.96 222.63,234.96 C222.63,234.96 222.37,234.97 222.37,234.97 C222.37,234.97 222.1,234.97 222.1,234.97 C222.1,234.97 221.84,234.97 221.84,234.97 C221.84,234.97 221.57,234.97 221.57,234.97 C221.57,234.97 221.31,234.97 221.31,234.97 C221.31,234.97 221.04,234.97 221.04,234.97 C221.04,234.97 220.78,234.97 220.78,234.97 C220.78,234.97 220.52,234.97 220.52,234.97 C220.52,234.97 220.25,234.97 220.25,234.97 C220.25,234.97 219.99,234.97 219.99,234.97 C219.99,234.97 219.72,234.97 219.72,234.97 C219.72,234.97 219.46,234.97 219.46,234.97 C219.46,234.97 219.19,234.97 219.19,234.97 C219.19,234.97 218.93,234.97 218.93,234.97 C218.93,234.97 218.67,234.97 218.67,234.97 C218.67,234.97 218.4,234.97 218.4,234.97 C218.4,234.97 218.14,234.97 218.14,234.97 C218.14,234.97 217.87,234.97 217.87,234.97 C217.87,234.97 217.61,234.97 217.61,234.97 C217.61,234.97 217.34,234.97 217.34,234.97 C217.34,234.97 217.08,234.97 217.08,234.97 C217.08,234.97 216.82,234.97 216.82,234.97 C216.82,234.97 216.55,234.97 216.55,234.97 C216.55,234.97 216.29,234.97 216.29,234.97 C216.29,234.97 216.02,234.97 216.02,234.97 C216.02,234.97 215.76,234.97 215.76,234.97 C215.76,234.97 215.49,234.97 215.49,234.97 C215.49,234.97 215.23,234.97 215.23,234.97 C215.23,234.97 214.97,234.97 214.97,234.97 C214.97,234.97 214.7,234.97 214.7,234.97 C214.7,234.97 214.44,234.97 214.44,234.97 C214.44,234.97 214.17,234.97 214.17,234.97 C214.17,234.97 213.91,234.97 213.91,234.97 C213.91,234.97 213.64,234.97 213.64,234.97 C213.64,234.97 213.38,234.97 213.38,234.97 C213.38,234.97 213.12,234.97 213.12,234.97 C213.12,234.97 212.85,234.97 212.85,234.97 C212.85,234.97 212.59,234.96 212.59,234.96 C212.59,234.96 212.32,234.96 212.32,234.96 C212.32,234.96 212.06,234.96 212.06,234.96 C212.06,234.96 211.79,234.96 211.79,234.96 C211.79,234.96 211.53,234.96 211.53,234.96 C211.53,234.96 211.27,234.96 211.27,234.96 C211.27,234.96 211,234.96 211,234.96 C211,234.96 210.74,234.96 210.74,234.96 C210.74,234.96 210.47,234.96 210.47,234.96 C210.47,234.96 210.21,234.95 210.21,234.95 C210.21,234.95 209.94,234.93 209.94,234.93 C209.94,234.93 209.68,234.9 209.68,234.9 C209.68,234.9 209.42,234.86 209.42,234.86 C209.42,234.86 209.16,234.8 209.16,234.8 C209.16,234.8 208.91,234.74 208.91,234.74 C208.91,234.74 208.66,234.66 208.66,234.66 C208.66,234.66 208.41,234.56 208.41,234.56 C208.41,234.56 208.17,234.46 208.17,234.46 C208.17,234.46 207.93,234.35 207.93,234.35 C207.93,234.35 207.69,234.22 207.69,234.22 C207.69,234.22 207.47,234.08 207.47,234.08 C207.47,234.08 207.25,233.94 207.25,233.94 C207.25,233.94 207.04,233.78 207.04,233.78 C207.04,233.78 206.83,233.62 206.83,233.62 C206.83,233.62 206.63,233.44 206.63,233.44 C206.63,233.44 206.44,233.26 206.44,233.26 C206.44,233.26 206.27,233.06 206.27,233.06 C206.27,233.06 206.09,232.86 206.09,232.86 C206.09,232.86 205.93,232.65 205.93,232.65 C205.93,232.65 205.78,232.44 205.78,232.44 C205.78,232.44 205.64,232.21 205.64,232.21 C205.64,232.21 205.51,231.98 205.51,231.98 C205.51,231.98 205.39,231.75 205.39,231.75 C205.39,231.75 205.28,231.51 205.28,231.51 C205.28,231.51 205.18,231.26 205.18,231.26 C205.18,231.26 205.09,231.01 205.09,231.01 C205.09,231.01 205.01,230.76 205.01,230.76 C205.01,230.76 204.93,230.51 204.93,230.51 C204.93,230.51 204.85,230.26 204.85,230.26 C204.85,230.26 204.76,230.01 204.76,230.01 C204.76,230.01 204.68,229.76 204.68,229.76 C204.68,229.76 204.6,229.51 204.6,229.51 C204.6,229.51 204.52,229.26 204.52,229.26 C204.52,229.26 204.43,229.01 204.43,229.01 C204.43,229.01 204.35,228.75 204.35,228.75 C204.35,228.75 204.27,228.5 204.27,228.5 C204.27,228.5 204.19,228.25 204.19,228.25 C204.19,228.25 204.1,228 204.1,228 C204.1,228 204.02,227.75 204.02,227.75 C204.02,227.75 203.94,227.5 203.94,227.5 C203.94,227.5 203.86,227.25 203.86,227.25 C203.86,227.25 203.78,227 203.78,227 C203.78,227 203.69,226.74 203.69,226.74 C203.69,226.74 203.61,226.49 203.61,226.49 C203.61,226.49 203.53,226.24 203.53,226.24 C203.53,226.24 203.45,225.99 203.45,225.99 C203.45,225.99 203.36,225.74 203.36,225.74 C203.36,225.74 203.28,225.49 203.28,225.49 C203.28,225.49 203.2,225.24 203.2,225.24 C203.2,225.24 203.12,224.99 203.12,224.99 C203.12,224.99 203.03,224.74 203.03,224.74 C203.03,224.74 202.95,224.48 202.95,224.48 C202.95,224.48 202.87,224.23 202.87,224.23 C202.87,224.23 202.79,223.98 202.79,223.98 C202.79,223.98 202.71,223.73 202.71,223.73 C202.71,223.73 202.63,223.48 202.63,223.48 C202.63,223.48 202.54,223.23 202.54,223.23 C202.54,223.23 202.46,222.98 202.46,222.98 C202.46,222.98 202.38,222.72 202.38,222.72 C202.38,222.72 202.3,222.47 202.3,222.47 C202.3,222.47 202.22,222.22 202.22,222.22 C202.22,222.22 202.14,221.97 202.14,221.97 C202.14,221.97 202.06,221.72 202.06,221.72 C202.06,221.72 201.97,221.47 201.97,221.47 C201.97,221.47 201.89,221.22 201.89,221.22 C201.89,221.22 201.81,220.96 201.81,220.96 C201.81,220.96 201.73,220.71 201.73,220.71 C201.73,220.71 201.65,220.46 201.65,220.46 C201.65,220.46 201.57,220.21 201.57,220.21 C201.57,220.21 201.49,219.96 201.49,219.96 C201.49,219.96 201.4,219.71 201.4,219.71 C201.4,219.71 201.32,219.46 201.32,219.46 C201.32,219.46 201.24,219.2 201.24,219.2 C201.24,219.2 201.16,218.95 201.16,218.95 C201.16,218.95 201.08,218.7 201.08,218.7 C201.08,218.7 201,218.45 201,218.45 C201,218.45 200.92,218.2 200.92,218.2 C200.92,218.2 200.83,217.95 200.83,217.95 C200.83,217.95 200.76,217.7 200.76,217.7 C200.76,217.7 200.69,217.44 200.69,217.44 C200.69,217.44 200.62,217.18 200.62,217.18 C200.62,217.18 200.58,216.92 200.58,216.92 C200.58,216.92 200.54,216.66 200.54,216.66 C200.54,216.66 200.52,216.4 200.52,216.4 C200.52,216.4 200.5,216.14 200.5,216.14 C200.5,216.14 200.5,215.87 200.5,215.87 C200.5,215.87 200.52,215.61 200.52,215.61 C200.52,215.61 200.54,215.34 200.54,215.34 C200.54,215.34 200.58,215.08 200.58,215.08 C200.58,215.08 200.62,214.82 200.62,214.82 C200.62,214.82 200.69,214.57 200.69,214.57 C200.69,214.57 200.76,214.31 200.76,214.31 C200.76,214.31 200.84,214.06 200.84,214.06 C200.84,214.06 200.93,213.81 200.93,213.81 C200.93,213.81 201.05,213.57 201.05,213.57 C201.05,213.57 201.16,213.33 201.16,213.33 C201.16,213.33 201.29,213.11 201.29,213.11 C201.29,213.11 201.43,212.88 201.43,212.88 C201.43,212.88 201.58,212.67 201.58,212.67 C201.58,212.67 201.74,212.45 201.74,212.45 C201.74,212.45 201.91,212.25 201.91,212.25 C201.91,212.25 202.09,212.06 202.09,212.06 C202.09,212.06 202.27,211.87 202.27,211.87 C202.27,211.87 202.47,211.69 202.47,211.69 C202.47,211.69 202.67,211.52 202.67,211.52 C202.67,211.52 202.88,211.36 202.88,211.36 C202.88,211.36 203.1,211.21 203.1,211.21 C203.1,211.21 203.31,211.05 203.31,211.05 C203.31,211.05 203.52,210.9 203.52,210.9 C203.52,210.9 203.74,210.74 203.74,210.74 C203.74,210.74 203.95,210.58 203.95,210.58 C203.95,210.58 204.16,210.43 204.16,210.43 C204.16,210.43 204.38,210.27 204.38,210.27 C204.38,210.27 204.59,210.12 204.59,210.12 C204.59,210.12 204.81,209.96 204.81,209.96 C204.81,209.96 205.02,209.81 205.02,209.81 C205.02,209.81 205.23,209.65 205.23,209.65 C205.23,209.65 205.45,209.5 205.45,209.5 C205.45,209.5 205.66,209.34 205.66,209.34 C205.66,209.34 205.87,209.19 205.87,209.19 C205.87,209.19 206.09,209.03 206.09,209.03 C206.09,209.03 206.3,208.88 206.3,208.88 C206.3,208.88 206.52,208.72 206.52,208.72 C206.52,208.72 206.73,208.57 206.73,208.57 C206.73,208.57 206.94,208.41 206.94,208.41 C206.94,208.41 207.16,208.25 207.16,208.25 C207.16,208.25 207.37,208.1 207.37,208.1 C207.37,208.1 207.58,207.94 207.58,207.94 C207.58,207.94 207.8,207.79 207.8,207.79 C207.8,207.79 208.01,207.63 208.01,207.63 C208.01,207.63 208.23,207.48 208.23,207.48 C208.23,207.48 208.44,207.32 208.44,207.32 C208.44,207.32 208.65,207.17 208.65,207.17 C208.65,207.17 208.87,207.01 208.87,207.01 C208.87,207.01 209.08,206.86 209.08,206.86 C209.08,206.86 209.3,206.7 209.3,206.7 C209.3,206.7 209.51,206.55 209.51,206.55 C209.51,206.55 209.73,206.39 209.73,206.39 C209.73,206.39 209.94,206.24 209.94,206.24 C209.94,206.24 210.15,206.08 210.15,206.08 C210.15,206.08 210.37,205.93 210.37,205.93 C210.37,205.93 210.58,205.77 210.58,205.77 C210.58,205.77 210.8,205.62 210.8,205.62 C210.8,205.62 211.01,205.46 211.01,205.46 C211.01,205.46 211.23,205.31 211.23,205.31 C211.23,205.31 211.44,205.16 211.44,205.16 C211.44,205.16 211.65,205 211.65,205 C211.65,205 211.87,204.85 211.87,204.85 C211.87,204.85 212.08,204.69 212.08,204.69 C212.08,204.69 212.3,204.54 212.3,204.54 C212.3,204.54 212.51,204.38 212.51,204.38 C212.51,204.38 212.73,204.23 212.73,204.23 C212.73,204.23 212.94,204.07 212.94,204.07 C212.94,204.07 213.15,203.92 213.15,203.92 C213.15,203.92 213.37,203.76 213.37,203.76 C213.37,203.76 213.58,203.61 213.58,203.61 C213.58,203.61 213.8,203.45 213.8,203.45 C213.8,203.45 214.01,203.3 214.01,203.3 C214.01,203.3 214.23,203.14 214.23,203.14 C214.23,203.14 214.45,203 214.45,203 C214.45,203 214.67,202.86 214.67,202.86 C214.67,202.86 214.9,202.73 214.9,202.73 C214.9,202.73 215.14,202.61 215.14,202.61 C215.14,202.61 215.38,202.51 215.38,202.51 C215.38,202.51 215.63,202.41 215.63,202.41 C215.63,202.41 215.88,202.33 215.88,202.33 C215.88,202.33 216.13,202.26 216.13,202.26 C216.13,202.26 216.39,202.2 216.39,202.2 C216.39,202.2 216.65,202.15 216.65,202.15 C216.65,202.15 216.91,202.11 216.91,202.11 C216.91,202.11 217.18,202.09 217.18,202.09 C217.18,202.09 217.44,202.08 217.44,202.08 C217.44,202.08 217.7,202.08 217.7,202.08c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="283" android:startOffset="67" android:valueFrom="M217.7 202.08 C217.7,202.08 217.97,202.09 217.97,202.09 C217.97,202.09 218.23,202.13 218.23,202.13 C218.23,202.13 218.49,202.16 218.49,202.16 C218.49,202.16 218.75,202.22 218.75,202.22 C218.75,202.22 219.01,202.28 219.01,202.28 C219.01,202.28 219.26,202.36 219.26,202.36 C219.26,202.36 219.51,202.44 219.51,202.44 C219.51,202.44 219.75,202.54 219.75,202.54 C219.75,202.54 219.99,202.65 219.99,202.65 C219.99,202.65 220.23,202.77 220.23,202.77 C220.23,202.77 220.46,202.9 220.46,202.9 C220.46,202.9 220.68,203.05 220.68,203.05 C220.68,203.05 220.9,203.2 220.9,203.2 C220.9,203.2 221.11,203.35 221.11,203.35 C221.11,203.35 221.33,203.51 221.33,203.51 C221.33,203.51 221.54,203.66 221.54,203.66 C221.54,203.66 221.75,203.82 221.75,203.82 C221.75,203.82 221.97,203.97 221.97,203.97 C221.97,203.97 222.18,204.13 222.18,204.13 C222.18,204.13 222.4,204.28 222.4,204.28 C222.4,204.28 222.61,204.44 222.61,204.44 C222.61,204.44 222.83,204.59 222.83,204.59 C222.83,204.59 223.04,204.75 223.04,204.75 C223.04,204.75 223.25,204.9 223.25,204.9 C223.25,204.9 223.47,205.06 223.47,205.06 C223.47,205.06 223.68,205.21 223.68,205.21 C223.68,205.21 223.9,205.37 223.9,205.37 C223.9,205.37 224.11,205.52 224.11,205.52 C224.11,205.52 224.33,205.68 224.33,205.68 C224.33,205.68 224.54,205.83 224.54,205.83 C224.54,205.83 224.75,205.98 224.75,205.98 C224.75,205.98 224.97,206.14 224.97,206.14 C224.97,206.14 225.18,206.29 225.18,206.29 C225.18,206.29 225.4,206.45 225.4,206.45 C225.4,206.45 225.61,206.6 225.61,206.6 C225.61,206.6 225.83,206.76 225.83,206.76 C225.83,206.76 226.04,206.91 226.04,206.91 C226.04,206.91 226.25,207.07 226.25,207.07 C226.25,207.07 226.47,207.22 226.47,207.22 C226.47,207.22 226.68,207.38 226.68,207.38 C226.68,207.38 226.9,207.53 226.9,207.53 C226.9,207.53 227.11,207.69 227.11,207.69 C227.11,207.69 227.32,207.84 227.32,207.84 C227.32,207.84 227.54,208 227.54,208 C227.54,208 227.75,208.15 227.75,208.15 C227.75,208.15 227.96,208.31 227.96,208.31 C227.96,208.31 228.18,208.46 228.18,208.46 C228.18,208.46 228.39,208.62 228.39,208.62 C228.39,208.62 228.61,208.78 228.61,208.78 C228.61,208.78 228.82,208.93 228.82,208.93 C228.82,208.93 229.03,209.09 229.03,209.09 C229.03,209.09 229.25,209.24 229.25,209.24 C229.25,209.24 229.46,209.4 229.46,209.4 C229.46,209.4 229.67,209.55 229.67,209.55 C229.67,209.55 229.89,209.71 229.89,209.71 C229.89,209.71 230.1,209.86 230.1,209.86 C230.1,209.86 230.32,210.02 230.32,210.02 C230.32,210.02 230.53,210.17 230.53,210.17 C230.53,210.17 230.74,210.33 230.74,210.33 C230.74,210.33 230.96,210.49 230.96,210.49 C230.96,210.49 231.17,210.64 231.17,210.64 C231.17,210.64 231.38,210.8 231.38,210.8 C231.38,210.8 231.6,210.95 231.6,210.95 C231.6,210.95 231.81,211.11 231.81,211.11 C231.81,211.11 232.03,211.26 232.03,211.26 C232.03,211.26 232.24,211.42 232.24,211.42 C232.24,211.42 232.44,211.59 232.44,211.59 C232.44,211.59 232.65,211.75 232.65,211.75 C232.65,211.75 232.84,211.94 232.84,211.94 C232.84,211.94 233.03,212.12 233.03,212.12 C233.03,212.12 233.2,212.32 233.2,212.32 C233.2,212.32 233.37,212.53 233.37,212.53 C233.37,212.53 233.52,212.74 233.52,212.74 C233.52,212.74 233.67,212.96 233.67,212.96 C233.67,212.96 233.8,213.19 233.8,213.19 C233.8,213.19 233.93,213.42 233.93,213.42 C233.93,213.42 234.04,213.66 234.04,213.66 C234.04,213.66 234.14,213.9 234.14,213.9 C234.14,213.9 234.24,214.15 234.24,214.15 C234.24,214.15 234.31,214.4 234.31,214.4 C234.31,214.4 234.39,214.66 234.39,214.66 C234.39,214.66 234.44,214.92 234.44,214.92 C234.44,214.92 234.49,215.18 234.49,215.18 C234.49,215.18 234.51,215.44 234.51,215.44 C234.51,215.44 234.54,215.7 234.54,215.7 C234.54,215.7 234.54,215.96 234.54,215.96 C234.54,215.96 234.54,216.23 234.54,216.23 C234.54,216.23 234.52,216.49 234.52,216.49 C234.52,216.49 234.49,216.76 234.49,216.76 C234.49,216.76 234.46,217.02 234.46,217.02 C234.46,217.02 234.4,217.28 234.4,217.28 C234.4,217.28 234.34,217.53 234.34,217.53 C234.34,217.53 234.26,217.79 234.26,217.79 C234.26,217.79 234.18,218.04 234.18,218.04 C234.18,218.04 234.1,218.29 234.1,218.29 C234.1,218.29 234.02,218.54 234.02,218.54 C234.02,218.54 233.94,218.79 233.94,218.79 C233.94,218.79 233.86,219.04 233.86,219.04 C233.86,219.04 233.78,219.29 233.78,219.29 C233.78,219.29 233.69,219.55 233.69,219.55 C233.69,219.55 233.61,219.8 233.61,219.8 C233.61,219.8 233.53,220.05 233.53,220.05 C233.53,220.05 233.45,220.3 233.45,220.3 C233.45,220.3 233.37,220.55 233.37,220.55 C233.37,220.55 233.29,220.8 233.29,220.8 C233.29,220.8 233.21,221.05 233.21,221.05 C233.21,221.05 233.12,221.31 233.12,221.31 C233.12,221.31 233.04,221.56 233.04,221.56 C233.04,221.56 232.96,221.81 232.96,221.81 C232.96,221.81 232.88,222.06 232.88,222.06 C232.88,222.06 232.8,222.31 232.8,222.31 C232.8,222.31 232.72,222.56 232.72,222.56 C232.72,222.56 232.64,222.81 232.64,222.81 C232.64,222.81 232.55,223.07 232.55,223.07 C232.55,223.07 232.47,223.32 232.47,223.32 C232.47,223.32 232.39,223.57 232.39,223.57 C232.39,223.57 232.31,223.82 232.31,223.82 C232.31,223.82 232.23,224.07 232.23,224.07 C232.23,224.07 232.15,224.32 232.15,224.32 C232.15,224.32 232.06,224.57 232.06,224.57 C232.06,224.57 231.98,224.83 231.98,224.83 C231.98,224.83 231.9,225.08 231.9,225.08 C231.9,225.08 231.82,225.33 231.82,225.33 C231.82,225.33 231.74,225.58 231.74,225.58 C231.74,225.58 231.65,225.83 231.65,225.83 C231.65,225.83 231.57,226.08 231.57,226.08 C231.57,226.08 231.49,226.33 231.49,226.33 C231.49,226.33 231.41,226.58 231.41,226.58 C231.41,226.58 231.32,226.83 231.32,226.83 C231.32,226.83 231.24,227.08 231.24,227.08 C231.24,227.08 231.16,227.34 231.16,227.34 C231.16,227.34 231.08,227.59 231.08,227.59 C231.08,227.59 230.99,227.84 230.99,227.84 C230.99,227.84 230.91,228.09 230.91,228.09 C230.91,228.09 230.83,228.34 230.83,228.34 C230.83,228.34 230.75,228.59 230.75,228.59 C230.75,228.59 230.67,228.84 230.67,228.84 C230.67,228.84 230.58,229.09 230.58,229.09 C230.58,229.09 230.5,229.35 230.5,229.35 C230.5,229.35 230.42,229.6 230.42,229.6 C230.42,229.6 230.34,229.85 230.34,229.85 C230.34,229.85 230.25,230.1 230.25,230.1 C230.25,230.1 230.17,230.35 230.17,230.35 C230.17,230.35 230.09,230.6 230.09,230.6 C230.09,230.6 230.01,230.85 230.01,230.85 C230.01,230.85 229.92,231.1 229.92,231.1 C229.92,231.1 229.83,231.35 229.83,231.35 C229.83,231.35 229.73,231.6 229.73,231.6 C229.73,231.6 229.61,231.83 229.61,231.83 C229.61,231.83 229.49,232.07 229.49,232.07 C229.49,232.07 229.36,232.29 229.36,232.29 C229.36,232.29 229.21,232.52 229.21,232.52 C229.21,232.52 229.06,232.73 229.06,232.73 C229.06,232.73 228.89,232.94 228.89,232.94 C228.89,232.94 228.72,233.13 228.72,233.13 C228.72,233.13 228.54,233.32 228.54,233.32 C228.54,233.32 228.34,233.51 228.34,233.51 C228.34,233.51 228.14,233.68 228.14,233.68 C228.14,233.68 227.94,233.84 227.94,233.84 C227.94,233.84 227.72,233.99 227.72,233.99 C227.72,233.99 227.5,234.14 227.5,234.14 C227.5,234.14 227.27,234.27 227.27,234.27 C227.27,234.27 227.04,234.39 227.04,234.39 C227.04,234.39 226.79,234.5 226.79,234.5 C226.79,234.5 226.55,234.6 226.55,234.6 C226.55,234.6 226.3,234.68 226.3,234.68 C226.3,234.68 226.05,234.76 226.05,234.76 C226.05,234.76 225.79,234.82 225.79,234.82 C225.79,234.82 225.53,234.88 225.53,234.88 C225.53,234.88 225.27,234.92 225.27,234.92 C225.27,234.92 225.01,234.95 225.01,234.95 C225.01,234.95 224.74,234.96 224.74,234.96 C224.74,234.96 224.48,234.96 224.48,234.96 C224.48,234.96 224.22,234.96 224.22,234.96 C224.22,234.96 223.95,234.96 223.95,234.96 C223.95,234.96 223.69,234.96 223.69,234.96 C223.69,234.96 223.42,234.96 223.42,234.96 C223.42,234.96 223.16,234.96 223.16,234.96 C223.16,234.96 222.89,234.96 222.89,234.96 C222.89,234.96 222.63,234.96 222.63,234.96 C222.63,234.96 222.37,234.97 222.37,234.97 C222.37,234.97 222.1,234.97 222.1,234.97 C222.1,234.97 221.84,234.97 221.84,234.97 C221.84,234.97 221.57,234.97 221.57,234.97 C221.57,234.97 221.31,234.97 221.31,234.97 C221.31,234.97 221.04,234.97 221.04,234.97 C221.04,234.97 220.78,234.97 220.78,234.97 C220.78,234.97 220.52,234.97 220.52,234.97 C220.52,234.97 220.25,234.97 220.25,234.97 C220.25,234.97 219.99,234.97 219.99,234.97 C219.99,234.97 219.72,234.97 219.72,234.97 C219.72,234.97 219.46,234.97 219.46,234.97 C219.46,234.97 219.19,234.97 219.19,234.97 C219.19,234.97 218.93,234.97 218.93,234.97 C218.93,234.97 218.67,234.97 218.67,234.97 C218.67,234.97 218.4,234.97 218.4,234.97 C218.4,234.97 218.14,234.97 218.14,234.97 C218.14,234.97 217.87,234.97 217.87,234.97 C217.87,234.97 217.61,234.97 217.61,234.97 C217.61,234.97 217.34,234.97 217.34,234.97 C217.34,234.97 217.08,234.97 217.08,234.97 C217.08,234.97 216.82,234.97 216.82,234.97 C216.82,234.97 216.55,234.97 216.55,234.97 C216.55,234.97 216.29,234.97 216.29,234.97 C216.29,234.97 216.02,234.97 216.02,234.97 C216.02,234.97 215.76,234.97 215.76,234.97 C215.76,234.97 215.49,234.97 215.49,234.97 C215.49,234.97 215.23,234.97 215.23,234.97 C215.23,234.97 214.97,234.97 214.97,234.97 C214.97,234.97 214.7,234.97 214.7,234.97 C214.7,234.97 214.44,234.97 214.44,234.97 C214.44,234.97 214.17,234.97 214.17,234.97 C214.17,234.97 213.91,234.97 213.91,234.97 C213.91,234.97 213.64,234.97 213.64,234.97 C213.64,234.97 213.38,234.97 213.38,234.97 C213.38,234.97 213.12,234.97 213.12,234.97 C213.12,234.97 212.85,234.97 212.85,234.97 C212.85,234.97 212.59,234.96 212.59,234.96 C212.59,234.96 212.32,234.96 212.32,234.96 C212.32,234.96 212.06,234.96 212.06,234.96 C212.06,234.96 211.79,234.96 211.79,234.96 C211.79,234.96 211.53,234.96 211.53,234.96 C211.53,234.96 211.27,234.96 211.27,234.96 C211.27,234.96 211,234.96 211,234.96 C211,234.96 210.74,234.96 210.74,234.96 C210.74,234.96 210.47,234.96 210.47,234.96 C210.47,234.96 210.21,234.95 210.21,234.95 C210.21,234.95 209.94,234.93 209.94,234.93 C209.94,234.93 209.68,234.9 209.68,234.9 C209.68,234.9 209.42,234.86 209.42,234.86 C209.42,234.86 209.16,234.8 209.16,234.8 C209.16,234.8 208.91,234.74 208.91,234.74 C208.91,234.74 208.66,234.66 208.66,234.66 C208.66,234.66 208.41,234.56 208.41,234.56 C208.41,234.56 208.17,234.46 208.17,234.46 C208.17,234.46 207.93,234.35 207.93,234.35 C207.93,234.35 207.69,234.22 207.69,234.22 C207.69,234.22 207.47,234.08 207.47,234.08 C207.47,234.08 207.25,233.94 207.25,233.94 C207.25,233.94 207.04,233.78 207.04,233.78 C207.04,233.78 206.83,233.62 206.83,233.62 C206.83,233.62 206.63,233.44 206.63,233.44 C206.63,233.44 206.44,233.26 206.44,233.26 C206.44,233.26 206.27,233.06 206.27,233.06 C206.27,233.06 206.09,232.86 206.09,232.86 C206.09,232.86 205.93,232.65 205.93,232.65 C205.93,232.65 205.78,232.44 205.78,232.44 C205.78,232.44 205.64,232.21 205.64,232.21 C205.64,232.21 205.51,231.98 205.51,231.98 C205.51,231.98 205.39,231.75 205.39,231.75 C205.39,231.75 205.28,231.51 205.28,231.51 C205.28,231.51 205.18,231.26 205.18,231.26 C205.18,231.26 205.09,231.01 205.09,231.01 C205.09,231.01 205.01,230.76 205.01,230.76 C205.01,230.76 204.93,230.51 204.93,230.51 C204.93,230.51 204.85,230.26 204.85,230.26 C204.85,230.26 204.76,230.01 204.76,230.01 C204.76,230.01 204.68,229.76 204.68,229.76 C204.68,229.76 204.6,229.51 204.6,229.51 C204.6,229.51 204.52,229.26 204.52,229.26 C204.52,229.26 204.43,229.01 204.43,229.01 C204.43,229.01 204.35,228.75 204.35,228.75 C204.35,228.75 204.27,228.5 204.27,228.5 C204.27,228.5 204.19,228.25 204.19,228.25 C204.19,228.25 204.1,228 204.1,228 C204.1,228 204.02,227.75 204.02,227.75 C204.02,227.75 203.94,227.5 203.94,227.5 C203.94,227.5 203.86,227.25 203.86,227.25 C203.86,227.25 203.78,227 203.78,227 C203.78,227 203.69,226.74 203.69,226.74 C203.69,226.74 203.61,226.49 203.61,226.49 C203.61,226.49 203.53,226.24 203.53,226.24 C203.53,226.24 203.45,225.99 203.45,225.99 C203.45,225.99 203.36,225.74 203.36,225.74 C203.36,225.74 203.28,225.49 203.28,225.49 C203.28,225.49 203.2,225.24 203.2,225.24 C203.2,225.24 203.12,224.99 203.12,224.99 C203.12,224.99 203.03,224.74 203.03,224.74 C203.03,224.74 202.95,224.48 202.95,224.48 C202.95,224.48 202.87,224.23 202.87,224.23 C202.87,224.23 202.79,223.98 202.79,223.98 C202.79,223.98 202.71,223.73 202.71,223.73 C202.71,223.73 202.63,223.48 202.63,223.48 C202.63,223.48 202.54,223.23 202.54,223.23 C202.54,223.23 202.46,222.98 202.46,222.98 C202.46,222.98 202.38,222.72 202.38,222.72 C202.38,222.72 202.3,222.47 202.3,222.47 C202.3,222.47 202.22,222.22 202.22,222.22 C202.22,222.22 202.14,221.97 202.14,221.97 C202.14,221.97 202.06,221.72 202.06,221.72 C202.06,221.72 201.97,221.47 201.97,221.47 C201.97,221.47 201.89,221.22 201.89,221.22 C201.89,221.22 201.81,220.96 201.81,220.96 C201.81,220.96 201.73,220.71 201.73,220.71 C201.73,220.71 201.65,220.46 201.65,220.46 C201.65,220.46 201.57,220.21 201.57,220.21 C201.57,220.21 201.49,219.96 201.49,219.96 C201.49,219.96 201.4,219.71 201.4,219.71 C201.4,219.71 201.32,219.46 201.32,219.46 C201.32,219.46 201.24,219.2 201.24,219.2 C201.24,219.2 201.16,218.95 201.16,218.95 C201.16,218.95 201.08,218.7 201.08,218.7 C201.08,218.7 201,218.45 201,218.45 C201,218.45 200.92,218.2 200.92,218.2 C200.92,218.2 200.83,217.95 200.83,217.95 C200.83,217.95 200.76,217.7 200.76,217.7 C200.76,217.7 200.69,217.44 200.69,217.44 C200.69,217.44 200.62,217.18 200.62,217.18 C200.62,217.18 200.58,216.92 200.58,216.92 C200.58,216.92 200.54,216.66 200.54,216.66 C200.54,216.66 200.52,216.4 200.52,216.4 C200.52,216.4 200.5,216.14 200.5,216.14 C200.5,216.14 200.5,215.87 200.5,215.87 C200.5,215.87 200.52,215.61 200.52,215.61 C200.52,215.61 200.54,215.34 200.54,215.34 C200.54,215.34 200.58,215.08 200.58,215.08 C200.58,215.08 200.62,214.82 200.62,214.82 C200.62,214.82 200.69,214.57 200.69,214.57 C200.69,214.57 200.76,214.31 200.76,214.31 C200.76,214.31 200.84,214.06 200.84,214.06 C200.84,214.06 200.93,213.81 200.93,213.81 C200.93,213.81 201.05,213.57 201.05,213.57 C201.05,213.57 201.16,213.33 201.16,213.33 C201.16,213.33 201.29,213.11 201.29,213.11 C201.29,213.11 201.43,212.88 201.43,212.88 C201.43,212.88 201.58,212.67 201.58,212.67 C201.58,212.67 201.74,212.45 201.74,212.45 C201.74,212.45 201.91,212.25 201.91,212.25 C201.91,212.25 202.09,212.06 202.09,212.06 C202.09,212.06 202.27,211.87 202.27,211.87 C202.27,211.87 202.47,211.69 202.47,211.69 C202.47,211.69 202.67,211.52 202.67,211.52 C202.67,211.52 202.88,211.36 202.88,211.36 C202.88,211.36 203.1,211.21 203.1,211.21 C203.1,211.21 203.31,211.05 203.31,211.05 C203.31,211.05 203.52,210.9 203.52,210.9 C203.52,210.9 203.74,210.74 203.74,210.74 C203.74,210.74 203.95,210.58 203.95,210.58 C203.95,210.58 204.16,210.43 204.16,210.43 C204.16,210.43 204.38,210.27 204.38,210.27 C204.38,210.27 204.59,210.12 204.59,210.12 C204.59,210.12 204.81,209.96 204.81,209.96 C204.81,209.96 205.02,209.81 205.02,209.81 C205.02,209.81 205.23,209.65 205.23,209.65 C205.23,209.65 205.45,209.5 205.45,209.5 C205.45,209.5 205.66,209.34 205.66,209.34 C205.66,209.34 205.87,209.19 205.87,209.19 C205.87,209.19 206.09,209.03 206.09,209.03 C206.09,209.03 206.3,208.88 206.3,208.88 C206.3,208.88 206.52,208.72 206.52,208.72 C206.52,208.72 206.73,208.57 206.73,208.57 C206.73,208.57 206.94,208.41 206.94,208.41 C206.94,208.41 207.16,208.25 207.16,208.25 C207.16,208.25 207.37,208.1 207.37,208.1 C207.37,208.1 207.58,207.94 207.58,207.94 C207.58,207.94 207.8,207.79 207.8,207.79 C207.8,207.79 208.01,207.63 208.01,207.63 C208.01,207.63 208.23,207.48 208.23,207.48 C208.23,207.48 208.44,207.32 208.44,207.32 C208.44,207.32 208.65,207.17 208.65,207.17 C208.65,207.17 208.87,207.01 208.87,207.01 C208.87,207.01 209.08,206.86 209.08,206.86 C209.08,206.86 209.3,206.7 209.3,206.7 C209.3,206.7 209.51,206.55 209.51,206.55 C209.51,206.55 209.73,206.39 209.73,206.39 C209.73,206.39 209.94,206.24 209.94,206.24 C209.94,206.24 210.15,206.08 210.15,206.08 C210.15,206.08 210.37,205.93 210.37,205.93 C210.37,205.93 210.58,205.77 210.58,205.77 C210.58,205.77 210.8,205.62 210.8,205.62 C210.8,205.62 211.01,205.46 211.01,205.46 C211.01,205.46 211.23,205.31 211.23,205.31 C211.23,205.31 211.44,205.16 211.44,205.16 C211.44,205.16 211.65,205 211.65,205 C211.65,205 211.87,204.85 211.87,204.85 C211.87,204.85 212.08,204.69 212.08,204.69 C212.08,204.69 212.3,204.54 212.3,204.54 C212.3,204.54 212.51,204.38 212.51,204.38 C212.51,204.38 212.73,204.23 212.73,204.23 C212.73,204.23 212.94,204.07 212.94,204.07 C212.94,204.07 213.15,203.92 213.15,203.92 C213.15,203.92 213.37,203.76 213.37,203.76 C213.37,203.76 213.58,203.61 213.58,203.61 C213.58,203.61 213.8,203.45 213.8,203.45 C213.8,203.45 214.01,203.3 214.01,203.3 C214.01,203.3 214.23,203.14 214.23,203.14 C214.23,203.14 214.45,203 214.45,203 C214.45,203 214.67,202.86 214.67,202.86 C214.67,202.86 214.9,202.73 214.9,202.73 C214.9,202.73 215.14,202.61 215.14,202.61 C215.14,202.61 215.38,202.51 215.38,202.51 C215.38,202.51 215.63,202.41 215.63,202.41 C215.63,202.41 215.88,202.33 215.88,202.33 C215.88,202.33 216.13,202.26 216.13,202.26 C216.13,202.26 216.39,202.2 216.39,202.2 C216.39,202.2 216.65,202.15 216.65,202.15 C216.65,202.15 216.91,202.11 216.91,202.11 C216.91,202.11 217.18,202.09 217.18,202.09 C217.18,202.09 217.44,202.08 217.44,202.08 C217.44,202.08 217.7,202.08 217.7,202.08c " android:valueTo="M217.68 210.56 C217.68,210.56 217.81,210.57 217.81,210.57 C217.81,210.57 217.93,210.57 217.93,210.57 C217.93,210.57 218.06,210.58 218.06,210.58 C218.06,210.58 218.18,210.59 218.18,210.59 C218.18,210.59 218.31,210.59 218.31,210.59 C218.31,210.59 218.43,210.61 218.43,210.61 C218.43,210.61 218.56,210.63 218.56,210.63 C218.56,210.63 218.68,210.64 218.68,210.64 C218.68,210.64 218.81,210.66 218.81,210.66 C218.81,210.66 218.93,210.68 218.93,210.68 C218.93,210.68 219.05,210.7 219.05,210.7 C219.05,210.7 219.18,210.72 219.18,210.72 C219.18,210.72 219.3,210.75 219.3,210.75 C219.3,210.75 219.42,210.78 219.42,210.78 C219.42,210.78 219.54,210.81 219.54,210.81 C219.54,210.81 219.66,210.84 219.66,210.84 C219.66,210.84 219.79,210.87 219.79,210.87 C219.79,210.87 219.91,210.91 219.91,210.91 C219.91,210.91 220.03,210.95 220.03,210.95 C220.03,210.95 220.14,210.99 220.14,210.99 C220.14,210.99 220.26,211.04 220.26,211.04 C220.26,211.04 220.38,211.08 220.38,211.08 C220.38,211.08 220.5,211.12 220.5,211.12 C220.5,211.12 220.62,211.17 220.62,211.17 C220.62,211.17 220.73,211.22 220.73,211.22 C220.73,211.22 220.84,211.27 220.84,211.27 C220.84,211.27 220.96,211.32 220.96,211.32 C220.96,211.32 221.07,211.38 221.07,211.38 C221.07,211.38 221.19,211.43 221.19,211.43 C221.19,211.43 221.3,211.49 221.3,211.49 C221.3,211.49 221.41,211.55 221.41,211.55 C221.41,211.55 221.51,211.61 221.51,211.61 C221.51,211.61 221.62,211.68 221.62,211.68 C221.62,211.68 221.73,211.74 221.73,211.74 C221.73,211.74 221.84,211.8 221.84,211.8 C221.84,211.8 221.94,211.87 221.94,211.87 C221.94,211.87 222.05,211.94 222.05,211.94 C222.05,211.94 222.15,212.02 222.15,212.02 C222.15,212.02 222.25,212.09 222.25,212.09 C222.25,212.09 222.35,212.16 222.35,212.16 C222.35,212.16 222.46,212.23 222.46,212.23 C222.46,212.23 222.55,212.31 222.55,212.31 C222.55,212.31 222.65,212.4 222.65,212.4 C222.65,212.4 222.74,212.48 222.74,212.48 C222.74,212.48 222.84,212.56 222.84,212.56 C222.84,212.56 222.93,212.64 222.93,212.64 C222.93,212.64 223.03,212.72 223.03,212.72 C223.03,212.72 223.12,212.81 223.12,212.81 C223.12,212.81 223.21,212.9 223.21,212.9 C223.21,212.9 223.29,212.99 223.29,212.99 C223.29,212.99 223.38,213.08 223.38,213.08 C223.38,213.08 223.47,213.17 223.47,213.17 C223.47,213.17 223.55,213.26 223.55,213.26 C223.55,213.26 223.63,213.36 223.63,213.36 C223.63,213.36 223.71,213.46 223.71,213.46 C223.71,213.46 223.79,213.56 223.79,213.56 C223.79,213.56 223.87,213.66 223.87,213.66 C223.87,213.66 223.95,213.75 223.95,213.75 C223.95,213.75 224.03,213.85 224.03,213.85 C224.03,213.85 224.09,213.96 224.09,213.96 C224.09,213.96 224.16,214.06 224.16,214.06 C224.16,214.06 224.23,214.17 224.23,214.17 C224.23,214.17 224.3,214.27 224.3,214.27 C224.3,214.27 224.37,214.38 224.37,214.38 C224.37,214.38 224.44,214.48 224.44,214.48 C224.44,214.48 224.5,214.59 224.5,214.59 C224.5,214.59 224.56,214.7 224.56,214.7 C224.56,214.7 224.62,214.81 224.62,214.81 C224.62,214.81 224.68,214.93 224.68,214.93 C224.68,214.93 224.74,215.04 224.74,215.04 C224.74,215.04 224.79,215.15 224.79,215.15 C224.79,215.15 224.84,215.26 224.84,215.26 C224.84,215.26 224.89,215.38 224.89,215.38 C224.89,215.38 224.94,215.5 224.94,215.5 C224.94,215.5 224.99,215.61 224.99,215.61 C224.99,215.61 225.04,215.73 225.04,215.73 C225.04,215.73 225.08,215.84 225.08,215.84 C225.08,215.84 225.12,215.96 225.12,215.96 C225.12,215.96 225.16,216.08 225.16,216.08 C225.16,216.08 225.19,216.2 225.19,216.2 C225.19,216.2 225.23,216.32 225.23,216.32 C225.23,216.32 225.27,216.44 225.27,216.44 C225.27,216.44 225.3,216.56 225.3,216.56 C225.3,216.56 225.33,216.69 225.33,216.69 C225.33,216.69 225.35,216.81 225.35,216.81 C225.35,216.81 225.38,216.93 225.38,216.93 C225.38,216.93 225.41,217.06 225.41,217.06 C225.41,217.06 225.43,217.18 225.43,217.18 C225.43,217.18 225.46,217.3 225.46,217.3 C225.46,217.3 225.47,217.43 225.47,217.43 C225.47,217.43 225.49,217.55 225.49,217.55 C225.49,217.55 225.5,217.68 225.5,217.68 C225.5,217.68 225.52,217.8 225.52,217.8 C225.52,217.8 225.52,217.93 225.52,217.93 C225.52,217.93 225.53,218.05 225.53,218.05 C225.53,218.05 225.54,218.18 225.54,218.18 C225.54,218.18 225.54,218.3 225.54,218.3 C225.54,218.3 225.55,218.43 225.55,218.43 C225.55,218.43 225.55,218.55 225.55,218.55 C225.55,218.55 225.55,218.68 225.55,218.68 C225.55,218.68 225.54,218.8 225.54,218.8 C225.54,218.8 225.54,218.93 225.54,218.93 C225.54,218.93 225.53,219.05 225.53,219.05 C225.53,219.05 225.52,219.18 225.52,219.18 C225.52,219.18 225.52,219.31 225.52,219.31 C225.52,219.31 225.5,219.43 225.5,219.43 C225.5,219.43 225.48,219.55 225.48,219.55 C225.48,219.55 225.47,219.68 225.47,219.68 C225.47,219.68 225.45,219.8 225.45,219.8 C225.45,219.8 225.43,219.93 225.43,219.93 C225.43,219.93 225.41,220.05 225.41,220.05 C225.41,220.05 225.39,220.17 225.39,220.17 C225.39,220.17 225.36,220.3 225.36,220.3 C225.36,220.3 225.33,220.42 225.33,220.42 C225.33,220.42 225.3,220.54 225.3,220.54 C225.3,220.54 225.27,220.66 225.27,220.66 C225.27,220.66 225.24,220.78 225.24,220.78 C225.24,220.78 225.2,220.9 225.2,220.9 C225.2,220.9 225.16,221.02 225.16,221.02 C225.16,221.02 225.12,221.14 225.12,221.14 C225.12,221.14 225.08,221.26 225.08,221.26 C225.08,221.26 225.03,221.38 225.03,221.38 C225.03,221.38 224.99,221.5 224.99,221.5 C224.99,221.5 224.95,221.61 224.95,221.61 C224.95,221.61 224.89,221.73 224.89,221.73 C224.89,221.73 224.84,221.84 224.84,221.84 C224.84,221.84 224.79,221.96 224.79,221.96 C224.79,221.96 224.73,222.07 224.73,222.07 C224.73,222.07 224.68,222.18 224.68,222.18 C224.68,222.18 224.62,222.29 224.62,222.29 C224.62,222.29 224.56,222.4 224.56,222.4 C224.56,222.4 224.5,222.51 224.5,222.51 C224.5,222.51 224.44,222.62 224.44,222.62 C224.44,222.62 224.37,222.73 224.37,222.73 C224.37,222.73 224.31,222.84 224.31,222.84 C224.31,222.84 224.24,222.94 224.24,222.94 C224.24,222.94 224.17,223.05 224.17,223.05 C224.17,223.05 224.09,223.15 224.09,223.15 C224.09,223.15 224.02,223.25 224.02,223.25 C224.02,223.25 223.95,223.35 223.95,223.35 C223.95,223.35 223.88,223.45 223.88,223.45 C223.88,223.45 223.8,223.55 223.8,223.55 C223.8,223.55 223.71,223.65 223.71,223.65 C223.71,223.65 223.63,223.74 223.63,223.74 C223.63,223.74 223.55,223.84 223.55,223.84 C223.55,223.84 223.47,223.93 223.47,223.93 C223.47,223.93 223.39,224.03 223.39,224.03 C223.39,224.03 223.3,224.12 223.3,224.12 C223.3,224.12 223.21,224.2 223.21,224.2 C223.21,224.2 223.12,224.29 223.12,224.29 C223.12,224.29 223.03,224.38 223.03,224.38 C223.03,224.38 222.94,224.46 222.94,224.46 C222.94,224.46 222.85,224.55 222.85,224.55 C222.85,224.55 222.75,224.63 222.75,224.63 C222.75,224.63 222.65,224.71 222.65,224.71 C222.65,224.71 222.55,224.79 222.55,224.79 C222.55,224.79 222.46,224.87 222.46,224.87 C222.46,224.87 222.36,224.95 222.36,224.95 C222.36,224.95 222.26,225.02 222.26,225.02 C222.26,225.02 222.15,225.09 222.15,225.09 C222.15,225.09 222.05,225.16 222.05,225.16 C222.05,225.16 221.94,225.23 221.94,225.23 C221.94,225.23 221.84,225.3 221.84,225.3 C221.84,225.3 221.74,225.37 221.74,225.37 C221.74,225.37 221.63,225.44 221.63,225.44 C221.63,225.44 221.52,225.5 221.52,225.5 C221.52,225.5 221.41,225.56 221.41,225.56 C221.41,225.56 221.3,225.62 221.3,225.62 C221.3,225.62 221.19,225.68 221.19,225.68 C221.19,225.68 221.08,225.73 221.08,225.73 C221.08,225.73 220.96,225.79 220.96,225.79 C220.96,225.79 220.85,225.84 220.85,225.84 C220.85,225.84 220.73,225.89 220.73,225.89 C220.73,225.89 220.62,225.94 220.62,225.94 C220.62,225.94 220.5,225.99 220.5,225.99 C220.5,225.99 220.38,226.03 220.38,226.03 C220.38,226.03 220.27,226.08 220.27,226.08 C220.27,226.08 220.15,226.12 220.15,226.12 C220.15,226.12 220.03,226.15 220.03,226.15 C220.03,226.15 219.91,226.19 219.91,226.19 C219.91,226.19 219.79,226.23 219.79,226.23 C219.79,226.23 219.67,226.27 219.67,226.27 C219.67,226.27 219.55,226.3 219.55,226.3 C219.55,226.3 219.42,226.33 219.42,226.33 C219.42,226.33 219.3,226.35 219.3,226.35 C219.3,226.35 219.18,226.38 219.18,226.38 C219.18,226.38 219.06,226.4 219.06,226.4 C219.06,226.4 218.93,226.43 218.93,226.43 C218.93,226.43 218.81,226.45 218.81,226.45 C218.81,226.45 218.68,226.47 218.68,226.47 C218.68,226.47 218.56,226.49 218.56,226.49 C218.56,226.49 218.44,226.5 218.44,226.5 C218.44,226.5 218.31,226.52 218.31,226.52 C218.31,226.52 218.19,226.52 218.19,226.52 C218.19,226.52 218.06,226.53 218.06,226.53 C218.06,226.53 217.93,226.53 217.93,226.53 C217.93,226.53 217.81,226.54 217.81,226.54 C217.81,226.54 217.68,226.55 217.68,226.55 C217.68,226.55 217.56,226.55 217.56,226.55 C217.56,226.55 217.43,226.55 217.43,226.55 C217.43,226.55 217.31,226.54 217.31,226.54 C217.31,226.54 217.18,226.53 217.18,226.53 C217.18,226.53 217.05,226.53 217.05,226.53 C217.05,226.53 216.93,226.52 216.93,226.52 C216.93,226.52 216.8,226.52 216.8,226.52 C216.8,226.52 216.68,226.5 216.68,226.5 C216.68,226.5 216.55,226.48 216.55,226.48 C216.55,226.48 216.43,226.46 216.43,226.46 C216.43,226.46 216.31,226.45 216.31,226.45 C216.31,226.45 216.18,226.43 216.18,226.43 C216.18,226.43 216.06,226.41 216.06,226.41 C216.06,226.41 215.93,226.38 215.93,226.38 C215.93,226.38 215.81,226.35 215.81,226.35 C215.81,226.35 215.69,226.32 215.69,226.32 C215.69,226.32 215.57,226.29 215.57,226.29 C215.57,226.29 215.45,226.26 215.45,226.26 C215.45,226.26 215.32,226.23 215.32,226.23 C215.32,226.23 215.2,226.2 215.2,226.2 C215.2,226.2 215.09,226.16 215.09,226.16 C215.09,226.16 214.97,226.12 214.97,226.12 C214.97,226.12 214.85,226.07 214.85,226.07 C214.85,226.07 214.73,226.03 214.73,226.03 C214.73,226.03 214.61,225.99 214.61,225.99 C214.61,225.99 214.5,225.94 214.5,225.94 C214.5,225.94 214.38,225.89 214.38,225.89 C214.38,225.89 214.27,225.84 214.27,225.84 C214.27,225.84 214.15,225.79 214.15,225.79 C214.15,225.79 214.04,225.73 214.04,225.73 C214.04,225.73 213.93,225.68 213.93,225.68 C213.93,225.68 213.81,225.62 213.81,225.62 C213.81,225.62 213.71,225.56 213.71,225.56 C213.71,225.56 213.6,225.5 213.6,225.5 C213.6,225.5 213.49,225.43 213.49,225.43 C213.49,225.43 213.38,225.37 213.38,225.37 C213.38,225.37 213.27,225.31 213.27,225.31 C213.27,225.31 213.17,225.24 213.17,225.24 C213.17,225.24 213.06,225.16 213.06,225.16 C213.06,225.16 212.96,225.09 212.96,225.09 C212.96,225.09 212.86,225.02 212.86,225.02 C212.86,225.02 212.76,224.95 212.76,224.95 C212.76,224.95 212.65,224.87 212.65,224.87 C212.65,224.87 212.56,224.79 212.56,224.79 C212.56,224.79 212.46,224.71 212.46,224.71 C212.46,224.71 212.37,224.63 212.37,224.63 C212.37,224.63 212.27,224.55 212.27,224.55 C212.27,224.55 212.18,224.47 212.18,224.47 C212.18,224.47 212.08,224.38 212.08,224.38 C212.08,224.38 211.99,224.3 211.99,224.3 C211.99,224.3 211.91,224.2 211.91,224.2 C211.91,224.2 211.82,224.11 211.82,224.11 C211.82,224.11 211.73,224.02 211.73,224.02 C211.73,224.02 211.64,223.93 211.64,223.93 C211.64,223.93 211.56,223.84 211.56,223.84 C211.56,223.84 211.48,223.75 211.48,223.75 C211.48,223.75 211.4,223.65 211.4,223.65 C211.4,223.65 211.32,223.55 211.32,223.55 C211.32,223.55 211.24,223.45 211.24,223.45 C211.24,223.45 211.16,223.35 211.16,223.35 C211.16,223.35 211.09,223.26 211.09,223.26 C211.09,223.26 211.02,223.15 211.02,223.15 C211.02,223.15 210.95,223.05 210.95,223.05 C210.95,223.05 210.88,222.94 210.88,222.94 C210.88,222.94 210.81,222.84 210.81,222.84 C210.81,222.84 210.74,222.73 210.74,222.73 C210.74,222.73 210.67,222.63 210.67,222.63 C210.67,222.63 210.61,222.52 210.61,222.52 C210.61,222.52 210.55,222.4 210.55,222.4 C210.55,222.4 210.49,222.29 210.49,222.29 C210.49,222.29 210.43,222.18 210.43,222.18 C210.43,222.18 210.38,222.07 210.38,222.07 C210.38,222.07 210.32,221.96 210.32,221.96 C210.32,221.96 210.27,221.84 210.27,221.84 C210.27,221.84 210.22,221.73 210.22,221.73 C210.22,221.73 210.17,221.61 210.17,221.61 C210.17,221.61 210.12,221.5 210.12,221.5 C210.12,221.5 210.08,221.38 210.08,221.38 C210.08,221.38 210.03,221.26 210.03,221.26 C210.03,221.26 209.99,221.14 209.99,221.14 C209.99,221.14 209.96,221.02 209.96,221.02 C209.96,221.02 209.92,220.9 209.92,220.9 C209.92,220.9 209.88,220.78 209.88,220.78 C209.88,220.78 209.84,220.67 209.84,220.67 C209.84,220.67 209.81,220.54 209.81,220.54 C209.81,220.54 209.78,220.42 209.78,220.42 C209.78,220.42 209.76,220.3 209.76,220.3 C209.76,220.3 209.73,220.18 209.73,220.18 C209.73,220.18 209.71,220.05 209.71,220.05 C209.71,220.05 209.68,219.93 209.68,219.93 C209.68,219.93 209.66,219.81 209.66,219.81 C209.66,219.81 209.64,219.68 209.64,219.68 C209.64,219.68 209.62,219.56 209.62,219.56 C209.62,219.56 209.61,219.43 209.61,219.43 C209.61,219.43 209.59,219.31 209.59,219.31 C209.59,219.31 209.59,219.18 209.59,219.18 C209.59,219.18 209.58,219.06 209.58,219.06 C209.58,219.06 209.58,218.93 209.58,218.93 C209.58,218.93 209.57,218.81 209.57,218.81 C209.57,218.81 209.56,218.68 209.56,218.68 C209.56,218.68 209.56,218.56 209.56,218.56 C209.56,218.56 209.56,218.43 209.56,218.43 C209.56,218.43 209.57,218.3 209.57,218.3 C209.57,218.3 209.58,218.18 209.58,218.18 C209.58,218.18 209.58,218.05 209.58,218.05 C209.58,218.05 209.59,217.93 209.59,217.93 C209.59,217.93 209.59,217.8 209.59,217.8 C209.59,217.8 209.61,217.68 209.61,217.68 C209.61,217.68 209.63,217.55 209.63,217.55 C209.63,217.55 209.65,217.43 209.65,217.43 C209.65,217.43 209.66,217.31 209.66,217.31 C209.66,217.31 209.68,217.18 209.68,217.18 C209.68,217.18 209.7,217.06 209.7,217.06 C209.7,217.06 209.73,216.93 209.73,216.93 C209.73,216.93 209.76,216.81 209.76,216.81 C209.76,216.81 209.79,216.69 209.79,216.69 C209.79,216.69 209.82,216.57 209.82,216.57 C209.82,216.57 209.85,216.45 209.85,216.45 C209.85,216.45 209.88,216.32 209.88,216.32 C209.88,216.32 209.91,216.2 209.91,216.2 C209.91,216.2 209.95,216.08 209.95,216.08 C209.95,216.08 210,215.97 210,215.97 C210,215.97 210.04,215.85 210.04,215.85 C210.04,215.85 210.08,215.73 210.08,215.73 C210.08,215.73 210.12,215.61 210.12,215.61 C210.12,215.61 210.17,215.49 210.17,215.49 C210.17,215.49 210.22,215.38 210.22,215.38 C210.22,215.38 210.27,215.27 210.27,215.27 C210.27,215.27 210.33,215.15 210.33,215.15 C210.33,215.15 210.38,215.04 210.38,215.04 C210.38,215.04 210.43,214.92 210.43,214.92 C210.43,214.92 210.49,214.81 210.49,214.81 C210.49,214.81 210.55,214.7 210.55,214.7 C210.55,214.7 210.61,214.6 210.61,214.6 C210.61,214.6 210.68,214.49 210.68,214.49 C210.68,214.49 210.74,214.38 210.74,214.38 C210.74,214.38 210.8,214.27 210.8,214.27 C210.8,214.27 210.87,214.17 210.87,214.17 C210.87,214.17 210.95,214.06 210.95,214.06 C210.95,214.06 211.02,213.96 211.02,213.96 C211.02,213.96 211.09,213.86 211.09,213.86 C211.09,213.86 211.16,213.76 211.16,213.76 C211.16,213.76 211.24,213.65 211.24,213.65 C211.24,213.65 211.32,213.56 211.32,213.56 C211.32,213.56 211.4,213.46 211.4,213.46 C211.4,213.46 211.48,213.37 211.48,213.37 C211.48,213.37 211.56,213.27 211.56,213.27 C211.56,213.27 211.64,213.18 211.64,213.18 C211.64,213.18 211.73,213.08 211.73,213.08 C211.73,213.08 211.82,212.99 211.82,212.99 C211.82,212.99 211.91,212.9 211.91,212.9 C211.91,212.9 212,212.82 212,212.82 C212,212.82 212.09,212.73 212.09,212.73 C212.09,212.73 212.18,212.64 212.18,212.64 C212.18,212.64 212.27,212.56 212.27,212.56 C212.27,212.56 212.36,212.48 212.36,212.48 C212.36,212.48 212.46,212.4 212.46,212.4 C212.46,212.4 212.56,212.32 212.56,212.32 C212.56,212.32 212.66,212.24 212.66,212.24 C212.66,212.24 212.76,212.16 212.76,212.16 C212.76,212.16 212.85,212.08 212.85,212.08 C212.85,212.08 212.96,212.02 212.96,212.02 C212.96,212.02 213.06,211.95 213.06,211.95 C213.06,211.95 213.17,211.88 213.17,211.88 C213.17,211.88 213.27,211.81 213.27,211.81 C213.27,211.81 213.38,211.74 213.38,211.74 C213.38,211.74 213.48,211.67 213.48,211.67 C213.48,211.67 213.6,211.61 213.6,211.61 C213.6,211.61 213.71,211.55 213.71,211.55 C213.71,211.55 213.82,211.49 213.82,211.49 C213.82,211.49 213.93,211.43 213.93,211.43 C213.93,211.43 214.04,211.37 214.04,211.37 C214.04,211.37 214.15,211.32 214.15,211.32 C214.15,211.32 214.27,211.27 214.27,211.27 C214.27,211.27 214.38,211.22 214.38,211.22 C214.38,211.22 214.5,211.17 214.5,211.17 C214.5,211.17 214.61,211.12 214.61,211.12 C214.61,211.12 214.73,211.07 214.73,211.07 C214.73,211.07 214.85,211.03 214.85,211.03 C214.85,211.03 214.97,210.99 214.97,210.99 C214.97,210.99 215.09,210.95 215.09,210.95 C215.09,210.95 215.21,210.92 215.21,210.92 C215.21,210.92 215.33,210.88 215.33,210.88 C215.33,210.88 215.45,210.84 215.45,210.84 C215.45,210.84 215.57,210.81 215.57,210.81 C215.57,210.81 215.69,210.78 215.69,210.78 C215.69,210.78 215.81,210.76 215.81,210.76 C215.81,210.76 215.93,210.73 215.93,210.73 C215.93,210.73 216.06,210.7 216.06,210.7 C216.06,210.7 216.18,210.68 216.18,210.68 C216.18,210.68 216.3,210.65 216.3,210.65 C216.3,210.65 216.43,210.64 216.43,210.64 C216.43,210.64 216.55,210.62 216.55,210.62 C216.55,210.62 216.68,210.61 216.68,210.61 C216.68,210.61 216.8,210.59 216.8,210.59 C216.8,210.59 216.93,210.59 216.93,210.59 C216.93,210.59 217.05,210.58 217.05,210.58 C217.05,210.58 217.18,210.58 217.18,210.58 C217.18,210.58 217.3,210.57 217.3,210.57 C217.3,210.57 217.43,210.56 217.43,210.56 C217.43,210.56 217.56,210.56 217.56,210.56 C217.56,210.56 217.68,210.56 217.68,210.56c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.3,0 0.8,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="500" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector> \ No newline at end of file
+<animated-vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vector android:height="30dp" android:width="30dp" android:viewportHeight="30" android:viewportWidth="30"><group android:name="_R_G"><group android:name="_R_G_L_1_G" android:translateX="15.397" android:translateY="15.691" android:scaleY="0"><path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-0.46 -13.65 C3.05,-13.65 12.63,-6.57 12.9,-3.63 C12.98,-2.7 12.65,12.85 -0.46,12.85 C-13.57,12.85 -13.77,-2.84 -13.76,-3.63 C-13.72,-6.87 -3.96,-13.65 -0.46,-13.65c "/></group><group android:name="_R_G_L_0_G" android:translateX="15" android:translateY="15.859" android:pivotY="-0.859" android:scaleX="0" android:scaleY="0"><path android:name="_R_G_L_0_G_D_0_P_0" android:fillColor="#ffffff" android:fillAlpha="1" android:fillType="nonZero" android:pathData=" M-2.82 -14.07 C-1.14,-15.29 1.14,-15.29 2.82,-14.07 C2.82,-14.07 7.73,-10.53 7.73,-10.53 C7.73,-10.53 12.58,-7 12.58,-7 C14.29,-5.76 15,-3.55 14.35,-1.54 C14.35,-1.54 12.51,4.14 12.51,4.14 C12.51,4.14 10.64,9.85 10.64,9.85 C9.99,11.84 8.14,13.19 6.05,13.19 C6.05,13.19 0,13.2 0,13.2 C0,13.2 -6.05,13.19 -6.05,13.19 C-8.14,13.19 -9.98,11.84 -10.64,9.85 C-10.64,9.85 -12.51,4.14 -12.51,4.14 C-12.51,4.14 -14.35,-1.54 -14.35,-1.54 C-15,-3.55 -14.29,-5.76 -12.58,-7 C-12.58,-7 -7.73,-10.53 -7.73,-10.53 C-7.73,-10.53 -2.82,-14.07 -2.82,-14.07c "/></group></group><group android:name="time_group"/></vector></aapt:attr><target android:name="_R_G_L_1_G_D_0_P_0"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="pathData" android:duration="67" android:startOffset="0" android:valueFrom="M-0.46 -13.65 C3.05,-13.65 12.63,-6.57 12.9,-3.63 C12.98,-2.7 12.65,12.85 -0.46,12.85 C-13.57,12.85 -13.77,-2.84 -13.76,-3.63 C-13.72,-6.87 -3.96,-13.65 -0.46,-13.65c " android:valueTo="M-0.46 -13.65 C3.05,-13.65 12.63,-6.57 12.9,-3.63 C12.98,-2.7 12.65,12.85 -0.46,12.85 C-13.57,12.85 -13.77,-2.84 -13.76,-3.63 C-13.72,-6.87 -3.96,-13.65 -0.46,-13.65c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0 0.8,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="pathData" android:duration="283" android:startOffset="67" android:valueFrom="M-0.46 -13.65 C3.05,-13.65 12.63,-6.57 12.9,-3.63 C12.98,-2.7 12.65,12.85 -0.46,12.85 C-13.57,12.85 -13.77,-2.84 -13.76,-3.63 C-13.72,-6.87 -3.96,-13.65 -0.46,-13.65c " android:valueTo="M-0.44 -8.69 C3.98,-8.69 7.56,-5.11 7.56,-0.69 C7.56,3.73 3.98,7.31 -0.44,7.31 C-4.86,7.31 -8.44,3.73 -8.44,-0.69 C-8.44,-5.11 -4.86,-8.69 -0.44,-8.69c " android:valueType="pathType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0 0.8,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_1_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="67" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target><target android:name="_R_G_L_0_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleX" android:duration="67" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="67" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleX" android:duration="283" android:startOffset="67" android:valueFrom="1" android:valueTo="0.35000000000000003" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.7,0 0.6,1 1.0,1.0"/></aapt:attr></objectAnimator><objectAnimator android:propertyName="scaleY" android:duration="283" android:startOffset="67" android:valueFrom="1" android:valueTo="0.35000000000000003" android:valueType="floatType"><aapt:attr name="android:interpolator"><pathInterpolator android:pathData="M 0.0,0.0 c0.7,0 0.6,1 1.0,1.0"/></aapt:attr></objectAnimator></set></aapt:attr></target><target android:name="_R_G_L_0_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target><target android:name="_R_G_L_0_G"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="scaleY" android:duration="0" android:startOffset="367" android:valueFrom="1" android:valueTo="0" android:valueType="floatType"/></set></aapt:attr></target><target android:name="time_group"><aapt:attr name="android:animation"><set android:ordering="together"><objectAnimator android:propertyName="translateX" android:duration="500" android:startOffset="0" android:valueFrom="0" android:valueTo="1" android:valueType="floatType"/></set></aapt:attr></target></animated-vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 754433bc0994..3ebaae0ca99d 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -481,6 +481,8 @@
<string name="accessibility_desc_notification_shade">Notification shade.</string>
<!-- Content description for the quick settings panel (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_desc_quick_settings">Quick settings.</string>
+ <!-- Content description for the split notification shade that also includes QS (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_desc_qs_notification_shade">Quick settings and Notification shade.</string>
<!-- Content description for the lock screen (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_desc_lock_screen">Lock screen.</string>
<!-- Content description for the work profile lock screen. This prevents work profile apps from being used, but personal apps can be used as normal (not shown on the screen). [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt b/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
index c9a25b067b94..b6aae69ebad6 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
+++ b/packages/SystemUI/shared/src/com/android/systemui/flags/Flag.kt
@@ -145,7 +145,7 @@ data class SysPropBooleanFlag constructor(
override val namespace: String,
override val default: Boolean = false,
) : SysPropFlag<Boolean> {
- // TODO(b/223379190): Teamfood not supported for sysprop flags yet.
+ // TODO(b/268520433): Teamfood not supported for sysprop flags yet.
override val teamfood: Boolean = false
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
index e1e806319ba0..90f44a75b005 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteAnimationTargetCompat.java
@@ -36,7 +36,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
-import android.app.TaskInfo;
import android.app.WindowConfiguration;
import android.graphics.Rect;
import android.util.ArrayMap;
@@ -48,7 +47,7 @@ import android.window.TransitionInfo;
import android.window.TransitionInfo.Change;
import java.util.ArrayList;
-import java.util.function.BiPredicate;
+import java.util.function.Predicate;
/**
* Some utility methods for creating {@link RemoteAnimationTarget} instances.
@@ -145,6 +144,18 @@ public class RemoteAnimationTargetCompat {
public static RemoteAnimationTarget newTarget(TransitionInfo.Change change, int order,
TransitionInfo info, SurfaceControl.Transaction t,
@Nullable ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
+ final SurfaceControl leash = createLeash(info, change, order, t);
+ if (leashMap != null) {
+ leashMap.put(change.getLeash(), leash);
+ }
+ return newTarget(change, order, leash);
+ }
+
+ /**
+ * Creates a new RemoteAnimationTarget from the provided change and leash
+ */
+ public static RemoteAnimationTarget newTarget(TransitionInfo.Change change, int order,
+ SurfaceControl leash) {
int taskId;
boolean isNotInRecents;
ActivityManager.RunningTaskInfo taskInfo;
@@ -169,7 +180,7 @@ public class RemoteAnimationTargetCompat {
newModeToLegacyMode(change.getMode()),
// TODO: once we can properly sync transactions across process,
// then get rid of this leash.
- createLeash(info, change, order, t),
+ leash,
(change.getFlags() & TransitionInfo.FLAG_TRANSLUCENT) != 0,
null,
// TODO(shell-transitions): we need to send content insets? evaluate how its used.
@@ -190,9 +201,6 @@ public class RemoteAnimationTargetCompat {
target.setWillShowImeOnTarget(
(change.getFlags() & TransitionInfo.FLAG_WILL_IME_SHOWN) != 0);
target.setRotationChange(change.getEndRotation() - change.getStartRotation());
- if (leashMap != null) {
- leashMap.put(change.getLeash(), target.leash);
- }
return target;
}
@@ -204,18 +212,7 @@ public class RemoteAnimationTargetCompat {
*/
public static RemoteAnimationTarget[] wrapApps(TransitionInfo info,
SurfaceControl.Transaction t, ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
- SparseBooleanArray childTaskTargets = new SparseBooleanArray();
- return wrap(info, t, leashMap, (change, taskInfo) -> {
- // Children always come before parent since changes are in top-to-bottom z-order.
- if ((taskInfo == null) || childTaskTargets.get(taskInfo.taskId)) {
- // has children, so not a leaf. Skip.
- return false;
- }
- if (taskInfo.hasParentTask()) {
- childTaskTargets.put(taskInfo.parentTaskId, true);
- }
- return true;
- });
+ return wrap(info, t, leashMap, new LeafTaskFilter());
}
/**
@@ -228,21 +225,56 @@ public class RemoteAnimationTargetCompat {
*/
public static RemoteAnimationTarget[] wrapNonApps(TransitionInfo info, boolean wallpapers,
SurfaceControl.Transaction t, ArrayMap<SurfaceControl, SurfaceControl> leashMap) {
- return wrap(info, t, leashMap, (change, taskInfo) -> (taskInfo == null)
- && wallpapers == change.hasFlags(FLAG_IS_WALLPAPER)
- && !change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY));
+ return wrap(info, t, leashMap, (change) ->
+ (wallpapers ? isWallpaper(change) : isNonApp(change)));
}
private static RemoteAnimationTarget[] wrap(TransitionInfo info,
SurfaceControl.Transaction t, ArrayMap<SurfaceControl, SurfaceControl> leashMap,
- BiPredicate<Change, TaskInfo> filter) {
+ Predicate<Change> filter) {
final ArrayList<RemoteAnimationTarget> out = new ArrayList<>();
for (int i = 0; i < info.getChanges().size(); i++) {
TransitionInfo.Change change = info.getChanges().get(i);
- if (filter.test(change, change.getTaskInfo())) {
+ if (filter.test(change)) {
out.add(newTarget(change, info.getChanges().size() - i, info, t, leashMap));
}
}
return out.toArray(new RemoteAnimationTarget[out.size()]);
}
+
+ /** Returns `true` if `change` is a wallpaper. */
+ public static boolean isWallpaper(Change change) {
+ return (change.getTaskInfo() == null)
+ && change.hasFlags(FLAG_IS_WALLPAPER)
+ && !change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY);
+ }
+
+ /** Returns `true` if `change` is not an app window or wallpaper. */
+ public static boolean isNonApp(Change change) {
+ return (change.getTaskInfo() == null)
+ && !change.hasFlags(FLAG_IS_WALLPAPER)
+ && !change.hasFlags(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY);
+ }
+
+ /**
+ * Filter that selects leaf-tasks only. THIS IS ORDER-DEPENDENT! For it to work properly, you
+ * MUST call `test` in the same order that the changes appear in the TransitionInfo.
+ */
+ public static class LeafTaskFilter implements Predicate<Change> {
+ private final SparseBooleanArray mChildTaskTargets = new SparseBooleanArray();
+
+ @Override
+ public boolean test(Change change) {
+ final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
+ // Children always come before parent since changes are in top-to-bottom z-order.
+ if ((taskInfo == null) || mChildTaskTargets.get(taskInfo.taskId)) {
+ // has children, so not a leaf. Skip.
+ return false;
+ }
+ if (taskInfo.hasParentTask()) {
+ mChildTaskTargets.put(taskInfo.parentTaskId, true);
+ }
+ return true;
+ }
+ }
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
index 44c0e169b6d9..2a37bd370b7c 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RemoteTransitionCompat.java
@@ -18,7 +18,6 @@ package com.android.systemui.shared.system;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
-import static android.view.RemoteAnimationTarget.MODE_CLOSING;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED;
@@ -72,71 +71,23 @@ public class RemoteTransitionCompat {
public void startAnimation(IBinder transition, TransitionInfo info,
SurfaceControl.Transaction t,
IRemoteTransitionFinishedCallback finishedCallback) {
- final ArrayMap<SurfaceControl, SurfaceControl> leashMap = new ArrayMap<>();
- final RemoteAnimationTarget[] apps =
- RemoteAnimationTargetCompat.wrapApps(info, t, leashMap);
- final RemoteAnimationTarget[] wallpapers =
- RemoteAnimationTargetCompat.wrapNonApps(
- info, true /* wallpapers */, t, leashMap);
// TODO(b/177438007): Move this set-up logic into launcher's animation impl.
mToken = transition;
- // This transition is for opening recents, so recents is on-top. We want to draw
- // the current going-away tasks on top of recents, though, so move them to front.
- // Note that we divide up the "layer space" into 3 regions each the size of
- // the change count. This way we can easily move changes into above/below/between
- // while maintaining their relative ordering.
- final ArrayList<WindowContainerToken> pausingTasks = new ArrayList<>();
- WindowContainerToken pipTask = null;
- WindowContainerToken recentsTask = null;
- int recentsTaskId = -1;
- for (int i = apps.length - 1; i >= 0; --i) {
- final ActivityManager.RunningTaskInfo taskInfo = apps[i].taskInfo;
- if (apps[i].mode == MODE_CLOSING) {
- t.setLayer(apps[i].leash, info.getChanges().size() * 3 - i);
- if (taskInfo == null) {
- continue;
- }
- // Add to front since we are iterating backwards.
- pausingTasks.add(0, taskInfo.token);
- if (taskInfo.pictureInPictureParams != null
- && taskInfo.pictureInPictureParams.isAutoEnterEnabled()) {
- pipTask = taskInfo.token;
- }
- } else if (taskInfo != null
- && taskInfo.topActivityType == ACTIVITY_TYPE_RECENTS) {
- // This task is for recents, keep it on top.
- t.setLayer(apps[i].leash, info.getChanges().size() * 3 - i);
- recentsTask = taskInfo.token;
- recentsTaskId = taskInfo.taskId;
- } else if (taskInfo != null && taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
- recentsTask = taskInfo.token;
- recentsTaskId = taskInfo.taskId;
- }
- }
- // Also make all the wallpapers opaque since we want the visible from the start
- for (int i = wallpapers.length - 1; i >= 0; --i) {
- t.setAlpha(wallpapers[i].leash, 1);
- }
- t.apply();
- mRecentsSession.setup(controller, info, finishedCallback, pausingTasks, pipTask,
- recentsTask, recentsTaskId, leashMap, mToken,
- (info.getFlags() & TRANSIT_FLAG_KEYGUARD_LOCKED) != 0);
- recents.onAnimationStart(mRecentsSession, apps, wallpapers, new Rect(0, 0, 0, 0),
- new Rect());
+ mRecentsSession.start(controller, recents, mToken, info, t, finishedCallback);
}
@Override
public void mergeAnimation(IBinder transition, TransitionInfo info,
SurfaceControl.Transaction t, IBinder mergeTarget,
IRemoteTransitionFinishedCallback finishedCallback) {
- if (mergeTarget.equals(mToken) && mRecentsSession.merge(info, t, recents)) {
+ if (mergeTarget.equals(mToken) && mRecentsSession.merge(info, t)) {
try {
finishedCallback.onTransitionFinished(null /* wct */, null /* sct */);
} catch (RemoteException e) {
Log.e(TAG, "Error merging transition.", e);
}
// commit taskAppeared after merge transition finished.
- mRecentsSession.commitTasksAppearedIfNeeded(recents);
+ mRecentsSession.commitTasksAppearedIfNeeded();
} else {
t.close();
info.releaseAllSurfaces();
@@ -152,15 +103,16 @@ public class RemoteTransitionCompat {
*/
@VisibleForTesting
static class RecentsControllerWrap extends RecentsAnimationControllerCompat {
+ private RecentsAnimationListener mListener = null;
private RecentsAnimationControllerCompat mWrapped = null;
private IRemoteTransitionFinishedCallback mFinishCB = null;
- private ArrayList<WindowContainerToken> mPausingTasks = null;
+ private ArrayList<TaskState> mPausingTasks = null;
private WindowContainerToken mPipTask = null;
private WindowContainerToken mRecentsTask = null;
private int mRecentsTaskId = 0;
private TransitionInfo mInfo = null;
private ArrayList<SurfaceControl> mOpeningLeashes = null;
- private boolean mOpeningHome = false;
+ private boolean mOpeningSeparateHome = false;
private ArrayMap<SurfaceControl, SurfaceControl> mLeashMap = null;
private PictureInPictureSurfaceTransaction mPipTransaction = null;
private IBinder mTransition = null;
@@ -168,34 +120,79 @@ public class RemoteTransitionCompat {
private RemoteAnimationTarget[] mAppearedTargets;
private boolean mWillFinishToHome = false;
- void setup(RecentsAnimationControllerCompat wrapped, TransitionInfo info,
- IRemoteTransitionFinishedCallback finishCB,
- ArrayList<WindowContainerToken> pausingTasks, WindowContainerToken pipTask,
- WindowContainerToken recentsTask, int recentsTaskId, ArrayMap<SurfaceControl,
- SurfaceControl> leashMap, IBinder transition, boolean keyguardLocked) {
+ void start(RecentsAnimationControllerCompat wrapped, RecentsAnimationListener listener,
+ IBinder transition, TransitionInfo info, SurfaceControl.Transaction t,
+ IRemoteTransitionFinishedCallback finishedCallback) {
if (mInfo != null) {
throw new IllegalStateException("Trying to run a new recents animation while"
+ " recents is already active.");
}
+ mListener = listener;
mWrapped = wrapped;
mInfo = info;
- mFinishCB = finishCB;
- mPausingTasks = pausingTasks;
- mPipTask = pipTask;
- mRecentsTask = recentsTask;
- mRecentsTaskId = recentsTaskId;
- mLeashMap = leashMap;
+ mFinishCB = finishedCallback;
+ mPausingTasks = new ArrayList<>();
+ mPipTask = null;
+ mRecentsTask = null;
+ mRecentsTaskId = -1;
+ mLeashMap = new ArrayMap<>();
mTransition = transition;
- mKeyguardLocked = keyguardLocked;
+ mKeyguardLocked = (info.getFlags() & TRANSIT_FLAG_KEYGUARD_LOCKED) != 0;
+
+ final ArrayList<RemoteAnimationTarget> apps = new ArrayList<>();
+ final ArrayList<RemoteAnimationTarget> wallpapers = new ArrayList<>();
+ RemoteAnimationTargetCompat.LeafTaskFilter leafTaskFilter =
+ new RemoteAnimationTargetCompat.LeafTaskFilter();
+ // About layering: we divide up the "layer space" into 3 regions (each the size of
+ // the change count). This lets us categorize things into above/below/between
+ // while maintaining their relative ordering.
+ for (int i = 0; i < info.getChanges().size(); ++i) {
+ final TransitionInfo.Change change = info.getChanges().get(i);
+ final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
+ if (RemoteAnimationTargetCompat.isWallpaper(change)) {
+ final RemoteAnimationTarget target = newTarget(change,
+ // wallpapers go into the "below" layer space
+ info.getChanges().size() - i, info, t, mLeashMap);
+ wallpapers.add(target);
+ // Make all the wallpapers opaque since we want them visible from the start
+ t.setAlpha(target.leash, 1);
+ } else if (leafTaskFilter.test(change)) {
+ // start by putting everything into the "below" layer space.
+ final RemoteAnimationTarget target = newTarget(change,
+ info.getChanges().size() - i, info, t, mLeashMap);
+ apps.add(target);
+ if (change.getMode() == TRANSIT_CLOSE || change.getMode() == TRANSIT_TO_BACK) {
+ // raise closing (pausing) task to "above" layer so it isn't covered
+ t.setLayer(target.leash, info.getChanges().size() * 3 - i);
+ mPausingTasks.add(new TaskState(change, target.leash));
+ if (taskInfo.pictureInPictureParams != null
+ && taskInfo.pictureInPictureParams.isAutoEnterEnabled()) {
+ mPipTask = taskInfo.token;
+ }
+ } else if (taskInfo != null
+ && taskInfo.topActivityType == ACTIVITY_TYPE_RECENTS) {
+ // There's a 3p launcher, so make sure recents goes above that.
+ t.setLayer(target.leash, info.getChanges().size() * 3 - i);
+ mRecentsTask = taskInfo.token;
+ mRecentsTaskId = taskInfo.taskId;
+ } else if (taskInfo != null && taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
+ mRecentsTask = taskInfo.token;
+ mRecentsTaskId = taskInfo.taskId;
+ }
+ }
+ }
+ t.apply();
+ mListener.onAnimationStart(this, apps.toArray(new RemoteAnimationTarget[apps.size()]),
+ wallpapers.toArray(new RemoteAnimationTarget[wallpapers.size()]),
+ new Rect(0, 0, 0, 0), new Rect());
}
@SuppressLint("NewApi")
- boolean merge(TransitionInfo info, SurfaceControl.Transaction t,
- RecentsAnimationListener recents) {
+ boolean merge(TransitionInfo info, SurfaceControl.Transaction t) {
SparseArray<TransitionInfo.Change> openingTasks = null;
mAppearedTargets = null;
- boolean cancelRecents = false;
- boolean homeGoingAway = false;
+ boolean foundHomeOpening = false;
+ boolean foundRecentsClosing = false;
boolean hasChangingApp = false;
for (int i = info.getChanges().size() - 1; i >= 0; --i) {
final TransitionInfo.Change change = info.getChanges().get(i);
@@ -203,8 +200,8 @@ public class RemoteTransitionCompat {
final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
if (taskInfo != null) {
if (taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
- // canceling recents animation
- cancelRecents = true;
+ // This is usually a 3p launcher
+ foundHomeOpening = true;
}
if (openingTasks == null) {
openingTasks = new SparseArray<>();
@@ -219,19 +216,18 @@ public class RemoteTransitionCompat {
} else if (change.getMode() == TRANSIT_CLOSE
|| change.getMode() == TRANSIT_TO_BACK) {
if (mRecentsTask.equals(change.getContainer())) {
- homeGoingAway = true;
+ foundRecentsClosing = true;
}
} else if (change.getMode() == TRANSIT_CHANGE) {
hasChangingApp = true;
}
}
- if (hasChangingApp && homeGoingAway) {
+ if (hasChangingApp && foundRecentsClosing) {
// This happens when a visible app is expanding (usually PiP). In this case,
- // The transition probably has a special-purpose animation, so finish recents
+ // that transition probably has a special-purpose animation, so finish recents
// now and let it do its animation (since recents is going to be occluded).
- if (!recents.onSwitchToScreenshot(() -> {
- finish(true /* toHome */, false /* userLeaveHint */);
- })) {
+ if (!mListener.onSwitchToScreenshot(
+ () -> finish(true /* toHome */, false /* userLeaveHint */))) {
Log.w(TAG, "Recents callback doesn't support support switching to screenshot"
+ ", there might be a flicker.");
finish(true /* toHome */, false /* userLeaveHint */);
@@ -240,9 +236,9 @@ public class RemoteTransitionCompat {
}
if (openingTasks == null) return false;
int pauseMatches = 0;
- if (!cancelRecents) {
+ if (!foundHomeOpening) {
for (int i = 0; i < openingTasks.size(); ++i) {
- if (mPausingTasks.contains(openingTasks.valueAt(i).getContainer())) {
+ if (TaskState.indexOf(mPausingTasks, openingTasks.valueAt(i)) >= 0) {
++pauseMatches;
}
}
@@ -262,7 +258,7 @@ public class RemoteTransitionCompat {
}
final int layer = mInfo.getChanges().size() * 3;
mOpeningLeashes = new ArrayList<>();
- mOpeningHome = cancelRecents;
+ mOpeningSeparateHome = foundHomeOpening;
final RemoteAnimationTarget[] targets =
new RemoteAnimationTarget[openingTasks.size()];
for (int i = 0; i < openingTasks.size(); ++i) {
@@ -280,9 +276,9 @@ public class RemoteTransitionCompat {
return true;
}
- private void commitTasksAppearedIfNeeded(RecentsAnimationListener recents) {
+ private void commitTasksAppearedIfNeeded() {
if (mAppearedTargets != null) {
- recents.onTasksAppeared(mAppearedTargets);
+ mListener.onTasksAppeared(mAppearedTargets);
mAppearedTargets = null;
}
}
@@ -346,27 +342,26 @@ public class RemoteTransitionCompat {
// re-showing it's task).
for (int i = mPausingTasks.size() - 1; i >= 0; --i) {
// reverse order so that index 0 ends up on top
- wct.reorder(mPausingTasks.get(i), true /* onTop */);
- t.show(mInfo.getChange(mPausingTasks.get(i)).getLeash());
+ wct.reorder(mPausingTasks.get(i).mToken, true /* onTop */);
+ t.show(mPausingTasks.get(i).mTaskSurface);
}
if (!mKeyguardLocked && mRecentsTask != null) {
wct.restoreTransientOrder(mRecentsTask);
}
- } else if (toHome && mOpeningHome && mPausingTasks != null) {
+ } else if (toHome && mOpeningSeparateHome && mPausingTasks != null) {
// Special situaition where 3p launcher was changed during recents (this happens
// during tapltests...). Here we get both "return to home" AND "home opening".
// This is basically going home, but we have to restore recents order and also
// treat the home "pausing" task properly.
for (int i = mPausingTasks.size() - 1; i >= 0; --i) {
- final TransitionInfo.Change change = mInfo.getChange(mPausingTasks.get(i));
- final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
- if (taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
+ final TaskState state = mPausingTasks.get(i);
+ if (state.mTaskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
// Treat as opening (see above)
- wct.reorder(mPausingTasks.get(i), true /* onTop */);
- t.show(mInfo.getChange(mPausingTasks.get(i)).getLeash());
+ wct.reorder(state.mToken, true /* onTop */);
+ t.show(state.mTaskSurface);
} else {
// Treat as hiding (see below)
- t.hide(mInfo.getChange(mPausingTasks.get(i)).getLeash());
+ t.hide(state.mTaskSurface);
}
}
if (!mKeyguardLocked && mRecentsTask != null) {
@@ -377,13 +372,13 @@ public class RemoteTransitionCompat {
if (!sendUserLeaveHint) {
// This means recents is not *actually* finishing, so of course we gotta
// do special stuff in WMCore to accommodate.
- wct.setDoNotPip(mPausingTasks.get(i));
+ wct.setDoNotPip(mPausingTasks.get(i).mToken);
}
// Since we will reparent out of the leashes, pre-emptively hide the child
// surface to match the leash. Otherwise, there will be a flicker before the
// visibility gets committed in Core when using split-screen (in splitscreen,
// the leaf-tasks are not "independent" so aren't hidden by normal setup).
- t.hide(mInfo.getChange(mPausingTasks.get(i)).getLeash());
+ t.hide(mPausingTasks.get(i).mTaskSurface);
}
if (mPipTask != null && mPipTransaction != null && sendUserLeaveHint) {
t.show(mInfo.getChange(mPipTask).getLeash());
@@ -404,11 +399,13 @@ public class RemoteTransitionCompat {
mInfo.releaseAllSurfaces();
// Reset all members.
mWrapped = null;
+ mListener = null;
mFinishCB = null;
mPausingTasks = null;
+ mAppearedTargets = null;
mInfo = null;
mOpeningLeashes = null;
- mOpeningHome = false;
+ mOpeningSeparateHome = false;
mLeashMap = null;
mTransition = null;
}
@@ -450,4 +447,36 @@ public class RemoteTransitionCompat {
@Override public void animateNavigationBarToApp(long duration) {
}
}
+
+ /** Utility class to track the state of a task as-seen by recents. */
+ private static class TaskState {
+ WindowContainerToken mToken;
+ ActivityManager.RunningTaskInfo mTaskInfo;
+
+ /** The surface/leash of the task provided by Core. */
+ SurfaceControl mTaskSurface;
+
+ /** The (local) animation-leash created for this task. */
+ SurfaceControl mLeash;
+
+ TaskState(TransitionInfo.Change change, SurfaceControl leash) {
+ mToken = change.getContainer();
+ mTaskInfo = change.getTaskInfo();
+ mTaskSurface = change.getLeash();
+ mLeash = leash;
+ }
+
+ static int indexOf(ArrayList<TaskState> list, TransitionInfo.Change change) {
+ for (int i = list.size() - 1; i >= 0; --i) {
+ if (list.get(i).mToken.equals(change.getContainer())) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public String toString() {
+ return "" + mToken + " : " + mLeash;
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
index 1254e1ee3311..92ee37310130 100644
--- a/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
+++ b/packages/SystemUI/src/com/android/keyguard/ClockEventController.kt
@@ -48,7 +48,7 @@ import com.android.systemui.plugins.ClockTickRate
import com.android.systemui.plugins.log.LogBuffer
import com.android.systemui.plugins.log.LogLevel.DEBUG
import com.android.systemui.shared.regionsampling.RegionSampler
-import com.android.systemui.plugins.Weather
+import com.android.systemui.plugins.WeatherData
import com.android.systemui.statusbar.policy.BatteryController
import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback
import com.android.systemui.statusbar.policy.ConfigurationController
@@ -291,10 +291,8 @@ constructor(
clock?.events?.onTimeFormatChanged(DateFormat.is24HourFormat(context))
}
- override fun onWeatherDataChanged(data: Weather?) {
- if (data != null) {
- clock?.events?.onWeatherDataChanged(data)
- }
+ override fun onWeatherDataChanged(data: WeatherData) {
+ clock?.events?.onWeatherDataChanged(data)
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index eec788b7add8..f164e7d33642 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -492,12 +492,14 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
case MotionEvent.ACTION_MOVE:
mVelocityTracker.addMovement(event);
int pointerIndex = event.findPointerIndex(mActivePointerId);
- float y = event.getY(pointerIndex);
- if (mLastTouchY != -1) {
- float dy = y - mLastTouchY;
- setTranslationY(getTranslationY() + dy * TOUCH_Y_MULTIPLIER);
+ if (pointerIndex != -1) {
+ float y = event.getY(pointerIndex);
+ if (mLastTouchY != -1) {
+ float dy = y - mLastTouchY;
+ setTranslationY(getTranslationY() + dy * TOUCH_Y_MULTIPLIER);
+ }
+ mLastTouchY = y;
}
- mLastTouchY = y;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 23f887ef0016..f1abdc68f97e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -17,7 +17,6 @@
package com.android.keyguard;
import static android.app.StatusBarManager.SESSION_KEYGUARD;
-import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_BIOMETRIC;
import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_EXTENDED_ACCESS;
@@ -36,7 +35,6 @@ import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.hardware.biometrics.BiometricOverlayConstants;
-import android.hardware.biometrics.BiometricSourceType;
import android.media.AudioManager;
import android.metrics.LogMaker;
import android.os.SystemClock;
@@ -321,7 +319,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
KeyguardSecurityContainerController.this.onDensityOrFontScaleChanged();
}
};
- private boolean mBouncerVisible = false;
private final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
new KeyguardUpdateMonitorCallback() {
@Override
@@ -356,19 +353,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
public void onDevicePolicyManagerStateChanged() {
showPrimarySecurityScreen(false);
}
-
- @Override
- public void onBiometricRunningStateChanged(boolean running,
- BiometricSourceType biometricSourceType) {
- if (biometricSourceType == FINGERPRINT) {
- updateSideFpsVisibility();
- }
- }
-
- @Override
- public void onStrongAuthStateChanged(int userId) {
- updateSideFpsVisibility();
- }
};
@Inject
@@ -460,35 +444,24 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
getCurrentSecurityController().onPause();
}
mView.onPause();
- // It might happen that onStartingToHide is not called when the device is locked while on
- // bouncer.
- setBouncerVisible(false);
mView.clearFocus();
}
- private void updateSideFpsVisibility() {
+ /**
+ * Shows and hides the side finger print sensor animation.
+ *
+ * @param isVisible sets whether we show or hide the side fps animation
+ */
+ public void updateSideFpsVisibility(boolean isVisible) {
if (!mSideFpsController.isPresent()) {
return;
}
- final boolean sfpsEnabled = getResources().getBoolean(
- R.bool.config_show_sidefps_hint_on_bouncer);
- final boolean fpsDetectionRunning = mUpdateMonitor.isFingerprintDetectionRunning();
- final boolean isUnlockingWithFpAllowed =
- mUpdateMonitor.isUnlockingWithFingerprintAllowed();
- boolean toShow = mBouncerVisible && sfpsEnabled && fpsDetectionRunning
- && isUnlockingWithFpAllowed;
-
- if (DEBUG) {
- Log.d(TAG, "sideFpsToShow=" + toShow + ", "
- + "mBouncerVisible=" + mBouncerVisible + ", "
- + "configEnabled=" + sfpsEnabled + ", "
- + "fpsDetectionRunning=" + fpsDetectionRunning + ", "
- + "isUnlockingWithFpAllowed=" + isUnlockingWithFpAllowed);
- }
- if (toShow) {
- mSideFpsController.get().show(SideFpsUiRequestSource.PRIMARY_BOUNCER,
- BiometricOverlayConstants.REASON_AUTH_KEYGUARD);
+ if (isVisible) {
+ mSideFpsController.get().show(
+ SideFpsUiRequestSource.PRIMARY_BOUNCER,
+ BiometricOverlayConstants.REASON_AUTH_KEYGUARD
+ );
} else {
mSideFpsController.get().hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
}
@@ -637,7 +610,6 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_BOUNCER_STATE_CHANGED, state);
getCurrentSecurityController().onResume(reason);
- updateSideFpsVisibility();
}
mView.onResume(
mSecurityModel.getSecurityMode(KeyguardUpdateMonitor.getCurrentUser()),
@@ -691,22 +663,15 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
if (mCurrentSecurityMode != SecurityMode.None) {
getCurrentSecurityController().onStartingToHide();
}
- setBouncerVisible(false);
}
/** Called when the bouncer changes visibility. */
- public void onBouncerVisibilityChanged(@View.Visibility int visibility) {
- setBouncerVisible(visibility == View.VISIBLE);
- if (visibility == View.INVISIBLE) {
+ public void onBouncerVisibilityChanged(boolean isVisible) {
+ if (!isVisible) {
mView.resetScale();
}
}
- private void setBouncerVisible(boolean visible) {
- mBouncerVisible = visible;
- updateSideFpsVisibility();
- }
-
/**
* Shows the next security screen if there is one.
* @param authenticated true if the user entered the correct authentication
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index addae72a5b25..eb4b05b42b91 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -96,8 +96,10 @@ import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricSourceType;
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
import android.hardware.biometrics.SensorProperties;
+import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.FaceManager;
import android.hardware.face.FaceSensorPropertiesInternal;
+import android.hardware.fingerprint.FingerprintAuthenticateOptions;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
import android.hardware.fingerprint.FingerprintManager.AuthenticationResult;
@@ -151,7 +153,7 @@ import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.dump.DumpsysTableLogger;
import com.android.systemui.log.SessionTracker;
-import com.android.systemui.plugins.Weather;
+import com.android.systemui.plugins.WeatherData;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.shared.system.TaskStackChangeListener;
@@ -2781,7 +2783,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
boolean shouldListen = shouldListenKeyguardState && shouldListenUserState
&& shouldListenBouncerState && shouldListenUdfpsState
- && shouldListenSideFpsState;
+ && shouldListenSideFpsState
+ && !isFingerprintLockedOut();
logListenerModelData(
new KeyguardFingerprintListenModel(
System.currentTimeMillis(),
@@ -2941,7 +2944,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
// Trigger the fingerprint success path so the bouncer can be shown
handleFingerprintAuthenticated(user, isStrongBiometric);
},
- userId);
+ new FingerprintAuthenticateOptions.Builder()
+ .setUserId(userId)
+ .build());
} else {
mLogger.v("startListeningForFingerprint - authenticate");
mFpm.authenticate(null /* crypto */, mFingerprintCancelSignal,
@@ -2987,7 +2992,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
if (supportsFaceDetection && !udfpsFingerprintAuthRunning) {
// Run face detection. (If a face is detected, show the bouncer.)
mLogger.v("startListeningForFace - detect");
- mFaceManager.detectFace(mFaceCancelSignal, mFaceDetectionCallback, userId);
+ mFaceManager.detectFace(mFaceCancelSignal, mFaceDetectionCallback,
+ new FaceAuthenticateOptions.Builder()
+ .setUserId(userId)
+ .build());
} else {
// Don't run face detection. Instead, inform the user
// face auth is unavailable and how to proceed.
@@ -3006,7 +3014,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
final boolean isBypassEnabled = mKeyguardBypassController != null
&& mKeyguardBypassController.isBypassEnabled();
mFaceManager.authenticate(null /* crypto */, mFaceCancelSignal,
- mFaceAuthenticationCallback, null /* handler */, userId, isBypassEnabled);
+ mFaceAuthenticationCallback, null /* handler */, userId);
}
setFaceRunningState(BIOMETRIC_STATE_RUNNING);
}
@@ -3302,12 +3310,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
/**
* @param data the weather data (temp, conditions, unit) for weather clock to use
*/
- public void sendWeatherData(Weather data) {
+ public void sendWeatherData(WeatherData data) {
mHandler.post(()-> {
handleWeatherDataUpdate(data); });
}
- private void handleWeatherDataUpdate(Weather data) {
+ private void handleWeatherDataUpdate(WeatherData data) {
Assert.isMainThread();
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 0da799e0964d..38f3e5065eec 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -23,7 +23,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.settingslib.fuelgauge.BatteryStatus;
-import com.android.systemui.plugins.Weather;
+import com.android.systemui.plugins.WeatherData;
import com.android.systemui.statusbar.KeyguardIndicationController;
import java.util.TimeZone;
@@ -61,7 +61,7 @@ public class KeyguardUpdateMonitorCallback {
/**
* Called when receive new weather data.
*/
- public void onWeatherDataChanged(Weather data) { }
+ public void onWeatherDataChanged(WeatherData data) { }
/**
* Called when the carrier PLMN or SPN changes.
diff --git a/packages/SystemUI/src/com/android/keyguard/PinShapeHintingView.java b/packages/SystemUI/src/com/android/keyguard/PinShapeHintingView.java
index cf9d0537defe..fc5c254fdf29 100644
--- a/packages/SystemUI/src/com/android/keyguard/PinShapeHintingView.java
+++ b/packages/SystemUI/src/com/android/keyguard/PinShapeHintingView.java
@@ -37,7 +37,6 @@ public class PinShapeHintingView extends LinearLayout implements PinShapeInput {
private int mPinLength;
private int mDotDiameter;
- private int mDotSpacing;
private int mColor = Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary)
.getDefaultColor();
private int mPosition = 0;
@@ -48,8 +47,7 @@ public class PinShapeHintingView extends LinearLayout implements PinShapeInput {
super(context, attrs);
mPinShapeAdapter = new PinShapeAdapter(context);
mPinLength = DEFAULT_PIN_LENGTH;
- mDotDiameter = context.getResources().getDimensionPixelSize(R.dimen.default_dot_diameter);
- mDotSpacing = context.getResources().getDimensionPixelSize(R.dimen.default_dot_spacing);
+ mDotDiameter = context.getResources().getDimensionPixelSize(R.dimen.password_shape_size);
for (int i = 0; i < mPinLength; i++) {
ImageView pinDot = new ImageView(context, attrs);
diff --git a/packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt b/packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt
index 0f00a040b094..603471b1de41 100644
--- a/packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt
+++ b/packages/SystemUI/src/com/android/keyguard/mediator/ScreenOnCoordinator.kt
@@ -73,6 +73,10 @@ class ScreenOnCoordinator @Inject constructor(
@BinderThread
fun onScreenTurnedOn() {
foldAodAnimationController?.onScreenTurnedOn()
+ }
+
+ @BinderThread
+ fun onScreenTurnedOff() {
pendingTasks.reset()
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
index 00f5ac2ffa23..12b5705190d9 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/SystemActions.java
@@ -58,13 +58,13 @@ import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.phone.StatusBarWindowCallback;
import com.android.systemui.util.Assert;
+import dagger.Lazy;
+
import java.util.Locale;
import java.util.Optional;
import javax.inject.Inject;
-import dagger.Lazy;
-
/**
* Class to register system actions with accessibility framework.
*/
@@ -473,7 +473,7 @@ public class SystemActions implements CoreStartable {
KeyEvent event = KeyEvent.obtain(downTime, time, action, keyCode, 0, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
InputDevice.SOURCE_KEYBOARD, null);
- InputManager.getInstance()
+ mContext.getSystemService(InputManager.class)
.injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
event.recycle();
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index 3e5d16ac007f..e42f051bf3bb 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -878,7 +878,7 @@ public class AuthContainerView extends LinearLayout
final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,
- WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG,
+ WindowManager.LayoutParams.TYPE_STATUS_BAR_ADDITIONAL,
windowFlags,
PixelFormat.TRANSLUCENT);
lp.privateFlags |= WindowManager.LayoutParams.SYSTEM_FLAG_SHOW_FOR_ALL_USERS;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
index 58b230f52e93..4b32759588e0 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthRippleView.kt
@@ -75,7 +75,7 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
}
private var radius: Float = 0f
set(value) {
- rippleShader.setMaxSize(value * 2f, value * 2f)
+ rippleShader.rippleSize.setMaxSize(value * 2f, value * 2f)
field = value
}
private var origin: Point = Point()
@@ -364,7 +364,7 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
if (drawRipple) {
canvas?.drawCircle(origin.x.toFloat(), origin.y.toFloat(),
- rippleShader.currentWidth, ripplePaint)
+ rippleShader.rippleSize.currentWidth, ripplePaint)
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
index 36103f8db8d8..cef415c8a490 100644
--- a/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/charging/WirelessChargingLayout.java
@@ -33,7 +33,9 @@ import android.widget.TextView;
import com.android.settingslib.Utils;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
+import com.android.systemui.shared.recents.utilities.Utilities;
import com.android.systemui.surfaceeffects.ripple.RippleAnimationConfig;
+import com.android.systemui.surfaceeffects.ripple.RippleShader;
import com.android.systemui.surfaceeffects.ripple.RippleShader.RippleShape;
import com.android.systemui.surfaceeffects.ripple.RippleView;
@@ -44,10 +46,12 @@ import java.text.NumberFormat;
*/
final class WirelessChargingLayout extends FrameLayout {
private static final long CIRCLE_RIPPLE_ANIMATION_DURATION = 1500;
- private static final long ROUNDED_BOX_RIPPLE_ANIMATION_DURATION = 1750;
+ private static final long ROUNDED_BOX_RIPPLE_ANIMATION_DURATION = 3000;
private static final int SCRIM_COLOR = 0x4C000000;
private static final int SCRIM_FADE_DURATION = 300;
private RippleView mRippleView;
+ // This is only relevant to the rounded box ripple.
+ private RippleShader.SizeAtProgress[] mSizeAtProgressArray;
WirelessChargingLayout(Context context, int transmittingBatteryLevel, int batteryLevel,
boolean isDozing, RippleShape rippleShape) {
@@ -125,20 +129,23 @@ final class WirelessChargingLayout extends FrameLayout {
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(textSizeAnimator, textOpacityAnimator, textFadeAnimator);
- ValueAnimator scrimFadeInAnimator = ObjectAnimator.ofArgb(this,
- "backgroundColor", Color.TRANSPARENT, SCRIM_COLOR);
- scrimFadeInAnimator.setDuration(SCRIM_FADE_DURATION);
- scrimFadeInAnimator.setInterpolator(Interpolators.LINEAR);
- ValueAnimator scrimFadeOutAnimator = ObjectAnimator.ofArgb(this,
- "backgroundColor", SCRIM_COLOR, Color.TRANSPARENT);
- scrimFadeOutAnimator.setDuration(SCRIM_FADE_DURATION);
- scrimFadeOutAnimator.setInterpolator(Interpolators.LINEAR);
- scrimFadeOutAnimator.setStartDelay((rippleShape == RippleShape.CIRCLE
- ? CIRCLE_RIPPLE_ANIMATION_DURATION : ROUNDED_BOX_RIPPLE_ANIMATION_DURATION)
- - SCRIM_FADE_DURATION);
- AnimatorSet animatorSetScrim = new AnimatorSet();
- animatorSetScrim.playTogether(scrimFadeInAnimator, scrimFadeOutAnimator);
- animatorSetScrim.start();
+ // For tablet docking animation, we don't play the background scrim.
+ if (!Utilities.isTablet(context)) {
+ ValueAnimator scrimFadeInAnimator = ObjectAnimator.ofArgb(this,
+ "backgroundColor", Color.TRANSPARENT, SCRIM_COLOR);
+ scrimFadeInAnimator.setDuration(SCRIM_FADE_DURATION);
+ scrimFadeInAnimator.setInterpolator(Interpolators.LINEAR);
+ ValueAnimator scrimFadeOutAnimator = ObjectAnimator.ofArgb(this,
+ "backgroundColor", SCRIM_COLOR, Color.TRANSPARENT);
+ scrimFadeOutAnimator.setDuration(SCRIM_FADE_DURATION);
+ scrimFadeOutAnimator.setInterpolator(Interpolators.LINEAR);
+ scrimFadeOutAnimator.setStartDelay((rippleShape == RippleShape.CIRCLE
+ ? CIRCLE_RIPPLE_ANIMATION_DURATION : ROUNDED_BOX_RIPPLE_ANIMATION_DURATION)
+ - SCRIM_FADE_DURATION);
+ AnimatorSet animatorSetScrim = new AnimatorSet();
+ animatorSetScrim.playTogether(scrimFadeInAnimator, scrimFadeOutAnimator);
+ animatorSetScrim.start();
+ }
mRippleView = findViewById(R.id.wireless_charging_ripple);
mRippleView.setupShader(rippleShape);
@@ -147,7 +154,26 @@ final class WirelessChargingLayout extends FrameLayout {
if (mRippleView.getRippleShape() == RippleShape.ROUNDED_BOX) {
mRippleView.setDuration(ROUNDED_BOX_RIPPLE_ANIMATION_DURATION);
mRippleView.setSparkleStrength(0.22f);
- mRippleView.setColor(color, 28);
+ mRippleView.setColor(color, 102); // 40% of opacity.
+ mRippleView.setBaseRingFadeParams(
+ /* fadeInStart = */ 0f,
+ /* fadeInEnd = */ 0f,
+ /* fadeOutStart = */ 0.2f,
+ /* fadeOutEnd= */ 0.47f
+ );
+ mRippleView.setSparkleRingFadeParams(
+ /* fadeInStart = */ 0f,
+ /* fadeInEnd = */ 0f,
+ /* fadeOutStart = */ 0.2f,
+ /* fadeOutEnd= */ 1f
+ );
+ mRippleView.setCenterFillFadeParams(
+ /* fadeInStart = */ 0f,
+ /* fadeInEnd = */ 0f,
+ /* fadeOutStart = */ 0f,
+ /* fadeOutEnd= */ 0.2f
+ );
+ mRippleView.setBlur(6.5f, 2.5f);
} else {
mRippleView.setDuration(CIRCLE_RIPPLE_ANIMATION_DURATION);
mRippleView.setColor(color, RippleAnimationConfig.RIPPLE_DEFAULT_ALPHA);
@@ -246,9 +272,7 @@ final class WirelessChargingLayout extends FrameLayout {
int height = getMeasuredHeight();
mRippleView.setCenter(width * 0.5f, height * 0.5f);
if (mRippleView.getRippleShape() == RippleShape.ROUNDED_BOX) {
- // Those magic numbers are introduced for visual polish. This aspect ratio maps with
- // the tablet's docking station.
- mRippleView.setMaxSize(width * 1.36f, height * 1.46f);
+ updateRippleSizeAtProgressList(width, height);
} else {
float maxSize = Math.max(width, height);
mRippleView.setMaxSize(maxSize, maxSize);
@@ -257,4 +281,36 @@ final class WirelessChargingLayout extends FrameLayout {
super.onLayout(changed, left, top, right, bottom);
}
+
+ private void updateRippleSizeAtProgressList(float width, float height) {
+ if (mSizeAtProgressArray == null) {
+ float maxSize = Math.max(width, height);
+ mSizeAtProgressArray = new RippleShader.SizeAtProgress[] {
+ // Those magic numbers are introduced for visual polish. It starts from a pill
+ // shape and expand to a full circle.
+ new RippleShader.SizeAtProgress(0f, 0f, 0f),
+ new RippleShader.SizeAtProgress(0.3f, width * 0.4f, height * 0.4f),
+ new RippleShader.SizeAtProgress(1f, maxSize, maxSize)
+ };
+ } else {
+ // Same multipliers, just need to recompute with the new width and height.
+ RippleShader.SizeAtProgress first = mSizeAtProgressArray[0];
+ first.setT(0f);
+ first.setWidth(0f);
+ first.setHeight(0f);
+
+ RippleShader.SizeAtProgress second = mSizeAtProgressArray[1];
+ second.setT(0.3f);
+ second.setWidth(width * 0.4f);
+ second.setHeight(height * 0.4f);
+
+ float maxSize = Math.max(width, height);
+ RippleShader.SizeAtProgress last = mSizeAtProgressArray[2];
+ last.setT(1f);
+ last.setWidth(maxSize);
+ last.setHeight(maxSize);
+ }
+
+ mRippleView.setSizeAtProgresses(mSizeAtProgressArray);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
index e9ac840cf4f4..f6b71336675f 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/BrightLineFalsingManager.java
@@ -402,7 +402,7 @@ public class BrightLineFalsingManager implements FalsingManager {
|| mAccessibilityManager.isTouchExplorationEnabled()
|| mDataProvider.isA11yAction()
|| (mFeatureFlags.isEnabled(Flags.FALSING_OFF_FOR_UNFOLDED)
- && !mDataProvider.isFolded());
+ && mDataProvider.isUnfolded());
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
index 5f347c158818..bc0f9950f865 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingDataProvider.java
@@ -380,8 +380,8 @@ public class FalsingDataProvider {
return mBatteryController.isWirelessCharging() || mDockManager.isDocked();
}
- public boolean isFolded() {
- return Boolean.TRUE.equals(mFoldStateListener.getFolded());
+ public boolean isUnfolded() {
+ return Boolean.FALSE.equals(mFoldStateListener.getFolded());
}
/** Implement to be alerted abotu the beginning and ending of falsing tracking. */
diff --git a/packages/SystemUI/src/com/android/systemui/devicepolicy/DevicePolicyManagerExt.kt b/packages/SystemUI/src/com/android/systemui/devicepolicy/DevicePolicyManagerExt.kt
new file mode 100644
index 000000000000..1390b4db3576
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/devicepolicy/DevicePolicyManagerExt.kt
@@ -0,0 +1,32 @@
+/*
+ * 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.devicepolicy
+
+import android.app.admin.DevicePolicyManager
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL
+import android.content.ComponentName
+
+/** Returns true if the admin of [userId] disallows keyguard shortcuts. */
+fun DevicePolicyManager.areKeyguardShortcutsDisabled(
+ admin: ComponentName? = null,
+ userId: Int
+): Boolean {
+ val flags = getKeyguardDisabledFeatures(admin, userId)
+ return flags and KEYGUARD_DISABLE_SHORTCUTS_ALL == KEYGUARD_DISABLE_SHORTCUTS_ALL ||
+ flags and KEYGUARD_DISABLE_FEATURES_ALL == KEYGUARD_DISABLE_FEATURES_ALL
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
index 3a37c6f1542c..f598c360dbcf 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamModule.java
@@ -30,7 +30,7 @@ import com.android.systemui.dreams.DreamOverlayService;
import com.android.systemui.dreams.complication.dagger.RegisteredComplicationsModule;
import com.android.systemui.dreams.dreamcomplication.dagger.ComplicationComponent;
import com.android.systemui.dreams.touch.scrim.dagger.ScrimModule;
-import com.android.systemui.process.condition.UserProcessCondition;
+import com.android.systemui.process.condition.SystemProcessCondition;
import com.android.systemui.shared.condition.Condition;
import com.android.systemui.shared.condition.Monitor;
@@ -129,7 +129,7 @@ public interface DreamModule {
@Binds
@IntoSet
@Named(DREAM_PRETEXT_CONDITIONS)
- Condition bindsUserProcessCondition(UserProcessCondition condition);
+ Condition bindSystemProcessCondition(SystemProcessCondition condition);
/** */
@Provides
diff --git a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
index fa4caaf8960d..2e37b348c5e3 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/Flags.kt
@@ -62,7 +62,7 @@ object Flags {
val FSI_REQUIRES_KEYGUARD = releasedFlag(110, "fsi_requires_keyguard")
// TODO(b/259130119): Tracking Bug
- val FSI_ON_DND_UPDATE = unreleasedFlag(259130119, "fsi_on_dnd_update", teamfood = true)
+ val FSI_ON_DND_UPDATE = releasedFlag(259130119, "fsi_on_dnd_update")
// TODO(b/265804648): Tracking Bug
@JvmField val DISABLE_FSI = unreleasedFlag(265804648, "disable_fsi")
@@ -266,6 +266,12 @@ object Flags {
@JvmField
val ENABLE_FONT_SCALING_TILE = unreleasedFlag(509, "enable_font_scaling_tile", teamfood = false)
+ /** Enables new QS Edit Mode visual refresh */
+ // TODO(b/269787742): Tracking Bug
+ @JvmField
+ val ENABLE_NEW_QS_EDIT_MODE =
+ unreleasedFlag(510, "enable_new_qs_edit_mode", teamfood = false)
+
// 600- status bar
// TODO(b/256614753): Tracking Bug
@@ -630,7 +636,8 @@ object Flags {
// 2600 - keyboard
// TODO(b/259352579): Tracking Bug
- @JvmField val SHORTCUT_LIST_SEARCH_LAYOUT = unreleasedFlag(2600, "shortcut_list_search_layout")
+ @JvmField val SHORTCUT_LIST_SEARCH_LAYOUT =
+ unreleasedFlag(2600, "shortcut_list_search_layout", teamfood = true)
// TODO(b/259428678): Tracking Bug
@JvmField
diff --git a/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt b/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt
index 7acd3f3447dd..9b748d0a0eb2 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt
+++ b/packages/SystemUI/src/com/android/systemui/flags/ServerFlagReader.kt
@@ -57,6 +57,7 @@ class ServerFlagReaderImpl @Inject constructor(
override fun onPropertiesChanged(properties: DeviceConfig.Properties) {
if (isTestHarness) {
Log.w(TAG, "Ignore server flag changes in Test Harness mode.")
+ return
}
if (properties.namespace != namespace) {
return
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt
index e9b8908214fc..496c64e1120e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/KeyboardModule.kt
@@ -17,6 +17,14 @@
package com.android.systemui.keyboard
+import com.android.systemui.keyboard.data.repository.KeyboardRepository
+import com.android.systemui.keyboard.data.repository.KeyboardRepositoryImpl
+import dagger.Binds
import dagger.Module
-@Module abstract class KeyboardModule
+@Module
+abstract class KeyboardModule {
+
+ @Binds
+ abstract fun bindKeyboardRepository(repository: KeyboardRepositoryImpl): KeyboardRepository
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/data/model/BacklightModel.kt b/packages/SystemUI/src/com/android/systemui/keyboard/data/model/BacklightModel.kt
new file mode 100644
index 000000000000..ea15a9f18584
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/data/model/BacklightModel.kt
@@ -0,0 +1,24 @@
+/*
+ * 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.keyboard.data.model
+
+/**
+ * Model for current state of keyboard backlight brightness. [level] indicates current level of
+ * backlight brightness and [maxLevel] its max possible value.
+ */
+data class BacklightModel(val level: Int, val maxLevel: Int)
diff --git a/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt
new file mode 100644
index 000000000000..70faf406d621
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyboard/data/repository/KeyboardRepository.kt
@@ -0,0 +1,100 @@
+/*
+ * 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.keyboard.data.repository
+
+import android.hardware.input.InputManager
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.keyboard.data.model.BacklightModel
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.flowOn
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.shareIn
+
+interface KeyboardRepository {
+ val keyboardConnected: Flow<Boolean>
+ val backlight: Flow<BacklightModel>
+}
+
+@SysUISingleton
+class KeyboardRepositoryImpl
+@Inject
+constructor(
+ @Application private val applicationScope: CoroutineScope,
+ @Background private val backgroundDispatcher: CoroutineDispatcher,
+ private val inputManager: InputManager,
+) : KeyboardRepository {
+
+ private val connectedDeviceIds: Flow<Set<Int>> =
+ conflatedCallbackFlow {
+ fun send(element: Set<Int>) = trySendWithFailureLogging(element, TAG)
+
+ var connectedKeyboards = inputManager.inputDeviceIds.toSet()
+ val listener =
+ object : InputManager.InputDeviceListener {
+ override fun onInputDeviceAdded(deviceId: Int) {
+ connectedKeyboards = connectedKeyboards + deviceId
+ send(connectedKeyboards)
+ }
+
+ override fun onInputDeviceChanged(deviceId: Int) = Unit
+
+ override fun onInputDeviceRemoved(deviceId: Int) {
+ connectedKeyboards = connectedKeyboards - deviceId
+ send(connectedKeyboards)
+ }
+ }
+ send(connectedKeyboards)
+ inputManager.registerInputDeviceListener(listener, /* handler= */ null)
+ awaitClose { inputManager.unregisterInputDeviceListener(listener) }
+ }
+ .shareIn(
+ scope = applicationScope,
+ started = SharingStarted.Lazily,
+ replay = 1,
+ )
+
+ override val keyboardConnected: Flow<Boolean> =
+ connectedDeviceIds
+ .map { it.any { deviceId -> isPhysicalFullKeyboard(deviceId) } }
+ .distinctUntilChanged()
+ .flowOn(backgroundDispatcher)
+
+ override val backlight: Flow<BacklightModel> =
+ conflatedCallbackFlow {
+ // TODO(b/268645734) register BacklightListener
+ }
+
+ private fun isPhysicalFullKeyboard(deviceId: Int): Boolean {
+ val device = inputManager.getInputDevice(deviceId)
+ return !device.isVirtual && device.isFullKeyboard
+ }
+
+ companion object {
+ const val TAG = "KeyboardRepositoryImpl"
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 7a891b0058af..eef7ccc65d95 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -602,6 +602,7 @@ public class KeyguardService extends Service {
checkPermission();
mKeyguardViewMediator.onScreenTurnedOff();
mKeyguardLifecyclesDispatcher.dispatch(KeyguardLifecyclesDispatcher.SCREEN_TURNED_OFF);
+ mScreenOnCoordinator.onScreenTurnedOff();
}
@Override // Binder interface
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 54fc5b588db7..02bee3efbe2f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -59,6 +59,7 @@ import android.hardware.biometrics.BiometricSourceType;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.SoundPool;
+import android.os.Binder;
import android.os.Bundle;
import android.os.DeadObjectException;
import android.os.Handler;
@@ -67,6 +68,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.Trace;
@@ -102,6 +104,7 @@ import com.android.internal.policy.IKeyguardDismissCallback;
import com.android.internal.policy.IKeyguardExitCallback;
import com.android.internal.policy.IKeyguardStateCallback;
import com.android.internal.policy.ScreenDecorationsUtils;
+import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.LatencyTracker;
import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardConstants;
@@ -270,6 +273,8 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
private AlarmManager mAlarmManager;
private AudioManager mAudioManager;
private StatusBarManager mStatusBarManager;
+ private final IStatusBarService mStatusBarService;
+ private final IBinder mStatusBarDisableToken = new Binder();
private final UserTracker mUserTracker;
private final SysuiStatusBarStateController mStatusBarStateController;
private final Executor mUiBgExecutor;
@@ -1213,6 +1218,8 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
mPM = powerManager;
mTrustManager = trustManager;
mUserSwitcherController = userSwitcherController;
+ mStatusBarService = IStatusBarService.Stub.asInterface(
+ ServiceManager.getService(Context.STATUS_BAR_SERVICE));
mKeyguardDisplayManager = keyguardDisplayManager;
mShadeController = shadeControllerLazy;
dumpManager.registerDumpable(getClass().getName(), this);
@@ -2918,7 +2925,12 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
// TODO (b/155663717) After restart, status bar will not properly hide home button
// unless disable is called to show un-hide it once first
if (forceClearFlags) {
- mStatusBarManager.disable(flags);
+ try {
+ mStatusBarService.disableForUser(flags, mStatusBarDisableToken,
+ mContext.getPackageName(), mUserTracker.getUserId());
+ } catch (RemoteException e) {
+ Log.d(TAG, "Failed to force clear flags", e);
+ }
}
if (forceHideHomeRecentsButtons || isShowingAndNotOccluded()) {
@@ -2934,7 +2946,12 @@ public class KeyguardViewMediator implements CoreStartable, Dumpable,
+ " --> flags=0x" + Integer.toHexString(flags));
}
- mStatusBarManager.disable(flags);
+ try {
+ mStatusBarService.disableForUser(flags, mStatusBarDisableToken,
+ mContext.getPackageName(), mUserTracker.getUserId());
+ } catch (RemoteException e) {
+ Log.d(TAG, "Failed to set disable flags: " + flags, e);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
index 4331fe66a0dc..0e85347c24b0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardBouncerRepository.kt
@@ -60,7 +60,6 @@ interface KeyguardBouncerRepository {
*/
val panelExpansionAmount: StateFlow<Float>
val keyguardPosition: StateFlow<Float>
- val onScreenTurnedOff: StateFlow<Boolean>
val isBackButtonEnabled: StateFlow<Boolean?>
/** Determines if user is already unlocked */
val keyguardAuthenticated: StateFlow<Boolean?>
@@ -70,6 +69,8 @@ interface KeyguardBouncerRepository {
val bouncerErrorMessage: CharSequence?
val alternateBouncerVisible: StateFlow<Boolean>
val alternateBouncerUIAvailable: StateFlow<Boolean>
+ val sideFpsShowing: StateFlow<Boolean>
+
var lastAlternateBouncerVisibleTime: Long
fun setPrimaryScrimmed(isScrimmed: Boolean)
@@ -98,11 +99,11 @@ interface KeyguardBouncerRepository {
fun setIsBackButtonEnabled(isBackButtonEnabled: Boolean)
- fun setOnScreenTurnedOff(onScreenTurnedOff: Boolean)
-
fun setAlternateVisible(isVisible: Boolean)
fun setAlternateBouncerUIAvailable(isAvailable: Boolean)
+
+ fun setSideFpsShowing(isShowing: Boolean)
}
@SysUISingleton
@@ -142,8 +143,6 @@ constructor(
override val panelExpansionAmount = _panelExpansionAmount.asStateFlow()
private val _keyguardPosition = MutableStateFlow(0f)
override val keyguardPosition = _keyguardPosition.asStateFlow()
- private val _onScreenTurnedOff = MutableStateFlow(false)
- override val onScreenTurnedOff = _onScreenTurnedOff.asStateFlow()
private val _isBackButtonEnabled = MutableStateFlow<Boolean?>(null)
override val isBackButtonEnabled = _isBackButtonEnabled.asStateFlow()
private val _keyguardAuthenticated = MutableStateFlow<Boolean?>(null)
@@ -165,6 +164,8 @@ constructor(
private val _alternateBouncerUIAvailable = MutableStateFlow(false)
override val alternateBouncerUIAvailable: StateFlow<Boolean> =
_alternateBouncerUIAvailable.asStateFlow()
+ private val _sideFpsShowing = MutableStateFlow(false)
+ override val sideFpsShowing: StateFlow<Boolean> = _sideFpsShowing.asStateFlow()
init {
setUpLogging()
@@ -235,8 +236,8 @@ constructor(
_isBackButtonEnabled.value = isBackButtonEnabled
}
- override fun setOnScreenTurnedOff(onScreenTurnedOff: Boolean) {
- _onScreenTurnedOff.value = onScreenTurnedOff
+ override fun setSideFpsShowing(isShowing: Boolean) {
+ _sideFpsShowing.value = isShowing
}
/** Sets up logs for state flows. */
@@ -276,9 +277,6 @@ constructor(
.map { it.toInt() }
.logDiffsForTable(buffer, "", "KeyguardPosition", -1)
.launchIn(applicationScope)
- onScreenTurnedOff
- .logDiffsForTable(buffer, "", "OnScreenTurnedOff", false)
- .launchIn(applicationScope)
isBackButtonEnabled
.filterNotNull()
.logDiffsForTable(buffer, "", "IsBackButtonEnabled", false)
@@ -293,6 +291,9 @@ constructor(
alternateBouncerUIAvailable
.logDiffsForTable(buffer, "", "IsAlternateBouncerUIAvailable", false)
.launchIn(applicationScope)
+ sideFpsShowing
+ .logDiffsForTable(buffer, "", "isSideFpsShowing", false)
+ .launchIn(applicationScope)
}
companion object {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManager.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManager.kt
index 2069891a23e0..a3268405a830 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManager.kt
@@ -18,6 +18,7 @@ package com.android.systemui.keyguard.data.repository
import android.app.StatusBarManager
import android.content.Context
+import android.hardware.face.FaceAuthenticateOptions
import android.hardware.face.FaceManager
import android.os.CancellationSignal
import com.android.internal.logging.InstanceId
@@ -235,8 +236,7 @@ constructor(
cancellationSignal,
faceAuthCallback,
null,
- currentUserId,
- lockscreenBypassEnabled
+ FaceAuthenticateOptions.Builder().setUserId(currentUserId).build()
)
}
}
@@ -255,7 +255,11 @@ constructor(
withContext(mainDispatcher) {
// We always want to invoke face detect in the main thread.
faceAuthLogger.faceDetectionStarted()
- faceManager?.detectFace(cancellationSignal, detectionCallback, currentUserId)
+ faceManager?.detectFace(
+ cancellationSignal,
+ detectionCallback,
+ FaceAuthenticateOptions.Builder().setUserId(currentUserId).build()
+ )
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
index dfbe1c216847..9b5f7f606c60 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardQuickAffordanceInteractor.kt
@@ -26,6 +26,7 @@ import com.android.systemui.animation.DialogLaunchAnimator
import com.android.systemui.animation.Expandable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.devicepolicy.areKeyguardShortcutsDisabled
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.quickaffordance.KeyguardQuickAffordanceConfig
@@ -410,16 +411,10 @@ constructor(
)
}
- private suspend fun isFeatureDisabledByDevicePolicy(): Boolean {
- val flags =
- withContext(backgroundDispatcher) {
- devicePolicyManager.getKeyguardDisabledFeatures(null, userTracker.userId)
- }
- val flagsToCheck =
- DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL or
- DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL
- return flagsToCheck and flags != 0
- }
+ private suspend fun isFeatureDisabledByDevicePolicy(): Boolean =
+ withContext(backgroundDispatcher) {
+ devicePolicyManager.areKeyguardShortcutsDisabled(userId = userTracker.userId)
+ }
companion object {
private const val TAG = "KeyguardQuickAffordanceInteractor"
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
index e819da9a50be..edd28972c05e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractor.kt
@@ -16,14 +16,19 @@
package com.android.systemui.keyguard.domain.interactor
+import android.content.Context
import android.content.res.ColorStateList
import android.hardware.biometrics.BiometricSourceType
import android.os.Handler
import android.os.Trace
import android.view.View
+import android.util.Log
+import com.android.keyguard.KeyguardConstants
import com.android.keyguard.KeyguardSecurityModel
import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.DejankUtils
+import com.android.systemui.R
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
@@ -60,8 +65,9 @@ constructor(
private val primaryBouncerCallbackInteractor: PrimaryBouncerCallbackInteractor,
private val falsingCollector: FalsingCollector,
private val dismissCallbackRegistry: DismissCallbackRegistry,
+ private val context: Context,
+ private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
keyguardBypassController: KeyguardBypassController,
- keyguardUpdateMonitor: KeyguardUpdateMonitor,
) {
/** Whether we want to wait for face auth. */
private val primaryBouncerFaceDelay =
@@ -88,7 +94,6 @@ constructor(
}
val keyguardAuthenticated: Flow<Boolean> = repository.keyguardAuthenticated.filterNotNull()
- val screenTurnedOff: Flow<Unit> = repository.onScreenTurnedOff.filter { it }.map {}
val show: Flow<KeyguardBouncerModel> = repository.primaryBouncerShow.filterNotNull()
val hide: Flow<Unit> = repository.primaryBouncerHide.filter { it }.map {}
val startingToHide: Flow<Unit> = repository.primaryBouncerStartingToHide.filter { it }.map {}
@@ -113,6 +118,24 @@ constructor(
}
/** Allow for interaction when just about fully visible */
val isInteractable: Flow<Boolean> = bouncerExpansion.map { it > 0.9 }
+ val sideFpsShowing: Flow<Boolean> = repository.sideFpsShowing
+
+ init {
+ keyguardUpdateMonitor.registerCallback(
+ object : KeyguardUpdateMonitorCallback() {
+ override fun onBiometricRunningStateChanged(
+ running: Boolean,
+ biometricSourceType: BiometricSourceType?
+ ) {
+ updateSideFpsVisibility()
+ }
+
+ override fun onStrongAuthStateChanged(userId: Int) {
+ updateSideFpsVisibility()
+ }
+ }
+ )
+ }
// TODO(b/243685699): Move isScrimmed logic to data layer.
// TODO(b/243695312): Encapsulate all of the show logic for the bouncer.
@@ -120,7 +143,6 @@ constructor(
@JvmOverloads
fun show(isScrimmed: Boolean) {
// Reset some states as we show the bouncer.
- repository.setOnScreenTurnedOff(false)
repository.setKeyguardAuthenticated(null)
repository.setPrimaryHide(false)
repository.setPrimaryStartingToHide(false)
@@ -254,11 +276,6 @@ constructor(
repository.setKeyguardAuthenticated(strongAuth)
}
- /** Tell the bouncer the screen has turned off. */
- fun onScreenTurnedOff() {
- repository.setOnScreenTurnedOff(true)
- }
-
/** Update the position of the bouncer when showing. */
fun setKeyguardPosition(position: Float) {
repository.setKeyguardPosition(position)
@@ -293,6 +310,35 @@ constructor(
repository.setPrimaryStartDisappearAnimation(finishRunnable)
}
+ /** Determine whether to show the side fps animation. */
+ fun updateSideFpsVisibility() {
+ val sfpsEnabled: Boolean =
+ context.resources.getBoolean(R.bool.config_show_sidefps_hint_on_bouncer)
+ val fpsDetectionRunning: Boolean = keyguardUpdateMonitor.isFingerprintDetectionRunning
+ val isUnlockingWithFpAllowed: Boolean =
+ keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed
+ val bouncerVisible = repository.primaryBouncerVisible.value
+ val toShow =
+ (repository.primaryBouncerVisible.value &&
+ sfpsEnabled &&
+ fpsDetectionRunning &&
+ isUnlockingWithFpAllowed &&
+ !isAnimatingAway())
+
+ if (KeyguardConstants.DEBUG) {
+ Log.d(
+ TAG,
+ ("sideFpsToShow=$toShow\n" +
+ "bouncerVisible=$bouncerVisible\n" +
+ "configEnabled=$sfpsEnabled\n" +
+ "fpsDetectionRunning=$fpsDetectionRunning\n" +
+ "isUnlockingWithFpAllowed=$isUnlockingWithFpAllowed\n" +
+ "isAnimatingAway=${isAnimatingAway()}")
+ )
+ }
+ repository.setSideFpsShowing(toShow)
+ }
+
/** Returns whether bouncer is fully showing. */
fun isFullyShowing(): Boolean {
return (repository.primaryBouncerShowingSoon.value ||
@@ -336,4 +382,8 @@ constructor(
DejankUtils.removeCallbacks(showRunnable)
mainHandler.removeCallbacks(showRunnable)
}
+
+ companion object {
+ private const val TAG = "PrimaryBouncerInteractor"
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
index 56f911f8b1da..7db567b2a0e9 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardBouncerViewBinder.kt
@@ -34,6 +34,7 @@ import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.plugins.ActivityStarter
import kotlinx.coroutines.awaitCancellation
+import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
@@ -121,7 +122,6 @@ object KeyguardBouncerViewBinder {
launch {
viewModel.hide.collect {
securityContainerController.cancelDismissAction()
- securityContainerController.onPause()
securityContainerController.reset()
}
}
@@ -155,13 +155,18 @@ object KeyguardBouncerViewBinder {
launch {
viewModel.isBouncerVisible.collect { isVisible ->
- val visibility = if (isVisible) View.VISIBLE else View.INVISIBLE
- view.visibility = visibility
- securityContainerController.onBouncerVisibilityChanged(visibility)
+ view.visibility = if (isVisible) View.VISIBLE else View.INVISIBLE
+ securityContainerController.onBouncerVisibilityChanged(isVisible)
}
}
launch {
+ viewModel.isBouncerVisible
+ .filter { !it }
+ .collect { securityContainerController.onPause() }
+ }
+
+ launch {
viewModel.isInteractable.collect { isInteractable ->
securityContainerController.setInteractable(isInteractable)
}
@@ -204,10 +209,14 @@ object KeyguardBouncerViewBinder {
}
launch {
- viewModel.screenTurnedOff.collect {
- if (view.visibility == View.VISIBLE) {
- securityContainerController.onPause()
- }
+ viewModel.shouldUpdateSideFps.collect {
+ viewModel.updateSideFpsVisibility()
+ }
+ }
+
+ launch {
+ viewModel.sideFpsShowing.collect {
+ securityContainerController.updateSideFpsVisibility(it)
}
}
awaitCancellation()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt
index b8b3a8e5db20..97e94d8f3232 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModel.kt
@@ -24,7 +24,9 @@ import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.merge
/** Models UI state for the lock screen bouncer; handles user input. */
class KeyguardBouncerViewModel
@@ -66,8 +68,16 @@ constructor(
/** Observe whether keyguard is authenticated already. */
val keyguardAuthenticated: Flow<Boolean> = interactor.keyguardAuthenticated
- /** Observe whether screen is turned off. */
- val screenTurnedOff: Flow<Unit> = interactor.screenTurnedOff
+ /** Observe whether the side fps is showing. */
+ val sideFpsShowing: Flow<Boolean> = interactor.sideFpsShowing
+
+ /** Observe whether we should update fps is showing. */
+ val shouldUpdateSideFps: Flow<Unit> =
+ merge(
+ interactor.startingToHide,
+ interactor.isVisible.map {},
+ interactor.startingDisappearAnimation.filterNotNull().map {}
+ )
/** Observe whether we want to update resources. */
fun notifyUpdateResources() {
@@ -84,6 +94,10 @@ constructor(
interactor.onMessageShown()
}
+ fun updateSideFpsVisibility() {
+ interactor.updateSideFpsVisibility()
+ }
+
/** Observe whether back button is enabled. */
fun observeOnIsBackButtonEnabled(systemUiVisibility: () -> Int): Flow<Int> {
return interactor.isBackButtonEnabled.map { enabled ->
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt b/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt
index dc7a4f18adbc..0b57175defe7 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/models/recommendation/SmartspaceMediaData.kt
@@ -88,6 +88,8 @@ data class SmartspaceMediaData(
}
}
+/** Key to indicate whether this card should be used to re-show recent media */
+const val EXTRA_KEY_TRIGGER_RESUME = "SHOULD_TRIGGER_RESUME"
/** Key for extras [SmartspaceMediaData.cardAction] indicating why the card was sent */
const val EXTRA_KEY_TRIGGER_SOURCE = "MEDIA_RECOMMENDATION_TRIGGER_SOURCE"
/** Value for [EXTRA_KEY_TRIGGER_SOURCE] when the card is sent on headphone connection */
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt
index 27f7b9736807..97717a64ce26 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/pipeline/MediaDataFilter.kt
@@ -23,6 +23,7 @@ import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.broadcast.BroadcastSender
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.media.controls.models.player.MediaData
+import com.android.systemui.media.controls.models.recommendation.EXTRA_KEY_TRIGGER_RESUME
import com.android.systemui.media.controls.models.recommendation.SmartspaceMediaData
import com.android.systemui.media.controls.util.MediaFlags
import com.android.systemui.media.controls.util.MediaUiEventLogger
@@ -138,14 +139,23 @@ constructor(
val sorted = userEntries.toSortedMap(compareBy { userEntries.get(it)?.lastActive ?: -1 })
val timeSinceActive = timeSinceActiveForMostRecentMedia(sorted)
var smartspaceMaxAgeMillis = SMARTSPACE_MAX_AGE
- data.cardAction?.let {
- val smartspaceMaxAgeSeconds = it.extras.getLong(RESUMABLE_MEDIA_MAX_AGE_SECONDS_KEY, 0)
+ data.cardAction?.extras?.let {
+ val smartspaceMaxAgeSeconds = it.getLong(RESUMABLE_MEDIA_MAX_AGE_SECONDS_KEY, 0)
if (smartspaceMaxAgeSeconds > 0) {
smartspaceMaxAgeMillis = TimeUnit.SECONDS.toMillis(smartspaceMaxAgeSeconds)
}
}
- val shouldReactivate = !hasActiveMedia() && hasAnyMedia() && data.isActive
+ // Check if smartspace has explicitly specified whether to re-activate resumable media.
+ // The default behavior is to trigger if the smartspace data is active.
+ val shouldTriggerResume =
+ if (data.cardAction?.extras?.containsKey(EXTRA_KEY_TRIGGER_RESUME) == true) {
+ data.cardAction.extras.getBoolean(EXTRA_KEY_TRIGGER_RESUME, true)
+ } else {
+ true
+ }
+ val shouldReactivate =
+ shouldTriggerResume && !hasActiveMedia() && hasAnyMedia() && data.isActive
if (timeSinceActive < smartspaceMaxAgeMillis) {
// It could happen there are existing active media resume cards, then we don't need to
diff --git a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt
index 4ff082ad6e06..0b0535df6228 100644
--- a/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/taptotransfer/receiver/ReceiverChipRippleView.kt
@@ -98,7 +98,7 @@ class ReceiverChipRippleView(context: Context?, attrs: AttributeSet?) : RippleVi
// Calculates the actual starting percentage according to ripple shader progress set method.
// Check calculations in [RippleShader.progress]
fun calculateStartingPercentage(newHeight: Float): Float {
- val ratio = rippleShader.currentHeight / newHeight
+ val ratio = rippleShader.rippleSize.currentHeight / newHeight
val remainingPercentage = (1 - ratio).toDouble().pow(1 / 3.toDouble()).toFloat()
return 1 - remainingPercentage
}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
index c3d736917b5d..f1a5c3e8ef43 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/TaskbarDelegate.java
@@ -75,6 +75,7 @@ import com.android.systemui.statusbar.phone.AutoHideController;
import com.android.systemui.statusbar.phone.BarTransitions;
import com.android.systemui.statusbar.phone.LightBarController;
import com.android.systemui.statusbar.phone.LightBarTransitionsController;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.wm.shell.back.BackAnimation;
import com.android.wm.shell.pip.Pip;
@@ -166,16 +167,20 @@ public class TaskbarDelegate implements CommandQueue.Callbacks,
private BackAnimation mBackAnimation;
+ private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@Inject
public TaskbarDelegate(Context context,
EdgeBackGestureHandler.Factory edgeBackGestureHandlerFactory,
- LightBarTransitionsController.Factory lightBarTransitionsControllerFactory) {
+ LightBarTransitionsController.Factory lightBarTransitionsControllerFactory,
+ StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
mLightBarTransitionsControllerFactory = lightBarTransitionsControllerFactory;
mEdgeBackGestureHandler = edgeBackGestureHandlerFactory.create(context);
mContext = context;
mDisplayManager = mContext.getSystemService(DisplayManager.class);
mPipListener = mEdgeBackGestureHandler::setPipStashExclusionBounds;
+ mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
+ mStatusBarKeyguardViewManager.setTaskbarDelegate(this);
}
public void setDependencies(CommandQueue commandQueue,
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index 389034af8a33..f3d60145a057 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -580,7 +580,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
}
// Register input event receiver
- mInputMonitor = InputManager.getInstance().monitorGestureInput(
+ mInputMonitor = mContext.getSystemService(InputManager.class).monitorGestureInput(
"edge-swipe", mDisplayId);
mInputEventReceiver = new InputChannelCompat.InputEventReceiver(
mInputMonitor.getInputChannel(), Looper.getMainLooper(),
@@ -1039,7 +1039,7 @@ public class EdgeBackGestureHandler implements PluginListener<NavigationEdgeBack
InputDevice.SOURCE_KEYBOARD);
ev.setDisplayId(mContext.getDisplay().getDisplayId());
- return InputManager.getInstance()
+ return mContext.getSystemService(InputManager.class)
.injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
}
diff --git a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
index be615d63a3d7..5702681d9240 100644
--- a/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
+++ b/packages/SystemUI/src/com/android/systemui/notetask/NoteTaskController.kt
@@ -17,17 +17,21 @@
package com.android.systemui.notetask
import android.app.KeyguardManager
+import android.app.admin.DevicePolicyManager
import android.content.ActivityNotFoundException
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
+import android.os.Build
import android.os.UserManager
import android.util.Log
import com.android.internal.logging.UiEvent
import com.android.internal.logging.UiEventLogger
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.devicepolicy.areKeyguardShortcutsDisabled
import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
+import com.android.systemui.settings.UserTracker
import com.android.systemui.util.kotlin.getOrNull
import com.android.wm.shell.bubbles.Bubbles
import java.util.Optional
@@ -49,8 +53,10 @@ constructor(
private val optionalBubbles: Optional<Bubbles>,
private val optionalKeyguardManager: Optional<KeyguardManager>,
private val optionalUserManager: Optional<UserManager>,
+ private val devicePolicyManager: DevicePolicyManager,
@NoteTaskEnabledKey private val isEnabled: Boolean,
private val uiEventLogger: UiEventLogger,
+ private val userTracker: UserTracker,
) {
/**
@@ -80,6 +86,18 @@ constructor(
// TODO(b/249954038): We should handle direct boot (isUserUnlocked). For now, we do nothing.
if (!userManager.isUserUnlocked) return
+ val isKeyguardLocked = keyguardManager.isKeyguardLocked
+ // KeyguardQuickAffordanceInteractor blocks the quick affordance from showing in the
+ // keyguard if it is not allowed by the admin policy. Here we block any other way to show
+ // note task when the screen is locked.
+ if (
+ isKeyguardLocked &&
+ devicePolicyManager.areKeyguardShortcutsDisabled(userId = userTracker.userId)
+ ) {
+ logDebug { "Enterprise policy disallows launching note app when the screen is locked." }
+ return
+ }
+
val noteTaskInfo = resolver.resolveInfo() ?: return
uiEvent?.let { uiEventLogger.log(it, noteTaskInfo.uid, noteTaskInfo.packageName) }
@@ -87,7 +105,7 @@ constructor(
// TODO(b/266686199): We should handle when app not available. For now, we log.
val intent = noteTaskInfo.toCreateNoteIntent()
try {
- if (isInMultiWindowMode || keyguardManager.isKeyguardLocked) {
+ if (isInMultiWindowMode || isKeyguardLocked) {
context.startActivity(intent)
} else {
bubbles.showOrHideAppBubble(intent)
@@ -144,7 +162,7 @@ constructor(
}
companion object {
- private val TAG = NoteTaskController::class.simpleName.orEmpty()
+ val TAG = NoteTaskController::class.simpleName.orEmpty()
private fun NoteTaskInfoResolver.NoteTaskInfo.toCreateNoteIntent(): Intent {
return Intent(ACTION_CREATE_NOTE)
@@ -165,3 +183,9 @@ constructor(
const val INTENT_EXTRA_USE_STYLUS_MODE = "android.intent.extra.USE_STYLUS_MODE"
}
}
+
+private inline fun logDebug(message: () -> String) {
+ if (Build.IS_DEBUGGABLE) {
+ Log.d(NoteTaskController.TAG, message())
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/process/ProcessWrapper.java b/packages/SystemUI/src/com/android/systemui/process/ProcessWrapper.java
index 245cf89a8337..27510720ae2f 100644
--- a/packages/SystemUI/src/com/android/systemui/process/ProcessWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/process/ProcessWrapper.java
@@ -26,7 +26,10 @@ public class ProcessWrapper {
@Inject
public ProcessWrapper() {}
- public int getUserHandleIdentifier() {
- return android.os.Process.myUserHandle().getIdentifier();
+ /**
+ * Returns {@code true} if System User is running the current process.
+ */
+ public boolean isSystemUser() {
+ return android.os.Process.myUserHandle().isSystem();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/process/condition/UserProcessCondition.java b/packages/SystemUI/src/com/android/systemui/process/condition/SystemProcessCondition.java
index 5a21ea075ea3..80fbf9115065 100644
--- a/packages/SystemUI/src/com/android/systemui/process/condition/UserProcessCondition.java
+++ b/packages/SystemUI/src/com/android/systemui/process/condition/SystemProcessCondition.java
@@ -17,29 +17,26 @@
package com.android.systemui.process.condition;
import com.android.systemui.process.ProcessWrapper;
-import com.android.systemui.settings.UserTracker;
import com.android.systemui.shared.condition.Condition;
import javax.inject.Inject;
/**
- * {@link UserProcessCondition} provides a signal when the process handle belongs to the current
- * user.
+ * {@link SystemProcessCondition} checks to make sure the current process is being ran by the
+ * System User.
*/
-public class UserProcessCondition extends Condition {
+public class SystemProcessCondition extends Condition {
private final ProcessWrapper mProcessWrapper;
- private final UserTracker mUserTracker;
@Inject
- public UserProcessCondition(ProcessWrapper processWrapper, UserTracker userTracker) {
+ public SystemProcessCondition(ProcessWrapper processWrapper) {
+ super();
mProcessWrapper = processWrapper;
- mUserTracker = userTracker;
}
@Override
protected void start() {
- updateCondition(mUserTracker.getUserId()
- == mProcessWrapper.getUserHandleIdentifier());
+ updateCondition(mProcessWrapper.isSystemUser());
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index b673f0e6813c..d1f02dceb292 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -50,9 +50,7 @@ import com.android.systemui.animation.Interpolators;
import com.android.systemui.animation.ShadeInterpolation;
import com.android.systemui.compose.ComposeFacade;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.media.controls.ui.MediaHost;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.plugins.qs.QSContainerController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -60,6 +58,7 @@ import com.android.systemui.qs.customize.QSCustomizerController;
import com.android.systemui.qs.dagger.QSFragmentComponent;
import com.android.systemui.qs.footer.ui.binder.FooterActionsViewBinder;
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel;
+import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -87,14 +86,11 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
private final Rect mQsBounds = new Rect();
private final SysuiStatusBarStateController mStatusBarStateController;
- private final FalsingManager mFalsingManager;
private final KeyguardBypassController mBypassController;
private boolean mQsExpanded;
private boolean mHeaderAnimating;
private boolean mStackScrollerOverscrolling;
- private long mDelay;
-
private QSAnimator mQSAnimator;
private HeightListener mPanelView;
private QSSquishinessController mQSSquishinessController;
@@ -115,8 +111,7 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
private final MediaHost mQqsMediaHost;
private final QSFragmentComponent.Factory mQsComponentFactory;
private final QSFragmentDisableFlagsLogger mQsFragmentDisableFlagsLogger;
- private final QSTileHost mHost;
- private final FeatureFlags mFeatureFlags;
+ private final QSLogger mLogger;
private final FooterActionsController mFooterActionsController;
private final FooterActionsViewModel.Factory mFooterActionsViewModelFactory;
private final ListeningAndVisibilityLifecycleOwner mListeningAndVisibilityLifecycleOwner;
@@ -149,11 +144,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
*/
private boolean mTransitioningToFullShade;
- /**
- * Whether the next Quick settings
- */
- private boolean mAnimateNextQsUpdate;
-
private final DumpManager mDumpManager;
/**
@@ -177,14 +167,13 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
@Inject
public QSFragment(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,
- QSTileHost qsTileHost,
SysuiStatusBarStateController statusBarStateController, CommandQueue commandQueue,
@Named(QS_PANEL) MediaHost qsMediaHost,
@Named(QUICK_QS_PANEL) MediaHost qqsMediaHost,
KeyguardBypassController keyguardBypassController,
QSFragmentComponent.Factory qsComponentFactory,
QSFragmentDisableFlagsLogger qsFragmentDisableFlagsLogger,
- FalsingManager falsingManager, DumpManager dumpManager, FeatureFlags featureFlags,
+ DumpManager dumpManager, QSLogger qsLogger,
FooterActionsController footerActionsController,
FooterActionsViewModel.Factory footerActionsViewModelFactory) {
mRemoteInputQuickSettingsDisabler = remoteInputQsDisabler;
@@ -192,13 +181,11 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
mQqsMediaHost = qqsMediaHost;
mQsComponentFactory = qsComponentFactory;
mQsFragmentDisableFlagsLogger = qsFragmentDisableFlagsLogger;
+ mLogger = qsLogger;
commandQueue.observe(getLifecycle(), this);
- mHost = qsTileHost;
- mFalsingManager = falsingManager;
mBypassController = keyguardBypassController;
mStatusBarStateController = statusBarStateController;
mDumpManager = dumpManager;
- mFeatureFlags = featureFlags;
mFooterActionsController = footerActionsController;
mFooterActionsViewModelFactory = footerActionsViewModelFactory;
mListeningAndVisibilityLifecycleOwner = new ListeningAndVisibilityLifecycleOwner();
@@ -715,8 +702,10 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
private void setAlphaAnimationProgress(float progress) {
final View view = getView();
if (progress == 0 && view.getVisibility() != View.INVISIBLE) {
+ mLogger.logVisibility("QS fragment", View.INVISIBLE);
view.setVisibility(View.INVISIBLE);
} else if (progress > 0 && view.getVisibility() != View.VISIBLE) {
+ mLogger.logVisibility("QS fragment", View.VISIBLE);
view.setVisibility((View.VISIBLE));
}
view.setAlpha(interpolateAlphaAnimationProgress(progress));
@@ -913,7 +902,6 @@ public class QSFragment extends LifecycleFragment implements QS, CommandQueue.Ca
getView().getViewTreeObserver().removeOnPreDrawListener(this);
getView().animate()
.translationY(0f)
- .setStartDelay(mDelay)
.setDuration(StackStateAnimator.ANIMATION_DURATION_GO_TO_FULL_SHADE)
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.setListener(mAnimateHeaderSlidingInListener)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt b/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
index d32ef327e90e..23c41db6d5a6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/logging/QSLogger.kt
@@ -17,15 +17,14 @@
package com.android.systemui.qs.logging
import android.service.quicksettings.Tile
+import android.view.View
import com.android.systemui.log.dagger.QSLog
import com.android.systemui.plugins.log.ConstantStringsLogger
import com.android.systemui.plugins.log.ConstantStringsLoggerImpl
import com.android.systemui.plugins.log.LogBuffer
-import com.android.systemui.plugins.log.LogLevel
import com.android.systemui.plugins.log.LogLevel.DEBUG
import com.android.systemui.plugins.log.LogLevel.ERROR
import com.android.systemui.plugins.log.LogLevel.VERBOSE
-import com.android.systemui.plugins.log.LogMessage
import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.statusbar.StatusBarState
import com.google.errorprone.annotations.CompileTimeConstant
@@ -332,4 +331,25 @@ class QSLogger @Inject constructor(@QSLog private val buffer: LogBuffer) :
else -> "wrong state"
}
}
+
+ fun logVisibility(viewName: String, @View.Visibility visibility: Int) {
+ buffer.log(
+ TAG,
+ DEBUG,
+ {
+ str1 = viewName
+ str2 = toVisibilityString(visibility)
+ },
+ { "$str1 visibility: $str2" }
+ )
+ }
+
+ private fun toVisibilityString(visibility: Int): String {
+ return when (visibility) {
+ View.VISIBLE -> "VISIBLE"
+ View.INVISIBLE -> "INVISIBLE"
+ View.GONE -> "GONE"
+ else -> "undefined"
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 5ed11c2ee7e7..a5da06e3f1e5 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -1197,6 +1197,7 @@ public final class NotificationPanelViewController implements Dumpable {
}
private void onSplitShadeEnabledChanged() {
+ mShadeLog.logSplitShadeChanged(mSplitShadeEnabled);
// when we switch between split shade and regular shade we want to enforce setting qs to
// the default state: expanded for split shade and collapsed otherwise
if (!isOnKeyguard() && mPanelExpanded) {
@@ -1777,7 +1778,7 @@ public final class NotificationPanelViewController implements Dumpable {
if (animate && !isFullyCollapsed()) {
animateCloseQs(true);
} else {
- mQsController.closeQs();
+ closeQsIfPossible();
}
mNotificationStackScrollLayoutController.setOverScrollAmount(0f, true /* onTop */, animate,
!animate /* cancelAnimators */);
@@ -1914,7 +1915,6 @@ public final class NotificationPanelViewController implements Dumpable {
// we want to perform an overshoot animation when flinging open
final boolean addOverscroll =
expand
- && !mSplitShadeEnabled // Split shade has its own overscroll logic
&& mStatusBarStateController.getState() != KEYGUARD
&& mOverExpansion == 0.0f
&& vel >= 0;
@@ -2206,7 +2206,12 @@ public final class NotificationPanelViewController implements Dumpable {
&& mQsController.getFullyExpanded()) {
// Upon initialisation when we are not layouted yet we don't want to announce that we
// are fully expanded, hence the != 0.0f check.
- return mResources.getString(R.string.accessibility_desc_quick_settings);
+ if (mSplitShadeEnabled) {
+ // In split shade, QS is expanded but it also shows notifications
+ return mResources.getString(R.string.accessibility_desc_qs_notification_shade);
+ } else {
+ return mResources.getString(R.string.accessibility_desc_quick_settings);
+ }
} else if (mBarState == KEYGUARD) {
return mResources.getString(R.string.accessibility_desc_lock_screen);
} else {
@@ -2585,9 +2590,14 @@ public final class NotificationPanelViewController implements Dumpable {
return;
}
mOverExpansion = overExpansion;
- // Translating the quick settings by half the overexpansion to center it in the background
- // frame
- mQsController.updateQsFrameTranslation();
+ if (mSplitShadeEnabled) {
+ mQsController.setOverScrollAmount((int) overExpansion);
+ mScrimController.setNotificationsOverScrollAmount((int) overExpansion);
+ } else {
+ // Translating the quick settings by half the overexpansion to center it in the
+ // background frame
+ mQsController.updateQsFrameTranslation();
+ }
mNotificationStackScrollLayoutController.setOverExpansion(overExpansion);
}
@@ -3589,7 +3599,7 @@ public final class NotificationPanelViewController implements Dumpable {
private void fling(float vel, boolean expand, float collapseSpeedUpFactor,
boolean expandBecauseOfFalsing) {
- float target = expand ? getMaxPanelHeight() : 0;
+ float target = expand ? getMaxPanelTransitionDistance() : 0;
if (!expand) {
setClosing(true);
}
@@ -3674,7 +3684,7 @@ public final class NotificationPanelViewController implements Dumpable {
float maxPanelHeight = getMaxPanelTransitionDistance();
if (mHeightAnimator == null) {
// Split shade has its own overscroll logic
- if (mTracking && !mSplitShadeEnabled) {
+ if (mTracking) {
float overExpansionPixels = Math.max(0, h - maxPanelHeight);
setOverExpansionInternal(overExpansionPixels, true /* isFromGesture */);
}
@@ -4020,9 +4030,17 @@ public final class NotificationPanelViewController implements Dumpable {
return mExpandingFromHeadsUp;
}
- /** TODO: remove need for this delegate (b/254870148) */
- public void closeQs() {
- mQsController.closeQs();
+ /**
+ * We don't always want to close QS when requested as shade might be in a different state
+ * already e.g. when going from collapse to expand very quickly. In that case StatusBar
+ * window might send signal to collapse QS but we might be already expanding and in split
+ * shade QS are always expanded
+ */
+ private void closeQsIfPossible() {
+ boolean openOrOpening = isShadeFullyOpen() || isExpanding();
+ if (!(mSplitShadeEnabled && openOrOpening)) {
+ mQsController.closeQs();
+ }
}
/** TODO: remove need for this delegate (b/254870148) */
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
index f7126291c7f0..2b6327f3eedf 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
@@ -16,7 +16,7 @@
package com.android.systemui.shade;
-import static android.os.Trace.TRACE_TAG_ALWAYS;
+import static android.os.Trace.TRACE_TAG_APP;
import static android.view.WindowInsets.Type.systemBars;
import static com.android.systemui.statusbar.phone.CentralSurfaces.DEBUG;
@@ -328,7 +328,7 @@ public class NotificationShadeWindowView extends FrameLayout {
@Override
public void requestLayout() {
- Trace.instant(TRACE_TAG_ALWAYS, "NotificationShadeWindowView#requestLayout");
+ Trace.instant(TRACE_TAG_APP, "NotificationShadeWindowView#requestLayout");
super.requestLayout();
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
index c0ef4c1a872a..a8378df81968 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/QuickSettingsController.java
@@ -663,8 +663,15 @@ public class QuickSettingsController {
mDozing = dozing;
}
- /** set QS state to closed */
+ /**
+ * This method closes QS but in split shade it should be used only in special cases: to make
+ * sure QS closes when shade is closed as well. Otherwise it will result in QS disappearing
+ * from split shade
+ */
public void closeQs() {
+ if (mSplitShadeEnabled) {
+ mShadeLog.d("Closing QS while in split shade");
+ }
cancelExpansionAnimation();
setExpansionHeight(getMinExpansionHeight());
// qsExpandImmediate is a safety latch in case we're calling closeQS while we're in the
@@ -803,6 +810,10 @@ public class QuickSettingsController {
}
}
+ void setOverScrollAmount(int overExpansion) {
+ mQs.setOverScrollAmount(overExpansion);
+ }
+
private void setOverScrolling(boolean overscrolling) {
mStackScrollerOverscrolling = overscrolling;
if (mQs != null) {
@@ -835,6 +846,7 @@ public class QuickSettingsController {
@VisibleForTesting
void setExpandImmediate(boolean expandImmediate) {
if (expandImmediate != mExpandImmediate) {
+ mShadeLog.logQsExpandImmediateChanged(expandImmediate);
mExpandImmediate = expandImmediate;
mShadeExpansionStateManager.notifyExpandImmediateChange(expandImmediate);
}
@@ -1377,6 +1389,9 @@ public class QuickSettingsController {
}
private void collapseOrExpandQs() {
+ if (mSplitShadeEnabled) {
+ return; // QS is always expanded in split shade
+ }
onExpansionStarted();
if (getExpanded()) {
flingQs(0, FLING_COLLAPSE, null, true);
@@ -1706,12 +1721,16 @@ public class QuickSettingsController {
*/
private void flingQs(float vel, int type, final Runnable onFinishRunnable,
boolean isClick) {
+ mShadeLog.flingQs(type, isClick);
float target;
switch (type) {
case FLING_EXPAND:
target = getMaxExpansionHeight();
break;
case FLING_COLLAPSE:
+ if (mSplitShadeEnabled) { // TODO:(b/269742565) remove below log
+ Log.wtfStack(TAG, "FLING_COLLAPSE called in split shade");
+ }
target = getMinExpansionHeight();
break;
case FLING_HIDE:
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
index 026673adb86b..c1369935db54 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerImpl.java
@@ -270,8 +270,6 @@ public final class ShadeControllerImpl implements ShadeController {
// Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868)
mNotificationPanelViewController.collapsePanel(false, false, 1.0f);
- mNotificationPanelViewController.closeQs();
-
mExpandedVisible = false;
notifyVisibilityChanged(false);
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
index b28509e8fbf5..d34e127b194b 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeLogger.kt
@@ -20,6 +20,9 @@ import android.view.MotionEvent
import com.android.systemui.log.dagger.ShadeLog
import com.android.systemui.plugins.log.LogBuffer
import com.android.systemui.plugins.log.LogLevel
+import com.android.systemui.shade.NotificationPanelViewController.FLING_COLLAPSE
+import com.android.systemui.shade.NotificationPanelViewController.FLING_EXPAND
+import com.android.systemui.shade.NotificationPanelViewController.FLING_HIDE
import com.google.errorprone.annotations.CompileTimeConstant
import javax.inject.Inject
@@ -150,6 +153,17 @@ class ShadeLogger @Inject constructor(@ShadeLog private val buffer: LogBuffer) {
)
}
+ fun logQsExpandImmediateChanged(newValue: Boolean) {
+ buffer.log(
+ TAG,
+ LogLevel.VERBOSE,
+ {
+ bool1 = newValue
+ },
+ { "qsExpandImmediate=$bool1" }
+ )
+ }
+
fun logQsExpansionChanged(
message: String,
qsExpanded: Boolean,
@@ -230,18 +244,40 @@ class ShadeLogger @Inject constructor(@ShadeLog private val buffer: LogBuffer) {
)
}
- fun logLastFlingWasExpanding(
- expand: Boolean
- ) {
+ fun logLastFlingWasExpanding(expand: Boolean) {
buffer.log(
- TAG,
- LogLevel.VERBOSE,
- {
- bool1 = expand
- },
- {
- "NPVC mLastFlingWasExpanding set to: $bool1"
- }
+ TAG,
+ LogLevel.VERBOSE,
+ { bool1 = expand },
+ { "NPVC mLastFlingWasExpanding set to: $bool1" }
+ )
+ }
+
+ fun flingQs(flingType: Int, isClick: Boolean) {
+ buffer.log(
+ TAG,
+ LogLevel.VERBOSE,
+ {
+ str1 = flingTypeToString(flingType)
+ bool1 = isClick
+ },
+ { "QS fling with type $str1, originated from click: $isClick" }
+ )
+ }
+
+ private fun flingTypeToString(flingType: Int) = when (flingType) {
+ FLING_EXPAND -> "FLING_EXPAND"
+ FLING_COLLAPSE -> "FLING_COLLAPSE"
+ FLING_HIDE -> "FLING_HIDE"
+ else -> "UNKNOWN"
+ }
+
+ fun logSplitShadeChanged(splitShadeEnabled: Boolean) {
+ buffer.log(
+ TAG,
+ LogLevel.VERBOSE,
+ { bool1 = splitShadeEnabled },
+ { "Split shade state changed: split shade ${if (bool1) "enabled" else "disabled"}" }
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt
index 07820ecd513e..129d09ec3c14 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/transition/ShadeTransitionController.kt
@@ -43,8 +43,6 @@ constructor(
shadeExpansionStateManager: ShadeExpansionStateManager,
dumpManager: DumpManager,
private val context: Context,
- private val splitShadeOverScrollerFactory: SplitShadeOverScroller.Factory,
- private val noOpOverScroller: NoOpOverScroller,
private val scrimShadeTransitionController: ScrimShadeTransitionController,
private val statusBarStateController: SysuiStatusBarStateController,
) {
@@ -57,17 +55,6 @@ constructor(
private var currentPanelState: Int? = null
private var lastShadeExpansionChangeEvent: ShadeExpansionChangeEvent? = null
- private val splitShadeOverScroller by lazy {
- splitShadeOverScrollerFactory.create({ qs }, { notificationStackScrollLayoutController })
- }
- private val shadeOverScroller: ShadeOverScroller
- get() =
- if (inSplitShade && isScreenUnlocked() && propertiesInitialized()) {
- splitShadeOverScroller
- } else {
- noOpOverScroller
- }
-
init {
updateResources()
configurationController.addCallback(
@@ -89,21 +76,14 @@ constructor(
private fun onPanelStateChanged(@PanelState state: Int) {
currentPanelState = state
- shadeOverScroller.onPanelStateChanged(state)
scrimShadeTransitionController.onPanelStateChanged(state)
}
private fun onPanelExpansionChanged(event: ShadeExpansionChangeEvent) {
lastShadeExpansionChangeEvent = event
- shadeOverScroller.onDragDownAmountChanged(event.dragDownPxAmount)
scrimShadeTransitionController.onPanelExpansionChanged(event)
}
- private fun propertiesInitialized() =
- this::qs.isInitialized &&
- this::notificationPanelViewController.isInitialized &&
- this::notificationStackScrollLayoutController.isInitialized
-
private fun dump(pw: PrintWriter) {
pw.println(
"""
diff --git a/packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeOverScroller.kt b/packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeOverScroller.kt
deleted file mode 100644
index f95125f5cb6c..000000000000
--- a/packages/SystemUI/src/com/android/systemui/shade/transition/SplitShadeOverScroller.kt
+++ /dev/null
@@ -1,167 +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.shade.transition
-
-import android.animation.Animator
-import android.animation.ValueAnimator
-import android.content.Context
-import android.content.res.Configuration
-import android.util.MathUtils
-import com.android.internal.annotations.VisibleForTesting
-import com.android.systemui.R
-import com.android.systemui.animation.Interpolators
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.plugins.qs.QS
-import com.android.systemui.shade.PanelState
-import com.android.systemui.shade.STATE_CLOSED
-import com.android.systemui.shade.STATE_OPENING
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
-import com.android.systemui.statusbar.phone.ScrimController
-import com.android.systemui.statusbar.policy.ConfigurationController
-import dagger.assisted.Assisted
-import dagger.assisted.AssistedFactory
-import dagger.assisted.AssistedInject
-import java.io.PrintWriter
-
-class SplitShadeOverScroller
-@AssistedInject
-constructor(
- configurationController: ConfigurationController,
- dumpManager: DumpManager,
- private val context: Context,
- private val scrimController: ScrimController,
- @Assisted private val qSProvider: () -> QS,
- @Assisted private val nsslControllerProvider: () -> NotificationStackScrollLayoutController
-) : ShadeOverScroller {
-
- private var releaseOverScrollDuration = 0L
- private var maxOverScrollAmount = 0
- private var previousOverscrollAmount = 0
- private var dragDownAmount: Float = 0f
- @PanelState private var panelState: Int = STATE_CLOSED
-
- private var releaseOverScrollAnimator: Animator? = null
-
- private val qS: QS
- get() = qSProvider()
-
- private val nsslController: NotificationStackScrollLayoutController
- get() = nsslControllerProvider()
-
- init {
- updateResources()
- configurationController.addCallback(
- object : ConfigurationController.ConfigurationListener {
- override fun onConfigChanged(newConfig: Configuration?) {
- updateResources()
- }
- })
- dumpManager.registerCriticalDumpable("SplitShadeOverScroller") { printWriter, _ ->
- dump(printWriter)
- }
- }
-
- private fun updateResources() {
- val resources = context.resources
- maxOverScrollAmount = resources.getDimensionPixelSize(R.dimen.shade_max_over_scroll_amount)
- releaseOverScrollDuration =
- resources.getInteger(R.integer.lockscreen_shade_over_scroll_release_duration).toLong()
- }
-
- override fun onPanelStateChanged(@PanelState newPanelState: Int) {
- if (shouldReleaseOverscroll(previousState = panelState, newState = newPanelState)) {
- releaseOverScroll()
- }
- panelState = newPanelState
- }
-
- override fun onDragDownAmountChanged(newDragDownAmount: Float) {
- if (dragDownAmount == newDragDownAmount) {
- return
- }
- dragDownAmount = newDragDownAmount
- if (shouldOverscroll()) {
- overScroll(newDragDownAmount)
- }
- }
-
- private fun shouldOverscroll() = panelState == STATE_OPENING
-
- private fun shouldReleaseOverscroll(@PanelState previousState: Int, @PanelState newState: Int) =
- previousState == STATE_OPENING && newState != STATE_OPENING
-
- private fun overScroll(dragDownAmount: Float) {
- val overscrollAmount: Int = calculateOverscrollAmount(dragDownAmount)
- applyOverscroll(overscrollAmount)
- previousOverscrollAmount = overscrollAmount
- }
-
- private fun calculateOverscrollAmount(dragDownAmount: Float): Int {
- val fullHeight: Int = nsslController.height
- val fullHeightProgress: Float = MathUtils.saturate(dragDownAmount / fullHeight)
- return (fullHeightProgress * maxOverScrollAmount).toInt()
- }
-
- private fun applyOverscroll(overscrollAmount: Int) {
- qS.setOverScrollAmount(overscrollAmount)
- scrimController.setNotificationsOverScrollAmount(overscrollAmount)
- nsslController.setOverScrollAmount(overscrollAmount)
- }
-
- private fun releaseOverScroll() {
- val animator = ValueAnimator.ofInt(previousOverscrollAmount, 0)
- animator.addUpdateListener {
- val overScrollAmount = it.animatedValue as Int
- qS.setOverScrollAmount(overScrollAmount)
- scrimController.setNotificationsOverScrollAmount(overScrollAmount)
- nsslController.setOverScrollAmount(overScrollAmount)
- }
- animator.interpolator = Interpolators.STANDARD
- animator.duration = releaseOverScrollDuration
- animator.start()
- releaseOverScrollAnimator = animator
- previousOverscrollAmount = 0
- }
-
- @VisibleForTesting
- internal fun finishAnimations() {
- releaseOverScrollAnimator?.end()
- releaseOverScrollAnimator = null
- }
-
- private fun dump(pw: PrintWriter) {
- pw.println(
- """
- SplitShadeOverScroller:
- Resources:
- releaseOverScrollDuration: $releaseOverScrollDuration
- maxOverScrollAmount: $maxOverScrollAmount
- State:
- previousOverscrollAmount: $previousOverscrollAmount
- dragDownAmount: $dragDownAmount
- panelState: $panelState
- """.trimIndent())
- }
-
- @AssistedFactory
- fun interface Factory {
- fun create(
- qSProvider: () -> QS,
- nsslControllerProvider: () -> NotificationStackScrollLayoutController
- ): SplitShadeOverScroller
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
index 1e4f5bbe17c0..84b40e05d808 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AlertingNotificationManager.java
@@ -298,9 +298,7 @@ public abstract class AlertingNotificationManager {
mLogger.logUpdateEntry(mEntry, updatePostTime);
final long now = mClock.currentTimeMillis();
- mEarliestRemovaltime = isSticky()
- ? mEntry.mCreationElapsedRealTime + mStickyDisplayTime
- : now + mMinimumDisplayTime;
+ mEarliestRemovaltime = now + mMinimumDisplayTime;
if (updatePostTime) {
mPostTime = Math.max(mPostTime, now);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index f20f929637cd..43fbc7cbae03 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -356,7 +356,7 @@ public final class KeyboardShortcuts {
* Keyboard with its default map.
*/
private void retrieveKeyCharacterMap(int deviceId) {
- final InputManager inputManager = InputManager.getInstance();
+ final InputManager inputManager = mContext.getSystemService(InputManager.class);
mBackupKeyCharacterMap = inputManager.getInputDevice(-1).getKeyCharacterMap();
if (deviceId != -1) {
final InputDevice inputDevice = inputManager.getInputDevice(deviceId);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
index 93aff7a43743..f395bea16131 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
@@ -52,18 +52,19 @@ import com.android.systemui.plugins.BcSmartspaceDataPlugin
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceTargetListener
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceView
import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.plugins.WeatherData
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.settings.UserTracker
import com.android.systemui.shared.regionsampling.RegionSampler
import com.android.systemui.shared.regionsampling.UpdateColorCallback
import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.DATE_SMARTSPACE_DATA_PLUGIN
import com.android.systemui.smartspace.dagger.SmartspaceModule.Companion.WEATHER_SMARTSPACE_DATA_PLUGIN
-import com.android.systemui.plugins.Weather
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.DeviceProvisionedController
import com.android.systemui.util.concurrency.Execution
import com.android.systemui.util.settings.SecureSettings
+import com.android.systemui.util.time.SystemClock
import java.io.PrintWriter
import java.time.Instant
import java.util.Optional
@@ -81,6 +82,7 @@ constructor(
private val smartspaceManager: SmartspaceManager,
private val activityStarter: ActivityStarter,
private val falsingManager: FalsingManager,
+ private val systemClock: SystemClock,
private val secureSettings: SecureSettings,
private val userTracker: UserTracker,
private val contentResolver: ContentResolver,
@@ -153,6 +155,18 @@ constructor(
// The weather data plugin takes unfiltered targets and performs the filtering internally.
weatherPlugin?.onTargetsAvailable(targets)
+ val now = Instant.ofEpochMilli(systemClock.currentTimeMillis())
+ val weatherTarget = targets.find { t ->
+ t.featureType == SmartspaceTarget.FEATURE_WEATHER &&
+ now.isAfter(Instant.ofEpochMilli(t.creationTimeMillis)) &&
+ now.isBefore(Instant.ofEpochMilli(t.expiryTimeMillis))
+ }
+ if (weatherTarget != null) {
+ val weatherData = WeatherData.fromBundle(weatherTarget.baseAction.extras)
+ if (weatherData != null) {
+ keyguardUpdateMonitor.sendWeatherData(weatherData)
+ }
+ }
val filteredTargets = targets.filter(::filterSmartspaceTarget)
plugin?.onTargetsAvailable(filteredTargets)
@@ -174,17 +188,6 @@ constructor(
}
isContentUpdatedOnce = true
}
-
- val now = Instant.now()
- val weatherTarget = targets.find { t ->
- t.featureType == SmartspaceTarget.FEATURE_WEATHER &&
- now.isAfter(Instant.ofEpochMilli(t.creationTimeMillis)) &&
- now.isBefore(Instant.ofEpochMilli(t.expiryTimeMillis))
- }
- if (weatherTarget != null) {
- val weatherData = Weather.fromBundle(weatherTarget.baseAction.extras)
- keyguardUpdateMonitor.sendWeatherData(weatherData)
- }
}
private val userTrackerCallback = object : UserTracker.Callback {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
index 32b8e09aa730..c9f31bad74c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -166,6 +166,11 @@ public class NotifCollection implements Dumpable, PipelineDumpable {
private Queue<NotifEvent> mEventQueue = new ArrayDeque<>();
+ private final Runnable mRebuildListRunnable = () -> {
+ if (mBuildListener != null) {
+ mBuildListener.onBuildList(mReadOnlyNotificationSet, "asynchronousUpdate");
+ }
+ };
private boolean mAttached = false;
private boolean mAmDispatchingToOtherCode;
@@ -462,7 +467,7 @@ public class NotifCollection implements Dumpable, PipelineDumpable {
int modificationType) {
Assert.isMainThread();
mEventQueue.add(new ChannelChangedEvent(pkgName, user, channel, modificationType));
- dispatchEventsAndRebuildList("onNotificationChannelModified");
+ dispatchEventsAndAsynchronouslyRebuildList();
}
private void onNotificationsInitialized() {
@@ -621,15 +626,39 @@ public class NotifCollection implements Dumpable, PipelineDumpable {
private void dispatchEventsAndRebuildList(String reason) {
Trace.beginSection("NotifCollection.dispatchEventsAndRebuildList");
+ if (mMainHandler.hasCallbacks(mRebuildListRunnable)) {
+ mMainHandler.removeCallbacks(mRebuildListRunnable);
+ }
+
+ dispatchEvents();
+
+ if (mBuildListener != null) {
+ mBuildListener.onBuildList(mReadOnlyNotificationSet, reason);
+ }
+ Trace.endSection();
+ }
+
+ private void dispatchEventsAndAsynchronouslyRebuildList() {
+ Trace.beginSection("NotifCollection.dispatchEventsAndAsynchronouslyRebuildList");
+
+ dispatchEvents();
+
+ if (!mMainHandler.hasCallbacks(mRebuildListRunnable)) {
+ mMainHandler.postDelayed(mRebuildListRunnable, 1000L);
+ }
+
+ Trace.endSection();
+ }
+
+ private void dispatchEvents() {
+ Trace.beginSection("NotifCollection.dispatchEvents");
+
mAmDispatchingToOtherCode = true;
while (!mEventQueue.isEmpty()) {
mEventQueue.remove().dispatchTo(mNotifCollectionListeners);
}
mAmDispatchingToOtherCode = false;
- if (mBuildListener != null) {
- mBuildListener.onBuildList(mReadOnlyNotificationSet, reason);
- }
Trace.endSection();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLogger.kt
index cc1103de8ec0..abe067039cd9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLogger.kt
@@ -20,6 +20,7 @@ package com.android.systemui.statusbar.notification.logging
import android.app.StatsManager
import android.util.Log
import android.util.StatsEvent
+import androidx.annotation.VisibleForTesting
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
@@ -143,67 +144,70 @@ constructor(
runBlocking(mainDispatcher) {
traceSection("NML#getNotifications") { notificationPipeline.allNotifs }
}
+}
- /** Aggregates memory usage data by package and style, returning sums. */
- private fun aggregateMemoryUsageData(
- notificationMemoryUse: List<NotificationMemoryUsage>
- ): Map<Pair<String, Int>, NotificationMemoryUseAtomBuilder> {
- return notificationMemoryUse
- .groupingBy { Pair(it.packageName, it.objectUsage.style) }
- .aggregate {
- _,
- accumulator: NotificationMemoryUseAtomBuilder?,
- element: NotificationMemoryUsage,
- first ->
- val use =
- if (first) {
- NotificationMemoryUseAtomBuilder(element.uid, element.objectUsage.style)
- } else {
- accumulator!!
- }
-
- use.count++
- // If the views of the notification weren't inflated, the list of memory usage
- // parameters will be empty.
- if (element.viewUsage.isNotEmpty()) {
- use.countWithInflatedViews++
+/** Aggregates memory usage data by package and style, returning sums. */
+@VisibleForTesting
+internal fun aggregateMemoryUsageData(
+ notificationMemoryUse: List<NotificationMemoryUsage>
+): Map<Pair<String, Int>, NotificationMemoryLogger.NotificationMemoryUseAtomBuilder> {
+ return notificationMemoryUse
+ .groupingBy { Pair(it.packageName, it.objectUsage.style) }
+ .aggregate {
+ _,
+ accumulator: NotificationMemoryLogger.NotificationMemoryUseAtomBuilder?,
+ element: NotificationMemoryUsage,
+ first ->
+ val use =
+ if (first) {
+ NotificationMemoryLogger.NotificationMemoryUseAtomBuilder(
+ element.uid,
+ element.objectUsage.style
+ )
+ } else {
+ accumulator!!
}
- use.smallIconObject += element.objectUsage.smallIcon
- if (element.objectUsage.smallIcon > 0) {
- use.smallIconBitmapCount++
- }
+ use.count++
+ // If the views of the notification weren't inflated, the list of memory usage
+ // parameters will be empty.
+ if (element.viewUsage.isNotEmpty()) {
+ use.countWithInflatedViews++
+ }
- use.largeIconObject += element.objectUsage.largeIcon
- if (element.objectUsage.largeIcon > 0) {
- use.largeIconBitmapCount++
- }
+ use.smallIconObject += element.objectUsage.smallIcon
+ if (element.objectUsage.smallIcon > 0) {
+ use.smallIconBitmapCount++
+ }
- use.bigPictureObject += element.objectUsage.bigPicture
- if (element.objectUsage.bigPicture > 0) {
- use.bigPictureBitmapCount++
- }
+ use.largeIconObject += element.objectUsage.largeIcon
+ if (element.objectUsage.largeIcon > 0) {
+ use.largeIconBitmapCount++
+ }
- use.extras += element.objectUsage.extras
- use.extenders += element.objectUsage.extender
-
- // Use totals count which are more accurate when aggregated
- // in this manner.
- element.viewUsage
- .firstOrNull { vu -> vu.viewType == ViewType.TOTAL }
- ?.let {
- use.smallIconViews += it.smallIcon
- use.largeIconViews += it.largeIcon
- use.systemIconViews += it.systemIcons
- use.styleViews += it.style
- use.customViews += it.style
- use.softwareBitmaps += it.softwareBitmapsPenalty
- }
-
- return@aggregate use
+ use.bigPictureObject += element.objectUsage.bigPicture
+ if (element.objectUsage.bigPicture > 0) {
+ use.bigPictureBitmapCount++
}
- }
- /** Rounds the passed value to the nearest KB - e.g. 700B rounds to 1KB. */
- private fun toKb(value: Int): Int = (value.toFloat() / 1024f).roundToInt()
+ use.extras += element.objectUsage.extras
+ use.extenders += element.objectUsage.extender
+
+ // Use totals count which are more accurate when aggregated
+ // in this manner.
+ element.viewUsage
+ .firstOrNull { vu -> vu.viewType == ViewType.TOTAL }
+ ?.let {
+ use.smallIconViews += it.smallIcon
+ use.largeIconViews += it.largeIcon
+ use.systemIconViews += it.systemIcons
+ use.styleViews += it.style
+ use.customViews += it.customViews
+ use.softwareBitmaps += it.softwareBitmapsPenalty
+ }
+
+ return@aggregate use
+ }
}
+/** Rounds the passed value to the nearest KB - e.g. 700B rounds to 1KB. */
+private fun toKb(value: Int): Int = (value.toFloat() / 1024f).roundToInt()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 1fb7eb5106e6..d2087ba6ca1c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -16,7 +16,7 @@
package com.android.systemui.statusbar.notification.stack;
-import static android.os.Trace.TRACE_TAG_ALWAYS;
+import static android.os.Trace.TRACE_TAG_APP;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_SCROLL_FLING;
import static com.android.internal.jank.InteractionJankMonitor.CUJ_SHADE_CLEAR_ALL;
@@ -1121,7 +1121,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
@Override
public void requestLayout() {
- Trace.instant(TRACE_TAG_ALWAYS, "NotificationStackScrollLayout#requestLayout");
+ Trace.instant(TRACE_TAG_APP, "NotificationStackScrollLayout#requestLayout");
super.requestLayout();
}
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 b1152333b5e1..a127139fcc69 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -66,6 +66,7 @@ import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInt
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.navigationbar.NavigationBarView;
import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.navigationbar.TaskbarDelegate;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.shade.NotificationPanelViewController;
import com.android.systemui.shade.ShadeController;
@@ -300,6 +301,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
@Nullable private KeyguardBypassController mBypassController;
@Nullable private OccludingAppBiometricUI mOccludingAppBiometricUI;
+ @Nullable private TaskbarDelegate mTaskbarDelegate;
private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
new KeyguardUpdateMonitorCallback() {
@Override
@@ -564,6 +566,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
updateStates();
}
+ public void setTaskbarDelegate(TaskbarDelegate taskbarDelegate) {
+ mTaskbarDelegate = taskbarDelegate;
+ }
+
/**
* Show the keyguard. Will handle creating and attaching to the view manager
* lazily.
@@ -790,7 +796,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
@Override
public void onFinishedGoingToSleep() {
- mPrimaryBouncerInteractor.onScreenTurnedOff();
+ mPrimaryBouncerInteractor.hide();
}
@Override
@@ -1193,7 +1199,8 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
* Updates the visibility of the nav bar window (which will cause insets changes).
*/
protected void updateNavigationBarVisibility(boolean navBarVisible) {
- if (mCentralSurfaces.getNavigationBarView() != null) {
+ if (mCentralSurfaces.getNavigationBarView() != null
+ || (mTaskbarDelegate != null && mTaskbarDelegate.isInitialized())) {
if (navBarVisible) {
long delay = getNavBarShowDelay();
if (delay == 0) {
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 559423b15514..94ce002f0c27 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -1416,6 +1416,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
@Override
public void onAnimationCancel(@NonNull Animator animation) {
mInteractionJankMonitor.cancel(CUJ_VOLUME_CONTROL);
+ Log.d(TAG, "onAnimationCancel");
}
@Override
@@ -1506,6 +1507,7 @@ public class VolumeDialogImpl implements VolumeDialog, Dumpable,
mHandler.removeMessages(H.DISMISS);
mHandler.removeMessages(H.SHOW);
if (mIsAnimatingDismiss) {
+ Log.d(TAG, "dismissH: isAnimatingDismiss");
return;
}
mIsAnimatingDismiss = true;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
index 568e8d20cd76..064bc9c0036d 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.java
@@ -32,11 +32,9 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -44,7 +42,6 @@ import static org.mockito.Mockito.when;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.hardware.biometrics.BiometricOverlayConstants;
-import android.hardware.biometrics.BiometricSourceType;
import android.media.AudioManager;
import android.telephony.TelephonyManager;
import android.testing.AndroidTestingRunner;
@@ -53,7 +50,6 @@ import android.testing.TestableResources;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
-import android.view.View;
import android.view.WindowInsetsController;
import android.widget.FrameLayout;
@@ -96,10 +92,8 @@ import java.util.Optional;
@TestableLooper.RunWithLooper()
public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
private static final int TARGET_USER_ID = 100;
-
@Rule
public MockitoRule mRule = MockitoJUnit.rule();
-
@Mock
private KeyguardSecurityContainer mView;
@Mock
@@ -368,134 +362,12 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
}
@Test
- public void onBouncerVisibilityChanged_allConditionsGood_sideFpsHintShown() {
- setupConditionsToEnableSideFpsHint();
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
-
- verify(mSideFpsController).show(SideFpsUiRequestSource.PRIMARY_BOUNCER,
- BiometricOverlayConstants.REASON_AUTH_KEYGUARD);
- verify(mSideFpsController, never()).hide(any());
- }
-
- @Test
- public void onBouncerVisibilityChanged_fpsSensorNotRunning_sideFpsHintHidden() {
- setupConditionsToEnableSideFpsHint();
- setFingerprintDetectionRunning(false);
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
-
- verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
- verify(mSideFpsController, never()).show(any(), anyInt());
- }
-
- @Test
- public void onBouncerVisibilityChanged_withoutSidedSecurity_sideFpsHintHidden() {
- setupConditionsToEnableSideFpsHint();
- setSideFpsHintEnabledFromResources(false);
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
-
- verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
- verify(mSideFpsController, never()).show(any(), anyInt());
- }
-
- @Test
- public void onBouncerVisibilityChanged_unlockingWithFingerprintNotAllowed_sideFpsHintHidden() {
- setupConditionsToEnableSideFpsHint();
- setUnlockingWithFingerprintAllowed(false);
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
-
- verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
- verify(mSideFpsController, never()).show(any(), anyInt());
- }
-
- @Test
- public void onBouncerVisibilityChanged_sideFpsHintShown_sideFpsHintHidden() {
- setupGetSecurityView();
- setupConditionsToEnableSideFpsHint();
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
- verify(mSideFpsController, atLeastOnce()).show(SideFpsUiRequestSource.PRIMARY_BOUNCER,
- BiometricOverlayConstants.REASON_AUTH_KEYGUARD);
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.INVISIBLE);
-
- verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
- verify(mSideFpsController, never()).show(any(), anyInt());
- }
-
- @Test
public void onBouncerVisibilityChanged_resetsScale() {
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.INVISIBLE);
-
+ mKeyguardSecurityContainerController.onBouncerVisibilityChanged(false);
verify(mView).resetScale();
}
@Test
- public void onStartingToHide_sideFpsHintShown_sideFpsHintHidden() {
- setupGetSecurityView();
- setupConditionsToEnableSideFpsHint();
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
- verify(mSideFpsController, atLeastOnce()).show(SideFpsUiRequestSource.PRIMARY_BOUNCER,
- BiometricOverlayConstants.REASON_AUTH_KEYGUARD);
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onStartingToHide();
-
- verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
- verify(mSideFpsController, never()).show(any(), anyInt());
- }
-
- @Test
- public void onPause_sideFpsHintShown_sideFpsHintHidden() {
- setupGetSecurityView();
- setupConditionsToEnableSideFpsHint();
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
- verify(mSideFpsController, atLeastOnce()).show(SideFpsUiRequestSource.PRIMARY_BOUNCER,
- BiometricOverlayConstants.REASON_AUTH_KEYGUARD);
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onPause();
-
- verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
- verify(mSideFpsController, never()).show(any(), anyInt());
- }
-
- @Test
- public void onResume_sideFpsHintShouldBeShown_sideFpsHintShown() {
- setupGetSecurityView();
- setupConditionsToEnableSideFpsHint();
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onResume(0);
-
- verify(mSideFpsController).show(SideFpsUiRequestSource.PRIMARY_BOUNCER,
- BiometricOverlayConstants.REASON_AUTH_KEYGUARD);
- verify(mSideFpsController, never()).hide(any());
- }
-
- @Test
- public void onResume_sideFpsHintShouldNotBeShown_sideFpsHintHidden() {
- setupGetSecurityView();
- setupConditionsToEnableSideFpsHint();
- setSideFpsHintEnabledFromResources(false);
- mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
- reset(mSideFpsController);
-
- mKeyguardSecurityContainerController.onResume(0);
-
- verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
- verify(mSideFpsController, never()).show(any(), anyInt());
- }
-
- @Test
public void showNextSecurityScreenOrFinish_setsSecurityScreenToPinAfterSimPinUnlock() {
// GIVEN the current security method is SimPin
when(mKeyguardUpdateMonitor.getUserHasTrust(anyInt())).thenReturn(false);
@@ -721,39 +593,31 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
any(KeyguardSecurityCallback.class));
}
+ @Test
+ public void testSideFpsControllerShow() {
+ mKeyguardSecurityContainerController.updateSideFpsVisibility(/* isVisible= */ true);
+ verify(mSideFpsController).show(
+ SideFpsUiRequestSource.PRIMARY_BOUNCER,
+ BiometricOverlayConstants.REASON_AUTH_KEYGUARD);
+ }
+
+ @Test
+ public void testSideFpsControllerHide() {
+ mKeyguardSecurityContainerController.updateSideFpsVisibility(/* isVisible= */ false);
+ verify(mSideFpsController).hide(SideFpsUiRequestSource.PRIMARY_BOUNCER);
+ }
+
private KeyguardSecurityContainer.SwipeListener getRegisteredSwipeListener() {
mKeyguardSecurityContainerController.onViewAttached();
verify(mView).setSwipeListener(mSwipeListenerArgumentCaptor.capture());
return mSwipeListenerArgumentCaptor.getValue();
}
- private void setupConditionsToEnableSideFpsHint() {
- attachView();
- setSideFpsHintEnabledFromResources(true);
- setFingerprintDetectionRunning(true);
- setUnlockingWithFingerprintAllowed(true);
- }
-
private void attachView() {
mKeyguardSecurityContainerController.onViewAttached();
verify(mKeyguardUpdateMonitor).registerCallback(mKeyguardUpdateMonitorCallback.capture());
}
- private void setFingerprintDetectionRunning(boolean running) {
- when(mKeyguardUpdateMonitor.isFingerprintDetectionRunning()).thenReturn(running);
- mKeyguardUpdateMonitorCallback.getValue().onBiometricRunningStateChanged(running,
- BiometricSourceType.FINGERPRINT);
- }
-
- private void setSideFpsHintEnabledFromResources(boolean enabled) {
- mTestableResources.addOverride(R.bool.config_show_sidefps_hint_on_bouncer,
- enabled);
- }
-
- private void setUnlockingWithFingerprintAllowed(boolean allowed) {
- when(mKeyguardUpdateMonitor.isUnlockingWithFingerprintAllowed()).thenReturn(allowed);
- }
-
private void setupGetSecurityView() {
when(mKeyguardSecurityViewFlipperController.getSecurityView(
any(), any(KeyguardSecurityCallback.class)))
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 9fe7506ca7dd..a1e4f70352d6 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -29,6 +29,7 @@ import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STR
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
import static com.android.keyguard.FaceAuthApiRequestReason.NOTIFICATION_PANEL_CLICKED;
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_AVAILABLE;
+import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_STATE_CANCELLING;
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_STATE_CANCELLING_RESTARTING;
import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT;
import static com.android.keyguard.KeyguardUpdateMonitor.HAL_POWER_PRESS_TIMEOUT;
@@ -48,6 +49,7 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
@@ -615,7 +617,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
anyInt());
- verify(mFingerprintManager, never()).detectFingerprint(any(), any(), anyInt());
+ verify(mFingerprintManager, never()).detectFingerprint(any(), any(), any());
}
@Test
@@ -627,7 +629,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
anyInt(), anyInt());
- verify(mFingerprintManager, never()).detectFingerprint(any(), any(), anyInt());
+ verify(mFingerprintManager, never()).detectFingerprint(any(), any(), any());
}
@Test
@@ -642,7 +644,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt());
- verify(mFingerprintManager).detectFingerprint(any(), any(), anyInt());
+ verify(mFingerprintManager).detectFingerprint(any(), any(), any());
}
@Test
@@ -731,7 +733,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
public void testTriesToAuthenticate_whenBouncer() {
setKeyguardBouncerVisibility(true);
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
verify(mFaceManager, never()).hasEnrolledTemplates(anyInt());
}
@@ -740,8 +742,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.sendPrimaryBouncerChanged(
/* bouncerIsOrWillBeShowing */ true, /* bouncerFullyShown */ false);
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -749,7 +750,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
keyguardIsVisible();
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
mTestableLooper.processAllMessages();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
verify(mUiEventLogger).logWithInstanceIdAndPosition(
eq(FaceAuthUiEvent.FACE_AUTH_UPDATED_STARTED_WAKING_UP),
eq(0),
@@ -765,8 +766,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
keyguardIsVisible();
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -777,8 +777,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
mTestableLooper.processAllMessages();
keyguardIsVisible();
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -802,9 +801,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
// THEN face detect and authenticate are NOT triggered
- verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verify(mFaceManager, never()).detectFace(any(), any(), any());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
// THEN biometric help message sent to callback
verify(keyguardUpdateMonitorCallback).onBiometricHelp(
@@ -825,9 +823,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
// FACE detect is triggered, not authenticate
- verify(mFaceManager).detectFace(any(), any(), anyInt());
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verify(mFaceManager).detectFace(any(), any(), any());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
// WHEN bouncer becomes visible
setKeyguardBouncerVisibility(true);
@@ -835,9 +832,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
// THEN face scanning is not run
mKeyguardUpdateMonitor.requestFaceAuth(FaceAuthApiRequestReason.UDFPS_POINTER_DOWN);
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
- verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
+ verify(mFaceManager, never()).detectFace(any(), any(), any());
}
@Test
@@ -852,9 +848,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
// FACE detect and authenticate are NOT triggered
- verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verify(mFaceManager, never()).detectFace(any(), any(), any());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -892,7 +887,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.setKeyguardShowing(true, true);
mKeyguardUpdateMonitor.setAssistantVisible(true);
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -904,8 +899,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
any(),
any(),
any(),
- anyInt(),
- anyBoolean());
+ anyInt());
}
@Test
@@ -936,7 +930,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
KeyguardUpdateMonitor.getCurrentUser(), 0 /* flags */,
new ArrayList<>());
keyguardIsVisible();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -944,7 +938,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.setKeyguardShowing(true, true);
mKeyguardUpdateMonitor.setAssistantVisible(true);
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
mTestableLooper.processAllMessages();
clearInvocations(mFaceManager);
@@ -961,8 +955,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
any(),
any(),
any(),
- anyInt(),
- anyBoolean());
+ anyInt());
}
@Test
@@ -972,8 +965,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.onTrustChanged(true /* enabled */, true /* newlyUnlocked */,
KeyguardUpdateMonitor.getCurrentUser(), 0 /* flags */, new ArrayList<>());
keyguardIsVisible();
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -985,9 +977,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
keyguardIsVisible();
mTestableLooper.processAllMessages();
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
- verify(mFaceManager, never()).detectFace(any(), any(), anyInt());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
+ verify(mFaceManager, never()).detectFace(any(), any(), any());
}
@Test
@@ -1017,8 +1008,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
setKeyguardBouncerVisibility(true);
mTestableLooper.processAllMessages();
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -1145,7 +1135,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
keyguardIsVisible();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
anyInt());
@@ -1175,10 +1165,11 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
assertThat(mKeyguardUpdateMonitor.isFingerprintLockedOut()).isEqualTo(fpLocked);
assertThat(mKeyguardUpdateMonitor.isFaceLockedOut()).isEqualTo(faceLocked);
- // Fingerprint should be restarted once its cancelled bc on lockout, the device
- // can still detectFingerprint (and if it's not locked out, fingerprint can listen)
+ // Fingerprint should be cancelled on lockout if going to lockout state, else
+ // restarted if it's not
assertThat(mKeyguardUpdateMonitor.mFingerprintRunningState)
- .isEqualTo(BIOMETRIC_STATE_CANCELLING_RESTARTING);
+ .isEqualTo(fpLocked
+ ? BIOMETRIC_STATE_CANCELLING : BIOMETRIC_STATE_CANCELLING_RESTARTING);
}
@Test
@@ -1596,8 +1587,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.setCredentialAttempted();
verify(mFingerprintManager, never()).authenticate(any(), any(), any(),
any(), anyInt());
- verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
- anyBoolean());
+ verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -1972,7 +1962,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
keyguardIsVisible();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
anyInt());
@@ -2001,7 +1991,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
verify(mFaceManager, never()).authenticate(
- any(), any(), any(), any(), anyInt(), anyBoolean());
+ any(), any(), any(), any(), anyInt());
}
@Test
@@ -2015,14 +2005,14 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
// THEN face auth isn't triggered
verify(mFaceManager, never()).authenticate(
- any(), any(), any(), any(), anyInt(), anyBoolean());
+ any(), any(), any(), any(), anyInt());
// WHEN device wakes up from the power button
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
mTestableLooper.processAllMessages();
// THEN face auth is triggered
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
}
@Test
@@ -2192,7 +2182,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
keyguardIsVisible();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
anyInt());
@@ -2225,7 +2215,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mTestableLooper.processAllMessages();
keyguardIsVisible();
- verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
+ verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt());
final CancellationSignal faceCancel = spy(mKeyguardUpdateMonitor.mFaceCancelSignal);
mKeyguardUpdateMonitor.mFaceCancelSignal = faceCancel;
@@ -2413,8 +2403,6 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
@Test
public void testUsbComplianceIntent_refreshBatteryInfo() {
Context contextSpy = getSpyContext();
- when(contextSpy.registerReceiver(eq(null), any(IntentFilter.class)))
- .thenReturn(getBatteryIntent());
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(
contextSpy, new Intent(UsbManager.ACTION_USB_PORT_COMPLIANCE_CHANGED));
@@ -2427,8 +2415,6 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
public void testUsbComplianceIntent_refreshBatteryInfoWithIncompatibleCharger() {
Context contextSpy = getSpyContext();
setupIncompatibleCharging();
- when(contextSpy.registerReceiver(eq(null), any(IntentFilter.class)))
- .thenReturn(getBatteryIntent());
mKeyguardUpdateMonitor.mBroadcastReceiver.onReceive(
contextSpy, new Intent(UsbManager.ACTION_USB_PORT_COMPLIANCE_CHANGED));
@@ -2597,8 +2583,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
any(),
mAuthenticationCallbackCaptor.capture(),
any(),
- anyInt(),
- anyBoolean());
+ anyInt());
mAuthenticationCallbackCaptor.getValue()
.onAuthenticationSucceeded(
new FaceManager.AuthenticationResult(null, null, mCurrentUserId, false));
@@ -2738,10 +2723,10 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
}
private Context getSpyContext() {
+ mContext.addMockSystemService(UsbManager.class, mUsbManager);
Context contextSpy = spy(mContext);
- when(contextSpy.getSystemService(UsbManager.class)).thenReturn(mUsbManager);
- when(contextSpy.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)))
- .thenReturn(new Intent(Intent.ACTION_BATTERY_CHANGED));
+ doReturn(getBatteryIntent()).when(contextSpy).registerReceiver(eq(null),
+ any(IntentFilter.class));
return contextSpy;
}
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt
index e9a2789bb5c8..9fe32f1e378b 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/mediator/ScreenOnCoordinatorTest.kt
@@ -32,6 +32,7 @@ import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito.`when`
+import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import java.util.Optional
@@ -83,6 +84,33 @@ class ScreenOnCoordinatorTest : SysuiTestCase() {
}
@Test
+ fun testTasksReady_onScreenTurningOnAndTurnedOnEventsCalledTogether_callsDrawnCallback() {
+ screenOnCoordinator.onScreenTurningOn(runnable)
+ screenOnCoordinator.onScreenTurnedOn()
+
+ onUnfoldOverlayReady()
+ onFoldAodReady()
+ waitHandlerIdle(testHandler)
+
+ // Should be called when both unfold overlay and keyguard drawn ready
+ verify(runnable).run()
+ }
+
+ @Test
+ fun testTasksReady_onScreenTurnedOnAndTurnedOffBeforeCompletion_doesNotCallDrawnCallback() {
+ screenOnCoordinator.onScreenTurningOn(runnable)
+ screenOnCoordinator.onScreenTurnedOn()
+ screenOnCoordinator.onScreenTurnedOff()
+
+ onUnfoldOverlayReady()
+ onFoldAodReady()
+ waitHandlerIdle(testHandler)
+
+ // Should not be called because this screen turning on call is not valid anymore
+ verify(runnable, never()).run()
+ }
+
+ @Test
fun testUnfoldTransitionDisabledDrawnTasksReady_onScreenTurningOn_callsDrawnCallback() {
// Recreate with empty unfoldComponent
screenOnCoordinator = ScreenOnCoordinator(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
index c73ff1dab3d8..54c9d392ad1c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerWithCoroutinesTest.kt
@@ -86,8 +86,9 @@ class UdfpsKeyguardViewControllerWithCoroutinesTest : UdfpsKeyguardViewControlle
mock(PrimaryBouncerCallbackInteractor::class.java),
mock(FalsingCollector::class.java),
mock(DismissCallbackRegistry::class.java),
+ context,
+ mKeyguardUpdateMonitor,
mock(KeyguardBypassController::class.java),
- mKeyguardUpdateMonitor
)
mAlternateBouncerInteractor =
AlternateBouncerInteractor(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
index e4df754ec96a..8cb91304808d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineClassifierTest.java
@@ -106,7 +106,7 @@ public class BrightLineClassifierTest extends SysuiTestCase {
mClassifiers.add(mClassifierB);
when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(mMotionEventList);
when(mKeyguardStateController.isShowing()).thenReturn(true);
- when(mFalsingDataProvider.isFolded()).thenReturn(true);
+ when(mFalsingDataProvider.isUnfolded()).thenReturn(false);
mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider,
mMetricsLogger, mClassifiers, mSingleTapClassfier, mLongTapClassifier,
mDoubleTapClassifier, mHistoryTracker, mKeyguardStateController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
index ae38eb67c431..315774aad71a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/BrightLineFalsingManagerTest.java
@@ -89,7 +89,7 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase {
mClassifiers.add(mClassifierA);
when(mFalsingDataProvider.getRecentMotionEvents()).thenReturn(mMotionEventList);
when(mKeyguardStateController.isShowing()).thenReturn(true);
- when(mFalsingDataProvider.isFolded()).thenReturn(true);
+ when(mFalsingDataProvider.isUnfolded()).thenReturn(false);
mBrightLineFalsingManager = new BrightLineFalsingManager(mFalsingDataProvider,
mMetricsLogger, mClassifiers, mSingleTapClassifier, mLongTapClassifier,
mDoubleTapClassifier, mHistoryTracker, mKeyguardStateController,
@@ -185,7 +185,7 @@ public class BrightLineFalsingManagerTest extends SysuiTestCase {
@Test
public void testSkipUnfolded() {
assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isTrue();
- when(mFalsingDataProvider.isFolded()).thenReturn(false);
+ when(mFalsingDataProvider.isUnfolded()).thenReturn(true);
assertThat(mBrightLineFalsingManager.isFalseTouch(Classifier.GENERIC)).isFalse();
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java
index c451a1e754c9..2edc3d361316 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/FalsingDataProviderTest.java
@@ -324,12 +324,18 @@ public class FalsingDataProviderTest extends ClassifierTest {
@Test
public void test_FoldedState_Folded() {
when(mFoldStateListener.getFolded()).thenReturn(true);
- assertThat(mDataProvider.isFolded()).isTrue();
+ assertThat(mDataProvider.isUnfolded()).isFalse();
}
@Test
public void test_FoldedState_Unfolded() {
when(mFoldStateListener.getFolded()).thenReturn(false);
- assertThat(mDataProvider.isFolded()).isFalse();
+ assertThat(mDataProvider.isUnfolded()).isTrue();
+ }
+
+ @Test
+ public void test_FoldedState_NotFoldable() {
+ when(mFoldStateListener.getFolded()).thenReturn(null);
+ assertThat(mDataProvider.isUnfolded()).isFalse();
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/devicepolicy/DevicePolicyManagerExtTest.kt b/packages/SystemUI/tests/src/com/android/systemui/devicepolicy/DevicePolicyManagerExtTest.kt
new file mode 100644
index 000000000000..34d5661597ca
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/devicepolicy/DevicePolicyManagerExtTest.kt
@@ -0,0 +1,93 @@
+/*
+ * 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.devicepolicy
+
+import android.app.admin.DevicePolicyManager
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FACE
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA
+import android.app.admin.DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL
+import androidx.test.filters.SmallTest
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(JUnit4::class)
+class DevicePolicyManagerExtTest {
+
+ @Mock lateinit var devicePolicyManager: DevicePolicyManager
+ @Mock private lateinit var userTracker: UserTracker
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+
+ whenever(userTracker.userId).thenReturn(CURRENT_USER_ID)
+ }
+
+ // region areKeyguardShortcutsDisabled
+ @Test
+ fun areKeyguardShortcutsDisabled_noDisabledKeyguardFeature_shouldReturnFalse() {
+ whenever(devicePolicyManager.getKeyguardDisabledFeatures(eq(null), anyInt()))
+ .thenReturn(KEYGUARD_DISABLE_FEATURES_NONE)
+
+ assertThat(devicePolicyManager.areKeyguardShortcutsDisabled(userId = CURRENT_USER_ID))
+ .isFalse()
+ }
+
+ @Test
+ fun areKeyguardShortcutsDisabled_otherDisabledKeyguardFeatures_shouldReturnFalse() {
+ whenever(devicePolicyManager.getKeyguardDisabledFeatures(eq(null), anyInt()))
+ .thenReturn(KEYGUARD_DISABLE_SECURE_CAMERA or KEYGUARD_DISABLE_FACE)
+
+ assertThat(devicePolicyManager.areKeyguardShortcutsDisabled(userId = CURRENT_USER_ID))
+ .isFalse()
+ }
+
+ @Test
+ fun areKeyguardShortcutsDisabled_disabledShortcutsKeyguardFeature_shouldReturnTrue() {
+ whenever(devicePolicyManager.getKeyguardDisabledFeatures(eq(null), anyInt()))
+ .thenReturn(KEYGUARD_DISABLE_SHORTCUTS_ALL)
+
+ assertThat(devicePolicyManager.areKeyguardShortcutsDisabled(userId = CURRENT_USER_ID))
+ .isTrue()
+ }
+
+ @Test
+ fun areKeyguardShortcutsDisabled_disabledAllKeyguardFeatures_shouldReturnTrue() {
+ whenever(devicePolicyManager.getKeyguardDisabledFeatures(eq(null), anyInt()))
+ .thenReturn(KEYGUARD_DISABLE_FEATURES_ALL)
+
+ assertThat(devicePolicyManager.areKeyguardShortcutsDisabled(userId = CURRENT_USER_ID))
+ .isTrue()
+ }
+ // endregion
+
+ private companion object {
+ const val CURRENT_USER_ID = 123
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt
index a12315b63fa7..2e9800606edf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/ServerFlagReaderImplTest.kt
@@ -26,6 +26,7 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
+import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@@ -58,4 +59,16 @@ class ServerFlagReaderImplTest : SysuiTestCase() {
verify(changeListener).onChange(flag)
}
+
+ @Test
+ fun testChange_ignoresListenersDuringTest() {
+ val serverFlagReader = ServerFlagReaderImpl(NAMESPACE, deviceConfig, executor, true)
+ val flag = ReleasedFlag(1, "1", "test")
+ serverFlagReader.listenForChanges(listOf(flag), changeListener)
+
+ deviceConfig.setProperty(NAMESPACE, "flag_override_1", "1", false)
+ executor.runAllReady()
+
+ verify(changeListener, never()).onChange(flag)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt
new file mode 100644
index 000000000000..f6ff4b214035
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyboard/data/repository/KeyboardRepositoryTest.kt
@@ -0,0 +1,191 @@
+/*
+ * 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.keyboard.data.repository
+
+import android.hardware.input.InputManager
+import android.view.InputDevice
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.mock
+import com.android.systemui.util.mockito.nullable
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class KeyboardRepositoryTest : SysuiTestCase() {
+
+ @Captor
+ private lateinit var deviceListenerCaptor: ArgumentCaptor<InputManager.InputDeviceListener>
+ @Mock private lateinit var inputManager: InputManager
+
+ private lateinit var underTest: KeyboardRepository
+ private lateinit var dispatcher: CoroutineDispatcher
+ private lateinit var testScope: TestScope
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ whenever(inputManager.inputDeviceIds).thenReturn(intArrayOf())
+ whenever(inputManager.getInputDevice(any())).then { invocation ->
+ val id = invocation.arguments.first()
+ INPUT_DEVICES_MAP[id]
+ }
+ dispatcher = StandardTestDispatcher()
+ testScope = TestScope(dispatcher)
+ underTest = KeyboardRepositoryImpl(testScope.backgroundScope, dispatcher, inputManager)
+ }
+
+ @Test
+ fun emitsDisconnected_ifNothingIsConnected() =
+ testScope.runTest {
+ val initialState = underTest.keyboardConnected.first()
+ assertThat(initialState).isFalse()
+ }
+
+ @Test
+ fun emitsConnected_ifKeyboardAlreadyConnectedAtTheStart() =
+ testScope.runTest {
+ whenever(inputManager.inputDeviceIds).thenReturn(intArrayOf(PHYSICAL_FULL_KEYBOARD_ID))
+ val initialValue = underTest.keyboardConnected.first()
+ assertThat(initialValue).isTrue()
+ }
+
+ @Test
+ fun emitsConnected_whenNewPhysicalKeyboardConnects() =
+ testScope.runTest {
+ val deviceListener = captureDeviceListener()
+ val isKeyboardConnected by collectLastValue(underTest.keyboardConnected)
+
+ deviceListener.onInputDeviceAdded(PHYSICAL_FULL_KEYBOARD_ID)
+
+ assertThat(isKeyboardConnected).isTrue()
+ }
+
+ @Test
+ fun emitsDisconnected_whenKeyboardDisconnects() =
+ testScope.runTest {
+ val deviceListener = captureDeviceListener()
+ val isKeyboardConnected by collectLastValue(underTest.keyboardConnected)
+
+ deviceListener.onInputDeviceAdded(PHYSICAL_FULL_KEYBOARD_ID)
+ assertThat(isKeyboardConnected).isTrue()
+
+ deviceListener.onInputDeviceRemoved(PHYSICAL_FULL_KEYBOARD_ID)
+ assertThat(isKeyboardConnected).isFalse()
+ }
+
+ private suspend fun captureDeviceListener(): InputManager.InputDeviceListener {
+ underTest.keyboardConnected.first()
+ verify(inputManager).registerInputDeviceListener(deviceListenerCaptor.capture(), nullable())
+ return deviceListenerCaptor.value
+ }
+
+ @Test
+ fun emitsDisconnected_whenVirtualOrNotFullKeyboardConnects() =
+ testScope.runTest {
+ val deviceListener = captureDeviceListener()
+ val isKeyboardConnected by collectLastValue(underTest.keyboardConnected)
+
+ deviceListener.onInputDeviceAdded(PHYSICAL_NOT_FULL_KEYBOARD_ID)
+ assertThat(isKeyboardConnected).isFalse()
+
+ deviceListener.onInputDeviceAdded(VIRTUAL_FULL_KEYBOARD_ID)
+ assertThat(isKeyboardConnected).isFalse()
+ }
+
+ @Test
+ fun emitsDisconnected_whenKeyboardDisconnectsAndWasAlreadyConnectedAtTheStart() =
+ testScope.runTest {
+ val deviceListener = captureDeviceListener()
+ val isKeyboardConnected by collectLastValue(underTest.keyboardConnected)
+
+ deviceListener.onInputDeviceRemoved(PHYSICAL_FULL_KEYBOARD_ID)
+ assertThat(isKeyboardConnected).isFalse()
+ }
+
+ @Test
+ fun emitsConnected_whenAnotherDeviceDisconnects() =
+ testScope.runTest {
+ val deviceListener = captureDeviceListener()
+ val isKeyboardConnected by collectLastValue(underTest.keyboardConnected)
+
+ deviceListener.onInputDeviceAdded(PHYSICAL_FULL_KEYBOARD_ID)
+ deviceListener.onInputDeviceRemoved(VIRTUAL_FULL_KEYBOARD_ID)
+
+ assertThat(isKeyboardConnected).isTrue()
+ }
+
+ @Test
+ fun emitsConnected_whenOnePhysicalKeyboardDisconnectsButAnotherRemainsConnected() =
+ testScope.runTest {
+ val deviceListener = captureDeviceListener()
+ val isKeyboardConnected by collectLastValue(underTest.keyboardConnected)
+
+ deviceListener.onInputDeviceAdded(PHYSICAL_FULL_KEYBOARD_ID)
+ deviceListener.onInputDeviceAdded(ANOTHER_PHYSICAL_FULL_KEYBOARD_ID)
+ deviceListener.onInputDeviceRemoved(ANOTHER_PHYSICAL_FULL_KEYBOARD_ID)
+
+ assertThat(isKeyboardConnected).isTrue()
+ }
+
+ @Test
+ fun passesKeyboardBacklightValues_fromBacklightListener() {
+ // TODO(b/268645734): implement when implementing backlight listener
+ }
+
+ private companion object {
+ private const val PHYSICAL_FULL_KEYBOARD_ID = 1
+ private const val VIRTUAL_FULL_KEYBOARD_ID = 2
+ private const val PHYSICAL_NOT_FULL_KEYBOARD_ID = 3
+ private const val ANOTHER_PHYSICAL_FULL_KEYBOARD_ID = 4
+
+ private val INPUT_DEVICES_MAP: Map<Int, InputDevice> =
+ mapOf(
+ PHYSICAL_FULL_KEYBOARD_ID to inputDevice(virtual = false, fullKeyboard = true),
+ VIRTUAL_FULL_KEYBOARD_ID to inputDevice(virtual = true, fullKeyboard = true),
+ PHYSICAL_NOT_FULL_KEYBOARD_ID to inputDevice(virtual = false, fullKeyboard = false),
+ ANOTHER_PHYSICAL_FULL_KEYBOARD_ID to
+ inputDevice(virtual = false, fullKeyboard = true)
+ )
+
+ private fun inputDevice(virtual: Boolean, fullKeyboard: Boolean): InputDevice =
+ mock<InputDevice>().also {
+ whenever(it.isVirtual).thenReturn(virtual)
+ whenever(it.isFullKeyboard).thenReturn(fullKeyboard)
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManagerTest.kt
index 7c604f760681..d55370b20d09 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardFaceAuthManagerTest.kt
@@ -21,6 +21,7 @@ import android.content.pm.UserInfo
import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_CANCELED
import android.hardware.biometrics.BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT
import android.hardware.biometrics.ComponentInfoInternal
+import android.hardware.face.FaceAuthenticateOptions
import android.hardware.face.FaceManager
import android.hardware.face.FaceSensorProperties
import android.hardware.face.FaceSensorPropertiesInternal
@@ -62,7 +63,6 @@ import org.junit.runner.RunWith
import org.junit.runners.JUnit4
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers.any
-import org.mockito.ArgumentMatchers.anyInt
import org.mockito.ArgumentMatchers.eq
import org.mockito.Captor
import org.mockito.Mock
@@ -276,7 +276,7 @@ class KeyguardFaceAuthManagerTest : SysuiTestCase() {
underTest.detect()
- verify(faceManager, never()).detectFace(any(), any(), anyInt())
+ verify(faceManager, never()).detectFace(any(), any(), any())
}
@Test
@@ -379,7 +379,7 @@ class KeyguardFaceAuthManagerTest : SysuiTestCase() {
.detectFace(
cancellationSignal.capture(),
detectionCallback.capture(),
- eq(currentUserId)
+ eq(FaceAuthenticateOptions.Builder().setUserId(currentUserId).build())
)
}
@@ -390,8 +390,7 @@ class KeyguardFaceAuthManagerTest : SysuiTestCase() {
cancellationSignal.capture(),
authenticationCallback.capture(),
isNull(),
- eq(currentUserId),
- eq(true)
+ eq(FaceAuthenticateOptions.Builder().setUserId(currentUserId).build())
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
index 46ed829e0574..6b7fd616e678 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorTest.kt
@@ -19,11 +19,13 @@ package com.android.systemui.keyguard.domain.interactor
import android.os.Looper
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper.RunWithLooper
+import android.testing.TestableResources
import android.view.View
import androidx.test.filters.SmallTest
import com.android.keyguard.KeyguardSecurityModel
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.DejankUtils
+import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.keyguard.DismissCallbackRegistry
@@ -69,6 +71,7 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
private val mainHandler = FakeHandler(Looper.getMainLooper())
private lateinit var underTest: PrimaryBouncerInteractor
+ private lateinit var resources: TestableResources
@Before
fun setUp() {
@@ -84,18 +87,19 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
mPrimaryBouncerCallbackInteractor,
falsingCollector,
dismissCallbackRegistry,
- keyguardBypassController,
+ context,
keyguardUpdateMonitor,
+ keyguardBypassController,
)
`when`(repository.primaryBouncerStartingDisappearAnimation.value).thenReturn(null)
`when`(repository.primaryBouncerShow.value).thenReturn(null)
`when`(bouncerView.delegate).thenReturn(bouncerViewDelegate)
+ resources = context.orCreateTestableResources
}
@Test
fun testShow_isScrimmed() {
underTest.show(true)
- verify(repository).setOnScreenTurnedOff(false)
verify(repository).setKeyguardAuthenticated(null)
verify(repository).setPrimaryHide(false)
verify(repository).setPrimaryStartingToHide(false)
@@ -207,12 +211,6 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
}
@Test
- fun testOnScreenTurnedOff() {
- underTest.onScreenTurnedOff()
- verify(repository).setOnScreenTurnedOff(true)
- }
-
- @Test
fun testSetKeyguardPosition() {
underTest.setKeyguardPosition(0f)
verify(repository).setKeyguardPosition(0f)
@@ -286,4 +284,98 @@ class PrimaryBouncerInteractorTest : SysuiTestCase() {
`when`(bouncerViewDelegate.willDismissWithActions()).thenReturn(false)
assertThat(underTest.willDismissWithAction()).isFalse()
}
+
+ @Test
+ fun testSideFpsVisibility() {
+ updateSideFpsVisibilityParameters(
+ isVisible = true,
+ sfpsEnabled = true,
+ fpsDetectionRunning = true,
+ isUnlockingWithFpAllowed = true,
+ isAnimatingAway = false
+ )
+ underTest.updateSideFpsVisibility()
+ verify(repository).setSideFpsShowing(true)
+ }
+
+ @Test
+ fun testSideFpsVisibility_notVisible() {
+ updateSideFpsVisibilityParameters(
+ isVisible = false,
+ sfpsEnabled = true,
+ fpsDetectionRunning = true,
+ isUnlockingWithFpAllowed = true,
+ isAnimatingAway = false
+ )
+ underTest.updateSideFpsVisibility()
+ verify(repository).setSideFpsShowing(false)
+ }
+
+ @Test
+ fun testSideFpsVisibility_sfpsNotEnabled() {
+ updateSideFpsVisibilityParameters(
+ isVisible = true,
+ sfpsEnabled = false,
+ fpsDetectionRunning = true,
+ isUnlockingWithFpAllowed = true,
+ isAnimatingAway = false
+ )
+ underTest.updateSideFpsVisibility()
+ verify(repository).setSideFpsShowing(false)
+ }
+
+ @Test
+ fun testSideFpsVisibility_fpsDetectionNotRunning() {
+ updateSideFpsVisibilityParameters(
+ isVisible = true,
+ sfpsEnabled = true,
+ fpsDetectionRunning = false,
+ isUnlockingWithFpAllowed = true,
+ isAnimatingAway = false
+ )
+ underTest.updateSideFpsVisibility()
+ verify(repository).setSideFpsShowing(false)
+ }
+
+ @Test
+ fun testSideFpsVisibility_UnlockingWithFpNotAllowed() {
+ updateSideFpsVisibilityParameters(
+ isVisible = true,
+ sfpsEnabled = true,
+ fpsDetectionRunning = true,
+ isUnlockingWithFpAllowed = false,
+ isAnimatingAway = false
+ )
+ underTest.updateSideFpsVisibility()
+ verify(repository).setSideFpsShowing(false)
+ }
+
+ @Test
+ fun testSideFpsVisibility_AnimatingAway() {
+ updateSideFpsVisibilityParameters(
+ isVisible = true,
+ sfpsEnabled = true,
+ fpsDetectionRunning = true,
+ isUnlockingWithFpAllowed = true,
+ isAnimatingAway = true
+ )
+ underTest.updateSideFpsVisibility()
+ verify(repository).setSideFpsShowing(false)
+ }
+
+ private fun updateSideFpsVisibilityParameters(
+ isVisible: Boolean,
+ sfpsEnabled: Boolean,
+ fpsDetectionRunning: Boolean,
+ isUnlockingWithFpAllowed: Boolean,
+ isAnimatingAway: Boolean
+ ) {
+ `when`(repository.primaryBouncerVisible.value).thenReturn(isVisible)
+ resources.addOverride(R.bool.config_show_sidefps_hint_on_bouncer, sfpsEnabled)
+ `when`(keyguardUpdateMonitor.isFingerprintDetectionRunning).thenReturn(fpsDetectionRunning)
+ `when`(keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed)
+ .thenReturn(isUnlockingWithFpAllowed)
+ `when`(repository.primaryBouncerStartingDisappearAnimation.value)
+ .thenReturn(if (isAnimatingAway) Runnable {} else null)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
index 75b74b0cfe28..f675e7997eb4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/PrimaryBouncerInteractorWithCoroutinesTest.kt
@@ -26,7 +26,6 @@ import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.BouncerView
-import com.android.systemui.keyguard.data.BouncerViewDelegate
import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -44,7 +43,6 @@ import org.mockito.MockitoAnnotations
class PrimaryBouncerInteractorWithCoroutinesTest : SysuiTestCase() {
private lateinit var repository: FakeKeyguardBouncerRepository
@Mock private lateinit var bouncerView: BouncerView
- @Mock private lateinit var bouncerViewDelegate: BouncerViewDelegate
@Mock private lateinit var keyguardStateController: KeyguardStateController
@Mock private lateinit var keyguardSecurityModel: KeyguardSecurityModel
@Mock private lateinit var primaryBouncerCallbackInteractor: PrimaryBouncerCallbackInteractor
@@ -69,8 +67,9 @@ class PrimaryBouncerInteractorWithCoroutinesTest : SysuiTestCase() {
primaryBouncerCallbackInteractor,
falsingCollector,
dismissCallbackRegistry,
- keyguardBypassController,
+ context,
keyguardUpdateMonitor,
+ keyguardBypassController,
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt
index 586af626d29e..65e4c10265cd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardBouncerViewModelTest.kt
@@ -16,15 +16,23 @@
package com.android.systemui.keyguard.ui.viewmodel
+import android.os.Looper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.keyguard.KeyguardSecurityModel
+import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.SysuiTestCase
+import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.BouncerView
+import com.android.systemui.keyguard.data.repository.FakeKeyguardBouncerRepository
+import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.utils.os.FakeHandler
import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.test.runCurrent
@@ -33,7 +41,6 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
-import org.mockito.Mockito
import org.mockito.MockitoAnnotations
@SmallTest
@@ -41,31 +48,69 @@ import org.mockito.MockitoAnnotations
@kotlinx.coroutines.ExperimentalCoroutinesApi
class KeyguardBouncerViewModelTest : SysuiTestCase() {
lateinit var underTest: KeyguardBouncerViewModel
+ lateinit var bouncerInteractor: PrimaryBouncerInteractor
@Mock lateinit var bouncerView: BouncerView
- @Mock lateinit var bouncerInteractor: PrimaryBouncerInteractor
+ @Mock private lateinit var keyguardStateController: KeyguardStateController
+ @Mock private lateinit var keyguardSecurityModel: KeyguardSecurityModel
+ @Mock private lateinit var primaryBouncerCallbackInteractor: PrimaryBouncerCallbackInteractor
+ @Mock private lateinit var falsingCollector: FalsingCollector
+ @Mock private lateinit var dismissCallbackRegistry: DismissCallbackRegistry
+ @Mock private lateinit var keyguardBypassController: KeyguardBypassController
+ @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
+ private val mainHandler = FakeHandler(Looper.getMainLooper())
+ val repository = FakeKeyguardBouncerRepository()
@Before
fun setup() {
MockitoAnnotations.initMocks(this)
+ bouncerInteractor =
+ PrimaryBouncerInteractor(
+ repository,
+ bouncerView,
+ mainHandler,
+ keyguardStateController,
+ keyguardSecurityModel,
+ primaryBouncerCallbackInteractor,
+ falsingCollector,
+ dismissCallbackRegistry,
+ context,
+ keyguardUpdateMonitor,
+ keyguardBypassController,
+ )
underTest = KeyguardBouncerViewModel(bouncerView, bouncerInteractor)
}
@Test
- fun setMessage() =
- runTest {
- val flow = MutableStateFlow<BouncerShowMessageModel?>(null)
- var message: BouncerShowMessageModel? = null
- Mockito.`when`(bouncerInteractor.showMessage)
- .thenReturn(flow as Flow<BouncerShowMessageModel>)
- // Reinitialize the view model.
- underTest = KeyguardBouncerViewModel(bouncerView, bouncerInteractor)
+ fun setMessage() = runTest {
+ var message: BouncerShowMessageModel? = null
+ val job = underTest.bouncerShowMessage.onEach { message = it }.launchIn(this)
- flow.value = BouncerShowMessageModel(message = "abc", colorStateList = null)
+ repository.setShowMessage(BouncerShowMessageModel("abc", null))
+ // Run the tasks that are pending at this point of virtual time.
+ runCurrent()
+ assertThat(message?.message).isEqualTo("abc")
+ job.cancel()
+ }
+
+ @Test
+ fun shouldUpdateSideFps() = runTest {
+ var count = 0
+ val job = underTest.shouldUpdateSideFps.onEach { count++ }.launchIn(this)
+ repository.setPrimaryVisible(true)
+ // Run the tasks that are pending at this point of virtual time.
+ runCurrent()
+ assertThat(count).isEqualTo(1)
+ job.cancel()
+ }
- val job = underTest.bouncerShowMessage.onEach { message = it }.launchIn(this)
- // Run the tasks that are pending at this point of virtual time.
- runCurrent()
- assertThat(message?.message).isEqualTo("abc")
- job.cancel()
- }
+ @Test
+ fun sideFpsShowing() = runTest {
+ var sideFpsIsShowing = false
+ val job = underTest.sideFpsShowing.onEach { sideFpsIsShowing = it }.launchIn(this)
+ repository.setSideFpsShowing(true)
+ // Run the tasks that are pending at this point of virtual time.
+ runCurrent()
+ assertThat(sideFpsIsShowing).isEqualTo(true)
+ job.cancel()
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataFilterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataFilterTest.kt
index eb6235ca8a6a..8532ffed85fb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataFilterTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/pipeline/MediaDataFilterTest.kt
@@ -17,6 +17,7 @@
package com.android.systemui.media.controls.pipeline
import android.app.smartspace.SmartspaceAction
+import android.os.Bundle
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import androidx.test.filters.SmallTest
@@ -25,6 +26,7 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.broadcast.BroadcastSender
import com.android.systemui.media.controls.MediaTestUtils
import com.android.systemui.media.controls.models.player.MediaData
+import com.android.systemui.media.controls.models.recommendation.EXTRA_KEY_TRIGGER_RESUME
import com.android.systemui.media.controls.models.recommendation.SmartspaceMediaData
import com.android.systemui.media.controls.ui.MediaPlayerData
import com.android.systemui.media.controls.util.MediaFlags
@@ -75,6 +77,7 @@ class MediaDataFilterTest : SysuiTestCase() {
@Mock private lateinit var smartspaceMediaRecommendationItem: SmartspaceAction
@Mock private lateinit var logger: MediaUiEventLogger
@Mock private lateinit var mediaFlags: MediaFlags
+ @Mock private lateinit var cardAction: SmartspaceAction
private lateinit var mediaDataFilter: MediaDataFilter
private lateinit var dataMain: MediaData
@@ -122,6 +125,7 @@ class MediaDataFilterTest : SysuiTestCase() {
whenever(smartspaceData.headphoneConnectionTimeMillis)
.thenReturn(clock.currentTimeMillis() - 100)
whenever(smartspaceData.instanceId).thenReturn(SMARTSPACE_INSTANCE_ID)
+ whenever(smartspaceData.cardAction).thenReturn(cardAction)
}
private fun setUser(id: Int) {
@@ -574,4 +578,55 @@ class MediaDataFilterTest : SysuiTestCase() {
verify(mediaDataManager, never())
.dismissSmartspaceRecommendation(eq(SMARTSPACE_KEY), anyLong())
}
+
+ @Test
+ fun testSmartspaceLoaded_shouldTriggerResume_doesTrigger() {
+ // WHEN we have media that was recently played, but not currently active
+ val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
+ mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent)
+ verify(listener)
+ .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false))
+
+ // AND we get a smartspace signal with extra to trigger resume
+ val extras = Bundle().apply { putBoolean(EXTRA_KEY_TRIGGER_RESUME, true) }
+ whenever(cardAction.extras).thenReturn(extras)
+ mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
+
+ // THEN we should tell listeners to treat the media as active instead
+ val dataCurrentAndActive = dataCurrent.copy(active = true)
+ verify(listener)
+ .onMediaDataLoaded(
+ eq(KEY),
+ eq(KEY),
+ eq(dataCurrentAndActive),
+ eq(true),
+ eq(100),
+ eq(true)
+ )
+ assertThat(mediaDataFilter.hasActiveMediaOrRecommendation()).isTrue()
+ // And send the smartspace data, but not prioritized
+ verify(listener)
+ .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false))
+ }
+
+ @Test
+ fun testSmartspaceLoaded_notShouldTriggerResume_doesNotTrigger() {
+ // WHEN we have media that was recently played, but not currently active
+ val dataCurrent = dataMain.copy(active = false, lastActive = clock.elapsedRealtime())
+ mediaDataFilter.onMediaDataLoaded(KEY, null, dataCurrent)
+ verify(listener)
+ .onMediaDataLoaded(eq(KEY), eq(null), eq(dataCurrent), eq(true), eq(0), eq(false))
+
+ // AND we get a smartspace signal with extra to not trigger resume
+ val extras = Bundle().apply { putBoolean(EXTRA_KEY_TRIGGER_RESUME, false) }
+ whenever(cardAction.extras).thenReturn(extras)
+ mediaDataFilter.onSmartspaceMediaDataLoaded(SMARTSPACE_KEY, smartspaceData)
+
+ // THEN listeners are not updated to show media
+ verify(listener, never())
+ .onMediaDataLoaded(eq(KEY), eq(KEY), any(), eq(true), eq(100), eq(true))
+ // But the smartspace update is still propagated
+ verify(listener)
+ .onSmartspaceMediaDataLoaded(eq(SMARTSPACE_KEY), eq(smartspaceData), eq(false))
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
index 537dfb821fef..1c9336a3fc66 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/navigationbar/TaskbarDelegateTest.kt
@@ -13,6 +13,7 @@ import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.phone.AutoHideController
import com.android.systemui.statusbar.phone.LightBarController
import com.android.systemui.statusbar.phone.LightBarTransitionsController
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
import com.android.wm.shell.back.BackAnimation
import com.android.wm.shell.pip.Pip
import org.junit.Before
@@ -66,6 +67,8 @@ class TaskbarDelegateTest : SysuiTestCase() {
lateinit var mBackAnimation: BackAnimation
@Mock
lateinit var mCurrentSysUiState: NavBarHelper.CurrentSysuiState
+ @Mock
+ lateinit var mStatusBarKeyguardViewManager: StatusBarKeyguardViewManager
@Before
fun setup() {
@@ -76,7 +79,7 @@ class TaskbarDelegateTest : SysuiTestCase() {
`when`(mSysUiState.setFlag(anyInt(), anyBoolean())).thenReturn(mSysUiState)
mTaskStackChangeListeners = TaskStackChangeListeners.getTestInstance()
mTaskbarDelegate = TaskbarDelegate(context, mEdgeBackGestureHandlerFactory,
- mLightBarControllerFactory)
+ mLightBarControllerFactory, mStatusBarKeyguardViewManager)
mTaskbarDelegate.setDependencies(mCommandQueue, mOverviewProxyService, mNavBarHelper,
mNavigationModeController, mSysUiState, mDumpManager, mAutoHideController,
mLightBarController, mOptionalPip, mBackAnimation, mTaskStackChangeListeners)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
index 39c4e06ff0bb..52b29ac909fe 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/notetask/NoteTaskControllerTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.notetask
import android.app.KeyguardManager
+import android.app.admin.DevicePolicyManager
import android.content.ComponentName
import android.content.Context
import android.content.Intent
@@ -29,6 +30,7 @@ import com.android.systemui.notetask.NoteTaskController.Companion.INTENT_EXTRA_U
import com.android.systemui.notetask.NoteTaskController.ShowNoteTaskUiEvent
import com.android.systemui.notetask.NoteTaskInfoResolver.NoteTaskInfo
import com.android.systemui.notetask.shortcut.CreateNoteTaskShortcutActivity
+import com.android.systemui.settings.UserTracker
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
@@ -39,6 +41,7 @@ import java.util.Optional
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyZeroInteractions
@@ -64,6 +67,8 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
@Mock lateinit var optionalUserManager: Optional<UserManager>
@Mock lateinit var userManager: UserManager
@Mock lateinit var uiEventLogger: UiEventLogger
+ @Mock private lateinit var userTracker: UserTracker
+ @Mock private lateinit var devicePolicyManager: DevicePolicyManager
@Before
fun setUp() {
@@ -75,6 +80,13 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
whenever(optionalKeyguardManager.orElse(null)).thenReturn(keyguardManager)
whenever(optionalUserManager.orElse(null)).thenReturn(userManager)
whenever(userManager.isUserUnlocked).thenReturn(true)
+ whenever(
+ devicePolicyManager.getKeyguardDisabledFeatures(
+ /* admin= */ eq(null),
+ /* userHandle= */ anyInt()
+ )
+ )
+ .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE)
}
private fun createNoteTaskController(isEnabled: Boolean = true): NoteTaskController {
@@ -84,8 +96,10 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
optionalBubbles = optionalBubbles,
optionalKeyguardManager = optionalKeyguardManager,
optionalUserManager = optionalUserManager,
+ devicePolicyManager = devicePolicyManager,
isEnabled = isEnabled,
uiEventLogger = uiEventLogger,
+ userTracker = userTracker,
)
}
@@ -291,6 +305,86 @@ internal class NoteTaskControllerTest : SysuiTestCase() {
}
// endregion
+ // region keyguard policy
+ @Test
+ fun showNoteTask_keyguardLocked_keyguardDisableShortcutsAll_shouldDoNothing() {
+ whenever(keyguardManager.isKeyguardLocked).thenReturn(true)
+ whenever(
+ devicePolicyManager.getKeyguardDisabledFeatures(
+ /* admin= */ eq(null),
+ /* userHandle= */ anyInt()
+ )
+ )
+ .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL)
+
+ createNoteTaskController().showNoteTask(isInMultiWindowMode = false, uiEvent = null)
+
+ verifyZeroInteractions(context, bubbles, uiEventLogger)
+ }
+
+ @Test
+ fun showNoteTask_keyguardLocked_keyguardDisableFeaturesAll_shouldDoNothing() {
+ whenever(keyguardManager.isKeyguardLocked).thenReturn(true)
+ whenever(
+ devicePolicyManager.getKeyguardDisabledFeatures(
+ /* admin= */ eq(null),
+ /* userHandle= */ anyInt()
+ )
+ )
+ .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL)
+
+ createNoteTaskController().showNoteTask(isInMultiWindowMode = false, uiEvent = null)
+
+ verifyZeroInteractions(context, bubbles, uiEventLogger)
+ }
+
+ @Test
+ fun showNoteTask_keyguardUnlocked_keyguardDisableShortcutsAll_shouldStartBubble() {
+ whenever(keyguardManager.isKeyguardLocked).thenReturn(false)
+ whenever(
+ devicePolicyManager.getKeyguardDisabledFeatures(
+ /* admin= */ eq(null),
+ /* userHandle= */ anyInt()
+ )
+ )
+ .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_SHORTCUTS_ALL)
+
+ createNoteTaskController().showNoteTask(isInMultiWindowMode = false, uiEvent = null)
+
+ val intentCaptor = argumentCaptor<Intent>()
+ verify(bubbles).showOrHideAppBubble(capture(intentCaptor))
+ intentCaptor.value.let { intent ->
+ assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
+ assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
+ assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
+ assertThat(intent.getBooleanExtra(INTENT_EXTRA_USE_STYLUS_MODE, false)).isTrue()
+ }
+ }
+
+ @Test
+ fun showNoteTask_keyguardUnlocked_keyguardDisableFeaturesAll_shouldStartBubble() {
+ whenever(keyguardManager.isKeyguardLocked).thenReturn(false)
+ whenever(
+ devicePolicyManager.getKeyguardDisabledFeatures(
+ /* admin= */ eq(null),
+ /* userHandle= */ anyInt()
+ )
+ )
+ .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_ALL)
+
+ createNoteTaskController().showNoteTask(isInMultiWindowMode = false, uiEvent = null)
+
+ val intentCaptor = argumentCaptor<Intent>()
+ verify(bubbles).showOrHideAppBubble(capture(intentCaptor))
+ intentCaptor.value.let { intent ->
+ assertThat(intent.action).isEqualTo(NoteTaskController.ACTION_CREATE_NOTE)
+ assertThat(intent.`package`).isEqualTo(NOTES_PACKAGE_NAME)
+ assertThat(intent.flags).isEqualTo(Intent.FLAG_ACTIVITY_NEW_TASK)
+ assertThat(intent.getBooleanExtra(INTENT_EXTRA_USE_STYLUS_MODE, false)).isTrue()
+ }
+ }
+ // endregion
+
private companion object {
const val NOTES_PACKAGE_NAME = "com.android.note.app"
const val NOTES_UID = 123456
diff --git a/packages/SystemUI/tests/src/com/android/systemui/process/condition/UserProcessConditionTest.java b/packages/SystemUI/tests/src/com/android/systemui/process/condition/SystemProcessConditionTest.java
index 2293fc577029..fb7197706ddc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/process/condition/UserProcessConditionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/process/condition/SystemProcessConditionTest.java
@@ -26,7 +26,6 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.process.ProcessWrapper;
-import com.android.systemui.settings.UserTracker;
import com.android.systemui.shared.condition.Condition;
import com.android.systemui.shared.condition.Monitor;
import com.android.systemui.util.concurrency.FakeExecutor;
@@ -41,10 +40,7 @@ import org.mockito.MockitoAnnotations;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
@SmallTest
-public class UserProcessConditionTest extends SysuiTestCase {
- @Mock
- UserTracker mUserTracker;
-
+public class SystemProcessConditionTest extends SysuiTestCase {
@Mock
ProcessWrapper mProcessWrapper;
@@ -59,15 +55,14 @@ public class UserProcessConditionTest extends SysuiTestCase {
}
/**
- * Verifies condition reports false when tracker reports a different user id than the
- * identifier from the process handle.
+ * Verifies condition reports false when tracker reports the process is being ran by the
+ * system user.
*/
@Test
- public void testConditionFailsWithDifferentIds() {
+ public void testConditionFailsWithNonSystemProcess() {
- final Condition condition = new UserProcessCondition(mProcessWrapper, mUserTracker);
- when(mProcessWrapper.getUserHandleIdentifier()).thenReturn(0);
- when(mUserTracker.getUserId()).thenReturn(1);
+ final Condition condition = new SystemProcessCondition(mProcessWrapper);
+ when(mProcessWrapper.isSystemUser()).thenReturn(false);
final Monitor monitor = new Monitor(mExecutor);
@@ -81,15 +76,14 @@ public class UserProcessConditionTest extends SysuiTestCase {
}
/**
- * Verifies condition reports false when tracker reports a different user id than the
- * identifier from the process handle.
+ * Verifies condition reports true when tracker reports the process is being ran by the
+ * system user.
*/
@Test
- public void testConditionSucceedsWithSameIds() {
+ public void testConditionSucceedsWithSystemProcess() {
- final Condition condition = new UserProcessCondition(mProcessWrapper, mUserTracker);
- when(mProcessWrapper.getUserHandleIdentifier()).thenReturn(0);
- when(mUserTracker.getUserId()).thenReturn(0);
+ final Condition condition = new SystemProcessCondition(mProcessWrapper);
+ when(mProcessWrapper.isSystemUser()).thenReturn(true);
final Monitor monitor = new Monitor(mExecutor);
@@ -101,5 +95,4 @@ public class UserProcessConditionTest extends SysuiTestCase {
verify(mCallback).onConditionsChanged(true);
}
-
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index 4caa50fa847d..89606bf6be3d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -52,14 +52,13 @@ import com.android.systemui.R;
import com.android.systemui.SysuiBaseFragmentTest;
import com.android.systemui.animation.ShadeInterpolation;
import com.android.systemui.dump.DumpManager;
-import com.android.systemui.flags.FakeFeatureFlags;
import com.android.systemui.media.controls.ui.MediaHost;
-import com.android.systemui.plugins.FalsingManager;
import com.android.systemui.qs.customize.QSCustomizerController;
import com.android.systemui.qs.dagger.QSFragmentComponent;
import com.android.systemui.qs.external.TileServiceRequestController;
import com.android.systemui.qs.footer.ui.binder.FooterActionsViewBinder;
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel;
+import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.settings.FakeDisplayTracker;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusBarState;
@@ -86,7 +85,6 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
@Mock private MediaHost mQSMediaHost;
@Mock private MediaHost mQQSMediaHost;
@Mock private KeyguardBypassController mBypassController;
- @Mock private FalsingManager mFalsingManager;
@Mock private TileServiceRequestController.Builder mTileServiceRequestControllerBuilder;
@Mock private TileServiceRequestController mTileServiceRequestController;
@Mock private QSCustomizerController mQsCustomizerController;
@@ -503,11 +501,9 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
setUpMedia();
setUpOther();
- FakeFeatureFlags featureFlags = new FakeFeatureFlags();
return new QSFragment(
new RemoteInputQuickSettingsDisabler(
context, commandQueue, mock(ConfigurationController.class)),
- mock(QSTileHost.class),
mStatusBarStateController,
commandQueue,
mQSMediaHost,
@@ -515,9 +511,8 @@ public class QSFragmentTest extends SysuiBaseFragmentTest {
mBypassController,
mQsComponentFactory,
mock(QSFragmentDisableFlagsLogger.class),
- mFalsingManager,
mock(DumpManager.class),
- featureFlags,
+ mock(QSLogger.class),
mock(FooterActionsController.class),
mFooterActionsViewModelFactory);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
index 8601d6c0a357..04b372c4a361 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ReduceBrightColorsTileTest.java
@@ -45,6 +45,7 @@ import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.settings.UserTracker;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -53,6 +54,7 @@ import org.mockito.MockitoAnnotations;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@SmallTest
+@Ignore("b/269171747")
public class ReduceBrightColorsTileTest extends SysuiTestCase {
@Mock
private QSTileHost mHost;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java
index d828e510999a..515e1ee172ed 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenshot/appclips/AppClipsActivityTest.java
@@ -57,6 +57,7 @@ import com.android.systemui.settings.UserTracker;
import org.junit.After;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -65,7 +66,6 @@ import org.mockito.MockitoAnnotations;
import java.util.function.BiConsumer;
-
@RunWith(AndroidTestingRunner.class)
public final class AppClipsActivityTest extends SysuiTestCase {
@@ -140,6 +140,7 @@ public final class AppClipsActivityTest extends SysuiTestCase {
mActivityRule.finishActivity();
}
+ @Ignore("b/269403503")
@Test
public void appClipsLaunched_screenshotDisplayed() {
launchActivity();
@@ -147,6 +148,7 @@ public final class AppClipsActivityTest extends SysuiTestCase {
assertThat(((ImageView) mActivity.findViewById(R.id.preview)).getDrawable()).isNotNull();
}
+ @Ignore("b/269403503")
@Test
public void screenshotDisplayed_userConsented_screenshotExportedSuccessfully() {
ResultReceiver resultReceiver = createResultReceiver((resultCode, data) -> {
@@ -166,6 +168,7 @@ public final class AppClipsActivityTest extends SysuiTestCase {
verify(mUiEventLogger).log(SCREENSHOT_FOR_NOTE_ACCEPTED, TEST_UID, TEST_CALLING_PACKAGE);
}
+ @Ignore("b/269403503")
@Test
public void screenshotDisplayed_userDeclined() {
ResultReceiver resultReceiver = createResultReceiver((resultCode, data) -> {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt
index 7cac854c0853..d5a1f804e6a0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ShadeTransitionControllerTest.kt
@@ -2,37 +2,24 @@ package com.android.systemui.shade.transition
import android.testing.AndroidTestingRunner
import androidx.test.filters.SmallTest
-import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
-import com.android.systemui.plugins.qs.QS
-import com.android.systemui.shade.NotificationPanelViewController
import com.android.systemui.shade.STATE_OPENING
import com.android.systemui.shade.ShadeExpansionChangeEvent
import com.android.systemui.shade.ShadeExpansionStateManager
-import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.SysuiStatusBarStateController
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
import com.android.systemui.statusbar.policy.FakeConfigurationController
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
-import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyZeroInteractions
-import org.mockito.Mockito.`when` as whenever
import org.mockito.MockitoAnnotations
@RunWith(AndroidTestingRunner::class)
@SmallTest
class ShadeTransitionControllerTest : SysuiTestCase() {
- @Mock private lateinit var npvc: NotificationPanelViewController
- @Mock private lateinit var nsslController: NotificationStackScrollLayoutController
- @Mock private lateinit var qs: QS
- @Mock private lateinit var noOpOverScroller: NoOpOverScroller
- @Mock private lateinit var splitShadeOverScroller: SplitShadeOverScroller
@Mock private lateinit var scrimShadeTransitionController: ScrimShadeTransitionController
@Mock private lateinit var dumpManager: DumpManager
@Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
@@ -52,119 +39,19 @@ class ShadeTransitionControllerTest : SysuiTestCase() {
shadeExpansionStateManager,
dumpManager,
context,
- splitShadeOverScrollerFactory = { _, _ -> splitShadeOverScroller },
- noOpOverScroller,
scrimShadeTransitionController,
statusBarStateController,
)
-
- // Resetting as they are notified upon initialization.
- reset(noOpOverScroller, splitShadeOverScroller)
- }
-
- @Test
- fun onPanelExpansionChanged_inSplitShade_forwardsToSplitShadeOverScroller() {
- initLateProperties()
- enableSplitShade()
-
- startPanelExpansion()
-
- verify(splitShadeOverScroller).onPanelStateChanged(STATE_OPENING)
- verify(splitShadeOverScroller).onDragDownAmountChanged(DEFAULT_DRAG_DOWN_AMOUNT)
- verifyZeroInteractions(noOpOverScroller)
- }
-
- @Test
- fun onPanelStateChanged_inSplitShade_propertiesNotInitialized_forwardsToNoOpOverScroller() {
- enableSplitShade()
-
- startPanelExpansion()
-
- verify(noOpOverScroller).onPanelStateChanged(STATE_OPENING)
- verify(noOpOverScroller).onDragDownAmountChanged(DEFAULT_DRAG_DOWN_AMOUNT)
- verifyZeroInteractions(splitShadeOverScroller)
- }
-
- @Test
- fun onPanelStateChanged_inSplitShade_onKeyguard_forwardsToNoOpOverScroller() {
- initLateProperties()
- enableSplitShade()
- setOnKeyguard()
-
- startPanelExpansion()
-
- verify(noOpOverScroller).onPanelStateChanged(STATE_OPENING)
- verify(noOpOverScroller).onDragDownAmountChanged(DEFAULT_DRAG_DOWN_AMOUNT)
- verifyZeroInteractions(splitShadeOverScroller)
- }
-
- @Test
- fun onPanelStateChanged_inSplitShade_onLockedShade_forwardsToNoOpOverScroller() {
- initLateProperties()
- enableSplitShade()
- setOnLockedShade()
-
- startPanelExpansion()
-
- verify(noOpOverScroller).onPanelStateChanged(STATE_OPENING)
- verify(noOpOverScroller).onDragDownAmountChanged(DEFAULT_DRAG_DOWN_AMOUNT)
- verifyZeroInteractions(splitShadeOverScroller)
- }
-
- @Test
- fun onPanelExpansionChanged_inSplitShade_onUnlockedShade_forwardsToSplitShadeOverScroller() {
- initLateProperties()
- enableSplitShade()
- setOnUnlockedShade()
-
- startPanelExpansion()
-
- verify(splitShadeOverScroller).onPanelStateChanged(STATE_OPENING)
- verify(splitShadeOverScroller).onDragDownAmountChanged(DEFAULT_DRAG_DOWN_AMOUNT)
- verifyZeroInteractions(noOpOverScroller)
- }
-
- @Test
- fun onPanelStateChanged_notInSplitShade_forwardsToNoOpOverScroller() {
- initLateProperties()
- disableSplitShade()
-
- startPanelExpansion()
-
- verify(noOpOverScroller).onPanelStateChanged(STATE_OPENING)
- verify(noOpOverScroller).onDragDownAmountChanged(DEFAULT_DRAG_DOWN_AMOUNT)
- verifyZeroInteractions(splitShadeOverScroller)
}
@Test
fun onPanelStateChanged_forwardsToScrimTransitionController() {
- initLateProperties()
-
startPanelExpansion()
verify(scrimShadeTransitionController).onPanelStateChanged(STATE_OPENING)
verify(scrimShadeTransitionController).onPanelExpansionChanged(DEFAULT_EXPANSION_EVENT)
}
- private fun initLateProperties() {
- controller.qs = qs
- controller.notificationStackScrollLayoutController = nsslController
- controller.notificationPanelViewController = npvc
- }
-
- private fun disableSplitShade() {
- setSplitShadeEnabled(false)
- }
-
- private fun enableSplitShade() {
- setSplitShadeEnabled(true)
- }
-
- private fun setSplitShadeEnabled(enabled: Boolean) {
- overrideResource(R.bool.config_use_split_notification_shade, enabled)
- configurationController.notifyConfigurationChanged()
- }
-
private fun startPanelExpansion() {
shadeExpansionStateManager.onPanelExpansionChanged(
DEFAULT_EXPANSION_EVENT.fraction,
@@ -174,23 +61,6 @@ class ShadeTransitionControllerTest : SysuiTestCase() {
)
}
- private fun setOnKeyguard() {
- setShadeState(StatusBarState.KEYGUARD)
- }
-
- private fun setOnLockedShade() {
- setShadeState(StatusBarState.SHADE_LOCKED)
- }
-
- private fun setOnUnlockedShade() {
- setShadeState(StatusBarState.SHADE)
- }
-
- private fun setShadeState(state: Int) {
- whenever(statusBarStateController.state).thenReturn(state)
- whenever(statusBarStateController.currentOrUpcomingState).thenReturn(state)
- }
-
companion object {
private const val DEFAULT_DRAG_DOWN_AMOUNT = 123f
private val DEFAULT_EXPANSION_EVENT =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/SplitShadeOverScrollerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/SplitShadeOverScrollerTest.kt
deleted file mode 100644
index 0e48b4835dfe..000000000000
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/SplitShadeOverScrollerTest.kt
+++ /dev/null
@@ -1,112 +0,0 @@
-package com.android.systemui.shade.transition
-
-import android.testing.AndroidTestingRunner
-import android.testing.TestableLooper
-import androidx.test.filters.SmallTest
-import com.android.systemui.R
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.plugins.qs.QS
-import com.android.systemui.shade.STATE_CLOSED
-import com.android.systemui.shade.STATE_OPEN
-import com.android.systemui.shade.STATE_OPENING
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
-import com.android.systemui.statusbar.phone.ScrimController
-import com.android.systemui.statusbar.policy.FakeConfigurationController
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito.atLeastOnce
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.verifyZeroInteractions
-import org.mockito.Mockito.`when` as whenever
-import org.mockito.MockitoAnnotations
-
-@RunWith(AndroidTestingRunner::class)
-@TestableLooper.RunWithLooper(setAsMainLooper = true)
-@SmallTest
-class SplitShadeOverScrollerTest : SysuiTestCase() {
-
- @Mock private lateinit var dumpManager: DumpManager
- @Mock private lateinit var scrimController: ScrimController
- @Mock private lateinit var qs: QS
- @Mock private lateinit var nsslController: NotificationStackScrollLayoutController
-
- private val configurationController = FakeConfigurationController()
- private lateinit var overScroller: SplitShadeOverScroller
-
- @Before
- fun setUp() {
- MockitoAnnotations.initMocks(this)
-
- whenever(nsslController.height).thenReturn(1000)
- overScroller =
- SplitShadeOverScroller(
- configurationController,
- dumpManager,
- context,
- scrimController,
- { qs },
- { nsslController })
- }
-
- @Test
- fun onDragDownAmountChanged_panelOpening_overScrolls_basedOnHeightAndMaxAmount() {
- val maxOverScrollAmount = 50
- val dragDownAmount = 100f
- overrideResource(R.dimen.shade_max_over_scroll_amount, maxOverScrollAmount)
- configurationController.notifyConfigurationChanged()
-
- overScroller.onPanelStateChanged(STATE_OPENING)
- overScroller.onDragDownAmountChanged(dragDownAmount)
-
- val expectedOverScrollAmount =
- (dragDownAmount / nsslController.height * maxOverScrollAmount).toInt()
- verify(qs).setOverScrollAmount(expectedOverScrollAmount)
- verify(nsslController).setOverScrollAmount(expectedOverScrollAmount)
- verify(scrimController).setNotificationsOverScrollAmount(expectedOverScrollAmount)
- }
-
- @Test
- fun onDragDownAmountChanged_panelClosed_doesNotOverScroll() {
- overScroller.onPanelStateChanged(STATE_CLOSED)
- overScroller.onDragDownAmountChanged(100f)
-
- verifyZeroInteractions(qs, scrimController, nsslController)
- }
-
- @Test
- fun onDragDownAmountChanged_panelOpen_doesNotOverScroll() {
- overScroller.onPanelStateChanged(STATE_OPEN)
- overScroller.onDragDownAmountChanged(100f)
-
- verifyZeroInteractions(qs, scrimController, nsslController)
- }
-
- @Test
- fun onPanelStateChanged_opening_thenOpen_releasesOverScroll() {
- overScroller.onPanelStateChanged(STATE_OPENING)
- overScroller.onDragDownAmountChanged(100f)
-
- overScroller.onPanelStateChanged(STATE_OPEN)
- overScroller.finishAnimations()
-
- verify(qs, atLeastOnce()).setOverScrollAmount(0)
- verify(scrimController, atLeastOnce()).setNotificationsOverScrollAmount(0)
- verify(nsslController, atLeastOnce()).setOverScrollAmount(0)
- }
-
- @Test
- fun onPanelStateChanged_opening_thenClosed_releasesOverScroll() {
- overScroller.onPanelStateChanged(STATE_OPENING)
- overScroller.onDragDownAmountChanged(100f)
-
- overScroller.onPanelStateChanged(STATE_CLOSED)
- overScroller.finishAnimations()
-
- verify(qs, atLeastOnce()).setOverScrollAmount(0)
- verify(scrimController, atLeastOnce()).setNotificationsOverScrollAmount(0)
- verify(nsslController, atLeastOnce()).setOverScrollAmount(0)
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
index 413767a19999..fe18fb53aecb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/AlertingNotificationManagerTest.java
@@ -200,20 +200,6 @@ public class AlertingNotificationManagerTest extends SysuiTestCase {
}
@Test
- public void testShowNotification_stickyHun_earliestRemovalTime() {
- NotificationEntry notifEntry = new NotificationEntryBuilder()
- .setSbn(createStickySbn(/* id= */ 0))
- .build();
- notifEntry.setCreationElapsedRealTime(0);
-
- mAlertingNotificationManager.showNotification(notifEntry);
-
- final long earliestRemovalTime = mAlertingNotificationManager
- .getCalculatedEarliestRemovalTime(notifEntry.getKey());
- assertEquals(TEST_STICKY_DISPLAY_TIME, earliestRemovalTime);
- }
-
- @Test
public void testRemoveNotification_removeDeferred() {
mAlertingNotificationManager.showNotification(mEntry);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
index 7fdcfb210804..2de57051d4f2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceControllerTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.lockscreen
+import android.app.smartspace.SmartspaceAction
import android.app.smartspace.SmartspaceManager
import android.app.smartspace.SmartspaceSession
import android.app.smartspace.SmartspaceSession.OnTargetsAvailableListener
@@ -26,6 +27,7 @@ import android.content.pm.UserInfo
import android.database.ContentObserver
import android.graphics.drawable.Drawable
import android.net.Uri
+import android.os.Bundle
import android.os.Handler
import android.os.UserHandle
import android.provider.Settings
@@ -43,6 +45,7 @@ import com.android.systemui.plugins.BcSmartspaceDataPlugin
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceTargetListener
import com.android.systemui.plugins.BcSmartspaceDataPlugin.SmartspaceView
import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.plugins.WeatherData
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener
import com.android.systemui.settings.UserTracker
@@ -54,6 +57,7 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceP
import com.android.systemui.util.concurrency.FakeExecution
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.argThat
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.settings.SecureSettings
@@ -69,6 +73,7 @@ import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.mock
import org.mockito.Mockito.never
import org.mockito.Mockito.spy
+import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
import java.util.Optional
@@ -76,6 +81,13 @@ import java.util.concurrent.Executor
@SmallTest
class LockscreenSmartspaceControllerTest : SysuiTestCase() {
+ companion object {
+ const val SMARTSPACE_TIME_TOO_EARLY = 1000L
+ const val SMARTSPACE_TIME_JUST_RIGHT = 4000L
+ const val SMARTSPACE_TIME_TOO_LATE = 9000L
+ const val SMARTSPACE_CREATION_TIME = 1234L
+ const val SMARTSPACE_EXPIRY_TIME = 5678L
+ }
@Mock
private lateinit var featureFlags: FeatureFlags
@Mock
@@ -224,6 +236,7 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
smartspaceManager,
activityStarter,
falsingManager,
+ clock,
secureSettings,
userTracker,
contentResolver,
@@ -529,6 +542,190 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
}
@Test
+ fun testSessionListener_ifWeatherExtraMissing_thenWeatherDataNotSent() {
+ connectSession()
+ clock.setCurrentTimeMillis(SMARTSPACE_TIME_JUST_RIGHT)
+ // WHEN we receive a list of targets
+ val targets = listOf(
+ makeTarget(1, userHandlePrimary, isSensitive = true),
+ makeTarget(2, userHandlePrimary, featureType = SmartspaceTarget.FEATURE_WEATHER)
+
+ )
+ sessionListener.onTargetsAvailable(targets)
+ verify(keyguardUpdateMonitor, times(0)).sendWeatherData(any())
+ }
+
+ @Test
+ fun testSessionListener_ifWeatherExtraIsMissingValues_thenWeatherDataNotSent() {
+ connectSession()
+
+ clock.setCurrentTimeMillis(SMARTSPACE_TIME_JUST_RIGHT)
+ // WHEN we receive a list of targets
+ val targets = listOf(
+ makeTarget(1, userHandlePrimary, isSensitive = true),
+ makeWeatherTargetWithExtras(
+ id = 2,
+ userHandle = userHandlePrimary,
+ description = null,
+ state = WeatherData.WeatherStateIcon.SUNNY.id,
+ temperature = "32",
+ useCelsius = null)
+
+ )
+
+ sessionListener.onTargetsAvailable(targets)
+
+ verify(keyguardUpdateMonitor, times(0)).sendWeatherData(any())
+ }
+
+ @Test
+ fun testSessionListener_ifTooEarly_thenWeatherDataNotSent() {
+ connectSession()
+
+ clock.setCurrentTimeMillis(SMARTSPACE_TIME_TOO_EARLY)
+ // WHEN we receive a list of targets
+ val targets = listOf(
+ makeWeatherTargetWithExtras(
+ id = 1,
+ userHandle = userHandleManaged,
+ description = "Sunny",
+ state = WeatherData.WeatherStateIcon.SUNNY.id,
+ temperature = "32",
+ useCelsius = false)
+ )
+ sessionListener.onTargetsAvailable(targets)
+ verify(keyguardUpdateMonitor, times(0)).sendWeatherData(any())
+ }
+
+ @Test
+ fun testSessionListener_ifOnTime_thenWeatherDataSent() {
+ connectSession()
+
+ clock.setCurrentTimeMillis(SMARTSPACE_TIME_JUST_RIGHT)
+ // WHEN we receive a list of targets
+ val targets = listOf(
+ makeWeatherTargetWithExtras(
+ id = 1,
+ userHandle = userHandleManaged,
+ description = "Snow Showers",
+ state = WeatherData.WeatherStateIcon.SNOW_SHOWERS_SNOW.id,
+ temperature = "-1",
+ useCelsius = false)
+ )
+ sessionListener.onTargetsAvailable(targets)
+ verify(keyguardUpdateMonitor).sendWeatherData(argThat { w ->
+ w.description == "Snow Showers" &&
+ w.state == WeatherData.WeatherStateIcon.SNOW_SHOWERS_SNOW &&
+ w.temperature == -1 && !w.useCelsius
+ })
+ }
+
+ @Test
+ fun testSessionListener_ifTooLate_thenWeatherDataNotSent() {
+ connectSession()
+
+ clock.setCurrentTimeMillis(SMARTSPACE_TIME_TOO_LATE)
+ // WHEN we receive a list of targets
+ val targets = listOf(
+ makeWeatherTargetWithExtras(
+ id = 1,
+ userHandle = userHandleManaged,
+ description = "Sunny",
+ state = WeatherData.WeatherStateIcon.SUNNY.id,
+ temperature = "72",
+ useCelsius = false)
+ )
+ sessionListener.onTargetsAvailable(targets)
+ verify(keyguardUpdateMonitor, times(0)).sendWeatherData(any())
+ }
+
+ @Test
+ fun testSessionListener_onlyFirstWeatherDataSent() {
+ connectSession()
+
+ clock.setCurrentTimeMillis(SMARTSPACE_TIME_JUST_RIGHT)
+ // WHEN we receive a list of targets
+ val targets = listOf(
+ makeWeatherTargetWithExtras(
+ id = 1,
+ userHandle = userHandleManaged,
+ description = "Sunny",
+ state = WeatherData.WeatherStateIcon.SUNNY.id,
+ temperature = "72",
+ useCelsius = false),
+ makeWeatherTargetWithExtras(
+ id = 2,
+ userHandle = userHandleManaged,
+ description = "Showers",
+ state = WeatherData.WeatherStateIcon.SHOWERS_RAIN.id,
+ temperature = "62",
+ useCelsius = true)
+ )
+ sessionListener.onTargetsAvailable(targets)
+ verify(keyguardUpdateMonitor).sendWeatherData(argThat { w ->
+ w.description == "Sunny" &&
+ w.state == WeatherData.WeatherStateIcon.SUNNY &&
+ w.temperature == 72 && !w.useCelsius
+ })
+ }
+
+ @Test
+ fun testSessionListener_ifDecouplingEnabled_weatherDataUpdates() {
+ `when`(featureFlags.isEnabled(Flags.SMARTSPACE_DATE_WEATHER_DECOUPLED)).thenReturn(true)
+ connectSession()
+
+ clock.setCurrentTimeMillis(SMARTSPACE_TIME_JUST_RIGHT)
+ // WHEN we receive a list of targets
+ val targets = listOf(
+ makeTarget(1, userHandlePrimary, isSensitive = true),
+ makeTarget(2, userHandlePrimary),
+ makeTarget(3, userHandleManaged),
+ makeWeatherTargetWithExtras(
+ id = 4,
+ userHandle = userHandlePrimary,
+ description = "Flurries",
+ state = WeatherData.WeatherStateIcon.FLURRIES.id,
+ temperature = "0",
+ useCelsius = true)
+ )
+
+ sessionListener.onTargetsAvailable(targets)
+
+ verify(keyguardUpdateMonitor).sendWeatherData(argThat { w ->
+ w.description == "Flurries" &&
+ w.state == WeatherData.WeatherStateIcon.FLURRIES &&
+ w.temperature == 0 && w.useCelsius
+ })
+ }
+
+ @Test
+ fun testSessionListener_ifDecouplingDisabled_weatherDataUpdates() {
+ `when`(featureFlags.isEnabled(Flags.SMARTSPACE_DATE_WEATHER_DECOUPLED)).thenReturn(false)
+ connectSession()
+
+ clock.setCurrentTimeMillis(SMARTSPACE_TIME_JUST_RIGHT)
+ // WHEN we receive a list of targets
+ val targets = listOf(
+ makeWeatherTargetWithExtras(
+ id = 1,
+ userHandle = userHandlePrimary,
+ description = "Sunny",
+ state = WeatherData.WeatherStateIcon.SUNNY.id,
+ temperature = "32",
+ useCelsius = false),
+ makeTarget(2, userHandlePrimary, isSensitive = true)
+ )
+
+ sessionListener.onTargetsAvailable(targets)
+
+ verify(keyguardUpdateMonitor).sendWeatherData(argThat { w ->
+ w.description == "Sunny" &&
+ w.state == WeatherData.WeatherStateIcon.SUNNY &&
+ w.temperature == 32 && !w.useCelsius
+ })
+ }
+
+ @Test
fun testSettingsAreReloaded() {
// GIVEN a connected session where the privacy settings later flip to false
connectSession()
@@ -740,7 +937,7 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
return userInfo
}
- fun makeTarget(
+ private fun makeTarget(
id: Int,
userHandle: UserHandle,
isSensitive: Boolean = false,
@@ -755,6 +952,38 @@ class LockscreenSmartspaceControllerTest : SysuiTestCase() {
.build()
}
+ private fun makeWeatherTargetWithExtras(
+ id: Int,
+ userHandle: UserHandle,
+ description: String?,
+ state: Int?,
+ temperature: String?,
+ useCelsius: Boolean?
+ ): SmartspaceTarget {
+ val mockWeatherBundle = mock(Bundle::class.java).apply {
+ `when`(getString(WeatherData.DESCRIPTION_KEY)).thenReturn(description)
+ if (state != null)
+ `when`(getInt(eq(WeatherData.STATE_KEY), any())).thenReturn(state)
+ `when`(getString(WeatherData.TEMPERATURE_KEY)).thenReturn(temperature)
+ `when`(containsKey(WeatherData.USE_CELSIUS_KEY)).thenReturn(useCelsius != null)
+ if (useCelsius != null)
+ `when`(getBoolean(WeatherData.USE_CELSIUS_KEY)).thenReturn(useCelsius)
+ }
+
+ val mockBaseAction = mock(SmartspaceAction::class.java)
+ `when`(mockBaseAction.extras).thenReturn(mockWeatherBundle)
+ return SmartspaceTarget.Builder(
+ "targetWithWeatherExtras$id",
+ ComponentName("testpackage", "testclass$id"),
+ userHandle)
+ .setSensitive(false)
+ .setFeatureType(SmartspaceTarget.FEATURE_WEATHER)
+ .setBaseAction(mockBaseAction)
+ .setExpiryTimeMillis(SMARTSPACE_EXPIRY_TIME)
+ .setCreationTimeMillis(SMARTSPACE_CREATION_TIME)
+ .build()
+ }
+
private fun setAllowPrivateNotifications(user: UserHandle, value: Boolean) {
`when`(secureSettings.getIntForUser(
eq(PRIVATE_LOCKSCREEN_SETTING),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
index 005c80ab577c..540bda6ea9dc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
@@ -106,6 +106,7 @@ import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.Spy;
+import org.mockito.stubbing.Answer;
import java.util.Arrays;
import java.util.Collection;
@@ -378,6 +379,90 @@ public class NotifCollectionTest extends SysuiTestCase {
}
@Test
+ public void testScheduleBuildNotificationListWhenChannelChanged() {
+ // GIVEN
+ final NotificationEntryBuilder neb = buildNotif(TEST_PACKAGE, 48);
+ final NotificationChannel channel = new NotificationChannel(
+ "channelId",
+ "channelName",
+ NotificationManager.IMPORTANCE_DEFAULT);
+ neb.setChannel(channel);
+
+ final NotifEvent notif = mNoMan.postNotif(neb);
+ final NotificationEntry entry = mCollectionListener.getEntry(notif.key);
+
+ when(mMainHandler.hasCallbacks(any())).thenReturn(false);
+
+ clearInvocations(mBuildListener);
+
+ // WHEN
+ mNotifHandler.onNotificationChannelModified(TEST_PACKAGE,
+ entry.getSbn().getUser(), channel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);
+
+ // THEN
+ verify(mMainHandler).postDelayed(any(), eq(1000L));
+ }
+
+ @Test
+ public void testCancelScheduledBuildNotificationListEventWhenNotifUpdatedSynchronously() {
+ // GIVEN
+ final NotificationEntry entry1 = buildNotif(TEST_PACKAGE, 1)
+ .setGroup(mContext, "group_1")
+ .build();
+ final NotificationEntry entry2 = buildNotif(TEST_PACKAGE, 2)
+ .setGroup(mContext, "group_1")
+ .setContentTitle(mContext, "New version")
+ .build();
+ final NotificationEntry entry3 = buildNotif(TEST_PACKAGE, 3)
+ .setGroup(mContext, "group_1")
+ .build();
+
+ final List<CoalescedEvent> entriesToBePosted = Arrays.asList(
+ new CoalescedEvent(entry1.getKey(), 0, entry1.getSbn(), entry1.getRanking(), null),
+ new CoalescedEvent(entry2.getKey(), 1, entry2.getSbn(), entry2.getRanking(), null),
+ new CoalescedEvent(entry3.getKey(), 2, entry3.getSbn(), entry3.getRanking(), null)
+ );
+
+ when(mMainHandler.hasCallbacks(any())).thenReturn(true);
+
+ // WHEN
+ mNotifHandler.onNotificationBatchPosted(entriesToBePosted);
+
+ // THEN
+ verify(mMainHandler).removeCallbacks(any());
+ }
+
+ @Test
+ public void testBuildNotificationListWhenChannelChanged() {
+ // GIVEN
+ final NotificationEntryBuilder neb = buildNotif(TEST_PACKAGE, 48);
+ final NotificationChannel channel = new NotificationChannel(
+ "channelId",
+ "channelName",
+ NotificationManager.IMPORTANCE_DEFAULT);
+ neb.setChannel(channel);
+
+ final NotifEvent notif = mNoMan.postNotif(neb);
+ final NotificationEntry entry = mCollectionListener.getEntry(notif.key);
+
+ when(mMainHandler.hasCallbacks(any())).thenReturn(false);
+ when(mMainHandler.postDelayed(any(), eq(1000L))).thenAnswer((Answer) invocation -> {
+ final Runnable runnable = invocation.getArgument(0);
+ runnable.run();
+ return null;
+ });
+
+ clearInvocations(mBuildListener);
+
+ // WHEN
+ mNotifHandler.onNotificationChannelModified(TEST_PACKAGE,
+ entry.getSbn().getUser(), channel, NOTIFICATION_CHANNEL_OR_GROUP_UPDATED);
+
+ // THEN
+ verifyBuiltList(List.of(entry));
+ }
+
+ @Test
public void testRankingsAreUpdatedForOtherNotifs() {
// GIVEN a collection with one notif
NotifEvent notif1 = mNoMan.postNotif(buildNotif(TEST_PACKAGE, 3)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLoggerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLoggerTest.kt
index bd039031cecc..33a838ed5183 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLoggerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/logging/NotificationMemoryLoggerTest.kt
@@ -20,6 +20,7 @@ import android.app.Notification
import android.app.StatsManager
import android.graphics.Bitmap
import android.graphics.drawable.Icon
+import android.stats.sysui.NotificationEnums
import android.testing.AndroidTestingRunner
import android.util.StatsEvent
import androidx.test.filters.SmallTest
@@ -31,10 +32,12 @@ 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.google.common.truth.Expect
import com.google.common.truth.Truth.assertThat
import java.lang.RuntimeException
import kotlinx.coroutines.Dispatchers
import org.junit.Before
+import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
@@ -45,6 +48,8 @@ import org.mockito.MockitoAnnotations
@RunWith(AndroidTestingRunner::class)
class NotificationMemoryLoggerTest : SysuiTestCase() {
+ @Rule @JvmField val expect = Expect.create()
+
private val bgExecutor = FakeExecutor(FakeSystemClock())
private val immediate = Dispatchers.Main.immediate
@@ -132,6 +137,123 @@ class NotificationMemoryLoggerTest : SysuiTestCase() {
.isEqualTo(StatsManager.PULL_SKIP)
}
+ @Test
+ fun aggregateMemoryUsageData_returnsCorrectlyAggregatedSamePackageData() {
+ val usage = getPresetMemoryUsages()
+ val aggregateUsage = aggregateMemoryUsageData(usage)
+
+ assertThat(aggregateUsage).hasSize(3)
+ assertThat(aggregateUsage)
+ .containsKey(Pair("package 1", NotificationEnums.STYLE_BIG_PICTURE))
+
+ // Aggregated fields
+ val aggregatedData =
+ aggregateUsage[Pair("package 1", NotificationEnums.STYLE_BIG_PICTURE)]!!
+ val presetUsage1 = usage[0]
+ val presetUsage2 = usage[1]
+ assertAggregatedData(
+ aggregatedData,
+ 2,
+ 2,
+ smallIconObject =
+ presetUsage1.objectUsage.smallIcon + presetUsage2.objectUsage.smallIcon,
+ smallIconBitmapCount = 2,
+ largeIconObject =
+ presetUsage1.objectUsage.largeIcon + presetUsage2.objectUsage.largeIcon,
+ largeIconBitmapCount = 2,
+ bigPictureObject =
+ presetUsage1.objectUsage.bigPicture + presetUsage2.objectUsage.bigPicture,
+ bigPictureBitmapCount = 2,
+ extras = presetUsage1.objectUsage.extras + presetUsage2.objectUsage.extras,
+ extenders = presetUsage1.objectUsage.extender + presetUsage2.objectUsage.extender,
+ // Only totals need to be summarized.
+ smallIconViews =
+ presetUsage1.viewUsage[0].smallIcon + presetUsage2.viewUsage[0].smallIcon,
+ largeIconViews =
+ presetUsage1.viewUsage[0].largeIcon + presetUsage2.viewUsage[0].largeIcon,
+ systemIconViews =
+ presetUsage1.viewUsage[0].systemIcons + presetUsage2.viewUsage[0].systemIcons,
+ styleViews = presetUsage1.viewUsage[0].style + presetUsage2.viewUsage[0].style,
+ customViews =
+ presetUsage1.viewUsage[0].customViews + presetUsage2.viewUsage[0].customViews,
+ softwareBitmaps =
+ presetUsage1.viewUsage[0].softwareBitmapsPenalty +
+ presetUsage2.viewUsage[0].softwareBitmapsPenalty,
+ seenCount = 0
+ )
+ }
+
+ @Test
+ fun aggregateMemoryUsageData_correctlySeparatesDifferentStyles() {
+ val usage = getPresetMemoryUsages()
+ val aggregateUsage = aggregateMemoryUsageData(usage)
+
+ assertThat(aggregateUsage).hasSize(3)
+ assertThat(aggregateUsage)
+ .containsKey(Pair("package 1", NotificationEnums.STYLE_BIG_PICTURE))
+ assertThat(aggregateUsage).containsKey(Pair("package 1", NotificationEnums.STYLE_BIG_TEXT))
+
+ // Different style should be separate
+ val separateStyleData =
+ aggregateUsage[Pair("package 1", NotificationEnums.STYLE_BIG_TEXT)]!!
+ val presetUsage = usage[2]
+ assertAggregatedData(
+ separateStyleData,
+ 1,
+ 1,
+ presetUsage.objectUsage.smallIcon,
+ 1,
+ presetUsage.objectUsage.largeIcon,
+ 1,
+ presetUsage.objectUsage.bigPicture,
+ 1,
+ presetUsage.objectUsage.extras,
+ presetUsage.objectUsage.extender,
+ presetUsage.viewUsage[0].smallIcon,
+ presetUsage.viewUsage[0].largeIcon,
+ presetUsage.viewUsage[0].systemIcons,
+ presetUsage.viewUsage[0].style,
+ presetUsage.viewUsage[0].customViews,
+ presetUsage.viewUsage[0].softwareBitmapsPenalty,
+ 0
+ )
+ }
+
+ @Test
+ fun aggregateMemoryUsageData_correctlySeparatesDifferentProcess() {
+ val usage = getPresetMemoryUsages()
+ val aggregateUsage = aggregateMemoryUsageData(usage)
+
+ assertThat(aggregateUsage).hasSize(3)
+ assertThat(aggregateUsage)
+ .containsKey(Pair("package 2", NotificationEnums.STYLE_BIG_PICTURE))
+
+ // Different UID/package should also be separate
+ val separatePackageData =
+ aggregateUsage[Pair("package 2", NotificationEnums.STYLE_BIG_PICTURE)]!!
+ val presetUsage = usage[3]
+ assertAggregatedData(
+ separatePackageData,
+ 1,
+ 1,
+ presetUsage.objectUsage.smallIcon,
+ 1,
+ presetUsage.objectUsage.largeIcon,
+ 1,
+ presetUsage.objectUsage.bigPicture,
+ 1,
+ presetUsage.objectUsage.extras,
+ presetUsage.objectUsage.extender,
+ presetUsage.viewUsage[0].smallIcon,
+ presetUsage.viewUsage[0].largeIcon,
+ presetUsage.viewUsage[0].systemIcons,
+ presetUsage.viewUsage[0].style,
+ presetUsage.viewUsage[0].customViews,
+ presetUsage.viewUsage[0].softwareBitmapsPenalty,
+ 0
+ )
+ }
+
private fun createLoggerWithNotifications(
notifications: List<Notification>
): NotificationMemoryLogger {
@@ -143,4 +265,182 @@ class NotificationMemoryLoggerTest : SysuiTestCase() {
whenever(pipeline.allNotifs).thenReturn(notifications)
return NotificationMemoryLogger(pipeline, statsManager, immediate, bgExecutor)
}
+
+ /**
+ * Short hand for making sure the passed NotificationMemoryUseAtomBuilder object contains
+ * expected values.
+ */
+ private fun assertAggregatedData(
+ value: NotificationMemoryLogger.NotificationMemoryUseAtomBuilder,
+ count: Int,
+ countWithInflatedViews: Int,
+ smallIconObject: Int,
+ smallIconBitmapCount: Int,
+ largeIconObject: Int,
+ largeIconBitmapCount: Int,
+ bigPictureObject: Int,
+ bigPictureBitmapCount: Int,
+ extras: Int,
+ extenders: Int,
+ smallIconViews: Int,
+ largeIconViews: Int,
+ systemIconViews: Int,
+ styleViews: Int,
+ customViews: Int,
+ softwareBitmaps: Int,
+ seenCount: Int
+ ) {
+ expect.withMessage("count").that(value.count).isEqualTo(count)
+ expect
+ .withMessage("countWithInflatedViews")
+ .that(value.countWithInflatedViews)
+ .isEqualTo(countWithInflatedViews)
+ expect.withMessage("smallIconObject").that(value.smallIconObject).isEqualTo(smallIconObject)
+ expect
+ .withMessage("smallIconBitmapCount")
+ .that(value.smallIconBitmapCount)
+ .isEqualTo(smallIconBitmapCount)
+ expect.withMessage("largeIconObject").that(value.largeIconObject).isEqualTo(largeIconObject)
+ expect
+ .withMessage("largeIconBitmapCount")
+ .that(value.largeIconBitmapCount)
+ .isEqualTo(largeIconBitmapCount)
+ expect
+ .withMessage("bigPictureObject")
+ .that(value.bigPictureObject)
+ .isEqualTo(bigPictureObject)
+ expect
+ .withMessage("bigPictureBitmapCount")
+ .that(value.bigPictureBitmapCount)
+ .isEqualTo(bigPictureBitmapCount)
+ expect.withMessage("extras").that(value.extras).isEqualTo(extras)
+ expect.withMessage("extenders").that(value.extenders).isEqualTo(extenders)
+ expect.withMessage("smallIconViews").that(value.smallIconViews).isEqualTo(smallIconViews)
+ expect.withMessage("largeIconViews").that(value.largeIconViews).isEqualTo(largeIconViews)
+ expect.withMessage("systemIconViews").that(value.systemIconViews).isEqualTo(systemIconViews)
+ expect.withMessage("styleViews").that(value.styleViews).isEqualTo(styleViews)
+ expect.withMessage("customViews").that(value.customViews).isEqualTo(customViews)
+ expect.withMessage("softwareBitmaps").that(value.softwareBitmaps).isEqualTo(softwareBitmaps)
+ expect.withMessage("seenCount").that(value.seenCount).isEqualTo(seenCount)
+ }
+
+ /** Generates a static set of [NotificationMemoryUsage] objects. */
+ private fun getPresetMemoryUsages() =
+ listOf(
+ // A pair of notifications that have to be aggregated, same UID and style
+ NotificationMemoryUsage(
+ "package 1",
+ 384,
+ "key1",
+ Notification.Builder(context).setStyle(Notification.BigPictureStyle()).build(),
+ NotificationObjectUsage(
+ 23,
+ 45,
+ 67,
+ NotificationEnums.STYLE_BIG_PICTURE,
+ 12,
+ 483,
+ 4382,
+ true
+ ),
+ listOf(
+ NotificationViewUsage(ViewType.TOTAL, 493, 584, 4833, 584, 4888, 5843),
+ NotificationViewUsage(
+ ViewType.PRIVATE_CONTRACTED_VIEW,
+ 100,
+ 250,
+ 300,
+ 594,
+ 6000,
+ 5843
+ )
+ )
+ ),
+ NotificationMemoryUsage(
+ "package 1",
+ 384,
+ "key2",
+ Notification.Builder(context).setStyle(Notification.BigPictureStyle()).build(),
+ NotificationObjectUsage(
+ 77,
+ 54,
+ 34,
+ NotificationEnums.STYLE_BIG_PICTURE,
+ 77,
+ 432,
+ 2342,
+ true
+ ),
+ listOf(
+ NotificationViewUsage(ViewType.TOTAL, 3245, 1234, 7653, 543, 765, 7655),
+ NotificationViewUsage(
+ ViewType.PRIVATE_CONTRACTED_VIEW,
+ 160,
+ 350,
+ 300,
+ 5544,
+ 66500,
+ 5433
+ )
+ )
+ ),
+ // Different style is different aggregation
+ NotificationMemoryUsage(
+ "package 1",
+ 384,
+ "key2",
+ Notification.Builder(context).setStyle(Notification.BigTextStyle()).build(),
+ NotificationObjectUsage(
+ 77,
+ 54,
+ 34,
+ NotificationEnums.STYLE_BIG_TEXT,
+ 77,
+ 432,
+ 2342,
+ true
+ ),
+ listOf(
+ NotificationViewUsage(ViewType.TOTAL, 3245, 1234, 7653, 543, 765, 7655),
+ NotificationViewUsage(
+ ViewType.PRIVATE_CONTRACTED_VIEW,
+ 160,
+ 350,
+ 300,
+ 5544,
+ 66500,
+ 5433
+ )
+ )
+ ),
+ // Different package is also different aggregation
+ NotificationMemoryUsage(
+ "package 2",
+ 684,
+ "key2",
+ Notification.Builder(context).setStyle(Notification.BigPictureStyle()).build(),
+ NotificationObjectUsage(
+ 32,
+ 654,
+ 234,
+ NotificationEnums.STYLE_BIG_PICTURE,
+ 211,
+ 776,
+ 435,
+ true
+ ),
+ listOf(
+ NotificationViewUsage(ViewType.TOTAL, 4355, 6543, 4322, 5435, 6546, 65485),
+ NotificationViewUsage(
+ ViewType.PRIVATE_CONTRACTED_VIEW,
+ 6546,
+ 7657,
+ 4353,
+ 6546,
+ 76575,
+ 54654
+ )
+ )
+ )
+ )
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index d8446f4721b3..1aad83eb73ae 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -38,6 +38,8 @@ import android.testing.TestableLooper;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewRootImpl;
+import android.view.WindowInsets;
+import android.view.WindowInsetsController;
import android.window.BackEvent;
import android.window.OnBackAnimationCallback;
import android.window.OnBackInvokedCallback;
@@ -65,8 +67,10 @@ import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInt
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback;
import com.android.systemui.keyguard.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.navigationbar.NavigationModeController;
+import com.android.systemui.navigationbar.TaskbarDelegate;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.shade.NotificationPanelViewController;
+import com.android.systemui.shade.NotificationShadeWindowView;
import com.android.systemui.shade.ShadeController;
import com.android.systemui.shade.ShadeExpansionChangeEvent;
import com.android.systemui.shade.ShadeExpansionStateManager;
@@ -123,6 +127,9 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
@Mock private BouncerView mBouncerView;
@Mock private BouncerViewDelegate mBouncerViewDelegate;
@Mock private OnBackAnimationCallback mBouncerViewDelegateBackCallback;
+ @Mock private NotificationShadeWindowView mNotificationShadeWindowView;
+ @Mock private WindowInsetsController mWindowInsetsController;
+ @Mock private TaskbarDelegate mTaskbarDelegate;
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
private PrimaryBouncerCallbackInteractor.PrimaryBouncerExpansionCallback
@@ -151,6 +158,11 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
.isEnabled(Flags.WM_ENABLE_PREDICTIVE_BACK_BOUNCER_ANIM))
.thenReturn(true);
+ when(mCentralSurfaces.getNotificationShadeWindowView())
+ .thenReturn(mNotificationShadeWindowView);
+ when(mNotificationShadeWindowView.getWindowInsetsController())
+ .thenReturn(mWindowInsetsController);
+
mStatusBarKeyguardViewManager =
new StatusBarKeyguardViewManager(
getContext(),
@@ -640,6 +652,14 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
}
@Test
+ public void testHideTaskbar() {
+ when(mTaskbarDelegate.isInitialized()).thenReturn(true);
+ mStatusBarKeyguardViewManager.setTaskbarDelegate(mTaskbarDelegate);
+ mStatusBarKeyguardViewManager.updateNavigationBarVisibility(false);
+ verify(mWindowInsetsController).hide(WindowInsets.Type.navigationBars());
+ }
+
+ @Test
public void hideAlternateBouncer_beforeCentralSurfacesRegistered() {
mStatusBarKeyguardViewManager =
new StatusBarKeyguardViewManager(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleShaderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleShaderTest.kt
new file mode 100644
index 000000000000..89cc18cc5d67
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/surfaceeffects/ripple/RippleShaderTest.kt
@@ -0,0 +1,121 @@
+/*
+ * 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.surfaceeffects.ripple
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+class RippleShaderTest : SysuiTestCase() {
+
+ private lateinit var rippleShader: RippleShader
+
+ @Before
+ fun setup() {
+ rippleShader = RippleShader()
+ }
+
+ @Test
+ fun setMaxSize_hasCorrectSizes() {
+ val expectedMaxWidth = 300f
+ val expectedMaxHeight = 500f
+
+ rippleShader.rippleSize.setMaxSize(expectedMaxWidth, expectedMaxHeight)
+
+ assertThat(rippleShader.rippleSize.sizes.size).isEqualTo(2)
+ assertThat(rippleShader.rippleSize.sizes[0]).isEqualTo(rippleShader.rippleSize.initialSize)
+ val maxSize = rippleShader.rippleSize.sizes[1]
+ assertThat(maxSize.t).isEqualTo(1f)
+ assertThat(maxSize.width).isEqualTo(expectedMaxWidth)
+ assertThat(maxSize.height).isEqualTo(expectedMaxHeight)
+ }
+
+ @Test
+ fun setSizeAtProgresses_hasCorrectSizes() {
+ val expectedSize0 = RippleShader.SizeAtProgress(t = 0f, width = 100f, height = 100f)
+ val expectedSize1 = RippleShader.SizeAtProgress(t = 0.2f, width = 1500f, height = 1200f)
+ val expectedSize2 = RippleShader.SizeAtProgress(t = 0.4f, width = 200f, height = 70f)
+
+ rippleShader.rippleSize.setSizeAtProgresses(expectedSize0, expectedSize1, expectedSize2)
+
+ assertThat(rippleShader.rippleSize.sizes.size).isEqualTo(3)
+ assertThat(rippleShader.rippleSize.sizes[0]).isEqualTo(expectedSize0)
+ assertThat(rippleShader.rippleSize.sizes[1]).isEqualTo(expectedSize1)
+ assertThat(rippleShader.rippleSize.sizes[2]).isEqualTo(expectedSize2)
+ }
+
+ @Test
+ fun setSizeAtProgresses_sizeListIsSortedByT() {
+ val expectedSize0 = RippleShader.SizeAtProgress(t = 0f, width = 100f, height = 100f)
+ val expectedSize1 = RippleShader.SizeAtProgress(t = 0.2f, width = 1500f, height = 1200f)
+ val expectedSize2 = RippleShader.SizeAtProgress(t = 0.4f, width = 200f, height = 70f)
+ val expectedSize3 = RippleShader.SizeAtProgress(t = 0.8f, width = 300f, height = 900f)
+ val expectedSize4 = RippleShader.SizeAtProgress(t = 1f, width = 500f, height = 300f)
+
+ // Add them in unsorted order
+ rippleShader.rippleSize.setSizeAtProgresses(
+ expectedSize0,
+ expectedSize3,
+ expectedSize2,
+ expectedSize4,
+ expectedSize1
+ )
+
+ assertThat(rippleShader.rippleSize.sizes.size).isEqualTo(5)
+ assertThat(rippleShader.rippleSize.sizes[0]).isEqualTo(expectedSize0)
+ assertThat(rippleShader.rippleSize.sizes[1]).isEqualTo(expectedSize1)
+ assertThat(rippleShader.rippleSize.sizes[2]).isEqualTo(expectedSize2)
+ assertThat(rippleShader.rippleSize.sizes[3]).isEqualTo(expectedSize3)
+ assertThat(rippleShader.rippleSize.sizes[4]).isEqualTo(expectedSize4)
+ }
+
+ @Test
+ fun update_getsCorrectNextTargetSize() {
+ val expectedSize0 = RippleShader.SizeAtProgress(t = 0f, width = 100f, height = 100f)
+ val expectedSize1 = RippleShader.SizeAtProgress(t = 0.2f, width = 1500f, height = 1200f)
+ val expectedSize2 = RippleShader.SizeAtProgress(t = 0.4f, width = 200f, height = 70f)
+ val expectedSize3 = RippleShader.SizeAtProgress(t = 0.8f, width = 300f, height = 900f)
+ val expectedSize4 = RippleShader.SizeAtProgress(t = 1f, width = 500f, height = 300f)
+
+ rippleShader.rippleSize.setSizeAtProgresses(
+ expectedSize0,
+ expectedSize1,
+ expectedSize2,
+ expectedSize3,
+ expectedSize4
+ )
+
+ rippleShader.rippleSize.update(0.5f)
+ // Progress is between 0.4 and 0.8 (expectedSize3 and 4), so the index should be 3.
+ assertThat(rippleShader.rippleSize.currentSizeIndex).isEqualTo(3)
+ }
+
+ @Test
+ fun update_sizeListIsEmpty_setsInitialSize() {
+ assertThat(rippleShader.rippleSize.sizes).isEmpty()
+
+ rippleShader.rippleSize.update(0.3f)
+
+ assertThat(rippleShader.rippleSize.sizes.size).isEqualTo(1)
+ assertThat(rippleShader.rippleSize.sizes[0]).isEqualTo(rippleShader.rippleSize.initialSize)
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt
index 337421974562..9cdce20bbf1e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardBouncerRepository.kt
@@ -21,6 +21,7 @@ import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.E
import com.android.systemui.keyguard.shared.model.BouncerShowMessageModel
import com.android.systemui.keyguard.shared.model.KeyguardBouncerModel
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
/** Fake implementation of [KeyguardRepository] */
@@ -44,8 +45,6 @@ class FakeKeyguardBouncerRepository : KeyguardBouncerRepository {
override val panelExpansionAmount = _panelExpansionAmount.asStateFlow()
private val _keyguardPosition = MutableStateFlow(0f)
override val keyguardPosition = _keyguardPosition.asStateFlow()
- private val _onScreenTurnedOff = MutableStateFlow(false)
- override val onScreenTurnedOff = _onScreenTurnedOff.asStateFlow()
private val _isBackButtonEnabled = MutableStateFlow<Boolean?>(null)
override val isBackButtonEnabled = _isBackButtonEnabled.asStateFlow()
private val _keyguardAuthenticated = MutableStateFlow<Boolean?>(null)
@@ -61,6 +60,8 @@ class FakeKeyguardBouncerRepository : KeyguardBouncerRepository {
override var lastAlternateBouncerVisibleTime: Long = 0L
private val _isAlternateBouncerUIAvailable = MutableStateFlow<Boolean>(false)
override val alternateBouncerUIAvailable = _isAlternateBouncerUIAvailable.asStateFlow()
+ private val _sideFpsShowing: MutableStateFlow<Boolean> = MutableStateFlow(false)
+ override val sideFpsShowing: StateFlow<Boolean> = _sideFpsShowing.asStateFlow()
override fun setPrimaryScrimmed(isScrimmed: Boolean) {
_primaryBouncerScrimmed.value = isScrimmed
@@ -122,7 +123,7 @@ class FakeKeyguardBouncerRepository : KeyguardBouncerRepository {
_isBackButtonEnabled.value = isBackButtonEnabled
}
- override fun setOnScreenTurnedOff(onScreenTurnedOff: Boolean) {
- _onScreenTurnedOff.value = onScreenTurnedOff
+ override fun setSideFpsShowing(isShowing: Boolean) {
+ _sideFpsShowing.value = isShowing
}
}
diff --git a/services/Android.bp b/services/Android.bp
index f8097ec1bb92..6e6c55325e3d 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -195,6 +195,10 @@ java_library {
"manifest_services.xml",
],
+ required: [
+ "libukey2_jni_shared",
+ ],
+
// Uncomment to enable output of certain warnings (deprecated, unchecked)
//javacflags: ["-Xlint"],
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 328b9719709b..cde820ad1b91 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -4577,6 +4577,17 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub
return false;
}
+ /**
+ * Called when always on magnification feature flag flips to check if the feature should be
+ * enabled for current user state.
+ */
+ public void updateAlwaysOnMagnification() {
+ synchronized (mLock) {
+ readAlwaysOnMagnificationLocked(getCurrentUserState());
+ }
+ }
+
+ @GuardedBy("mLock")
boolean readAlwaysOnMagnificationLocked(AccessibilityUserState userState) {
final boolean isSettingsAlwaysOnEnabled = Settings.Secure.getIntForUser(
mContext.getContentResolver(),
diff --git a/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java b/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
index e6abc4c90fac..eba92305dd7b 100644
--- a/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
+++ b/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
@@ -335,7 +335,7 @@ public class SystemActionPerformer {
KeyEvent event = KeyEvent.obtain(downTime, time, action, keyCode, 0, 0,
KeyCharacterMap.VIRTUAL_KEYBOARD, 0, KeyEvent.FLAG_FROM_SYSTEM,
InputDevice.SOURCE_KEYBOARD, null);
- InputManager.getInstance()
+ mContext.getSystemService(InputManager.class)
.injectInputEvent(event, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
event.recycle();
}
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/AlwaysOnMagnificationFeatureFlag.java b/services/accessibility/java/com/android/server/accessibility/magnification/AlwaysOnMagnificationFeatureFlag.java
index ed45e7b449f4..16d2e6b47a54 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/AlwaysOnMagnificationFeatureFlag.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/AlwaysOnMagnificationFeatureFlag.java
@@ -16,10 +16,13 @@
package com.android.server.accessibility.magnification;
+import android.annotation.NonNull;
import android.provider.DeviceConfig;
import com.android.internal.annotations.VisibleForTesting;
+import java.util.concurrent.Executor;
+
/**
* Encapsulates the feature flags for always on magnification. {@see DeviceConfig}
*
@@ -50,4 +53,39 @@ public class AlwaysOnMagnificationFeatureFlag {
Boolean.toString(isEnabled),
/* makeDefault= */ false);
}
+
+ /**
+ * Adds a listener for when the feature flag changes.
+ *
+ * <p>{@see DeviceConfig#addOnPropertiesChangedListener(
+ * String, Executor, DeviceConfig.OnPropertiesChangedListener)}
+ */
+ @NonNull
+ public static DeviceConfig.OnPropertiesChangedListener addOnChangedListener(
+ @NonNull Executor executor, @NonNull Runnable listener) {
+ DeviceConfig.OnPropertiesChangedListener onChangedListener =
+ properties -> {
+ if (properties.getKeyset().contains(
+ FEATURE_NAME_ENABLE_ALWAYS_ON_MAGNIFICATION)) {
+ listener.run();
+ }
+ };
+ DeviceConfig.addOnPropertiesChangedListener(
+ NAMESPACE,
+ executor,
+ onChangedListener);
+
+ return onChangedListener;
+ }
+
+ /**
+ * Remove a listener for when the feature flag changes.
+ *
+ * <p>{@see DeviceConfig#addOnPropertiesChangedListener(String, Executor,
+ * DeviceConfig.OnPropertiesChangedListener)}
+ */
+ public static void removeOnChangedListener(
+ @NonNull DeviceConfig.OnPropertiesChangedListener onChangedListener) {
+ DeviceConfig.removeOnPropertiesChangedListener(onChangedListener);
+ }
}
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 a6e6bd7d7b66..4753a545adb0 100644
--- a/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
+++ b/services/accessibility/java/com/android/server/accessibility/magnification/MagnificationController.java
@@ -48,6 +48,7 @@ import android.view.accessibility.MagnificationAnimationCallback;
import com.android.internal.accessibility.util.AccessibilityStatsLogUtils;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ConcurrentUtils;
import com.android.server.LocalServices;
import com.android.server.accessibility.AccessibilityManagerService;
import com.android.server.wm.WindowManagerInternal;
@@ -149,6 +150,9 @@ public class MagnificationController implements WindowMagnificationManager.Callb
.getAccessibilityController().setUiChangesForAccessibilityCallbacks(this);
mSupportWindowMagnification = context.getPackageManager().hasSystemFeature(
FEATURE_WINDOW_MAGNIFICATION);
+
+ AlwaysOnMagnificationFeatureFlag.addOnChangedListener(
+ ConcurrentUtils.DIRECT_EXECUTOR, mAms::updateAlwaysOnMagnification);
}
@VisibleForTesting
diff --git a/services/companion/Android.bp b/services/companion/Android.bp
index cdeb2dcf87e9..a248d9e55a8a 100644
--- a/services/companion/Android.bp
+++ b/services/companion/Android.bp
@@ -24,4 +24,7 @@ java_library_static {
"app-compat-annotations",
"services.core",
],
+ static_libs: [
+ "ukey2_jni",
+ ],
}
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index 0f2ba35bd2ab..a35cae9dffda 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -726,6 +726,11 @@ public class CompanionDeviceManagerService extends SystemService {
}
@Override
+ public void enableSecureTransport(boolean enabled) {
+ mTransportManager.enableSecureTransport(enabled);
+ }
+
+ @Override
public void notifyDeviceAppeared(int associationId) {
if (DEBUG) Log.i(TAG, "notifyDevice_Appeared() id=" + associationId);
diff --git a/services/companion/java/com/android/server/companion/RolesUtils.java b/services/companion/java/com/android/server/companion/RolesUtils.java
index f674a7d20b82..163f614fb65d 100644
--- a/services/companion/java/com/android/server/companion/RolesUtils.java
+++ b/services/companion/java/com/android/server/companion/RolesUtils.java
@@ -27,6 +27,7 @@ import android.annotation.UserIdInt;
import android.app.role.RoleManager;
import android.companion.AssociationInfo;
import android.content.Context;
+import android.os.Binder;
import android.os.UserHandle;
import android.util.Log;
import android.util.Slog;
@@ -84,7 +85,9 @@ final class RolesUtils {
Slog.i(TAG, "Removing CDM role holder, role=" + deviceProfile
+ ", package=u" + userId + "\\" + packageName);
- roleManager.removeRoleHolderAsUser(deviceProfile, packageName,
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ roleManager.removeRoleHolderAsUser(deviceProfile, packageName,
MANAGE_HOLDERS_FLAG_DONT_KILL_APP, userHandle, context.getMainExecutor(),
success -> {
if (!success) {
@@ -92,6 +95,9 @@ final class RolesUtils {
+ " from the list of " + deviceProfile + " holders.");
}
});
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
}
private RolesUtils() {};
diff --git a/services/companion/java/com/android/server/companion/securechannel/AttestationVerifier.java b/services/companion/java/com/android/server/companion/securechannel/AttestationVerifier.java
new file mode 100644
index 000000000000..adaee757b96a
--- /dev/null
+++ b/services/companion/java/com/android/server/companion/securechannel/AttestationVerifier.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.companion.securechannel;
+
+import static android.security.attestationverification.AttestationVerificationManager.PARAM_CHALLENGE;
+import static android.security.attestationverification.AttestationVerificationManager.PROFILE_PEER_DEVICE;
+import static android.security.attestationverification.AttestationVerificationManager.TYPE_CHALLENGE;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.os.Bundle;
+import android.security.attestationverification.AttestationProfile;
+import android.security.attestationverification.AttestationVerificationManager;
+import android.security.attestationverification.VerificationToken;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.BiConsumer;
+
+/**
+ * Helper class to perform attestation verification synchronously.
+ */
+class AttestationVerifier {
+ private static final long ATTESTATION_VERIFICATION_TIMEOUT_SECONDS = 10; // 10 seconds
+ private static final String PARAM_OWNED_BY_SYSTEM = "android.key_owned_by_system";
+
+ private final Context mContext;
+
+ AttestationVerifier(Context context) {
+ this.mContext = context;
+ }
+
+ /**
+ * Synchronously verify remote attestation as a suitable peer device on current thread.
+ *
+ * The peer device must be owned by the Android system and be protected with appropriate
+ * public key that this device can verify as attestation challenge.
+ *
+ * @param remoteAttestation the full certificate chain containing attestation extension.
+ * @param attestationChallenge attestation challenge for authentication.
+ * @return true if attestation is successfully verified; false otherwise.
+ */
+ @NonNull
+ public int verifyAttestation(
+ @NonNull byte[] remoteAttestation,
+ @NonNull byte[] attestationChallenge
+ ) throws SecureChannelException {
+ Bundle requirements = new Bundle();
+ requirements.putByteArray(PARAM_CHALLENGE, attestationChallenge);
+ requirements.putBoolean(PARAM_OWNED_BY_SYSTEM, true); // Custom parameter for CDM
+
+ // Synchronously execute attestation verification.
+ AtomicInteger verificationResult = new AtomicInteger(0);
+ CountDownLatch verificationFinished = new CountDownLatch(1);
+ BiConsumer<Integer, VerificationToken> onVerificationResult = (result, token) -> {
+ verificationResult.set(result);
+ verificationFinished.countDown();
+ };
+
+ mContext.getSystemService(AttestationVerificationManager.class).verifyAttestation(
+ new AttestationProfile(PROFILE_PEER_DEVICE),
+ /* localBindingType */ TYPE_CHALLENGE,
+ requirements,
+ remoteAttestation,
+ Runnable::run,
+ onVerificationResult
+ );
+
+ boolean finished;
+ try {
+ finished = verificationFinished.await(
+ ATTESTATION_VERIFICATION_TIMEOUT_SECONDS,
+ TimeUnit.SECONDS
+ );
+ } catch (InterruptedException e) {
+ throw new SecureChannelException("Attestation verification was interrupted", e);
+ }
+
+ if (!finished) {
+ throw new SecureChannelException("Attestation verification timed out.");
+ }
+
+ return verificationResult.get();
+ }
+}
diff --git a/services/companion/java/com/android/server/companion/securechannel/KeyStoreUtils.java b/services/companion/java/com/android/server/companion/securechannel/KeyStoreUtils.java
new file mode 100644
index 000000000000..18ebec4b6fd3
--- /dev/null
+++ b/services/companion/java/com/android/server/companion/securechannel/KeyStoreUtils.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.companion.securechannel;
+
+import static android.security.keystore.KeyProperties.DIGEST_SHA256;
+import static android.security.keystore.KeyProperties.KEY_ALGORITHM_EC;
+import static android.security.keystore.KeyProperties.PURPOSE_SIGN;
+import static android.security.keystore.KeyProperties.PURPOSE_VERIFY;
+
+import android.security.keystore.KeyGenParameterSpec;
+import android.security.keystore2.AndroidKeyStoreSpi;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.cert.Certificate;
+
+/**
+ * Utility class to help generate, store, and access key-pair for the secure channel. Uses
+ * Android Keystore.
+ */
+final class KeyStoreUtils {
+ private static final String TAG = "CDM_SecureChannelKeyStore";
+ private static final String ANDROID_KEYSTORE = AndroidKeyStoreSpi.NAME;
+
+ private KeyStoreUtils() {}
+
+ /**
+ * Load Android keystore to be used by the secure channel.
+ *
+ * @return loaded keystore instance
+ */
+ static KeyStore loadKeyStore() throws GeneralSecurityException {
+ KeyStore androidKeyStore = KeyStore.getInstance(ANDROID_KEYSTORE);
+
+ try {
+ androidKeyStore.load(null);
+ } catch (IOException e) {
+ // Should not happen
+ throw new KeyStoreException("Failed to load Android Keystore.", e);
+ }
+
+ return androidKeyStore;
+ }
+
+ /**
+ * Fetch the certificate chain encoded as byte array in the form of concatenated
+ * X509 certificates.
+ *
+ * @param alias unique alias for the key-pair entry
+ * @return a single byte-array containing the entire certificate chain
+ */
+ static byte[] getEncodedCertificateChain(String alias) throws GeneralSecurityException {
+ KeyStore ks = loadKeyStore();
+
+ Certificate[] certificateChain = ks.getCertificateChain(alias);
+
+ ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+ for (Certificate certificate : certificateChain) {
+ buffer.writeBytes(certificate.getEncoded());
+ }
+ return buffer.toByteArray();
+ }
+
+ /**
+ * Generate a new attestation key-pair.
+ *
+ * @param alias unique alias for the key-pair entry
+ * @param attestationChallenge challenge value to check against for authentication
+ */
+ static void generateAttestationKeyPair(String alias, byte[] attestationChallenge)
+ throws GeneralSecurityException {
+ KeyGenParameterSpec parameterSpec =
+ new KeyGenParameterSpec.Builder(alias, PURPOSE_SIGN | PURPOSE_VERIFY)
+ .setAttestationChallenge(attestationChallenge)
+ .setDigests(DIGEST_SHA256)
+ .build();
+
+ KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
+ /* algorithm */ KEY_ALGORITHM_EC,
+ /* provider */ ANDROID_KEYSTORE);
+ keyPairGenerator.initialize(parameterSpec);
+ keyPairGenerator.generateKeyPair();
+ }
+
+ /**
+ * Check if alias exists.
+ *
+ * @param alias unique alias for the key-pair entry
+ * @return true if given alias already exists in the keystore
+ */
+ static boolean aliasExists(String alias) {
+ try {
+ KeyStore ks = loadKeyStore();
+ return ks.containsAlias(alias);
+ } catch (GeneralSecurityException e) {
+ return false;
+ }
+
+ }
+
+ static void cleanUp(String alias) {
+ try {
+ KeyStore ks = loadKeyStore();
+
+ if (ks.containsAlias(alias)) {
+ ks.deleteEntry(alias);
+ }
+ } catch (Exception ignored) {
+ // Do nothing;
+ }
+ }
+}
diff --git a/services/companion/java/com/android/server/companion/securechannel/SecureChannel.java b/services/companion/java/com/android/server/companion/securechannel/SecureChannel.java
new file mode 100644
index 000000000000..13dba84487e3
--- /dev/null
+++ b/services/companion/java/com/android/server/companion/securechannel/SecureChannel.java
@@ -0,0 +1,543 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.companion.securechannel;
+
+import static android.security.attestationverification.AttestationVerificationManager.RESULT_SUCCESS;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.os.Build;
+import android.util.Slog;
+
+import com.google.security.cryptauth.lib.securegcm.BadHandleException;
+import com.google.security.cryptauth.lib.securegcm.CryptoException;
+import com.google.security.cryptauth.lib.securegcm.D2DConnectionContextV1;
+import com.google.security.cryptauth.lib.securegcm.D2DHandshakeContext;
+import com.google.security.cryptauth.lib.securegcm.D2DHandshakeContext.Role;
+import com.google.security.cryptauth.lib.securegcm.DefaultUkey2Logger;
+import com.google.security.cryptauth.lib.securegcm.HandshakeException;
+
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.util.Arrays;
+import java.util.UUID;
+
+/**
+ * Data stream channel that establishes secure connection between two peer devices.
+ */
+public class SecureChannel {
+ private static final String TAG = "CDM_SecureChannel";
+ private static final boolean DEBUG = Build.IS_DEBUGGABLE;
+
+ private static final int VERSION = 1;
+ private static final int HEADER_LENGTH = 6;
+
+ private static final String HANDSHAKE_PROTOCOL = "AES_256_CBC-HMAC_SHA256";
+
+ private final InputStream mInput;
+ private final OutputStream mOutput;
+ private final Callback mCallback;
+ private final byte[] mPreSharedKey;
+ private final AttestationVerifier mVerifier;
+
+ private volatile boolean mStopped;
+ private boolean mInProgress;
+
+ private Role mRole;
+ private D2DHandshakeContext mHandshakeContext;
+ private D2DConnectionContextV1 mConnectionContext;
+
+ private String mAlias;
+ private int mVerificationResult;
+
+
+ /**
+ * Create a new secure channel object. This secure channel allows secure messages to be
+ * exchanged with unattested devices. The pre-shared key must have been distributed to both
+ * participants of the channel in a secure way previously.
+ *
+ * @param in input stream from which data is received
+ * @param out output stream from which data is sent out
+ * @param callback subscription to received messages from the channel
+ * @param preSharedKey pre-shared key to authenticate unattested participant
+ */
+ public SecureChannel(
+ @NonNull final InputStream in,
+ @NonNull final OutputStream out,
+ @NonNull Callback callback,
+ @NonNull byte[] preSharedKey
+ ) {
+ this(in, out, callback, preSharedKey, null);
+ }
+
+ /**
+ * Create a new secure channel object. This secure channel allows secure messages to be
+ * exchanged with Android devices that were authenticated and verified with an attestation key.
+ *
+ * @param in input stream from which data is received
+ * @param out output stream from which data is sent out
+ * @param callback subscription to received messages from the channel
+ * @param context context for fetching the Attestation Verifier Framework system service
+ */
+ public SecureChannel(
+ @NonNull final InputStream in,
+ @NonNull final OutputStream out,
+ @NonNull Callback callback,
+ @NonNull Context context
+ ) {
+ this(in, out, callback, null, new AttestationVerifier(context));
+ }
+
+ private SecureChannel(
+ final InputStream in,
+ final OutputStream out,
+ Callback callback,
+ byte[] preSharedKey,
+ AttestationVerifier verifier
+ ) {
+ this.mInput = in;
+ this.mOutput = out;
+ this.mCallback = callback;
+ this.mPreSharedKey = preSharedKey;
+ this.mVerifier = verifier;
+ }
+
+ /**
+ * Start listening for incoming messages.
+ */
+ public void start() {
+ new Thread(() -> {
+ try {
+ // 1. Wait for the next handshake message and process it.
+ exchangeHandshake();
+
+ // 2. Authenticate remote actor via attestation or pre-shared key.
+ exchangeAuthentication();
+
+ // 3. Notify secure channel is ready.
+ mInProgress = false;
+ mCallback.onSecureConnection();
+
+ // Listen for secure messages.
+ while (!mStopped) {
+ receiveSecureMessage();
+ }
+ } catch (Exception e) {
+ if (mStopped) {
+ return;
+ }
+ // TODO: Handle different types errors.
+
+ Slog.e(TAG, "Secure channel encountered an error.", e);
+ stop();
+ mCallback.onError(e);
+ }
+ }).start();
+ }
+
+ /**
+ * Stop listening to incoming messages and close the channel.
+ */
+ public void stop() {
+ if (DEBUG) {
+ Slog.d(TAG, "Stopping secure channel.");
+ }
+ mStopped = true;
+ mInProgress = false;
+
+ IoUtils.closeQuietly(mInput);
+ IoUtils.closeQuietly(mOutput);
+ KeyStoreUtils.cleanUp(mAlias);
+ }
+
+ /**
+ * Start exchanging handshakes to create a secure layer asynchronously. When the handshake is
+ * completed successfully, then the {@link Callback#onSecureConnection()} will trigger. Any
+ * error that occurs during the handshake will be passed by {@link Callback#onError(Throwable)}.
+ *
+ * This method must only be called from one of the two participants.
+ */
+ public void establishSecureConnection() throws IOException, SecureChannelException {
+ if (isSecured()) {
+ Slog.d(TAG, "Channel is already secure.");
+ return;
+ }
+ if (mInProgress) {
+ Slog.w(TAG, "Channel has already started establishing secure connection.");
+ return;
+ }
+
+ try {
+ initiateHandshake();
+ mInProgress = true;
+ } catch (BadHandleException e) {
+ throw new SecureChannelException("Failed to initiate handshake protocol.", e);
+ }
+ }
+
+ /**
+ * Send an encrypted, authenticated message via this channel.
+ *
+ * @param data data to be sent to the other side.
+ * @throws IOException if the output stream fails to write given data.
+ */
+ public void sendSecureMessage(byte[] data) throws IOException {
+ if (!isSecured()) {
+ Slog.d(TAG, "Cannot send a message without a secure connection.");
+ throw new IllegalStateException("Channel is not secured yet.");
+ }
+
+ // Encrypt constructed message
+ try {
+ sendMessage(MessageType.SECURE_MESSAGE, data);
+ } catch (BadHandleException e) {
+ throw new SecureChannelException("Failed to encrypt data.", e);
+ }
+ }
+
+ private void receiveSecureMessage() throws IOException, CryptoException {
+ // Check if channel is secured. Trigger error callback. Let user handle it.
+ if (!isSecured()) {
+ Slog.d(TAG, "Received a message without a secure connection. "
+ + "Message will be ignored.");
+ mCallback.onError(new IllegalStateException("Connection is not secure."));
+ return;
+ }
+
+ try {
+ byte[] receivedMessage = readMessage(MessageType.SECURE_MESSAGE);
+ mCallback.onSecureMessageReceived(receivedMessage);
+ } catch (SecureChannelException e) {
+ Slog.w(TAG, "Ignoring received message.", e);
+ }
+ }
+
+ private byte[] readMessage(MessageType expected)
+ throws IOException, SecureChannelException, CryptoException {
+ if (DEBUG) {
+ if (isSecured()) {
+ Slog.d(TAG, "Waiting to receive next secure message.");
+ } else {
+ Slog.d(TAG, "Waiting to receive next message.");
+ }
+ }
+
+ // TODO: Handle message timeout
+
+ // Header is _not_ encrypted, but will be covered by MAC
+ final byte[] headerBytes = new byte[HEADER_LENGTH];
+ Streams.readFully(mInput, headerBytes);
+ final ByteBuffer header = ByteBuffer.wrap(headerBytes);
+ final int version = header.getInt();
+ final short type = header.getShort();
+
+ if (version != VERSION) {
+ Streams.skipByReading(mInput, Long.MAX_VALUE);
+ throw new SecureChannelException("Secure channel version mismatch. "
+ + "Currently on version " + VERSION + ". Skipping rest of data.");
+ }
+
+ if (type != expected.mValue) {
+ Streams.skipByReading(mInput, Long.MAX_VALUE);
+ throw new SecureChannelException("Unexpected message type. Expected " + expected.name()
+ + "; Found " + MessageType.from(type).name() + ". Skipping rest of data.");
+ }
+
+ // Length of attached data is prepended as plaintext
+ final byte[] lengthBytes = new byte[4];
+ Streams.readFully(mInput, lengthBytes);
+ final int length = ByteBuffer.wrap(lengthBytes).getInt();
+
+ // Read data based on the length
+ final byte[] data;
+ try {
+ data = new byte[length];
+ } catch (OutOfMemoryError error) {
+ throw new SecureChannelException("Payload is too large.", error);
+ }
+
+ Streams.readFully(mInput, data);
+ if (!MessageType.shouldEncrypt(expected)) {
+ return data;
+ }
+
+ return mConnectionContext.decodeMessageFromPeer(data, headerBytes);
+ }
+
+ private void sendMessage(MessageType messageType, byte[] payload)
+ throws IOException, BadHandleException {
+ synchronized (mOutput) {
+ byte[] header = ByteBuffer.allocate(HEADER_LENGTH)
+ .putInt(VERSION)
+ .putShort(messageType.mValue)
+ .array();
+ byte[] data = MessageType.shouldEncrypt(messageType)
+ ? mConnectionContext.encodeMessageToPeer(payload, header)
+ : payload;
+ mOutput.write(header);
+ mOutput.write(ByteBuffer.allocate(4)
+ .putInt(data.length)
+ .array());
+ mOutput.write(data);
+ mOutput.flush();
+ }
+ }
+
+ private void initiateHandshake() throws IOException, BadHandleException {
+ if (mConnectionContext != null) {
+ Slog.d(TAG, "Ukey2 handshake is already completed.");
+ return;
+ }
+
+ mRole = Role.Initiator;
+ mHandshakeContext = D2DHandshakeContext.forInitiator(DefaultUkey2Logger.INSTANCE);
+
+ // Send Client Init
+ if (DEBUG) {
+ Slog.d(TAG, "Sending Ukey2 Client Init message");
+ }
+ sendMessage(MessageType.HANDSHAKE_INIT, mHandshakeContext.getNextHandshakeMessage());
+ }
+
+ private void exchangeHandshake()
+ throws IOException, HandshakeException, BadHandleException, CryptoException {
+ if (mConnectionContext != null) {
+ Slog.d(TAG, "Ukey2 handshake is already completed.");
+ return;
+ }
+
+ // Waiting for message
+ byte[] handshakeMessage = readMessage(MessageType.HANDSHAKE_INIT);
+
+ if (mHandshakeContext == null) { // Server-side logic
+ mRole = Role.Responder;
+ mHandshakeContext = D2DHandshakeContext.forResponder(DefaultUkey2Logger.INSTANCE);
+
+ // Receive Client Init
+ if (DEBUG) {
+ Slog.d(TAG, "Receiving Ukey2 Client Init message");
+ }
+ mHandshakeContext.parseHandshakeMessage(handshakeMessage);
+
+ // Send Server Init
+ if (DEBUG) {
+ Slog.d(TAG, "Sending Ukey2 Server Init message");
+ }
+ sendMessage(MessageType.HANDSHAKE_INIT, mHandshakeContext.getNextHandshakeMessage());
+
+ // Receive Client Finish
+ if (DEBUG) {
+ Slog.d(TAG, "Receiving Ukey2 Client Finish message");
+ }
+ mHandshakeContext.parseHandshakeMessage(readMessage(MessageType.HANDSHAKE_FINISH));
+ } else { // Client-side logic
+
+ // Receive Server Init
+ if (DEBUG) {
+ Slog.d(TAG, "Receiving Ukey2 Server Init message");
+ }
+ mHandshakeContext.parseHandshakeMessage(handshakeMessage);
+
+ // Send Client Finish
+ if (DEBUG) {
+ Slog.d(TAG, "Sending Ukey2 Client Finish message");
+ }
+ sendMessage(MessageType.HANDSHAKE_FINISH, mHandshakeContext.getNextHandshakeMessage());
+ }
+
+ // Convert secrets to connection context
+ if (mHandshakeContext.isHandshakeComplete()) {
+ if (DEBUG) {
+ Slog.d(TAG, "Ukey2 Handshake completed successfully");
+ }
+ mConnectionContext = mHandshakeContext.toConnectionContext();
+ } else {
+ Slog.e(TAG, "Failed to complete Ukey2 Handshake");
+ throw new IllegalStateException("Ukey2 Handshake did not complete as expected.");
+ }
+ }
+
+ private void exchangeAuthentication()
+ throws IOException, GeneralSecurityException, BadHandleException, CryptoException {
+ if (mVerifier == null) {
+ exchangePreSharedKey();
+ } else {
+ exchangeAttestation();
+ }
+ }
+
+ private void exchangePreSharedKey()
+ throws IOException, GeneralSecurityException, BadHandleException, CryptoException {
+
+ // Exchange hashed pre-shared keys
+ if (DEBUG) {
+ Slog.d(TAG, "Exchanging pre-shared keys.");
+ }
+ sendMessage(MessageType.PRE_SHARED_KEY, constructToken(mRole, mPreSharedKey));
+ byte[] receivedAuthToken = readMessage(MessageType.PRE_SHARED_KEY);
+ byte[] expectedAuthToken = constructToken(mRole == Role.Initiator
+ ? Role.Responder
+ : Role.Initiator,
+ mPreSharedKey);
+ boolean authenticated = Arrays.equals(receivedAuthToken, expectedAuthToken);
+
+ if (!authenticated) {
+ throw new SecureChannelException("Failed to verify the hash of pre-shared key.");
+ }
+
+ if (DEBUG) {
+ Slog.d(TAG, "The pre-shared key was successfully authenticated.");
+ }
+ }
+
+ private void exchangeAttestation()
+ throws IOException, GeneralSecurityException, BadHandleException, CryptoException {
+ if (mVerificationResult == RESULT_SUCCESS) {
+ Slog.d(TAG, "Remote attestation was already verified.");
+ return;
+ }
+
+ // Send local attestation
+ if (DEBUG) {
+ Slog.d(TAG, "Exchanging device attestation.");
+ }
+ if (mAlias == null) {
+ mAlias = generateAlias();
+ }
+ byte[] localChallenge = constructToken(mRole, mConnectionContext.getSessionUnique());
+ KeyStoreUtils.generateAttestationKeyPair(mAlias, localChallenge);
+ byte[] localAttestation = KeyStoreUtils.getEncodedCertificateChain(mAlias);
+ sendMessage(MessageType.ATTESTATION, localAttestation);
+ byte[] remoteAttestation = readMessage(MessageType.ATTESTATION);
+
+ // Verifying remote attestation with public key local binding param
+ byte[] expectedChallenge = constructToken(mRole == Role.Initiator
+ ? Role.Responder
+ : Role.Initiator,
+ mConnectionContext.getSessionUnique());
+ mVerificationResult = mVerifier.verifyAttestation(remoteAttestation, expectedChallenge);
+
+ // Exchange attestation verification result and finish
+ byte[] verificationResult = ByteBuffer.allocate(4)
+ .putInt(mVerificationResult)
+ .array();
+ sendMessage(MessageType.AVF_RESULT, verificationResult);
+ byte[] remoteVerificationResult = readMessage(MessageType.AVF_RESULT);
+
+ if (ByteBuffer.wrap(remoteVerificationResult).getInt() != RESULT_SUCCESS) {
+ throw new SecureChannelException("Remote device failed to verify local attestation.");
+ }
+
+ if (mVerificationResult != RESULT_SUCCESS) {
+ throw new SecureChannelException("Failed to verify remote attestation.");
+ }
+
+ if (DEBUG) {
+ Slog.d(TAG, "Remote attestation was successfully verified.");
+ }
+ }
+
+ private boolean isSecured() {
+ if (mConnectionContext == null) {
+ return false;
+ }
+ return mVerifier == null || mVerificationResult == RESULT_SUCCESS;
+ }
+
+ private byte[] constructToken(D2DHandshakeContext.Role role, byte[] authValue)
+ throws GeneralSecurityException {
+ MessageDigest hash = MessageDigest.getInstance("SHA-256");
+ byte[] roleUtf8 = role.name().getBytes(StandardCharsets.UTF_8);
+ int tokenLength = roleUtf8.length + authValue.length;
+ return hash.digest(ByteBuffer.allocate(tokenLength)
+ .put(roleUtf8)
+ .put(authValue)
+ .array());
+ }
+
+ private String generateAlias() {
+ String alias;
+ do {
+ alias = "secure-channel-" + UUID.randomUUID();
+ } while (KeyStoreUtils.aliasExists(alias));
+ return alias;
+ }
+
+ private enum MessageType {
+ HANDSHAKE_INIT(0x4849), // HI
+ HANDSHAKE_FINISH(0x4846), // HF
+ PRE_SHARED_KEY(0x504b), // PK
+ ATTESTATION(0x4154), // AT
+ AVF_RESULT(0x5652), // VR
+ SECURE_MESSAGE(0x534d), // SM
+ UNKNOWN(0); // X
+
+ private final short mValue;
+
+ MessageType(int value) {
+ this.mValue = (short) value;
+ }
+
+ static MessageType from(short value) {
+ for (MessageType messageType : values()) {
+ if (value == messageType.mValue) {
+ return messageType;
+ }
+ }
+ return UNKNOWN;
+ }
+
+ // Encrypt every message besides Ukey2 handshake messages
+ private static boolean shouldEncrypt(MessageType type) {
+ return type != HANDSHAKE_INIT && type != HANDSHAKE_FINISH;
+ }
+ }
+
+ /**
+ * Callback that passes securely received message to the subscribed user.
+ */
+ public interface Callback {
+ /**
+ * Triggered after {@link SecureChannel#establishSecureConnection()} finishes exchanging
+ * every required handshakes to fully establish a secure connection.
+ */
+ void onSecureConnection();
+
+ /**
+ * Callback that passes securely received and decrypted data to the subscribed user.
+ *
+ * @param data securely received plaintext data.
+ */
+ void onSecureMessageReceived(byte[] data);
+
+ /**
+ * Callback that passes error that occurred during handshakes or while listening to
+ * messages in the secure channel.
+ *
+ * @param error
+ */
+ void onError(Throwable error);
+ }
+}
diff --git a/services/companion/java/com/android/server/companion/securechannel/SecureChannelException.java b/services/companion/java/com/android/server/companion/securechannel/SecureChannelException.java
new file mode 100644
index 000000000000..68db97e35261
--- /dev/null
+++ b/services/companion/java/com/android/server/companion/securechannel/SecureChannelException.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.companion.securechannel;
+
+/**
+ * Catch-all exception for any error in the secure channel.
+ */
+public class SecureChannelException extends RuntimeException {
+ /**
+ *
+ * @param message
+ */
+ public SecureChannelException(String message) {
+ super(message);
+ }
+
+ public SecureChannelException(String message, Throwable t) {
+ super(message, t);
+ }
+}
diff --git a/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java b/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java
index 6db99a0d0b73..494c5a6c0779 100644
--- a/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java
+++ b/services/companion/java/com/android/server/companion/transport/CompanionTransportManager.java
@@ -34,6 +34,7 @@ import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
import com.android.server.LocalServices;
+import com.android.server.companion.securechannel.SecureChannel;
import libcore.io.IoUtils;
import libcore.io.Streams;
@@ -43,6 +44,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
@@ -54,8 +57,6 @@ public class CompanionTransportManager {
private static final boolean DEBUG = true;
private static final int HEADER_LENGTH = 12;
- // TODO: refactor message processing to use streams to remove this limit
- private static final int MAX_PAYLOAD_LENGTH = 1_000_000;
private static final int MESSAGE_REQUEST_PING = 0x63807378; // ?PIN
private static final int MESSAGE_REQUEST_PERMISSION_RESTORE = 0x63826983; // ?RES
@@ -63,6 +64,8 @@ public class CompanionTransportManager {
private static final int MESSAGE_RESPONSE_SUCCESS = 0x33838567; // !SUC
private static final int MESSAGE_RESPONSE_FAILURE = 0x33706573; // !FAI
+ private boolean mSecureTransportEnabled = true;
+
private static boolean isRequest(int message) {
return (message & 0xFF000000) == 0x63000000;
}
@@ -122,7 +125,13 @@ public class CompanionTransportManager {
detachSystemDataTransport(packageName, userId, associationId);
}
- final Transport transport = new Transport(associationId, fd);
+ final Transport transport;
+ if (isSecureTransportEnabled(associationId)) {
+ transport = new SecureTransport(associationId, fd);
+ } else {
+ transport = new RawTransport(associationId, fd);
+ }
+
transport.start();
mTransports.put(associationId, transport);
}
@@ -142,61 +151,65 @@ public class CompanionTransportManager {
public Future<?> requestPermissionRestore(int associationId, byte[] data) {
synchronized (mTransports) {
final Transport transport = mTransports.get(associationId);
- if (transport != null) {
- return transport.requestForResponse(MESSAGE_REQUEST_PERMISSION_RESTORE, data);
- } else {
+ if (transport == null) {
return CompletableFuture.failedFuture(new IOException("Missing transport"));
}
+
+ return transport.requestForResponse(MESSAGE_REQUEST_PERMISSION_RESTORE, data);
}
}
- private class Transport {
- private final int mAssociationId;
-
- private final InputStream mRemoteIn;
- private final OutputStream mRemoteOut;
+ /**
+ * @hide
+ */
+ public void enableSecureTransport(boolean enabled) {
+ this.mSecureTransportEnabled = enabled;
+ }
- private final AtomicInteger mNextSequence = new AtomicInteger();
+ private boolean isSecureTransportEnabled(int associationId) {
+ boolean enabled = !Build.IS_DEBUGGABLE || mSecureTransportEnabled;
- @GuardedBy("mPendingRequests")
- private final SparseArray<CompletableFuture<byte[]>> mPendingRequests = new SparseArray<>();
+ // TODO: version comparison logic
+ return enabled;
+ }
- private volatile boolean mStopped;
+ // TODO: Make Transport inner classes into standalone classes.
+ private abstract class Transport {
+ protected final int mAssociationId;
+ protected final InputStream mRemoteIn;
+ protected final OutputStream mRemoteOut;
- public Transport(int associationId, ParcelFileDescriptor fd) {
- mAssociationId = associationId;
- mRemoteIn = new ParcelFileDescriptor.AutoCloseInputStream(fd);
- mRemoteOut = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
+ @GuardedBy("mPendingRequests")
+ protected final SparseArray<CompletableFuture<byte[]>> mPendingRequests =
+ new SparseArray<>();
+ protected final AtomicInteger mNextSequence = new AtomicInteger();
+
+ Transport(int associationId, ParcelFileDescriptor fd) {
+ this(associationId,
+ new ParcelFileDescriptor.AutoCloseInputStream(fd),
+ new ParcelFileDescriptor.AutoCloseOutputStream(fd));
}
- public void start() {
- new Thread(() -> {
- try {
- while (!mStopped) {
- receiveMessage();
- }
- } catch (IOException e) {
- if (!mStopped) {
- Slog.w(TAG, "Trouble during transport", e);
- stop();
- }
- }
- }).start();
+ Transport(int associationId, InputStream in, OutputStream out) {
+ this.mAssociationId = associationId;
+ this.mRemoteIn = in;
+ this.mRemoteOut = out;
}
- public void stop() {
- mStopped = true;
+ public abstract void start();
+ public abstract void stop();
- IoUtils.closeQuietly(mRemoteIn);
- IoUtils.closeQuietly(mRemoteOut);
- }
+ protected abstract void sendMessage(int message, int sequence, @NonNull byte[] data)
+ throws IOException;
public Future<byte[]> requestForResponse(int message, byte[] data) {
+ if (DEBUG) Slog.d(TAG, "Requesting for response");
final int sequence = mNextSequence.incrementAndGet();
final CompletableFuture<byte[]> pending = new CompletableFuture<>();
synchronized (mPendingRequests) {
mPendingRequests.put(sequence, pending);
}
+
try {
sendMessage(message, sequence, data);
} catch (IOException e) {
@@ -205,58 +218,24 @@ public class CompanionTransportManager {
}
pending.completeExceptionally(e);
}
+
return pending;
}
- private void sendMessage(int message, int sequence, @NonNull byte[] data)
+ protected final void handleMessage(int message, int sequence, @NonNull byte[] data)
throws IOException {
if (DEBUG) {
- Slog.d(TAG, "Sending message 0x" + Integer.toHexString(message)
- + " sequence " + sequence + " length " + data.length
- + " to association " + mAssociationId);
- }
-
- synchronized (mRemoteOut) {
- final ByteBuffer header = ByteBuffer.allocate(HEADER_LENGTH)
- .putInt(message)
- .putInt(sequence)
- .putInt(data.length);
- mRemoteOut.write(header.array());
- mRemoteOut.write(data);
- mRemoteOut.flush();
- }
- }
-
- private void receiveMessage() throws IOException {
- if (DEBUG) {
- Slog.d(TAG, "Waiting for next message...");
- }
-
- final byte[] headerBytes = new byte[HEADER_LENGTH];
- Streams.readFully(mRemoteIn, headerBytes);
- final ByteBuffer header = ByteBuffer.wrap(headerBytes);
- final int message = header.getInt();
- final int sequence = header.getInt();
- final int length = header.getInt();
-
- if (DEBUG) {
Slog.d(TAG, "Received message 0x" + Integer.toHexString(message)
- + " sequence " + sequence + " length " + length
+ + " sequence " + sequence + " length " + data.length
+ " from association " + mAssociationId);
}
- if (length > MAX_PAYLOAD_LENGTH) {
- Slog.w(TAG, "Ignoring message 0x" + Integer.toHexString(message)
- + " sequence " + sequence + " length " + length
- + " from association " + mAssociationId + " beyond maximum length");
- Streams.skipByReading(mRemoteIn, length);
- return;
- }
-
- final byte[] data = new byte[length];
- Streams.readFully(mRemoteIn, data);
if (isRequest(message)) {
- processRequest(message, sequence, data);
+ try {
+ processRequest(message, sequence, data);
+ } catch (IOException e) {
+ Slog.w(TAG, "Failed to respond to 0x" + Integer.toHexString(message), e);
+ }
} else if (isResponse(message)) {
processResponse(message, sequence, data);
} else {
@@ -320,4 +299,169 @@ public class CompanionTransportManager {
}
}
}
+
+ private class RawTransport extends Transport {
+ private volatile boolean mStopped;
+
+ RawTransport(int associationId, ParcelFileDescriptor fd) {
+ super(associationId, fd);
+ }
+
+ @Override
+ public void start() {
+ new Thread(() -> {
+ try {
+ while (!mStopped) {
+ receiveMessage();
+ }
+ } catch (IOException e) {
+ if (!mStopped) {
+ Slog.w(TAG, "Trouble during transport", e);
+ stop();
+ }
+ }
+ }).start();
+ }
+
+ @Override
+ public void stop() {
+ mStopped = true;
+
+ IoUtils.closeQuietly(mRemoteIn);
+ IoUtils.closeQuietly(mRemoteOut);
+ }
+
+ @Override
+ protected void sendMessage(int message, int sequence, @NonNull byte[] data)
+ throws IOException {
+ if (DEBUG) {
+ Slog.d(TAG, "Sending message 0x" + Integer.toHexString(message)
+ + " sequence " + sequence + " length " + data.length
+ + " to association " + mAssociationId);
+ }
+
+ synchronized (mRemoteOut) {
+ final ByteBuffer header = ByteBuffer.allocate(HEADER_LENGTH)
+ .putInt(message)
+ .putInt(sequence)
+ .putInt(data.length);
+ mRemoteOut.write(header.array());
+ mRemoteOut.write(data);
+ mRemoteOut.flush();
+ }
+ }
+
+ private void receiveMessage() throws IOException {
+ final byte[] headerBytes = new byte[HEADER_LENGTH];
+ Streams.readFully(mRemoteIn, headerBytes);
+ final ByteBuffer header = ByteBuffer.wrap(headerBytes);
+ final int message = header.getInt();
+ final int sequence = header.getInt();
+ final int length = header.getInt();
+ final byte[] data = new byte[length];
+ Streams.readFully(mRemoteIn, data);
+
+ handleMessage(message, sequence, data);
+ }
+ }
+
+ private class SecureTransport extends Transport implements SecureChannel.Callback {
+ private final SecureChannel mSecureChannel;
+
+ private volatile boolean mShouldProcessRequests = false;
+
+ private final BlockingQueue<byte[]> mRequestQueue = new ArrayBlockingQueue<>(100);
+
+ SecureTransport(int associationId, ParcelFileDescriptor fd) {
+ super(associationId, fd);
+ mSecureChannel = new SecureChannel(mRemoteIn, mRemoteOut, this, mContext);
+ }
+
+ @Override
+ public void start() {
+ mSecureChannel.start();
+ }
+
+ @Override
+ public void stop() {
+ mSecureChannel.stop();
+ mShouldProcessRequests = false;
+ }
+
+ @Override
+ public Future<byte[]> requestForResponse(int message, byte[] data) {
+ // Check if channel is secured and start securing
+ if (!mShouldProcessRequests) {
+ Slog.d(TAG, "Establishing secure connection.");
+ try {
+ mSecureChannel.establishSecureConnection();
+ } catch (Exception e) {
+ Slog.w(TAG, "Failed to initiate secure channel handshake.", e);
+ onError(e);
+ }
+ }
+
+ return super.requestForResponse(message, data);
+ }
+
+ @Override
+ protected void sendMessage(int message, int sequence, @NonNull byte[] data)
+ throws IOException {
+ if (DEBUG) {
+ Slog.d(TAG, "Queueing message 0x" + Integer.toHexString(message)
+ + " sequence " + sequence + " length " + data.length
+ + " to association " + mAssociationId);
+ }
+
+ // Queue up a message to send
+ mRequestQueue.add(ByteBuffer.allocate(HEADER_LENGTH + data.length)
+ .putInt(message)
+ .putInt(sequence)
+ .putInt(data.length)
+ .put(data)
+ .array());
+ }
+
+ @Override
+ public void onSecureConnection() {
+ mShouldProcessRequests = true;
+ Slog.d(TAG, "Secure connection established.");
+
+ // TODO: find a better way to handle incoming requests than a dedicated thread.
+ new Thread(() -> {
+ try {
+ while (mShouldProcessRequests) {
+ byte[] request = mRequestQueue.poll();
+ if (request != null) {
+ mSecureChannel.sendSecureMessage(request);
+ }
+ }
+ } catch (IOException e) {
+ onError(e);
+ }
+ }).start();
+ }
+
+ @Override
+ public void onSecureMessageReceived(byte[] data) {
+ final ByteBuffer payload = ByteBuffer.wrap(data);
+ final int message = payload.getInt();
+ final int sequence = payload.getInt();
+ final int length = payload.getInt();
+ final byte[] content = new byte[length];
+ payload.get(content);
+
+ try {
+ handleMessage(message, sequence, content);
+ } catch (IOException error) {
+ onError(error);
+ }
+ }
+
+ @Override
+ public void onError(Throwable error) {
+ mShouldProcessRequests = false;
+ Slog.e(TAG, error.getMessage(), error);
+ }
+ }
}
diff --git a/services/companion/java/com/android/server/companion/transport/CryptoManager.java b/services/companion/java/com/android/server/companion/transport/CryptoManager.java
new file mode 100644
index 000000000000..b08354afc8ad
--- /dev/null
+++ b/services/companion/java/com/android/server/companion/transport/CryptoManager.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.companion.transport;
+
+import android.security.keystore.KeyGenParameterSpec;
+import android.security.keystore.KeyProperties;
+import android.util.Slog;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableEntryException;
+import java.security.cert.CertificateException;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.Cipher;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.KeyGenerator;
+import javax.crypto.NoSuchPaddingException;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+
+/**
+ * This class can be used to encrypt and decrypt bytes using Android Cryptography
+ */
+public class CryptoManager {
+
+ private static final String TAG = "CDM_CryptoManager";
+
+ private static final String KEY_STORE_ALIAS = "cdm_secret";
+ private static final String ALGORITHM = KeyProperties.KEY_ALGORITHM_AES;
+ private static final String BLOCK_MODE = KeyProperties.BLOCK_MODE_CBC;
+ private static final String PADDING = KeyProperties.ENCRYPTION_PADDING_PKCS7;
+ private static final String TRANSFORMATION = ALGORITHM + "/" + BLOCK_MODE + "/" + PADDING;
+
+ private final KeyStore mKeyStore;
+
+ public CryptoManager() {
+ // Initialize KeyStore
+ try {
+ mKeyStore = KeyStore.getInstance("AndroidKeyStore");
+ mKeyStore.load(null);
+ } catch (KeyStoreException | IOException | NoSuchAlgorithmException
+ | CertificateException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Output format: | iv length (int) | iv | encrypted bytes length (int) | encrypted bytes |
+ */
+ public byte[] encrypt(byte[] input) {
+ try {
+ // Encrypt using Cipher
+ Cipher encryptCipher = Cipher.getInstance(TRANSFORMATION);
+ encryptCipher.init(Cipher.ENCRYPT_MODE, getKey());
+ byte[] encryptedBytes = encryptCipher.doFinal(input);
+
+ // Write to bytes
+ ByteBuffer buffer = ByteBuffer.allocate(
+ 4 + encryptCipher.getIV().length + 4 + encryptedBytes.length)
+ .putInt(encryptCipher.getIV().length)
+ .put(encryptCipher.getIV())
+ .putInt(encryptedBytes.length)
+ .put(encryptedBytes);
+ return buffer.array();
+ } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
+ | IllegalBlockSizeException | BadPaddingException e) {
+ Slog.e(TAG, e.getMessage());
+ return null;
+ }
+ }
+
+ /**
+ * Input format: | iv length (int) | iv | encrypted bytes length (int) | encrypted bytes |
+ */
+ public byte[] decrypt(byte[] input) {
+ ByteBuffer buffer = ByteBuffer.wrap(input);
+ byte[] iv = new byte[buffer.getInt()];
+ buffer.get(iv);
+ byte[] encryptedBytes = new byte[buffer.getInt()];
+ buffer.get(encryptedBytes);
+ try {
+ Cipher decryptCipher = Cipher.getInstance(TRANSFORMATION);
+ decryptCipher.init(Cipher.DECRYPT_MODE, getKey(), new IvParameterSpec(iv));
+ return decryptCipher.doFinal(encryptedBytes);
+ } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
+ | InvalidAlgorithmParameterException | IllegalBlockSizeException
+ | BadPaddingException e) {
+ Slog.e(TAG, e.getMessage());
+ return null;
+ }
+ }
+
+ private SecretKey getKey() {
+ try {
+ KeyStore.Entry keyEntry = mKeyStore.getEntry(KEY_STORE_ALIAS, null);
+ if (keyEntry instanceof KeyStore.SecretKeyEntry
+ && ((KeyStore.SecretKeyEntry) keyEntry).getSecretKey() != null) {
+ return ((KeyStore.SecretKeyEntry) keyEntry).getSecretKey();
+ } else {
+ return createKey();
+ }
+ } catch (NoSuchAlgorithmException | UnrecoverableEntryException | KeyStoreException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private SecretKey createKey() {
+ try {
+ KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM);
+ keyGenerator.init(
+ new KeyGenParameterSpec.Builder(KEY_STORE_ALIAS,
+ KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
+ .setBlockModes(BLOCK_MODE)
+ .setEncryptionPaddings(PADDING)
+ .setUserAuthenticationRequired(false)
+ .setRandomizedEncryptionRequired(true)
+ .build());
+ return keyGenerator.generateKey();
+ } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/services/companion/java/com/android/server/companion/virtual/InputController.java b/services/companion/java/com/android/server/companion/virtual/InputController.java
index df5e37c947cc..21b51b1acef0 100644
--- a/services/companion/java/com/android/server/companion/virtual/InputController.java
+++ b/services/companion/java/com/android/server/companion/virtual/InputController.java
@@ -242,7 +242,7 @@ class InputController {
private void closeInputDeviceDescriptorLocked(IBinder token,
InputDeviceDescriptor inputDeviceDescriptor) {
token.unlinkToDeath(inputDeviceDescriptor.getDeathRecipient(), /* flags= */ 0);
- mNativeWrapper.closeUinput(inputDeviceDescriptor.getFileDescriptor());
+ mNativeWrapper.closeUinput(inputDeviceDescriptor.getNativePointer());
String phys = inputDeviceDescriptor.getPhys();
InputManager.getInstance().removeUniqueIdAssociation(phys);
// Type associations are added in the case of navigation touchpads. Those should be removed
@@ -366,7 +366,7 @@ class InputController {
throw new IllegalArgumentException(
"Could not send key event to input device for given token");
}
- return mNativeWrapper.writeDpadKeyEvent(inputDeviceDescriptor.getFileDescriptor(),
+ return mNativeWrapper.writeDpadKeyEvent(inputDeviceDescriptor.getNativePointer(),
event.getKeyCode(), event.getAction());
}
}
@@ -379,7 +379,7 @@ class InputController {
throw new IllegalArgumentException(
"Could not send key event to input device for given token");
}
- return mNativeWrapper.writeKeyEvent(inputDeviceDescriptor.getFileDescriptor(),
+ return mNativeWrapper.writeKeyEvent(inputDeviceDescriptor.getNativePointer(),
event.getKeyCode(), event.getAction());
}
}
@@ -397,7 +397,7 @@ class InputController {
throw new IllegalStateException(
"Display id associated with this mouse is not currently targetable");
}
- return mNativeWrapper.writeButtonEvent(inputDeviceDescriptor.getFileDescriptor(),
+ return mNativeWrapper.writeButtonEvent(inputDeviceDescriptor.getNativePointer(),
event.getButtonCode(), event.getAction());
}
}
@@ -410,7 +410,7 @@ class InputController {
throw new IllegalArgumentException(
"Could not send touch event to input device for given token");
}
- return mNativeWrapper.writeTouchEvent(inputDeviceDescriptor.getFileDescriptor(),
+ return mNativeWrapper.writeTouchEvent(inputDeviceDescriptor.getNativePointer(),
event.getPointerId(), event.getToolType(), event.getAction(), event.getX(),
event.getY(), event.getPressure(), event.getMajorAxisSize());
}
@@ -429,7 +429,7 @@ class InputController {
throw new IllegalStateException(
"Display id associated with this mouse is not currently targetable");
}
- return mNativeWrapper.writeRelativeEvent(inputDeviceDescriptor.getFileDescriptor(),
+ return mNativeWrapper.writeRelativeEvent(inputDeviceDescriptor.getNativePointer(),
event.getRelativeX(), event.getRelativeY());
}
}
@@ -447,7 +447,7 @@ class InputController {
throw new IllegalStateException(
"Display id associated with this mouse is not currently targetable");
}
- return mNativeWrapper.writeScrollEvent(inputDeviceDescriptor.getFileDescriptor(),
+ return mNativeWrapper.writeScrollEvent(inputDeviceDescriptor.getNativePointer(),
event.getXAxisMovement(), event.getYAxisMovement());
}
}
@@ -474,7 +474,7 @@ class InputController {
synchronized (mLock) {
fout.println(" Active descriptors: ");
for (InputDeviceDescriptor inputDeviceDescriptor : mInputDeviceDescriptors.values()) {
- fout.println(" fd: " + inputDeviceDescriptor.getFileDescriptor());
+ fout.println(" ptr: " + inputDeviceDescriptor.getNativePointer());
fout.println(" displayId: " + inputDeviceDescriptor.getDisplayId());
fout.println(" creationOrder: "
+ inputDeviceDescriptor.getCreationOrderNumber());
@@ -487,10 +487,10 @@ class InputController {
}
@VisibleForTesting
- void addDeviceForTesting(IBinder deviceToken, int fd, int type, int displayId, String phys,
+ void addDeviceForTesting(IBinder deviceToken, long ptr, int type, int displayId, String phys,
String deviceName, int inputDeviceId) {
synchronized (mLock) {
- mInputDeviceDescriptors.put(deviceToken, new InputDeviceDescriptor(fd, () -> {
+ mInputDeviceDescriptors.put(deviceToken, new InputDeviceDescriptor(ptr, () -> {
}, type, displayId, phys, deviceName, inputDeviceId));
}
}
@@ -504,75 +504,76 @@ class InputController {
return inputDeviceDescriptors;
}
- private static native int nativeOpenUinputDpad(String deviceName, int vendorId, int productId,
+ private static native long nativeOpenUinputDpad(String deviceName, int vendorId, int productId,
String phys);
- private static native int nativeOpenUinputKeyboard(String deviceName, int vendorId,
+ private static native long nativeOpenUinputKeyboard(String deviceName, int vendorId,
int productId, String phys);
- private static native int nativeOpenUinputMouse(String deviceName, int vendorId, int productId,
+ private static native long nativeOpenUinputMouse(String deviceName, int vendorId, int productId,
String phys);
- private static native int nativeOpenUinputTouchscreen(String deviceName, int vendorId,
+ private static native long nativeOpenUinputTouchscreen(String deviceName, int vendorId,
int productId, String phys, int height, int width);
- private static native boolean nativeCloseUinput(int fd);
- private static native boolean nativeWriteDpadKeyEvent(int fd, int androidKeyCode, int action);
- private static native boolean nativeWriteKeyEvent(int fd, int androidKeyCode, int action);
- private static native boolean nativeWriteButtonEvent(int fd, int buttonCode, int action);
- private static native boolean nativeWriteTouchEvent(int fd, int pointerId, int toolType,
+ private static native void nativeCloseUinput(long ptr);
+ private static native boolean nativeWriteDpadKeyEvent(long ptr, int androidKeyCode, int action);
+ private static native boolean nativeWriteKeyEvent(long ptr, int androidKeyCode, int action);
+ private static native boolean nativeWriteButtonEvent(long ptr, int buttonCode, int action);
+ private static native boolean nativeWriteTouchEvent(long ptr, int pointerId, int toolType,
int action, float locationX, float locationY, float pressure, float majorAxisSize);
- private static native boolean nativeWriteRelativeEvent(int fd, float relativeX,
+ private static native boolean nativeWriteRelativeEvent(long ptr, float relativeX,
float relativeY);
- private static native boolean nativeWriteScrollEvent(int fd, float xAxisMovement,
+ private static native boolean nativeWriteScrollEvent(long ptr, float xAxisMovement,
float yAxisMovement);
/** Wrapper around the static native methods for tests. */
@VisibleForTesting
protected static class NativeWrapper {
- public int openUinputDpad(String deviceName, int vendorId, int productId, String phys) {
+ public long openUinputDpad(String deviceName, int vendorId, int productId, String phys) {
return nativeOpenUinputDpad(deviceName, vendorId, productId, phys);
}
- public int openUinputKeyboard(String deviceName, int vendorId, int productId, String phys) {
+ public long openUinputKeyboard(String deviceName, int vendorId, int productId,
+ String phys) {
return nativeOpenUinputKeyboard(deviceName, vendorId, productId, phys);
}
- public int openUinputMouse(String deviceName, int vendorId, int productId, String phys) {
+ public long openUinputMouse(String deviceName, int vendorId, int productId, String phys) {
return nativeOpenUinputMouse(deviceName, vendorId, productId, phys);
}
- public int openUinputTouchscreen(String deviceName, int vendorId,
+ public long openUinputTouchscreen(String deviceName, int vendorId,
int productId, String phys, int height, int width) {
return nativeOpenUinputTouchscreen(deviceName, vendorId, productId, phys, height,
width);
}
- public boolean closeUinput(int fd) {
- return nativeCloseUinput(fd);
+ public void closeUinput(long ptr) {
+ nativeCloseUinput(ptr);
}
- public boolean writeDpadKeyEvent(int fd, int androidKeyCode, int action) {
- return nativeWriteDpadKeyEvent(fd, androidKeyCode, action);
+ public boolean writeDpadKeyEvent(long ptr, int androidKeyCode, int action) {
+ return nativeWriteDpadKeyEvent(ptr, androidKeyCode, action);
}
- public boolean writeKeyEvent(int fd, int androidKeyCode, int action) {
- return nativeWriteKeyEvent(fd, androidKeyCode, action);
+ public boolean writeKeyEvent(long ptr, int androidKeyCode, int action) {
+ return nativeWriteKeyEvent(ptr, androidKeyCode, action);
}
- public boolean writeButtonEvent(int fd, int buttonCode, int action) {
- return nativeWriteButtonEvent(fd, buttonCode, action);
+ public boolean writeButtonEvent(long ptr, int buttonCode, int action) {
+ return nativeWriteButtonEvent(ptr, buttonCode, action);
}
- public boolean writeTouchEvent(int fd, int pointerId, int toolType, int action,
+ public boolean writeTouchEvent(long ptr, int pointerId, int toolType, int action,
float locationX, float locationY, float pressure, float majorAxisSize) {
- return nativeWriteTouchEvent(fd, pointerId, toolType,
+ return nativeWriteTouchEvent(ptr, pointerId, toolType,
action, locationX, locationY,
pressure, majorAxisSize);
}
- public boolean writeRelativeEvent(int fd, float relativeX, float relativeY) {
- return nativeWriteRelativeEvent(fd, relativeX, relativeY);
+ public boolean writeRelativeEvent(long ptr, float relativeX, float relativeY) {
+ return nativeWriteRelativeEvent(ptr, relativeX, relativeY);
}
- public boolean writeScrollEvent(int fd, float xAxisMovement, float yAxisMovement) {
- return nativeWriteScrollEvent(fd, xAxisMovement,
+ public boolean writeScrollEvent(long ptr, float xAxisMovement, float yAxisMovement) {
+ return nativeWriteScrollEvent(ptr, xAxisMovement,
yAxisMovement);
}
}
@@ -597,7 +598,8 @@ class InputController {
private static final AtomicLong sNextCreationOrderNumber = new AtomicLong(1);
- private final int mFd;
+ // Pointer to the native input device object.
+ private final long mPtr;
private final IBinder.DeathRecipient mDeathRecipient;
private final @Type int mType;
private final int mDisplayId;
@@ -611,9 +613,9 @@ class InputController {
// Monotonically increasing number; devices with lower numbers were created earlier.
private final long mCreationOrderNumber;
- InputDeviceDescriptor(int fd, IBinder.DeathRecipient deathRecipient, @Type int type,
+ InputDeviceDescriptor(long ptr, IBinder.DeathRecipient deathRecipient, @Type int type,
int displayId, String phys, String name, int inputDeviceId) {
- mFd = fd;
+ mPtr = ptr;
mDeathRecipient = deathRecipient;
mType = type;
mDisplayId = displayId;
@@ -623,8 +625,8 @@ class InputController {
mCreationOrderNumber = sNextCreationOrderNumber.getAndIncrement();
}
- public int getFileDescriptor() {
- return mFd;
+ public long getNativePointer() {
+ return mPtr;
}
public int getType() {
@@ -767,7 +769,7 @@ class InputController {
*/
private void createDeviceInternal(@InputDeviceDescriptor.Type int type, String deviceName,
int vendorId, int productId, IBinder deviceToken, int displayId, String phys,
- Supplier<Integer> deviceOpener)
+ Supplier<Long> deviceOpener)
throws DeviceCreationException {
if (!mThreadVerifier.isValidThread()) {
throw new IllegalStateException(
@@ -776,19 +778,22 @@ class InputController {
}
validateDeviceName(deviceName);
- final int fd;
+ final long ptr;
final BinderDeathRecipient binderDeathRecipient;
final int inputDeviceId;
setUniqueIdAssociation(displayId, phys);
try (WaitForDevice waiter = new WaitForDevice(deviceName, vendorId, productId)) {
- fd = deviceOpener.get();
- if (fd < 0) {
+ ptr = deviceOpener.get();
+ // See INVALID_PTR in libs/input/VirtualInputDevice.cpp.
+ if (ptr == 0) {
throw new DeviceCreationException(
- "A native error occurred when creating touchscreen: " + -fd);
+ "A native error occurred when creating virtual input device: "
+ + deviceName);
}
- // The fd is valid from here, so ensure that all failures close the fd after this point.
+ // The pointer to the native input device is valid from here, so ensure that all
+ // failures close the device after this point.
try {
inputDeviceId = waiter.waitForDeviceCreation();
@@ -800,7 +805,7 @@ class InputController {
"Client died before virtual device could be created.", e);
}
} catch (DeviceCreationException e) {
- mNativeWrapper.closeUinput(fd);
+ mNativeWrapper.closeUinput(ptr);
throw e;
}
} catch (DeviceCreationException e) {
@@ -810,7 +815,7 @@ class InputController {
synchronized (mLock) {
mInputDeviceDescriptors.put(deviceToken,
- new InputDeviceDescriptor(fd, binderDeathRecipient, type, displayId, phys,
+ new InputDeviceDescriptor(ptr, binderDeathRecipient, type, displayId, phys,
deviceName, inputDeviceId));
}
}
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index 08ee6d76f284..61fc32d5fa15 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -169,6 +169,7 @@ public final class ContentCaptureManagerService extends
@GuardedBy("mLock") int mDevCfgTextChangeFlushingFrequencyMs;
@GuardedBy("mLock") int mDevCfgLogHistorySize;
@GuardedBy("mLock") int mDevCfgIdleUnbindTimeoutMs;
+ @GuardedBy("mLock") boolean mDevCfgDisableFlushForViewTreeAppearing;
private final Executor mDataShareExecutor = Executors.newCachedThreadPool();
private final Handler mHandler = new Handler(Looper.getMainLooper());
@@ -359,6 +360,8 @@ public final class ContentCaptureManagerService extends
case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE:
case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_TEXT_CHANGE_FLUSH_FREQUENCY:
case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_UNBIND_TIMEOUT:
+ case ContentCaptureManager
+ .DEVICE_CONFIG_PROPERTY_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING:
setFineTuneParamsFromDeviceConfig();
return;
default:
@@ -388,13 +391,20 @@ public final class ContentCaptureManagerService extends
DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_UNBIND_TIMEOUT,
(int) AbstractRemoteService.PERMANENT_BOUND_TIMEOUT_MS);
+ mDevCfgDisableFlushForViewTreeAppearing = DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
+ ContentCaptureManager
+ .DEVICE_CONFIG_PROPERTY_DISABLE_FLUSH_FOR_VIEW_TREE_APPEARING,
+ false);
if (verbose) {
Slog.v(TAG, "setFineTuneParamsFromDeviceConfig(): "
+ "bufferSize=" + mDevCfgMaxBufferSize
+ ", idleFlush=" + mDevCfgIdleFlushingFrequencyMs
+ ", textFluxh=" + mDevCfgTextChangeFlushingFrequencyMs
+ ", logHistory=" + mDevCfgLogHistorySize
- + ", idleUnbindTimeoutMs=" + mDevCfgIdleUnbindTimeoutMs);
+ + ", idleUnbindTimeoutMs=" + mDevCfgIdleUnbindTimeoutMs
+ + ", disableFlushForViewTreeAppearing="
+ + mDevCfgDisableFlushForViewTreeAppearing);
}
}
}
@@ -629,6 +639,7 @@ public final class ContentCaptureManagerService extends
}
@Override // from AbstractMasterSystemService
+ @GuardedBy("mLock")
protected void dumpLocked(String prefix, PrintWriter pw) {
super.dumpLocked(prefix, pw);
@@ -646,6 +657,8 @@ public final class ContentCaptureManagerService extends
pw.print(prefix2); pw.print("logHistorySize: "); pw.println(mDevCfgLogHistorySize);
pw.print(prefix2); pw.print("idleUnbindTimeoutMs: ");
pw.println(mDevCfgIdleUnbindTimeoutMs);
+ pw.print(prefix2); pw.print("disableFlushForViewTreeAppearing: ");
+ pw.println(mDevCfgDisableFlushForViewTreeAppearing);
pw.print(prefix); pw.println("Global Options:");
mGlobalContentCaptureOptions.dump(prefix2, pw);
}
@@ -1005,12 +1018,15 @@ public final class ContentCaptureManagerService extends
return null;
}
- final ContentCaptureOptions options = new ContentCaptureOptions(mDevCfgLoggingLevel,
- mDevCfgMaxBufferSize, mDevCfgIdleFlushingFrequencyMs,
- mDevCfgTextChangeFlushingFrequencyMs, mDevCfgLogHistorySize,
- whitelistedComponents);
- if (verbose) Slog.v(TAG, "getOptionsForPackage(" + packageName + "): " + options);
- return options;
+ synchronized (mLock) {
+ final ContentCaptureOptions options = new ContentCaptureOptions(mDevCfgLoggingLevel,
+ mDevCfgMaxBufferSize, mDevCfgIdleFlushingFrequencyMs,
+ mDevCfgTextChangeFlushingFrequencyMs, mDevCfgLogHistorySize,
+ mDevCfgDisableFlushForViewTreeAppearing,
+ whitelistedComponents);
+ if (verbose) Slog.v(TAG, "getOptionsForPackage(" + packageName + "): " + options);
+ return options;
+ }
}
@Override
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 57a07139f004..aaa376afa139 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -2739,7 +2739,7 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
.setImsCallServiceType(prev.getImsCallServiceType())
.setImsCallType(prev.getImsCallType()).build());
} else {
- log("There is no active call to report CallQaulity");
+ log("There is no active call to report CallQuality");
return;
}
@@ -2771,6 +2771,18 @@ public class TelephonyRegistry extends ITelephonyRegistry.Stub {
// most purposes.
final CellIdentity noLocationCi = cellIdentity.sanitizeLocationInfo();
+
+ // This shouldn't be necessary, but better to not take the chance
+ final String primaryPlmn = (cellIdentity != null) ? cellIdentity.getPlmn() : "<UNKNOWN>";
+
+ final String logStr = "Registration Failed for phoneId=" + phoneId
+ + " subId=" + subId + "primaryPlmn=" + primaryPlmn
+ + " chosenPlmn=" + chosenPlmn + " domain=" + domain
+ + " causeCode=" + causeCode + " additionalCauseCode=" + additionalCauseCode;
+
+ mLocalLog.log(logStr);
+ if (DBG) log(logStr);
+
synchronized (mRecords) {
if (validatePhoneId(phoneId)) {
for (Record r : mRecords) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 96d5f38bd720..2045cca8be16 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -191,7 +191,6 @@ import android.app.ApplicationStartInfo;
import android.app.ApplicationThreadConstants;
import android.app.BackgroundStartPrivileges;
import android.app.BroadcastOptions;
-import android.app.ComponentOptions;
import android.app.ContentProviderHolder;
import android.app.ForegroundServiceDelegationOptions;
import android.app.IActivityController;
@@ -7031,6 +7030,17 @@ public class ActivityManagerService extends IActivityManager.Stub
mCpHelper.getProviderMimeTypeAsync(uri, userId, resultCallback);
}
+ /**
+ * Filters calls to getType based on permission. If the caller has required permission,
+ * then it returns the contentProvider#getType.
+ * Else, it returns the contentProvider#getTypeAnonymous, which does not
+ * reveal any internal information which should be protected by any permission.
+ */
+ @Override
+ public void getMimeTypeFilterAsync(Uri uri, int userId, RemoteCallback resultCallback) {
+ mCpHelper.getMimeTypeFilterAsync(uri, userId, resultCallback);
+ }
+
// =========================================================
// GLOBAL MANAGEMENT
// =========================================================
@@ -8603,7 +8613,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// On Automotive / Headless System User Mode, at this point the system user has already been
// started and unlocked, and some of the tasks we do here have already been done. So skip
// those in that case. The duplicate system user start is guarded in SystemServiceManager.
- // TODO(b/242195409): this workaround shouldn't be necessary once we move the headless-user
+ // TODO(b/266158156): this workaround shouldn't be necessary once we move the headless-user
// start logic to UserManager-land.
mUserController.onSystemUserStarting();
@@ -8636,7 +8646,7 @@ public class ActivityManagerService extends IActivityManager.Stub
// Some systems - like automotive - will explicitly unlock system user then switch
// to a secondary user.
- // TODO(b/242195409): this workaround shouldn't be necessary once we move
+ // TODO(b/266158156): this workaround shouldn't be necessary once we move
// the headless-user start logic to UserManager-land.
if (isBootingSystemUser && !UserManager.isHeadlessSystemUserMode()) {
t.traceBegin("startHomeOnAllDisplays");
@@ -8659,26 +8669,10 @@ public class ActivityManagerService extends IActivityManager.Stub
final int callingPid = Binder.getCallingPid();
final long ident = Binder.clearCallingIdentity();
try {
- Intent intent = new Intent(Intent.ACTION_USER_STARTED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
- | Intent.FLAG_RECEIVER_FOREGROUND);
- intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId);
- broadcastIntentLocked(null, null, null, intent,
- null, null, 0, null, null, null, null, null, OP_NONE,
- null, false, false, MY_PID, SYSTEM_UID, callingUid, callingPid,
- currentUserId);
- intent = new Intent(Intent.ACTION_USER_STARTING);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- intent.putExtra(Intent.EXTRA_USER_HANDLE, currentUserId);
- broadcastIntentLocked(null, null, null, intent, null,
- new IIntentReceiver.Stub() {
- @Override
- public void performReceive(Intent intent, int resultCode,
- String data, Bundle extras, boolean ordered, boolean sticky,
- int sendingUser) {}
- }, 0, null, null, new String[] {INTERACT_ACROSS_USERS}, null, null,
- OP_NONE, null, true, false, MY_PID, SYSTEM_UID, callingUid, callingPid,
- UserHandle.USER_ALL);
+ mUserController.sendUserStartedBroadcast(
+ currentUserId, callingUid, callingPid);
+ mUserController.sendUserStartingBroadcast(
+ currentUserId, callingUid, callingPid);
} catch (Throwable e) {
Slog.wtf(TAG, "Failed sending first user broadcasts", e);
} finally {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 19235c9985a7..160756616907 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -29,6 +29,7 @@ import static android.os.BatteryStats.POWER_DATA_UNAVAILABLE;
import android.annotation.EnforcePermission;
import android.annotation.NonNull;
import android.annotation.RequiresNoPermission;
+import android.app.AlarmManager;
import android.app.StatsManager;
import android.app.usage.NetworkStatsManager;
import android.bluetooth.BluetoothActivityEnergyInfo;
@@ -370,6 +371,16 @@ public final class BatteryStatsService extends IBatteryStats.Stub
mStats.setRadioScanningTimeoutLocked(mContext.getResources().getInteger(
com.android.internal.R.integer.config_radioScanningTimeout) * 1000L);
mStats.setPowerProfileLocked(mPowerProfile);
+
+ final boolean resetOnUnplugHighBatteryLevel = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_batteryStatsResetOnUnplugHighBatteryLevel);
+ final boolean resetOnUnplugAfterSignificantCharge = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_batteryStatsResetOnUnplugAfterSignificantCharge);
+ mStats.setBatteryStatsConfig(
+ new BatteryStatsImpl.BatteryStatsConfig.Builder()
+ .setResetOnUnplugHighBatteryLevel(resetOnUnplugHighBatteryLevel)
+ .setResetOnUnplugAfterSignificantCharge(resetOnUnplugAfterSignificantCharge)
+ .build());
mStats.startTrackingSystemServerCpuTime();
if (BATTERY_USAGE_STORE_ENABLED) {
@@ -401,6 +412,18 @@ public final class BatteryStatsService extends IBatteryStats.Stub
Slog.e(TAG, "Could not register INetworkManagement event observer " + e);
}
+ final AlarmManager am = mContext.getSystemService(AlarmManager.class);
+ mHandler.post(() -> {
+ synchronized (mStats) {
+ mStats.setLongPlugInAlarmInterface(new AlarmInterface(am, () -> {
+ synchronized (mStats) {
+ if (mStats.isOnBattery()) return;
+ mStats.maybeResetWhilePluggedInLocked();
+ }
+ }));
+ }
+ });
+
synchronized (mPowerStatsLock) {
mPowerStatsInternal = LocalServices.getService(PowerStatsInternal.class);
if (mPowerStatsInternal != null) {
@@ -2484,6 +2507,32 @@ public final class BatteryStatsService extends IBatteryStats.Stub
}
}
+ final class AlarmInterface implements BatteryStatsImpl.AlarmInterface,
+ AlarmManager.OnAlarmListener {
+ private AlarmManager mAm;
+ private Runnable mOnAlarm;
+
+ AlarmInterface(AlarmManager am, Runnable onAlarm) {
+ mAm = am;
+ mOnAlarm = onAlarm;
+ }
+
+ @Override
+ public void schedule(long rtcTimeMs, long windowLengthMs) {
+ mAm.setWindow(AlarmManager.RTC, rtcTimeMs, windowLengthMs, TAG, this, mHandler);
+ }
+
+ @Override
+ public void cancel() {
+ mAm.cancel(this);
+ }
+
+ @Override
+ public void onAlarm() {
+ mOnAlarm.run();
+ }
+ }
+
private static native int nativeWaitWakeup(ByteBuffer outBuffer);
private void dumpHelp(PrintWriter pw) {
@@ -2684,7 +2733,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub
} else if ("--reset-all".equals(arg)) {
awaitCompletion();
synchronized (mStats) {
- mStats.resetAllStatsCmdLocked();
+ mStats.resetAllStatsAndHistoryLocked(
+ BatteryStatsImpl.RESET_REASON_ADB_COMMAND);
mBatteryUsageStatsStore.removeAllSnapshots();
pw.println("Battery stats and history reset.");
noOutput = true;
@@ -2692,7 +2742,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub
} else if ("--reset".equals(arg)) {
awaitCompletion();
synchronized (mStats) {
- mStats.resetAllStatsCmdLocked();
+ mStats.resetAllStatsAndHistoryLocked(
+ BatteryStatsImpl.RESET_REASON_ADB_COMMAND);
pw.println("Battery stats reset.");
noOutput = true;
}
diff --git a/services/core/java/com/android/server/am/BroadcastProcessQueue.java b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
index 6e97317a5523..84c03e59c658 100644
--- a/services/core/java/com/android/server/am/BroadcastProcessQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastProcessQueue.java
@@ -751,6 +751,22 @@ class BroadcastProcessQueue {
}
/**
+ * Quickly determine if this queue has ordered broadcasts waiting to be delivered,
+ * which indicates we should request an OOM adjust.
+ */
+ public boolean isPendingOrdered() {
+ return mCountOrdered > 0;
+ }
+
+ /**
+ * Quickly determine if this queue has broadcasts waiting to be delivered for which result is
+ * expected from the senders, which indicates we should request an OOM adjust.
+ */
+ public boolean isPendingResultTo() {
+ return mCountResultTo > 0;
+ }
+
+ /**
* Report whether this queue is currently handling an urgent broadcast.
*/
public boolean isPendingUrgent() {
diff --git a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
index 5c7fde79821c..b942f4b96b21 100644
--- a/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
+++ b/services/core/java/com/android/server/am/BroadcastQueueModernImpl.java
@@ -466,7 +466,9 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
// Emit all trace events for this process into a consistent track
queue.runningTraceTrackName = TAG + ".mRunning[" + queueIndex + "]";
- queue.runningOomAdjusted = queue.isPendingManifest();
+ queue.runningOomAdjusted = queue.isPendingManifest()
+ || queue.isPendingOrdered()
+ || queue.isPendingResultTo();
// If already warm, we can make OOM adjust request immediately;
// otherwise we need to wait until process becomes warm
@@ -1620,6 +1622,18 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
*/
private void notifyFinishReceiver(@Nullable BroadcastProcessQueue queue,
@NonNull BroadcastRecord r, int index, @NonNull Object receiver) {
+ if (r.wasDeliveryAttempted(index)) {
+ logBroadcastDeliveryEventReported(queue, r, index, receiver);
+ }
+
+ final boolean recordFinished = (r.terminalCount == r.receivers.size());
+ if (recordFinished) {
+ notifyFinishBroadcast(r);
+ }
+ }
+
+ private void logBroadcastDeliveryEventReported(@Nullable BroadcastProcessQueue queue,
+ @NonNull BroadcastRecord r, int index, @NonNull Object receiver) {
// Report statistics for each individual receiver
final int uid = getReceiverUid(receiver);
final int senderUid = (r.callingUid == -1) ? Process.SYSTEM_UID : r.callingUid;
@@ -1647,11 +1661,6 @@ class BroadcastQueueModernImpl extends BroadcastQueue {
FrameworkStatsLog.write(BROADCAST_DELIVERY_EVENT_REPORTED, uid, senderUid, actionName,
receiverType, type, dispatchDelay, receiveDelay, finishDelay, packageState);
}
-
- final boolean recordFinished = (r.terminalCount == r.receivers.size());
- if (recordFinished) {
- notifyFinishBroadcast(r);
- }
}
private void notifyFinishBroadcast(@NonNull BroadcastRecord r) {
diff --git a/services/core/java/com/android/server/am/BroadcastRecord.java b/services/core/java/com/android/server/am/BroadcastRecord.java
index 67783be871b6..f793c5078b5e 100644
--- a/services/core/java/com/android/server/am/BroadcastRecord.java
+++ b/services/core/java/com/android/server/am/BroadcastRecord.java
@@ -632,6 +632,18 @@ final class BroadcastRecord extends Binder {
return delivery[index];
}
+ boolean wasDeliveryAttempted(int index) {
+ final int deliveryState = getDeliveryState(index);
+ switch (deliveryState) {
+ case DELIVERY_DELIVERED:
+ case DELIVERY_TIMEOUT:
+ case DELIVERY_FAILURE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
void copyEnqueueTimeFrom(@NonNull BroadcastRecord replacedBroadcast) {
originalEnqueueClockTime = enqueueClockTime;
enqueueTime = replacedBroadcast.enqueueTime;
diff --git a/services/core/java/com/android/server/am/ContentProviderHelper.java b/services/core/java/com/android/server/am/ContentProviderHelper.java
index 31301666ad53..f721d69958f5 100644
--- a/services/core/java/com/android/server/am/ContentProviderHelper.java
+++ b/services/core/java/com/android/server/am/ContentProviderHelper.java
@@ -15,6 +15,7 @@
*/
package com.android.server.am;
+import static android.Manifest.permission.GET_ANY_PROVIDER_TYPE;
import static android.content.ContentProvider.isAuthorityRedirectedForCloneProfile;
import static android.os.Process.PROC_CHAR;
import static android.os.Process.PROC_OUT_LONG;
@@ -23,8 +24,6 @@ import static android.os.Process.PROC_SPACE_TERM;
import static android.os.Process.SYSTEM_UID;
import static com.android.internal.util.FrameworkStatsLog.GET_TYPE_ACCESSED_WITHOUT_PERMISSION;
-import static com.android.internal.util.FrameworkStatsLog.GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__AM_CHECK_URI_PERMISSION;
-import static com.android.internal.util.FrameworkStatsLog.GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__AM_ERROR;
import static com.android.internal.util.FrameworkStatsLog.GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__AM_FRAMEWORK_PERMISSION;
import static com.android.internal.util.FrameworkStatsLog.PROVIDER_ACQUISITION_EVENT_REPORTED;
import static com.android.internal.util.FrameworkStatsLog.PROVIDER_ACQUISITION_EVENT_REPORTED__PACKAGE_STOPPED_STATE__PACKAGE_STATE_NORMAL;
@@ -52,7 +51,6 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.IContentProvider;
import android.content.Intent;
-import android.content.PermissionChecker;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -1019,9 +1017,6 @@ public class ContentProviderHelper {
mService.mHandler.postDelayed(providerNotResponding, 1000);
try {
final String type = holder.provider.getType(uri);
- if (type != null) {
- backgroundLogging(callingUid, callingPid, userId, uri, holder, type);
- }
return type;
} finally {
mService.mHandler.removeCallbacks(providerNotResponding);
@@ -1079,10 +1074,6 @@ public class ContentProviderHelper {
Binder.restoreCallingIdentity(identity);
}
resultCallback.sendResult(result);
- final String type = result.getPairValue();
- if (type != null) {
- backgroundLogging(callingUid, callingPid, userId, uri, holder, type);
- }
}));
} else {
resultCallback.sendResult(Bundle.EMPTY);
@@ -1093,67 +1084,84 @@ public class ContentProviderHelper {
}
}
- private void backgroundLogging(int callingUid, int callingPid, int userId, Uri uri,
- ContentProviderHolder holder, String type) {
- // Push the logging code in a different handlerThread.
+ /**
+ * Filters calls to getType based on permission. If the caller has required permission,
+ * then it returns the contentProvider#getType.
+ * Else, it returns the contentProvider#getTypeAnonymous, which does not
+ * reveal any internal information which should be protected by any permission.
+ */
+ void getMimeTypeFilterAsync(Uri uri, int userId, RemoteCallback resultCallback) {
+ mService.enforceNotIsolatedCaller("getProviderMimeTypeAsync");
+ final String name = uri.getAuthority();
+ final int callingUid = Binder.getCallingUid();
+ final int callingPid = Binder.getCallingPid();
+ final int safeUserId = mService.mUserController.unsafeConvertIncomingUser(userId);
+ final long ident = canClearIdentity(callingPid, callingUid, safeUserId)
+ ? Binder.clearCallingIdentity() : 0;
+ final ContentProviderHolder holder;
try {
- mService.mHandler.post(new Runnable() {
- @Override
- public void run() {
- logGetTypeData(callingUid, callingPid, userId,
- uri, holder, type);
- }
- });
- } catch (Exception e) {
- // To ensure logging does not break the getType calls.
+ holder = getContentProviderExternalUnchecked(name, null /* token */, callingUid,
+ "*getmimetype*", safeUserId);
+ } finally {
+ if (ident != 0) {
+ Binder.restoreCallingIdentity(ident);
+ }
}
- }
- // Utility function to log the getTypeData calls
- private void logGetTypeData(int callingUid, int callingPid, int userId, Uri uri,
- ContentProviderHolder holder, String type) {
try {
- boolean checkUser = true;
- final String authority = uri.getAuthority();
- if (isAuthorityRedirectedForCloneProfile(authority)) {
- UserManagerInternal umInternal =
- LocalServices.getService(UserManagerInternal.class);
- UserInfo userInfo = umInternal.getUserInfo(userId);
-
- if (userInfo != null && userInfo.isCloneProfile()) {
- userId = umInternal.getProfileParentId(userId);
- checkUser = false;
+ if (isHolderVisibleToCaller(holder, callingUid, safeUserId)) {
+ if (checkGetAnyTypePermission(callingUid, callingPid)) {
+ final AttributionSource attributionSource =
+ new AttributionSource.Builder(callingUid).build();
+ holder.provider.getTypeAsync(attributionSource,
+ uri, new RemoteCallback(result -> {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ removeContentProviderExternalUnchecked(name, null, safeUserId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ resultCallback.sendResult(result);
+ }));
+ } else {
+ holder.provider.getTypeAnonymousAsync(uri, new RemoteCallback(result -> {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ removeContentProviderExternalUnchecked(name, null, safeUserId);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ resultCallback.sendResult(result);
+ final String type = result.getPairValue();
+ if (type != null) {
+ logGetTypeData(callingUid, uri, type);
+ }
+ }));
}
+ } else {
+ resultCallback.sendResult(Bundle.EMPTY);
}
- final ProviderInfo cpi = holder.info;
- final AttributionSource attributionSource =
- new AttributionSource.Builder(callingUid).build();
- final String permissionCheck =
- checkContentProviderPermission(cpi, callingPid, callingUid,
- userId, checkUser, null);
- final boolean grantCheck = mService.checkUriPermission(uri, callingPid, callingUid,
- Intent.FLAG_GRANT_READ_URI_PERMISSION , userId, null)
- == PackageManager.PERMISSION_GRANTED;
-
- if (!grantCheck && permissionCheck != null) {
- FrameworkStatsLog.write(GET_TYPE_ACCESSED_WITHOUT_PERMISSION,
- GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__AM_FRAMEWORK_PERMISSION,
- callingUid, authority, type);
- } else if (!grantCheck && cpi.forceUriPermissions
- && holder.provider.checkUriPermission(attributionSource,
- uri, callingUid, Intent.FLAG_GRANT_READ_URI_PERMISSION)
- != PermissionChecker.PERMISSION_GRANTED) {
- FrameworkStatsLog.write(GET_TYPE_ACCESSED_WITHOUT_PERMISSION,
- GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__AM_CHECK_URI_PERMISSION,
- callingUid, authority, type);
- }
- } catch (Exception e) {
- FrameworkStatsLog.write(GET_TYPE_ACCESSED_WITHOUT_PERMISSION,
- GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__AM_ERROR, callingUid,
- uri.getAuthority(), type);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Content provider dead retrieving " + uri, e);
+ resultCallback.sendResult(Bundle.EMPTY);
}
}
+ private boolean checkGetAnyTypePermission(int callingUid, int callingPid) {
+ if (mService.checkPermission(GET_ANY_PROVIDER_TYPE, callingPid, callingUid)
+ == PackageManager.PERMISSION_GRANTED) {
+ return true;
+ }
+ return false;
+ }
+
+ // Utility function to log the getTypeData calls
+ private void logGetTypeData(int callingUid, Uri uri, String type) {
+ FrameworkStatsLog.write(GET_TYPE_ACCESSED_WITHOUT_PERMISSION,
+ GET_TYPE_ACCESSED_WITHOUT_PERMISSION__LOCATION__AM_FRAMEWORK_PERMISSION,
+ callingUid, uri.getAuthority(), type);
+ }
+
private boolean canClearIdentity(int callingPid, int callingUid, int userId) {
if (UserHandle.getUserId(callingUid) == userId) {
return true;
diff --git a/services/core/java/com/android/server/am/UserController.java b/services/core/java/com/android/server/am/UserController.java
index 0e49c6614483..1b378837e558 100644
--- a/services/core/java/com/android/server/am/UserController.java
+++ b/services/core/java/com/android/server/am/UserController.java
@@ -365,13 +365,13 @@ class UserController implements Handler.Callback {
private volatile ArraySet<String> mCurWaitingUserSwitchCallbacks;
/**
- * Messages for for switching from {@link android.os.UserHandle#SYSTEM}.
+ * Messages for switching from {@link android.os.UserHandle#SYSTEM}.
*/
@GuardedBy("mLock")
private String mSwitchingFromSystemUserMessage;
/**
- * Messages for for switching to {@link android.os.UserHandle#SYSTEM}.
+ * Messages for switching to {@link android.os.UserHandle#SYSTEM}.
*/
@GuardedBy("mLock")
private String mSwitchingToSystemUserMessage;
@@ -384,6 +384,16 @@ class UserController implements Handler.Callback {
private final LockPatternUtils mLockPatternUtils;
+ // TODO(b/266158156): remove this once we improve/refactor the way broadcasts are sent for
+ // the system user in HSUM.
+ @GuardedBy("mLock")
+ private boolean mIsBroadcastSentForSystemUserStarted;
+
+ // TODO(b/266158156): remove this once we improve/refactor the way broadcasts are sent for
+ // the system user in HSUM.
+ @GuardedBy("mLock")
+ private boolean mIsBroadcastSentForSystemUserStarting;
+
volatile boolean mBootCompleted;
/**
@@ -635,7 +645,7 @@ class UserController implements Handler.Callback {
// user transitions to RUNNING_LOCKED. However, in "headless system user mode", the
// system user is explicitly started before the device has finished booting. In
// that case, we need to wait until onBootComplete() to send the broadcast.
- if (!(UserManager.isHeadlessSystemUserMode() && uss.mHandle.isSystem())) {
+ if (!(mInjector.isHeadlessSystemUserMode() && uss.mHandle.isSystem())) {
// ACTION_LOCKED_BOOT_COMPLETED
sendLockedBootCompletedBroadcast(resultTo, userId);
}
@@ -1823,15 +1833,17 @@ class UserController implements Handler.Callback {
needStart = false;
}
- if (needStart) {
- // Send USER_STARTED broadcast
- Intent intent = new Intent(Intent.ACTION_USER_STARTED);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
- | Intent.FLAG_RECEIVER_FOREGROUND);
- intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
- mInjector.broadcastIntent(intent,
- null, null, 0, null, null, null, AppOpsManager.OP_NONE,
- null, false, false, MY_PID, SYSTEM_UID, callingUid, callingPid, userId);
+ // In most cases, broadcast for the system user starting/started is sent by
+ // ActivityManagerService#systemReady(). However on some HSUM devices (e.g. tablets)
+ // the user switches from the system user to a secondary user while running
+ // ActivityManagerService#systemReady(), thus broadcast is not sent for the system user.
+ // Therefore we send the broadcast for the system user here as well in HSUM.
+ // TODO(b/266158156): Improve/refactor the way broadcasts are sent for the system user
+ // in HSUM. Ideally it'd be best to have one single place that sends this notification.
+ final boolean isSystemUserInHeadlessMode = (userId == UserHandle.USER_SYSTEM)
+ && mInjector.isHeadlessSystemUserMode();
+ if (needStart || isSystemUserInHeadlessMode) {
+ sendUserStartedBroadcast(userId, callingUid, callingPid);
}
t.traceEnd();
@@ -1845,23 +1857,9 @@ class UserController implements Handler.Callback {
t.traceEnd();
}
- if (needStart) {
+ if (needStart || isSystemUserInHeadlessMode) {
t.traceBegin("sendRestartBroadcast");
- Intent intent = new Intent(Intent.ACTION_USER_STARTING);
- intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
- mInjector.broadcastIntent(intent,
- null, new IIntentReceiver.Stub() {
- @Override
- public void performReceive(Intent intent, int resultCode,
- String data, Bundle extras, boolean ordered,
- boolean sticky,
- int sendingUser) throws RemoteException {
- }
- }, 0, null, null,
- new String[]{INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE,
- null, true, false, MY_PID, SYSTEM_UID, callingUid, callingPid,
- UserHandle.USER_ALL);
+ sendUserStartingBroadcast(userId, callingUid, callingPid);
t.traceEnd();
}
} finally {
@@ -2283,6 +2281,62 @@ class UserController implements Handler.Callback {
EventLogTags.writeAmSwitchUser(newUserId);
}
+ // The two methods sendUserStartedBroadcast() and sendUserStartingBroadcast()
+ // could be merged for better reuse. However, the params they are calling broadcastIntent()
+ // with are different - resultCode receiver, permissions, ordered, and userId, etc. Therefore,
+ // we decided to keep two separate methods for better code readability/clarity.
+ // TODO(b/266158156): Improve/refactor the way broadcasts are sent for the system user
+ // in HSUM. Ideally it'd be best to have one single place that sends this notification.
+ /** Sends {@code ACTION_USER_STARTED} broadcast. */
+ void sendUserStartedBroadcast(@UserIdInt int userId, int callingUid, int callingPid) {
+ if (userId == UserHandle.USER_SYSTEM) {
+ synchronized (mLock) {
+ // Make sure that the broadcast is sent only once for the system user.
+ if (mIsBroadcastSentForSystemUserStarted) {
+ return;
+ }
+ mIsBroadcastSentForSystemUserStarted = true;
+ }
+ }
+ final Intent intent = new Intent(Intent.ACTION_USER_STARTED);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY
+ | Intent.FLAG_RECEIVER_FOREGROUND);
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+ mInjector.broadcastIntent(intent, /* resolvedType= */ null, /* resultTo= */ null,
+ /* resultCode= */ 0, /* resultData= */ null, /* resultExtras= */ null,
+ /* requiredPermissions= */ null, AppOpsManager.OP_NONE, /* bOptions= */ null,
+ /* ordered= */ false, /* sticky= */ false, MY_PID, SYSTEM_UID,
+ callingUid, callingPid, userId);
+ }
+
+ /** Sends {@code ACTION_USER_STARTING} broadcast. */
+ void sendUserStartingBroadcast(@UserIdInt int userId, int callingUid, int callingPid) {
+ if (userId == UserHandle.USER_SYSTEM) {
+ synchronized (mLock) {
+ // Make sure that the broadcast is sent only once for the system user.
+ if (mIsBroadcastSentForSystemUserStarting) {
+ return;
+ }
+ mIsBroadcastSentForSystemUserStarting = true;
+ }
+ }
+ final Intent intent = new Intent(Intent.ACTION_USER_STARTING);
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ intent.putExtra(Intent.EXTRA_USER_HANDLE, userId);
+ mInjector.broadcastIntent(intent, /* resolvedType= */ null,
+ new IIntentReceiver.Stub() {
+ @Override
+ public void performReceive(Intent intent, int resultCode,
+ String data, Bundle extras, boolean ordered,
+ boolean sticky,
+ int sendingUser) throws RemoteException {
+ }
+ }, /* resultCode= */ 0, /* resultData= */ null, /* resultExtras= */ null,
+ new String[]{INTERACT_ACROSS_USERS}, AppOpsManager.OP_NONE, /* bOptions= */ null,
+ /* ordered= */ true, /* sticky= */ false, MY_PID, SYSTEM_UID,
+ callingUid, callingPid, UserHandle.USER_ALL);
+ }
+
void sendUserSwitchBroadcasts(int oldUserId, int newUserId) {
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
@@ -2568,7 +2622,7 @@ class UserController implements Handler.Callback {
for (int i = 0; i < startedUsers.size(); i++) {
int userId = startedUsers.keyAt(i);
UserState uss = startedUsers.valueAt(i);
- if (!UserManager.isHeadlessSystemUserMode()) {
+ if (!mInjector.isHeadlessSystemUserMode()) {
finishUserBoot(uss, resultTo);
} else {
if (userId == UserHandle.USER_SYSTEM) {
@@ -2589,9 +2643,9 @@ class UserController implements Handler.Callback {
mInjector.reportCurWakefulnessUsageEvent();
}
- // TODO(b/242195409): remove this method if initial system user boot logic is refactored?
+ // TODO(b/266158156): remove this method if initial system user boot logic is refactored?
void onSystemUserStarting() {
- if (!UserManager.isHeadlessSystemUserMode()) {
+ if (!mInjector.isHeadlessSystemUserMode()) {
// Don't need to call on HSUM because it will be called when the system user is
// restarted on background
mInjector.onUserStarting(UserHandle.USER_SYSTEM);
@@ -3059,6 +3113,10 @@ class UserController implements Handler.Callback {
pw.println(" mMaxRunningUsers:" + mMaxRunningUsers);
pw.println(" mUserSwitchUiEnabled:" + mUserSwitchUiEnabled);
pw.println(" mInitialized:" + mInitialized);
+ pw.println(" mIsBroadcastSentForSystemUserStarted:"
+ + mIsBroadcastSentForSystemUserStarted);
+ pw.println(" mIsBroadcastSentForSystemUserStarting:"
+ + mIsBroadcastSentForSystemUserStarting);
if (mSwitchingFromSystemUserMessage != null) {
pw.println(" mSwitchingFromSystemUserMessage: " + mSwitchingFromSystemUserMessage);
}
@@ -3749,6 +3807,10 @@ class UserController implements Handler.Callback {
}, /* message= */ null);
}
+ boolean isHeadlessSystemUserMode() {
+ return UserManager.isHeadlessSystemUserMode();
+ }
+
boolean isUsersOnSecondaryDisplaysEnabled() {
return UserManager.isVisibleBackgroundUsersEnabled();
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index b001f3d0c892..12681565f84c 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -1263,6 +1263,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
sendILMsg(MSG_IL_BTA2DP_TIMEOUT, SENDMSG_QUEUE, a2dpCodec, address, delayMs);
}
+ /*package*/ void setLeAudioTimeout(String address, int device, int delayMs) {
+ sendILMsg(MSG_IL_BTLEAUDIO_TIMEOUT, SENDMSG_QUEUE, device, address, delayMs);
+ }
+
/*package*/ void setAvrcpAbsoluteVolumeSupported(boolean supported) {
synchronized (mDeviceStateLock) {
mBtHelper.setAvrcpAbsoluteVolumeSupported(supported);
@@ -1467,6 +1471,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
mDeviceInventory.onMakeA2dpDeviceUnavailableNow((String) msg.obj, msg.arg1);
}
break;
+ case MSG_IL_BTLEAUDIO_TIMEOUT:
+ // msg.obj == address of LE Audio device
+ synchronized (mDeviceStateLock) {
+ mDeviceInventory.onMakeLeAudioDeviceUnavailableNow(
+ (String) msg.obj, msg.arg1);
+ }
+ break;
case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
final BluetoothDevice btDevice = (BluetoothDevice) msg.obj;
synchronized (mDeviceStateLock) {
@@ -1556,6 +1567,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
case MSG_I_BT_SERVICE_DISCONNECTED_PROFILE:
if (msg.arg1 != BluetoothProfile.HEADSET) {
synchronized (mDeviceStateLock) {
+ mBtHelper.onBtProfileDisconnected(msg.arg1);
mDeviceInventory.onBtProfileDisconnected(msg.arg1);
}
} else {
@@ -1703,12 +1715,14 @@ import java.util.concurrent.atomic.AtomicBoolean;
private static final int MSG_IL_SAVE_NDEF_DEVICE_FOR_STRATEGY = 47;
private static final int MSG_IL_SAVE_REMOVE_NDEF_DEVICE_FOR_STRATEGY = 48;
+ private static final int MSG_IL_BTLEAUDIO_TIMEOUT = 49;
private static boolean isMessageHandledUnderWakelock(int msgId) {
switch(msgId) {
case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
case MSG_L_SET_BT_ACTIVE_DEVICE:
case MSG_IL_BTA2DP_TIMEOUT:
+ case MSG_IL_BTLEAUDIO_TIMEOUT:
case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
case MSG_TOGGLE_HDMI:
case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT:
@@ -1800,6 +1814,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
case MSG_L_SET_BT_ACTIVE_DEVICE:
case MSG_L_SET_WIRED_DEVICE_CONNECTION_STATE:
case MSG_IL_BTA2DP_TIMEOUT:
+ case MSG_IL_BTLEAUDIO_TIMEOUT:
case MSG_L_A2DP_DEVICE_CONFIG_CHANGE:
if (sLastDeviceConnectMsgTime >= time) {
// add a little delay to make sure messages are ordered as expected
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index f9270c9b32bb..aae1d3884344 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -395,7 +395,7 @@ public class AudioDeviceInventory {
case BluetoothProfile.LE_AUDIO:
case BluetoothProfile.LE_AUDIO_BROADCAST:
if (switchToUnavailable) {
- makeLeAudioDeviceUnavailable(address, btInfo.mAudioSystemDevice);
+ makeLeAudioDeviceUnavailableNow(address, btInfo.mAudioSystemDevice);
} else if (switchToAvailable) {
makeLeAudioDeviceAvailable(address, BtHelper.getName(btInfo.mDevice),
streamType, btInfo.mVolume == -1 ? -1 : btInfo.mVolume * 10,
@@ -507,6 +507,12 @@ public class AudioDeviceInventory {
}
}
+ /*package*/ void onMakeLeAudioDeviceUnavailableNow(String address, int device) {
+ synchronized (mDevicesLock) {
+ makeLeAudioDeviceUnavailableNow(address, device);
+ }
+ }
+
/*package*/ void onReportNewRoutes() {
int n = mRoutesObservers.beginBroadcast();
if (n > 0) {
@@ -1027,10 +1033,11 @@ public class AudioDeviceInventory {
new MediaMetrics.Item(mMetricsId + "disconnectLeAudio")
.record();
if (toRemove.size() > 0) {
- final int delay = checkSendBecomingNoisyIntentInt(device, 0,
+ final int delay = checkSendBecomingNoisyIntentInt(device,
+ AudioService.CONNECTION_STATE_DISCONNECTED,
AudioSystem.DEVICE_NONE);
toRemove.stream().forEach(deviceAddress ->
- makeLeAudioDeviceUnavailable(deviceAddress, device)
+ makeLeAudioDeviceUnavailableLater(deviceAddress, device, delay)
);
}
}
@@ -1331,9 +1338,21 @@ public class AudioDeviceInventory {
*/
mDeviceBroker.setBluetoothA2dpOnInt(true, false /*fromA2dp*/, eventSource);
- AudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(device, address, name),
+ final int res = AudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(
+ device, address, name),
AudioSystem.DEVICE_STATE_AVAILABLE,
AudioSystem.AUDIO_FORMAT_DEFAULT);
+ if (res != AudioSystem.AUDIO_STATUS_OK) {
+ AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
+ "APM failed to make available LE Audio device addr=" + address
+ + " error=" + res).printLog(TAG));
+ // TODO: connection failed, stop here
+ // TODO: return;
+ } else {
+ AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
+ "LE Audio device addr=" + address + " now available").printLog(TAG));
+ }
+
mConnectedDevices.put(DeviceInfo.makeDeviceListKey(device, address),
new DeviceInfo(device, name, address, AudioSystem.AUDIO_FORMAT_DEFAULT));
mDeviceBroker.postAccessoryPlugMediaUnmute(device);
@@ -1354,11 +1373,23 @@ public class AudioDeviceInventory {
}
@GuardedBy("mDevicesLock")
- private void makeLeAudioDeviceUnavailable(String address, int device) {
+ private void makeLeAudioDeviceUnavailableNow(String address, int device) {
if (device != AudioSystem.DEVICE_NONE) {
- AudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(device, address),
+ final int res = AudioSystem.setDeviceConnectionState(new AudioDeviceAttributes(
+ device, address),
AudioSystem.DEVICE_STATE_UNAVAILABLE,
AudioSystem.AUDIO_FORMAT_DEFAULT);
+
+ if (res != AudioSystem.AUDIO_STATUS_OK) {
+ AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
+ "APM failed to make unavailable LE Audio device addr=" + address
+ + " error=" + res).printLog(TAG));
+ // TODO: failed to disconnect, stop here
+ // TODO: return;
+ } else {
+ AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
+ "LE Audio device addr=" + address + " made unavailable").printLog(TAG));
+ }
mConnectedDevices.remove(DeviceInfo.makeDeviceListKey(device, address));
}
@@ -1366,6 +1397,14 @@ public class AudioDeviceInventory {
}
@GuardedBy("mDevicesLock")
+ private void makeLeAudioDeviceUnavailableLater(String address, int device, int delayMs) {
+ // the device will be made unavailable later, so consider it disconnected right away
+ mConnectedDevices.remove(DeviceInfo.makeDeviceListKey(device, address));
+ // send the delayed message to make the device unavailable later
+ mDeviceBroker.setLeAudioTimeout(address, device, delayMs);
+ }
+
+ @GuardedBy("mDevicesLock")
private void setCurrentAudioRouteNameIfPossible(String name, boolean fromA2dp) {
synchronized (mCurAudioRoutes) {
if (TextUtils.equals(mCurAudioRoutes.bluetoothName, name)) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index c2c59f2026cc..88c0c7ff052b 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -4370,7 +4370,8 @@ public class AudioService extends IAudioService.Stub
}
}
- private void setLeAudioVolumeOnModeUpdate(int mode, int device) {
+ private void setLeAudioVolumeOnModeUpdate(int mode, int device, int streamType, int index,
+ int maxIndex) {
switch (mode) {
case AudioSystem.MODE_IN_COMMUNICATION:
case AudioSystem.MODE_IN_CALL:
@@ -4388,16 +4389,15 @@ public class AudioService extends IAudioService.Stub
// (like the outgoing call) the value of 'device' is not DEVICE_OUT_BLE_*
// even when BLE is connected.
if (!AudioSystem.isLeAudioDeviceType(device)) {
+ Log.w(TAG, "setLeAudioVolumeOnModeUpdate got unexpected device=" + device
+ + ", forcing to device=" + AudioSystem.DEVICE_OUT_BLE_HEADSET);
device = AudioSystem.DEVICE_OUT_BLE_HEADSET;
}
- final int streamType = getBluetoothContextualVolumeStream(mode);
- final int index = mStreamStates[streamType].getIndex(device);
- final int maxIndex = mStreamStates[streamType].getMaxIndex();
-
if (DEBUG_VOL) {
- Log.d(TAG, "setLeAudioVolumeOnModeUpdate postSetLeAudioVolumeIndex index="
- + index + " maxIndex=" + maxIndex + " streamType=" + streamType);
+ Log.d(TAG, "setLeAudioVolumeOnModeUpdate postSetLeAudioVolumeIndex device="
+ + device + ", mode=" + mode + ", index=" + index + " maxIndex=" + maxIndex
+ + " streamType=" + streamType);
}
mDeviceBroker.postSetLeAudioVolumeIndex(index, maxIndex, streamType);
mDeviceBroker.postApplyVolumeOnDevice(streamType, device, "setLeAudioVolumeOnModeUpdate");
@@ -5865,10 +5865,18 @@ public class AudioService extends IAudioService.Stub
mModeLogger.enqueue(new PhoneStateEvent(requesterPackage, requesterPid,
requestedMode, pid, mode));
- int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
- int device = getDeviceForStream(streamType);
- int index = mStreamStates[mStreamVolumeAlias[streamType]].getIndex(device);
- setStreamVolumeInt(mStreamVolumeAlias[streamType], index, device, true,
+ final int streamType = getActiveStreamType(AudioManager.USE_DEFAULT_STREAM_TYPE);
+ final int device = getDeviceForStream(streamType);
+ final int streamAlias = mStreamVolumeAlias[streamType];
+
+ if (DEBUG_MODE) {
+ Log.v(TAG, "onUpdateAudioMode: streamType=" + streamType
+ + ", streamAlias=" + streamAlias);
+ }
+
+ final int index = mStreamStates[streamAlias].getIndex(device);
+ final int maxIndex = mStreamStates[streamAlias].getMaxIndex();
+ setStreamVolumeInt(streamAlias, index, device, true,
requesterPackage, true /*hasModifyAudioSettings*/);
updateStreamVolumeAlias(true /*updateVolumes*/, requesterPackage);
@@ -5876,7 +5884,7 @@ public class AudioService extends IAudioService.Stub
// change of mode may require volume to be re-applied on some devices
updateAbsVolumeMultiModeDevices(previousMode, mode);
- setLeAudioVolumeOnModeUpdate(mode, device);
+ setLeAudioVolumeOnModeUpdate(mode, device, streamAlias, index, maxIndex);
// when entering RINGTONE, IN_CALL or IN_COMMUNICATION mode, clear all SCO
// connections not started by the application changing the mode when pid changes
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index df65dbd53e06..2dcdc5419452 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -278,7 +278,11 @@ public class BtHelper {
}
AudioService.sVolumeLogger.enqueue(new AudioServiceEvents.VolumeEvent(
AudioServiceEvents.VolumeEvent.VOL_SET_AVRCP_VOL, index));
- mA2dp.setAvrcpAbsoluteVolume(index);
+ try {
+ mA2dp.setAvrcpAbsoluteVolume(index);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception while changing abs volume", e);
+ }
}
/*package*/ synchronized @AudioSystem.AudioFormatNativeEnumForBtCodec int getA2dpCodec(
@@ -286,7 +290,12 @@ public class BtHelper {
if (mA2dp == null) {
return AudioSystem.AUDIO_FORMAT_DEFAULT;
}
- final BluetoothCodecStatus btCodecStatus = mA2dp.getCodecStatus(device);
+ BluetoothCodecStatus btCodecStatus = null;
+ try {
+ btCodecStatus = mA2dp.getCodecStatus(device);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception while getting status of " + device, e);
+ }
if (btCodecStatus == null) {
return AudioSystem.AUDIO_FORMAT_DEFAULT;
}
@@ -420,7 +429,11 @@ public class BtHelper {
}
AudioService.sVolumeLogger.enqueue(new AudioServiceEvents.VolumeEvent(
AudioServiceEvents.VolumeEvent.VOL_SET_LE_AUDIO_VOL, index, maxIndex));
- mLeAudio.setVolume(volume);
+ try {
+ mLeAudio.setVolume(volume);
+ } catch (Exception e) {
+ Log.e(TAG, "Exception while setting LE volume", e);
+ }
}
/*package*/ synchronized void setHearingAidVolume(int index, int streamType,
@@ -446,7 +459,11 @@ public class BtHelper {
AudioService.sVolumeLogger.enqueue(new AudioServiceEvents.VolumeEvent(
AudioServiceEvents.VolumeEvent.VOL_SET_HEARING_AID_VOL, index, gainDB));
}
- mHearingAid.setVolume(gainDB);
+ try {
+ mHearingAid.setVolume(gainDB);
+ } catch (Exception e) {
+ Log.i(TAG, "Exception while setting hearing aid volume", e);
+ }
}
/*package*/ synchronized void onBroadcastScoConnectionState(int state) {
@@ -471,7 +488,7 @@ public class BtHelper {
}
// @GuardedBy("AudioDeviceBroker.mSetModeLock")
- @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
+ //@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ synchronized void resetBluetoothSco() {
mScoAudioState = SCO_STATE_INACTIVE;
broadcastScoConnectionState(AudioManager.SCO_AUDIO_STATE_DISCONNECTED);
@@ -486,6 +503,35 @@ public class BtHelper {
mBluetoothHeadset = null;
}
+ //@GuardedBy("AudioDeviceBroker.mDeviceStateLock")
+ /*package*/ synchronized void onBtProfileDisconnected(int profile) {
+ switch (profile) {
+ case BluetoothProfile.A2DP:
+ mA2dp = null;
+ break;
+ case BluetoothProfile.HEARING_AID:
+ mHearingAid = null;
+ break;
+ case BluetoothProfile.LE_AUDIO:
+ mLeAudio = null;
+ break;
+
+ case BluetoothProfile.A2DP_SINK:
+ case BluetoothProfile.LE_AUDIO_BROADCAST:
+ // shouldn't be received here as profile doesn't involve BtHelper
+ Log.e(TAG, "onBtProfileDisconnected: Not a profile handled by BtHelper "
+ + BluetoothProfile.getProfileName(profile));
+ break;
+
+ default:
+ // Not a valid profile to disconnect
+ Log.e(TAG, "onBtProfileDisconnected: Not a valid profile to disconnect "
+ + BluetoothProfile.getProfileName(profile));
+ break;
+ }
+ }
+
+ @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ synchronized void onBtProfileConnected(int profile, BluetoothProfile proxy) {
if (profile == BluetoothProfile.HEADSET) {
onHeadsetProfileConnected((BluetoothHeadset) proxy);
@@ -671,7 +717,6 @@ public class BtHelper {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
switch(profile) {
case BluetoothProfile.A2DP:
- case BluetoothProfile.A2DP_SINK:
case BluetoothProfile.HEADSET:
case BluetoothProfile.HEARING_AID:
case BluetoothProfile.LE_AUDIO:
@@ -681,6 +726,10 @@ public class BtHelper {
mDeviceBroker.postBtProfileConnected(profile, proxy);
break;
+ case BluetoothProfile.A2DP_SINK:
+ // no A2DP sink functionality handled by BtHelper
+ case BluetoothProfile.LE_AUDIO_BROADCAST:
+ // no broadcast functionality handled by BtHelper
default:
break;
}
@@ -689,14 +738,19 @@ public class BtHelper {
switch (profile) {
case BluetoothProfile.A2DP:
- case BluetoothProfile.A2DP_SINK:
case BluetoothProfile.HEADSET:
case BluetoothProfile.HEARING_AID:
case BluetoothProfile.LE_AUDIO:
- case BluetoothProfile.LE_AUDIO_BROADCAST:
+ AudioService.sDeviceLogger.enqueue(new EventLogger.StringEvent(
+ "BT profile service: disconnecting "
+ + BluetoothProfile.getProfileName(profile) + " profile"));
mDeviceBroker.postBtProfileDisconnected(profile);
break;
+ case BluetoothProfile.A2DP_SINK:
+ // no A2DP sink functionality handled by BtHelper
+ case BluetoothProfile.LE_AUDIO_BROADCAST:
+ // no broadcast functionality handled by BtHelper
default:
break;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
index 57d28f95eb6a..dce88da6f111 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -75,7 +75,6 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
private final LockoutTracker mLockoutTracker;
private final boolean mIsRestricted;
private final boolean mAllowBackgroundAuthentication;
- private final boolean mIsKeyguardBypassEnabled;
// TODO: This is currently hard to maintain, as each AuthenticationClient subclass must update
// the state. We should think of a way to improve this in the future.
@State
@@ -95,7 +94,7 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
@NonNull BiometricLogger biometricLogger, @NonNull BiometricContext biometricContext,
boolean isStrongBiometric, @Nullable TaskStackListener taskStackListener,
@NonNull LockoutTracker lockoutTracker, boolean allowBackgroundAuthentication,
- boolean shouldVibrate, boolean isKeyguardBypassEnabled, int sensorStrength) {
+ boolean shouldVibrate, int sensorStrength) {
super(context, lazyDaemon, token, listener, targetUserId, owner, cookie, sensorId,
shouldVibrate, biometricLogger, biometricContext);
mIsStrongBiometric = isStrongBiometric;
@@ -107,7 +106,6 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
mLockoutTracker = lockoutTracker;
mIsRestricted = restricted;
mAllowBackgroundAuthentication = allowBackgroundAuthentication;
- mIsKeyguardBypassEnabled = isKeyguardBypassEnabled;
mShouldUseLockoutTracker = lockoutTracker != null;
mSensorStrength = sensorStrength;
}
@@ -374,14 +372,6 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
return mState;
}
- /**
- * @return true if the client supports bypass (e.g. passive auth such as face), and if it's
- * enabled by the user.
- */
- public boolean isKeyguardBypassEnabled() {
- return mIsKeyguardBypassEnabled;
- }
-
@Override
public int getProtoEnum() {
return BiometricsProto.CM_AUTHENTICATE;
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java
index b2fd46d1475d..51829684f3ab 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceAuthenticator.java
@@ -23,6 +23,7 @@ import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.ITestSession;
import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.biometrics.SensorPropertiesInternal;
+import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.IFaceService;
import android.os.IBinder;
import android.os.RemoteException;
@@ -64,8 +65,11 @@ public final class FaceAuthenticator extends IBiometricAuthenticator.Stub {
String opPackageName, long requestId, int cookie, boolean allowBackgroundAuthentication)
throws RemoteException {
mFaceService.prepareForAuthentication(mSensorId, requireConfirmation, token, operationId,
- userId, sensorReceiver, opPackageName, requestId, cookie,
- allowBackgroundAuthentication);
+ sensorReceiver, new FaceAuthenticateOptions.Builder()
+ .setUserId(userId)
+ .setOpPackageName(opPackageName)
+ .build(),
+ requestId, cookie, allowBackgroundAuthentication);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
index 0248010bc9f3..1ee9f53c5774 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/FaceService.java
@@ -35,6 +35,7 @@ import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.biometrics.face.IFace;
import android.hardware.biometrics.face.SensorProps;
import android.hardware.face.Face;
+import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.face.FaceServiceReceiver;
import android.hardware.face.IFaceAuthenticatorsRegisteredCallback;
@@ -238,14 +239,15 @@ public class FaceService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override // Binder call
- public long authenticate(final IBinder token, final long operationId, int userId,
- final IFaceServiceReceiver receiver, final String opPackageName,
- boolean isKeyguardBypassEnabled) {
+ public long authenticate(final IBinder token, final long operationId,
+ final IFaceServiceReceiver receiver, final FaceAuthenticateOptions options) {
// TODO(b/152413782): If the sensor supports face detect and the device is encrypted or
// lockdown, something wrong happened. See similar path in FingerprintService.
super.authenticate_enforcePermission();
+ final int userId = options.getUserId();
+ final String opPackageName = options.getOpPackageName();
final boolean restricted = false; // Face APIs are private
final int statsClient = Utils.isKeyguard(getContext(), opPackageName)
? BiometricsProtoEnums.CLIENT_KEYGUARD
@@ -261,18 +263,18 @@ public class FaceService extends SystemService {
return -1;
}
- return provider.second.scheduleAuthenticate(provider.first, token, operationId, userId,
- 0 /* cookie */,
- new ClientMonitorCallbackConverter(receiver), opPackageName, restricted,
- statsClient, isKeyguard, isKeyguardBypassEnabled);
+ return provider.second.scheduleAuthenticate(provider.first, token, operationId,
+ 0 /* cookie */, new ClientMonitorCallbackConverter(receiver), options,
+ restricted, statsClient, isKeyguard);
}
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override // Binder call
- public long detectFace(final IBinder token, final int userId,
- final IFaceServiceReceiver receiver, final String opPackageName) {
+ public long detectFace(final IBinder token,
+ final IFaceServiceReceiver receiver, final FaceAuthenticateOptions options) {
super.detectFace_enforcePermission();
+ final String opPackageName = options.getOpPackageName();
if (!Utils.isKeyguard(getContext(), opPackageName)) {
Slog.w(TAG, "detectFace called from non-sysui package: " + opPackageName);
return -1;
@@ -284,7 +286,7 @@ public class FaceService extends SystemService {
return -1;
}
- return provider.second.scheduleFaceDetect(provider.first, token, userId,
+ return provider.second.scheduleFaceDetect(provider.first, token, options.getUserId(),
new ClientMonitorCallbackConverter(receiver), opPackageName,
BiometricsProtoEnums.CLIENT_KEYGUARD);
}
@@ -292,9 +294,9 @@ public class FaceService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override // Binder call
public void prepareForAuthentication(int sensorId, boolean requireConfirmation,
- IBinder token, long operationId, int userId,
- IBiometricSensorReceiver sensorReceiver, String opPackageName, long requestId,
- int cookie, boolean allowBackgroundAuthentication) {
+ IBinder token, long operationId, IBiometricSensorReceiver sensorReceiver,
+ FaceAuthenticateOptions options, long requestId, int cookie,
+ boolean allowBackgroundAuthentication) {
super.prepareForAuthentication_enforcePermission();
final ServiceProvider provider = mRegistry.getProviderForSensor(sensorId);
@@ -305,10 +307,10 @@ public class FaceService extends SystemService {
final boolean isKeyguardBypassEnabled = false; // only valid for keyguard clients
final boolean restricted = true; // BiometricPrompt is always restricted
- provider.scheduleAuthenticate(sensorId, token, operationId, userId, cookie,
- new ClientMonitorCallbackConverter(sensorReceiver), opPackageName, requestId,
+ provider.scheduleAuthenticate(sensorId, token, operationId, cookie,
+ new ClientMonitorCallbackConverter(sensorReceiver), options, requestId,
restricted, BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
- allowBackgroundAuthentication, isKeyguardBypassEnabled);
+ allowBackgroundAuthentication);
}
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
index 85f95cec8377..609c6a77e50a 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/ServiceProvider.java
@@ -22,6 +22,7 @@ import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.ITestSession;
import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.face.Face;
+import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.FaceManager;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.face.IFaceServiceReceiver;
@@ -88,15 +89,15 @@ public interface ServiceProvider extends BiometricServiceProvider<FaceSensorProp
void cancelFaceDetect(int sensorId, @NonNull IBinder token, long requestId);
- long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId,
+ long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
int cookie, @NonNull ClientMonitorCallbackConverter callback,
- @NonNull String opPackageName, boolean restricted, int statsClient,
- boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled);
+ @NonNull FaceAuthenticateOptions options,
+ boolean restricted, int statsClient, boolean allowBackgroundAuthentication);
- void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId,
+ void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
int cookie, @NonNull ClientMonitorCallbackConverter callback,
- @NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
- boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled);
+ @NonNull FaceAuthenticateOptions options, long requestId,
+ boolean restricted, int statsClient, boolean allowBackgroundAuthentication);
void cancelAuthentication(int sensorId, @NonNull IBinder token, long requestId);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
index d8b825d2c0e5..29dd707a7c1d 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
@@ -85,11 +85,11 @@ class FaceAuthenticationClient extends AuthenticationClient<AidlSession>
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
boolean isStrongBiometric, @NonNull UsageStats usageStats,
@NonNull LockoutCache lockoutCache, boolean allowBackgroundAuthentication,
- boolean isKeyguardBypassEnabled, @Authenticators.Types int sensorStrength) {
+ @Authenticators.Types int sensorStrength) {
this(context, lazyDaemon, token, requestId, listener, targetUserId, operationId,
restricted, owner, cookie, requireConfirmation, sensorId, logger, biometricContext,
isStrongBiometric, usageStats, lockoutCache /* lockoutCache */,
- allowBackgroundAuthentication, isKeyguardBypassEnabled,
+ allowBackgroundAuthentication,
context.getSystemService(SensorPrivacyManager.class), sensorStrength);
}
@@ -102,13 +102,13 @@ class FaceAuthenticationClient extends AuthenticationClient<AidlSession>
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
boolean isStrongBiometric, @NonNull UsageStats usageStats,
@NonNull LockoutCache lockoutCache, boolean allowBackgroundAuthentication,
- boolean isKeyguardBypassEnabled, SensorPrivacyManager sensorPrivacyManager,
+ SensorPrivacyManager sensorPrivacyManager,
@Authenticators.Types int biometricStrength) {
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
owner, cookie, requireConfirmation, sensorId, logger, biometricContext,
isStrongBiometric, null /* taskStackListener */, null /* lockoutCache */,
allowBackgroundAuthentication, false /* shouldVibrate */,
- isKeyguardBypassEnabled, biometricStrength);
+ biometricStrength);
setRequestId(requestId);
mUsageStats = usageStats;
mNotificationManager = context.getSystemService(NotificationManager.class);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
index 89852a14ba9b..41e02691ddf8 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
@@ -32,6 +32,7 @@ import android.hardware.biometrics.common.ComponentInfo;
import android.hardware.biometrics.face.IFace;
import android.hardware.biometrics.face.SensorProps;
import android.hardware.face.Face;
+import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.face.IFaceServiceReceiver;
import android.os.Binder;
@@ -435,21 +436,21 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
@Override
public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
- int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback,
- @NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
- boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled) {
+ int cookie, @NonNull ClientMonitorCallbackConverter callback,
+ @NonNull FaceAuthenticateOptions options,
+ long requestId, boolean restricted, int statsClient,
+ boolean allowBackgroundAuthentication) {
mHandler.post(() -> {
+ final int userId = options.getUserId();
final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
final FaceAuthenticationClient client = new FaceAuthenticationClient(
mContext, mSensors.get(sensorId).getLazySession(), token, requestId, callback,
- userId, operationId, restricted, opPackageName, cookie,
+ userId, operationId, restricted, options.getOpPackageName(), cookie,
false /* requireConfirmation */, sensorId,
createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
mBiometricContext, isStrongBiometric,
mUsageStats, mSensors.get(sensorId).getLockoutCache(),
- allowBackgroundAuthentication, isKeyguardBypassEnabled,
- Utils.getCurrentStrength(sensorId)
- );
+ allowBackgroundAuthentication, Utils.getCurrentStrength(sensorId));
scheduleForSensor(sensorId, client, new ClientMonitorCallback() {
@Override
public void onClientStarted(
@@ -470,14 +471,13 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
@Override
public long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
- int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback,
- @NonNull String opPackageName, boolean restricted, int statsClient,
- boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled) {
+ int cookie, @NonNull ClientMonitorCallbackConverter callback,
+ @NonNull FaceAuthenticateOptions options, boolean restricted, int statsClient,
+ boolean allowBackgroundAuthentication) {
final long id = mRequestCounter.incrementAndGet();
- scheduleAuthenticate(sensorId, token, operationId, userId, cookie, callback,
- opPackageName, id, restricted, statsClient,
- allowBackgroundAuthentication, isKeyguardBypassEnabled);
+ scheduleAuthenticate(sensorId, token, operationId, cookie, callback,
+ options, id, restricted, statsClient, allowBackgroundAuthentication);
return id;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
index 1adc5e3e74b5..7e575bc23f9c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
@@ -31,6 +31,7 @@ import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
import android.hardware.biometrics.face.V1_0.IBiometricsFaceClientCallback;
import android.hardware.face.Face;
+import android.hardware.face.FaceAuthenticateOptions;
import android.hardware.face.FaceSensorPropertiesInternal;
import android.hardware.face.IFaceServiceReceiver;
import android.os.Binder;
@@ -665,19 +666,20 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
@Override
public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
- int userId, int cookie, @NonNull ClientMonitorCallbackConverter receiver,
- @NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
- boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled) {
+ int cookie, @NonNull ClientMonitorCallbackConverter receiver,
+ @NonNull FaceAuthenticateOptions options, long requestId, boolean restricted,
+ int statsClient, boolean allowBackgroundAuthentication) {
mHandler.post(() -> {
+ final int userId = options.getUserId();
scheduleUpdateActiveUserWithoutHandler(userId);
final boolean isStrongBiometric = Utils.isStrongBiometric(mSensorId);
final FaceAuthenticationClient client = new FaceAuthenticationClient(mContext,
mLazyDaemon, token, requestId, receiver, userId, operationId, restricted,
- opPackageName, cookie, false /* requireConfirmation */, mSensorId,
+ options.getOpPackageName(), cookie, false /* requireConfirmation */, mSensorId,
createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
mBiometricContext, isStrongBiometric, mLockoutTracker,
- mUsageStats, allowBackgroundAuthentication, isKeyguardBypassEnabled,
+ mUsageStats, allowBackgroundAuthentication,
Utils.getCurrentStrength(mSensorId));
mScheduler.scheduleClientMonitor(client);
});
@@ -685,14 +687,13 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
@Override
public long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
- int userId, int cookie, @NonNull ClientMonitorCallbackConverter receiver,
- @NonNull String opPackageName, boolean restricted, int statsClient,
- boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled) {
+ int cookie, @NonNull ClientMonitorCallbackConverter receiver,
+ @NonNull FaceAuthenticateOptions options, boolean restricted, int statsClient,
+ boolean allowBackgroundAuthentication) {
final long id = mRequestCounter.incrementAndGet();
- scheduleAuthenticate(sensorId, token, operationId, userId, cookie, receiver,
- opPackageName, id, restricted, statsClient,
- allowBackgroundAuthentication, isKeyguardBypassEnabled);
+ scheduleAuthenticate(sensorId, token, operationId, cookie, receiver,
+ options, id, restricted, statsClient, allowBackgroundAuthentication);
return id;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
index d4a7f085b8c5..1c1f56ccddd5 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
@@ -72,12 +72,12 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> {
@NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
boolean isStrongBiometric, @NonNull LockoutTracker lockoutTracker,
@NonNull UsageStats usageStats, boolean allowBackgroundAuthentication,
- boolean isKeyguardBypassEnabled, @Authenticators.Types int sensorStrength) {
+ @Authenticators.Types int sensorStrength) {
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
owner, cookie, requireConfirmation, sensorId, logger, biometricContext,
isStrongBiometric, null /* taskStackListener */,
lockoutTracker, allowBackgroundAuthentication, false /* shouldVibrate */,
- isKeyguardBypassEnabled, sensorStrength);
+ sensorStrength);
setRequestId(requestId);
mUsageStats = usageStats;
mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index 229393def27f..affc496edc70 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -45,6 +45,7 @@ import android.hardware.biometrics.ITestSessionCallback;
import android.hardware.biometrics.fingerprint.IFingerprint;
import android.hardware.biometrics.fingerprint.PointerContext;
import android.hardware.fingerprint.Fingerprint;
+import android.hardware.fingerprint.FingerprintAuthenticateOptions;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.FingerprintServiceReceiver;
@@ -252,15 +253,15 @@ public class FingerprintService extends SystemService {
public long authenticate(
final IBinder token,
final long operationId,
- final int sensorId,
- final int userId,
final IFingerprintServiceReceiver receiver,
- final String opPackageName,
- final String attributionTag,
- boolean ignoreEnrollmentState) {
+ final FingerprintAuthenticateOptions options) {
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
final int callingUserId = UserHandle.getCallingUserId();
+ final String opPackageName = options.getOpPackageName();
+ final String attributionTag = options.getAttributionTag();
+ final int userId = options.getUserId();
+ final int sensorId = options.getSensorId();
if (!canUseFingerprint(
opPackageName,
@@ -314,7 +315,8 @@ public class FingerprintService extends SystemService {
&& sensorProps != null && sensorProps.isAnyUdfpsType()) {
try {
return authenticateWithPrompt(operationId, sensorProps, callingUid,
- callingUserId, receiver, opPackageName, ignoreEnrollmentState);
+ callingUserId, receiver, opPackageName,
+ options.isIgnoreEnrollmentState());
} catch (PackageManager.NameNotFoundException e) {
Slog.e(TAG, "Invalid package", e);
return -1;
@@ -412,22 +414,31 @@ public class FingerprintService extends SystemService {
@android.annotation.EnforcePermission(android.Manifest.permission.USE_BIOMETRIC_INTERNAL)
@Override
- public long detectFingerprint(final IBinder token, final int userId,
- final IFingerprintServiceReceiver receiver, final String opPackageName) {
+ public long detectFingerprint(final IBinder token,
+ final IFingerprintServiceReceiver receiver,
+ final FingerprintAuthenticateOptions options) {
super.detectFingerprint_enforcePermission();
+ final String opPackageName = options.getOpPackageName();
if (!Utils.isKeyguard(getContext(), opPackageName)) {
Slog.w(TAG, "detectFingerprint called from non-sysui package: " + opPackageName);
return -1;
}
+ if (!Utils.isUserEncryptedOrLockdown(mLockPatternUtils, options.getUserId())) {
+ // If this happens, something in KeyguardUpdateMonitor is wrong. This should only
+ // ever be invoked when the user is encrypted or lockdown.
+ Slog.e(TAG, "detectFingerprint invoked when user is not encrypted or lockdown");
+ return -1;
+ }
+
final Pair<Integer, ServiceProvider> provider = mRegistry.getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for detectFingerprint");
return -1;
}
- return provider.second.scheduleFingerDetect(provider.first, token, userId,
+ return provider.second.scheduleFingerDetect(provider.first, token, options.getUserId(),
new ClientMonitorCallbackConverter(receiver), opPackageName,
BiometricsProtoEnums.CLIENT_KEYGUARD);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
index a90679e755cf..d1a7b1339179 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
@@ -136,7 +136,6 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession>
null /* lockoutCache */,
allowBackgroundAuthentication,
false /* shouldVibrate */,
- false /* isKeyguardBypassEnabled */,
biometricStrength);
setRequestId(requestId);
mSensorOverlays = new SensorOverlays(udfpsOverlayController,
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestHal.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestHal.java
index 67511533de66..399f6a8ca5ad 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestHal.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/TestHal.java
@@ -217,6 +217,16 @@ public class TestHal extends IFingerprint.Stub {
public void onContextChanged(OperationContext context) {
Slog.w(TAG, "onContextChanged");
}
+
+ @Override
+ public void onPointerCancelWithContext(PointerContext context) {
+ Slog.w(TAG, "onPointerCancelWithContext");
+ }
+
+ @Override
+ public void setIgnoreDisplayTouches(boolean shouldIgnore) {
+ Slog.w(TAG, "setIgnoreDisplayTouches");
+ }
};
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
index a9cc897a2937..957005a9223e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
@@ -87,8 +87,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
owner, cookie, requireConfirmation, sensorId, logger, biometricContext,
isStrongBiometric, taskStackListener, lockoutTracker, allowBackgroundAuthentication,
- false /* shouldVibrate */, false /* isKeyguardBypassEnabled */,
- sensorStrength);
+ false /* shouldVibrate */, sensorStrength);
setRequestId(requestId);
mLockoutFrameworkImpl = lockoutTracker;
mSensorOverlays = new SensorOverlays(udfpsOverlayController,
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index c15e419c073c..ab2c002c2b24 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -25,6 +25,8 @@ import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.RouteInfo.RTN_THROW;
import static android.net.RouteInfo.RTN_UNREACHABLE;
import static android.net.VpnManager.NOTIFICATION_CHANNEL_VPN;
+import static android.net.ipsec.ike.IkeSessionParams.ESP_ENCAP_TYPE_AUTO;
+import static android.net.ipsec.ike.IkeSessionParams.ESP_IP_VERSION_AUTO;
import static android.os.PowerWhitelistManager.REASON_VPN;
import static android.os.UserHandle.PER_USER_RANGE;
@@ -251,6 +253,14 @@ public class Vpn {
*/
private static final int STARTING_TOKEN = -1;
+ // TODO : read this from carrier config instead of a constant
+ @VisibleForTesting
+ public static final int AUTOMATIC_KEEPALIVE_DELAY_SECONDS = 30;
+
+ // Default keepalive timeout for carrier config is 5 minutes. Mimic this.
+ @VisibleForTesting
+ static final int DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT = 5 * 60;
+
// TODO: create separate trackers for each unique VPN to support
// automated reconnection
@@ -3071,6 +3081,7 @@ public class Vpn {
prepareStatusIntent();
}
agentConnect(this::onValidationStatus);
+ mSession.setUnderpinnedNetwork(mNetworkAgent.getNetwork());
return; // Link properties are already sent.
} else {
// Underlying networks also set in agentConnect()
@@ -3179,6 +3190,7 @@ public class Vpn {
if (!removedAddrs.isEmpty()) {
startNewNetworkAgent(
mNetworkAgent, "MTU too low for IPv6; restarting network agent");
+ mSession.setUnderpinnedNetwork(mNetworkAgent.getNetwork());
for (LinkAddress removed : removedAddrs) {
mTunnelIface.removeAddress(
@@ -3251,14 +3263,22 @@ public class Vpn {
private IkeSessionParams getIkeSessionParams(@NonNull Network underlyingNetwork) {
final IkeTunnelConnectionParams ikeTunConnParams =
mProfile.getIkeTunnelConnectionParams();
+ final IkeSessionParams.Builder builder;
if (ikeTunConnParams != null) {
- final IkeSessionParams.Builder builder =
- new IkeSessionParams.Builder(ikeTunConnParams.getIkeSessionParams())
- .setNetwork(underlyingNetwork);
- return builder.build();
+ builder = new IkeSessionParams.Builder(ikeTunConnParams.getIkeSessionParams())
+ .setNetwork(underlyingNetwork);
} else {
- return VpnIkev2Utils.buildIkeSessionParams(mContext, mProfile, underlyingNetwork);
+ builder = VpnIkev2Utils.makeIkeSessionParamsBuilder(mContext, mProfile,
+ underlyingNetwork);
}
+ if (mProfile.isAutomaticNattKeepaliveTimerEnabled()) {
+ builder.setNattKeepAliveDelaySeconds(guessNattKeepaliveTimerForNetwork());
+ }
+ if (mProfile.isAutomaticIpVersionSelectionEnabled()) {
+ builder.setIpVersion(guessEspIpVersionForNetwork());
+ builder.setEncapType(guessEspEncapTypeForNetwork());
+ }
+ return builder.build();
}
@NonNull
@@ -3322,6 +3342,23 @@ public class Vpn {
startIkeSession(underlyingNetwork);
}
+ private int guessEspIpVersionForNetwork() {
+ // TODO : guess the IP version based on carrier if auto IP version selection is enabled
+ return ESP_IP_VERSION_AUTO;
+ }
+
+ private int guessEspEncapTypeForNetwork() {
+ // TODO : guess the ESP encap type based on carrier if auto IP version selection is
+ // enabled
+ return ESP_ENCAP_TYPE_AUTO;
+ }
+
+ private int guessNattKeepaliveTimerForNetwork() {
+ // TODO : guess the keepalive delay based on carrier if auto keepalive timer is
+ // enabled
+ return AUTOMATIC_KEEPALIVE_DELAY_SECONDS;
+ }
+
boolean maybeMigrateIkeSession(@NonNull Network underlyingNetwork) {
if (mSession == null || !mMobikeEnabled) return false;
@@ -3331,7 +3368,20 @@ public class Vpn {
+ mCurrentToken
+ " to network "
+ underlyingNetwork);
- mSession.setNetwork(underlyingNetwork);
+ final int ipVersion = mProfile.isAutomaticIpVersionSelectionEnabled()
+ ? guessEspIpVersionForNetwork() : ESP_IP_VERSION_AUTO;
+ final int encapType = mProfile.isAutomaticIpVersionSelectionEnabled()
+ ? guessEspEncapTypeForNetwork() : ESP_ENCAP_TYPE_AUTO;
+ final int keepaliveDelaySeconds;
+ if (mProfile.isAutomaticNattKeepaliveTimerEnabled()) {
+ keepaliveDelaySeconds = guessNattKeepaliveTimerForNetwork();
+ } else if (mProfile.getIkeTunnelConnectionParams() != null) {
+ keepaliveDelaySeconds = mProfile.getIkeTunnelConnectionParams()
+ .getIkeSessionParams().getNattKeepAliveDelaySeconds();
+ } else {
+ keepaliveDelaySeconds = DEFAULT_UDP_PORT_4500_NAT_TIMEOUT_SEC_INT;
+ }
+ mSession.setNetwork(underlyingNetwork, ipVersion, encapType, keepaliveDelaySeconds);
return true;
}
@@ -4661,8 +4711,14 @@ public class Vpn {
}
/** Update the underlying network of the IKE Session */
- public void setNetwork(@NonNull Network network) {
- mImpl.setNetwork(network);
+ public void setNetwork(@NonNull Network network, int ipVersion, int encapType,
+ int keepaliveDelaySeconds) {
+ mImpl.setNetwork(network, ipVersion, encapType, keepaliveDelaySeconds);
+ }
+
+ /** Set the underpinned network */
+ public void setUnderpinnedNetwork(@NonNull Network underpinnedNetwork) {
+ mImpl.setUnderpinnedNetwork(underpinnedNetwork);
}
/** Forcibly terminate the IKE Session */
diff --git a/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java b/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java
index 857c86de57ca..a48c9fcd4181 100644
--- a/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java
+++ b/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java
@@ -99,7 +99,7 @@ import java.util.concurrent.Executor;
public class VpnIkev2Utils {
private static final String TAG = VpnIkev2Utils.class.getSimpleName();
- static IkeSessionParams buildIkeSessionParams(
+ static IkeSessionParams.Builder makeIkeSessionParamsBuilder(
@NonNull Context context, @NonNull Ikev2VpnProfile profile, @NonNull Network network) {
final IkeIdentification localId = parseIkeIdentification(profile.getUserIdentity());
final IkeIdentification remoteId = parseIkeIdentification(profile.getServerAddr());
@@ -117,7 +117,7 @@ public class VpnIkev2Utils {
ikeOptionsBuilder.addSaProposal(ikeProposal);
}
- return ikeOptionsBuilder.build();
+ return ikeOptionsBuilder;
}
static ChildSessionParams buildChildSessionParams(List<String> allowedAlgorithms) {
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 850f6da7e35f..6eb465e1049e 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -24,6 +24,7 @@ import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE;
import static android.hardware.display.DisplayManager.EventsMask;
+import static android.hardware.display.DisplayManager.HDR_OUTPUT_CONTROL_FLAG;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR;
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
@@ -38,8 +39,10 @@ import static android.hardware.display.DisplayManagerGlobal.DisplayEvent;
import static android.hardware.display.DisplayViewport.VIEWPORT_EXTERNAL;
import static android.hardware.display.DisplayViewport.VIEWPORT_INTERNAL;
import static android.hardware.display.DisplayViewport.VIEWPORT_VIRTUAL;
+import static android.hardware.display.HdrConversionMode.HDR_CONVERSION_UNSUPPORTED;
import static android.os.Process.FIRST_APPLICATION_UID;
import static android.os.Process.ROOT_UID;
+import static android.provider.DeviceConfig.NAMESPACE_DISPLAY_MANAGER;
import android.Manifest;
import android.annotation.NonNull;
@@ -137,6 +140,7 @@ import android.window.ScreenCapture;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.display.BrightnessSynchronizer;
+import com.android.internal.os.BackgroundThread;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.internal.util.IndentingPrintWriter;
@@ -232,6 +236,9 @@ public final class DisplayManagerService extends SystemService {
private static final int MSG_LOAD_BRIGHTNESS_CONFIGURATIONS = 6;
private static final int MSG_DELIVER_DISPLAY_EVENT_FRAME_RATE_OVERRIDE = 7;
private static final int MSG_DELIVER_DISPLAY_GROUP_EVENT = 8;
+ private static final int[] EMPTY_ARRAY = new int[0];
+ private static final HdrConversionMode HDR_CONVERSION_MODE_UNSUPPORTED = new HdrConversionMode(
+ HDR_CONVERSION_UNSUPPORTED);
private final Context mContext;
private final DisplayManagerHandler mHandler;
@@ -250,6 +257,10 @@ public final class DisplayManagerService extends SystemService {
@GuardedBy("mSyncRoot")
private boolean mAreUserDisabledHdrTypesAllowed = true;
+ // This value indicates whether or not HDR output control is enabled.
+ // It is read from DeviceConfig and is updated via a listener if the config changes.
+ private volatile boolean mIsHdrOutputControlEnabled;
+
// Display mode chosen by user.
private Display.Mode mUserPreferredMode;
// HDR conversion mode chosen by user
@@ -466,6 +477,8 @@ public final class DisplayManagerService extends SystemService {
private boolean mIsDocked;
private boolean mIsDreaming;
+ private boolean mBootCompleted = false;
+
private final BroadcastReceiver mIdleModeReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -602,6 +615,12 @@ public final class DisplayManagerService extends SystemService {
}
}
} else if (phase == PHASE_BOOT_COMPLETED) {
+ synchronized (mSyncRoot) {
+ mBootCompleted = true;
+ for (int i = 0; i < mDisplayPowerControllers.size(); i++) {
+ mDisplayPowerControllers.valueAt(i).onBootCompleted();
+ }
+ }
mDisplayModeDirector.onBootCompleted();
mLogicalDisplayMapper.onBootCompleted();
}
@@ -666,6 +685,11 @@ public final class DisplayManagerService extends SystemService {
synchronized (mSyncRoot) {
mSafeMode = safeMode;
mSystemReady = true;
+ mIsHdrOutputControlEnabled = isDeviceConfigHdrOutputControlEnabled();
+ DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_DISPLAY_MANAGER,
+ BackgroundThread.getExecutor(),
+ properties -> mIsHdrOutputControlEnabled =
+ isDeviceConfigHdrOutputControlEnabled());
// Just in case the top inset changed before the system was ready. At this point, any
// relevant configuration should be in place.
recordTopInsetLocked(mLogicalDisplayMapper.getDisplayLocked(Display.DEFAULT_DISPLAY));
@@ -673,7 +697,9 @@ public final class DisplayManagerService extends SystemService {
updateSettingsLocked();
updateUserDisabledHdrTypesFromSettingsLocked();
updateUserPreferredDisplayModeSettingsLocked();
- updateHdrConversionModeSettingsLocked();
+ if (mIsHdrOutputControlEnabled) {
+ updateHdrConversionModeSettingsLocked();
+ }
}
mDisplayModeDirector.setDesiredDisplayModeSpecsListener(
@@ -694,6 +720,12 @@ public final class DisplayManagerService extends SystemService {
mContext.registerReceiver(mIdleModeReceiver, filter);
}
+ private boolean isDeviceConfigHdrOutputControlEnabled() {
+ return DeviceConfig.getBoolean(NAMESPACE_DISPLAY_MANAGER,
+ HDR_OUTPUT_CONTROL_FLAG,
+ true);
+ }
+
@VisibleForTesting
Handler getDisplayHandler() {
return mHandler;
@@ -2109,7 +2141,7 @@ public final class DisplayManagerService extends SystemService {
private HdrConversionMode getHdrConversionModeSettingInternal() {
if (!mInjector.getHdrOutputConversionSupport()) {
- return new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_UNSUPPORTED);
+ return HDR_CONVERSION_MODE_UNSUPPORTED;
}
synchronized (mSyncRoot) {
if (mHdrConversionMode != null) {
@@ -2121,7 +2153,7 @@ public final class DisplayManagerService extends SystemService {
private HdrConversionMode getHdrConversionModeInternal() {
if (!mInjector.getHdrOutputConversionSupport()) {
- return new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_UNSUPPORTED);
+ return HDR_CONVERSION_MODE_UNSUPPORTED;
}
HdrConversionMode mode;
synchronized (mSyncRoot) {
@@ -2998,12 +3030,12 @@ public final class DisplayManagerService extends SystemService {
displayPowerController = new DisplayPowerController2(
mContext, /* injector= */ null, mDisplayPowerCallbacks, mPowerHandler,
mSensorManager, mDisplayBlanker, display, mBrightnessTracker, brightnessSetting,
- () -> handleBrightnessChange(display), hbmMetadata);
+ () -> handleBrightnessChange(display), hbmMetadata, mBootCompleted);
} else {
displayPowerController = new DisplayPowerController(
mContext, /* injector= */ null, mDisplayPowerCallbacks, mPowerHandler,
mSensorManager, mDisplayBlanker, display, mBrightnessTracker, brightnessSetting,
- () -> handleBrightnessChange(display), hbmMetadata);
+ () -> handleBrightnessChange(display), hbmMetadata, mBootCompleted);
}
mDisplayPowerControllers.append(display.getDisplayIdLocked(), displayPowerController);
}
@@ -3940,6 +3972,9 @@ public final class DisplayManagerService extends SystemService {
@Override // Binder call
public void setHdrConversionMode(HdrConversionMode hdrConversionMode) {
+ if (!mIsHdrOutputControlEnabled) {
+ return;
+ }
mContext.enforceCallingOrSelfPermission(
Manifest.permission.MODIFY_HDR_CONVERSION_MODE,
"Permission required to set the HDR conversion mode.");
@@ -3953,6 +3988,9 @@ public final class DisplayManagerService extends SystemService {
@Override // Binder call
public HdrConversionMode getHdrConversionModeSetting() {
+ if (!mIsHdrOutputControlEnabled) {
+ return HDR_CONVERSION_MODE_UNSUPPORTED;
+ }
final long token = Binder.clearCallingIdentity();
try {
return getHdrConversionModeSettingInternal();
@@ -3963,6 +4001,9 @@ public final class DisplayManagerService extends SystemService {
@Override // Binder call
public HdrConversionMode getHdrConversionMode() {
+ if (!mIsHdrOutputControlEnabled) {
+ return HDR_CONVERSION_MODE_UNSUPPORTED;
+ }
final long token = Binder.clearCallingIdentity();
try {
return getHdrConversionModeInternal();
@@ -3974,6 +4015,9 @@ public final class DisplayManagerService extends SystemService {
@Display.HdrCapabilities.HdrType
@Override // Binder call
public int[] getSupportedHdrOutputTypes() {
+ if (!mIsHdrOutputControlEnabled) {
+ return EMPTY_ARRAY;
+ }
final long token = Binder.clearCallingIdentity();
try {
return getSupportedHdrOutputTypesInternal();
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index d26968a942d0..31f5ab7dfe98 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -1352,6 +1352,8 @@ public class DisplayModeDirector {
return "PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE";
case PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE:
return "PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE";
+ case PRIORITY_LAYOUT_LIMITED_FRAME_RATE:
+ return "PRIORITY_LAYOUT_LIMITED_FRAME_RATE";
default:
return Integer.toString(priority);
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 82e6e308cab3..d4877eb4973d 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -139,6 +139,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
private static final int MSG_BRIGHTNESS_RAMP_DONE = 12;
private static final int MSG_STATSD_HBM_BRIGHTNESS = 13;
private static final int MSG_SWITCH_USER = 14;
+ private static final int MSG_BOOT_COMPLETED = 15;
private static final int PROXIMITY_UNKNOWN = -1;
private static final int PROXIMITY_NEGATIVE = 0;
@@ -518,6 +519,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
private final SparseArray<DisplayPowerControllerInterface> mDisplayBrightnessFollowers =
new SparseArray<>();
+ private boolean mBootCompleted;
+
/**
* Creates the display power controller.
*/
@@ -525,7 +528,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
DisplayPowerCallbacks callbacks, Handler handler,
SensorManager sensorManager, DisplayBlanker blanker, LogicalDisplay logicalDisplay,
BrightnessTracker brightnessTracker, BrightnessSetting brightnessSetting,
- Runnable onBrightnessChangeRunnable, HighBrightnessModeMetadata hbmMetadata) {
+ Runnable onBrightnessChangeRunnable, HighBrightnessModeMetadata hbmMetadata,
+ boolean bootCompleted) {
mInjector = injector != null ? injector : new Injector();
mClock = mInjector.getClock();
@@ -662,6 +666,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mTemporaryAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
mPendingAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
+ mBootCompleted = bootCompleted;
}
private void applyReduceBrightColorsSplineAdjustment() {
@@ -1188,17 +1193,15 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
loadScreenOffBrightnessSensor();
int[] sensorValueToLux = mDisplayDeviceConfig.getScreenOffBrightnessSensorValueToLux();
- // TODO (b/265793751): Don't instantiate ScreenOffBrightnessSensorController if this is
- // a complementary display
if (mScreenOffBrightnessSensor != null && sensorValueToLux != null) {
- mScreenOffBrightnessSensorController = new ScreenOffBrightnessSensorController(
- mSensorManager,
- mScreenOffBrightnessSensor,
- mHandler,
- SystemClock::uptimeMillis,
- sensorValueToLux,
- mInteractiveModeBrightnessMapper
- );
+ mScreenOffBrightnessSensorController =
+ mInjector.getScreenOffBrightnessSensorController(
+ mSensorManager,
+ mScreenOffBrightnessSensor,
+ mHandler,
+ SystemClock::uptimeMillis,
+ sensorValueToLux,
+ mInteractiveModeBrightnessMapper);
}
} else {
mUseSoftwareAutoBrightnessConfig = false;
@@ -1390,8 +1393,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
if (mScreenOffBrightnessSensorController != null) {
mScreenOffBrightnessSensorController.setLightSensorEnabled(mUseAutoBrightness
- && (state == Display.STATE_OFF || (state == Display.STATE_DOZE
- && !mAllowAutoBrightnessWhileDozingConfig)));
+ && mIsEnabled && (state == Display.STATE_OFF || (state == Display.STATE_DOZE
+ && !mAllowAutoBrightnessWhileDozingConfig))
+ && mLeadDisplayId == Layout.NO_LEAD_DISPLAY);
}
boolean skipRampBecauseOfProximityChangeToNegative = false;
@@ -1448,7 +1452,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Initialize things the first time the power state is changed.
if (mustInitialize) {
- initialize(state);
+ initialize(readyToUpdateDisplayState() ? state : Display.STATE_UNKNOWN);
}
// Animate the screen state change unless already animating.
@@ -2154,7 +2158,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
}
- if (!reportOnly && mPowerState.getScreenState() != state) {
+ if (!reportOnly && mPowerState.getScreenState() != state
+ && readyToUpdateDisplayState()) {
Trace.traceCounter(Trace.TRACE_TAG_POWER, "ScreenState", state);
// TODO(b/153319140) remove when we can get this from the above trace invocation
SystemProperties.set("debug.tracing.screen_state", String.valueOf(state));
@@ -2538,11 +2543,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mContext.getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS_MODE,
Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT);
- mHandler.post(() -> {
+ mHandler.postAtTime(() -> {
mUseAutoBrightness = screenBrightnessModeSetting
== Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
updatePowerState();
- });
+ }, mClock.uptimeMillis());
}
private float getAutoBrightnessAdjustmentSetting() {
@@ -2567,6 +2572,12 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
mBrightnessSetting.setBrightness(brightnessValue);
}
+ @Override
+ public void onBootCompleted() {
+ Message msg = mHandler.obtainMessage(MSG_BOOT_COMPLETED);
+ mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
+ }
+
private void updateScreenBrightnessSetting(float brightnessValue) {
if (!isValidBrightnessValue(brightnessValue)
|| brightnessValue == mCurrentScreenBrightnessSetting) {
@@ -2712,6 +2723,17 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
};
+ /**
+ * Indicates whether the display state is ready to update. If this is the default display, we
+ * want to update it right away so that we can draw the boot animation on it. If it is not
+ * the default display, drawing the boot animation on it would look incorrect, so we need
+ * to wait until boot is completed.
+ * @return True if the display state is ready to update
+ */
+ private boolean readyToUpdateDisplayState() {
+ return mDisplayId == Display.DEFAULT_DISPLAY || mBootCompleted;
+ }
+
@Override
public void dump(final PrintWriter pw) {
synchronized (mLock) {
@@ -3235,6 +3257,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
case MSG_SWITCH_USER:
handleOnSwitchUser(msg.arg1);
break;
+
+ case MSG_BOOT_COMPLETED:
+ mBootCompleted = true;
+ updatePowerState();
+ break;
}
}
}
@@ -3418,6 +3445,23 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
darkeningThresholdLevels, minDarkeningThreshold, minBrighteningThreshold,
potentialOldBrightnessRange);
}
+
+ ScreenOffBrightnessSensorController getScreenOffBrightnessSensorController(
+ SensorManager sensorManager,
+ Sensor lightSensor,
+ Handler handler,
+ ScreenOffBrightnessSensorController.Clock clock,
+ int[] sensorValueToLux,
+ BrightnessMappingStrategy brightnessMapper) {
+ return new ScreenOffBrightnessSensorController(
+ sensorManager,
+ lightSensor,
+ handler,
+ clock,
+ sensorValueToLux,
+ brightnessMapper
+ );
+ }
}
static class CachedBrightnessInfo {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController2.java b/services/core/java/com/android/server/display/DisplayPowerController2.java
index 0861a37247c4..a92877796a8a 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController2.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController2.java
@@ -137,6 +137,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
private static final int MSG_BRIGHTNESS_RAMP_DONE = 10;
private static final int MSG_STATSD_HBM_BRIGHTNESS = 11;
private static final int MSG_SWITCH_USER = 12;
+ private static final int MSG_BOOT_COMPLETED = 13;
private static final int BRIGHTNESS_CHANGE_STATSD_REPORT_INTERVAL_MS = 500;
@@ -425,6 +426,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
private SparseArray<DisplayPowerControllerInterface> mDisplayBrightnessFollowers =
new SparseArray();
+ private boolean mBootCompleted;
+
/**
* Creates the display power controller.
*/
@@ -432,7 +435,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
DisplayPowerCallbacks callbacks, Handler handler,
SensorManager sensorManager, DisplayBlanker blanker, LogicalDisplay logicalDisplay,
BrightnessTracker brightnessTracker, BrightnessSetting brightnessSetting,
- Runnable onBrightnessChangeRunnable, HighBrightnessModeMetadata hbmMetadata) {
+ Runnable onBrightnessChangeRunnable, HighBrightnessModeMetadata hbmMetadata,
+ boolean bootCompleted) {
mInjector = injector != null ? injector : new Injector();
mClock = mInjector.getClock();
@@ -555,6 +559,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
mTemporaryAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
mPendingAutoBrightnessAdjustment = PowerManager.BRIGHTNESS_INVALID_FLOAT;
+ mBootCompleted = bootCompleted;
}
private void applyReduceBrightColorsSplineAdjustment() {
@@ -1025,17 +1030,15 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
loadScreenOffBrightnessSensor();
int[] sensorValueToLux = mDisplayDeviceConfig.getScreenOffBrightnessSensorValueToLux();
- // TODO (b/265793751): Don't instantiate ScreenOffBrightnessSensorController if this is
- // a complementary display
if (mScreenOffBrightnessSensor != null && sensorValueToLux != null) {
- mScreenOffBrightnessSensorController = new ScreenOffBrightnessSensorController(
- mSensorManager,
- mScreenOffBrightnessSensor,
- mHandler,
- SystemClock::uptimeMillis,
- sensorValueToLux,
- mInteractiveModeBrightnessMapper
- );
+ mScreenOffBrightnessSensorController =
+ mInjector.getScreenOffBrightnessSensorController(
+ mSensorManager,
+ mScreenOffBrightnessSensor,
+ mHandler,
+ SystemClock::uptimeMillis,
+ sensorValueToLux,
+ mInteractiveModeBrightnessMapper);
}
} else {
mUseSoftwareAutoBrightnessConfig = false;
@@ -1184,13 +1187,14 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
if (mScreenOffBrightnessSensorController != null) {
mScreenOffBrightnessSensorController.setLightSensorEnabled(mUseAutoBrightness
- && (state == Display.STATE_OFF || (state == Display.STATE_DOZE
- && !mDisplayBrightnessController.isAllowAutoBrightnessWhileDozingConfig())));
+ && mIsEnabled && (state == Display.STATE_OFF || (state == Display.STATE_DOZE
+ && !mDisplayBrightnessController.isAllowAutoBrightnessWhileDozingConfig()))
+ && mLeadDisplayId == Layout.NO_LEAD_DISPLAY);
}
// Initialize things the first time the power state is changed.
if (mustInitialize) {
- initialize(state);
+ initialize(readyToUpdateDisplayState() ? state : Display.STATE_UNKNOWN);
}
// Animate the screen state change unless already animating.
@@ -1720,6 +1724,12 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
}
}
+ @Override
+ public void onBootCompleted() {
+ Message msg = mHandler.obtainMessage(MSG_BOOT_COMPLETED);
+ mHandler.sendMessageAtTime(msg, mClock.uptimeMillis());
+ }
+
private boolean saveBrightnessInfo(float brightness) {
return saveBrightnessInfo(brightness, brightness);
}
@@ -1861,7 +1871,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
}
}
- if (!reportOnly && mPowerState.getScreenState() != state) {
+ if (!reportOnly && mPowerState.getScreenState() != state
+ && readyToUpdateDisplayState()) {
Trace.traceCounter(Trace.TRACE_TAG_POWER, "ScreenState", state);
// TODO(b/153319140) remove when we can get this from the above trace invocation
SystemProperties.set("debug.tracing.screen_state", String.valueOf(state));
@@ -2138,11 +2149,11 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
mContext.getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS_MODE,
Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT);
- mHandler.post(() -> {
+ mHandler.postAtTime(() -> {
mUseAutoBrightness = screenBrightnessModeSetting
== Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
updatePowerState();
- });
+ }, mClock.uptimeMillis());
}
private float getAutoBrightnessAdjustmentSetting() {
@@ -2519,6 +2530,17 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
}
}
+ /**
+ * Indicates whether the display state is ready to update. If this is the default display, we
+ * want to update it right away so that we can draw the boot animation on it. If it is not
+ * the default display, drawing the boot animation on it would look incorrect, so we need
+ * to wait until boot is completed.
+ * @return True if the display state is ready to update
+ */
+ private boolean readyToUpdateDisplayState() {
+ return mDisplayId == Display.DEFAULT_DISPLAY || mBootCompleted;
+ }
+
// Return bucket index of range_[left]_[right] where
// left <= nits < right
private int nitsToRangeIndex(float nits) {
@@ -2738,6 +2760,11 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
case MSG_SWITCH_USER:
handleOnSwitchUser(msg.arg1);
break;
+
+ case MSG_BOOT_COMPLETED:
+ mBootCompleted = true;
+ updatePowerState();
+ break;
}
}
}
@@ -2896,6 +2923,23 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
darkeningThresholdLevels, minDarkeningThreshold, minBrighteningThreshold,
potentialOldBrightnessRange);
}
+
+ ScreenOffBrightnessSensorController getScreenOffBrightnessSensorController(
+ SensorManager sensorManager,
+ Sensor lightSensor,
+ Handler handler,
+ ScreenOffBrightnessSensorController.Clock clock,
+ int[] sensorValueToLux,
+ BrightnessMappingStrategy brightnessMapper) {
+ return new ScreenOffBrightnessSensorController(
+ sensorManager,
+ lightSensor,
+ handler,
+ clock,
+ sensorValueToLux,
+ brightnessMapper
+ );
+ }
}
static class CachedBrightnessInfo {
diff --git a/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java b/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java
index 0bc8154b610c..73edb970ff95 100644
--- a/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java
+++ b/services/core/java/com/android/server/display/DisplayPowerControllerInterface.java
@@ -206,4 +206,9 @@ public interface DisplayPowerControllerInterface {
* @param follower The DPC to remove from the followers list
*/
void removeDisplayBrightnessFollower(DisplayPowerControllerInterface follower);
+
+ /**
+ * Indicate that boot has been completed and the screen is ready to update.
+ */
+ void onBootCompleted();
}
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 2104ee3e50cb..fc90db66c1cb 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -332,6 +332,19 @@ final class LogicalDisplay {
}
/**
+ * Updates layoutLimitedRefreshRate
+ *
+ * @param layoutLimitedRefreshRate refresh rate limited by layout or null.
+ */
+ public void updateLayoutLimitedRefreshRateLocked(
+ @Nullable SurfaceControl.RefreshRateRange layoutLimitedRefreshRate) {
+ if (!Objects.equals(layoutLimitedRefreshRate, mBaseDisplayInfo.layoutLimitedRefreshRate)) {
+ mBaseDisplayInfo.layoutLimitedRefreshRate = layoutLimitedRefreshRate;
+ mInfo.set(null);
+ }
+ }
+
+ /**
* Updates the state of the logical display based on the available display devices.
* The logical display might become invalid if it is attached to a display device
* that no longer exists.
diff --git a/services/core/java/com/android/server/display/LogicalDisplayMapper.java b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
index 80e76b63ad35..2ac7d9d1a73e 100644
--- a/services/core/java/com/android/server/display/LogicalDisplayMapper.java
+++ b/services/core/java/com/android/server/display/LogicalDisplayMapper.java
@@ -1016,7 +1016,12 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
newDisplay.setDevicePositionLocked(displayLayout.getPosition());
newDisplay.setLeadDisplayLocked(displayLayout.getLeadDisplayId());
- setLayoutLimitedRefreshRate(newDisplay, device, displayLayout);
+ newDisplay.updateLayoutLimitedRefreshRateLocked(
+ device.getDisplayDeviceConfig().getRefreshRange(
+ displayLayout.getRefreshRateZoneId()
+ )
+ );
+
setEnabledLocked(newDisplay, displayLayout.isEnabled());
newDisplay.setBrightnessThrottlingDataIdLocked(
displayLayout.getBrightnessThrottlingMapId() == null
@@ -1027,13 +1032,6 @@ class LogicalDisplayMapper implements DisplayDeviceRepository.Listener {
}
}
- private void setLayoutLimitedRefreshRate(@NonNull LogicalDisplay logicalDisplay,
- @NonNull DisplayDevice device, @NonNull Layout.Display display) {
- DisplayDeviceConfig config = device.getDisplayDeviceConfig();
- DisplayInfo info = logicalDisplay.getDisplayInfoLocked();
- info.layoutLimitedRefreshRate = config.getRefreshRange(display.getRefreshRateZoneId());
- }
-
/**
* Creates a new logical display for the specified device and display Id and adds it to the list
* of logical displays.
diff --git a/services/core/java/com/android/server/hdmi/HdmiEarcController.java b/services/core/java/com/android/server/hdmi/HdmiEarcController.java
index 2bb9ffb61eed..46a8f039584b 100644
--- a/services/core/java/com/android/server/hdmi/HdmiEarcController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiEarcController.java
@@ -35,40 +35,40 @@ final class HdmiEarcController {
private final HdmiControlService mService;
- private EArcNativeWrapper mEArcNativeWrapperImpl;
+ private EarcNativeWrapper mEarcNativeWrapperImpl;
- protected interface EArcNativeWrapper {
+ protected interface EarcNativeWrapper {
boolean nativeInit();
- void nativeSetEArcEnabled(boolean enabled);
- boolean nativeIsEArcEnabled();
+ void nativeSetEarcEnabled(boolean enabled);
+ boolean nativeIsEarcEnabled();
void nativeSetCallback(EarcAidlCallback callback);
byte nativeGetState(int portId);
byte[] nativeGetLastReportedAudioCapabilities(int portId);
}
- private static final class EArcNativeWrapperImpl implements EArcNativeWrapper,
+ private static final class EarcNativeWrapperImpl implements EarcNativeWrapper,
IBinder.DeathRecipient {
- private IEArc mEArc;
- private EarcAidlCallback mEArcCallback;
+ private IEArc mEarc;
+ private EarcAidlCallback mEarcCallback;
@Override
public void binderDied() {
- mEArc.asBinder().unlinkToDeath(this, 0);
+ mEarc.asBinder().unlinkToDeath(this, 0);
connectToHal();
- if (mEArcCallback != null) {
- nativeSetCallback(mEArcCallback);
+ if (mEarcCallback != null) {
+ nativeSetCallback(mEarcCallback);
}
}
boolean connectToHal() {
- mEArc =
+ mEarc =
IEArc.Stub.asInterface(
ServiceManager.getService(IEArc.DESCRIPTOR + "/default"));
- if (mEArc == null) {
+ if (mEarc == null) {
return false;
}
try {
- mEArc.asBinder().linkToDeath(this, 0);
+ mEarc.asBinder().linkToDeath(this, 0);
} catch (RemoteException e) {
HdmiLogger.error("Couldn't link callback object: ", e);
}
@@ -81,9 +81,9 @@ final class HdmiEarcController {
}
@Override
- public void nativeSetEArcEnabled(boolean enabled) {
+ public void nativeSetEarcEnabled(boolean enabled) {
try {
- mEArc.setEArcEnabled(enabled);
+ mEarc.setEArcEnabled(enabled);
} catch (ServiceSpecificException sse) {
HdmiLogger.error(
"Could not set eARC enabled to " + enabled + ". Error: ", sse.errorCode);
@@ -93,9 +93,9 @@ final class HdmiEarcController {
}
@Override
- public boolean nativeIsEArcEnabled() {
+ public boolean nativeIsEarcEnabled() {
try {
- return mEArc.isEArcEnabled();
+ return mEarc.isEArcEnabled();
} catch (RemoteException re) {
HdmiLogger.error("Could not read if eARC is enabled. Exception: ", re);
return false;
@@ -104,9 +104,9 @@ final class HdmiEarcController {
@Override
public void nativeSetCallback(EarcAidlCallback callback) {
- mEArcCallback = callback;
+ mEarcCallback = callback;
try {
- mEArc.setCallback(callback);
+ mEarc.setCallback(callback);
} catch (RemoteException re) {
HdmiLogger.error("Could not set callback. Exception: ", re);
}
@@ -115,7 +115,7 @@ final class HdmiEarcController {
@Override
public byte nativeGetState(int portId) {
try {
- return mEArc.getState(portId);
+ return mEarc.getState(portId);
} catch (RemoteException re) {
HdmiLogger.error("Could not get eARC state. Exception: ", re);
return -1;
@@ -125,7 +125,7 @@ final class HdmiEarcController {
@Override
public byte[] nativeGetLastReportedAudioCapabilities(int portId) {
try {
- return mEArc.getLastReportedAudioCapabilities(portId);
+ return mEarc.getLastReportedAudioCapabilities(portId);
} catch (RemoteException re) {
HdmiLogger.error(
"Could not read last reported audio capabilities. Exception: ", re);
@@ -135,9 +135,9 @@ final class HdmiEarcController {
}
// Private constructor. Use HdmiEarcController.create().
- private HdmiEarcController(HdmiControlService service, EArcNativeWrapper nativeWrapper) {
+ private HdmiEarcController(HdmiControlService service, EarcNativeWrapper nativeWrapper) {
mService = service;
- mEArcNativeWrapperImpl = nativeWrapper;
+ mEarcNativeWrapperImpl = nativeWrapper;
}
/**
@@ -151,14 +151,14 @@ final class HdmiEarcController {
* returns {@code null}.
*/
static HdmiEarcController create(HdmiControlService service) {
- return createWithNativeWrapper(service, new EArcNativeWrapperImpl());
+ return createWithNativeWrapper(service, new EarcNativeWrapperImpl());
}
/**
* A factory method with injection of native methods for testing.
*/
static HdmiEarcController createWithNativeWrapper(HdmiControlService service,
- EArcNativeWrapper nativeWrapper) {
+ EarcNativeWrapper nativeWrapper) {
HdmiEarcController controller = new HdmiEarcController(service, nativeWrapper);
if (!controller.init(nativeWrapper)) {
HdmiLogger.warning("Could not connect to eARC AIDL HAL.");
@@ -167,10 +167,10 @@ final class HdmiEarcController {
return controller;
}
- private boolean init(EArcNativeWrapper nativeWrapper) {
+ private boolean init(EarcNativeWrapper nativeWrapper) {
if (nativeWrapper.nativeInit()) {
mControlHandler = new Handler(mService.getServiceLooper());
- mEArcNativeWrapperImpl.nativeSetCallback(new EarcAidlCallback());
+ mEarcNativeWrapperImpl.nativeSetCallback(new EarcAidlCallback());
return true;
}
return false;
@@ -194,7 +194,7 @@ final class HdmiEarcController {
@HdmiAnnotations.ServiceThreadOnly
void setEarcEnabled(boolean enabled) {
assertRunOnServiceThread();
- mEArcNativeWrapperImpl.nativeSetEArcEnabled(enabled);
+ mEarcNativeWrapperImpl.nativeSetEarcEnabled(enabled);
}
/**
@@ -205,7 +205,7 @@ final class HdmiEarcController {
@HdmiAnnotations.ServiceThreadOnly
@Constants.EarcStatus
int getState(int portId) {
- return mEArcNativeWrapperImpl.nativeGetState(portId);
+ return mEarcNativeWrapperImpl.nativeGetState(portId);
}
/**
@@ -215,7 +215,7 @@ final class HdmiEarcController {
*/
@HdmiAnnotations.ServiceThreadOnly
byte[] getLastReportedCaps(int portId) {
- return mEArcNativeWrapperImpl.nativeGetLastReportedAudioCapabilities(portId);
+ return mEarcNativeWrapperImpl.nativeGetLastReportedAudioCapabilities(portId);
}
final class EarcAidlCallback extends IEArcCallback.Stub {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index c7e4cd22fc08..f5875abe17e6 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -4549,19 +4549,23 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
@BinderThread
private void applyImeVisibility(IBinder token, IBinder windowToken, boolean setVisible,
@Nullable ImeTracker.Token statsToken) {
- Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.applyImeVisibility");
- synchronized (ImfLock.class) {
- if (!calledWithValidTokenLocked(token)) {
- ImeTracker.forLogging().onFailed(statsToken,
- ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
- return;
+ try {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.applyImeVisibility");
+ synchronized (ImfLock.class) {
+ if (!calledWithValidTokenLocked(token)) {
+ ImeTracker.forLogging().onFailed(statsToken,
+ ImeTracker.PHASE_SERVER_APPLY_IME_VISIBILITY);
+ return;
+ }
+ final IBinder requestToken = mVisibilityStateComputer.getWindowTokenFrom(
+ windowToken);
+ mVisibilityApplier.applyImeVisibility(requestToken, statsToken,
+ setVisible ? ImeVisibilityStateComputer.STATE_SHOW_IME
+ : ImeVisibilityStateComputer.STATE_HIDE_IME);
}
- final IBinder requestToken = mVisibilityStateComputer.getWindowTokenFrom(windowToken);
- mVisibilityApplier.applyImeVisibility(requestToken, statsToken,
- setVisible ? ImeVisibilityStateComputer.STATE_SHOW_IME
- : ImeVisibilityStateComputer.STATE_HIDE_IME);
+ } finally {
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
- Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
@BinderThread
@@ -4632,39 +4636,45 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
@BinderThread
private void hideMySoftInput(@NonNull IBinder token, int flags,
@SoftInputShowHideReason int reason) {
- Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.hideMySoftInput");
- synchronized (ImfLock.class) {
- if (!calledWithValidTokenLocked(token)) {
- return;
- }
- final long ident = Binder.clearCallingIdentity();
- try {
- hideCurrentInputLocked(mLastImeTargetWindow, null /* statsToken */, flags,
- null /* resultReceiver */, reason);
- } finally {
- Binder.restoreCallingIdentity(ident);
+ try {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.hideMySoftInput");
+ synchronized (ImfLock.class) {
+ if (!calledWithValidTokenLocked(token)) {
+ return;
+ }
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ hideCurrentInputLocked(mLastImeTargetWindow, null /* statsToken */, flags,
+ null /* resultReceiver */, reason);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
+ } finally {
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
- Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
@BinderThread
private void showMySoftInput(@NonNull IBinder token, int flags) {
- Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.showMySoftInput");
- synchronized (ImfLock.class) {
- if (!calledWithValidTokenLocked(token)) {
- return;
- }
- final long ident = Binder.clearCallingIdentity();
- try {
- showCurrentInputLocked(mLastImeTargetWindow, null /* statsToken */, flags,
- null /* resultReceiver */,
- SoftInputShowHideReason.SHOW_SOFT_INPUT_FROM_IME);
- } finally {
- Binder.restoreCallingIdentity(ident);
+ try {
+ Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "IMMS.showMySoftInput");
+ synchronized (ImfLock.class) {
+ if (!calledWithValidTokenLocked(token)) {
+ return;
+ }
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ showCurrentInputLocked(mLastImeTargetWindow, null /* statsToken */, flags,
+ null /* resultReceiver */,
+ SoftInputShowHideReason.SHOW_SOFT_INPUT_FROM_IME);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
}
+ } finally {
+ Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
- Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
@VisibleForTesting
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index a01b2c1d9c6a..0d394570ab8e 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -17,6 +17,7 @@
package com.android.server.notification;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
+import static android.app.ActivityManagerInternal.ServiceNotificationPolicy.NOT_FOREGROUND_SERVICE;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.Notification.BubbleMetadata.FLAG_SUPPRESS_NOTIFICATION;
import static android.app.Notification.FLAG_AUTOGROUP_SUMMARY;
@@ -228,7 +229,6 @@ import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.VibrationEffect;
-import android.permission.PermissionCheckerManager;
import android.permission.PermissionManager;
import android.provider.DeviceConfig;
import android.provider.Settings;
@@ -6517,9 +6517,17 @@ public class NotificationManagerService extends SystemService {
checkRestrictedCategories(notification);
+ // Notifications passed to setForegroundService() have FLAG_FOREGROUND_SERVICE,
+ // but it's also possible that the app has called notify() with an update to an
+ // FGS notification that hasn't yet been displayed. Make sure we check for any
+ // FGS-related situation up front, outside of any locks so it's safe to call into
+ // the Activity Manager.
+ final ServiceNotificationPolicy policy = mAmi.applyForegroundServiceNotification(
+ notification, tag, id, pkg, userId);
+
// Fix the notification as best we can.
try {
- fixNotification(notification, pkg, tag, id, userId, notificationUid);
+ fixNotification(notification, pkg, tag, id, userId, notificationUid, policy);
} catch (Exception e) {
if (notification.isForegroundService()) {
throw new SecurityException("Invalid FGS notification", e);
@@ -6528,13 +6536,7 @@ public class NotificationManagerService extends SystemService {
return;
}
- // Notifications passed to setForegroundService() have FLAG_FOREGROUND_SERVICE,
- // but it's also possible that the app has called notify() with an update to an
- // FGS notification that hasn't yet been displayed. Make sure we check for any
- // FGS-related situation up front, outside of any locks so it's safe to call into
- // the Activity Manager.
- final ServiceNotificationPolicy policy = mAmi.applyForegroundServiceNotification(
- notification, tag, id, pkg, userId);
+
if (policy == ServiceNotificationPolicy.UPDATE_ONLY) {
// Proceed if the notification is already showing/known, otherwise ignore
// because the service lifecycle logic has retained responsibility for its
@@ -6707,14 +6709,17 @@ public class NotificationManagerService extends SystemService {
@VisibleForTesting
protected void fixNotification(Notification notification, String pkg, String tag, int id,
- @UserIdInt int userId, int notificationUid) throws NameNotFoundException,
- RemoteException {
-
+ @UserIdInt int userId, int notificationUid, ServiceNotificationPolicy fgsPolicy)
+ throws NameNotFoundException, RemoteException {
final ApplicationInfo ai = mPackageManagerClient.getApplicationInfoAsUser(
pkg, PackageManager.MATCH_DEBUG_TRIAGED_MISSING,
(userId == UserHandle.USER_ALL) ? USER_SYSTEM : userId);
Notification.addFieldsFromContext(ai, notification);
+ if (notification.isForegroundService() && fgsPolicy == NOT_FOREGROUND_SERVICE) {
+ notification.flags &= ~FLAG_FOREGROUND_SERVICE;
+ }
+
// Only notifications that can be non-dismissible can have the flag FLAG_NO_DISMISS
if (mFlagResolver.isEnabled(ALLOW_DISMISS_ONGOING)) {
if (((notification.flags & FLAG_ONGOING_EVENT) > 0)
@@ -6768,7 +6773,7 @@ public class NotificationManagerService extends SystemService {
final int permissionResult = mPermissionManager.checkPermissionForDataDelivery(
Manifest.permission.USE_FULL_SCREEN_INTENT, source, /* message= */ null);
- if (permissionResult != PermissionCheckerManager.PERMISSION_GRANTED) {
+ if (permissionResult != PermissionManager.PERMISSION_GRANTED) {
makeStickyHun(notification);
}
@@ -6857,11 +6862,7 @@ public class NotificationManagerService extends SystemService {
* A notification should be dismissible, unless it's exempted for some reason.
*/
private boolean canBeNonDismissible(ApplicationInfo ai, Notification notification) {
- // Check if the app is on the system partition, or an update to an app on the system
- // partition.
- boolean isSystemAppExempt = (ai.flags
- & (ApplicationInfo.FLAG_UPDATED_SYSTEM_APP | ApplicationInfo.FLAG_SYSTEM)) > 0;
- return isSystemAppExempt || notification.isMediaNotification() || isEnterpriseExempted(ai);
+ return notification.isMediaNotification() || isEnterpriseExempted(ai);
}
private boolean isEnterpriseExempted(ApplicationInfo ai) {
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 69ea55969b03..c63cdddc8560 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -22,6 +22,7 @@ import static android.app.NotificationChannel.USER_LOCKED_IMPORTANCE;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_MAX;
import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
import static android.util.StatsLog.ANNOTATION_ID_IS_UID;
@@ -905,6 +906,9 @@ public class PreferencesHelper implements RankingConfig {
Objects.requireNonNull(channel);
Objects.requireNonNull(channel.getId());
Preconditions.checkArgument(!TextUtils.isEmpty(channel.getName()));
+ Preconditions.checkArgument(channel.getImportance() >= IMPORTANCE_NONE
+ && channel.getImportance() <= IMPORTANCE_MAX, "Invalid importance level");
+
boolean needsPolicyFileChange = false, wasUndeleted = false, needsDndChange = false;
synchronized (mPackagePreferences) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
@@ -993,11 +997,6 @@ public class PreferencesHelper implements RankingConfig {
needsPolicyFileChange = true;
- if (channel.getImportance() < IMPORTANCE_NONE
- || channel.getImportance() > NotificationManager.IMPORTANCE_MAX) {
- throw new IllegalArgumentException("Invalid importance level");
- }
-
// Reset fields that apps aren't allowed to set.
if (fromTargetApp && !hasDndAccess) {
channel.setBypassDnd(r.priority == Notification.PRIORITY_MAX);
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index 58a609e3e370..5984360a534c 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -65,6 +65,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
+import android.app.admin.DevicePolicyManagerInternal;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -2190,6 +2191,11 @@ public class ComputerEngine implements Computer {
&& UserHandle.getAppId(uid) == pkg.getUid();
}
+ private boolean isCallerFromManagedUserOrProfile(@UserIdInt int userId) {
+ final var dpmi = mInjector.getLocalService(DevicePolicyManagerInternal.class);
+ return dpmi != null && dpmi.isUserOrganizationManaged(userId);
+ }
+
public final boolean isComponentVisibleToInstantApp(@Nullable ComponentName component) {
if (isComponentVisibleToInstantApp(component, TYPE_ACTIVITY)) {
return true;
@@ -5002,8 +5008,15 @@ public class ComputerEngine implements Computer {
updateOwnerPackageName = installSource.mUpdateOwnerPackageName;
if (updateOwnerPackageName != null) {
final PackageStateInternal ps = mSettings.getPackage(updateOwnerPackageName);
+ final boolean isCallerSystemOrUpdateOwner = callingUid == Process.SYSTEM_UID
+ || isCallerSameApp(updateOwnerPackageName, callingUid);
+ // Except for package visibility filtering, we also hide update owner if the installer
+ // is in the managed user or profile. As we don't enforce the update ownership for the
+ // managed user and profile, knowing there's an update owner is meaningless in that
+ // user unless the installer is the owner.
if (ps == null
- || shouldFilterApplicationIncludingUninstalled(ps, callingUid, userId)) {
+ || shouldFilterApplicationIncludingUninstalled(ps, callingUid, userId)
+ || (!isCallerSystemOrUpdateOwner && isCallerFromManagedUserOrProfile(userId))) {
updateOwnerPackageName = null;
}
}
diff --git a/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java b/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java
index 84ea077a0687..9eb73aa6befc 100644
--- a/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java
+++ b/services/core/java/com/android/server/pm/DefaultCrossProfileIntentFiltersUtils.java
@@ -401,7 +401,7 @@ public class DefaultCrossProfileIntentFiltersUtils {
/*
Allowing view action from clone to parent profile to open any app-links or web links
*/
- private static final DefaultCrossProfileIntentFilter CLONE_TO_PARENT_VIEW_ACTION =
+ private static final DefaultCrossProfileIntentFilter CLONE_TO_PARENT_WEB_VIEW_ACTION =
new DefaultCrossProfileIntentFilter.Builder(
DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
/* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER
@@ -415,7 +415,7 @@ public class DefaultCrossProfileIntentFiltersUtils {
/*
Allowing view action from parent to clone profile to open any app-links or web links
*/
- private static final DefaultCrossProfileIntentFilter PARENT_TO_CLONE_VIEW_ACTION =
+ private static final DefaultCrossProfileIntentFilter PARENT_TO_CLONE_WEB_VIEW_ACTION =
new DefaultCrossProfileIntentFilter.Builder(
DefaultCrossProfileIntentFilter.Direction.TO_PROFILE,
/* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER
@@ -427,6 +427,21 @@ public class DefaultCrossProfileIntentFiltersUtils {
.build();
/*
+ Allowing view action from clone to parent profile to any data type e.g. pdf, including custom
+ content providers.
+ */
+ private static final DefaultCrossProfileIntentFilter CLONE_TO_PARENT_VIEW_ACTION =
+ new DefaultCrossProfileIntentFilter.Builder(
+ DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
+ /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER
+ // and FLAG_ALLOW_CHAINED_RESOLUTION set
+ /* letsPersonalDataIntoProfile= */ false)
+ .addAction(Intent.ACTION_VIEW)
+ .addDataType("*/*")
+ .build();
+
+
+ /*
Allowing pick,insert and edit action from clone to parent profile to open picker or contacts
insert/edit.
*/
@@ -441,7 +456,10 @@ public class DefaultCrossProfileIntentFiltersUtils {
.addAction(Intent.ACTION_EDIT)
.addAction(Intent.ACTION_INSERT)
.addAction(Intent.ACTION_INSERT_OR_EDIT)
+ .addAction(Intent.ACTION_OPEN_DOCUMENT)
.addDataType("*/*")
+ .addCategory(Intent.CATEGORY_DEFAULT)
+ .addCategory(Intent.CATEGORY_OPENABLE)
.build();
/*
@@ -458,19 +476,71 @@ public class DefaultCrossProfileIntentFiltersUtils {
.addAction(Intent.ACTION_EDIT)
.addAction(Intent.ACTION_INSERT)
.addAction(Intent.ACTION_INSERT_OR_EDIT)
+ .addAction(Intent.ACTION_OPEN_DOCUMENT)
.addDataType("*/*")
+ .addCategory(Intent.CATEGORY_DEFAULT)
+ .addCategory(Intent.CATEGORY_OPENABLE)
+ .build();
+
+ private static final DefaultCrossProfileIntentFilter PARENT_TO_CLONE_DIAL_DATA =
+ new DefaultCrossProfileIntentFilter.Builder(
+ DefaultCrossProfileIntentFilter.Direction.TO_PROFILE,
+ /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER
+ // and FLAG_ALLOW_CHAINED_RESOLUTION set
+ /* letsPersonalDataIntoProfile= */ false)
+ .addAction(Intent.ACTION_DIAL)
+ .addAction(Intent.ACTION_VIEW)
+ .addCategory(Intent.CATEGORY_DEFAULT)
+ .addCategory(Intent.CATEGORY_BROWSABLE)
+ .addDataScheme("tel")
+ .addDataScheme("sip")
+ .addDataScheme("voicemail")
+ .build();
+
+ private static final DefaultCrossProfileIntentFilter CLONE_TO_PARENT_DIAL_DATA =
+ new DefaultCrossProfileIntentFilter.Builder(
+ DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
+ /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER
+ // and FLAG_ALLOW_CHAINED_RESOLUTION set
+ /* letsPersonalDataIntoProfile= */ false)
+ .addAction(Intent.ACTION_DIAL)
+ .addAction(Intent.ACTION_VIEW)
+ .addCategory(Intent.CATEGORY_DEFAULT)
+ .addCategory(Intent.CATEGORY_BROWSABLE)
+ .addDataScheme("tel")
+ .addDataScheme("sip")
+ .addDataScheme("voicemail")
+ .build();
+
+ private static final DefaultCrossProfileIntentFilter CLONE_TO_PARENT_SMS_MMS =
+ new DefaultCrossProfileIntentFilter.Builder(
+ DefaultCrossProfileIntentFilter.Direction.TO_PARENT,
+ /* flags= */ 0x00000018, // 0x00000018 means FLAG_IS_PACKAGE_FOR_FILTER
+ // and FLAG_ALLOW_CHAINED_RESOLUTION set
+ /* letsPersonalDataIntoProfile= */ false)
+ .addAction(Intent.ACTION_VIEW)
+ .addAction(Intent.ACTION_SENDTO)
+ .addCategory(Intent.CATEGORY_DEFAULT)
+ .addCategory(Intent.CATEGORY_BROWSABLE)
+ .addDataScheme("sms")
+ .addDataScheme("smsto")
+ .addDataScheme("mms")
+ .addDataScheme("mmsto")
.build();
public static List<DefaultCrossProfileIntentFilter> getDefaultCloneProfileFilters() {
return Arrays.asList(
PARENT_TO_CLONE_SEND_ACTION,
- PARENT_TO_CLONE_VIEW_ACTION,
+ PARENT_TO_CLONE_WEB_VIEW_ACTION,
PARENT_TO_CLONE_PICK_INSERT_ACTION,
+ PARENT_TO_CLONE_DIAL_DATA,
CLONE_TO_PARENT_MEDIA_CAPTURE,
CLONE_TO_PARENT_SEND_ACTION,
+ CLONE_TO_PARENT_WEB_VIEW_ACTION,
CLONE_TO_PARENT_VIEW_ACTION,
- CLONE_TO_PARENT_PICK_INSERT_ACTION
-
+ CLONE_TO_PARENT_PICK_INSERT_ACTION,
+ CLONE_TO_PARENT_DIAL_DATA,
+ CLONE_TO_PARENT_SMS_MMS
);
}
}
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 4b2be2ff500d..a868470b0042 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -102,6 +102,7 @@ import android.app.AppOpsManager;
import android.app.ApplicationExitInfo;
import android.app.ApplicationPackageManager;
import android.app.BroadcastOptions;
+import android.app.admin.DevicePolicyManagerInternal;
import android.app.backup.IBackupManager;
import android.content.ContentResolver;
import android.content.Context;
@@ -144,6 +145,7 @@ import android.provider.DeviceConfig;
import android.stats.storage.StorageEnums;
import android.system.ErrnoException;
import android.system.Os;
+import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.EventLog;
@@ -317,10 +319,16 @@ final class InstallPackageHelper {
InstallSource installSource = request.getInstallSource();
final boolean isApex = (scanFlags & SCAN_AS_APEX) != 0;
+ final boolean pkgAlreadyExists = oldPkgSetting != null;
+ final boolean isAllowUpdateOwnership = parsedPackage.isAllowUpdateOwnership();
+ final String oldUpdateOwner =
+ pkgAlreadyExists ? oldPkgSetting.getInstallSource().mUpdateOwnerPackageName : null;
final String updateOwnerFromSysconfig = isApex || !pkgSetting.isSystem() ? null
: mPm.mInjector.getSystemConfig().getSystemAppUpdateOwnerPackageName(
parsedPackage.getPackageName());
- // For new install (standard install), the installSource isn't null.
+ final boolean isUpdateOwnershipEnabled = oldUpdateOwner != null;
+
+ // For standard install (install via session), the installSource isn't null.
if (installSource != null) {
// If this is part of a standard install, set the initiating package name, else rely on
// previous device state.
@@ -334,39 +342,68 @@ final class InstallPackageHelper {
}
// Handle the update ownership enforcement for APK
- if (updateOwnerFromSysconfig != null) {
- // For system app, we always use the update owner from sysconfig if presented.
- installSource = installSource.setUpdateOwnerPackageName(updateOwnerFromSysconfig);
- } else if (!parsedPackage.isAllowUpdateOwnership()) {
+ if (!isAllowUpdateOwnership) {
// If the app wants to opt-out of the update ownership enforcement via manifest,
// it overrides the installer's use of #setRequestUpdateOwnership.
installSource = installSource.setUpdateOwnerPackageName(null);
} else if (!isApex) {
- final boolean isUpdate = oldPkgSetting != null;
- final String oldUpdateOwner =
- isUpdate ? oldPkgSetting.getInstallSource().mUpdateOwnerPackageName : null;
- final boolean isUpdateOwnershipEnabled = oldUpdateOwner != null;
+ // User installer UID as "current" userId if present; otherwise, use the userId
+ // from InstallRequest.
+ final int userId = installSource.mInstallerPackageUid != Process.INVALID_UID
+ ? UserHandle.getUserId(installSource.mInstallerPackageUid)
+ : request.getUserId();
+ // Whether the parsedPackage is installed on the userId
+ // If the oldPkgSetting doesn't exist, this package isn't installed for all users.
+ final boolean isUpdate = pkgAlreadyExists && (userId >= UserHandle.USER_SYSTEM
+ // If userID >= 0, we could check via oldPkgSetting.getInstalled(userId).
+ ? oldPkgSetting.getInstalled(userId)
+ // When userId is -1 (USER_ALL) and it's not installed for any user,
+ // treat it as not installed.
+ : oldPkgSetting.getNotInstalledUserIds().length
+ <= (UserManager.isHeadlessSystemUserMode() ? 1 : 0));
final boolean isRequestUpdateOwnership = (request.getInstallFlags()
& PackageManager.INSTALL_REQUEST_UPDATE_OWNERSHIP) != 0;
-
- // Here we assign the update owner for the package, and the rules are:
- // -. If the installer doesn't request update ownership on initial installation,
- // keep the update owner as null.
- // -. If the installer doesn't want to be the owner to provide the subsequent
- // update (doesn't request to be the update owner), e.g., non-store installer
- // (file manager), ADB, or DO/PO, we should not update the owner.
- // -. Else, the installer requests update ownership on initial installation or
- // update, we use installSource.mUpdateOwnerPackageName as the update owner.
- if (!isRequestUpdateOwnership || (isUpdate && !isUpdateOwnershipEnabled)) {
- installSource = installSource.setUpdateOwnerPackageName(oldUpdateOwner);
+ final boolean isSameUpdateOwner =
+ TextUtils.equals(oldUpdateOwner, installSource.mInstallerPackageName);
+
+ // Here we handle the update owner for the package, and the rules are:
+ // -. Only enabling update ownership enforcement on initial installation if the
+ // installer has requested.
+ // -. Once the installer changes and users agree to proceed, clear the update
+ // owner (package state in other users are taken into account as well).
+ if (!isUpdate) {
+ if (!isRequestUpdateOwnership) {
+ installSource = installSource.setUpdateOwnerPackageName(null);
+ } else if ((!isUpdateOwnershipEnabled && pkgAlreadyExists)
+ || (isUpdateOwnershipEnabled && !isSameUpdateOwner)) {
+ installSource = installSource.setUpdateOwnerPackageName(null);
+ }
+ } else if (!isSameUpdateOwner || !isUpdateOwnershipEnabled) {
+ installSource = installSource.setUpdateOwnerPackageName(null);
}
}
pkgSetting.setInstallSource(installSource);
- // non-standard install (addForInit and install existing packages), installSource is null.
- } else if (updateOwnerFromSysconfig != null) {
- // For system app, we always use the update owner from sysconfig if presented.
- pkgSetting.setUpdateOwnerPackage(updateOwnerFromSysconfig);
+ // For non-standard install (addForInit), installSource is null.
+ } else if (pkgSetting.isSystem()) {
+ // We still honor the manifest attr if the system app wants to opt-out of it.
+ if (!isAllowUpdateOwnership) {
+ pkgSetting.setUpdateOwnerPackage(null);
+ } else {
+ final boolean isSameUpdateOwner = isUpdateOwnershipEnabled
+ && TextUtils.equals(oldUpdateOwner, updateOwnerFromSysconfig);
+
+ // Here we handle the update owner for the system package, and the rules are:
+ // -. We use the update owner from sysconfig as the initial value.
+ // -. Once an app becomes to system app later via OTA, only retains the update
+ // owner if it's consistence with sysconfig.
+ // -. Clear the update owner when update owner changes from sysconfig.
+ if (!pkgAlreadyExists || isSameUpdateOwner) {
+ pkgSetting.setUpdateOwnerPackage(updateOwnerFromSysconfig);
+ } else {
+ pkgSetting.setUpdateOwnerPackage(null);
+ }
+ }
}
if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0) {
@@ -641,6 +678,18 @@ final class InstallPackageHelper {
}
if (installed) {
+ final String updateOwner = pkgSetting.getInstallSource().mUpdateOwnerPackageName;
+ final var dpmi = mInjector.getLocalService(DevicePolicyManagerInternal.class);
+ final boolean isFromManagedUserOrProfile =
+ dpmi != null && dpmi.isUserOrganizationManaged(userId);
+ // Here we handle the update owner when install existing package, and the rules are:
+ // -. Retain the update owner when enable a system app in managed user or profile.
+ // -. Retain the update owner if the installer is the same.
+ // -. Clear the update owner when update owner changes.
+ if (!preLockSnapshot.isCallerSameApp(updateOwner, callingUid)
+ && (!pkgSetting.isSystem() || !isFromManagedUserOrProfile)) {
+ pkgSetting.setUpdateOwnerPackage(null);
+ }
if (pkgSetting.getPkg() != null) {
final PermissionManagerServiceInternal.PackageInstalledParams.Builder
permissionParamsBuilder =
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 77ffa165b6ad..adc0b0b6fc6a 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -926,6 +926,11 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
requestedInstallerPackageName = null;
}
+ final var dpmi = LocalServices.getService(DevicePolicyManagerInternal.class);
+ if (dpmi != null && dpmi.isUserOrganizationManaged(userId)) {
+ params.installFlags |= PackageManager.INSTALL_FROM_MANAGED_USER_OR_PROFILE;
+ }
+
if (isApex || mContext.checkCallingOrSelfPermission(
Manifest.permission.ENFORCE_UPDATE_OWNERSHIP) == PackageManager.PERMISSION_DENIED) {
params.installFlags &= ~PackageManager.INSTALL_REQUEST_UPDATE_OWNERSHIP;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index fb6ae8b50a26..fa535c38c5d2 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -868,15 +868,13 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private static final int USER_ACTION_NOT_NEEDED = 0;
private static final int USER_ACTION_REQUIRED = 1;
private static final int USER_ACTION_PENDING_APK_PARSING = 2;
- private static final int USER_ACTION_REQUIRED_UPDATE_OWNER_CHANGED = 3;
- private static final int USER_ACTION_REQUIRED_UPDATE_OWNER_RETAINED = 4;
+ private static final int USER_ACTION_REQUIRED_UPDATE_OWNER_REMINDER = 3;
@IntDef({
USER_ACTION_NOT_NEEDED,
USER_ACTION_REQUIRED,
USER_ACTION_PENDING_APK_PARSING,
- USER_ACTION_REQUIRED_UPDATE_OWNER_CHANGED,
- USER_ACTION_REQUIRED_UPDATE_OWNER_RETAINED
+ USER_ACTION_REQUIRED_UPDATE_OWNER_REMINDER,
})
@interface UserActionRequirement {}
@@ -937,7 +935,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
: null;
final boolean isInstallerOfRecord = isUpdate
&& Objects.equals(existingInstallerPackageName, getInstallerPackageName());
- final boolean isUpdateOwner = Objects.equals(existingUpdateOwnerPackageName,
+ final boolean isUpdateOwner = TextUtils.equals(existingUpdateOwnerPackageName,
getInstallerPackageName());
final boolean isSelfUpdate = targetPackageUid == mInstallerUid;
final boolean isPermissionGranted = isInstallPermissionGranted
@@ -947,6 +945,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
final boolean isInstallerRoot = (mInstallerUid == Process.ROOT_UID);
final boolean isInstallerSystem = (mInstallerUid == Process.SYSTEM_UID);
final boolean isInstallerShell = (mInstallerUid == Process.SHELL_UID);
+ final boolean isFromManagedUserOrProfile =
+ (params.installFlags & PackageManager.INSTALL_FROM_MANAGED_USER_OR_PROFILE) != 0;
final boolean isUpdateOwnershipEnforcementEnabled =
mPm.isUpdateOwnershipEnforcementAvailable()
&& existingUpdateOwnerPackageName != null;
@@ -963,12 +963,10 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
if (isUpdateOwnershipEnforcementEnabled
&& !isApexSession()
&& !isUpdateOwner
- && !isInstallerShell) {
- final boolean isRequestUpdateOwner =
- (params.installFlags & PackageManager.INSTALL_REQUEST_UPDATE_OWNERSHIP) != 0;
-
- return isRequestUpdateOwner ? USER_ACTION_REQUIRED_UPDATE_OWNER_CHANGED
- : USER_ACTION_REQUIRED_UPDATE_OWNER_RETAINED;
+ && !isInstallerShell
+ // We don't enforce the update ownership for the managed user and profile.
+ && !isFromManagedUserOrProfile) {
+ return USER_ACTION_REQUIRED_UPDATE_OWNER_REMINDER;
}
if (isPermissionGranted) {
@@ -2361,8 +2359,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
userActionRequirement = session.computeUserActionRequirement();
session.updateUserActionRequirement(userActionRequirement);
if (userActionRequirement == USER_ACTION_REQUIRED
- || userActionRequirement == USER_ACTION_REQUIRED_UPDATE_OWNER_CHANGED
- || userActionRequirement == USER_ACTION_REQUIRED_UPDATE_OWNER_RETAINED) {
+ || userActionRequirement == USER_ACTION_REQUIRED_UPDATE_OWNER_REMINDER) {
session.sendPendingUserActionIntent(target);
return true;
}
@@ -2425,9 +2422,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
private static @UserActionReason int userActionRequirementToReason(
@UserActionRequirement int requirement) {
switch (requirement) {
- case USER_ACTION_REQUIRED_UPDATE_OWNER_CHANGED:
- return PackageInstaller.REASON_OWNERSHIP_CHANGED;
- case USER_ACTION_REQUIRED_UPDATE_OWNER_RETAINED:
+ case USER_ACTION_REQUIRED_UPDATE_OWNER_REMINDER:
return PackageInstaller.REASON_REMIND_OWNERSHIP;
default:
return PackageInstaller.REASON_CONFIRM_PACKAGE_CHANGE;
diff --git a/services/core/java/com/android/server/pm/RestrictionsSet.java b/services/core/java/com/android/server/pm/RestrictionsSet.java
index e7ad5b92ed2e..08047695a42a 100644
--- a/services/core/java/com/android/server/pm/RestrictionsSet.java
+++ b/services/core/java/com/android/server/pm/RestrictionsSet.java
@@ -20,7 +20,9 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.os.Bundle;
+import android.os.UserHandle;
import android.os.UserManager;
+import android.util.IntArray;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
@@ -37,9 +39,7 @@ import java.util.ArrayList;
import java.util.List;
/**
- * Data structure that contains the mapping of users to user restrictions (either the user
- * restrictions that apply to them, or the user restrictions that they set, depending on the
- * circumstances).
+ * Data structure that contains the mapping of users to user restrictions.
*
* @hide
*/
@@ -88,6 +88,24 @@ public class RestrictionsSet {
}
/**
+ * Removes a particular restriction for all users.
+ *
+ * @return whether the restriction was removed or not.
+ */
+ public boolean removeRestrictionsForAllUsers(String restriction) {
+ boolean removed = false;
+ for (int i = 0; i < mUserRestrictions.size(); i++) {
+ final Bundle restrictions = mUserRestrictions.valueAt(i);
+
+ if (UserRestrictionsUtils.contains(restrictions, restriction)) {
+ restrictions.remove(restriction);
+ removed = true;
+ }
+ }
+ return removed;
+ }
+
+ /**
* Moves a particular restriction from one restriction set to another, e.g. for all users.
*/
public void moveRestriction(@NonNull RestrictionsSet destRestrictions, String restriction) {
@@ -139,22 +157,19 @@ public class RestrictionsSet {
* @return list of enforcing users that enforce a particular restriction.
*/
public @NonNull List<UserManager.EnforcingUser> getEnforcingUsers(String restriction,
- @UserIdInt int deviceOwnerUserId) {
+ @UserIdInt int userId) {
final List<UserManager.EnforcingUser> result = new ArrayList<>();
- for (int i = 0; i < mUserRestrictions.size(); i++) {
- if (UserRestrictionsUtils.contains(mUserRestrictions.valueAt(i), restriction)) {
- result.add(getEnforcingUser(mUserRestrictions.keyAt(i), deviceOwnerUserId));
- }
+ if (getRestrictionsNonNull(userId).containsKey(restriction)) {
+ result.add(new UserManager.EnforcingUser(userId,
+ UserManager.RESTRICTION_SOURCE_PROFILE_OWNER));
+ }
+
+ if (getRestrictionsNonNull(UserHandle.USER_ALL).containsKey(restriction)) {
+ result.add(new UserManager.EnforcingUser(UserHandle.USER_ALL,
+ UserManager.RESTRICTION_SOURCE_DEVICE_OWNER));
}
- return result;
- }
- private UserManager.EnforcingUser getEnforcingUser(@UserIdInt int userId,
- @UserIdInt int deviceOwnerUserId) {
- int source = deviceOwnerUserId == userId
- ? UserManager.RESTRICTION_SOURCE_DEVICE_OWNER
- : UserManager.RESTRICTION_SOURCE_PROFILE_OWNER;
- return new UserManager.EnforcingUser(userId, source);
+ return result;
}
/**
@@ -165,6 +180,11 @@ public class RestrictionsSet {
return mUserRestrictions.get(userId);
}
+ /** @return list of user restrictions for a given user that is not null. */
+ public @NonNull Bundle getRestrictionsNonNull(@UserIdInt int userId) {
+ return UserRestrictionsUtils.nonNull(mUserRestrictions.get(userId));
+ }
+
/**
* Removes a given user from the restrictions set, returning true if the user has non-empty
* restrictions before removal.
@@ -236,6 +256,15 @@ public class RestrictionsSet {
}
}
+ /** @return list of users in this restriction set. */
+ public IntArray getUserIds() {
+ IntArray userIds = new IntArray(mUserRestrictions.size());
+ for (int i = 0; i < mUserRestrictions.size(); i++) {
+ userIds.add(mUserRestrictions.keyAt(i));
+ }
+ return userIds;
+ }
+
public boolean containsKey(@UserIdInt int userId) {
return mUserRestrictions.contains(userId);
}
diff --git a/services/core/java/com/android/server/pm/UserManagerInternal.java b/services/core/java/com/android/server/pm/UserManagerInternal.java
index 36efc0ddfc44..9ef1bba16351 100644
--- a/services/core/java/com/android/server/pm/UserManagerInternal.java
+++ b/services/core/java/com/android/server/pm/UserManagerInternal.java
@@ -141,6 +141,18 @@ public abstract class UserManagerInternal {
public abstract void setDevicePolicyUserRestrictions(int originatingUserId,
@Nullable Bundle global, @Nullable RestrictionsSet local, boolean isDeviceOwner);
+ /**
+ * Called by {@link com.android.server.devicepolicy.DevicePolicyManagerService} to set a
+ * user restriction.
+ *
+ * @param userId user id to apply the restriction to. {@link com.android.os.UserHandle.USER_ALL}
+ * will apply the restriction to all users globally.
+ * @param key The key of the restriction.
+ * @param value The value of the restriction.
+ */
+ public abstract void setUserRestriction(@UserIdInt int userId, @NonNull String key,
+ boolean value);
+
/** Return a user restriction. */
public abstract boolean getUserRestriction(int userId, String key);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 19a0e03a9329..dd014ee637c7 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -457,30 +457,12 @@ public class UserManagerService extends IUserManager.Stub {
/**
* User restrictions set by {@link com.android.server.devicepolicy.DevicePolicyManagerService}
- * that should be applied to all users, including guests. Only non-empty restriction bundles are
- * stored.
- * The key is the user id of the user whom the restriction originated from.
- */
- @GuardedBy("mRestrictionsLock")
- private final RestrictionsSet mDevicePolicyGlobalUserRestrictions = new RestrictionsSet();
-
- /**
- * Id of the user that set global restrictions.
- */
- @GuardedBy("mRestrictionsLock")
- private int mDeviceOwnerUserId = UserHandle.USER_NULL;
-
- /**
- * User restrictions set by {@link com.android.server.devicepolicy.DevicePolicyManagerService}
- * for each user.
+ * for each user. Restrictions that apply to all users (global) are represented by
+ * {@link com.android.os.UserHandle.USER_ALL}.
* The key is the user id of the user whom the restrictions are targeting.
- * The key inside the restrictionsSet is the user id of the user whom the restriction
- * originated from.
- * targetUserId -> originatingUserId -> restrictionBundle
*/
@GuardedBy("mRestrictionsLock")
- private final SparseArray<RestrictionsSet> mDevicePolicyLocalUserRestrictions =
- new SparseArray<>();
+ private final RestrictionsSet mDevicePolicyUserRestrictions = new RestrictionsSet();
@GuardedBy("mGuestRestrictions")
private final Bundle mGuestRestrictions = new Bundle();
@@ -2567,150 +2549,72 @@ public class UserManagerService extends IUserManager.Stub {
}
}
- /**
- * See {@link UserManagerInternal#setDevicePolicyUserRestrictions}
- */
- private void setDevicePolicyUserRestrictionsInner(@UserIdInt int originatingUserId,
- @NonNull Bundle global, @NonNull RestrictionsSet local,
- boolean isDeviceOwner) {
- boolean globalChanged, localChanged;
- List<Integer> updatedLocalTargetUserIds;
- synchronized (mRestrictionsLock) {
- // Update global and local restrictions if they were changed.
- globalChanged = mDevicePolicyGlobalUserRestrictions
- .updateRestrictions(originatingUserId, global);
- updatedLocalTargetUserIds = getUpdatedTargetUserIdsFromLocalRestrictions(
- originatingUserId, local);
- localChanged = updateLocalRestrictionsForTargetUsersLR(originatingUserId, local,
- updatedLocalTargetUserIds);
- if (isDeviceOwner) {
- // Remember the global restriction owner userId to be able to make a distinction
- // in getUserRestrictionSource on who set local policies.
- mDeviceOwnerUserId = originatingUserId;
- } else {
- if (mDeviceOwnerUserId == originatingUserId) {
- // When profile owner sets restrictions it passes null global bundle and we
- // reset global restriction owner userId.
- // This means this user used to have DO, but now the DO is gone and the user
- // instead has PO.
- mDeviceOwnerUserId = UserHandle.USER_NULL;
- }
- }
- }
- if (DBG) {
- Slog.d(LOG_TAG, "setDevicePolicyUserRestrictions: "
- + " originatingUserId=" + originatingUserId
- + " global=" + global + (globalChanged ? " (changed)" : "")
- + " local=" + local + (localChanged ? " (changed)" : "")
- );
- }
- // Don't call them within the mRestrictionsLock.
- synchronized (mPackagesLock) {
- if (globalChanged || localChanged) {
- if (updatedLocalTargetUserIds.size() == 1
- && updatedLocalTargetUserIds.contains(originatingUserId)) {
- writeUserLP(getUserDataNoChecks(originatingUserId));
- } else {
- if (globalChanged) {
- writeUserLP(getUserDataNoChecks(originatingUserId));
- }
- if (localChanged) {
- for (int targetUserId : updatedLocalTargetUserIds) {
- writeAllTargetUsersLP(targetUserId);
- }
- }
- }
- }
+ private void setUserRestrictionInner(int userId, @NonNull String key, boolean value) {
+ if (!UserRestrictionsUtils.isValidRestriction(key)) {
+ return;
}
-
synchronized (mRestrictionsLock) {
- if (globalChanged) {
- applyUserRestrictionsForAllUsersLR();
- } else if (localChanged) {
- for (int targetUserId : updatedLocalTargetUserIds) {
- applyUserRestrictionsLR(targetUserId);
+ final Bundle newRestrictions = BundleUtils.clone(
+ mDevicePolicyUserRestrictions.getRestrictions(userId));
+ newRestrictions.putBoolean(key, value);
+
+ if (mDevicePolicyUserRestrictions.updateRestrictions(userId, newRestrictions)) {
+ if (userId == UserHandle.USER_ALL) {
+ applyUserRestrictionsForAllUsersLR();
+ } else {
+ applyUserRestrictionsLR(userId);
}
}
}
}
/**
- * @return the list of updated target user ids in device policy local restrictions for a
- * given originating user id.
+ * See {@link UserManagerInternal#setDevicePolicyUserRestrictions}
*/
- private List<Integer> getUpdatedTargetUserIdsFromLocalRestrictions(int originatingUserId,
- @NonNull RestrictionsSet local) {
- List<Integer> targetUserIds = new ArrayList<>();
- // Update all the target user ids from the local restrictions set
- for (int i = 0; i < local.size(); i++) {
- targetUserIds.add(local.keyAt(i));
- }
- // Update the target user id from device policy local restrictions if the local
- // restrictions set does not contain the target user id.
- for (int i = 0; i < mDevicePolicyLocalUserRestrictions.size(); i++) {
- int targetUserId = mDevicePolicyLocalUserRestrictions.keyAt(i);
- RestrictionsSet restrictionsSet = mDevicePolicyLocalUserRestrictions.valueAt(i);
- if (!local.containsKey(targetUserId)
- && restrictionsSet.containsKey(originatingUserId)) {
- targetUserIds.add(targetUserId);
- }
- }
- return targetUserIds;
- }
+ private void setDevicePolicyUserRestrictionsInner(@UserIdInt int originatingUserId,
+ @NonNull Bundle global, @NonNull RestrictionsSet local,
+ boolean isDeviceOwner) {
+ synchronized (mRestrictionsLock) {
+ final IntArray updatedUserIds = mDevicePolicyUserRestrictions.getUserIds();
- /**
- * Update restrictions for all target users in the restriction set. If a target user does not
- * exist in device policy local restrictions, remove the restrictions bundle for that target
- * user originating from the specified originating user.
- */
- @GuardedBy("mRestrictionsLock")
- private boolean updateLocalRestrictionsForTargetUsersLR(int originatingUserId,
- RestrictionsSet local, List<Integer> updatedTargetUserIds) {
- boolean changed = false;
- for (int targetUserId : updatedTargetUserIds) {
- Bundle restrictions = local.getRestrictions(targetUserId);
- if (restrictions == null) {
- restrictions = new Bundle();
- }
- if (getDevicePolicyLocalRestrictionsForTargetUserLR(targetUserId)
- .updateRestrictions(originatingUserId, restrictions)) {
- changed = true;
+ mCachedEffectiveUserRestrictions.removeAllRestrictions();
+ mDevicePolicyUserRestrictions.removeAllRestrictions();
+
+ mDevicePolicyUserRestrictions.updateRestrictions(UserHandle.USER_ALL, global);
+
+ final IntArray localUserIds = local.getUserIds();
+ for (int i = 0; i < localUserIds.size(); i++) {
+ final int userId = localUserIds.get(i);
+ mDevicePolicyUserRestrictions.updateRestrictions(userId,
+ local.getRestrictions(userId));
+ updatedUserIds.add(userId);
}
- }
- return changed;
- }
- /**
- * A new restriction set is created if a restriction set does not already exist for a given
- * target user.
- *
- * @return restrictions set for a given target user.
- */
- @GuardedBy("mRestrictionsLock")
- private @NonNull RestrictionsSet getDevicePolicyLocalRestrictionsForTargetUserLR(
- int targetUserId) {
- RestrictionsSet result = mDevicePolicyLocalUserRestrictions.get(targetUserId);
- if (result == null) {
- result = new RestrictionsSet();
- mDevicePolicyLocalUserRestrictions.put(targetUserId, result);
+ applyUserRestrictionsForAllUsersLR();
+ for (int i = 0; i < updatedUserIds.size(); i++) {
+ if (updatedUserIds.get(i) == UserHandle.USER_ALL) {
+ continue;
+ }
+ applyUserRestrictionsLR(updatedUserIds.get(i));
+ }
}
- return result;
}
@GuardedBy("mRestrictionsLock")
private Bundle computeEffectiveUserRestrictionsLR(@UserIdInt int userId) {
- final Bundle baseRestrictions =
- UserRestrictionsUtils.nonNull(mBaseUserRestrictions.getRestrictions(userId));
- final Bundle global = mDevicePolicyGlobalUserRestrictions.mergeAll();
- final RestrictionsSet local = getDevicePolicyLocalRestrictionsForTargetUserLR(userId);
+ final Bundle baseRestrictions = mBaseUserRestrictions.getRestrictionsNonNull(userId);
+
+ final Bundle global = mDevicePolicyUserRestrictions.getRestrictionsNonNull(
+ UserHandle.USER_ALL);
+ final Bundle local = mDevicePolicyUserRestrictions.getRestrictionsNonNull(userId);
- if (BundleUtils.isEmpty(global) && local.isEmpty()) {
+ if (global.isEmpty() && local.isEmpty()) {
// Common case first.
return baseRestrictions;
}
final Bundle effective = BundleUtils.clone(baseRestrictions);
UserRestrictionsUtils.merge(effective, global);
- UserRestrictionsUtils.merge(effective, local.mergeAll());
+ UserRestrictionsUtils.merge(effective, local);
return effective;
}
@@ -2834,13 +2738,7 @@ public class UserManagerService extends IUserManager.Stub {
}
synchronized (mRestrictionsLock) {
- // Check if it is set as a local restriction.
- result.addAll(getDevicePolicyLocalRestrictionsForTargetUserLR(userId).getEnforcingUsers(
- restrictionKey, mDeviceOwnerUserId));
-
- // Check if it is set as a global restriction.
- result.addAll(mDevicePolicyGlobalUserRestrictions.getEnforcingUsers(restrictionKey,
- mDeviceOwnerUserId));
+ result.addAll(mDevicePolicyUserRestrictions.getEnforcingUsers(restrictionKey, userId));
}
return result;
}
@@ -2990,6 +2888,7 @@ public class UserManagerService extends IUserManager.Stub {
@GuardedBy("mRestrictionsLock")
private void applyUserRestrictionsLR(@UserIdInt int userId) {
updateUserRestrictionsInternalLR(null, userId);
+ scheduleWriteUser(getUserDataNoChecks(userId));
}
@GuardedBy("mRestrictionsLock")
@@ -3666,10 +3565,6 @@ public class UserManagerService extends IUserManager.Stub {
parser.getAttributeInt(null, ATTR_USER_TYPE_VERSION, mUserTypeVersion);
}
- // Pre-O global user restriction were stored as a single bundle (as opposed to per-user
- // currently), take care of it in case of upgrade.
- Bundle oldDevicePolicyGlobalUserRestrictions = null;
-
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
if (type == XmlPullParser.START_TAG) {
final String name = parser.getName();
@@ -3698,23 +3593,12 @@ public class UserManagerService extends IUserManager.Stub {
break;
}
}
- } else if (name.equals(TAG_DEVICE_OWNER_USER_ID)
- // Legacy name, should only be encountered when upgrading from pre-O.
- || name.equals(TAG_GLOBAL_RESTRICTION_OWNER_ID)) {
- synchronized (mRestrictionsLock) {
- mDeviceOwnerUserId =
- parser.getAttributeInt(null, ATTR_ID, mDeviceOwnerUserId);
- }
- } else if (name.equals(TAG_DEVICE_POLICY_RESTRICTIONS)) {
- // Should only happen when upgrading from pre-O (version < 7).
- oldDevicePolicyGlobalUserRestrictions =
- UserRestrictionsUtils.readRestrictions(parser);
}
}
}
updateUserIds();
- upgradeIfNecessaryLP(oldDevicePolicyGlobalUserRestrictions);
+ upgradeIfNecessaryLP();
} catch (IOException | XmlPullParserException e) {
fallbackToSingleUserLP();
} finally {
@@ -3724,21 +3608,19 @@ public class UserManagerService extends IUserManager.Stub {
/**
* Upgrade steps between versions, either for fixing bugs or changing the data format.
- * @param oldGlobalUserRestrictions Pre-O global device policy restrictions.
*/
@GuardedBy({"mPackagesLock"})
- private void upgradeIfNecessaryLP(Bundle oldGlobalUserRestrictions) {
- upgradeIfNecessaryLP(oldGlobalUserRestrictions, mUserVersion, mUserTypeVersion);
+ private void upgradeIfNecessaryLP() {
+ upgradeIfNecessaryLP(mUserVersion, mUserTypeVersion);
}
/**
- * Version of {@link #upgradeIfNecessaryLP(Bundle)} that takes in the userVersion for testing
- * purposes. For non-tests, use {@link #upgradeIfNecessaryLP(Bundle)}.
+ * Version of {@link #upgradeIfNecessaryLP()} that takes in the userVersion for testing
+ * purposes. For non-tests, use {@link #upgradeIfNecessaryLP()}.
*/
@GuardedBy({"mPackagesLock"})
@VisibleForTesting
- void upgradeIfNecessaryLP(Bundle oldGlobalUserRestrictions, int userVersion,
- int userTypeVersion) {
+ void upgradeIfNecessaryLP(int userVersion, int userTypeVersion) {
Slog.i(LOG_TAG, "Upgrading users from userVersion " + userVersion + " to " + USER_VERSION);
Set<Integer> userIdsToWrite = new ArraySet<>();
final int originalVersion = mUserVersion;
@@ -3792,16 +3674,11 @@ public class UserManagerService extends IUserManager.Stub {
if (userVersion < 7) {
// Previously only one user could enforce global restrictions, now it is per-user.
synchronized (mRestrictionsLock) {
- if (!BundleUtils.isEmpty(oldGlobalUserRestrictions)
- && mDeviceOwnerUserId != UserHandle.USER_NULL) {
- mDevicePolicyGlobalUserRestrictions.updateRestrictions(
- mDeviceOwnerUserId, oldGlobalUserRestrictions);
+ if (mDevicePolicyUserRestrictions.removeRestrictionsForAllUsers(
+ UserManager.ENSURE_VERIFY_APPS)) {
+ mDevicePolicyUserRestrictions.getRestrictionsNonNull(UserHandle.USER_ALL)
+ .putBoolean(UserManager.ENSURE_VERIFY_APPS, true);
}
- // ENSURE_VERIFY_APPS is now enforced globally even if put by profile owner, so move
- // it from local to global bundle for all users who set it.
- UserRestrictionsUtils.moveRestriction(UserManager.ENSURE_VERIFY_APPS,
- mDevicePolicyLocalUserRestrictions, mDevicePolicyGlobalUserRestrictions
- );
}
// DISALLOW_CONFIG_WIFI was made a default guest restriction some time during version 6.
final List<UserInfo> guestUsers = getGuestUsers();
@@ -4064,22 +3941,22 @@ public class UserManagerService extends IUserManager.Stub {
@GuardedBy({"mPackagesLock"})
private void fallbackToSingleUserLP() {
- int flags = UserInfo.FLAG_SYSTEM | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_ADMIN
- | UserInfo.FLAG_PRIMARY;
// Create the system user
- String systemUserType = isDefaultHeadlessSystemUserMode()
+ final String systemUserType = isDefaultHeadlessSystemUserMode()
? UserManager.USER_TYPE_SYSTEM_HEADLESS
: UserManager.USER_TYPE_FULL_SYSTEM;
- flags |= mUserTypes.get(systemUserType).getDefaultUserInfoFlags();
- UserInfo system = new UserInfo(UserHandle.USER_SYSTEM, null, null, flags, systemUserType);
- UserData userData = putUserInfo(system);
+ final int flags = mUserTypes.get(systemUserType).getDefaultUserInfoFlags()
+ | UserInfo.FLAG_INITIALIZED;
+ final UserInfo system = new UserInfo(UserHandle.USER_SYSTEM,
+ /* name= */ null, /* iconPath= */ null, flags, systemUserType);
+ final UserData userData = putUserInfo(system);
userData.userProperties = new UserProperties(
mUserTypes.get(userData.info.userType).getDefaultUserPropertiesReference());
mNextSerialNumber = MIN_USER_ID;
mUserVersion = USER_VERSION;
mUserTypeVersion = UserTypeFactory.getUserTypeVersion();
- Bundle restrictions = new Bundle();
+ final Bundle restrictions = new Bundle();
try {
final String[] defaultFirstUserRestrictions = mContext.getResources().getStringArray(
com.android.internal.R.array.config_defaultFirstUserRestrictions);
@@ -4135,17 +4012,6 @@ public class UserManagerService extends IUserManager.Stub {
}
@GuardedBy({"mPackagesLock"})
- private void writeAllTargetUsersLP(int originatingUserId) {
- for (int i = 0; i < mDevicePolicyLocalUserRestrictions.size(); i++) {
- int targetUserId = mDevicePolicyLocalUserRestrictions.keyAt(i);
- RestrictionsSet restrictionsSet = mDevicePolicyLocalUserRestrictions.valueAt(i);
- if (restrictionsSet.containsKey(originatingUserId)) {
- writeUserLP(getUserDataNoChecks(targetUserId));
- }
- }
- }
-
- @GuardedBy({"mPackagesLock"})
private void writeUserLP(UserData userData) {
if (DBG) {
debug("writeUserLP " + userData);
@@ -4231,11 +4097,14 @@ public class UserManagerService extends IUserManager.Stub {
synchronized (mRestrictionsLock) {
UserRestrictionsUtils.writeRestrictions(serializer,
mBaseUserRestrictions.getRestrictions(userInfo.id), TAG_RESTRICTIONS);
- getDevicePolicyLocalRestrictionsForTargetUserLR(userInfo.id).writeRestrictions(
- serializer, TAG_DEVICE_POLICY_LOCAL_RESTRICTIONS);
+
+ UserRestrictionsUtils.writeRestrictions(serializer,
+ mDevicePolicyUserRestrictions.getRestrictions(UserHandle.USER_ALL),
+ TAG_DEVICE_POLICY_RESTRICTIONS);
+
UserRestrictionsUtils.writeRestrictions(serializer,
- mDevicePolicyGlobalUserRestrictions.getRestrictions(userInfo.id),
- TAG_DEVICE_POLICY_GLOBAL_RESTRICTIONS);
+ mDevicePolicyUserRestrictions.getRestrictions(userInfo.id),
+ TAG_DEVICE_POLICY_RESTRICTIONS);
}
if (userData.account != null) {
@@ -4303,11 +4172,6 @@ public class UserManagerService extends IUserManager.Stub {
.writeRestrictions(serializer, mGuestRestrictions, TAG_RESTRICTIONS);
}
serializer.endTag(null, TAG_GUEST_RESTRICTIONS);
- serializer.startTag(null, TAG_DEVICE_OWNER_USER_ID);
- synchronized (mRestrictionsLock) {
- serializer.attributeInt(null, ATTR_ID, mDeviceOwnerUserId);
- }
- serializer.endTag(null, TAG_DEVICE_OWNER_USER_ID);
int[] userIdsToWrite;
synchronized (mUsersLock) {
userIdsToWrite = new int[mUsers.size()];
@@ -4379,7 +4243,7 @@ public class UserManagerService extends IUserManager.Stub {
UserProperties userProperties = null;
Bundle baseRestrictions = null;
Bundle legacyLocalRestrictions = null;
- RestrictionsSet localRestrictions = null;
+ Bundle localRestrictions = null;
Bundle globalRestrictions = null;
boolean ignorePrepareStorageErrors = true; // default is true for old users
@@ -4445,8 +4309,7 @@ public class UserManagerService extends IUserManager.Stub {
} else if (TAG_DEVICE_POLICY_RESTRICTIONS.equals(tag)) {
legacyLocalRestrictions = UserRestrictionsUtils.readRestrictions(parser);
} else if (TAG_DEVICE_POLICY_LOCAL_RESTRICTIONS.equals(tag)) {
- localRestrictions = RestrictionsSet.readRestrictions(parser,
- TAG_DEVICE_POLICY_LOCAL_RESTRICTIONS);
+ localRestrictions = UserRestrictionsUtils.readRestrictions(parser);
} else if (TAG_DEVICE_POLICY_GLOBAL_RESTRICTIONS.equals(tag)) {
globalRestrictions = UserRestrictionsUtils.readRestrictions(parser);
} else if (TAG_ACCOUNT.equals(tag)) {
@@ -4516,19 +4379,15 @@ public class UserManagerService extends IUserManager.Stub {
mBaseUserRestrictions.updateRestrictions(id, baseRestrictions);
}
if (localRestrictions != null) {
- mDevicePolicyLocalUserRestrictions.put(id, localRestrictions);
+ mDevicePolicyUserRestrictions.updateRestrictions(id, localRestrictions);
if (legacyLocalRestrictions != null) {
Slog.wtf(LOG_TAG, "Seeing both legacy and current local restrictions in xml");
}
} else if (legacyLocalRestrictions != null) {
- RestrictionsSet legacyLocalRestrictionsSet =
- legacyLocalRestrictions.isEmpty()
- ? new RestrictionsSet()
- : new RestrictionsSet(id, legacyLocalRestrictions);
- mDevicePolicyLocalUserRestrictions.put(id, legacyLocalRestrictionsSet);
+ mDevicePolicyUserRestrictions.updateRestrictions(id, legacyLocalRestrictions);
}
if (globalRestrictions != null) {
- mDevicePolicyGlobalUserRestrictions.updateRestrictions(id,
+ mDevicePolicyUserRestrictions.updateRestrictions(UserHandle.USER_ALL,
globalRestrictions);
}
}
@@ -5364,18 +5223,12 @@ public class UserManagerService extends IUserManager.Stub {
}
} else if (atomTag == FrameworkStatsLog.MULTI_USER_INFO) {
if (UserManager.getMaxSupportedUsers() > 1) {
- int deviceOwnerUserId = UserHandle.USER_NULL;
-
- synchronized (mRestrictionsLock) {
- deviceOwnerUserId = mDeviceOwnerUserId;
- }
-
data.add(FrameworkStatsLog.buildStatsEvent(FrameworkStatsLog.MULTI_USER_INFO,
UserManager.getMaxSupportedUsers(),
- isUserSwitcherEnabled(deviceOwnerUserId),
+ isUserSwitcherEnabled(UserHandle.USER_ALL),
UserManager.supportsMultipleUsers()
&& !hasUserRestriction(UserManager.DISALLOW_ADD_USER,
- deviceOwnerUserId)));
+ UserHandle.USER_ALL)));
}
} else {
Slogf.e(LOG_TAG, "Unexpected atom tag: %d", atomTag);
@@ -5843,17 +5696,8 @@ public class UserManagerService extends IUserManager.Stub {
mBaseUserRestrictions.remove(userId);
mAppliedUserRestrictions.remove(userId);
mCachedEffectiveUserRestrictions.remove(userId);
- // Remove local restrictions affecting user
- mDevicePolicyLocalUserRestrictions.delete(userId);
- // Remove local restrictions set by user
- boolean changed = false;
- for (int i = 0; i < mDevicePolicyLocalUserRestrictions.size(); i++) {
- int targetUserId = mDevicePolicyLocalUserRestrictions.keyAt(i);
- changed |= getDevicePolicyLocalRestrictionsForTargetUserLR(targetUserId)
- .remove(userId);
- }
- changed |= mDevicePolicyGlobalUserRestrictions.remove(userId);
- if (changed) {
+ // Remove restrictions affecting the user
+ if (mDevicePolicyUserRestrictions.remove(userId)) {
applyUserRestrictionsForAllUsersLR();
}
}
@@ -6587,10 +6431,12 @@ public class UserManagerService extends IUserManager.Stub {
pw.println();
pw.println("Device properties:");
+ pw.println(" Device policy global restrictions:");
synchronized (mRestrictionsLock) {
- pw.println(" Device owner id:" + mDeviceOwnerUserId);
+ UserRestrictionsUtils.dumpRestrictions(
+ pw, " ",
+ mDevicePolicyUserRestrictions.getRestrictions(UserHandle.USER_ALL));
}
- pw.println();
pw.println(" Guest restrictions:");
synchronized (mGuestRestrictions) {
UserRestrictionsUtils.dumpRestrictions(pw, " ", mGuestRestrictions);
@@ -6768,13 +6614,10 @@ public class UserManagerService extends IUserManager.Stub {
synchronized (mRestrictionsLock) {
UserRestrictionsUtils.dumpRestrictions(
pw, " ", mBaseUserRestrictions.getRestrictions(userInfo.id));
- pw.println(" Device policy global restrictions:");
+ pw.println(" Device policy restrictions:");
UserRestrictionsUtils.dumpRestrictions(
pw, " ",
- mDevicePolicyGlobalUserRestrictions.getRestrictions(userInfo.id));
- pw.println(" Device policy local restrictions:");
- getDevicePolicyLocalRestrictionsForTargetUserLR(
- userInfo.id).dumpRestrictions(pw, " ");
+ mDevicePolicyUserRestrictions.getRestrictions(userInfo.id));
pw.println(" Effective restrictions:");
UserRestrictionsUtils.dumpRestrictions(
pw, " ",
@@ -6857,6 +6700,11 @@ public class UserManagerService extends IUserManager.Stub {
}
@Override
+ public void setUserRestriction(int userId, @NonNull String key, boolean value) {
+ UserManagerService.this.setUserRestrictionInner(userId, key, value);
+ }
+
+ @Override
public boolean getUserRestriction(@UserIdInt int userId, String key) {
return getUserRestrictions(userId).getBoolean(key);
}
diff --git a/services/core/java/com/android/server/pm/UserTypeDetails.java b/services/core/java/com/android/server/pm/UserTypeDetails.java
index f86ee9032ee9..6065372e1ea0 100644
--- a/services/core/java/com/android/server/pm/UserTypeDetails.java
+++ b/services/core/java/com/android/server/pm/UserTypeDetails.java
@@ -76,7 +76,7 @@ public final class UserTypeDetails {
private final @UserInfoFlag int mBaseType;
// TODO(b/143784345): Update doc/name when we clean up UserInfo.
- /** The {@link UserInfo.UserInfoFlag}s that all users of this type will automatically have. */
+ /** The {@link UserInfoFlag}s to apply by default to newly created users of this type. */
private final @UserInfoFlag int mDefaultUserInfoPropertyFlags;
/**
@@ -224,7 +224,7 @@ public final class UserTypeDetails {
}
// TODO(b/143784345): Update comment when UserInfo is reorganized.
- /** The {@link UserInfo.UserInfoFlag}s that all users of this type will automatically have. */
+ /** The {@link UserInfoFlag}s to apply by default to newly created users of this type. */
public int getDefaultUserInfoFlags() {
return mDefaultUserInfoPropertyFlags | mBaseType;
}
@@ -526,6 +526,7 @@ public final class UserTypeDetails {
Preconditions.checkArgument(hasValidPropertyFlags(),
"UserTypeDetails " + mName + " has invalid flags: "
+ Integer.toHexString(mDefaultUserInfoPropertyFlags));
+ checkSystemAndMainUserPreconditions();
if (hasBadge()) {
Preconditions.checkArgument(mBadgeLabels != null && mBadgeLabels.length != 0,
"UserTypeDetails " + mName + " has badge but no badgeLabels.");
@@ -578,8 +579,6 @@ public final class UserTypeDetails {
// TODO(b/143784345): Refactor this when we clean up UserInfo.
private boolean hasValidPropertyFlags() {
final int forbiddenMask =
- UserInfo.FLAG_PRIMARY |
- UserInfo.FLAG_ADMIN |
UserInfo.FLAG_INITIALIZED |
UserInfo.FLAG_QUIET_MODE |
UserInfo.FLAG_FULL |
@@ -587,6 +586,18 @@ public final class UserTypeDetails {
UserInfo.FLAG_PROFILE;
return (mDefaultUserInfoPropertyFlags & forbiddenMask) == 0;
}
+
+ private void checkSystemAndMainUserPreconditions() {
+ // Primary must be synonymous with System.
+ Preconditions.checkArgument(
+ ((mBaseType & UserInfo.FLAG_SYSTEM) != 0) ==
+ ((mDefaultUserInfoPropertyFlags & UserInfo.FLAG_PRIMARY) != 0),
+ "UserTypeDetails " + mName + " cannot be SYSTEM xor PRIMARY.");
+ // At most one MainUser is ever allowed at a time.
+ Preconditions.checkArgument(
+ ((mDefaultUserInfoPropertyFlags & UserInfo.FLAG_MAIN) == 0) || mMaxAllowed == 1,
+ "UserTypeDetails " + mName + " must not sanction more than one MainUser.");
+ }
}
/**
diff --git a/services/core/java/com/android/server/pm/UserTypeFactory.java b/services/core/java/com/android/server/pm/UserTypeFactory.java
index 4cf8c0960a87..b7a2b86b1bcd 100644
--- a/services/core/java/com/android/server/pm/UserTypeFactory.java
+++ b/services/core/java/com/android/server/pm/UserTypeFactory.java
@@ -16,11 +16,14 @@
package com.android.server.pm;
+import static android.content.pm.UserInfo.FLAG_ADMIN;
import static android.content.pm.UserInfo.FLAG_DEMO;
import static android.content.pm.UserInfo.FLAG_EPHEMERAL;
import static android.content.pm.UserInfo.FLAG_FULL;
import static android.content.pm.UserInfo.FLAG_GUEST;
+import static android.content.pm.UserInfo.FLAG_MAIN;
import static android.content.pm.UserInfo.FLAG_MANAGED_PROFILE;
+import static android.content.pm.UserInfo.FLAG_PRIMARY;
import static android.content.pm.UserInfo.FLAG_PROFILE;
import static android.content.pm.UserInfo.FLAG_RESTRICTED;
import static android.content.pm.UserInfo.FLAG_SYSTEM;
@@ -62,7 +65,7 @@ import java.util.function.Consumer;
* This class is responsible both for defining the AOSP use types, as well as reading in customized
* user types from {@link com.android.internal.R.xml#config_user_types}.
*
- * Tests are located in UserManagerServiceUserTypeTest.java.
+ * Tests are located in {@link UserManagerServiceUserTypeTest}.
* @hide
*/
public final class UserTypeFactory {
@@ -277,7 +280,8 @@ public final class UserTypeFactory {
return new UserTypeDetails.Builder()
.setName(USER_TYPE_FULL_SYSTEM)
.setBaseType(FLAG_SYSTEM | FLAG_FULL)
- .setDefaultUserInfoPropertyFlags(UserInfo.FLAG_MAIN);
+ .setDefaultUserInfoPropertyFlags(FLAG_PRIMARY | FLAG_ADMIN | FLAG_MAIN)
+ .setMaxAllowed(1);
}
/**
@@ -287,7 +291,9 @@ public final class UserTypeFactory {
private static UserTypeDetails.Builder getDefaultTypeSystemHeadless() {
return new UserTypeDetails.Builder()
.setName(USER_TYPE_SYSTEM_HEADLESS)
- .setBaseType(FLAG_SYSTEM);
+ .setBaseType(FLAG_SYSTEM)
+ .setDefaultUserInfoPropertyFlags(FLAG_PRIMARY | FLAG_ADMIN)
+ .setMaxAllowed(1);
}
private static Bundle getDefaultSecondaryUserRestrictions() {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index 78761bdbabf1..cc2c9adfcba4 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -3673,9 +3673,9 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
isAppOpPermission = bp.isAppOp();
}
+ final int flags = getPermissionFlagsInternal(pkg.getPackageName(), permission,
+ myUid, userId);
if (shouldGrantRuntimePermission) {
- final int flags = getPermissionFlagsInternal(pkg.getPackageName(), permission,
- myUid, userId);
if (supportsRuntimePermissions) {
// Installer cannot change immutable permissions.
if ((flags & immutableFlags) == 0) {
@@ -3693,6 +3693,9 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
} else if (isAppOpPermission
&& PackageInstallerService.INSTALLER_CHANGEABLE_APP_OP_PERMISSIONS
.contains(permission)) {
+ if ((flags & PackageManager.FLAG_PERMISSION_USER_SET) != 0) {
+ continue;
+ }
int mode =
permissionState == PERMISSION_STATE_GRANTED ? MODE_ALLOWED : MODE_ERRORED;
int uid = UserHandle.getUid(userId, pkg.getUid());
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 449801da426c..336ad75c5b2c 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -129,7 +129,6 @@ import android.media.AudioSystem;
import android.media.IAudioService;
import android.media.session.MediaSessionLegacyHelper;
import android.os.Binder;
-import android.os.Build;
import android.os.Bundle;
import android.os.DeviceIdleManager;
import android.os.FactoryTest;
@@ -203,6 +202,7 @@ import com.android.internal.policy.PhoneWindow;
import com.android.internal.policy.TransitionAnimation;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.widget.LockPatternUtils;
import com.android.server.AccessibilityManagerInternal;
import com.android.server.ExtconStateObserver;
import com.android.server.ExtconUEventObserver;
@@ -416,6 +416,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
AppOpsManager mAppOpsManager;
PackageManager mPackageManager;
SideFpsEventHandler mSideFpsEventHandler;
+ LockPatternUtils mLockPatternUtils;
private boolean mHasFeatureAuto;
private boolean mHasFeatureWatch;
private boolean mHasFeatureLeanback;
@@ -1074,8 +1075,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
synchronized (mLock) {
- // Lock the device after the dream transition has finished.
- mLockAfterAppTransitionFinished = true;
+ // If the setting to lock instantly on power button press is true, then set the flag to
+ // lock after the dream transition has finished.
+ mLockAfterAppTransitionFinished =
+ mLockPatternUtils.getPowerButtonInstantlyLocks(mCurrentUserId);
}
dreamManagerInternal.requestDream();
@@ -1993,6 +1996,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mAccessibilityShortcutController = injector.getAccessibilityShortcutController(
mContext, new Handler(), mCurrentUserId);
mGlobalActionsFactory = injector.getGlobalActionsFactory();
+ mLockPatternUtils = new LockPatternUtils(mContext);
mLogger = new MetricsLogger();
mScreenOffSleepTokenAcquirer = mActivityTaskManagerInternal
@@ -3409,7 +3413,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_SPACE:
if (down && repeatCount == 0) {
// Handle keyboard layout switching. (CTRL + SPACE)
- if (KeyEvent.metaStateHasModifiers(metaState, KeyEvent.META_CTRL_ON)) {
+ if (KeyEvent.metaStateHasModifiers(metaState & ~KeyEvent.META_SHIFT_MASK,
+ KeyEvent.META_CTRL_ON)) {
int direction = (metaState & KeyEvent.META_SHIFT_MASK) != 0 ? -1 : 1;
mWindowManagerFuncs.switchKeyboardLayout(event.getDeviceId(), direction);
return true;
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 add4a8912858..3d3c5e26e4f7 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -82,6 +82,7 @@ import android.telephony.ServiceState.RegState;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
@@ -212,6 +213,7 @@ public class BatteryStatsImpl extends BatteryStats {
public static final int RESET_REASON_ADB_COMMAND = 2;
public static final int RESET_REASON_FULL_CHARGE = 3;
public static final int RESET_REASON_ENERGY_CONSUMER_BUCKETS_CHANGE = 4;
+ public static final int RESET_REASON_PLUGGED_IN_FOR_LONG_DURATION = 5;
protected Clock mClock;
@@ -423,6 +425,89 @@ public class BatteryStatsImpl extends BatteryStats {
}
}
+ /** Provide BatteryStatsImpl configuration choices */
+ public static class BatteryStatsConfig {
+ static final int RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG = 1 << 0;
+ static final int RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG = 1 << 1;
+
+ private final int mFlags;
+
+ private BatteryStatsConfig(Builder builder) {
+ int flags = 0;
+ if (builder.mResetOnUnplugHighBatteryLevel) {
+ flags |= RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG;
+ }
+ if (builder.mResetOnUnplugAfterSignificantCharge) {
+ flags |= RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG;
+ }
+ mFlags = flags;
+ }
+
+ /**
+ * Returns whether a BatteryStats reset should occur on unplug when the battery level is
+ * high.
+ */
+ boolean shouldResetOnUnplugHighBatteryLevel() {
+ return (mFlags & RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG)
+ == RESET_ON_UNPLUG_HIGH_BATTERY_LEVEL_FLAG;
+ }
+
+ /**
+ * Returns whether a BatteryStats reset should occur on unplug if the battery charge a
+ * significant amount since it has been plugged in.
+ */
+ boolean shouldResetOnUnplugAfterSignificantCharge() {
+ return (mFlags & RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG)
+ == RESET_ON_UNPLUG_AFTER_SIGNIFICANT_CHARGE_FLAG;
+ }
+
+ /**
+ * Builder for BatteryStatsConfig
+ */
+ public static class Builder {
+ private boolean mResetOnUnplugHighBatteryLevel;
+ private boolean mResetOnUnplugAfterSignificantCharge;
+ public Builder() {
+ mResetOnUnplugHighBatteryLevel = true;
+ mResetOnUnplugAfterSignificantCharge = true;
+ }
+
+ /**
+ * Build the BatteryStatsConfig.
+ */
+ public BatteryStatsConfig build() {
+ return new BatteryStatsConfig(this);
+ }
+
+ /**
+ * Set whether a BatteryStats reset should occur on unplug when the battery level is
+ * high.
+ */
+ public Builder setResetOnUnplugHighBatteryLevel(boolean reset) {
+ mResetOnUnplugHighBatteryLevel = reset;
+ return this;
+ }
+
+ /**
+ * Set whether a BatteryStats reset should occur on unplug if the battery charge a
+ * significant amount since it has been plugged in.
+ */
+ public Builder setResetOnUnplugAfterSignificantCharge(boolean reset) {
+ mResetOnUnplugAfterSignificantCharge = reset;
+ return this;
+ }
+ }
+
+ }
+
+ /** Handles calls to AlarmManager */
+ public interface AlarmInterface {
+ /** Schedule an RTC alarm */
+ void schedule(long rtcTimeMs, long windowLengthMs);
+ /** Cancel the previously scheduled alarm */
+ void cancel();
+ }
+
private final PlatformIdleStateCallback mPlatformIdleStateCallback;
private final Runnable mDeferSetCharging = new Runnable() {
@@ -773,6 +858,7 @@ public class BatteryStatsImpl extends BatteryStats {
private boolean mHaveBatteryLevel = false;
private boolean mBatteryPluggedIn;
+ private long mBatteryPluggedInRealTimeMs = 0;
private int mBatteryStatus;
private int mBatteryLevel;
private int mBatteryPlugType;
@@ -1479,6 +1565,13 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
protected final Constants mConstants;
+ @VisibleForTesting
+ @GuardedBy("this")
+ protected BatteryStatsConfig mBatteryStatsConfig = new BatteryStatsConfig.Builder().build();
+
+ @VisibleForTesting
+ protected AlarmInterface mLongPlugInAlarmInterface = null;
+
/*
* Holds a SamplingTimer associated with each Resource Power Manager state and voter,
* recording their times when on-battery (regardless of screen state).
@@ -1646,12 +1739,13 @@ public class BatteryStatsImpl extends BatteryStats {
mHandler = null;
mConstants = new Constants(mHandler);
mStartClockTimeMs = clock.currentTimeMillis();
- mCheckinFile = null;
mDailyFile = null;
if (historyDirectory == null) {
+ mCheckinFile = null;
mStatsFile = null;
mHistory = new BatteryStatsHistory(mStepDetailsCalculator, mClock);
} else {
+ mCheckinFile = new AtomicFile(new File(historyDirectory, "batterystats-checkin.bin"));
mStatsFile = new AtomicFile(new File(historyDirectory, "batterystats.bin"));
mHistory = new BatteryStatsHistory(historyDirectory, mConstants.MAX_HISTORY_FILES,
mConstants.MAX_HISTORY_BUFFER, mStepDetailsCalculator, mClock);
@@ -10954,6 +11048,27 @@ public class BatteryStatsImpl extends BatteryStats {
}
/**
+ * Injects BatteryStatsConfig
+ */
+ public void setBatteryStatsConfig(BatteryStatsConfig config) {
+ synchronized (this) {
+ mBatteryStatsConfig = config;
+ }
+ }
+
+ /**
+ * Injects an AlarmInterface for the long plug in alarm.
+ */
+ public void setLongPlugInAlarmInterface(AlarmInterface longPlugInAlarmInterface) {
+ synchronized (this) {
+ mLongPlugInAlarmInterface = longPlugInAlarmInterface;
+ if (mBatteryPluggedIn) {
+ scheduleNextResetWhilePluggedInCheck();
+ }
+ }
+ }
+
+ /**
* Starts tracking CPU time-in-state for threads of the system server process,
* keeping a separate account of threads receiving incoming binder calls.
*/
@@ -11386,12 +11501,12 @@ public class BatteryStatsImpl extends BatteryStats {
}
@GuardedBy("this")
- public void resetAllStatsCmdLocked() {
+ public void resetAllStatsAndHistoryLocked(int reason) {
final long mSecUptime = mClock.uptimeMillis();
long uptimeUs = mSecUptime * 1000;
long mSecRealtime = mClock.elapsedRealtime();
long realtimeUs = mSecRealtime * 1000;
- resetAllStatsLocked(mSecUptime, mSecRealtime, RESET_REASON_ADB_COMMAND);
+ resetAllStatsLocked(mSecUptime, mSecRealtime, reason);
pullPendingStateUpdatesLocked();
mHistory.writeHistoryItem(mSecRealtime, mSecUptime);
mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel = mBatteryLevel;
@@ -14051,6 +14166,100 @@ public class BatteryStatsImpl extends BatteryStats {
mRecordAllHistory = true;
}
+ /**
+ * Might reset battery stats if conditions are met. Assumed the device is currently plugged in.
+ */
+ @GuardedBy("this")
+ public void maybeResetWhilePluggedInLocked() {
+ final long elapsedRealtimeMs = mClock.elapsedRealtime();
+ if (shouldResetWhilePluggedInLocked(elapsedRealtimeMs)) {
+ Slog.i(TAG,
+ "Resetting due to long plug in duration. elapsed time = " + elapsedRealtimeMs
+ + " ms, last plug in time = " + mBatteryPluggedInRealTimeMs
+ + " ms, last reset time = " + mRealtimeStartUs / 1000);
+ resetAllStatsAndHistoryLocked(RESET_REASON_PLUGGED_IN_FOR_LONG_DURATION);
+ }
+
+ scheduleNextResetWhilePluggedInCheck();
+ }
+
+ @GuardedBy("this")
+ private void scheduleNextResetWhilePluggedInCheck() {
+ if (mLongPlugInAlarmInterface != null) {
+ final long timeoutMs = mClock.currentTimeMillis()
+ + mConstants.RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS
+ * DateUtils.HOUR_IN_MILLIS;
+ Calendar nextAlarm = Calendar.getInstance();
+ nextAlarm.setTimeInMillis(timeoutMs);
+
+ // Find the 2 AM the same day as the end of the minimum duration.
+ // This logic does not handle a Daylight Savings transition, or a timezone change
+ // while the alarm has been set. The need to reset after a long period while plugged
+ // in is not strict enough to warrant a well architected out solution.
+ nextAlarm.set(Calendar.MILLISECOND, 0);
+ nextAlarm.set(Calendar.SECOND, 0);
+ nextAlarm.set(Calendar.MINUTE, 0);
+ nextAlarm.set(Calendar.HOUR_OF_DAY, 2);
+ long nextTimeMs = nextAlarm.getTimeInMillis();
+ if (nextTimeMs < timeoutMs) {
+ // The 2AM on the day of the timeout, move on the next day.
+ nextTimeMs += DateUtils.DAY_IN_MILLIS;
+ }
+ mLongPlugInAlarmInterface.schedule(nextTimeMs, DateUtils.HOUR_IN_MILLIS);
+ }
+ }
+
+
+ @GuardedBy("this")
+ private boolean shouldResetWhilePluggedInLocked(long elapsedRealtimeMs) {
+ if (mNoAutoReset) return false;
+ if (!mSystemReady) return false;
+ if (!mHistory.isResetEnabled()) return false;
+
+ final long pluggedInThresholdMs = mBatteryPluggedInRealTimeMs
+ + mConstants.RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS
+ * DateUtils.HOUR_IN_MILLIS;
+ if (elapsedRealtimeMs >= pluggedInThresholdMs) {
+ // The device has been plugged in for a long time.
+ final long resetThresholdMs = mRealtimeStartUs / 1000
+ + mConstants.RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS
+ * DateUtils.HOUR_IN_MILLIS;
+ if (elapsedRealtimeMs >= resetThresholdMs) {
+ // And it has been a long time since the last reset.
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @GuardedBy("this")
+ private boolean shouldResetOnUnplugLocked(int batteryStatus, int batteryLevel) {
+ if (mNoAutoReset) return false;
+ if (!mSystemReady) return false;
+ if (!mHistory.isResetEnabled()) return false;
+ if (mBatteryStatsConfig.shouldResetOnUnplugHighBatteryLevel()) {
+ // Allow resetting due to currently being at high battery level
+ if (batteryStatus == BatteryManager.BATTERY_STATUS_FULL) return true;
+ if (batteryLevel >= 90) return true;
+ }
+ if (mBatteryStatsConfig.shouldResetOnUnplugAfterSignificantCharge()) {
+ // Allow resetting after a significant charge (from a very low level to a now very
+ // high level).
+ if (mDischargePlugLevel < 20 && batteryLevel >= 80) return true;
+ }
+ if (getHighDischargeAmountSinceCharge() >= 200) {
+ // Reset the stats if battery got partially charged and discharged repeatedly without
+ // ever reaching the full charge.
+ // This reset is done in order to prevent stats sessions from going on forever.
+ // Exceedingly long battery sessions would lead to an overflow of
+ // data structures such as mWakeupReasonStats.
+ return true;
+ }
+
+ return false;
+ }
+
@GuardedBy("this")
protected void setOnBatteryLocked(final long mSecRealtime, final long mSecUptime,
final boolean onBattery, final int oldStatus, final int level, final int chargeUah) {
@@ -14063,24 +14272,10 @@ public class BatteryStatsImpl extends BatteryStats {
final long realtimeUs = mSecRealtime * 1000;
final int screenState = mScreenState;
if (onBattery) {
- // We will reset our status if we are unplugging after the
- // battery was last full, or the level is at 100, or
- // we have gone through a significant charge (from a very low
- // level to a now very high level).
- // Also, we will reset the stats if battery got partially charged
- // and discharged repeatedly without ever reaching the full charge.
- // This reset is done in order to prevent stats sessions from going on forever.
- // Exceedingly long battery sessions would lead to an overflow of
- // data structures such as mWakeupReasonStats.
boolean reset = false;
- if (!mNoAutoReset && mSystemReady
- && (oldStatus == BatteryManager.BATTERY_STATUS_FULL
- || level >= 90
- || (mDischargeCurrentLevel < 20 && level >= 80)
- || getHighDischargeAmountSinceCharge() >= 200)
- && mHistory.isResetEnabled()) {
+ if (shouldResetOnUnplugLocked(oldStatus, level)) {
Slog.i(TAG, "Resetting battery stats: level=" + level + " status=" + oldStatus
- + " dischargeLevel=" + mDischargeCurrentLevel
+ + " dischargeLevel=" + mDischargePlugLevel
+ " lowAmount=" + getLowDischargeAmountSinceCharge()
+ " highAmount=" + getHighDischargeAmountSinceCharge());
// Before we write, collect a snapshot of the final aggregated
@@ -14140,6 +14335,9 @@ public class BatteryStatsImpl extends BatteryStats {
initActiveHistoryEventsLocked(mSecRealtime, mSecUptime);
}
mBatteryPluggedIn = false;
+ if (mLongPlugInAlarmInterface != null) {
+ mLongPlugInAlarmInterface.cancel();
+ }
mHistory.recordBatteryState(mSecRealtime, mSecUptime, level, mBatteryPluggedIn);
mDischargeCurrentLevel = mDischargeUnplugLevel = level;
if (Display.isOnState(screenState)) {
@@ -14163,6 +14361,7 @@ public class BatteryStatsImpl extends BatteryStats {
mOnBattery = mOnBatteryInternal = false;
pullPendingStateUpdatesLocked();
mBatteryPluggedIn = true;
+ mBatteryPluggedInRealTimeMs = mSecRealtime;
mHistory.recordBatteryState(mSecRealtime, mSecUptime, level, mBatteryPluggedIn);
mDischargeCurrentLevel = mDischargePlugLevel = level;
if (level < mDischargeUnplugLevel) {
@@ -14176,6 +14375,7 @@ public class BatteryStatsImpl extends BatteryStats {
mMaxChargeStepLevel = level;
mInitStepMode = mCurStepMode;
mModStepMode = 0;
+ scheduleNextResetWhilePluggedInCheck();
}
if (doWrite || (mLastWriteTimeMs + (60 * 1000)) < mSecRealtime) {
if (mStatsFile != null && !mHistory.isReadOnly()) {
@@ -15082,6 +15282,8 @@ public class BatteryStatsImpl extends BatteryStats {
"per_uid_modem_power_model";
public static final String KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION =
"phone_on_external_stats_collection";
+ public static final String KEY_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS =
+ "reset_while_plugged_in_minimum_duration_hours";
public static final String PER_UID_MODEM_POWER_MODEL_MOBILE_RADIO_ACTIVE_TIME_NAME =
"mobile_radio_active_time";
@@ -15131,6 +15333,8 @@ public class BatteryStatsImpl extends BatteryStats {
private static final int DEFAULT_PER_UID_MODEM_MODEL =
PER_UID_MODEM_POWER_MODEL_MODEM_ACTIVITY_INFO_RX_TX;
private static final boolean DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION = true;
+ // Little less than 2 days
+ private static final int DEFAULT_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS = 47;
public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME;
/* Do not set default value for KERNEL_UID_READERS_THROTTLE_TIME. Need to trigger an
@@ -15150,6 +15354,8 @@ public class BatteryStatsImpl extends BatteryStats {
public int PER_UID_MODEM_MODEL = DEFAULT_PER_UID_MODEM_MODEL;
public boolean PHONE_ON_EXTERNAL_STATS_COLLECTION =
DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION;
+ public int RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS =
+ DEFAULT_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS;
private ContentResolver mResolver;
private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -15235,6 +15441,10 @@ public class BatteryStatsImpl extends BatteryStats {
KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION,
DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION);
+ RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS = mParser.getInt(
+ KEY_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS,
+ DEFAULT_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS);
+
updateBatteryChargedDelayMsLocked();
onChange();
@@ -15306,6 +15516,8 @@ public class BatteryStatsImpl extends BatteryStats {
pw.println(getPerUidModemModelName(PER_UID_MODEM_MODEL));
pw.print(KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION); pw.print("=");
pw.println(PHONE_ON_EXTERNAL_STATS_COLLECTION);
+ pw.print(KEY_RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS); pw.print("=");
+ pw.println(RESET_WHILE_PLUGGED_IN_MINIMUM_DURATION_HOURS);
}
}
diff --git a/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java b/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java
index 080929729fe3..4a6c794cf11d 100644
--- a/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java
+++ b/services/core/java/com/android/server/timedetector/NetworkTimeUpdateService.java
@@ -115,7 +115,7 @@ public class NetworkTimeUpdateService extends Binder {
TimeDetectorInternal timeDetectorInternal =
LocalServices.getService(TimeDetectorInternal.class);
// Broadcast alarms sent by system are immutable
- Intent pollIntent = new Intent(ACTION_POLL, null);
+ Intent pollIntent = new Intent(ACTION_POLL, null).setPackage("android");
PendingIntent pendingPollIntent = PendingIntent.getBroadcast(mContext, POLL_REQUEST,
pollIntent, PendingIntent.FLAG_IMMUTABLE);
mRefreshCallbacks = new Engine.RefreshCallbacks() {
@@ -228,16 +228,14 @@ public class NetworkTimeUpdateService extends Binder {
}
private void onPollNetworkTime(@NonNull String reason) {
- // If we don't have any default network, don't bother.
Network network;
synchronized (mLock) {
network = mDefaultNetwork;
}
- if (network == null) return;
mWakeLock.acquire();
try {
- mEngine.refreshIfRequiredAndReschedule(network, reason, mRefreshCallbacks);
+ mEngine.refreshAndRescheduleIfRequired(network, reason, mRefreshCallbacks);
} finally {
mWakeLock.release();
}
@@ -338,10 +336,10 @@ public class NetworkTimeUpdateService extends Binder {
* Attempts to refresh the network time if required, i.e. if there isn't a recent-enough
* network time available. It must also schedule the next call. This is a blocking call.
*
- * @param network the network to use
+ * @param network the network to use, or null if no network is available
* @param reason the reason for the refresh (for logging)
*/
- void refreshIfRequiredAndReschedule(@NonNull Network network, @NonNull String reason,
+ void refreshAndRescheduleIfRequired(@Nullable Network network, @NonNull String reason,
@NonNull RefreshCallbacks refreshCallbacks);
void dump(@NonNull PrintWriter pw);
@@ -391,7 +389,7 @@ public class NetworkTimeUpdateService extends Binder {
/**
* Records the time of the last refresh attempt (successful or otherwise) by this service.
* This is used when scheduling the next refresh attempt. In cases where {@link
- * #refreshIfRequiredAndReschedule} is called too frequently, this will prevent each call
+ * #refreshAndRescheduleIfRequired} is called too frequently, this will prevent each call
* resulting in a network request. See also {@link #mShortPollingIntervalMillis}.
*
* <p>Time servers are a shared resource and so Android should avoid loading them.
@@ -443,9 +441,19 @@ public class NetworkTimeUpdateService extends Binder {
}
@Override
- public void refreshIfRequiredAndReschedule(
- @NonNull Network network, @NonNull String reason,
+ public void refreshAndRescheduleIfRequired(
+ @Nullable Network network, @NonNull String reason,
@NonNull RefreshCallbacks refreshCallbacks) {
+ if (network == null) {
+ // If we don't have any default network, don't do anything: When a new network
+ // is available then this method will be called again.
+ logToDebugAndDumpsys("refreshIfRequiredAndReschedule:"
+ + " reason=" + reason
+ + ": No default network available. No refresh attempted and no next"
+ + " attempt scheduled.");
+ return;
+ }
+
// Attempt to refresh the network time if there is no latest time result, or if the
// latest time result is considered too old.
NtpTrustedTime.TimeResult initialTimeResult = mNtpTrustedTime.getCachedTimeResult();
diff --git a/services/core/java/com/android/server/timedetector/NetworkTimeUpdateServiceShellCommand.java b/services/core/java/com/android/server/timedetector/NetworkTimeUpdateServiceShellCommand.java
index 410b50f8a88b..afc0bdd30f29 100644
--- a/services/core/java/com/android/server/timedetector/NetworkTimeUpdateServiceShellCommand.java
+++ b/services/core/java/com/android/server/timedetector/NetworkTimeUpdateServiceShellCommand.java
@@ -157,7 +157,7 @@ class NetworkTimeUpdateServiceShellCommand extends ShellCommand {
SET_SERVER_CONFIG_SERVER_ARG, SET_SERVER_CONFIG_SERVER_ARG,
SET_SERVER_CONFIG_TIMEOUT_ARG);
pw.printf(" NTP server URIs must be in the form \"ntp://hostname\" or"
- + " \"ntp://hostname:port\"");
+ + " \"ntp://hostname:port\"\n");
pw.printf(" %s\n", SHELL_COMMAND_RESET_SERVER_CONFIG);
pw.printf(" Resets/clears the NTP server config set via %s.\n",
SHELL_COMMAND_SET_SERVER_CONFIG);
diff --git a/services/core/java/com/android/server/timedetector/ServerFlags.java b/services/core/java/com/android/server/timedetector/ServerFlags.java
index 678222980ea4..28d34c26e0dd 100644
--- a/services/core/java/com/android/server/timedetector/ServerFlags.java
+++ b/services/core/java/com/android/server/timedetector/ServerFlags.java
@@ -304,7 +304,7 @@ public final class ServerFlags {
/**
* Returns an {@link Instant} from {@link DeviceConfig} from the system_time
- * namespace, returns the {@code defaultValue} if the value is missing or invalid.
+ * namespace, returns {@link Optional#empty()} if there is no explicit value set.
*/
@NonNull
public Optional<Instant> getOptionalInstant(@DeviceConfigKey String key) {
@@ -341,16 +341,17 @@ public final class ServerFlags {
}
/**
- * Returns a boolean value from {@link DeviceConfig} from the system_time
- * namespace, or {@code defaultValue} if there is no explicit value set.
+ * Returns a boolean value from {@link DeviceConfig} from the system_time namespace, or
+ * {@code defaultValue} if there is no explicit value set.
*/
public boolean getBoolean(@DeviceConfigKey String key, boolean defaultValue) {
return DeviceConfig.getBoolean(NAMESPACE_SYSTEM_TIME, key, defaultValue);
}
/**
- * Returns a positive duration from {@link DeviceConfig} from the system_time
- * namespace, or {@code defaultValue} if there is no explicit value set.
+ * Returns a positive duration from {@link DeviceConfig} from the system_time namespace,
+ * or {@code defaultValue} if there is no explicit value set or if the value is not a number or
+ * is negative.
*/
@Nullable
public Duration getDurationFromMillis(
diff --git a/services/core/java/com/android/server/vibrator/HalVibration.java b/services/core/java/com/android/server/vibrator/HalVibration.java
index 87f189aed592..b8032738c1af 100644
--- a/services/core/java/com/android/server/vibrator/HalVibration.java
+++ b/services/core/java/com/android/server/vibrator/HalVibration.java
@@ -155,7 +155,7 @@ final class HalVibration extends Vibration {
return mStatus != Status.RUNNING;
}
- /** Return true is effect is a repeating vibration. */
+ @Override
public boolean isRepeating() {
return mEffect.getDuration() == Long.MAX_VALUE;
}
diff --git a/services/core/java/com/android/server/vibrator/Vibration.java b/services/core/java/com/android/server/vibrator/Vibration.java
index 1cc0a4ff4b75..c6bd80f85f76 100644
--- a/services/core/java/com/android/server/vibrator/Vibration.java
+++ b/services/core/java/com/android/server/vibrator/Vibration.java
@@ -37,7 +37,7 @@ import java.util.concurrent.atomic.AtomicInteger;
/**
* The base class for all vibrations.
*/
-class Vibration {
+abstract class Vibration {
private static final SimpleDateFormat DEBUG_DATE_FORMAT =
new SimpleDateFormat("MM-dd HH:mm:ss.SSS");
// Used to generate globally unique vibration ids.
@@ -97,6 +97,9 @@ class Vibration {
this.callerInfo = callerInfo;
}
+ /** Return true if vibration is a repeating vibration. */
+ abstract boolean isRepeating();
+
/**
* Holds lightweight immutable info on the process that triggered the vibration. This data
* could potentially be kept in memory for a long time for bugreport dumpsys operations.
diff --git a/services/core/java/com/android/server/vibrator/VibratorManagerService.java b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
index 5756414a303d..cb7e54dda527 100644
--- a/services/core/java/com/android/server/vibrator/VibratorManagerService.java
+++ b/services/core/java/com/android/server/vibrator/VibratorManagerService.java
@@ -419,31 +419,28 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
if (DEBUG) {
Slog.d(TAG, "Starting vibrate for vibration " + vib.id);
}
- Vibration.CallerInfo ignoredByCallerInfo = null;
- Vibration.Status status;
// Check if user settings or DnD is set to ignore this vibration.
- status = shouldIgnoreVibrationLocked(vib.callerInfo);
-
- // Check if something has external control, assume it's more important.
- if ((status == null) && (mCurrentExternalVibration != null)) {
- status = Vibration.Status.IGNORED_FOR_EXTERNAL;
- ignoredByCallerInfo = mCurrentExternalVibration.callerInfo;
- }
+ Vibration.EndInfo vibrationEndInfo = shouldIgnoreVibrationLocked(vib.callerInfo);
// Check if ongoing vibration is more important than this vibration.
- if (status == null) {
- status = shouldIgnoreVibrationForOngoingLocked(vib);
- if (status != null) {
- ignoredByCallerInfo = mCurrentVibration.getVibration().callerInfo;
- }
+ if (vibrationEndInfo == null) {
+ vibrationEndInfo = shouldIgnoreVibrationForOngoingLocked(vib);
}
// If not ignored so far then try to start this vibration.
- if (status == null) {
+ if (vibrationEndInfo == null) {
final long ident = Binder.clearCallingIdentity();
try {
- if (mCurrentVibration != null) {
+ if (mCurrentExternalVibration != null) {
+ mCurrentExternalVibration.mute();
+ vib.stats.reportInterruptedAnotherVibration(
+ mCurrentExternalVibration.callerInfo);
+ endExternalVibrateLocked(
+ new Vibration.EndInfo(Vibration.Status.CANCELLED_SUPERSEDED,
+ vib.callerInfo),
+ /* continueExternalControl= */ false);
+ } else if (mCurrentVibration != null) {
if (mCurrentVibration.getVibration().canPipelineWith(vib)) {
// Don't cancel the current vibration if it's pipeline-able.
// Note that if there is a pending next vibration that can't be
@@ -461,17 +458,15 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
/* immediate= */ false);
}
}
- status = startVibrationLocked(vib);
+ vibrationEndInfo = startVibrationLocked(vib);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
// Ignored or failed to start the vibration, end it and report metrics right away.
- if (status != Vibration.Status.RUNNING) {
- endVibrationLocked(vib,
- new Vibration.EndInfo(status, ignoredByCallerInfo),
- /* shouldWriteStats= */ true);
+ if (vibrationEndInfo != null) {
+ endVibrationLocked(vib, vibrationEndInfo, /* shouldWriteStats= */ true);
}
return vib;
}
@@ -633,12 +628,13 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
HalVibration vib = mCurrentVibration.getVibration();
- Vibration.Status ignoreStatus = shouldIgnoreVibrationLocked(vib.callerInfo);
+ Vibration.EndInfo vibrationEndInfo = shouldIgnoreVibrationLocked(vib.callerInfo);
- if (inputDevicesChanged || (ignoreStatus != null)) {
+ if (inputDevicesChanged || (vibrationEndInfo != null)) {
if (DEBUG) {
Slog.d(TAG, "Canceling vibration because settings changed: "
- + (inputDevicesChanged ? "input devices changed" : ignoreStatus));
+ + (inputDevicesChanged ? "input devices changed"
+ : vibrationEndInfo.status));
}
mCurrentVibration.notifyCancelled(
new Vibration.EndInfo(Vibration.Status.CANCELLED_BY_SETTINGS_UPDATE),
@@ -662,8 +658,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
if (vibrator == null) {
continue;
}
- Vibration.Status ignoreStatus = shouldIgnoreVibrationLocked(vib.callerInfo);
- if (ignoreStatus == null) {
+ Vibration.EndInfo vibrationEndInfo = shouldIgnoreVibrationLocked(vib.callerInfo);
+ if (vibrationEndInfo == null) {
effect = mVibrationScaler.scale(effect, vib.callerInfo.attrs.getUsage());
} else {
// Vibration should not run, use null effect to remove registered effect.
@@ -674,7 +670,8 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
}
@GuardedBy("mLock")
- private Vibration.Status startVibrationLocked(HalVibration vib) {
+ @Nullable
+ private Vibration.EndInfo startVibrationLocked(HalVibration vib) {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "startVibrationLocked");
try {
vib.updateEffects(
@@ -682,7 +679,7 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
boolean inputDevicesAvailable = mInputDeviceDelegate.vibrateIfAvailable(
vib.callerInfo, vib.getEffect());
if (inputDevicesAvailable) {
- return Vibration.Status.FORWARDED_TO_INPUT_DEVICES;
+ return new Vibration.EndInfo(Vibration.Status.FORWARDED_TO_INPUT_DEVICES);
}
VibrationStepConductor conductor = new VibrationStepConductor(vib, mVibrationSettings,
@@ -697,14 +694,15 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
clearNextVibrationLocked(
new Vibration.EndInfo(Vibration.Status.IGNORED_SUPERSEDED, vib.callerInfo));
mNextVibration = conductor;
- return Vibration.Status.RUNNING;
+ return null;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
}
}
@GuardedBy("mLock")
- private Vibration.Status startVibrationOnThreadLocked(VibrationStepConductor conductor) {
+ @Nullable
+ private Vibration.EndInfo startVibrationOnThreadLocked(VibrationStepConductor conductor) {
Trace.traceBegin(Trace.TRACE_TAG_VIBRATOR, "startVibrationThreadLocked");
try {
HalVibration vib = conductor.getVibration();
@@ -717,15 +715,15 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
if (!mVibrationThread.runVibrationOnVibrationThread(mCurrentVibration)) {
// Shouldn't happen. The method call already logs a wtf.
mCurrentVibration = null; // Aborted.
- return Vibration.Status.IGNORED_ERROR_SCHEDULING;
+ return new Vibration.EndInfo(Vibration.Status.IGNORED_ERROR_SCHEDULING);
}
- return Vibration.Status.RUNNING;
+ return null;
case AppOpsManager.MODE_ERRORED:
Slog.w(TAG, "Start AppOpsManager operation errored for uid "
+ vib.callerInfo.uid);
- return Vibration.Status.IGNORED_ERROR_APP_OPS;
+ return new Vibration.EndInfo(Vibration.Status.IGNORED_ERROR_APP_OPS);
default:
- return Vibration.Status.IGNORED_APP_OPS;
+ return new Vibration.EndInfo(Vibration.Status.IGNORED_APP_OPS);
}
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIBRATOR);
@@ -849,39 +847,91 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
/**
* Check if given vibration should be ignored by this service because of the ongoing vibration.
*
- * @return One of Vibration.Status.IGNORED_* values if the vibration should be ignored, null
- * otherwise.
+ * @return a Vibration.EndInfo if the vibration should be ignored, null otherwise.
*/
@GuardedBy("mLock")
@Nullable
- private Vibration.Status shouldIgnoreVibrationForOngoingLocked(HalVibration vib) {
- if (mCurrentVibration == null || vib.isRepeating()) {
- // Incoming repeating vibrations always take precedence over ongoing vibrations.
- return null;
+ private Vibration.EndInfo shouldIgnoreVibrationForOngoingLocked(Vibration vib) {
+ if (mCurrentExternalVibration != null) {
+ return shouldIgnoreVibrationForOngoing(vib, mCurrentExternalVibration);
}
- HalVibration currentVibration = mCurrentVibration.getVibration();
- if (currentVibration.hasEnded() || mCurrentVibration.wasNotifiedToCancel()) {
- // Current vibration has ended or is cancelling, should not block incoming vibrations.
- return null;
+ if (mNextVibration != null) {
+ Vibration.EndInfo vibrationEndInfo = shouldIgnoreVibrationForOngoing(vib,
+ mNextVibration.getVibration());
+ if (vibrationEndInfo != null) {
+ // Next vibration has higher importance than the new one, so the new vibration
+ // should be ignored.
+ return vibrationEndInfo;
+ }
+ }
+
+ if (mCurrentVibration != null) {
+ HalVibration currentVibration = mCurrentVibration.getVibration();
+ if (currentVibration.hasEnded() || mCurrentVibration.wasNotifiedToCancel()) {
+ // Current vibration has ended or is cancelling, should not block incoming
+ // vibrations.
+ return null;
+ }
+
+ return shouldIgnoreVibrationForOngoing(vib, currentVibration);
}
- int currentUsage = currentVibration.callerInfo.attrs.getUsage();
- int newUsage = vib.callerInfo.attrs.getUsage();
- if (getVibrationImportance(currentUsage) > getVibrationImportance(newUsage)) {
- // Current vibration has higher importance than this one and should not be cancelled.
- return Vibration.Status.IGNORED_FOR_HIGHER_IMPORTANCE;
+ return null;
+ }
+
+ /**
+ * Checks if the ongoing vibration has higher importance than the new one. If they have similar
+ * importance, then {@link Vibration#isRepeating()} is used as a tiebreaker.
+ *
+ * @return a Vibration.EndInfo if the vibration should be ignored, null otherwise.
+ */
+ @Nullable
+ private static Vibration.EndInfo shouldIgnoreVibrationForOngoing(
+ @NonNull Vibration newVibration, @NonNull Vibration ongoingVibration) {
+
+ int newVibrationImportance = getVibrationImportance(newVibration);
+ int ongoingVibrationImportance = getVibrationImportance(ongoingVibration);
+
+ if (newVibrationImportance > ongoingVibrationImportance) {
+ // New vibration has higher importance and should not be ignored.
+ return null;
}
- if (currentVibration.isRepeating()) {
- // Current vibration is repeating, assume it's more important.
- return Vibration.Status.IGNORED_FOR_ONGOING;
+ if (ongoingVibrationImportance > newVibrationImportance) {
+ // Existing vibration has higher importance and should not be cancelled.
+ return new Vibration.EndInfo(Vibration.Status.IGNORED_FOR_HIGHER_IMPORTANCE,
+ ongoingVibration.callerInfo);
}
+ // Same importance, use repeating as a tiebreaker.
+ if (ongoingVibration.isRepeating() && !newVibration.isRepeating()) {
+ // Ongoing vibration is repeating and new one is not, give priority to ongoing
+ return new Vibration.EndInfo(Vibration.Status.IGNORED_FOR_ONGOING,
+ ongoingVibration.callerInfo);
+ }
+ // New vibration is repeating or this is a complete tie between them,
+ // give priority to new vibration.
return null;
}
- private static int getVibrationImportance(@VibrationAttributes.Usage int usage) {
+ /**
+ * Gets the vibration importance based on usage. In the case where usage is unknown, it maps
+ * repeating vibrations to ringtones and non-repeating vibrations to touches.
+ *
+ * @return a numeric representation for the vibration importance, larger values represent a
+ * higher importance
+ */
+ private static int getVibrationImportance(Vibration vibration) {
+ int usage = vibration.callerInfo.attrs.getUsage();
+ if (usage == VibrationAttributes.USAGE_UNKNOWN) {
+ if (vibration.isRepeating()) {
+ usage = VibrationAttributes.USAGE_RINGTONE;
+ } else {
+ usage = VibrationAttributes.USAGE_TOUCH;
+ }
+ }
+
switch (usage) {
case VibrationAttributes.USAGE_RINGTONE:
return 5;
@@ -897,7 +947,6 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
return 1;
case VibrationAttributes.USAGE_MEDIA:
case VibrationAttributes.USAGE_TOUCH:
- case VibrationAttributes.USAGE_UNKNOWN:
default:
return 0;
}
@@ -906,15 +955,14 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
/**
* Check if given vibration should be ignored by this service.
*
- * @return One of Vibration.Status.IGNORED_* values if the vibration should be ignored, null
- * otherwise.
+ * @return a Vibration.EndInfo if the vibration should be ignored, null otherwise.
*/
@GuardedBy("mLock")
@Nullable
- private Vibration.Status shouldIgnoreVibrationLocked(Vibration.CallerInfo callerInfo) {
+ private Vibration.EndInfo shouldIgnoreVibrationLocked(Vibration.CallerInfo callerInfo) {
Vibration.Status statusFromSettings = mVibrationSettings.shouldIgnoreVibration(callerInfo);
if (statusFromSettings != null) {
- return statusFromSettings;
+ return new Vibration.EndInfo(statusFromSettings);
}
int mode = checkAppOpModeLocked(callerInfo);
@@ -922,9 +970,9 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
if (mode == AppOpsManager.MODE_ERRORED) {
// We might be getting calls from within system_server, so we don't actually
// want to throw a SecurityException here.
- return Vibration.Status.IGNORED_ERROR_APP_OPS;
+ return new Vibration.EndInfo(Vibration.Status.IGNORED_ERROR_APP_OPS);
} else {
- return Vibration.Status.IGNORED_APP_OPS;
+ return new Vibration.EndInfo(Vibration.Status.IGNORED_APP_OPS);
}
}
@@ -1327,11 +1375,12 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
if (mNextVibration != null) {
VibrationStepConductor nextConductor = mNextVibration;
mNextVibration = null;
- Vibration.Status status = startVibrationOnThreadLocked(nextConductor);
- if (status != Vibration.Status.RUNNING) {
+ Vibration.EndInfo vibrationEndInfo = startVibrationOnThreadLocked(
+ nextConductor);
+ if (vibrationEndInfo != null) {
// Failed to start the vibration, end it and report metrics right away.
endVibrationLocked(nextConductor.getVibration(),
- new Vibration.EndInfo(status), /* shouldWriteStats= */ true);
+ vibrationEndInfo, /* shouldWriteStats= */ true);
}
}
}
@@ -1471,6 +1520,16 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
externalVibration.getVibrationAttributes().getUsage(), mStatus, stats,
completionUptimeMillis);
}
+
+ @Override
+ boolean isRepeating() {
+ // We don't currently know if the external vibration is repeating, so we just use a
+ // heuristic based on the usage. Ideally this would be propagated in the
+ // ExternalVibration.
+ int usage = externalVibration.getVibrationAttributes().getUsage();
+ return usage == VibrationAttributes.USAGE_RINGTONE
+ || usage == VibrationAttributes.USAGE_ALARM;
+ }
}
/** Wrapper around the static-native methods of {@link VibratorManagerService} for tests. */
@@ -1672,19 +1731,29 @@ public class VibratorManagerService extends IVibratorManagerService.Stub {
synchronized (mLock) {
// TODO(b/243604888): propagating displayID from IExternalVibration instead of
// using INVALID_DISPLAY for all external vibrations.
- Vibration.Status ignoreStatus = shouldIgnoreVibrationLocked(vibHolder.callerInfo);
- if (ignoreStatus != null) {
- vibHolder.scale = IExternalVibratorService.SCALE_MUTE;
- // Failed to start the vibration, end it and report metrics right away.
- endVibrationAndWriteStatsLocked(vibHolder, new Vibration.EndInfo(ignoreStatus));
- return vibHolder.scale;
- }
- if (mCurrentExternalVibration != null
+ Vibration.EndInfo vibrationEndInfo = shouldIgnoreVibrationLocked(
+ vibHolder.callerInfo);
+
+ if (vibrationEndInfo == null
+ && mCurrentExternalVibration != null
&& mCurrentExternalVibration.isHoldingSameVibration(vib)) {
// We are already playing this external vibration, so we can return the same
// scale calculated in the previous call to this method.
return mCurrentExternalVibration.scale;
}
+
+ if (vibrationEndInfo == null) {
+ // Check if ongoing vibration is more important than this vibration.
+ vibrationEndInfo = shouldIgnoreVibrationForOngoingLocked(vibHolder);
+ }
+
+ if (vibrationEndInfo != null) {
+ vibHolder.scale = IExternalVibratorService.SCALE_MUTE;
+ // Failed to start the vibration, end it and report metrics right away.
+ endVibrationAndWriteStatsLocked(vibHolder, vibrationEndInfo);
+ return vibHolder.scale;
+ }
+
if (mCurrentExternalVibration == null) {
// If we're not under external control right now, then cancel any normal
// vibration that may be playing and ready the vibrator for external control.
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperDataParser.java b/services/core/java/com/android/server/wallpaper/WallpaperDataParser.java
index 7923bb216016..799d14944650 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperDataParser.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperDataParser.java
@@ -29,6 +29,7 @@ import static com.android.server.wallpaper.WallpaperUtils.makeWallpaperIdLocked;
import android.annotation.Nullable;
import android.app.WallpaperColors;
+import android.app.WallpaperManager.SetWallpaperFlags;
import android.app.backup.WallpaperBackupHelper;
import android.content.ComponentName;
import android.content.Context;
@@ -124,6 +125,8 @@ class WallpaperDataParser {
}
/**
+ * TODO(b/197814683) adapt comment once flag is removed
+ *
* Load the system wallpaper (and the lock wallpaper, if it exists) from disk
* @param userId the id of the user for which the wallpaper should be loaded
* @param keepDimensionHints if false, parse and set the
@@ -132,17 +135,21 @@ class WallpaperDataParser {
* If null, a new object will be created.
* @param lockWallpaper the lock wallpaper object to reuse to do the modifications.
* If null, a new object will be created.
+ * @param which The wallpaper(s) to load. If {@link #mEnableSeparateLockScreenEngine} is false,
+ * this flag has no effect and both wallpapers will always be loaded.
* @return a {@link WallpaperLoadingResult} object containing the wallpaper data.
* This object will contain the {@code wallpaper} and
* {@code lockWallpaper} provided as parameters, if they are not null.
*/
public WallpaperLoadingResult loadSettingsLocked(int userId, boolean keepDimensionHints,
- WallpaperData wallpaper, WallpaperData lockWallpaper) {
+ WallpaperData wallpaper, WallpaperData lockWallpaper, @SetWallpaperFlags int which) {
JournaledFile journal = makeJournaledFile(userId);
FileInputStream stream = null;
File file = journal.chooseForRead();
boolean migrateFromOld = wallpaper == null;
+ boolean loadSystem = !mEnableSeparateLockScreenEngine || (which & FLAG_SYSTEM) != 0;
+ boolean loadLock = !mEnableSeparateLockScreenEngine || (which & FLAG_LOCK) != 0;
// don't reuse the wallpaper objects in the new version
if (mEnableSeparateLockScreenEngine) {
@@ -150,7 +157,7 @@ class WallpaperDataParser {
lockWallpaper = null;
}
- if (wallpaper == null) {
+ if (wallpaper == null && loadSystem) {
// Do this once per boot
if (migrateFromOld) migrateFromOld();
wallpaper = new WallpaperData(userId, FLAG_SYSTEM);
@@ -176,8 +183,8 @@ class WallpaperDataParser {
type = parser.next();
if (type == XmlPullParser.START_TAG) {
String tag = parser.getName();
- if ("wp".equals(tag)
- || ("kwp".equals(tag) && mEnableSeparateLockScreenEngine)) {
+ if (("wp".equals(tag) && loadSystem)
+ || ("kwp".equals(tag) && mEnableSeparateLockScreenEngine && loadLock)) {
if ("kwp".equals(tag) && lockWallpaper == null) {
lockWallpaper = new WallpaperData(userId, FLAG_LOCK);
@@ -206,9 +213,8 @@ class WallpaperDataParser {
Slog.v(TAG, "mNextWallpaperComponent:"
+ wallpaper.nextWallpaperComponent);
}
- } else if ("kwp".equals(tag)) {
- // keyguard-specific wallpaper for this user
-
+ } else if ("kwp".equals(tag) && !mEnableSeparateLockScreenEngine) {
+ // keyguard-specific wallpaper for this user (legacy code)
if (lockWallpaper == null) {
lockWallpaper = new WallpaperData(userId, FLAG_LOCK);
}
@@ -232,29 +238,32 @@ class WallpaperDataParser {
}
IoUtils.closeQuietly(stream);
- if (!success) {
- wallpaper.cropHint.set(0, 0, 0, 0);
- wpdData.mPadding.set(0, 0, 0, 0);
- wallpaper.name = "";
- lockWallpaper = null;
- } else {
- if (wallpaper.wallpaperId <= 0) {
- wallpaper.wallpaperId = makeWallpaperIdLocked();
- if (DEBUG) {
- Slog.w(TAG, "Didn't set wallpaper id in loadSettingsLocked(" + userId
- + "); now " + wallpaper.wallpaperId);
+ mWallpaperDisplayHelper.ensureSaneWallpaperDisplaySize(wpdData, DEFAULT_DISPLAY);
+
+ if (loadSystem) {
+ if (!success) {
+ wallpaper.cropHint.set(0, 0, 0, 0);
+ wpdData.mPadding.set(0, 0, 0, 0);
+ wallpaper.name = "";
+ } else {
+ if (wallpaper.wallpaperId <= 0) {
+ wallpaper.wallpaperId = makeWallpaperIdLocked();
+ if (DEBUG) {
+ Slog.w(TAG, "Didn't set wallpaper id in loadSettingsLocked(" + userId
+ + "); now " + wallpaper.wallpaperId);
+ }
}
}
+ ensureSaneWallpaperData(wallpaper);
+ wallpaper.mWhich = lockWallpaper != null ? FLAG_SYSTEM : FLAG_SYSTEM | FLAG_LOCK;
}
- mWallpaperDisplayHelper.ensureSaneWallpaperDisplaySize(wpdData, DEFAULT_DISPLAY);
- ensureSaneWallpaperData(wallpaper);
- if (lockWallpaper != null) {
- ensureSaneWallpaperData(lockWallpaper);
- lockWallpaper.mWhich = FLAG_LOCK;
- wallpaper.mWhich = FLAG_SYSTEM;
- } else {
- wallpaper.mWhich = FLAG_SYSTEM | FLAG_LOCK;
+ if (loadLock) {
+ if (!success) lockWallpaper = null;
+ if (lockWallpaper != null) {
+ ensureSaneWallpaperData(lockWallpaper);
+ lockWallpaper.mWhich = FLAG_LOCK;
+ }
}
return new WallpaperLoadingResult(wallpaper, lockWallpaper, success);
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index d7829c844367..ac03808deba1 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -297,7 +297,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
if (DEBUG) {
Slog.v(TAG, "Wallpaper restore; reloading metadata");
}
- loadSettingsLocked(wallpaper.userId, true);
+ loadSettingsLocked(wallpaper.userId, true, FLAG_SYSTEM | FLAG_LOCK);
}
if (DEBUG) {
Slog.v(TAG, "Wallpaper written; generating crop");
@@ -440,7 +440,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
if (DEBUG) {
Slog.v(TAG, "moved-to, therefore restore; reloading metadata");
}
- loadSettingsLocked(wallpaper.userId, true);
+ loadSettingsLocked(wallpaper.userId, true, FLAG_SYSTEM | FLAG_LOCK);
}
mWallpaperCropper.generateCrop(wallpaper);
if (DEBUG) {
@@ -772,7 +772,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
DisplayConnector connector =
targetWallpaper.connection.getDisplayConnectorOrCreate(displayId);
if (connector == null) return;
- connector.disconnectLocked();
+ connector.disconnectLocked(targetWallpaper.connection);
targetWallpaper.connection.removeDisplayConnector(displayId);
mWallpaperDisplayHelper.removeDisplayData(displayId);
}
@@ -859,7 +859,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
if (fallbackConnection.mDisplayConnector.size() != 0) {
fallbackConnection.forEachDisplayConnector(connector -> {
if (connector.mEngine != null) {
- connector.disconnectLocked();
+ connector.disconnectLocked(fallbackConnection);
}
});
fallbackConnection.mDisplayConnector.clear();
@@ -940,16 +940,14 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
t.traceEnd();
}
- void disconnectLocked() {
+ void disconnectLocked(WallpaperConnection connection) {
if (DEBUG) Slog.v(TAG, "Removing window token: " + mToken);
mWindowManagerInternal.removeWindowToken(mToken, false/* removeWindows */,
mDisplayId);
try {
- if (mEngine != null) {
- mEngine.destroy();
- }
+ connection.mService.detach(mToken);
} catch (RemoteException e) {
- Slog.w(TAG, "Engine.destroy() threw a RemoteException");
+ Slog.w(TAG, "connection.mService.destroy() threw a RemoteException");
}
mEngine = null;
}
@@ -1249,12 +1247,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
synchronized (mLock) {
final DisplayConnector connector = getDisplayConnectorOrCreate(displayId);
if (connector == null) {
- try {
- engine.destroy();
- } catch (RemoteException e) {
- Slog.w(TAG, "Failed to destroy engine", e);
- }
- return;
+ throw new IllegalStateException("Connector has already been destroyed");
}
connector.mEngine = engine;
connector.ensureStatusHandled();
@@ -1628,7 +1621,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
// Initialize state from the persistent store, then guarantee that the
// WallpaperData for the system imagery is instantiated & active, creating
// it from defaults if necessary.
- loadSettingsLocked(UserHandle.USER_SYSTEM, false);
+ loadSettingsLocked(UserHandle.USER_SYSTEM, false, FLAG_SYSTEM | FLAG_LOCK);
getWallpaperSafeLocked(UserHandle.USER_SYSTEM, FLAG_SYSTEM);
}
@@ -1943,7 +1936,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
wallpaper = mWallpaperMap.get(userId);
if (wallpaper == null) {
// Might need to bring it in the first time to establish our rewrite
- loadSettingsLocked(userId, false);
+ loadSettingsLocked(userId, false, FLAG_SYSTEM);
wallpaper = mWallpaperMap.get(userId);
}
}
@@ -2041,7 +2034,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
WallpaperData wd = mWallpaperMap.get(user.id);
if (wd == null) {
// User hasn't started yet, so load their settings to peek at the wallpaper
- loadSettingsLocked(user.id, false);
+ loadSettingsLocked(user.id, false, FLAG_SYSTEM | FLAG_LOCK);
wd = mWallpaperMap.get(user.id);
}
if (wd != null && name.equals(wd.name)) {
@@ -2917,8 +2910,16 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
liveSync.complete();
}
};
+
+ /*
+ * If we have a shared system+lock wallpaper, and we reapply the same wallpaper
+ * to system only, force rebind: the current wallpaper will be migrated to lock
+ * and a new engine with the same wallpaper will be applied to system.
+ */
+ boolean forceRebind = same && systemIsBoth && which == FLAG_SYSTEM;
+
boolean bindSuccess = bindWallpaperComponentLocked(name, /* force */
- false, /* fromUser */ true, newWallpaper, callback);
+ forceRebind, /* fromUser */ true, newWallpaper, callback);
if (bindSuccess) {
if (!same) {
newWallpaper.primaryColors = null;
@@ -3261,20 +3262,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
}
wallpaper.connection.mReply = null;
}
- try {
- // It can be null if user switching happens before service connection.
- if (wallpaper.connection.mService != null) {
- wallpaper.connection.mService.detach();
- }
- } catch (RemoteException e) {
- Slog.w(TAG, "Failed detaching wallpaper service ", e);
- }
- try {
- mContext.unbindService(wallpaper.connection);
- } catch (IllegalArgumentException e) {
- Slog.w(TAG, "Attempted to unbind unregistered service");
- }
- wallpaper.connection.forEachDisplayConnector(DisplayConnector::disconnectLocked);
+ wallpaper.connection.forEachDisplayConnector(
+ connector -> connector.disconnectLocked(wallpaper.connection));
wallpaper.connection.mService = null;
wallpaper.connection.mDisplayConnector.clear();
@@ -3284,6 +3273,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
mContext.getMainThreadHandler().removeCallbacks(
wallpaper.connection.mTryToRebindRunnable);
+ mContext.unbindService(wallpaper.connection);
wallpaper.connection = null;
if (wallpaper == mLastWallpaper) {
mLastWallpaper = null;
@@ -3452,7 +3442,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
if (wallpaper == null) {
// common case, this is the first lookup post-boot of the system or
// unified lock, so we bring up the saved state lazily now and recheck.
- loadSettingsLocked(userId, false);
+ int whichLoad = (which == FLAG_LOCK) ? FLAG_LOCK : FLAG_SYSTEM;
+ loadSettingsLocked(userId, false, whichLoad);
wallpaper = whichSet.get(userId);
if (wallpaper == null) {
// if it's still null here, this is likely a lock-only operation and there is not
@@ -3473,18 +3464,23 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
return wallpaper;
}
- private void loadSettingsLocked(int userId, boolean keepDimensionHints) {
+ private void loadSettingsLocked(int userId, boolean keepDimensionHints, int which) {
initializeFallbackWallpaper();
WallpaperData wallpaperData = mWallpaperMap.get(userId);
WallpaperData lockWallpaperData = mLockWallpaperMap.get(userId);
WallpaperDataParser.WallpaperLoadingResult result = mWallpaperDataParser.loadSettingsLocked(
- userId, keepDimensionHints, wallpaperData, lockWallpaperData);
+ userId, keepDimensionHints, wallpaperData, lockWallpaperData, which);
- mWallpaperMap.put(userId, result.getSystemWallpaperData());
- if (result.success()) {
- mLockWallpaperMap.put(userId, result.getLockWallpaperData());
- } else {
- mLockWallpaperMap.remove(userId);
+ boolean updateSystem = !mEnableSeparateLockScreenEngine || (which & FLAG_SYSTEM) != 0;
+ boolean updateLock = !mEnableSeparateLockScreenEngine || (which & FLAG_LOCK) != 0;
+
+ if (updateSystem) mWallpaperMap.put(userId, result.getSystemWallpaperData());
+ if (updateLock) {
+ if (result.success()) {
+ mLockWallpaperMap.put(userId, result.getLockWallpaperData());
+ } else {
+ mLockWallpaperMap.remove(userId);
+ }
}
}
@@ -3511,7 +3507,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub
WallpaperData wallpaper = null;
boolean success = false;
synchronized (mLock) {
- loadSettingsLocked(UserHandle.USER_SYSTEM, false);
+ loadSettingsLocked(UserHandle.USER_SYSTEM, false, FLAG_SYSTEM | FLAG_LOCK);
wallpaper = mWallpaperMap.get(UserHandle.USER_SYSTEM);
wallpaper.wallpaperId = makeWallpaperIdLocked(); // always bump id at restore
wallpaper.allowBackup = true; // by definition if it was restored
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 3545747a67e3..d21274a7b6ba 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2159,7 +2159,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
boolean appActivityEmbeddingEnabled = false;
try {
- appActivityEmbeddingEnabled = WindowManagerService.sWindowExtensionsEnabled
+ appActivityEmbeddingEnabled = WindowManager.hasWindowExtensionsEnabled()
&& mAtmService.mContext.getPackageManager()
.getProperty(PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED, packageName)
.getBoolean();
@@ -5225,7 +5225,16 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
Debug.getCallers(6));
// Before setting mVisibleRequested so we can track changes.
- mTransitionController.collect(this);
+ boolean isCollecting = false;
+ if (mTransitionController.isShellTransitionsEnabled()) {
+ isCollecting = mTransitionController.isCollecting();
+ if (isCollecting) {
+ mTransitionController.collect(this);
+ } else {
+ Slog.e(TAG, "setVisibility=" + visible + " while transition is not collecting "
+ + this + " caller=" + Debug.getCallers(8));
+ }
+ }
onChildVisibilityRequested(visible);
@@ -5297,9 +5306,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
// Defer committing visibility until transition starts.
- if (inTransition()) {
- if (!visible && mTransitionController.inPlayingTransition(this)
- && mTransitionController.isCollecting(this)) {
+ if (isCollecting) {
+ // It may be occluded by the activity above that calls convertFromTranslucent().
+ if (!visible && mTransitionController.inPlayingTransition(this)) {
mTransitionChangeFlags |= FLAG_IS_OCCLUDED;
}
return;
@@ -5319,11 +5328,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
* Then its visibility will be committed until the transition is ready.
*/
private boolean deferCommitVisibilityChange(boolean visible) {
+ if (mTransitionController.isShellTransitionsEnabled()) {
+ // Shell transition doesn't use opening/closing sets.
+ return false;
+ }
if (!mDisplayContent.mAppTransition.isTransitionSet()) {
- if (mTransitionController.isShellTransitionsEnabled()) {
- // Shell transition doesn't use opening/closing sets.
- return false;
- }
// Defer committing visibility for non-home app which is animating by recents.
if (isActivityTypeHome() || !isAnimating(PARENTS, ANIMATION_TYPE_RECENTS)) {
return false;
@@ -7978,6 +7987,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
/**
+ * @return The {@code true} if the current instance has {@link mCompatDisplayInsets} without
+ * considering the inheritance implemented in {@link #getCompatDisplayInsets()}
+ */
+ boolean hasCompatDisplayInsetsWithoutInheritance() {
+ return mCompatDisplayInsets != null;
+ }
+
+ /**
* @return {@code true} if this activity is in size compatibility mode that uses the different
* density than its parent or its bounds don't fit in parent naturally.
*/
@@ -7985,7 +8002,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (mInSizeCompatModeForBounds) {
return true;
}
- if (mCompatDisplayInsets == null || !shouldCreateCompatDisplayInsets()
+ if (getCompatDisplayInsets() == null || !shouldCreateCompatDisplayInsets()
// The orientation is different from parent when transforming.
|| isFixedRotationTransforming()) {
return false;
@@ -8056,11 +8073,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
private void updateCompatDisplayInsets() {
- if (mLetterboxUiController.hasInheritedLetterboxBehavior()) {
- mCompatDisplayInsets = mLetterboxUiController.getInheritedCompatDisplayInsets();
- return;
- }
- if (mCompatDisplayInsets != null || !shouldCreateCompatDisplayInsets()) {
+ if (getCompatDisplayInsets() != null || !shouldCreateCompatDisplayInsets()) {
// The override configuration is set only once in size compatibility mode.
return;
}
@@ -8123,9 +8136,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
@Override
float getCompatScale() {
- if (mLetterboxUiController.hasInheritedLetterboxBehavior()) {
- return mLetterboxUiController.getInheritedSizeCompatScale();
- }
return hasSizeCompatBounds() ? mSizeCompatScale : super.getCompatScale();
}
@@ -8172,7 +8182,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
resolveFixedOrientationConfiguration(newParentConfiguration);
}
- if (mCompatDisplayInsets != null) {
+ if (getCompatDisplayInsets() != null) {
resolveSizeCompatModeConfiguration(newParentConfiguration);
} else if (inMultiWindowMode() && !isFixedOrientationLetterboxAllowed) {
// We ignore activities' requested orientation in multi-window modes. They may be
@@ -8190,7 +8200,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
resolveAspectRatioRestriction(newParentConfiguration);
}
- if (isFixedOrientationLetterboxAllowed || mCompatDisplayInsets != null
+ if (isFixedOrientationLetterboxAllowed || getCompatDisplayInsets() != null
// In fullscreen, can be letterboxed for aspect ratio.
|| !inMultiWindowMode()) {
updateResolvedBoundsPosition(newParentConfiguration);
@@ -8198,7 +8208,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
boolean isIgnoreOrientationRequest = mDisplayContent != null
&& mDisplayContent.getIgnoreOrientationRequest();
- if (mCompatDisplayInsets == null // for size compat mode set in updateCompatDisplayInsets
+ if (getCompatDisplayInsets() == null
+ // for size compat mode set in updateCompatDisplayInsets
// Fixed orientation letterboxing is possible on both large screen devices
// with ignoreOrientationRequest enabled and on phones in split screen even with
// ignoreOrientationRequest disabled.
@@ -8244,7 +8255,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
info.neverSandboxDisplayApis(sConstrainDisplayApisConfig),
info.alwaysSandboxDisplayApis(sConstrainDisplayApisConfig),
!matchParentBounds(),
- mCompatDisplayInsets != null,
+ getCompatDisplayInsets() != null,
shouldCreateCompatDisplayInsets());
}
resolvedConfig.windowConfiguration.setMaxBounds(mTmpBounds);
@@ -8551,8 +8562,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
|| orientationRespectedWithInsets)) {
return;
}
+ final CompatDisplayInsets compatDisplayInsets = getCompatDisplayInsets();
- if (mCompatDisplayInsets != null && !mCompatDisplayInsets.mIsInFixedOrientationLetterbox) {
+ if (compatDisplayInsets != null && !compatDisplayInsets.mIsInFixedOrientationLetterbox) {
// App prefers to keep its original size.
// If the size compat is from previous fixed orientation letterboxing, we may want to
// have fixed orientation letterbox again, otherwise it will show the size compat
@@ -8607,9 +8619,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mIsAspectRatioApplied = applyAspectRatio(resolvedBounds, containingBoundsWithInsets,
containingBounds, desiredAspectRatio);
- if (mCompatDisplayInsets != null) {
- mCompatDisplayInsets.getBoundsByRotation(
- mTmpBounds, newParentConfig.windowConfiguration.getRotation());
+ if (compatDisplayInsets != null) {
+ compatDisplayInsets.getBoundsByRotation(mTmpBounds,
+ newParentConfig.windowConfiguration.getRotation());
if (resolvedBounds.width() != mTmpBounds.width()
|| resolvedBounds.height() != mTmpBounds.height()) {
// The app shouldn't be resized, we only do fixed orientation letterboxing if the
@@ -8623,7 +8635,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Calculate app bounds using fixed orientation bounds because they will be needed later
// for comparison with size compat app bounds in {@link resolveSizeCompatModeConfiguration}.
getTaskFragment().computeConfigResourceOverrides(getResolvedOverrideConfiguration(),
- newParentConfig, mCompatDisplayInsets);
+ newParentConfig, compatDisplayInsets);
mLetterboxBoundsForFixedOrientationAndAspectRatio = new Rect(resolvedBounds);
}
@@ -8680,13 +8692,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
? requestedOrientation
// We should use the original orientation of the activity when possible to avoid
// forcing the activity in the opposite orientation.
- : mCompatDisplayInsets.mOriginalRequestedOrientation != ORIENTATION_UNDEFINED
- ? mCompatDisplayInsets.mOriginalRequestedOrientation
+ : getCompatDisplayInsets().mOriginalRequestedOrientation != ORIENTATION_UNDEFINED
+ ? getCompatDisplayInsets().mOriginalRequestedOrientation
: newParentConfiguration.orientation;
int rotation = newParentConfiguration.windowConfiguration.getRotation();
final boolean isFixedToUserRotation = mDisplayContent == null
|| mDisplayContent.getDisplayRotation().isFixedToUserRotation();
- if (!isFixedToUserRotation && !mCompatDisplayInsets.mIsFloating) {
+ if (!isFixedToUserRotation && !getCompatDisplayInsets().mIsFloating) {
// Use parent rotation because the original display can be rotated.
resolvedConfig.windowConfiguration.setRotation(rotation);
} else {
@@ -8702,11 +8714,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// rely on them to contain the original and unchanging width and height of the app.
final Rect containingAppBounds = new Rect();
final Rect containingBounds = mTmpBounds;
- mCompatDisplayInsets.getContainerBounds(containingAppBounds, containingBounds, rotation,
+ getCompatDisplayInsets().getContainerBounds(containingAppBounds, containingBounds, rotation,
orientation, orientationRequested, isFixedToUserRotation);
resolvedBounds.set(containingBounds);
// The size of floating task is fixed (only swap), so the aspect ratio is already correct.
- if (!mCompatDisplayInsets.mIsFloating) {
+ if (!getCompatDisplayInsets().mIsFloating) {
mIsAspectRatioApplied =
applyAspectRatio(resolvedBounds, containingAppBounds, containingBounds);
}
@@ -8715,7 +8727,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// are calculated in compat container space. The actual position on screen will be applied
// later, so the calculation is simpler that doesn't need to involve offset from parent.
getTaskFragment().computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
- mCompatDisplayInsets);
+ getCompatDisplayInsets());
// Use current screen layout as source because the size of app is independent to parent.
resolvedConfig.screenLayout = computeScreenLayout(
getConfiguration().screenLayout, resolvedConfig.screenWidthDp,
@@ -8750,14 +8762,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Calculates the scale the size compatibility bounds into the region which is available
// to application.
- final int contentW = resolvedAppBounds.width();
- final int contentH = resolvedAppBounds.height();
- final int viewportW = containerAppBounds.width();
- final int viewportH = containerAppBounds.height();
final float lastSizeCompatScale = mSizeCompatScale;
- // Only allow to scale down.
- mSizeCompatScale = (contentW <= viewportW && contentH <= viewportH)
- ? 1f : Math.min((float) viewportW / contentW, (float) viewportH / contentH);
+ updateSizeCompatScale(resolvedAppBounds, containerAppBounds);
+
final int containerTopInset = containerAppBounds.top - containerBounds.top;
final boolean topNotAligned =
containerTopInset != resolvedAppBounds.top - resolvedBounds.top;
@@ -8797,6 +8804,20 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
isInSizeCompatModeForBounds(resolvedAppBounds, containerAppBounds);
}
+ void updateSizeCompatScale(Rect resolvedAppBounds, Rect containerAppBounds) {
+ // Only allow to scale down.
+ mSizeCompatScale = mLetterboxUiController.findOpaqueNotFinishingActivityBelow()
+ .map(activityRecord -> activityRecord.mSizeCompatScale)
+ .orElseGet(() -> {
+ final int contentW = resolvedAppBounds.width();
+ final int contentH = resolvedAppBounds.height();
+ final int viewportW = containerAppBounds.width();
+ final int viewportH = containerAppBounds.height();
+ return (contentW <= viewportW && contentH <= viewportH) ? 1f : Math.min(
+ (float) viewportW / contentW, (float) viewportH / contentH);
+ });
+ }
+
private boolean isInSizeCompatModeForBounds(final Rect appBounds, final Rect containerBounds) {
if (mLetterboxUiController.hasInheritedLetterboxBehavior()) {
// To avoid wrong app behaviour, we decided to disable SCM when a translucent activity
@@ -8859,10 +8880,16 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
@Override
public Rect getBounds() {
- if (mSizeCompatBounds != null) {
- return mSizeCompatBounds;
- }
- return super.getBounds();
+ // TODO(b/268458693): Refactor configuration inheritance in case of translucent activities
+ final Rect superBounds = super.getBounds();
+ return mLetterboxUiController.findOpaqueNotFinishingActivityBelow()
+ .map(ActivityRecord::getBounds)
+ .orElseGet(() -> {
+ if (mSizeCompatBounds != null) {
+ return mSizeCompatBounds;
+ }
+ return superBounds;
+ });
}
@Override
@@ -8887,7 +8914,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Max bounds should be sandboxed when an activity should have compatDisplayInsets, and it
// will keep the same bounds and screen configuration when it was first launched regardless
// how its parent window changes, so that the sandbox API will provide a consistent result.
- if (mCompatDisplayInsets != null || shouldCreateCompatDisplayInsets()) {
+ if (getCompatDisplayInsets() != null || shouldCreateCompatDisplayInsets()) {
return true;
}
@@ -8929,7 +8956,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
mTransitionController.collect(this);
}
}
- if (mCompatDisplayInsets != null) {
+ if (getCompatDisplayInsets() != null) {
Configuration overrideConfig = getRequestedOverrideConfiguration();
// Adapt to changes in orientation locking. The app is still non-resizable, but
// it can change which orientation is fixed. If the fixed orientation changes,
@@ -9005,7 +9032,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
if (mVisibleRequested) {
// It may toggle the UI for user to restart the size compatibility mode activity.
display.handleActivitySizeCompatModeIfNeeded(this);
- } else if (mCompatDisplayInsets != null && !visibleIgnoringKeyguard
+ } else if (getCompatDisplayInsets() != null && !visibleIgnoringKeyguard
&& (app == null || !app.hasVisibleActivities())) {
// visibleIgnoringKeyguard is checked to avoid clearing mCompatDisplayInsets during
// displays change. Displays are turned off during the change so mVisibleRequested
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 5c20cedbee7c..8d671f768e87 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -4764,13 +4764,6 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
mWindowManager.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
true /*updateInputWindows*/);
}
- if (task != prevFocusTask) {
- if (prevFocusTask != null) {
- mTaskChangeNotificationController.notifyTaskFocusChanged(
- prevFocusTask.mTaskId, false);
- }
- mTaskChangeNotificationController.notifyTaskFocusChanged(task.mTaskId, true);
- }
}
if (task != prevTask) {
mTaskSupervisor.mRecentTasks.add(task);
diff --git a/services/core/java/com/android/server/wm/AsyncRotationController.java b/services/core/java/com/android/server/wm/AsyncRotationController.java
index dcafe80686ad..0dc6e0ff1054 100644
--- a/services/core/java/com/android/server/wm/AsyncRotationController.java
+++ b/services/core/java/com/android/server/wm/AsyncRotationController.java
@@ -217,6 +217,34 @@ class AsyncRotationController extends FadeAnimationController implements Consume
if (DEBUG) Slog.d(TAG, "Requested to sync draw transaction");
}
+ /**
+ * If an async window is not requested to redraw or its surface is removed, then complete its
+ * operation directly to avoid waiting until timeout.
+ */
+ void updateTargetWindows() {
+ if (mTransitionOp == OP_LEGACY || !mIsStartTransactionCommitted) return;
+ for (int i = mTargetWindowTokens.size() - 1; i >= 0; i--) {
+ final Operation op = mTargetWindowTokens.valueAt(i);
+ if (op.mIsCompletionPending || op.mAction == Operation.ACTION_SEAMLESS) {
+ // Skip completed target. And seamless windows use the signal from blast sync.
+ continue;
+ }
+ final WindowToken token = mTargetWindowTokens.keyAt(i);
+ int readyCount = 0;
+ final int childCount = token.getChildCount();
+ for (int j = childCount - 1; j >= 0; j--) {
+ final WindowState w = token.getChildAt(j);
+ // If the token no longer contains pending drawn windows, then it is ready.
+ if (w.isDrawn() || !w.mWinAnimator.getShown()) {
+ readyCount++;
+ }
+ }
+ if (readyCount == childCount) {
+ mDisplayContent.finishAsyncRotation(token);
+ }
+ }
+ }
+
/** Lets the window fit in new rotation naturally. */
private void finishOp(WindowToken windowToken) {
final Operation op = mTargetWindowTokens.remove(windowToken);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 8cd22fe71db5..17ec9cbd7428 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -4589,7 +4589,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
*/
@VisibleForTesting
SurfaceControl computeImeParent() {
- if (!ImeTargetVisibilityPolicy.isReadyToComputeImeParent(mImeLayeringTarget,
+ if (!ImeTargetVisibilityPolicy.isValidToComputeImeParent(mImeLayeringTarget,
mImeInputTarget)) {
return null;
}
@@ -4761,6 +4761,9 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
void updateWindowsForAnimator() {
forAllWindows(mUpdateWindowsForAnimator, true /* traverseTopToBottom */);
+ if (mAsyncRotationController != null) {
+ mAsyncRotationController.updateTargetWindows();
+ }
}
boolean isInputMethodClientFocus(int uid, int pid) {
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 7aeebbc2c585..2b34660d307f 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -1940,7 +1940,8 @@ public class DisplayPolicy {
final @InsetsType int restorePositionTypes = (Type.statusBars() | Type.navigationBars())
& controlTarget.getRequestedVisibleTypes();
- if (swipeTarget == mNavigationBar
+ final InsetsSourceProvider sp = swipeTarget.getControllableInsetProvider();
+ if (sp != null && sp.getSource().getType() == Type.navigationBars()
&& (restorePositionTypes & Type.navigationBars()) != 0) {
// Don't show status bar when swiping on already visible navigation bar.
// But restore the position of navigation bar if it has been moved by the control
diff --git a/services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java b/services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java
index 49218ad07dff..471bdf224b59 100644
--- a/services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java
+++ b/services/core/java/com/android/server/wm/ImeTargetVisibilityPolicy.java
@@ -19,6 +19,7 @@ package com.android.server.wm;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
+import android.annotation.Nullable;
import android.os.IBinder;
import android.view.WindowManager;
@@ -50,10 +51,12 @@ public abstract class ImeTargetVisibilityPolicy {
* Called when {@link DisplayContent#computeImeParent()} to check if it's valid to keep
* computing the ime parent.
*
+ * @param imeLayeringTarget The window which IME target to layer on top of it.
+ * @param imeInputTarget The window which start the input connection, receive input from IME.
* @return {@code true} to keep computing the ime parent, {@code false} to defer this operation
*/
- public static boolean isReadyToComputeImeParent(WindowState imeLayeringTarget,
- InputTarget imeInputTarget) {
+ public static boolean isValidToComputeImeParent(@Nullable WindowState imeLayeringTarget,
+ @Nullable InputTarget imeInputTarget) {
if (imeLayeringTarget == null) {
return false;
}
@@ -69,7 +72,9 @@ public abstract class ImeTargetVisibilityPolicy {
boolean imeLayeringTargetMayUseIme =
WindowManager.LayoutParams.mayUseInputMethod(imeLayeringTarget.mAttrs.flags)
|| imeLayeringTarget.mAttrs.type == TYPE_APPLICATION_STARTING;
-
+ if (isImeTargetMismatchOnEmbedding(imeLayeringTarget, imeInputTarget)) {
+ return true;
+ }
// Do not change parent if the window hasn't requested IME.
var inputAndLayeringTargetsDisagree = (imeInputTarget == null
|| imeLayeringTarget.mActivityRecord != imeInputTarget.getActivityRecord());
@@ -77,4 +82,27 @@ public abstract class ImeTargetVisibilityPolicy {
return !inputTargetStale;
}
+
+ private static boolean isImeTargetMismatchOnEmbedding(
+ @Nullable WindowState imeLayeringTarget, @Nullable InputTarget imeInputTarget) {
+ if (imeInputTarget == null || imeLayeringTarget == null) {
+ return false;
+ }
+ final ActivityRecord inputTargetRecord = imeInputTarget.getActivityRecord();
+ final ActivityRecord layeringTargetRecord = imeLayeringTarget.getActivityRecord();
+ final WindowState inputTargetWindow = imeInputTarget.getWindowState();
+ if (inputTargetRecord == null || layeringTargetRecord == null
+ || inputTargetWindow == null) {
+ return false;
+ }
+ final boolean isImeTargetEmbedded = inputTargetRecord.isEmbedded()
+ && layeringTargetRecord.isEmbedded();
+ // The IME layering target is calculated by the window hierarchy in DisplayContent.
+ // The layering target and input target may be different when the window hasn't started
+ // input connection, WMS hasn't received the target which reported from IMMS. We basically
+ // won't update IME parent for better IME transition.
+ // But in activity embedding, tapping a window won't update it to the top window so the IME
+ // layering target may higher than input target. Update IME parent for this case.
+ return isImeTargetEmbedded && imeLayeringTarget.compareTo(inputTargetWindow) > 0;
+ }
}
diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
index 513667024caa..fa49a6ba6c2b 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
@@ -22,6 +22,7 @@ import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ALLOW
import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_CAMERA_COMPAT_TREATMENT;
import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_COMPAT_FAKE_FOCUS;
import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY;
+import static com.android.server.wm.LetterboxConfigurationDeviceConfig.KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY;
import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -296,7 +297,6 @@ final class LetterboxConfiguration {
R.bool.config_isCompatFakeFocusEnabled);
mIsPolicyForIgnoringRequestedOrientationEnabled = mContext.getResources().getBoolean(
R.bool.config_letterboxIsPolicyForIgnoringRequestedOrientationEnabled);
-
mIsDisplayRotationImmersiveAppCompatPolicyEnabled = mContext.getResources().getBoolean(
R.bool.config_letterboxIsDisplayRotationImmersiveAppCompatPolicyEnabled);
mDeviceConfig.updateFlagActiveStatus(
@@ -311,7 +311,9 @@ final class LetterboxConfiguration {
mDeviceConfig.updateFlagActiveStatus(
/* isActive */ mIsCompatFakeFocusEnabled,
/* key */ KEY_ENABLE_COMPAT_FAKE_FOCUS);
-
+ mDeviceConfig.updateFlagActiveStatus(
+ /* isActive */ mTranslucentLetterboxingEnabled,
+ /* key */ KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY);
mLetterboxConfigurationPersister = letterboxConfigurationPersister;
mLetterboxConfigurationPersister.start();
}
@@ -1003,7 +1005,7 @@ final class LetterboxConfiguration {
boolean isTranslucentLetterboxingEnabled() {
return mTranslucentLetterboxingOverrideEnabled || (mTranslucentLetterboxingEnabled
- && isTranslucentLetterboxingAllowed());
+ && mDeviceConfig.getFlag(KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY));
}
void setTranslucentLetterboxingEnabled(boolean translucentLetterboxingEnabled) {
@@ -1051,13 +1053,6 @@ final class LetterboxConfiguration {
isDeviceInTabletopMode, nextVerticalPosition);
}
- // TODO(b/262378106): Cache a runtime flag and implement
- // DeviceConfig.OnPropertiesChangedListener
- static boolean isTranslucentLetterboxingAllowed() {
- return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
- "enable_translucent_activity_letterbox", false);
- }
-
/** Whether fake sending focus is enabled for unfocused apps in splitscreen */
boolean isCompatFakeFocusEnabled() {
return mIsCompatFakeFocusEnabled && mDeviceConfig.getFlag(KEY_ENABLE_COMPAT_FAKE_FOCUS);
diff --git a/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java b/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java
index b364872e56e7..df3c8f0fdccc 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfigurationDeviceConfig.java
@@ -48,6 +48,11 @@ final class LetterboxConfigurationDeviceConfig
static final String KEY_ENABLE_COMPAT_FAKE_FOCUS = "enable_compat_fake_focus";
private static final boolean DEFAULT_VALUE_ENABLE_COMPAT_FAKE_FOCUS = true;
+ static final String KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY =
+ "enable_letterbox_translucent_activity";
+
+ private static final boolean DEFAULT_VALUE_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY = true;
+
@VisibleForTesting
static final Map<String, Boolean> sKeyToDefaultValueMap = Map.of(
KEY_ENABLE_CAMERA_COMPAT_TREATMENT,
@@ -57,7 +62,9 @@ final class LetterboxConfigurationDeviceConfig
KEY_ALLOW_IGNORE_ORIENTATION_REQUEST,
DEFAULT_VALUE_ALLOW_IGNORE_ORIENTATION_REQUEST,
KEY_ENABLE_COMPAT_FAKE_FOCUS,
- DEFAULT_VALUE_ENABLE_COMPAT_FAKE_FOCUS
+ DEFAULT_VALUE_ENABLE_COMPAT_FAKE_FOCUS,
+ KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY,
+ DEFAULT_VALUE_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY
);
// Whether camera compatibility treatment is enabled.
@@ -82,6 +89,10 @@ final class LetterboxConfigurationDeviceConfig
// which isn't guaranteed by default in multi-window modes.
private boolean mIsCompatFakeFocusAllowed = DEFAULT_VALUE_ENABLE_COMPAT_FAKE_FOCUS;
+ // Whether the letterbox strategy for transparent activities is allowed
+ private boolean mIsTranslucentLetterboxingAllowed =
+ DEFAULT_VALUE_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY;
+
// Set of active device configs that need to be updated in
// DeviceConfig.OnPropertiesChangedListener#onPropertiesChanged.
private final ArraySet<String> mActiveDeviceConfigsSet = new ArraySet<>();
@@ -129,6 +140,8 @@ final class LetterboxConfigurationDeviceConfig
return mIsAllowIgnoreOrientationRequest;
case KEY_ENABLE_COMPAT_FAKE_FOCUS:
return mIsCompatFakeFocusAllowed;
+ case KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY:
+ return mIsTranslucentLetterboxingAllowed;
default:
throw new AssertionError("Unexpected flag name: " + key);
}
@@ -141,20 +154,20 @@ final class LetterboxConfigurationDeviceConfig
}
switch (key) {
case KEY_ENABLE_CAMERA_COMPAT_TREATMENT:
- mIsCameraCompatTreatmentEnabled =
- getDeviceConfig(key, defaultValue);
+ mIsCameraCompatTreatmentEnabled = getDeviceConfig(key, defaultValue);
break;
case KEY_ENABLE_DISPLAY_ROTATION_IMMERSIVE_APP_COMPAT_POLICY:
mIsDisplayRotationImmersiveAppCompatPolicyEnabled =
getDeviceConfig(key, defaultValue);
break;
case KEY_ALLOW_IGNORE_ORIENTATION_REQUEST:
- mIsAllowIgnoreOrientationRequest =
- getDeviceConfig(key, defaultValue);
+ mIsAllowIgnoreOrientationRequest = getDeviceConfig(key, defaultValue);
break;
case KEY_ENABLE_COMPAT_FAKE_FOCUS:
- mIsCompatFakeFocusAllowed =
- getDeviceConfig(key, defaultValue);
+ mIsCompatFakeFocusAllowed = getDeviceConfig(key, defaultValue);
+ break;
+ case KEY_ENABLE_LETTERBOX_TRANSLUCENT_ACTIVITY:
+ mIsTranslucentLetterboxingAllowed = getDeviceConfig(key, defaultValue);
break;
default:
throw new AssertionError("Unexpected flag name: " + key);
diff --git a/services/core/java/com/android/server/wm/LetterboxConfigurationPersister.java b/services/core/java/com/android/server/wm/LetterboxConfigurationPersister.java
index 4a99db594755..3b10debaa753 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfigurationPersister.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfigurationPersister.java
@@ -216,6 +216,10 @@ class LetterboxConfigurationPersister {
}
private void readCurrentConfiguration() {
+ if (!mConfigurationFile.exists()) {
+ useDefaultValue();
+ return;
+ }
FileInputStream fis = null;
try {
fis = mConfigurationFile.openRead();
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index e3437683e957..e1dbe01aca61 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -193,12 +193,6 @@ final class LetterboxUiController {
// The app compat state for the opaque activity if any
private int mInheritedAppCompatState = APP_COMPAT_STATE_CHANGED__STATE__UNKNOWN;
- // If true it means that the opaque activity beneath a translucent one is in SizeCompatMode.
- private boolean mIsInheritedInSizeCompatMode;
-
- // This is the SizeCompatScale of the opaque activity beneath a translucent one
- private float mInheritedSizeCompatScale;
-
// The CompatDisplayInsets of the opaque activity beneath the translucent one.
private ActivityRecord.CompatDisplayInsets mInheritedCompatDisplayInsets;
@@ -735,8 +729,21 @@ final class LetterboxUiController {
: mActivityRecord.inMultiWindowMode()
? mActivityRecord.getTask().getBounds()
: mActivityRecord.getRootTask().getParent().getBounds();
+ // In case of translucent activities an option is to use the WindowState#getFrame() of
+ // the first opaque activity beneath. In some cases (e.g. an opaque activity is using
+ // non MATCH_PARENT layouts or a Dialog theme) this might not provide the correct
+ // information and in particular it might provide a value for a smaller area making
+ // the letterbox overlap with the translucent activity's frame.
+ // If we use WindowState#getFrame() for the translucent activity's letterbox inner
+ // frame, the letterbox will then be overlapped with the translucent activity's frame.
+ // Because the surface layer of letterbox is lower than an activity window, this
+ // won't crop the content, but it may affect other features that rely on values stored
+ // in mLetterbox, e.g. transitions, a status bar scrim and recents preview in Launcher
+ // For this reason we use ActivityRecord#getBounds() that the translucent activity
+ // inherits from the first opaque activity beneath and also takes care of the scaling
+ // in case of activities in size compat mode.
final Rect innerFrame = hasInheritedLetterboxBehavior()
- ? mActivityRecord.getWindowConfiguration().getBounds() : w.getFrame();
+ ? mActivityRecord.getBounds() : w.getFrame();
mLetterbox.layout(spaceToFill, innerFrame, mTmpPoint);
} else if (mLetterbox != null) {
mLetterbox.hide();
@@ -1386,10 +1393,10 @@ final class LetterboxUiController {
mLetterboxConfigListener.onRemoved();
clearInheritedConfig();
}
- // In case mActivityRecord.getCompatDisplayInsets() is not null we don't apply the
+ // In case mActivityRecord.hasCompatDisplayInsetsWithoutOverride() we don't apply the
// opaque activity constraints because we're expecting the activity is already letterboxed.
- if (mActivityRecord.getTask() == null || mActivityRecord.getCompatDisplayInsets() != null
- || mActivityRecord.fillsParent()) {
+ if (mActivityRecord.getTask() == null || mActivityRecord.fillsParent()
+ || mActivityRecord.hasCompatDisplayInsetsWithoutInheritance()) {
return;
}
final ActivityRecord firstOpaqueActivityBeneath = mActivityRecord.getTask().getActivity(
@@ -1417,6 +1424,7 @@ final class LetterboxUiController {
// We need to initialize appBounds to avoid NPE. The actual value will
// be set ahead when resolving the Configuration for the activity.
mutatedConfiguration.windowConfiguration.setAppBounds(new Rect());
+ inheritConfiguration(firstOpaqueActivityBeneath);
return mutatedConfiguration;
});
}
@@ -1457,16 +1465,12 @@ final class LetterboxUiController {
return mInheritedAppCompatState;
}
- float getInheritedSizeCompatScale() {
- return mInheritedSizeCompatScale;
- }
-
@Configuration.Orientation
int getInheritedOrientation() {
return mInheritedOrientation;
}
- public ActivityRecord.CompatDisplayInsets getInheritedCompatDisplayInsets() {
+ ActivityRecord.CompatDisplayInsets getInheritedCompatDisplayInsets() {
return mInheritedCompatDisplayInsets;
}
@@ -1486,7 +1490,7 @@ final class LetterboxUiController {
* @return The first not finishing opaque activity beneath the current translucent activity
* if it exists and the strategy is enabled.
*/
- private Optional<ActivityRecord> findOpaqueNotFinishingActivityBelow() {
+ Optional<ActivityRecord> findOpaqueNotFinishingActivityBelow() {
if (!hasInheritedLetterboxBehavior() || mActivityRecord.getTask() == null) {
return Optional.empty();
}
@@ -1508,8 +1512,6 @@ final class LetterboxUiController {
}
mInheritedOrientation = firstOpaque.getRequestedConfigurationOrientation();
mInheritedAppCompatState = firstOpaque.getAppCompatState();
- mIsInheritedInSizeCompatMode = firstOpaque.inSizeCompatMode();
- mInheritedSizeCompatScale = firstOpaque.getCompatScale();
mInheritedCompatDisplayInsets = firstOpaque.getCompatDisplayInsets();
}
@@ -1519,8 +1521,6 @@ final class LetterboxUiController {
mInheritedMaxAspectRatio = UNDEFINED_ASPECT_RATIO;
mInheritedOrientation = Configuration.ORIENTATION_UNDEFINED;
mInheritedAppCompatState = APP_COMPAT_STATE_CHANGED__STATE__UNKNOWN;
- mIsInheritedInSizeCompatMode = false;
- mInheritedSizeCompatScale = 1f;
mInheritedCompatDisplayInsets = null;
}
}
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 10e4929ded6a..2af5460182dd 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -1290,12 +1290,12 @@ class Task extends TaskFragment {
return null;
}
- void updateTaskMovement(boolean toTop, int position) {
+ void updateTaskMovement(boolean toTop, boolean toBottom, int position) {
EventLogTags.writeWmTaskMoved(mTaskId, getRootTaskId(), getDisplayId(), toTop ? 1 : 0,
position);
final TaskDisplayArea taskDisplayArea = getDisplayArea();
if (taskDisplayArea != null && isLeafTask()) {
- taskDisplayArea.onLeafTaskMoved(this, toTop);
+ taskDisplayArea.onLeafTaskMoved(this, toTop, toBottom);
}
if (isPersistable) {
mLastTimeMoved = System.currentTimeMillis();
@@ -2561,7 +2561,7 @@ class Task extends TaskFragment {
final Task task = child.asTask();
if (task != null) {
- task.updateTaskMovement(toTop, position);
+ task.updateTaskMovement(toTop, position == POSITION_BOTTOM, position);
}
}
@@ -3389,6 +3389,11 @@ class Task extends TaskFragment {
&& top.getOrganizedTask() == this && top.isState(RESUMED);
// Whether the direct top activity is in size compat mode on foreground.
info.topActivityInSizeCompat = isTopActivityResumed && top.inSizeCompatMode();
+ if (info.topActivityInSizeCompat
+ && mWmService.mLetterboxConfiguration.isTranslucentLetterboxingEnabled()) {
+ // We hide the restart button in case of transparent activities.
+ info.topActivityInSizeCompat = top.fillsParent();
+ }
// Whether the direct top activity is eligible for letterbox education.
info.topActivityEligibleForLetterboxEducation = isTopActivityResumed
&& top.isEligibleForLetterboxEducation();
@@ -4323,6 +4328,8 @@ class Task extends TaskFragment {
dispatchTaskInfoChangedIfNeeded(false /* force */);
final Task parentTask = getParent().asTask();
if (parentTask != null) parentTask.dispatchTaskInfoChangedIfNeeded(false /* force */);
+
+ mAtmService.getTaskChangeNotificationController().notifyTaskFocusChanged(mTaskId, hasFocus);
}
void onPictureInPictureParamsChanged() {
@@ -4588,6 +4595,36 @@ class Task extends TaskFragment {
}
}
+ /**
+ * Abort an incomplete pip-entry. If left in this state, it will cover everything but remain
+ * paused. If this is needed, there is a bug -- this should only be used for recovery.
+ */
+ void abortPipEnter(ActivityRecord top) {
+ // an incomplete state has the task PINNED but the activity not.
+ if (!inPinnedWindowingMode() || top.inPinnedWindowingMode() || !canMoveTaskToBack(this)) {
+ return;
+ }
+ final Transition transition = new Transition(TRANSIT_TO_BACK, 0 /* flags */,
+ mTransitionController, mWmService.mSyncEngine);
+ mTransitionController.moveToCollecting(transition);
+ mTransitionController.requestStartTransition(transition, this, null /* remoteTransition */,
+ null /* displayChange */);
+ if (top.getLastParentBeforePip() != null) {
+ final Task lastParentBeforePip = top.getLastParentBeforePip();
+ if (lastParentBeforePip.isAttached()) {
+ top.reparent(lastParentBeforePip, lastParentBeforePip.getChildCount() /* top */,
+ "movePinnedActivityToOriginalTask");
+ }
+ }
+ if (isAttached()) {
+ setWindowingMode(WINDOWING_MODE_UNDEFINED);
+ moveTaskToBackInner(this);
+ }
+ if (top.isAttached()) {
+ top.setWindowingMode(WINDOWING_MODE_UNDEFINED);
+ }
+ }
+
void resumeNextFocusAfterReparent() {
adjustFocusToNextFocusableTask("reparent", true /* allowFocusSelf */,
true /* moveDisplayToTop */);
@@ -4655,13 +4692,9 @@ class Task extends TaskFragment {
final Task lastFocusedTask = displayArea.getFocusedRootTask();
displayArea.positionChildAt(POSITION_BOTTOM, this, false /*includingParents*/);
displayArea.updateLastFocusedRootTask(lastFocusedTask, reason);
- mAtmService.getTaskChangeNotificationController().notifyTaskMovedToBack(
- getTaskInfo());
}
if (task != null && task != this) {
positionChildAtBottom(task);
- mAtmService.getTaskChangeNotificationController().notifyTaskMovedToBack(
- task.getTaskInfo());
}
return;
}
@@ -5923,7 +5956,7 @@ class Task extends TaskFragment {
if (canBeLaunchedOnDisplay(newParent.getDisplayId())) {
reparent(newParent, onTop ? POSITION_TOP : POSITION_BOTTOM);
if (isLeafTask()) {
- newParent.onLeafTaskMoved(this, onTop);
+ newParent.onLeafTaskMoved(this, onTop, !onTop);
}
} else {
Slog.w(TAG, "Task=" + this + " can't reparent to " + newParent);
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index a0608db35952..8cbd553fbebd 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -403,7 +403,7 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> {
this /* child */, true /* includingParents */);
}
- child.updateTaskMovement(moveToTop, targetPosition);
+ child.updateTaskMovement(moveToTop, moveToBottom, targetPosition);
// The insert position may be adjusted to non-top when there is always-on-top root task.
// Since the original position is preferred to be top, the root task should have higher
@@ -433,7 +433,12 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> {
}
}
- void onLeafTaskMoved(Task t, boolean toTop) {
+ void onLeafTaskMoved(Task t, boolean toTop, boolean toBottom) {
+ if (toBottom) {
+ mAtmService.getTaskChangeNotificationController().notifyTaskMovedToBack(
+ t.getTaskInfo());
+ }
+
if (!toTop) {
if (t.mTaskId == mLastLeafTaskToFrontId) {
mLastLeafTaskToFrontId = INVALID_TASK_ID;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 2037fdc10352..679f0f592035 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -220,7 +220,7 @@ class TaskSnapshotController extends AbsAppSnapshotController<Task, TaskSnapshot
}
final WindowState imeWindow = task.getDisplayContent().mInputMethodWindow;
ScreenCapture.ScreenshotHardwareBuffer imeBuffer = null;
- if (imeWindow != null && imeWindow.isWinVisibleLw()) {
+ if (imeWindow != null && imeWindow.isVisible()) {
final Rect bounds = imeWindow.getParentFrame();
bounds.offsetTo(0, 0);
imeBuffer = ScreenCapture.captureLayersExcluding(imeWindow.getSurfaceControl(),
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 4e41da0e5d0b..a68b3cb2a2ea 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -878,6 +878,25 @@ class Transition implements BLASTSyncEngine.TransactionReadyListener {
" Commit wallpaper becoming invisible: %s", wt);
wt.commitVisibility(false /* visible */);
}
+ continue;
+ }
+ final Task tr = participant.asTask();
+ if (tr != null && tr.isVisibleRequested() && tr.inPinnedWindowingMode()) {
+ final ActivityRecord top = tr.getTopNonFinishingActivity();
+ if (top != null && !top.inPinnedWindowingMode()) {
+ mController.mStateValidators.add(() -> {
+ if (!tr.isAttached() || !tr.isVisibleRequested()
+ || !tr.inPinnedWindowingMode()) return;
+ final ActivityRecord currTop = tr.getTopNonFinishingActivity();
+ if (currTop.inPinnedWindowingMode()) return;
+ Slog.e(TAG, "Enter-PIP was started but not completed, this is a Shell/SysUI"
+ + " bug. This state breaks gesture-nav, so attempting clean-up.");
+ // We don't know the destination bounds, so we can't actually finish the
+ // operation. So, to prevent the half-pipped task from covering everything,
+ // abort the action (which moves the task to back).
+ tr.abortPipEnter(currTop);
+ });
+ }
}
}
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index ed7e9ed78446..79eb63462d0b 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -97,11 +97,23 @@ class TransitionController {
new ArrayList<>();
/**
+ * List of runnables to run when there are no ongoing transitions. Use this for state-validation
+ * checks (eg. to recover from incomplete states). Eventually this should be removed.
+ */
+ final ArrayList<Runnable> mStateValidators = new ArrayList<>();
+
+ /**
* Currently playing transitions (in the order they were started). When finished, records are
* removed from this list.
*/
private final ArrayList<Transition> mPlayingTransitions = new ArrayList<>();
+ /**
+ * The windows that request to be invisible while it is in transition. After the transition
+ * is finished and the windows are no longer animating, their surfaces will be destroyed.
+ */
+ final ArrayList<WindowState> mAnimatingExitWindows = new ArrayList<>();
+
final Lock mRunningLock = new Lock();
private final IBinder.DeathRecipient mTransitionPlayerDeath;
@@ -658,7 +670,33 @@ class TransitionController {
mPlayingTransitions.remove(record);
updateRunningRemoteAnimation(record, false /* isPlaying */);
record.finishTransition();
+ for (int i = mAnimatingExitWindows.size() - 1; i >= 0; i--) {
+ final WindowState w = mAnimatingExitWindows.get(i);
+ if (w.mAnimatingExit && w.mHasSurface && !w.inTransition()) {
+ w.onExitAnimationDone();
+ }
+ if (!w.mAnimatingExit || !w.mHasSurface) {
+ mAnimatingExitWindows.remove(i);
+ }
+ }
mRunningLock.doNotifyLocked();
+ // Run state-validation checks when no transitions are active anymore.
+ if (!inTransition()) {
+ validateStates();
+ }
+ }
+
+ private void validateStates() {
+ for (int i = 0; i < mStateValidators.size(); ++i) {
+ mStateValidators.get(i).run();
+ if (inTransition()) {
+ // the validator may have started a new transition, so wait for that before
+ // checking the rest.
+ mStateValidators.subList(0, i + 1).clear();
+ return;
+ }
+ }
+ mStateValidators.clear();
}
void moveToPlaying(Transition transition) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index d5bf9f9a516c..98563f6e73fc 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -89,6 +89,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED;
import static android.view.WindowManager.TRANSIT_NONE;
import static android.view.WindowManager.TRANSIT_RELAUNCH;
+import static android.view.WindowManager.TRANSIT_TO_FRONT;
import static android.view.WindowManager.fixScale;
import static android.view.WindowManagerGlobal.ADD_OKAY;
import static android.view.WindowManagerGlobal.RELAYOUT_RES_CANCEL_AND_REDRAW;
@@ -442,16 +443,6 @@ public class WindowManagerService extends IWindowManager.Stub
static final boolean ENABLE_FIXED_ROTATION_TRANSFORM =
SystemProperties.getBoolean("persist.wm.fixed_rotation_transform", true);
- /**
- * Whether the device supports the WindowManager Extensions.
- * OEMs can enable this by having their device config to inherit window_extensions.mk, such as:
- * <pre>
- * $(call inherit-product, $(SRC_TARGET_DIR)/product/window_extensions.mk)
- * </pre>
- */
- static final boolean sWindowExtensionsEnabled =
- SystemProperties.getBoolean("persist.wm.extensions.enabled", false);
-
// Enums for animation scale update types.
@Retention(RetentionPolicy.SOURCE)
@IntDef({WINDOW_ANIMATION_SCALE, TRANSITION_ANIMATION_SCALE, ANIMATION_DURATION_SCALE})
@@ -2425,7 +2416,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (wallpaperMayMove) {
displayContent.mWallpaperController.adjustWallpaperWindows();
}
- focusMayChange = tryStartExitingAnimation(win, winAnimator, focusMayChange);
+ tryStartExitingAnimation(win, winAnimator);
}
}
@@ -2610,8 +2601,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- private boolean tryStartExitingAnimation(WindowState win, WindowStateAnimator winAnimator,
- boolean focusMayChange) {
+ private void tryStartExitingAnimation(WindowState win, WindowStateAnimator winAnimator) {
// Try starting an animation; if there isn't one, we
// can destroy the surface right away.
int transit = WindowManagerPolicy.TRANSIT_EXIT;
@@ -2619,39 +2609,30 @@ public class WindowManagerService extends IWindowManager.Stub
transit = WindowManagerPolicy.TRANSIT_PREVIEW_DONE;
}
- if (win.isWinVisibleLw() && win.mDisplayContent.okToAnimate()) {
+ if (win.isVisible() && win.isDisplayed() && win.mDisplayContent.okToAnimate()) {
String reason = null;
if (winAnimator.applyAnimationLocked(transit, false)) {
// This is a WMCore-driven window animation.
reason = "applyAnimation";
- focusMayChange = true;
- win.mAnimatingExit = true;
- } else if (
- // This is already animating via a WMCore-driven window animation
- win.isSelfAnimating(0 /* flags */, ANIMATION_TYPE_WINDOW_ANIMATION)
- // Or already animating as part of a legacy app-transition
- || win.isAnimating(PARENTS | TRANSITION,
- ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_RECENTS)
- // Or already animating as part of a shell-transition.
- || (win.inTransition()
- // Filter out non-app windows since transitions don't animate those
- // (but may still "wait" on them for readiness)
- && (win.mActivityRecord != null || win.mIsWallpaper))) {
- // TODO(b/247005789): set mAnimatingExit somewhere in shell-transitions setup.
- reason = "animating";
- win.mAnimatingExit = true;
- } else if (win.mDisplayContent.mWallpaperController.isWallpaperTarget(win)
- && win.mAttrs.type != TYPE_NOTIFICATION_SHADE) {
- reason = "isWallpaperTarget";
- // If the wallpaper is currently behind this app window, they should be updated
- // in a transaction to avoid artifacts.
- // For NotificationShade, sysui is in charge of running window animation and it
- // updates the client view visibility only after both NotificationShade and the
- // wallpaper are hidden. So the exit animation is not needed and can destroy its
- // surface immediately.
- win.mAnimatingExit = true;
+ } else if (win.isSelfAnimating(0 /* flags */, ANIMATION_TYPE_WINDOW_ANIMATION)) {
+ // This is already animating via a WMCore-driven window animation.
+ reason = "selfAnimating";
+ } else {
+ if (win.mTransitionController.isShellTransitionsEnabled()) {
+ // Already animating as part of a shell-transition. Currently this only handles
+ // activity window because other types should be WMCore-driven.
+ if ((win.mActivityRecord != null && win.mActivityRecord.inTransition())) {
+ win.mTransitionController.mAnimatingExitWindows.add(win);
+ reason = "inTransition";
+ }
+ } else if (win.isAnimating(PARENTS | TRANSITION,
+ ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_RECENTS)) {
+ // Already animating as part of a legacy app-transition.
+ reason = "inLegacyTransition";
+ }
}
if (reason != null) {
+ win.mAnimatingExit = true;
ProtoLog.d(WM_DEBUG_ANIM,
"Set animatingExit: reason=startExitingAnimation/%s win=%s", reason, win);
}
@@ -2667,8 +2648,6 @@ public class WindowManagerService extends IWindowManager.Stub
if (mAccessibilityController.hasCallbacks()) {
mAccessibilityController.onWindowTransition(win, transit);
}
-
- return focusMayChange;
}
private int createSurfaceControl(SurfaceControl outSurfaceControl, int result,
@@ -7378,7 +7357,8 @@ public class WindowManagerService extends IWindowManager.Stub
ProtoLog.w(WM_ERROR, "unable to restore pointer icon");
}
} else {
- InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_DEFAULT);
+ mContext.getSystemService(InputManager.class)
+ .setPointerIconType(PointerIcon.TYPE_DEFAULT);
}
}
@@ -8689,7 +8669,13 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ // focus-transfer can re-order windows and thus potentially causes visible changes:
+ final Transition transition = mAtmService.getTransitionController()
+ .requestTransitionIfNeeded(TRANSIT_TO_FRONT, task);
mAtmService.setFocusedTask(task.mTaskId, touchedActivity);
+ if (transition != null) {
+ transition.setReady(task, true /* ready */);
+ }
}
/**
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index f9592cc46681..8e22821820a1 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -315,6 +315,13 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
}
transition = mTransitionController.createTransition(type);
}
+ if (!transition.isCollecting()) {
+ Slog.e(TAG, "Trying to start a transition that isn't collecting. This probably"
+ + " means Shell took too long to respond to a request. WM State may be"
+ + " incorrect now, please file a bug");
+ applyTransaction(wct, -1 /*syncId*/, null /*transition*/, caller);
+ return transition.getToken();
+ }
transition.start();
transition.mLogger.mStartWCT = wct;
applyTransaction(wct, -1 /*syncId*/, transition, caller);
@@ -1900,16 +1907,13 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
}
ownerTask.addChild(taskFragment, position);
taskFragment.setWindowingMode(creationParams.getWindowingMode());
- if (creationParams.areInitialRelativeBoundsSet()) {
+ if (!creationParams.getInitialRelativeBounds().isEmpty()) {
// Set relative bounds instead of using setBounds. This will avoid unnecessary update in
// case the parent has resized since the last time parent info is sent to the organizer.
taskFragment.setRelativeEmbeddedBounds(creationParams.getInitialRelativeBounds());
// Recompute configuration as the bounds will be calculated based on relative bounds in
// TaskFragment#resolveOverrideConfiguration.
taskFragment.recomputeConfiguration();
- } else {
- // TODO(b/232476698): remove after remove creationParams.getInitialBounds().
- taskFragment.setBounds(creationParams.getInitialBounds());
}
mLaunchTaskFragments.put(creationParams.getFragmentToken(), taskFragment);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 581939ae937a..87e87b95fdfd 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1922,16 +1922,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
/**
- * Is this window visible, ignoring its app token? It is not visible if there is no surface,
- * or we are in the process of running an exit animation that will remove the surface.
- */
- // TODO: Can we consolidate this with #isVisible() or have a more appropriate name for this?
- boolean isWinVisibleLw() {
- return (mActivityRecord == null || mActivityRecord.isVisibleRequested()
- || mActivityRecord.isAnimating(TRANSITION | PARENTS)) && isVisible();
- }
-
- /**
* The same as isVisible(), but follows the current hidden state of the associated app token,
* not the pending requested hidden state.
*/
@@ -2530,7 +2520,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
// If we are not currently running the exit animation, we need to see about starting one
- wasVisible = isWinVisibleLw();
+ wasVisible = isVisible();
if (keepVisibleDeadWindow) {
ProtoLog.v(WM_DEBUG_ADD_REMOVE,
@@ -2556,7 +2546,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// look weird if its orientation is changed.
&& !inRelaunchingActivity();
- if (wasVisible) {
+ if (wasVisible && isDisplayed()) {
final int transit = (!startingWindow) ? TRANSIT_EXIT : TRANSIT_PREVIEW_DONE;
// Try starting an animation.
@@ -3111,7 +3101,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
* interacts with it.
*/
private boolean shouldKeepVisibleDeadAppWindow() {
- if (!isWinVisibleLw() || mActivityRecord == null || !mActivityRecord.isClientVisible()) {
+ if (!isVisible() || mActivityRecord == null || !mActivityRecord.isClientVisible()) {
// Not a visible app window or the app isn't dead.
return false;
}
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index a102986832fe..e8625bc3d64b 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -32,7 +32,6 @@ import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
-import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
@@ -424,7 +423,7 @@ class WindowStateAnimator {
computeShownFrameLocked();
- if (w.isParentWindowHidden() || !w.isOnScreen()) {
+ if (!w.isOnScreen()) {
hide(t, "prepareSurfaceLocked");
mWallpaperControllerLocked.hideWallpapers(w);
@@ -449,30 +448,23 @@ class WindowStateAnimator {
if (prepared && mDrawState == HAS_DRAWN) {
if (mLastHidden) {
- if (showSurfaceRobustlyLocked(t)) {
- mAnimator.requestRemovalOfReplacedWindows(w);
- mLastHidden = false;
- final DisplayContent displayContent = w.getDisplayContent();
- if (!displayContent.getLastHasContent()) {
- // This draw means the difference between unique content and mirroring.
- // Run another pass through performLayout to set mHasContent in the
- // LogicalDisplay.
- displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
- if (DEBUG_LAYOUT_REPEATS) {
- mService.mWindowPlacerLocked.debugLayoutRepeats(
- "showSurfaceRobustlyLocked " + w,
- displayContent.pendingLayoutChanges);
- }
+ mSurfaceController.showRobustly(t);
+ mAnimator.requestRemovalOfReplacedWindows(w);
+ mLastHidden = false;
+ final DisplayContent displayContent = w.getDisplayContent();
+ if (!displayContent.getLastHasContent()) {
+ // This draw means the difference between unique content and mirroring.
+ // Run another pass through performLayout to set mHasContent in the
+ // LogicalDisplay.
+ displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_ANIM;
+ if (DEBUG_LAYOUT_REPEATS) {
+ mService.mWindowPlacerLocked.debugLayoutRepeats(
+ "showSurfaceRobustlyLocked " + w,
+ displayContent.pendingLayoutChanges);
}
- } else {
- w.setOrientationChanging(false);
}
}
}
- } else {
- if (mWin.isAnimating(TRANSITION | PARENTS)) {
- ProtoLog.v(WM_DEBUG_ANIM, "prepareSurface: No changes in animation for %s", this);
- }
}
if (w.getOrientationChanging()) {
@@ -511,22 +503,6 @@ class WindowStateAnimator {
mSurfaceController.setColorSpaceAgnostic(mWin.getPendingTransaction(), agnostic);
}
- /**
- * Have the surface flinger show a surface, robustly dealing with
- * error conditions. In particular, if there is not enough memory
- * to show the surface, then we will try to get rid of other surfaces
- * in order to succeed.
- *
- * @return Returns true if the surface was successfully shown.
- */
- private boolean showSurfaceRobustlyLocked(SurfaceControl.Transaction t) {
- boolean shown = mSurfaceController.showRobustly(t);
- if (!shown)
- return false;
-
- return true;
- }
-
void applyEnterAnimationLocked() {
// If we are the new part of a window replacement transition and we have requested
// not to animate, we instead want to make it seamless, so we don't want to apply
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 607ce251c4d1..33751b9f16a0 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -245,13 +245,13 @@ class WindowSurfaceController {
t.setColorSpaceAgnostic(mSurfaceControl, agnostic);
}
- boolean showRobustly(SurfaceControl.Transaction t) {
+ void showRobustly(SurfaceControl.Transaction t) {
ProtoLog.i(WM_SHOW_TRANSACTIONS, "SURFACE SHOW (performLayout): %s", title);
if (DEBUG_VISIBILITY) Slog.v(TAG, "Showing " + this
+ " during relayout");
if (mSurfaceShown) {
- return true;
+ return;
}
setShown(true);
@@ -262,7 +262,6 @@ class WindowSurfaceController {
dc.mDisplayId, 1 /* request shown */,
String.valueOf(dc.mWallpaperController.getWallpaperTarget()));
}
- return true;
}
boolean clearWindowContentFrameStats() {
diff --git a/services/core/jni/com_android_server_companion_virtual_InputController.cpp b/services/core/jni/com_android_server_companion_virtual_InputController.cpp
index dd757bc91415..4898d95b8e4b 100644
--- a/services/core/jni/com_android_server_companion_virtual_InputController.cpp
+++ b/services/core/jni/com_android_server_companion_virtual_InputController.cpp
@@ -22,6 +22,7 @@
#include <errno.h>
#include <fcntl.h>
#include <input/Input.h>
+#include <input/VirtualInputDevice.h>
#include <linux/uinput.h>
#include <math.h>
#include <nativehelper/JNIHelp.h>
@@ -32,16 +33,12 @@
#include <set>
#include <string>
-/**
- * Log debug messages about native virtual input devices.
- * Enable this via "adb shell setprop log.tag.InputController DEBUG"
- */
-static bool isDebug() {
- return __android_log_is_loggable(ANDROID_LOG_DEBUG, LOG_TAG, ANDROID_LOG_INFO);
-}
+using android::base::unique_fd;
namespace android {
+static constexpr jlong INVALID_PTR = 0;
+
enum class DeviceType {
KEYBOARD,
MOUSE,
@@ -49,176 +46,18 @@ enum class DeviceType {
DPAD,
};
-enum class UinputAction {
- RELEASE = 0,
- PRESS = 1,
- MOVE = 2,
- CANCEL = 3,
-};
-
-static std::map<int, UinputAction> BUTTON_ACTION_MAPPING = {
- {AMOTION_EVENT_ACTION_BUTTON_PRESS, UinputAction::PRESS},
- {AMOTION_EVENT_ACTION_BUTTON_RELEASE, UinputAction::RELEASE},
-};
-
-static std::map<int, UinputAction> KEY_ACTION_MAPPING = {
- {AKEY_EVENT_ACTION_DOWN, UinputAction::PRESS},
- {AKEY_EVENT_ACTION_UP, UinputAction::RELEASE},
-};
-
-static std::map<int, UinputAction> TOUCH_ACTION_MAPPING = {
- {AMOTION_EVENT_ACTION_DOWN, UinputAction::PRESS},
- {AMOTION_EVENT_ACTION_UP, UinputAction::RELEASE},
- {AMOTION_EVENT_ACTION_MOVE, UinputAction::MOVE},
- {AMOTION_EVENT_ACTION_CANCEL, UinputAction::CANCEL},
-};
-
-// Button code mapping from https://source.android.com/devices/input/touch-devices
-static std::map<int, int> BUTTON_CODE_MAPPING = {
- {AMOTION_EVENT_BUTTON_PRIMARY, BTN_LEFT}, {AMOTION_EVENT_BUTTON_SECONDARY, BTN_RIGHT},
- {AMOTION_EVENT_BUTTON_TERTIARY, BTN_MIDDLE}, {AMOTION_EVENT_BUTTON_BACK, BTN_BACK},
- {AMOTION_EVENT_BUTTON_FORWARD, BTN_FORWARD},
-};
-
-// Tool type mapping from https://source.android.com/devices/input/touch-devices
-static std::map<int, int> TOOL_TYPE_MAPPING = {
- {AMOTION_EVENT_TOOL_TYPE_FINGER, MT_TOOL_FINGER},
- {AMOTION_EVENT_TOOL_TYPE_PALM, MT_TOOL_PALM},
-};
-
-// Dpad keycode mapping from https://source.android.com/devices/input/keyboard-devices
-static std::map<int, int> DPAD_KEY_CODE_MAPPING = {
- {AKEYCODE_DPAD_DOWN, KEY_DOWN}, {AKEYCODE_DPAD_UP, KEY_UP},
- {AKEYCODE_DPAD_LEFT, KEY_LEFT}, {AKEYCODE_DPAD_RIGHT, KEY_RIGHT},
- {AKEYCODE_DPAD_CENTER, KEY_SELECT}, {AKEYCODE_BACK, KEY_BACK},
-};
-
-// Keycode mapping from https://source.android.com/devices/input/keyboard-devices
-static std::map<int, int> KEY_CODE_MAPPING = {
- {AKEYCODE_0, KEY_0},
- {AKEYCODE_1, KEY_1},
- {AKEYCODE_2, KEY_2},
- {AKEYCODE_3, KEY_3},
- {AKEYCODE_4, KEY_4},
- {AKEYCODE_5, KEY_5},
- {AKEYCODE_6, KEY_6},
- {AKEYCODE_7, KEY_7},
- {AKEYCODE_8, KEY_8},
- {AKEYCODE_9, KEY_9},
- {AKEYCODE_A, KEY_A},
- {AKEYCODE_B, KEY_B},
- {AKEYCODE_C, KEY_C},
- {AKEYCODE_D, KEY_D},
- {AKEYCODE_E, KEY_E},
- {AKEYCODE_F, KEY_F},
- {AKEYCODE_G, KEY_G},
- {AKEYCODE_H, KEY_H},
- {AKEYCODE_I, KEY_I},
- {AKEYCODE_J, KEY_J},
- {AKEYCODE_K, KEY_K},
- {AKEYCODE_L, KEY_L},
- {AKEYCODE_M, KEY_M},
- {AKEYCODE_N, KEY_N},
- {AKEYCODE_O, KEY_O},
- {AKEYCODE_P, KEY_P},
- {AKEYCODE_Q, KEY_Q},
- {AKEYCODE_R, KEY_R},
- {AKEYCODE_S, KEY_S},
- {AKEYCODE_T, KEY_T},
- {AKEYCODE_U, KEY_U},
- {AKEYCODE_V, KEY_V},
- {AKEYCODE_W, KEY_W},
- {AKEYCODE_X, KEY_X},
- {AKEYCODE_Y, KEY_Y},
- {AKEYCODE_Z, KEY_Z},
- {AKEYCODE_GRAVE, KEY_GRAVE},
- {AKEYCODE_MINUS, KEY_MINUS},
- {AKEYCODE_EQUALS, KEY_EQUAL},
- {AKEYCODE_LEFT_BRACKET, KEY_LEFTBRACE},
- {AKEYCODE_RIGHT_BRACKET, KEY_RIGHTBRACE},
- {AKEYCODE_BACKSLASH, KEY_BACKSLASH},
- {AKEYCODE_SEMICOLON, KEY_SEMICOLON},
- {AKEYCODE_APOSTROPHE, KEY_APOSTROPHE},
- {AKEYCODE_COMMA, KEY_COMMA},
- {AKEYCODE_PERIOD, KEY_DOT},
- {AKEYCODE_SLASH, KEY_SLASH},
- {AKEYCODE_ALT_LEFT, KEY_LEFTALT},
- {AKEYCODE_ALT_RIGHT, KEY_RIGHTALT},
- {AKEYCODE_CTRL_LEFT, KEY_LEFTCTRL},
- {AKEYCODE_CTRL_RIGHT, KEY_RIGHTCTRL},
- {AKEYCODE_SHIFT_LEFT, KEY_LEFTSHIFT},
- {AKEYCODE_SHIFT_RIGHT, KEY_RIGHTSHIFT},
- {AKEYCODE_META_LEFT, KEY_LEFTMETA},
- {AKEYCODE_META_RIGHT, KEY_RIGHTMETA},
- {AKEYCODE_CAPS_LOCK, KEY_CAPSLOCK},
- {AKEYCODE_SCROLL_LOCK, KEY_SCROLLLOCK},
- {AKEYCODE_NUM_LOCK, KEY_NUMLOCK},
- {AKEYCODE_ENTER, KEY_ENTER},
- {AKEYCODE_TAB, KEY_TAB},
- {AKEYCODE_SPACE, KEY_SPACE},
- {AKEYCODE_DPAD_DOWN, KEY_DOWN},
- {AKEYCODE_DPAD_UP, KEY_UP},
- {AKEYCODE_DPAD_LEFT, KEY_LEFT},
- {AKEYCODE_DPAD_RIGHT, KEY_RIGHT},
- {AKEYCODE_MOVE_END, KEY_END},
- {AKEYCODE_MOVE_HOME, KEY_HOME},
- {AKEYCODE_PAGE_DOWN, KEY_PAGEDOWN},
- {AKEYCODE_PAGE_UP, KEY_PAGEUP},
- {AKEYCODE_DEL, KEY_BACKSPACE},
- {AKEYCODE_FORWARD_DEL, KEY_DELETE},
- {AKEYCODE_INSERT, KEY_INSERT},
- {AKEYCODE_ESCAPE, KEY_ESC},
- {AKEYCODE_BREAK, KEY_PAUSE},
- {AKEYCODE_F1, KEY_F1},
- {AKEYCODE_F2, KEY_F2},
- {AKEYCODE_F3, KEY_F3},
- {AKEYCODE_F4, KEY_F4},
- {AKEYCODE_F5, KEY_F5},
- {AKEYCODE_F6, KEY_F6},
- {AKEYCODE_F7, KEY_F7},
- {AKEYCODE_F8, KEY_F8},
- {AKEYCODE_F9, KEY_F9},
- {AKEYCODE_F10, KEY_F10},
- {AKEYCODE_F11, KEY_F11},
- {AKEYCODE_F12, KEY_F12},
- {AKEYCODE_BACK, KEY_BACK},
- {AKEYCODE_FORWARD, KEY_FORWARD},
- {AKEYCODE_NUMPAD_1, KEY_KP1},
- {AKEYCODE_NUMPAD_2, KEY_KP2},
- {AKEYCODE_NUMPAD_3, KEY_KP3},
- {AKEYCODE_NUMPAD_4, KEY_KP4},
- {AKEYCODE_NUMPAD_5, KEY_KP5},
- {AKEYCODE_NUMPAD_6, KEY_KP6},
- {AKEYCODE_NUMPAD_7, KEY_KP7},
- {AKEYCODE_NUMPAD_8, KEY_KP8},
- {AKEYCODE_NUMPAD_9, KEY_KP9},
- {AKEYCODE_NUMPAD_0, KEY_KP0},
- {AKEYCODE_NUMPAD_ADD, KEY_KPPLUS},
- {AKEYCODE_NUMPAD_SUBTRACT, KEY_KPMINUS},
- {AKEYCODE_NUMPAD_MULTIPLY, KEY_KPASTERISK},
- {AKEYCODE_NUMPAD_DIVIDE, KEY_KPSLASH},
- {AKEYCODE_NUMPAD_DOT, KEY_KPDOT},
- {AKEYCODE_NUMPAD_ENTER, KEY_KPENTER},
- {AKEYCODE_NUMPAD_EQUALS, KEY_KPEQUAL},
- {AKEYCODE_NUMPAD_COMMA, KEY_KPCOMMA},
-};
-
-/*
- * Map from the uinput touchscreen fd to the pointers present in the previous touch events that
- * hasn't been lifted.
- * We only allow pointer id to go up to MAX_POINTERS because the maximum slots of virtual
- * touchscreen is set up with MAX_POINTERS. Note that in other cases Android allows pointer id to go
- * up to MAX_POINTERS_ID.
- */
-static std::map<int32_t, std::bitset<MAX_POINTERS>> unreleasedTouches;
+static unique_fd invalidFd() {
+ return unique_fd(-1);
+}
/** Creates a new uinput device and assigns a file descriptor. */
-static int openUinput(const char* readableName, jint vendorId, jint productId, const char* phys,
- DeviceType deviceType, jint screenHeight, jint screenWidth) {
- android::base::unique_fd fd(TEMP_FAILURE_RETRY(::open("/dev/uinput", O_WRONLY | O_NONBLOCK)));
+static unique_fd openUinput(const char* readableName, jint vendorId, jint productId,
+ const char* phys, DeviceType deviceType, jint screenHeight,
+ jint screenWidth) {
+ unique_fd fd(TEMP_FAILURE_RETRY(::open("/dev/uinput", O_WRONLY | O_NONBLOCK)));
if (fd < 0) {
ALOGE("Error creating uinput device: %s", strerror(errno));
- return -errno;
+ return invalidFd();
}
ioctl(fd, UI_SET_PHYS, phys);
@@ -227,12 +66,12 @@ static int openUinput(const char* readableName, jint vendorId, jint productId, c
ioctl(fd, UI_SET_EVBIT, EV_SYN);
switch (deviceType) {
case DeviceType::DPAD:
- for (const auto& [_, keyCode] : DPAD_KEY_CODE_MAPPING) {
+ for (const auto& [_, keyCode] : VirtualDpad::DPAD_KEY_CODE_MAPPING) {
ioctl(fd, UI_SET_KEYBIT, keyCode);
}
break;
case DeviceType::KEYBOARD:
- for (const auto& [_, keyCode] : KEY_CODE_MAPPING) {
+ for (const auto& [_, keyCode] : VirtualKeyboard::KEY_CODE_MAPPING) {
ioctl(fd, UI_SET_KEYBIT, keyCode);
}
break;
@@ -277,7 +116,7 @@ static int openUinput(const char* readableName, jint vendorId, jint productId, c
xAbsSetup.absinfo.minimum = 0;
if (ioctl(fd, UI_ABS_SETUP, &xAbsSetup) != 0) {
ALOGE("Error creating touchscreen uinput x axis: %s", strerror(errno));
- return -errno;
+ return invalidFd();
}
uinput_abs_setup yAbsSetup;
yAbsSetup.code = ABS_MT_POSITION_Y;
@@ -285,7 +124,7 @@ static int openUinput(const char* readableName, jint vendorId, jint productId, c
yAbsSetup.absinfo.minimum = 0;
if (ioctl(fd, UI_ABS_SETUP, &yAbsSetup) != 0) {
ALOGE("Error creating touchscreen uinput y axis: %s", strerror(errno));
- return -errno;
+ return invalidFd();
}
uinput_abs_setup majorAbsSetup;
majorAbsSetup.code = ABS_MT_TOUCH_MAJOR;
@@ -293,7 +132,7 @@ static int openUinput(const char* readableName, jint vendorId, jint productId, c
majorAbsSetup.absinfo.minimum = 0;
if (ioctl(fd, UI_ABS_SETUP, &majorAbsSetup) != 0) {
ALOGE("Error creating touchscreen uinput major axis: %s", strerror(errno));
- return -errno;
+ return invalidFd();
}
uinput_abs_setup pressureAbsSetup;
pressureAbsSetup.code = ABS_MT_PRESSURE;
@@ -301,7 +140,7 @@ static int openUinput(const char* readableName, jint vendorId, jint productId, c
pressureAbsSetup.absinfo.minimum = 0;
if (ioctl(fd, UI_ABS_SETUP, &pressureAbsSetup) != 0) {
ALOGE("Error creating touchscreen uinput pressure axis: %s", strerror(errno));
- return -errno;
+ return invalidFd();
}
uinput_abs_setup slotAbsSetup;
slotAbsSetup.code = ABS_MT_SLOT;
@@ -309,12 +148,12 @@ static int openUinput(const char* readableName, jint vendorId, jint productId, c
slotAbsSetup.absinfo.minimum = 0;
if (ioctl(fd, UI_ABS_SETUP, &slotAbsSetup) != 0) {
ALOGE("Error creating touchscreen uinput slots: %s", strerror(errno));
- return -errno;
+ return invalidFd();
}
}
if (ioctl(fd, UI_DEV_SETUP, &setup) != 0) {
ALOGE("Error creating uinput device: %s", strerror(errno));
- return -errno;
+ return invalidFd();
}
} else {
// UI_DEV_SETUP was not introduced until version 5. Try setting up manually.
@@ -338,255 +177,118 @@ static int openUinput(const char* readableName, jint vendorId, jint productId, c
}
if (TEMP_FAILURE_RETRY(write(fd, &fallback, sizeof(fallback))) != sizeof(fallback)) {
ALOGE("Error creating uinput device: %s", strerror(errno));
- return -errno;
+ return invalidFd();
}
}
if (ioctl(fd, UI_DEV_CREATE) != 0) {
ALOGE("Error creating uinput device: %s", strerror(errno));
- return -errno;
+ return invalidFd();
}
- return fd.release();
+ return fd;
}
-static int openUinputJni(JNIEnv* env, jstring name, jint vendorId, jint productId, jstring phys,
- DeviceType deviceType, int screenHeight, int screenWidth) {
+static unique_fd openUinputJni(JNIEnv* env, jstring name, jint vendorId, jint productId,
+ jstring phys, DeviceType deviceType, int screenHeight,
+ int screenWidth) {
ScopedUtfChars readableName(env, name);
ScopedUtfChars readablePhys(env, phys);
return openUinput(readableName.c_str(), vendorId, productId, readablePhys.c_str(), deviceType,
screenHeight, screenWidth);
}
-static int nativeOpenUinputDpad(JNIEnv* env, jobject thiz, jstring name, jint vendorId,
- jint productId, jstring phys) {
- return openUinputJni(env, name, vendorId, productId, phys, DeviceType::DPAD,
- /* screenHeight */ 0, /* screenWidth */ 0);
-}
-
-static int nativeOpenUinputKeyboard(JNIEnv* env, jobject thiz, jstring name, jint vendorId,
- jint productId, jstring phys) {
- return openUinputJni(env, name, vendorId, productId, phys, DeviceType::KEYBOARD,
- /* screenHeight */ 0, /* screenWidth */ 0);
-}
-
-static int nativeOpenUinputMouse(JNIEnv* env, jobject thiz, jstring name, jint vendorId,
- jint productId, jstring phys) {
- return openUinputJni(env, name, vendorId, productId, phys, DeviceType::MOUSE,
- /* screenHeight */ 0, /* screenWidth */ 0);
+static jlong nativeOpenUinputDpad(JNIEnv* env, jobject thiz, jstring name, jint vendorId,
+ jint productId, jstring phys) {
+ auto fd = openUinputJni(env, name, vendorId, productId, phys, DeviceType::DPAD,
+ /* screenHeight= */ 0, /* screenWidth= */ 0);
+ return fd.ok() ? reinterpret_cast<jlong>(new VirtualDpad(std::move(fd))) : INVALID_PTR;
}
-static int nativeOpenUinputTouchscreen(JNIEnv* env, jobject thiz, jstring name, jint vendorId,
- jint productId, jstring phys, jint height, jint width) {
- return openUinputJni(env, name, vendorId, productId, phys, DeviceType::TOUCHSCREEN, height,
- width);
+static jlong nativeOpenUinputKeyboard(JNIEnv* env, jobject thiz, jstring name, jint vendorId,
+ jint productId, jstring phys) {
+ auto fd = openUinputJni(env, name, vendorId, productId, phys, DeviceType::KEYBOARD,
+ /* screenHeight= */ 0, /* screenWidth= */ 0);
+ return fd.ok() ? reinterpret_cast<jlong>(new VirtualKeyboard(std::move(fd))) : INVALID_PTR;
}
-static bool nativeCloseUinput(JNIEnv* env, jobject thiz, jint fd) {
- ioctl(fd, UI_DEV_DESTROY);
- if (auto touchesOnFd = unreleasedTouches.find(fd); touchesOnFd != unreleasedTouches.end()) {
- const size_t remainingPointers = touchesOnFd->second.size();
- unreleasedTouches.erase(touchesOnFd);
- ALOGW_IF(remainingPointers > 0, "Closing touchscreen %d, erased %zu unreleased pointers.",
- fd, remainingPointers);
- }
- return close(fd);
+static jlong nativeOpenUinputMouse(JNIEnv* env, jobject thiz, jstring name, jint vendorId,
+ jint productId, jstring phys) {
+ auto fd = openUinputJni(env, name, vendorId, productId, phys, DeviceType::MOUSE,
+ /* screenHeight= */ 0, /* screenWidth= */ 0);
+ return fd.ok() ? reinterpret_cast<jlong>(new VirtualMouse(std::move(fd))) : INVALID_PTR;
}
-static bool writeInputEvent(int fd, uint16_t type, uint16_t code, int32_t value) {
- struct input_event ev = {.type = type, .code = code, .value = value};
- return TEMP_FAILURE_RETRY(write(fd, &ev, sizeof(struct input_event))) == sizeof(ev);
+static jlong nativeOpenUinputTouchscreen(JNIEnv* env, jobject thiz, jstring name, jint vendorId,
+ jint productId, jstring phys, jint height, jint width) {
+ auto fd = openUinputJni(env, name, vendorId, productId, phys, DeviceType::TOUCHSCREEN, height,
+ width);
+ return fd.ok() ? reinterpret_cast<jlong>(new VirtualTouchscreen(std::move(fd))) : INVALID_PTR;
}
-static bool writeKeyEvent(jint fd, jint androidKeyCode, jint action,
- const std::map<int, int>& keyCodeMapping) {
- auto keyCodeIterator = keyCodeMapping.find(androidKeyCode);
- if (keyCodeIterator == keyCodeMapping.end()) {
- ALOGE("Unsupported native keycode for androidKeyCode %d", androidKeyCode);
- return false;
- }
- auto actionIterator = KEY_ACTION_MAPPING.find(action);
- if (actionIterator == KEY_ACTION_MAPPING.end()) {
- return false;
- }
- if (!writeInputEvent(fd, EV_KEY, static_cast<uint16_t>(keyCodeIterator->second),
- static_cast<int32_t>(actionIterator->second))) {
- return false;
- }
- if (!writeInputEvent(fd, EV_SYN, SYN_REPORT, 0)) {
- return false;
- }
- return true;
+static void nativeCloseUinput(JNIEnv* env, jobject thiz, jlong ptr) {
+ VirtualInputDevice* virtualInputDevice = reinterpret_cast<VirtualInputDevice*>(ptr);
+ delete virtualInputDevice;
}
-static bool nativeWriteDpadKeyEvent(JNIEnv* env, jobject thiz, jint fd, jint androidKeyCode,
+// Native methods for VirtualDpad
+static bool nativeWriteDpadKeyEvent(JNIEnv* env, jobject thiz, jlong ptr, jint androidKeyCode,
jint action) {
- return writeKeyEvent(fd, androidKeyCode, action, DPAD_KEY_CODE_MAPPING);
+ VirtualDpad* virtualDpad = reinterpret_cast<VirtualDpad*>(ptr);
+ return virtualDpad->writeDpadKeyEvent(androidKeyCode, action);
}
-static bool nativeWriteKeyEvent(JNIEnv* env, jobject thiz, jint fd, jint androidKeyCode,
+// Native methods for VirtualKeyboard
+static bool nativeWriteKeyEvent(JNIEnv* env, jobject thiz, jlong ptr, jint androidKeyCode,
jint action) {
- return writeKeyEvent(fd, androidKeyCode, action, KEY_CODE_MAPPING);
+ VirtualKeyboard* virtualKeyboard = reinterpret_cast<VirtualKeyboard*>(ptr);
+ return virtualKeyboard->writeKeyEvent(androidKeyCode, action);
}
-static bool nativeWriteButtonEvent(JNIEnv* env, jobject thiz, jint fd, jint buttonCode,
- jint action) {
- auto buttonCodeIterator = BUTTON_CODE_MAPPING.find(buttonCode);
- if (buttonCodeIterator == BUTTON_CODE_MAPPING.end()) {
- return false;
- }
- auto actionIterator = BUTTON_ACTION_MAPPING.find(action);
- if (actionIterator == BUTTON_ACTION_MAPPING.end()) {
- return false;
- }
- if (!writeInputEvent(fd, EV_KEY, static_cast<uint16_t>(buttonCodeIterator->second),
- static_cast<int32_t>(actionIterator->second))) {
- return false;
- }
- if (!writeInputEvent(fd, EV_SYN, SYN_REPORT, 0)) {
- return false;
- }
- return true;
-}
-
-static bool handleTouchUp(int fd, int pointerId) {
- if (!writeInputEvent(fd, EV_ABS, ABS_MT_TRACKING_ID, static_cast<int32_t>(-1))) {
- return false;
- }
- auto touchesOnFd = unreleasedTouches.find(fd);
- if (touchesOnFd == unreleasedTouches.end()) {
- ALOGE("PointerId %d action UP received with no prior events on touchscreen %d.", pointerId,
- fd);
- return false;
- }
- ALOGD_IF(isDebug(), "Unreleased touches found for touchscreen %d in the map", fd);
-
- // When a pointer is no longer in touch, remove the pointer id from the corresponding
- // entry in the unreleased touches map.
- if (pointerId < 0 || pointerId >= MAX_POINTERS) {
- ALOGE("Virtual touch event has invalid pointer id %d; value must be between 0 and %zu",
- pointerId, MAX_POINTERS - 1);
- return false;
- }
- if (!touchesOnFd->second.test(pointerId)) {
- ALOGE("PointerId %d action UP received with no prior action DOWN on touchscreen %d.",
- pointerId, fd);
- return false;
- }
- touchesOnFd->second.reset(pointerId);
- ALOGD_IF(isDebug(), "Pointer %d erased from the touchscreen %d", pointerId, fd);
-
- // Only sends the BTN UP event when there's no pointers on the touchscreen.
- if (touchesOnFd->second.none()) {
- unreleasedTouches.erase(touchesOnFd);
- if (!writeInputEvent(fd, EV_KEY, BTN_TOUCH, static_cast<int32_t>(UinputAction::RELEASE))) {
- return false;
- }
- ALOGD_IF(isDebug(), "No pointers on touchscreen %d, BTN UP event sent.", fd);
- }
- return true;
-}
-
-static bool handleTouchDown(int fd, int pointerId) {
- // When a new pointer is down on the touchscreen, add the pointer id in the corresponding
- // entry in the unreleased touches map.
- auto touchesOnFd = unreleasedTouches.find(fd);
- if (touchesOnFd == unreleasedTouches.end()) {
- // Only sends the BTN Down event when the first pointer on the touchscreen is down.
- if (!writeInputEvent(fd, EV_KEY, BTN_TOUCH, static_cast<int32_t>(UinputAction::PRESS))) {
- return false;
- }
- touchesOnFd = unreleasedTouches.insert({fd, {}}).first;
- ALOGD_IF(isDebug(), "New touchscreen with fd %d added in the unreleased touches map.", fd);
- }
- if (touchesOnFd->second.test(pointerId)) {
- ALOGE("Repetitive action DOWN event received on a pointer %d that is already down.",
- pointerId);
- return false;
- }
- touchesOnFd->second.set(pointerId);
- ALOGD_IF(isDebug(), "Added pointer %d under touchscreen %d in the map", pointerId, fd);
- if (!writeInputEvent(fd, EV_ABS, ABS_MT_TRACKING_ID, static_cast<int32_t>(pointerId))) {
- return false;
- }
- return true;
+// Native methods for VirtualTouchscreen
+static bool nativeWriteTouchEvent(JNIEnv* env, jobject thiz, jlong ptr, jint pointerId,
+ jint toolType, jint action, jfloat locationX, jfloat locationY,
+ jfloat pressure, jfloat majorAxisSize) {
+ VirtualTouchscreen* virtualTouchscreen = reinterpret_cast<VirtualTouchscreen*>(ptr);
+ return virtualTouchscreen->writeTouchEvent(pointerId, toolType, action, locationX, locationY,
+ pressure, majorAxisSize);
}
-static bool nativeWriteTouchEvent(JNIEnv* env, jobject thiz, jint fd, jint pointerId, jint toolType,
- jint action, jfloat locationX, jfloat locationY, jfloat pressure,
- jfloat majorAxisSize) {
- if (!writeInputEvent(fd, EV_ABS, ABS_MT_SLOT, pointerId)) {
- return false;
- }
- auto toolTypeIterator = TOOL_TYPE_MAPPING.find(toolType);
- if (toolTypeIterator == TOOL_TYPE_MAPPING.end()) {
- return false;
- }
- if (toolType != -1) {
- if (!writeInputEvent(fd, EV_ABS, ABS_MT_TOOL_TYPE,
- static_cast<int32_t>(toolTypeIterator->second))) {
- return false;
- }
- }
- auto actionIterator = TOUCH_ACTION_MAPPING.find(action);
- if (actionIterator == TOUCH_ACTION_MAPPING.end()) {
- return false;
- }
- UinputAction uinputAction = actionIterator->second;
- if (uinputAction == UinputAction::PRESS && !handleTouchDown(fd, pointerId)) {
- return false;
- } else if (uinputAction == UinputAction::RELEASE && !handleTouchUp(fd, pointerId)) {
- return false;
- }
- if (!writeInputEvent(fd, EV_ABS, ABS_MT_POSITION_X, locationX)) {
- return false;
- }
- if (!writeInputEvent(fd, EV_ABS, ABS_MT_POSITION_Y, locationY)) {
- return false;
- }
- if (!isnan(pressure)) {
- if (!writeInputEvent(fd, EV_ABS, ABS_MT_PRESSURE, pressure)) {
- return false;
- }
- }
- if (!isnan(majorAxisSize)) {
- if (!writeInputEvent(fd, EV_ABS, ABS_MT_TOUCH_MAJOR, majorAxisSize)) {
- return false;
- }
- }
- return writeInputEvent(fd, EV_SYN, SYN_REPORT, 0);
+// Native methods for VirtualMouse
+static bool nativeWriteButtonEvent(JNIEnv* env, jobject thiz, jlong ptr, jint buttonCode,
+ jint action) {
+ VirtualMouse* virtualMouse = reinterpret_cast<VirtualMouse*>(ptr);
+ return virtualMouse->writeButtonEvent(buttonCode, action);
}
-static bool nativeWriteRelativeEvent(JNIEnv* env, jobject thiz, jint fd, jfloat relativeX,
+static bool nativeWriteRelativeEvent(JNIEnv* env, jobject thiz, jlong ptr, jfloat relativeX,
jfloat relativeY) {
- return writeInputEvent(fd, EV_REL, REL_X, relativeX) &&
- writeInputEvent(fd, EV_REL, REL_Y, relativeY) &&
- writeInputEvent(fd, EV_SYN, SYN_REPORT, 0);
+ VirtualMouse* virtualMouse = reinterpret_cast<VirtualMouse*>(ptr);
+ return virtualMouse->writeRelativeEvent(relativeX, relativeY);
}
-static bool nativeWriteScrollEvent(JNIEnv* env, jobject thiz, jint fd, jfloat xAxisMovement,
+static bool nativeWriteScrollEvent(JNIEnv* env, jobject thiz, jlong ptr, jfloat xAxisMovement,
jfloat yAxisMovement) {
- return writeInputEvent(fd, EV_REL, REL_HWHEEL, xAxisMovement) &&
- writeInputEvent(fd, EV_REL, REL_WHEEL, yAxisMovement) &&
- writeInputEvent(fd, EV_SYN, SYN_REPORT, 0);
+ VirtualMouse* virtualMouse = reinterpret_cast<VirtualMouse*>(ptr);
+ return virtualMouse->writeScrollEvent(xAxisMovement, yAxisMovement);
}
static JNINativeMethod methods[] = {
- {"nativeOpenUinputDpad", "(Ljava/lang/String;IILjava/lang/String;)I",
+ {"nativeOpenUinputDpad", "(Ljava/lang/String;IILjava/lang/String;)J",
(void*)nativeOpenUinputDpad},
- {"nativeOpenUinputKeyboard", "(Ljava/lang/String;IILjava/lang/String;)I",
+ {"nativeOpenUinputKeyboard", "(Ljava/lang/String;IILjava/lang/String;)J",
(void*)nativeOpenUinputKeyboard},
- {"nativeOpenUinputMouse", "(Ljava/lang/String;IILjava/lang/String;)I",
+ {"nativeOpenUinputMouse", "(Ljava/lang/String;IILjava/lang/String;)J",
(void*)nativeOpenUinputMouse},
- {"nativeOpenUinputTouchscreen", "(Ljava/lang/String;IILjava/lang/String;II)I",
+ {"nativeOpenUinputTouchscreen", "(Ljava/lang/String;IILjava/lang/String;II)J",
(void*)nativeOpenUinputTouchscreen},
- {"nativeCloseUinput", "(I)Z", (void*)nativeCloseUinput},
- {"nativeWriteDpadKeyEvent", "(III)Z", (void*)nativeWriteDpadKeyEvent},
- {"nativeWriteKeyEvent", "(III)Z", (void*)nativeWriteKeyEvent},
- {"nativeWriteButtonEvent", "(III)Z", (void*)nativeWriteButtonEvent},
- {"nativeWriteTouchEvent", "(IIIIFFFF)Z", (void*)nativeWriteTouchEvent},
- {"nativeWriteRelativeEvent", "(IFF)Z", (void*)nativeWriteRelativeEvent},
- {"nativeWriteScrollEvent", "(IFF)Z", (void*)nativeWriteScrollEvent},
+ {"nativeCloseUinput", "(J)V", (void*)nativeCloseUinput},
+ {"nativeWriteDpadKeyEvent", "(JII)Z", (void*)nativeWriteDpadKeyEvent},
+ {"nativeWriteKeyEvent", "(JII)Z", (void*)nativeWriteKeyEvent},
+ {"nativeWriteButtonEvent", "(JII)Z", (void*)nativeWriteButtonEvent},
+ {"nativeWriteTouchEvent", "(JIIIFFFF)Z", (void*)nativeWriteTouchEvent},
+ {"nativeWriteRelativeEvent", "(JFF)Z", (void*)nativeWriteRelativeEvent},
+ {"nativeWriteScrollEvent", "(JFF)Z", (void*)nativeWriteScrollEvent},
};
int register_android_server_companion_virtual_InputController(JNIEnv* env) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
index e16b0f7c3f17..c42a4573d2e3 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/ActiveAdmin.java
@@ -71,6 +71,10 @@ import java.util.function.Predicate;
import java.util.stream.Collectors;
class ActiveAdmin {
+
+ private final int userId;
+ public final boolean isPermissionBased;
+
private static final String TAG_DISABLE_KEYGUARD_FEATURES = "disable-keyguard-features";
private static final String TAG_TEST_ONLY_ADMIN = "test-only-admin";
private static final String TAG_DISABLE_CAMERA = "disable-camera";
@@ -356,8 +360,20 @@ class ActiveAdmin {
String mSmsPackage;
ActiveAdmin(DeviceAdminInfo info, boolean isParent) {
+ this.userId = -1;
this.info = info;
this.isParent = isParent;
+ this.isPermissionBased = false;
+ }
+
+ ActiveAdmin(int userId, boolean permissionBased) {
+ if (permissionBased == false) {
+ throw new IllegalArgumentException("Can only pass true for permissionBased admin");
+ }
+ this.userId = userId;
+ this.isPermissionBased = permissionBased;
+ this.isParent = false;
+ this.info = null;
}
ActiveAdmin getParentActiveAdmin() {
@@ -374,10 +390,16 @@ class ActiveAdmin {
}
int getUid() {
+ if (isPermissionBased) {
+ return -1;
+ }
return info.getActivityInfo().applicationInfo.uid;
}
public UserHandle getUserHandle() {
+ if (isPermissionBased) {
+ return UserHandle.of(userId);
+ }
return UserHandle.of(UserHandle.getUserId(info.getActivityInfo().applicationInfo.uid));
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
index a5b9d4397eaf..6d51bd7c7770 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyData.java
@@ -133,9 +133,9 @@ class DevicePolicyData {
// Create or get the permission-based admin. The permission-based admin will not have a
// DeviceAdminInfo or ComponentName.
- ActiveAdmin createOrGetPermissionBasedAdmin() {
+ ActiveAdmin createOrGetPermissionBasedAdmin(int userId) {
if (mPermissionBasedAdmin == null) {
- mPermissionBasedAdmin = new ActiveAdmin(/* info= */ null, /* parent= */ false);
+ mPermissionBasedAdmin = new ActiveAdmin(userId, /* permissionBased= */ true);
}
return mPermissionBasedAdmin;
}
@@ -509,7 +509,7 @@ class DevicePolicyData {
Slogf.w(TAG, e, "Failed loading admin %s", name);
}
} else if ("permission-based-admin".equals(tag)) {
- ActiveAdmin ap = new ActiveAdmin(/* info= */ null, /* parent= */ false);
+ ActiveAdmin ap = new ActiveAdmin(policy.mUserId, /* permissionBased= */ true);
ap.readFromXml(parser, /* overwritePolicies= */ false);
policy.mPermissionBasedAdmin = ap;
} else if ("delegation".equals(tag)) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 821a5f667b7b..bfcb4c7b6bc0 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3616,7 +3616,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final int N = admins.size();
for (int i = 0; i < N; i++) {
ActiveAdmin admin = admins.get(i);
- if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)
+ if ((admin.isPermissionBased || admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD))
&& admin.passwordExpirationTimeout > 0L
&& now >= admin.passwordExpirationDate - EXPIRATION_GRACE_PERIOD_MS
&& admin.passwordExpirationDate > 0L) {
@@ -4296,15 +4296,26 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
+ @GuardedBy("getLockObject()")
private List<ActiveAdmin> getActiveAdminsForLockscreenPoliciesLocked(int userHandle) {
if (isSeparateProfileChallengeEnabled(userHandle)) {
+
+ if (isPermissionCheckFlagEnabled()) {
+ return getActiveAdminsForAffectedUserInclPermissionBasedAdminLocked(userHandle);
+ }
// If this user has a separate challenge, only return its restrictions.
return getUserDataUnchecked(userHandle).mAdminList;
}
// If isSeparateProfileChallengeEnabled is false and userHandle points to a managed profile
// we need to query the parent user who owns the credential.
- return getActiveAdminsForUserAndItsManagedProfilesLocked(getProfileParentId(userHandle),
- (user) -> !mLockPatternUtils.isSeparateProfileChallengeEnabled(user.id));
+ if (isPermissionCheckFlagEnabled()) {
+ return getActiveAdminsForUserAndItsManagedProfilesInclPermissionBasedAdminLocked(getProfileParentId(userHandle),
+ (user) -> !mLockPatternUtils.isSeparateProfileChallengeEnabled(user.id));
+ } else {
+ return getActiveAdminsForUserAndItsManagedProfilesLocked(getProfileParentId(userHandle),
+ (user) -> !mLockPatternUtils.isSeparateProfileChallengeEnabled(user.id));
+ }
+
}
/**
@@ -4340,7 +4351,14 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@GuardedBy("getLockObject()")
private List<ActiveAdmin> getActiveAdminsForAffectedUserInclPermissionBasedAdminLocked(
int userHandle) {
- List<ActiveAdmin> list = getActiveAdminsForAffectedUserLocked(userHandle);
+ List<ActiveAdmin> list;
+
+ if (isManagedProfile(userHandle)) {
+ list = getUserDataUnchecked(userHandle).mAdminList;
+ }
+ list = getActiveAdminsForUserAndItsManagedProfilesInclPermissionBasedAdminLocked(userHandle,
+ /* shouldIncludeProfileAdmins */ (user) -> false);
+
if (getUserData(userHandle).mPermissionBasedAdmin != null) {
list.add(getUserData(userHandle).mPermissionBasedAdmin);
}
@@ -4378,6 +4396,44 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return admins;
}
+ /**
+ * Returns the list of admins on the given user, as well as parent admins for each managed
+ * profile associated with the given user. Optionally also include the admin of each managed
+ * profile.
+ * <p> Should not be called on a profile user.
+ */
+ @GuardedBy("getLockObject()")
+ private List<ActiveAdmin> getActiveAdminsForUserAndItsManagedProfilesInclPermissionBasedAdminLocked(int userHandle,
+ Predicate<UserInfo> shouldIncludeProfileAdmins) {
+ ArrayList<ActiveAdmin> admins = new ArrayList<>();
+ mInjector.binderWithCleanCallingIdentity(() -> {
+ for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) {
+ DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
+ if (userInfo.id == userHandle) {
+ admins.addAll(policy.mAdminList);
+ if (policy.mPermissionBasedAdmin != null) {
+ admins.add(policy.mPermissionBasedAdmin);
+ }
+ } else if (userInfo.isManagedProfile()) {
+ for (int i = 0; i < policy.mAdminList.size(); i++) {
+ ActiveAdmin admin = policy.mAdminList.get(i);
+ if (admin.hasParentActiveAdmin()) {
+ admins.add(admin.getParentActiveAdmin());
+ }
+ if (shouldIncludeProfileAdmins.test(userInfo)) {
+ admins.add(admin);
+ }
+ }
+ if (policy.mPermissionBasedAdmin != null
+ && shouldIncludeProfileAdmins.test(userInfo)) {
+ admins.add(policy.mPermissionBasedAdmin);
+ }
+ }
+ }
+ });
+ return admins;
+ }
+
private boolean isSeparateProfileChallengeEnabled(int userHandle) {
return mInjector.binderWithCleanCallingIdentity(() ->
mLockPatternUtils.isSeparateProfileChallengeEnabled(userHandle));
@@ -4697,6 +4753,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
* Return a single admin's expiration date/time, or the min (soonest) for all admins.
* Returns 0 if not configured.
*/
+ @GuardedBy("getLockObject()")
private long getPasswordExpirationLocked(ComponentName who, int userHandle, boolean parent) {
long timeout = 0L;
@@ -5010,7 +5067,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
@Override
- public boolean isActivePasswordSufficient(int userHandle, boolean parent) {
+ public boolean isActivePasswordSufficient(
+ String callerPackageName, int userHandle, boolean parent) {
if (!mHasFeature) {
return true;
}
@@ -5024,7 +5082,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
if (isPermissionCheckFlagEnabled()) {
int affectedUser = parent ? getProfileParentId(userHandle) : userHandle;
enforcePermission(MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS,
- /*callerPackageName=*/ null, affectedUser);
+ callerPackageName, affectedUser);
} else {
// This API can only be called by an active device admin,
// so try to retrieve it to check that the caller is one.
@@ -5282,11 +5340,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
adminPackageName, userId, affectedUserId, complexity);
}
}
-
+ @GuardedBy("getLockObject()")
private int getAggregatedPasswordComplexityLocked(@UserIdInt int userHandle) {
return getAggregatedPasswordComplexityLocked(userHandle, false);
}
+ @GuardedBy("getLockObject()")
private int getAggregatedPasswordComplexityLocked(@UserIdInt int userHandle,
boolean deviceWideOnly) {
ensureLocked();
@@ -5305,7 +5364,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
@Override
- public int getRequiredPasswordComplexity(boolean calledOnParent) {
+ public int getRequiredPasswordComplexity(String callerPackageName, boolean calledOnParent) {
if (!mHasFeature) {
return PASSWORD_COMPLEXITY_NONE;
}
@@ -5316,7 +5375,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
int affectedUser = calledOnParent ? getProfileParentId(caller.getUserId())
: caller.getUserId();
enforcePermission(MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS,
- /*callerPackageName=*/ null, affectedUser);
+ callerPackageName, affectedUser);
} else {
Preconditions.checkCallAuthorization(
isDefaultDeviceOwner(caller) || isProfileOwner(caller));
@@ -5347,7 +5406,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
@Override
- public int getCurrentFailedPasswordAttempts(int userHandle, boolean parent) {
+ public int getCurrentFailedPasswordAttempts(
+ String callerPackageName, int userHandle, boolean parent) {
if (!mLockPatternUtils.hasSecureLockScreen()) {
return 0;
}
@@ -5363,7 +5423,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
if (isPermissionCheckFlagEnabled()) {
int affectedUser = parent ? getProfileParentId(userHandle) : userHandle;
enforcePermission(MANAGE_DEVICE_POLICY_LOCK_CREDENTIALS,
- /*callerPackageName=*/ null, affectedUser);
+ callerPackageName, affectedUser);
} else {
getActiveAdminForCallerLocked(
null, DeviceAdminInfo.USES_POLICY_WATCH_LOGIN, parent);
@@ -5469,6 +5529,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
* profile.
* Returns {@code null} if no participating admin has that policy set.
*/
+ @GuardedBy("getLockObject()")
private ActiveAdmin getAdminWithMinimumFailedPasswordsForWipeLocked(
int userHandle, boolean parent) {
int count = 0;
@@ -5699,6 +5760,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
}
+ @GuardedBy("getLockObject()")
private void updateMaximumTimeToLockLocked(@UserIdInt int userId) {
// Update the profile's timeout
if (isManagedProfile(userId)) {
@@ -5727,6 +5789,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
});
}
+ @GuardedBy("getLockObject()")
private void updateProfileLockTimeoutLocked(@UserIdInt int userId) {
final long timeMs;
if (isSeparateProfileChallengeEnabled(userId)) {
@@ -7459,9 +7522,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final String adminName;
final ComponentName adminComp;
if (admin != null) {
- adminComp = admin.info.getComponent();
- adminName = adminComp.flattenToShortString();
- event.setAdmin(adminComp);
+ if (admin.isPermissionBased) {
+ adminComp = null;
+ adminName = caller.getPackageName();
+ event.setAdmin(adminName);
+ } else {
+ adminComp = admin.info.getComponent();
+ adminName = adminComp.flattenToShortString();
+ event.setAdmin(adminComp);
+ }
} else {
adminComp = null;
adminName = mInjector.getPackageManager().getPackagesForUid(caller.getUid())[0];
@@ -7750,13 +7819,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
|| hasCallingPermission(permission.MASTER_CLEAR)
|| hasCallingPermission(MANAGE_DEVICE_POLICY_FACTORY_RESET),
"Must be called by the FRP management agent on device");
- // TODO(b/261999445): Remove
- if (isHeadlessFlagEnabled()) {
- admin = getDeviceOwnerOrProfileOwnerOfOrganizationOwnedDeviceLocked();
- } else {
- admin = getDeviceOwnerOrProfileOwnerOfOrganizationOwnedDeviceLocked(
- UserHandle.getUserId(frpManagementAgentUid));
- }
+ admin = getDeviceOwnerOrProfileOwnerOfOrganizationOwnedDeviceOrSystemPermissionBasedAdminLocked();
} else {
Preconditions.checkCallAuthorization(
isDefaultDeviceOwner(caller)
@@ -7927,12 +7990,13 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
*
* @return the set of user IDs that have been affected
*/
+ @GuardedBy("getLockObject()")
private Set<Integer> updatePasswordExpirationsLocked(int userHandle) {
final ArraySet<Integer> affectedUserIds = new ArraySet<>();
List<ActiveAdmin> admins = getActiveAdminsForLockscreenPoliciesLocked(userHandle);
for (int i = 0; i < admins.size(); i++) {
ActiveAdmin admin = admins.get(i);
- if (admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)) {
+ if (admin.isPermissionBased || admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_EXPIRE_PASSWORD)) {
affectedUserIds.add(admin.getUserHandle().getIdentifier());
long timeout = admin.passwordExpirationTimeout;
admin.passwordExpirationDate =
@@ -8026,6 +8090,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
*/
private int getUserIdToWipeForFailedPasswords(ActiveAdmin admin) {
final int userId = admin.getUserHandle().getIdentifier();
+ if (admin.isPermissionBased) {
+ return userId;
+ }
final ComponentName component = admin.info.getComponent();
return isProfileOwnerOfOrganizationOwnedDevice(component, userId)
? getProfileParentId(userId) : userId;
@@ -9653,6 +9720,15 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return admin;
}
+ ActiveAdmin getDeviceOwnerOrProfileOwnerOfOrganizationOwnedDeviceOrSystemPermissionBasedAdminLocked() {
+ ensureLocked();
+ ActiveAdmin doOrPo = getDeviceOwnerOrProfileOwnerOfOrganizationOwnedDeviceLocked();
+ if (isPermissionCheckFlagEnabled() && doOrPo == null) {
+ return getUserData(0).mPermissionBasedAdmin;
+ }
+ return doOrPo;
+ }
+
ActiveAdmin getDeviceOwnerOrProfileOwnerOfOrganizationOwnedDeviceParentLocked(int userId) {
ensureLocked();
ActiveAdmin admin = getDeviceOwnerAdminLocked();
@@ -10659,9 +10735,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return false;
}
- final ComponentName profileOwner = getProfileOwnerAsUser(userId);
- if (profileOwner == null) {
- return false;
+ if (!isPermissionCheckFlagEnabled()) {
+ // TODO: Figure out if something like this needs to be restored for policy engine
+ final ComponentName profileOwner = getProfileOwnerAsUser(userId);
+ if (profileOwner == null) {
+ return false;
+ }
}
// Managed profiles are not allowed to use lock task
@@ -11245,7 +11324,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
setBackwardsCompatibleAppRestrictions(
packageName, restrictions, caller.getUserHandle());
} else {
- Objects.requireNonNull(who, "ComponentName is null");
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
&& (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
|| (caller.hasPackage() && isCallerDelegate(caller,
@@ -11884,7 +11962,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
synchronized (getLockObject()) {
List<String> result = null;
// Only device or profile owners can have permitted lists set.
- List<ActiveAdmin> admins = getActiveAdminsForAffectedUserLocked(userId);
+ List<ActiveAdmin> admins = getActiveAdminsForAffectedUserInclPermissionBasedAdminLocked(userId);
for (ActiveAdmin admin: admins) {
List<String> fromAdmin = admin.permittedInputMethods;
if (fromAdmin != null) {
@@ -12597,7 +12675,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
return policies.get(enforcingAdmin).getValue();
} else {
- Objects.requireNonNull(who, "ComponentName is null");
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
&& (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
|| (caller.hasPackage() && isCallerDelegate(caller,
@@ -12823,11 +12900,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_USER_RESTRICTION);
if (useDevicePolicyEngine(caller, /* delegateScope= */ null)) {
+ int affectedUserId = parent ? getProfileParentId(userId) : userId;
EnforcingAdmin admin = enforcePermissionForUserRestriction(
who,
key,
caller.getPackageName(),
- userId);
+ affectedUserId);
PolicyDefinition<Boolean> policyDefinition =
PolicyDefinition.getPolicyDefinitionForUserRestriction(key);
if (enabledFromThisOwner) {
@@ -12835,7 +12913,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
policyDefinition,
admin,
new BooleanPolicyValue(true),
- parent ? getProfileParentId(userId) : userId);
+ affectedUserId);
} else {
// Remove any local and global policy that was set by the admin
if (!policyDefinition.isLocalOnlyPolicy()) {
@@ -13623,7 +13701,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
new BooleanPolicyValue(uninstallBlocked),
caller.getUserId());
} else {
- Objects.requireNonNull(who, "ComponentName is null");
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
&& (isProfileOwner(caller) || isDefaultDeviceOwner(caller)
|| isFinancedDeviceOwner(caller)))
@@ -14198,7 +14275,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
mDevicePolicyEngine.setLocalPolicy(
PolicyDefinition.LOCK_TASK,
- EnforcingAdmin.createEnterpriseEnforcingAdmin(who, caller.getUserId()),
+ enforcingAdmin,
policy,
caller.getUserId());
}
@@ -14265,7 +14342,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
final int userId = mInjector.userHandleGetCallingUserId();
// Is it ok to just check that no active policies exist currently?
- if (mDevicePolicyEngine.hasActivePolicies()) {
+ if (isDevicePolicyEngineFlagEnabled() && mDevicePolicyEngine.hasActivePolicies()) {
LockTaskPolicy policy = mDevicePolicyEngine.getResolvedPolicy(
PolicyDefinition.LOCK_TASK, userId);
if (policy == null) {
@@ -14549,7 +14626,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
CallerIdentity caller = getCallerIdentity(who);
if (isPermissionCheckFlagEnabled()) {
- enforcePermission(MANAGE_DEVICE_POLICY_WIFI, /*callerPackageName=*/ null,
+ enforcePermission(MANAGE_DEVICE_POLICY_WIFI, who.getPackageName(),
UserHandle.USER_ALL);
} else {
Preconditions.checkNotNull(who, "ComponentName is null");
@@ -15814,7 +15891,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
if (admin.mPasswordPolicy.quality < minPasswordQuality) {
return false;
}
- return admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
+ return admin.isPermissionBased || admin.info.usesPolicy(DeviceAdminInfo.USES_POLICY_LIMIT_PASSWORD);
}
@Override
@@ -18533,9 +18610,9 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
public StringParceledListSlice getOwnerInstalledCaCerts(@NonNull UserHandle user) {
final int userId = user.getIdentifier();
final CallerIdentity caller = getCallerIdentity();
- Preconditions.checkCallAuthorization((userId == caller.getUserId())
- || isProfileOwner(caller) || isDefaultDeviceOwner(caller)
- || hasFullCrossUsersPermission(caller, userId));
+ Preconditions.checkCallAuthorization(
+ (isProfileOwner(caller) || isDefaultDeviceOwner(caller) || canQueryAdminPolicy(
+ caller)) && hasFullCrossUsersPermission(caller, userId));
synchronized (getLockObject()) {
return new StringParceledListSlice(
@@ -21435,10 +21512,10 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
@Override
- public WifiSsidPolicy getWifiSsidPolicy() {
+ public WifiSsidPolicy getWifiSsidPolicy(String callerPackageName) {
final CallerIdentity caller = getCallerIdentity();
if (isPermissionCheckFlagEnabled()) {
- enforcePermission(MANAGE_DEVICE_POLICY_WIFI, /*callerPackageName=*/ null,
+ enforcePermission(MANAGE_DEVICE_POLICY_WIFI, callerPackageName,
caller.getUserId());
} else {
Preconditions.checkCallAuthorization(
@@ -21451,13 +21528,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
synchronized (getLockObject()) {
ActiveAdmin admin;
- // TODO(b/261999445): remove
- if (isHeadlessFlagEnabled()) {
- admin = getDeviceOwnerOrProfileOwnerOfOrganizationOwnedDeviceLocked();
- } else {
- admin = getDeviceOwnerOrProfileOwnerOfOrganizationOwnedDeviceLocked(
- UserHandle.USER_SYSTEM);
- }
+ admin = getDeviceOwnerOrProfileOwnerOfOrganizationOwnedDeviceOrSystemPermissionBasedAdminLocked();
return admin != null ? admin.mWifiSsidPolicy : null;
}
}
@@ -22395,7 +22466,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
} else {
// If the permission maps to no policy (null) this means that any active admin
// has permission.
- return getActiveAdminForUidLocked(null, caller.getUid()) != null;
+ return isCallerActiveAdminOrDelegate(caller, null);
}
} catch (SecurityException e) {
// A security exception means there is not an active admin with permission and
@@ -22434,27 +22505,29 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
private EnforcingAdmin getEnforcingAdminForCaller(@Nullable ComponentName who,
String callerPackageName) {
- CallerIdentity caller = getCallerIdentity(callerPackageName);
+ CallerIdentity caller = getCallerIdentity(who, callerPackageName);
int userId = caller.getUserId();
ActiveAdmin admin;
- synchronized (getLockObject()) {
- admin = getActiveAdminUncheckedLocked(who, userId);
- }
- if (isDeviceOwner(caller) || isProfileOwner(caller)) {
- return EnforcingAdmin.createEnterpriseEnforcingAdmin(who, userId, admin);
- }
- if (isCallerDelegate(caller)) {
- ComponentName profileOwner = mOwners.getProfileOwnerComponent(caller.getUserId());
- ComponentName dpc = profileOwner != null ? profileOwner :
- mOwners.getDeviceOwnerComponent();
- ActiveAdmin dpcAdmin = getDeviceOrProfileOwnerAdminLocked(caller.getUserId());
- return EnforcingAdmin.createEnterpriseEnforcingAdmin(dpc, userId, dpcAdmin);
+ if (isDeviceOwner(caller) || isProfileOwner(caller) || isCallerDelegate(caller)) {
+ ComponentName component;
+ synchronized (getLockObject()) {
+ if (who != null) {
+ admin = getActiveAdminUncheckedLocked(who, userId);
+ component = who;
+ } else {
+ admin = getDeviceOrProfileOwnerAdminLocked(userId);
+ component = admin.info.getComponent();
+ }
+ }
+ return EnforcingAdmin.createEnterpriseEnforcingAdmin(component, userId, admin);
}
- if (getActiveAdminUncheckedLocked(who, userId) != null) {
+ // Check for non-DPC active admins.
+ admin = getActiveAdminForCaller(who, caller);
+ if (admin != null) {
return EnforcingAdmin.createDeviceAdminEnforcingAdmin(who, userId, admin);
}
if (admin == null) {
- admin = getUserData(userId).createOrGetPermissionBasedAdmin();
+ admin = getUserData(userId).createOrGetPermissionBasedAdmin(userId);
}
return EnforcingAdmin.createEnforcingAdmin(caller.getPackageName(), userId, admin);
}
@@ -23014,26 +23087,12 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
return admins;
}
- // TODO: This can actually accept an EnforcingAdmin that gets created in the permission check
- // method.
private boolean useDevicePolicyEngine(CallerIdentity caller, @Nullable String delegateScope) {
- if (!isCallerActiveAdminOrDelegate(caller, delegateScope)) {
- if (!isDevicePolicyEngineFlagEnabled()) {
- throw new IllegalStateException("Non DPC caller can't set device policies.");
- }
- if (hasDPCsNotSupportingCoexistence()) {
- throw new IllegalStateException("Non DPC caller can't set device policies with "
- + "existing legacy admins on the device.");
- }
- return true;
- } else {
- return isDevicePolicyEngineEnabled();
- }
+ return isDevicePolicyEngineEnabled();
}
private boolean isDevicePolicyEngineEnabled() {
- return isDevicePolicyEngineFlagEnabled() && !hasDPCsNotSupportingCoexistence()
- && isPermissionCheckFlagEnabled();
+ return isDevicePolicyEngineFlagEnabled() && isPermissionCheckFlagEnabled();
}
private boolean isDevicePolicyEngineFlagEnabled() {
@@ -23079,6 +23138,26 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
});
}
+ private ActiveAdmin getActiveAdminForCaller(@Nullable ComponentName who,
+ CallerIdentity caller) {
+ synchronized (getLockObject()) {
+ if (who != null) {
+ return getActiveAdminUncheckedLocked(who, caller.getUserId());
+ }
+ return mInjector.binderWithCleanCallingIdentity(() -> {
+ List<ComponentName> activeAdmins = getActiveAdmins(caller.getUserId());
+ if (activeAdmins != null) {
+ for (ComponentName admin : activeAdmins) {
+ if (admin.getPackageName().equals(caller.getPackageName())) {
+ return getActiveAdminUncheckedLocked(admin, caller.getUserId());
+ }
+ }
+ }
+ return null;
+ });
+ }
+ }
+
// TODO(b/266808047): This will return false for DeviceAdmins not targetting U, which is
// inconsistent with the migration logic that allows migration with old DeviceAdmins.
private boolean canAddActiveAdminIfPolicyEngineEnabled(String packageName, int userId) {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java
index daa8a26e00d1..fd91249fac62 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/PolicyEnforcerCallbacks.java
@@ -215,10 +215,9 @@ final class PolicyEnforcerCallbacks {
}
UserRestrictionPolicyKey parsedKey =
(UserRestrictionPolicyKey) policyKey;
- // TODO: call into new UserManager API when merged
UserManagerInternal userManager = LocalServices.getService(UserManagerInternal.class);
-// userManager.setUserRestriction(
-// userId, parsedKey.getRestriction(), enabled != null && enabled);
+ userManager.setUserRestriction(
+ userId, parsedKey.getRestriction(), enabled != null && enabled);
return true;
}));
}
diff --git a/services/robotests/src/com/android/server/media/OWNERS b/services/robotests/src/com/android/server/media/OWNERS
new file mode 100644
index 000000000000..c74c9ac98b13
--- /dev/null
+++ b/services/robotests/src/com/android/server/media/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 137631
+include platform/frameworks/av:/media/janitors/media_solutions_OWNERS
+
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/RestrictionsSetTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/RestrictionsSetTest.java
index e7adf7b757f1..8345a43979af 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/RestrictionsSetTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/RestrictionsSetTest.java
@@ -32,6 +32,7 @@ import android.platform.test.annotations.Presubmit;
import androidx.test.runner.AndroidJUnit4;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -138,6 +139,7 @@ public class RestrictionsSetTest {
}
@Test
+ @Ignore("b/268334580")
public void testGetEnforcingUsers_hasEnforcingUser() {
mRestrictionsSet.updateRestrictions(originatingUserId,
newRestrictions(UserManager.ENSURE_VERIFY_APPS));
@@ -154,6 +156,7 @@ public class RestrictionsSetTest {
}
@Test
+ @Ignore("b/268334580")
public void testGetEnforcingUsers_hasMultipleEnforcingUsers() {
int originatingUserId2 = 10;
mRestrictionsSet.updateRestrictions(originatingUserId,
diff --git a/services/tests/mockingservicestests/src/android/hardware/face/FaceManagerTest.java b/services/tests/mockingservicestests/src/android/hardware/face/FaceManagerTest.java
deleted file mode 100644
index f3feb0269598..000000000000
--- a/services/tests/mockingservicestests/src/android/hardware/face/FaceManagerTest.java
+++ /dev/null
@@ -1,86 +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 android.hardware.face;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.os.Looper;
-import android.os.RemoteException;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoJUnitRunner;
-import org.mockito.junit.MockitoRule;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@RunWith(MockitoJUnitRunner.class)
-public class FaceManagerTest {
- @Rule
- public final MockitoRule mockito = MockitoJUnit.rule();
-
- @Mock
- Context mContext;
- @Mock
- IFaceService mService;
-
- @Captor
- ArgumentCaptor<IFaceAuthenticatorsRegisteredCallback> mCaptor;
-
- List<FaceSensorPropertiesInternal> mProps;
- FaceManager mFaceManager;
-
- @Before
- public void setUp() throws Exception {
- when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
- mFaceManager = new FaceManager(mContext, mService);
- mProps = new ArrayList<>();
- mProps.add(new FaceSensorPropertiesInternal(
- 0 /* id */,
- FaceSensorProperties.STRENGTH_STRONG,
- 1 /* maxTemplatesAllowed */,
- new ArrayList<>() /* conponentInfo */,
- FaceSensorProperties.TYPE_UNKNOWN,
- true /* supportsFaceDetection */,
- true /* supportsSelfIllumination */,
- false /* resetLockoutRequiresChallenge */));
- }
-
- @Test
- public void getSensorPropertiesInternal_noBinderCalls() throws RemoteException {
- verify(mService).addAuthenticatorsRegisteredCallback(mCaptor.capture());
-
- mCaptor.getValue().onAllAuthenticatorsRegistered(mProps);
- List<FaceSensorPropertiesInternal> actual = mFaceManager.getSensorPropertiesInternal();
-
- assertThat(actual).isEqualTo(mProps);
- verify(mService, never()).getSensorPropertiesInternal(any());
- }
-}
diff --git a/services/tests/mockingservicestests/src/android/hardware/fingerprint/FingerprintManagerTest.java b/services/tests/mockingservicestests/src/android/hardware/fingerprint/FingerprintManagerTest.java
deleted file mode 100644
index 558202d51b27..000000000000
--- a/services/tests/mockingservicestests/src/android/hardware/fingerprint/FingerprintManagerTest.java
+++ /dev/null
@@ -1,88 +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 android.hardware.fingerprint;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.os.Looper;
-import android.os.RemoteException;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoJUnitRunner;
-import org.mockito.junit.MockitoRule;
-
-import java.util.ArrayList;
-import java.util.List;
-
-
-@RunWith(MockitoJUnitRunner.class)
-public class FingerprintManagerTest {
- @Rule
- public final MockitoRule mockito = MockitoJUnit.rule();
-
- @Mock
- Context mContext;
- @Mock
- IFingerprintService mService;
-
- @Captor
- ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mCaptor;
-
- List<FingerprintSensorPropertiesInternal> mProps;
- FingerprintManager mFingerprintManager;
-
- @Before
- public void setUp() throws Exception {
- when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
- mFingerprintManager = new FingerprintManager(mContext, mService);
- mProps = new ArrayList<>();
- mProps.add(new FingerprintSensorPropertiesInternal(
- 0 /* sensorId */,
- FingerprintSensorProperties.STRENGTH_STRONG,
- 1 /* maxEnrollmentsPerUser */,
- new ArrayList<>() /* componentInfo */,
- FingerprintSensorProperties.TYPE_UNKNOWN,
- true /* halControlsIllumination */,
- true /* resetLockoutRequiresHardwareAuthToken */,
- new ArrayList<>() /* sensorLocations */));
- }
-
- @Test
- public void getSensorPropertiesInternal_noBinderCalls() throws RemoteException {
- verify(mService).addAuthenticatorsRegisteredCallback(mCaptor.capture());
-
- mCaptor.getValue().onAllAuthenticatorsRegistered(mProps);
- List<FingerprintSensorPropertiesInternal> actual =
- mFingerprintManager.getSensorPropertiesInternal();
-
- assertThat(actual).isEqualTo(mProps);
- verify(mService, never()).getSensorPropertiesInternal(any());
- }
-}
diff --git a/services/tests/mockingservicestests/src/android/hardware/fingerprint/OWNERS b/services/tests/mockingservicestests/src/android/hardware/fingerprint/OWNERS
index 3edcf70d7e67..6a2192a2c7fb 100644
--- a/services/tests/mockingservicestests/src/android/hardware/fingerprint/OWNERS
+++ b/services/tests/mockingservicestests/src/android/hardware/fingerprint/OWNERS
@@ -1 +1 @@
-include /services/core/java/com/android/server/biometrics/OWNERS \ No newline at end of file
+include /services/core/java/com/android/server/biometrics/OWNERS
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
index 68cfe4591c51..dcdee37059a9 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueModernImplTest.java
@@ -16,6 +16,10 @@
package com.android.server.am;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.internal.util.FrameworkStatsLog.BROADCAST_DELIVERY_EVENT_REPORTED;
+import static com.android.internal.util.FrameworkStatsLog.BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD;
+import static com.android.internal.util.FrameworkStatsLog.BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__MANIFEST;
import static com.android.server.am.BroadcastProcessQueue.REASON_CONTAINS_ALARM;
import static com.android.server.am.BroadcastProcessQueue.REASON_CONTAINS_FOREGROUND;
import static com.android.server.am.BroadcastProcessQueue.REASON_CONTAINS_INTERACTIVE;
@@ -44,8 +48,12 @@ import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
import android.annotation.NonNull;
import android.app.Activity;
@@ -70,6 +78,11 @@ import android.util.Pair;
import androidx.test.filters.SmallTest;
+import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
+import com.android.internal.util.FrameworkStatsLog;
+import com.android.server.ExtendedMockitoTestCase;
+import com.android.server.am.BroadcastQueueTest.SyncBarrier;
+
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@@ -86,7 +99,7 @@ import java.util.List;
@SmallTest
@RunWith(MockitoJUnitRunner.class)
-public class BroadcastQueueModernImplTest {
+public class BroadcastQueueModernImplTest extends ExtendedMockitoTestCase {
private static final int TEST_UID = android.os.Process.FIRST_APPLICATION_UID;
private static final int TEST_UID2 = android.os.Process.FIRST_APPLICATION_UID + 1;
@@ -105,6 +118,11 @@ public class BroadcastQueueModernImplTest {
BroadcastProcessQueue mHead;
+ @Override
+ protected void initializeSession(StaticMockitoSessionBuilder builder) {
+ builder.spyStatic(FrameworkStatsLog.class);
+ }
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -1081,6 +1099,28 @@ public class BroadcastQueueModernImplTest {
}
}
+ @Test
+ public void testBroadcastDeliveryEventReported() throws Exception {
+ final Intent timeTick = new Intent(Intent.ACTION_TIME_TICK);
+ final BroadcastOptions optionsTimeTick = BroadcastOptions.makeBasic();
+ optionsTimeTick.setDeliveryGroupPolicy(BroadcastOptions.DELIVERY_GROUP_POLICY_MOST_RECENT);
+
+ // Halt all processing so that we get a consistent view
+ try (SyncBarrier b = new SyncBarrier(mHandlerThread)) {
+ mImpl.enqueueBroadcastLocked(makeBroadcastRecord(timeTick, optionsTimeTick));
+ mImpl.enqueueBroadcastLocked(makeBroadcastRecord(timeTick, optionsTimeTick));
+ }
+ mImpl.waitForIdle(null);
+
+ // Verify that there is only one delivery event reported since one of the broadcasts
+ // should have been skipped.
+ verify(() -> FrameworkStatsLog.write(eq(BROADCAST_DELIVERY_EVENT_REPORTED),
+ eq(getUidForPackage(PACKAGE_GREEN)), anyInt(), eq(Intent.ACTION_TIME_TICK),
+ eq(BROADCAST_DELIVERY_EVENT_REPORTED__RECEIVER_TYPE__MANIFEST),
+ eq(BROADCAST_DELIVERY_EVENT_REPORTED__PROC_START_TYPE__PROCESS_START_TYPE_COLD),
+ anyLong(), anyLong(), anyLong(), anyInt()), times(1));
+ }
+
private Intent createPackageChangedIntent(int uid, List<String> componentNameList) {
final Intent packageChangedIntent = new Intent(Intent.ACTION_PACKAGE_CHANGED);
packageChangedIntent.putExtra(Intent.EXTRA_UID, uid);
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
index e7b3dd985053..cf8460bca1a6 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/BroadcastQueueTest.java
@@ -346,16 +346,18 @@ public class BroadcastQueueTest {
* Helper that leverages try-with-resources to pause dispatch of
* {@link #mHandlerThread} until released.
*/
- private class SyncBarrier implements AutoCloseable {
+ static class SyncBarrier implements AutoCloseable {
private final int mToken;
+ private HandlerThread mThread;
- public SyncBarrier() {
- mToken = mHandlerThread.getLooper().getQueue().postSyncBarrier();
+ SyncBarrier(HandlerThread thread) {
+ mThread = thread;
+ mToken = mThread.getLooper().getQueue().postSyncBarrier();
}
@Override
public void close() throws Exception {
- mHandlerThread.getLooper().getQueue().removeSyncBarrier(mToken);
+ mThread.getLooper().getQueue().removeSyncBarrier(mToken);
}
}
@@ -1120,7 +1122,7 @@ public class BroadcastQueueTest {
final ProcessRecord receiverApp = makeActiveProcessRecord(PACKAGE_GREEN);
final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
- try (SyncBarrier b = new SyncBarrier()) {
+ try (SyncBarrier b = new SyncBarrier(mHandlerThread)) {
enqueueBroadcast(makeBroadcastRecord(airplane, callerApp, new ArrayList<>(
List.of(makeRegisteredReceiver(receiverApp),
makeManifestReceiver(PACKAGE_GREEN, CLASS_RED),
@@ -1164,7 +1166,7 @@ public class BroadcastQueueTest {
final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
final Intent timeZone = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
- try (SyncBarrier b = new SyncBarrier()) {
+ try (SyncBarrier b = new SyncBarrier(mHandlerThread)) {
enqueueBroadcast(makeBroadcastRecord(airplane, callerApp, USER_GUEST, new ArrayList<>(
List.of(makeRegisteredReceiver(callerApp),
makeManifestReceiver(PACKAGE_GREEN, CLASS_RED, USER_GUEST),
@@ -1204,7 +1206,7 @@ public class BroadcastQueueTest {
final ProcessRecord oldApp = makeActiveProcessRecord(PACKAGE_GREEN);
final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
- try (SyncBarrier b = new SyncBarrier()) {
+ try (SyncBarrier b = new SyncBarrier(mHandlerThread)) {
enqueueBroadcast(makeBroadcastRecord(airplane, callerApp, new ArrayList<>(
List.of(makeRegisteredReceiver(oldApp),
makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN)))));
@@ -1585,7 +1587,7 @@ public class BroadcastQueueTest {
final Intent timezone = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
airplane.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
- try (SyncBarrier b = new SyncBarrier()) {
+ try (SyncBarrier b = new SyncBarrier(mHandlerThread)) {
enqueueBroadcast(makeBroadcastRecord(timezone, callerApp,
List.of(makeRegisteredReceiver(receiverBlueApp, 10),
makeRegisteredReceiver(receiverGreenApp, 10),
@@ -1638,7 +1640,7 @@ public class BroadcastQueueTest {
final IIntentReceiver resultToFirst = mock(IIntentReceiver.class);
final IIntentReceiver resultToSecond = mock(IIntentReceiver.class);
- try (SyncBarrier b = new SyncBarrier()) {
+ try (SyncBarrier b = new SyncBarrier(mHandlerThread)) {
enqueueBroadcast(makeOrderedBroadcastRecord(timezoneFirst, callerApp,
List.of(makeManifestReceiver(PACKAGE_BLUE, CLASS_BLUE),
makeManifestReceiver(PACKAGE_BLUE, CLASS_GREEN)),
@@ -1729,7 +1731,7 @@ public class BroadcastQueueTest {
timeTickFirst.putExtra(Intent.EXTRA_INDEX, "third");
timeTickThird.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
- try (SyncBarrier b = new SyncBarrier()) {
+ try (SyncBarrier b = new SyncBarrier(mHandlerThread)) {
enqueueBroadcast(makeBroadcastRecord(timeTickFirst, callerApp,
List.of(makeManifestReceiver(PACKAGE_BLUE, CLASS_BLUE))));
enqueueBroadcast(makeBroadcastRecord(timeTickSecond, callerApp,
@@ -1771,7 +1773,7 @@ public class BroadcastQueueTest {
assertTrue(mQueue.isIdleLocked());
assertTrue(mQueue.isBeyondBarrierLocked(beforeFirst));
- try (SyncBarrier b = new SyncBarrier()) {
+ try (SyncBarrier b = new SyncBarrier(mHandlerThread)) {
final Intent timezone = new Intent(Intent.ACTION_TIMEZONE_CHANGED);
enqueueBroadcast(makeBroadcastRecord(timezone, callerApp,
List.of(makeRegisteredReceiver(receiverApp))));
@@ -1820,6 +1822,42 @@ public class BroadcastQueueTest {
}
/**
+ * Verify that we OOM adjust for ordered broadcast receivers.
+ */
+ @Test
+ public void testOomAdjust_Ordered() throws Exception {
+ final ProcessRecord callerApp = makeActiveProcessRecord(PACKAGE_RED);
+
+ final IIntentReceiver orderedResultTo = mock(IIntentReceiver.class);
+ final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+ enqueueBroadcast(makeOrderedBroadcastRecord(airplane, callerApp,
+ List.of(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN),
+ makeManifestReceiver(PACKAGE_GREEN, CLASS_BLUE),
+ makeManifestReceiver(PACKAGE_GREEN, CLASS_RED)), orderedResultTo, null));
+
+ waitForIdle();
+ verify(mAms, atLeastOnce()).enqueueOomAdjTargetLocked(any());
+ }
+
+ /**
+ * Verify that we OOM adjust for resultTo broadcast receivers.
+ */
+ @Test
+ public void testOomAdjust_ResultTo() throws Exception {
+ final ProcessRecord callerApp = makeActiveProcessRecord(PACKAGE_RED);
+
+ final IIntentReceiver resultTo = mock(IIntentReceiver.class);
+ final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+ enqueueBroadcast(makeBroadcastRecord(airplane, callerApp,
+ List.of(makeManifestReceiver(PACKAGE_GREEN, CLASS_GREEN),
+ makeManifestReceiver(PACKAGE_GREEN, CLASS_BLUE),
+ makeManifestReceiver(PACKAGE_GREEN, CLASS_RED)), resultTo));
+
+ waitForIdle();
+ verify(mAms, atLeastOnce()).enqueueOomAdjTargetLocked(any());
+ }
+
+ /**
* Verify that we never OOM adjust for registered receivers.
*/
@Test
@@ -1865,7 +1903,7 @@ public class BroadcastQueueTest {
final ProcessRecord receiverBlueApp = makeActiveProcessRecord(PACKAGE_BLUE);
final Intent airplane = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
- try (SyncBarrier b = new SyncBarrier()) {
+ try (SyncBarrier b = new SyncBarrier(mHandlerThread)) {
final Object greenReceiver = makeRegisteredReceiver(receiverGreenApp);
final Object blueReceiver = makeRegisteredReceiver(receiverBlueApp);
final Object yellowReceiver = makeManifestReceiver(PACKAGE_YELLOW, CLASS_YELLOW);
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
index 3fd0e072809f..f8cfdf131a28 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/CachedAppOptimizerTest.java
@@ -17,9 +17,12 @@
package com.android.server.am;
import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
+
import static com.android.server.am.ActivityManagerService.Injector;
import static com.android.server.am.CachedAppOptimizer.compactActionIntToAction;
+
import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
@@ -34,27 +37,30 @@ import android.os.Process;
import android.platform.test.annotations.Presubmit;
import android.provider.DeviceConfig;
import android.text.TextUtils;
+
import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.dx.mockito.inline.extended.StaticMockitoSessionBuilder;
import com.android.modules.utils.testing.TestableDeviceConfig;
+import com.android.server.ExtendedMockitoTestCase;
import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.appop.AppOpsService;
import com.android.server.wm.ActivityTaskManagerService;
-import java.io.File;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
+
import org.junit.After;
import org.junit.Assume;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
-import org.junit.runner.RunWith;
import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnitRunner;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
/**
* Tests for {@link CachedAppOptimizer}.
@@ -63,10 +69,7 @@ import org.mockito.junit.MockitoJUnitRunner;
* atest FrameworksMockingServicesTests:CachedAppOptimizerTest
*/
@Presubmit
-@RunWith(MockitoJUnitRunner.class)
-@Ignore("TODO(b/226641572): this test is broken and it cannot use ExtendedMockitoTestCase as it "
- + "uses TestableDeviceConfigRule, which creates its own mockito session")
-public final class CachedAppOptimizerTest {
+public final class CachedAppOptimizerTest extends ExtendedMockitoTestCase {
private ServiceThread mThread;
@@ -84,16 +87,21 @@ public final class CachedAppOptimizerTest {
@Mock
private PackageManagerInternal mPackageManagerInt;
- @Rule
- public final TestableDeviceConfig.TestableDeviceConfigRule
- mDeviceConfigRule = new TestableDeviceConfig.TestableDeviceConfigRule();
+ private final TestableDeviceConfig mDeviceConfig = new TestableDeviceConfig();
+
@Rule
public final ApplicationExitInfoTest.ServiceThreadRule
mServiceThreadRule = new ApplicationExitInfoTest.ServiceThreadRule();
+ @Override
+ protected void initializeSession(StaticMockitoSessionBuilder builder) {
+ mDeviceConfig.setUpMockedClasses(builder);
+ }
+
@Before
public void setUp() {
System.loadLibrary("mockingservicestestjni");
+ mDeviceConfig.setUpMockBehaviors();
mHandlerThread = new HandlerThread("");
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
@@ -124,6 +132,7 @@ public final class CachedAppOptimizerTest {
mHandlerThread.quit();
mThread.quit();
mCountDown = null;
+ mDeviceConfig.tearDown();
}
private ProcessRecord makeProcessRecord(int pid, int uid, int packageUid, String processName,
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
index 6e63315d2830..96b63455598d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerController2Test.java
@@ -26,12 +26,15 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.Resources;
@@ -44,7 +47,9 @@ import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.os.SystemProperties;
+import android.os.UserHandle;
import android.os.test.TestLooper;
+import android.provider.Settings;
import android.util.FloatProperty;
import android.view.Display;
import android.view.DisplayInfo;
@@ -57,6 +62,7 @@ import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.server.LocalServices;
import com.android.server.am.BatteryStatsService;
import com.android.server.display.RampAnimator.DualRampAnimator;
+import com.android.server.display.brightness.BrightnessEvent;
import com.android.server.display.color.ColorDisplayService;
import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
import com.android.server.policy.WindowManagerPolicy;
@@ -122,6 +128,7 @@ public final class DisplayPowerController2Test {
.spyStatic(SystemProperties.class)
.spyStatic(LocalServices.class)
.spyStatic(BatteryStatsService.class)
+ .spyStatic(Settings.System.class)
.startMocking();
mContextSpy = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
mClock = new OffsettableClock.Stopped();
@@ -139,8 +146,7 @@ public final class DisplayPowerController2Test {
ColorDisplayService.ColorDisplayServiceInternal.class));
doAnswer((Answer<Void>) invocationOnMock -> null).when(BatteryStatsService::getService);
- mProxSensor = setUpProxSensor();
-
+ setUpSensors();
mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID);
}
@@ -169,7 +175,7 @@ public final class DisplayPowerController2Test {
advanceTime(1);
// two times, one for unfinished business and one for proximity
- verify(mHolder.wakelockController).acquireWakelock(
+ verify(mHolder.wakelockController, times(2)).acquireWakelock(
WakelockController.WAKE_LOCK_UNFINISHED_BUSINESS);
verify(mHolder.wakelockController).acquireWakelock(
WakelockController.WAKE_LOCK_PROXIMITY_DEBOUNCE);
@@ -177,7 +183,7 @@ public final class DisplayPowerController2Test {
mHolder.dpc.stop();
advanceTime(1);
// two times, one for unfinished business and one for proximity
- verify(mHolder.wakelockController).acquireWakelock(
+ verify(mHolder.wakelockController, times(2)).acquireWakelock(
WakelockController.WAKE_LOCK_UNFINISHED_BUSINESS);
verify(mHolder.wakelockController).acquireWakelock(
WakelockController.WAKE_LOCK_PROXIMITY_DEBOUNCE);
@@ -214,12 +220,13 @@ public final class DisplayPowerController2Test {
mTestLooper.dispatchAll();
}
- private Sensor setUpProxSensor() throws Exception {
- Sensor proxSensor = TestUtils.createSensor(
+ private void setUpSensors() throws Exception {
+ mProxSensor = TestUtils.createSensor(
Sensor.TYPE_PROXIMITY, Sensor.STRING_TYPE_PROXIMITY);
+ Sensor screenOffBrightnessSensor = TestUtils.createSensor(
+ Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT);
when(mSensorManagerMock.getSensorList(eq(Sensor.TYPE_ALL)))
- .thenReturn(List.of(proxSensor));
- return proxSensor;
+ .thenReturn(List.of(mProxSensor, screenOffBrightnessSensor));
}
private SensorEventListener getSensorEventListener(Sensor sensor) {
@@ -229,14 +236,15 @@ public final class DisplayPowerController2Test {
}
private void setUpDisplay(int displayId, String uniqueId, LogicalDisplay logicalDisplayMock,
- DisplayDevice displayDeviceMock, DisplayDeviceConfig displayDeviceConfigMock) {
+ DisplayDevice displayDeviceMock, DisplayDeviceConfig displayDeviceConfigMock,
+ boolean isEnabled) {
DisplayInfo info = new DisplayInfo();
DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
when(logicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId);
when(logicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(displayDeviceMock);
when(logicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
- when(logicalDisplayMock.isEnabledLocked()).thenReturn(true);
+ when(logicalDisplayMock.isEnabledLocked()).thenReturn(isEnabled);
when(logicalDisplayMock.isInTransitionLocked()).thenReturn(false);
when(displayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
when(displayDeviceMock.getUniqueId()).thenReturn(uniqueId);
@@ -253,7 +261,14 @@ public final class DisplayPowerController2Test {
when(displayDeviceConfigMock.getAmbientLightSensor()).thenReturn(
new DisplayDeviceConfig.SensorData());
when(displayDeviceConfigMock.getScreenOffBrightnessSensor()).thenReturn(
- new DisplayDeviceConfig.SensorData());
+ new DisplayDeviceConfig.SensorData() {
+ {
+ type = Sensor.STRING_TYPE_LIGHT;
+ name = null;
+ }
+ });
+ when(displayDeviceConfigMock.getScreenOffBrightnessSensorValueToLux())
+ .thenReturn(new int[0]);
}
@Test
@@ -460,8 +475,164 @@ public final class DisplayPowerController2Test {
verify(secondFollowerDpc.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
}
+ @Test
+ public void testDoesNotSetScreenStateForNonDefaultDisplayUntilBootCompleted() {
+ // We should still set screen state for the default display
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1);
+ verify(mHolder.displayPowerState, times(2)).setScreenState(anyInt());
+
+ mHolder = createDisplayPowerController(42, UNIQUE_ID);
+
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1);
+ verify(mHolder.displayPowerState, never()).setScreenState(anyInt());
+
+ mHolder.dpc.onBootCompleted();
+ advanceTime(1);
+ verify(mHolder.displayPowerState).setScreenState(anyInt());
+ }
+
+ @Test
+ public void testSetScreenOffBrightnessSensorEnabled_DisplayIsOff() {
+ doAnswer((Answer<Integer>) invocationOnMock ->
+ Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC)
+ .when(() -> Settings.System.getIntForUser(any(ContentResolver.class),
+ eq(Settings.System.SCREEN_BRIGHTNESS_MODE), anyInt(),
+ eq(UserHandle.USER_CURRENT)));
+
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ dpr.policy = DisplayPowerRequest.POLICY_OFF;
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
+ .setLightSensorEnabled(true);
+
+ // The display turns on and we use the brightness value recommended by
+ // ScreenOffBrightnessSensorController
+ clearInvocations(mHolder.screenOffBrightnessSensorController);
+ float brightness = 0.14f;
+ when(mHolder.screenOffBrightnessSensorController.getAutomaticScreenBrightness())
+ .thenReturn(brightness);
+ dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
+ when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
+ when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness(
+ any(BrightnessEvent.class))).thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT);
+
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
+ .getAutomaticScreenBrightness();
+ verify(mHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+ }
+
+ @Test
+ public void testSetScreenOffBrightnessSensorEnabled_DisplayIsInDoze() {
+ doAnswer((Answer<Integer>) invocationOnMock ->
+ Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC)
+ .when(() -> Settings.System.getIntForUser(any(ContentResolver.class),
+ eq(Settings.System.SCREEN_BRIGHTNESS_MODE), anyInt(),
+ eq(UserHandle.USER_CURRENT)));
+
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ dpr.policy = DisplayPowerRequest.POLICY_DOZE;
+ when(mResourcesMock.getBoolean(
+ com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing))
+ .thenReturn(true);
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
+ .setLightSensorEnabled(true);
+
+ // The display turns on and we use the brightness value recommended by
+ // ScreenOffBrightnessSensorController
+ clearInvocations(mHolder.screenOffBrightnessSensorController);
+ float brightness = 0.14f;
+ when(mHolder.screenOffBrightnessSensorController.getAutomaticScreenBrightness())
+ .thenReturn(brightness);
+ dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
+ when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
+ when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness(
+ any(BrightnessEvent.class))).thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT);
+
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
+ .getAutomaticScreenBrightness();
+ verify(mHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+ }
+
+ @Test
+ public void testSetScreenOffBrightnessSensorDisabled_AutoBrightnessIsDisabled() {
+ doAnswer((Answer<Integer>) invocationOnMock ->
+ Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL)
+ .when(() -> Settings.System.getIntForUser(any(ContentResolver.class),
+ eq(Settings.System.SCREEN_BRIGHTNESS_MODE), anyInt(),
+ eq(UserHandle.USER_CURRENT)));
+
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ dpr.policy = DisplayPowerRequest.POLICY_OFF;
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
+ .setLightSensorEnabled(false);
+ }
+
+ @Test
+ public void testSetScreenOffBrightnessSensorDisabled_DisplayIsDisabled() {
+ doAnswer((Answer<Integer>) invocationOnMock ->
+ Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC)
+ .when(() -> Settings.System.getIntForUser(any(ContentResolver.class),
+ eq(Settings.System.SCREEN_BRIGHTNESS_MODE), anyInt(),
+ eq(UserHandle.USER_CURRENT)));
+ mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID, /* isEnabled= */ false);
+
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
+ .setLightSensorEnabled(false);
+ }
+
+ @Test
+ public void testSetScreenOffBrightnessSensorDisabled_DisplayIsOn() {
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
+
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
+ .setLightSensorEnabled(false);
+ }
+
+ @Test
+ public void testSetScreenOffBrightnessSensorDisabled_DisplayIsAFollower() {
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ dpr.policy = DisplayPowerRequest.POLICY_OFF;
+
+ mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, /* leadDisplayId= */ 42);
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
+ .setLightSensorEnabled(false);
+ }
+
private DisplayPowerControllerHolder createDisplayPowerController(int displayId,
String uniqueId) {
+ return createDisplayPowerController(displayId, uniqueId, /* isEnabled= */ true);
+ }
+
+ private DisplayPowerControllerHolder createDisplayPowerController(int displayId,
+ String uniqueId, boolean isEnabled) {
final DisplayPowerState displayPowerState = mock(DisplayPowerState.class);
final DualRampAnimator<DisplayPowerState> animator = mock(DualRampAnimator.class);
final AutomaticBrightnessController automaticBrightnessController =
@@ -470,10 +641,12 @@ public final class DisplayPowerController2Test {
final BrightnessMappingStrategy brightnessMappingStrategy =
mock(BrightnessMappingStrategy.class);
final HysteresisLevels hysteresisLevels = mock(HysteresisLevels.class);
+ final ScreenOffBrightnessSensorController screenOffBrightnessSensorController =
+ mock(ScreenOffBrightnessSensorController.class);
TestInjector injector = new TestInjector(displayPowerState, animator,
automaticBrightnessController, wakelockController, brightnessMappingStrategy,
- hysteresisLevels);
+ hysteresisLevels, screenOffBrightnessSensorController);
final LogicalDisplay display = mock(LogicalDisplay.class);
final DisplayDevice device = mock(DisplayDevice.class);
@@ -481,16 +654,17 @@ public final class DisplayPowerController2Test {
final BrightnessSetting brightnessSetting = mock(BrightnessSetting.class);
final DisplayDeviceConfig config = mock(DisplayDeviceConfig.class);
- setUpDisplay(displayId, uniqueId, display, device, config);
+ setUpDisplay(displayId, uniqueId, display, device, config, isEnabled);
final DisplayPowerController2 dpc = new DisplayPowerController2(
mContextSpy, injector, mDisplayPowerCallbacksMock, mHandler,
mSensorManagerMock, mDisplayBlankerMock, display,
mBrightnessTrackerMock, brightnessSetting, () -> {},
- hbmMetadata);
+ hbmMetadata, /* bootCompleted= */ false);
return new DisplayPowerControllerHolder(dpc, displayPowerState, brightnessSetting, animator,
- automaticBrightnessController, wakelockController);
+ automaticBrightnessController, wakelockController,
+ screenOffBrightnessSensorController, hbmMetadata);
}
/**
@@ -504,18 +678,24 @@ public final class DisplayPowerController2Test {
public final DualRampAnimator<DisplayPowerState> animator;
public final AutomaticBrightnessController automaticBrightnessController;
public final WakelockController wakelockController;
+ public final ScreenOffBrightnessSensorController screenOffBrightnessSensorController;
+ public final HighBrightnessModeMetadata hbmMetadata;
DisplayPowerControllerHolder(DisplayPowerController2 dpc,
DisplayPowerState displayPowerState, BrightnessSetting brightnessSetting,
DualRampAnimator<DisplayPowerState> animator,
AutomaticBrightnessController automaticBrightnessController,
- WakelockController wakelockController) {
+ WakelockController wakelockController,
+ ScreenOffBrightnessSensorController screenOffBrightnessSensorController,
+ HighBrightnessModeMetadata hbmMetadata) {
this.dpc = dpc;
this.displayPowerState = displayPowerState;
this.brightnessSetting = brightnessSetting;
this.animator = animator;
this.automaticBrightnessController = automaticBrightnessController;
this.wakelockController = wakelockController;
+ this.screenOffBrightnessSensorController = screenOffBrightnessSensorController;
+ this.hbmMetadata = hbmMetadata;
}
}
@@ -526,18 +706,21 @@ public final class DisplayPowerController2Test {
private final WakelockController mWakelockController;
private final BrightnessMappingStrategy mBrightnessMappingStrategy;
private final HysteresisLevels mHysteresisLevels;
+ private final ScreenOffBrightnessSensorController mScreenOffBrightnessSensorController;
TestInjector(DisplayPowerState dps, DualRampAnimator<DisplayPowerState> animator,
AutomaticBrightnessController automaticBrightnessController,
WakelockController wakelockController,
BrightnessMappingStrategy brightnessMappingStrategy,
- HysteresisLevels hysteresisLevels) {
+ HysteresisLevels hysteresisLevels,
+ ScreenOffBrightnessSensorController screenOffBrightnessSensorController) {
mDisplayPowerState = dps;
mAnimator = animator;
mAutomaticBrightnessController = automaticBrightnessController;
mWakelockController = wakelockController;
mBrightnessMappingStrategy = brightnessMappingStrategy;
mHysteresisLevels = hysteresisLevels;
+ mScreenOffBrightnessSensorController = screenOffBrightnessSensorController;
}
@Override
@@ -617,5 +800,13 @@ public final class DisplayPowerController2Test {
float minBrighteningThreshold, boolean potentialOldBrightnessRange) {
return mHysteresisLevels;
}
+
+ @Override
+ ScreenOffBrightnessSensorController getScreenOffBrightnessSensorController(
+ SensorManager sensorManager, Sensor lightSensor, Handler handler,
+ ScreenOffBrightnessSensorController.Clock clock, int[] sensorValueToLux,
+ BrightnessMappingStrategy brightnessMapper) {
+ return mScreenOffBrightnessSensorController;
+ }
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
index a8c3e4e9dc7e..28319acc5f1b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/DisplayPowerControllerTest.java
@@ -26,12 +26,15 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isA;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.when;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.Resources;
@@ -44,7 +47,9 @@ import android.os.Handler;
import android.os.Looper;
import android.os.PowerManager;
import android.os.SystemProperties;
+import android.os.UserHandle;
import android.os.test.TestLooper;
+import android.provider.Settings;
import android.util.FloatProperty;
import android.view.Display;
import android.view.DisplayInfo;
@@ -57,6 +62,7 @@ import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.server.LocalServices;
import com.android.server.am.BatteryStatsService;
import com.android.server.display.RampAnimator.DualRampAnimator;
+import com.android.server.display.brightness.BrightnessEvent;
import com.android.server.display.color.ColorDisplayService;
import com.android.server.display.whitebalance.DisplayWhiteBalanceController;
import com.android.server.policy.WindowManagerPolicy;
@@ -122,6 +128,7 @@ public final class DisplayPowerControllerTest {
.spyStatic(SystemProperties.class)
.spyStatic(LocalServices.class)
.spyStatic(BatteryStatsService.class)
+ .spyStatic(Settings.System.class)
.startMocking();
mContextSpy = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
mClock = new OffsettableClock.Stopped();
@@ -140,8 +147,7 @@ public final class DisplayPowerControllerTest {
ColorDisplayService.ColorDisplayServiceInternal.class));
doAnswer((Answer<Void>) invocationOnMock -> null).when(BatteryStatsService::getService);
- mProxSensor = setUpProxSensor();
-
+ setUpSensors();
mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID);
}
@@ -217,12 +223,13 @@ public final class DisplayPowerControllerTest {
mTestLooper.dispatchAll();
}
- private Sensor setUpProxSensor() throws Exception {
- Sensor proxSensor = TestUtils.createSensor(
+ private void setUpSensors() throws Exception {
+ mProxSensor = TestUtils.createSensor(
Sensor.TYPE_PROXIMITY, Sensor.STRING_TYPE_PROXIMITY);
+ Sensor screenOffBrightnessSensor = TestUtils.createSensor(
+ Sensor.TYPE_LIGHT, Sensor.STRING_TYPE_LIGHT);
when(mSensorManagerMock.getSensorList(eq(Sensor.TYPE_ALL)))
- .thenReturn(List.of(proxSensor));
- return proxSensor;
+ .thenReturn(List.of(mProxSensor, screenOffBrightnessSensor));
}
private SensorEventListener getSensorEventListener(Sensor sensor) {
@@ -232,14 +239,15 @@ public final class DisplayPowerControllerTest {
}
private void setUpDisplay(int displayId, String uniqueId, LogicalDisplay logicalDisplayMock,
- DisplayDevice displayDeviceMock, DisplayDeviceConfig displayDeviceConfigMock) {
+ DisplayDevice displayDeviceMock, DisplayDeviceConfig displayDeviceConfigMock,
+ boolean isEnabled) {
DisplayInfo info = new DisplayInfo();
DisplayDeviceInfo deviceInfo = new DisplayDeviceInfo();
when(logicalDisplayMock.getDisplayIdLocked()).thenReturn(displayId);
when(logicalDisplayMock.getPrimaryDisplayDeviceLocked()).thenReturn(displayDeviceMock);
when(logicalDisplayMock.getDisplayInfoLocked()).thenReturn(info);
- when(logicalDisplayMock.isEnabledLocked()).thenReturn(true);
+ when(logicalDisplayMock.isEnabledLocked()).thenReturn(isEnabled);
when(logicalDisplayMock.isInTransitionLocked()).thenReturn(false);
when(displayDeviceMock.getDisplayDeviceInfoLocked()).thenReturn(deviceInfo);
when(displayDeviceMock.getUniqueId()).thenReturn(uniqueId);
@@ -256,7 +264,14 @@ public final class DisplayPowerControllerTest {
when(displayDeviceConfigMock.getAmbientLightSensor()).thenReturn(
new DisplayDeviceConfig.SensorData());
when(displayDeviceConfigMock.getScreenOffBrightnessSensor()).thenReturn(
- new DisplayDeviceConfig.SensorData());
+ new DisplayDeviceConfig.SensorData() {
+ {
+ type = Sensor.STRING_TYPE_LIGHT;
+ name = null;
+ }
+ });
+ when(displayDeviceConfigMock.getScreenOffBrightnessSensorValueToLux())
+ .thenReturn(new int[0]);
}
@Test
@@ -464,8 +479,164 @@ public final class DisplayPowerControllerTest {
verify(secondFollowerHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
}
+ @Test
+ public void testDoesNotSetScreenStateForNonDefaultDisplayUntilBootCompleted() {
+ // We should still set screen state for the default display
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1);
+ verify(mHolder.displayPowerState, times(2)).setScreenState(anyInt());
+
+ mHolder = createDisplayPowerController(42, UNIQUE_ID);
+
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1);
+ verify(mHolder.displayPowerState, never()).setScreenState(anyInt());
+
+ mHolder.dpc.onBootCompleted();
+ advanceTime(1);
+ verify(mHolder.displayPowerState).setScreenState(anyInt());
+ }
+
+ @Test
+ public void testSetScreenOffBrightnessSensorEnabled_DisplayIsOff() {
+ doAnswer((Answer<Integer>) invocationOnMock ->
+ Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC)
+ .when(() -> Settings.System.getIntForUser(any(ContentResolver.class),
+ eq(Settings.System.SCREEN_BRIGHTNESS_MODE), anyInt(),
+ eq(UserHandle.USER_CURRENT)));
+
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ dpr.policy = DisplayPowerRequest.POLICY_OFF;
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
+ .setLightSensorEnabled(true);
+
+ // The display turns on and we use the brightness value recommended by
+ // ScreenOffBrightnessSensorController
+ clearInvocations(mHolder.screenOffBrightnessSensorController);
+ float brightness = 0.14f;
+ when(mHolder.screenOffBrightnessSensorController.getAutomaticScreenBrightness())
+ .thenReturn(brightness);
+ dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
+ when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
+ when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness(
+ any(BrightnessEvent.class))).thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT);
+
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
+ .getAutomaticScreenBrightness();
+ verify(mHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+ }
+
+ @Test
+ public void testSetScreenOffBrightnessSensorEnabled_DisplayIsInDoze() {
+ doAnswer((Answer<Integer>) invocationOnMock ->
+ Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC)
+ .when(() -> Settings.System.getIntForUser(any(ContentResolver.class),
+ eq(Settings.System.SCREEN_BRIGHTNESS_MODE), anyInt(),
+ eq(UserHandle.USER_CURRENT)));
+
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ dpr.policy = DisplayPowerRequest.POLICY_DOZE;
+ when(mResourcesMock.getBoolean(
+ com.android.internal.R.bool.config_allowAutoBrightnessWhileDozing))
+ .thenReturn(true);
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
+ .setLightSensorEnabled(true);
+
+ // The display turns on and we use the brightness value recommended by
+ // ScreenOffBrightnessSensorController
+ clearInvocations(mHolder.screenOffBrightnessSensorController);
+ float brightness = 0.14f;
+ when(mHolder.screenOffBrightnessSensorController.getAutomaticScreenBrightness())
+ .thenReturn(brightness);
+ dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
+ when(mHolder.displayPowerState.getScreenState()).thenReturn(Display.STATE_ON);
+ when(mHolder.automaticBrightnessController.getAutomaticScreenBrightness(
+ any(BrightnessEvent.class))).thenReturn(PowerManager.BRIGHTNESS_INVALID_FLOAT);
+
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
+ .getAutomaticScreenBrightness();
+ verify(mHolder.animator).animateTo(eq(brightness), anyFloat(), anyFloat());
+ }
+
+ @Test
+ public void testSetScreenOffBrightnessSensorDisabled_AutoBrightnessIsDisabled() {
+ doAnswer((Answer<Integer>) invocationOnMock ->
+ Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL)
+ .when(() -> Settings.System.getIntForUser(any(ContentResolver.class),
+ eq(Settings.System.SCREEN_BRIGHTNESS_MODE), anyInt(),
+ eq(UserHandle.USER_CURRENT)));
+
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ dpr.policy = DisplayPowerRequest.POLICY_OFF;
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
+ .setLightSensorEnabled(false);
+ }
+
+ @Test
+ public void testSetScreenOffBrightnessSensorDisabled_DisplayIsDisabled() {
+ doAnswer((Answer<Integer>) invocationOnMock ->
+ Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC)
+ .when(() -> Settings.System.getIntForUser(any(ContentResolver.class),
+ eq(Settings.System.SCREEN_BRIGHTNESS_MODE), anyInt(),
+ eq(UserHandle.USER_CURRENT)));
+ mHolder = createDisplayPowerController(DISPLAY_ID, UNIQUE_ID, /* isEnabled= */ false);
+
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
+ .setLightSensorEnabled(false);
+ }
+
+ @Test
+ public void testSetScreenOffBrightnessSensorDisabled_DisplayIsOn() {
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ dpr.policy = DisplayPowerRequest.POLICY_BRIGHT;
+
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
+ .setLightSensorEnabled(false);
+ }
+
+ @Test
+ public void testSetScreenOffBrightnessSensorDisabled_DisplayIsAFollower() {
+ DisplayPowerRequest dpr = new DisplayPowerRequest();
+ dpr.policy = DisplayPowerRequest.POLICY_OFF;
+
+ mHolder.dpc.onDisplayChanged(mHolder.hbmMetadata, /* leadDisplayId= */ 42);
+ mHolder.dpc.requestPowerState(dpr, /* waitForNegativeProximity= */ false);
+ advanceTime(1); // Run updatePowerState
+
+ verify(mHolder.screenOffBrightnessSensorController, atLeastOnce())
+ .setLightSensorEnabled(false);
+ }
+
private DisplayPowerControllerHolder createDisplayPowerController(int displayId,
String uniqueId) {
+ return createDisplayPowerController(displayId, uniqueId, /* isEnabled= */ true);
+ }
+
+ private DisplayPowerControllerHolder createDisplayPowerController(int displayId,
+ String uniqueId, boolean isEnabled) {
final DisplayPowerState displayPowerState = mock(DisplayPowerState.class);
final DualRampAnimator<DisplayPowerState> animator = mock(DualRampAnimator.class);
final AutomaticBrightnessController automaticBrightnessController =
@@ -473,9 +644,12 @@ public final class DisplayPowerControllerTest {
final BrightnessMappingStrategy brightnessMappingStrategy =
mock(BrightnessMappingStrategy.class);
final HysteresisLevels hysteresisLevels = mock(HysteresisLevels.class);
+ final ScreenOffBrightnessSensorController screenOffBrightnessSensorController =
+ mock(ScreenOffBrightnessSensorController.class);
DisplayPowerController.Injector injector = new TestInjector(displayPowerState, animator,
- automaticBrightnessController, brightnessMappingStrategy, hysteresisLevels);
+ automaticBrightnessController, brightnessMappingStrategy, hysteresisLevels,
+ screenOffBrightnessSensorController);
final LogicalDisplay display = mock(LogicalDisplay.class);
final DisplayDevice device = mock(DisplayDevice.class);
@@ -483,16 +657,16 @@ public final class DisplayPowerControllerTest {
final BrightnessSetting brightnessSetting = mock(BrightnessSetting.class);
final DisplayDeviceConfig config = mock(DisplayDeviceConfig.class);
- setUpDisplay(displayId, uniqueId, display, device, config);
+ setUpDisplay(displayId, uniqueId, display, device, config, isEnabled);
final DisplayPowerController dpc = new DisplayPowerController(
mContextSpy, injector, mDisplayPowerCallbacksMock, mHandler,
mSensorManagerMock, mDisplayBlankerMock, display,
mBrightnessTrackerMock, brightnessSetting, () -> {},
- hbmMetadata);
+ hbmMetadata, /* bootCompleted= */ false);
return new DisplayPowerControllerHolder(dpc, displayPowerState, brightnessSetting, animator,
- automaticBrightnessController);
+ automaticBrightnessController, screenOffBrightnessSensorController, hbmMetadata);
}
/**
@@ -505,16 +679,22 @@ public final class DisplayPowerControllerTest {
public final BrightnessSetting brightnessSetting;
public final DualRampAnimator<DisplayPowerState> animator;
public final AutomaticBrightnessController automaticBrightnessController;
+ public final ScreenOffBrightnessSensorController screenOffBrightnessSensorController;
+ public final HighBrightnessModeMetadata hbmMetadata;
DisplayPowerControllerHolder(DisplayPowerController dpc,
DisplayPowerState displayPowerState, BrightnessSetting brightnessSetting,
DualRampAnimator<DisplayPowerState> animator,
- AutomaticBrightnessController automaticBrightnessController) {
+ AutomaticBrightnessController automaticBrightnessController,
+ ScreenOffBrightnessSensorController screenOffBrightnessSensorController,
+ HighBrightnessModeMetadata hbmMetadata) {
this.dpc = dpc;
this.displayPowerState = displayPowerState;
this.brightnessSetting = brightnessSetting;
this.animator = animator;
this.automaticBrightnessController = automaticBrightnessController;
+ this.screenOffBrightnessSensorController = screenOffBrightnessSensorController;
+ this.hbmMetadata = hbmMetadata;
}
}
@@ -524,16 +704,19 @@ public final class DisplayPowerControllerTest {
private final AutomaticBrightnessController mAutomaticBrightnessController;
private final BrightnessMappingStrategy mBrightnessMappingStrategy;
private final HysteresisLevels mHysteresisLevels;
+ private final ScreenOffBrightnessSensorController mScreenOffBrightnessSensorController;
TestInjector(DisplayPowerState dps, DualRampAnimator<DisplayPowerState> animator,
AutomaticBrightnessController automaticBrightnessController,
BrightnessMappingStrategy brightnessMappingStrategy,
- HysteresisLevels hysteresisLevels) {
+ HysteresisLevels hysteresisLevels,
+ ScreenOffBrightnessSensorController screenOffBrightnessSensorController) {
mDisplayPowerState = dps;
mAnimator = animator;
mAutomaticBrightnessController = automaticBrightnessController;
mBrightnessMappingStrategy = brightnessMappingStrategy;
mHysteresisLevels = hysteresisLevels;
+ mScreenOffBrightnessSensorController = screenOffBrightnessSensorController;
}
@Override
@@ -597,5 +780,13 @@ public final class DisplayPowerControllerTest {
float minBrighteningThreshold, boolean potentialOldBrightnessRange) {
return mHysteresisLevels;
}
+
+ @Override
+ ScreenOffBrightnessSensorController getScreenOffBrightnessSensorController(
+ SensorManager sensorManager, Sensor lightSensor, Handler handler,
+ ScreenOffBrightnessSensorController.Clock clock, int[] sensorValueToLux,
+ BrightnessMappingStrategy brightnessMapper) {
+ return mScreenOffBrightnessSensorController;
+ }
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
index 63a5ff17fedc..991d5667206b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
@@ -276,11 +276,11 @@ public class JobSchedulerServiceTest {
mService.getMinJobExecutionGuaranteeMs(ejMax));
assertEquals(mService.mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS,
mService.getMinJobExecutionGuaranteeMs(ejHigh));
- assertEquals(mService.mConstants.RUNTIME_MIN_HIGH_PRIORITY_GUARANTEE_MS,
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
mService.getMinJobExecutionGuaranteeMs(ejMaxDowngraded));
- assertEquals(mService.mConstants.RUNTIME_MIN_HIGH_PRIORITY_GUARANTEE_MS,
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
mService.getMinJobExecutionGuaranteeMs(ejHighDowngraded));
- assertEquals(mService.mConstants.RUNTIME_MIN_HIGH_PRIORITY_GUARANTEE_MS,
+ assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
mService.getMinJobExecutionGuaranteeMs(jobHigh));
assertEquals(mService.mConstants.RUNTIME_MIN_GUARANTEE_MS,
mService.getMinJobExecutionGuaranteeMs(jobDef));
diff --git a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
index 89a5b12c0945..8994a488bd56 100644
--- a/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/UserControllerTest.java
@@ -133,6 +133,7 @@ public class UserControllerTest {
private static final int TEST_USER_ID1 = 101;
private static final int TEST_USER_ID2 = 102;
private static final int TEST_USER_ID3 = 103;
+ private static final int SYSTEM_USER_ID = UserHandle.SYSTEM.getIdentifier();
private static final int NONEXIST_USER_ID = 2;
private static final int TEST_PRE_CREATED_USER_ID = 103;
@@ -231,6 +232,31 @@ public class UserControllerTest {
}
@Test
+ public void testStartUser_sendsNoBroadcastsForSystemUserInNonHeadlessMode() {
+ setUpUser(SYSTEM_USER_ID, UserInfo.FLAG_SYSTEM, /* preCreated= */ false,
+ UserManager.USER_TYPE_FULL_SYSTEM);
+ mockIsHeadlessSystemUserMode(false);
+
+ mUserController.startUser(SYSTEM_USER_ID, USER_START_MODE_FOREGROUND);
+
+ assertWithMessage("Broadcasts for starting the system user in non-headless mode")
+ .that(mInjector.mSentIntents).isEmpty();
+ }
+
+ @Test
+ public void testStartUser_sendsBroadcastsForSystemUserInHeadlessMode() {
+ setUpUser(SYSTEM_USER_ID, UserInfo.FLAG_SYSTEM, /* preCreated= */ false,
+ UserManager.USER_TYPE_SYSTEM_HEADLESS);
+ mockIsHeadlessSystemUserMode(true);
+
+ mUserController.startUser(SYSTEM_USER_ID, USER_START_MODE_FOREGROUND);
+
+ assertWithMessage("Broadcasts for starting the system user in headless mode")
+ .that(getActions(mInjector.mSentIntents)).containsExactly(
+ Intent.ACTION_USER_STARTED, Intent.ACTION_USER_STARTING);
+ }
+
+ @Test
public void testStartUser_displayAssignmentFailed() {
doReturn(UserManagerInternal.USER_ASSIGNMENT_RESULT_FAILURE)
.when(mInjector.mUserManagerInternalMock)
@@ -999,6 +1025,10 @@ public class UserControllerTest {
}
}
+ private void mockIsHeadlessSystemUserMode(boolean value) {
+ when(mInjector.isHeadlessSystemUserMode()).thenReturn(value);
+ }
+
private void mockIsUsersOnSecondaryDisplaysEnabled(boolean value) {
when(mInjector.isUsersOnSecondaryDisplaysEnabled()).thenReturn(value);
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
index 4c898b0c4d58..b0c3a6e26b7a 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
@@ -705,7 +705,7 @@ public class BiometricSchedulerTest {
TEST_SENSOR_ID, mock(BiometricLogger.class), biometricContext,
true /* isStrongBiometric */, null /* taskStackListener */,
null /* lockoutTracker */, false /* isKeyguard */,
- true /* shouldVibrate */, false /* isKeyguardBypassEnabled */,
+ true /* shouldVibrate */,
0 /* sensorStrength */);
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
index 139910ba8926..184a5562a689 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
@@ -159,7 +159,7 @@ public class FaceAuthenticationClientTest {
false /* requireConfirmation */, 9 /* sensorId */,
mBiometricLogger, mBiometricContext, true /* isStrongBiometric */,
mUsageStats, null /* mLockoutCache */, false /* allowBackgroundAuthentication */,
- false /* isKeyguardBypassEnabled */, null /* sensorPrivacyManager */,
+ null /* sensorPrivacyManager */,
0 /* biometricStrength */) {
@Override
protected ActivityTaskManager getActivityTaskManager() {
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/InputManagerMockHelper.java b/services/tests/servicestests/src/com/android/server/companion/virtual/InputManagerMockHelper.java
index 51bd5b0f76c9..3cc6b0103322 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/InputManagerMockHelper.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/InputManagerMockHelper.java
@@ -79,7 +79,7 @@ class InputManagerMockHelper {
InputManager.resetInstance(mIInputManagerMock);
}
- private Void handleNativeOpenInputDevice(InvocationOnMock inv) {
+ private long handleNativeOpenInputDevice(InvocationOnMock inv) {
Objects.requireNonNull(mDevicesChangedListener,
"InputController did not register an InputDevicesChangedListener.");
@@ -101,6 +101,7 @@ class InputManagerMockHelper {
}
// Process the device added notification.
mTestableLooper.processAllMessages();
- return null;
+ // Return a placeholder pointer to the native input device.
+ return 1L;
}
}
diff --git a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java
index d28050d29b4a..ff89be75c5d4 100644
--- a/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/LogicalDisplayTest.java
@@ -166,4 +166,16 @@ public class LogicalDisplayTest {
assertEquals(Display.REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY,
mLogicalDisplay.getDisplayInfoLocked().removeMode);
}
+
+ @Test
+ public void testLayoutLimitedRefreshRateNotClearedAfterUpdate() {
+ SurfaceControl.RefreshRateRange refreshRateRange = new SurfaceControl.RefreshRateRange(1,
+ 2);
+ mLogicalDisplay.updateLayoutLimitedRefreshRateLocked(refreshRateRange);
+ mLogicalDisplay.updateDisplayGroupIdLocked(1);
+
+ DisplayInfo result = mLogicalDisplay.getDisplayInfoLocked();
+
+ assertEquals(refreshRateRange, result.layoutLimitedRefreshRate);
+ }
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/FakeEArcNativeWrapper.java b/services/tests/servicestests/src/com/android/server/hdmi/FakeEarcNativeWrapper.java
index ac491f44bbbf..e0c8e818782d 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/FakeEArcNativeWrapper.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/FakeEarcNativeWrapper.java
@@ -18,10 +18,10 @@ package com.android.server.hdmi;
import android.hardware.tv.hdmi.earc.IEArcStatus;
-final class FakeEArcNativeWrapper implements HdmiEarcController.EArcNativeWrapper {
- private static final String TAG = "FakeEArcNativeWrapper";
+final class FakeEarcNativeWrapper implements HdmiEarcController.EarcNativeWrapper {
+ private static final String TAG = "FakeEarcNativeWrapper";
- private boolean mIsEArcEnabled = true;
+ private boolean mIsEarcEnabled = true;
@Override
public boolean nativeInit() {
@@ -29,13 +29,13 @@ final class FakeEArcNativeWrapper implements HdmiEarcController.EArcNativeWrappe
}
@Override
- public void nativeSetEArcEnabled(boolean enabled) {
- mIsEArcEnabled = enabled;
+ public void nativeSetEarcEnabled(boolean enabled) {
+ mIsEarcEnabled = enabled;
}
@Override
- public boolean nativeIsEArcEnabled() {
- return mIsEArcEnabled;
+ public boolean nativeIsEarcEnabled() {
+ return mIsEarcEnabled;
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
index ccfc2b969745..d2b1bdd127d2 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceTvTest.java
@@ -29,9 +29,11 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -91,7 +93,7 @@ public class HdmiCecLocalDeviceTvTest {
private HdmiCecLocalDeviceTv mHdmiCecLocalDeviceTv;
private FakeNativeWrapper mNativeWrapper;
private HdmiEarcController mHdmiEarcController;
- private FakeEArcNativeWrapper mEArcNativeWrapper;
+ private FakeEarcNativeWrapper mEarcNativeWrapper;
private FakePowerManagerWrapper mPowerManager;
private Looper mMyLooper;
private TestLooper mTestLooper = new TestLooper();
@@ -187,9 +189,9 @@ public class HdmiCecLocalDeviceTvTest {
mHdmiCecController = HdmiCecController.createWithNativeWrapper(
mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
mHdmiControlService.setCecController(mHdmiCecController);
- mEArcNativeWrapper = new FakeEArcNativeWrapper();
+ mEarcNativeWrapper = new FakeEarcNativeWrapper();
mHdmiEarcController = HdmiEarcController.createWithNativeWrapper(
- mHdmiControlService, mEArcNativeWrapper);
+ mHdmiControlService, mEarcNativeWrapper);
mHdmiControlService.setEarcController(mHdmiEarcController);
mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
HdmiPortInfo[] hdmiPortInfos = new HdmiPortInfo[2];
@@ -240,6 +242,61 @@ public class HdmiCecLocalDeviceTvTest {
}
}
+
+ private void initiateArcAndValidate() {
+ HdmiCecMessage initiateArc = HdmiCecMessageBuilder.buildInitiateArc(
+ ADDR_AUDIO_SYSTEM,
+ ADDR_TV);
+
+ mNativeWrapper.onCecMessage(initiateArc);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage reportArcInitiated = HdmiCecMessageBuilder.buildReportArcInitiated(
+ ADDR_TV,
+ ADDR_AUDIO_SYSTEM);
+ // <Report ARC Initiated> should only be sent after SAD querying is done
+ assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportArcInitiated);
+
+ // Finish querying SADs
+ assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
+ mNativeWrapper.clearResultMessages();
+ mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+ assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
+ mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
+ mTestLooper.dispatchAll();
+
+ assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated);
+ mNativeWrapper.clearResultMessages();
+ }
+
+ private void initateSamAndValidate() {
+ // Record that previous system audio mode is on.
+ mHdmiCecLocalDeviceTv.setSystemAudioControlFeatureEnabled(true);
+
+ HdmiCecFeatureAction action = new SystemAudioAutoInitiationAction(mHdmiCecLocalDeviceTv,
+ ADDR_AUDIO_SYSTEM);
+ mHdmiCecLocalDeviceTv.addAndStartAction(action);
+ mTestLooper.dispatchAll();
+
+ HdmiCecMessage giveSystemAudioModeStatus =
+ HdmiCecMessageBuilder.buildGiveSystemAudioModeStatus(
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ ADDR_AUDIO_SYSTEM);
+
+ assertThat(mNativeWrapper.getResultMessages()).contains(giveSystemAudioModeStatus);
+
+ HdmiCecMessage reportSystemAudioMode =
+ HdmiCecMessageBuilder.buildReportSystemAudioMode(
+ ADDR_AUDIO_SYSTEM,
+ mHdmiCecLocalDeviceTv.getDeviceInfo().getLogicalAddress(),
+ true);
+ mHdmiControlService.handleCecCommand(reportSystemAudioMode);
+ mTestLooper.dispatchAll();
+
+ assertThat(mHdmiControlService.isSystemAudioActivated()).isTrue();
+ }
+
@Test
public void initialPowerStateIsStandby() {
assertThat(mHdmiCecLocalDeviceTv.getPowerStatus()).isEqualTo(
@@ -1531,30 +1588,33 @@ public class HdmiCecLocalDeviceTvTest {
mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
- HdmiCecMessage initiateArc = HdmiCecMessageBuilder.buildInitiateArc(
- ADDR_AUDIO_SYSTEM,
- ADDR_TV);
+ initiateArcAndValidate();
- mNativeWrapper.onCecMessage(initiateArc);
+ mHdmiControlService.setEarcEnabled(HdmiControlManager.EARC_FEATURE_ENABLED);
mTestLooper.dispatchAll();
- HdmiCecMessage reportArcInitiated = HdmiCecMessageBuilder.buildReportArcInitiated(
+ HdmiCecMessage requestArcTermination = HdmiCecMessageBuilder.buildRequestArcTermination(
ADDR_TV,
ADDR_AUDIO_SYSTEM);
- // <Report ARC Initiated> should only be sent after SAD querying is done
- assertThat(mNativeWrapper.getResultMessages()).doesNotContain(reportArcInitiated);
- // Finish querying SADs
- assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
- mNativeWrapper.clearResultMessages();
- mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
- mTestLooper.dispatchAll();
- assertThat(mNativeWrapper.getResultMessages()).contains(SAD_QUERY);
- mTestLooper.moveTimeForward(HdmiConfig.TIMEOUT_MS);
+ assertThat(mNativeWrapper.getResultMessages()).contains(requestArcTermination);
+ }
+
+ @Test
+ public void fromArcToEarc_SamRemainsOn() {
+ initateSamAndValidate();
+
+ // Emulate Audio device on port 0x2000 (supports ARC and eARC)
+ mNativeWrapper.setPortConnectionStatus(2, true);
+ HdmiCecMessage reportPhysicalAddress =
+ HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
+ ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
+ mNativeWrapper.onCecMessage(reportPhysicalAddress);
mTestLooper.dispatchAll();
- assertThat(mNativeWrapper.getResultMessages()).contains(reportArcInitiated);
- mNativeWrapper.clearResultMessages();
+ initiateArcAndValidate();
+
+ assertThat(mHdmiControlService.isSystemAudioActivated()).isTrue();
mHdmiControlService.setEarcEnabled(HdmiControlManager.EARC_FEATURE_ENABLED);
mTestLooper.dispatchAll();
@@ -1564,5 +1624,34 @@ public class HdmiCecLocalDeviceTvTest {
ADDR_AUDIO_SYSTEM);
assertThat(mNativeWrapper.getResultMessages()).contains(requestArcTermination);
+ assertThat(mHdmiControlService.isSystemAudioActivated()).isTrue();
+ }
+
+ @Test
+ public void disableEarc_SamRemainsOn() {
+ initateSamAndValidate();
+
+ // Emulate Audio device on port 0x2000 (supports ARC and eARC)
+ mNativeWrapper.setPortConnectionStatus(2, true);
+ HdmiCecMessage reportPhysicalAddress =
+ HdmiCecMessageBuilder.buildReportPhysicalAddressCommand(
+ ADDR_AUDIO_SYSTEM, 0x2000, HdmiDeviceInfo.DEVICE_AUDIO_SYSTEM);
+ mNativeWrapper.onCecMessage(reportPhysicalAddress);
+ mTestLooper.dispatchAll();
+
+ mHdmiControlService.setEarcEnabled(HdmiControlManager.EARC_FEATURE_ENABLED);
+ mTestLooper.dispatchAll();
+ assertThat(mHdmiControlService.isSystemAudioActivated()).isTrue();
+
+ mHdmiControlService.initializeEarcLocalDevice(HdmiControlService.INITIATED_BY_BOOT_UP);
+ HdmiEarcLocalDevice mHdmiEarcLocalDeviceTx = mHdmiControlService.getEarcLocalDevice();
+ mHdmiEarcLocalDeviceTx.handleEarcStateChange(Constants.HDMI_EARC_STATUS_EARC_CONNECTED);
+ mTestLooper.moveTimeForward(HdmiEarcLocalDeviceTx.REPORT_CAPS_MAX_DELAY_MS + 1);
+ mTestLooper.dispatchAll();
+ verify(mAudioManager, times(1)).setWiredDeviceConnectionState(
+ any(), eq(1));
+
+ assertThat(mHdmiControlService.isSystemAudioActivated()).isTrue();
+
}
}
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
index 8baad61b40fb..4dd5e94541e4 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
@@ -88,7 +88,7 @@ public class HdmiControlServiceTest {
private MockPlaybackDevice mPlaybackDeviceSpy;
private FakeNativeWrapper mNativeWrapper;
private HdmiEarcController mHdmiEarcController;
- private FakeEArcNativeWrapper mEArcNativeWrapper;
+ private FakeEarcNativeWrapper mEarcNativeWrapper;
private FakePowerManagerWrapper mPowerManager;
private Looper mMyLooper;
private TestLooper mTestLooper = new TestLooper();
@@ -128,9 +128,9 @@ public class HdmiControlServiceTest {
mHdmiCecController = HdmiCecController.createWithNativeWrapper(
mHdmiControlServiceSpy, mNativeWrapper, mHdmiControlServiceSpy.getAtomWriter());
mHdmiControlServiceSpy.setCecController(mHdmiCecController);
- mEArcNativeWrapper = new FakeEArcNativeWrapper();
+ mEarcNativeWrapper = new FakeEarcNativeWrapper();
mHdmiEarcController = HdmiEarcController.createWithNativeWrapper(
- mHdmiControlServiceSpy, mEArcNativeWrapper);
+ mHdmiControlServiceSpy, mEarcNativeWrapper);
mHdmiControlServiceSpy.setEarcController(mHdmiEarcController);
mHdmiControlServiceSpy.setHdmiMhlController(HdmiMhlControllerStub.create(
mHdmiControlServiceSpy));
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiEarcLocalDeviceTxTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiEarcLocalDeviceTxTest.java
index 4ac23f80ac68..c3aec841ac3d 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiEarcLocalDeviceTxTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiEarcLocalDeviceTxTest.java
@@ -69,7 +69,7 @@ public class HdmiEarcLocalDeviceTxTest {
private HdmiEarcLocalDevice mHdmiEarcLocalDeviceTx;
private FakeNativeWrapper mNativeWrapper;
private HdmiEarcController mHdmiEarcController;
- private FakeEArcNativeWrapper mEArcNativeWrapper;
+ private FakeEarcNativeWrapper mEarcNativeWrapper;
private FakePowerManagerWrapper mPowerManager;
private byte[] mEarcCapabilities = new byte[]{
0x01, 0x01, 0x1a, 0x35, 0x0f, 0x7f, 0x07, 0x15, 0x07, 0x50, 0x3d, 0x1f, (byte) 0xc0,
@@ -128,9 +128,9 @@ public class HdmiEarcLocalDeviceTxTest {
mHdmiCecController = HdmiCecController.createWithNativeWrapper(
mHdmiControlService, mNativeWrapper, mHdmiControlService.getAtomWriter());
mHdmiControlService.setCecController(mHdmiCecController);
- mEArcNativeWrapper = new FakeEArcNativeWrapper();
+ mEarcNativeWrapper = new FakeEarcNativeWrapper();
mHdmiEarcController = HdmiEarcController.createWithNativeWrapper(
- mHdmiControlService, mEArcNativeWrapper);
+ mHdmiControlService, mEarcNativeWrapper);
mHdmiControlService.setEarcController(mHdmiEarcController);
mHdmiControlService.setHdmiMhlController(HdmiMhlControllerStub.create(mHdmiControlService));
mHdmiControlService.initService();
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
index d999aa315940..2273fcd22b38 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerServiceUserInfoTest.java
@@ -230,7 +230,7 @@ public class UserManagerServiceUserInfoTest {
mUserManagerService.putUserInfo(createUser(105, FLAG_SYSTEM | FLAG_FULL, null));
mUserManagerService.putUserInfo(createUser(106, FLAG_DEMO | FLAG_FULL, null));
- mUserManagerService.upgradeIfNecessaryLP(null, versionToTest - 1, userTypeVersion);
+ mUserManagerService.upgradeIfNecessaryLP(versionToTest - 1, userTypeVersion);
assertTrue(mUserManagerService.isUserOfType(100, USER_TYPE_PROFILE_MANAGED));
assertTrue((mUserManagerService.getUserInfo(100).flags & FLAG_PROFILE) != 0);
diff --git a/services/tests/servicestests/src/com/android/server/power/LowPowerStandbyControllerTest.java b/services/tests/servicestests/src/com/android/server/power/LowPowerStandbyControllerTest.java
index 8a29f75994bd..d3c0e354838b 100644
--- a/services/tests/servicestests/src/com/android/server/power/LowPowerStandbyControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/LowPowerStandbyControllerTest.java
@@ -16,10 +16,10 @@
package com.android.server.power;
+import static android.os.PowerManager.FEATURE_WAKE_ON_LAN_IN_LOW_POWER_STANDBY;
import static android.os.PowerManager.LOW_POWER_STANDBY_ALLOWED_REASON_ONGOING_CALL;
import static android.os.PowerManager.LOW_POWER_STANDBY_ALLOWED_REASON_TEMP_POWER_SAVE_ALLOWLIST;
import static android.os.PowerManager.LOW_POWER_STANDBY_ALLOWED_REASON_VOICE_INTERACTION;
-import static android.os.PowerManager.LOW_POWER_STANDBY_FEATURE_WAKE_ON_LAN;
import static android.os.PowerManager.LowPowerStandbyPortDescription.MATCH_PORT_LOCAL;
import static android.os.PowerManager.LowPowerStandbyPortDescription.PROTOCOL_TCP;
import static android.os.PowerManager.LowPowerStandbyPortDescription.PROTOCOL_UDP;
@@ -571,17 +571,17 @@ public class LowPowerStandbyControllerTest {
mController.setEnabled(false);
mTestLooper.dispatchAll();
- assertTrue(mController.isAllowed(LOW_POWER_STANDBY_FEATURE_WAKE_ON_LAN));
+ assertTrue(mController.isAllowed(FEATURE_WAKE_ON_LAN_IN_LOW_POWER_STANDBY));
}
@Test
public void testSetAllowedFeatures_isAllowedWhenEnabled() throws Exception {
mController.systemReady();
mController.setEnabled(true);
- mController.setPolicy(policyWithAllowedFeatures(LOW_POWER_STANDBY_FEATURE_WAKE_ON_LAN));
+ mController.setPolicy(policyWithAllowedFeatures(FEATURE_WAKE_ON_LAN_IN_LOW_POWER_STANDBY));
mTestLooper.dispatchAll();
- assertTrue(mController.isAllowed(LOW_POWER_STANDBY_FEATURE_WAKE_ON_LAN));
+ assertTrue(mController.isAllowed(FEATURE_WAKE_ON_LAN_IN_LOW_POWER_STANDBY));
}
@Test
@@ -590,7 +590,7 @@ public class LowPowerStandbyControllerTest {
mController.setEnabled(true);
mTestLooper.dispatchAll();
- assertFalse(mController.isAllowed(LOW_POWER_STANDBY_FEATURE_WAKE_ON_LAN));
+ assertFalse(mController.isAllowed(FEATURE_WAKE_ON_LAN_IN_LOW_POWER_STANDBY));
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsResetTest.java b/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsResetTest.java
new file mode 100644
index 000000000000..a0fb631812f4
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/power/stats/BatteryStatsResetTest.java
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.power.stats;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.BatteryManager;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class BatteryStatsResetTest {
+
+ private static final int BATTERY_NOMINAL_VOLTAGE_MV = 3700;
+ private static final int BATTERY_CAPACITY_UAH = 4_000_000;
+ private static final int BATTERY_CHARGE_RATE_SECONDS_PER_LEVEL = 100;
+
+ private MockClock mMockClock;
+ private MockBatteryStatsImpl mBatteryStatsImpl;
+
+
+ /**
+ * Battery status. Must be one of the following:
+ * {@link BatteryManager#BATTERY_STATUS_UNKNOWN}
+ * {@link BatteryManager#BATTERY_STATUS_CHARGING}
+ * {@link BatteryManager#BATTERY_STATUS_DISCHARGING}
+ * {@link BatteryManager#BATTERY_STATUS_NOT_CHARGING}
+ * {@link BatteryManager#BATTERY_STATUS_FULL}
+ */
+ private int mBatteryStatus;
+ /**
+ * Battery health. Must be one of the following:
+ * {@link BatteryManager#BATTERY_HEALTH_UNKNOWN}
+ * {@link BatteryManager#BATTERY_HEALTH_GOOD}
+ * {@link BatteryManager#BATTERY_HEALTH_OVERHEAT}
+ * {@link BatteryManager#BATTERY_HEALTH_DEAD}
+ * {@link BatteryManager#BATTERY_HEALTH_OVER_VOLTAGE}
+ * {@link BatteryManager#BATTERY_HEALTH_UNSPECIFIED_FAILURE}
+ * {@link BatteryManager#BATTERY_HEALTH_COLD}
+ */
+ private int mBatteryHealth;
+ /**
+ * Battery plug type. Can be the union of any number of the following flags:
+ * {@link BatteryManager#BATTERY_PLUGGED_AC}
+ * {@link BatteryManager#BATTERY_PLUGGED_USB}
+ * {@link BatteryManager#BATTERY_PLUGGED_WIRELESS}
+ * {@link BatteryManager#BATTERY_PLUGGED_DOCK}
+ *
+ * Zero means the device is unplugged.
+ */
+ private int mBatteryPlugType;
+ private int mBatteryLevel;
+ private int mBatteryTemp;
+ private int mBatteryVoltageMv;
+ private int mBatteryChargeUah;
+ private int mBatteryChargeFullUah;
+ private long mBatteryChargeTimeToFullSeconds;
+
+ @Before
+ public void setUp() {
+ final Context context = InstrumentationRegistry.getContext();
+
+ mMockClock = new MockClock();
+ mBatteryStatsImpl = new MockBatteryStatsImpl(mMockClock, context.getFilesDir());
+ mBatteryStatsImpl.onSystemReady();
+
+
+ // Set up the battery state. Start off with a fully charged plugged in battery.
+ mBatteryStatus = BatteryManager.BATTERY_STATUS_FULL;
+ mBatteryHealth = BatteryManager.BATTERY_HEALTH_GOOD;
+ mBatteryPlugType = BatteryManager.BATTERY_PLUGGED_USB;
+ mBatteryLevel = 100;
+ mBatteryTemp = 70; // Arbitrary reasonable temperature.
+ mBatteryVoltageMv = BATTERY_NOMINAL_VOLTAGE_MV;
+ mBatteryChargeUah = BATTERY_CAPACITY_UAH;
+ mBatteryChargeFullUah = BATTERY_CAPACITY_UAH;
+ mBatteryChargeTimeToFullSeconds = 0;
+ }
+
+ @Test
+ public void testResetOnUnplug_highBatteryLevel() {
+ mBatteryStatsImpl.setBatteryStatsConfig(
+ new BatteryStatsImpl.BatteryStatsConfig.Builder()
+ .setResetOnUnplugHighBatteryLevel(true)
+ .build());
+
+ long expectedResetTimeUs = 0;
+
+ unplugBattery();
+ dischargeToLevel(60);
+
+ plugBattery(BatteryManager.BATTERY_PLUGGED_USB);
+ chargeToLevel(80);
+ unplugBattery();
+ // Reset should not occur until battery level above 90.
+ assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs);
+
+ plugBattery(BatteryManager.BATTERY_PLUGGED_USB);
+ chargeToLevel(95);
+ // Reset should not occur until unplug.
+ assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs);
+
+ unplugBattery();
+ // Reset should occur on unplug now that battery level is high (>=90)
+ expectedResetTimeUs = mMockClock.elapsedRealtime() * 1000;
+ assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs);
+
+ // disable high battery level reset on unplug.
+ mBatteryStatsImpl.setBatteryStatsConfig(
+ new BatteryStatsImpl.BatteryStatsConfig.Builder()
+ .setResetOnUnplugHighBatteryLevel(false)
+ .build());
+
+ dischargeToLevel(60);
+
+ plugBattery(BatteryManager.BATTERY_PLUGGED_USB);
+ chargeToLevel(95);
+ unplugBattery();
+ // Reset should not occur since the high battery level logic has been disabled.
+ assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs);
+ }
+
+ @Test
+ public void testResetOnUnplug_significantCharge() {
+ mBatteryStatsImpl.setBatteryStatsConfig(
+ new BatteryStatsImpl.BatteryStatsConfig.Builder()
+ .setResetOnUnplugAfterSignificantCharge(true)
+ .build());
+ long expectedResetTimeUs = 0;
+
+ unplugBattery();
+ // Battery level dropped below 20%.
+ dischargeToLevel(15);
+
+ plugBattery(BatteryManager.BATTERY_PLUGGED_USB);
+ chargeToLevel(50);
+ unplugBattery();
+ // Reset should not occur until battery level above 80
+ assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs);
+
+ plugBattery(BatteryManager.BATTERY_PLUGGED_USB);
+ chargeToLevel(85);
+ unplugBattery();
+ // Reset should not occur because the charge session did not go from 20% to 80%
+ assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs);
+
+ // Battery level dropped below 20%.
+ dischargeToLevel(15);
+
+ plugBattery(BatteryManager.BATTERY_PLUGGED_USB);
+ chargeToLevel(85);
+ unplugBattery();
+ // Reset should occur after significant charge amount.
+ expectedResetTimeUs = mMockClock.elapsedRealtime() * 1000;
+ assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs);
+
+ // disable reset on unplug after significant charge.
+ mBatteryStatsImpl.setBatteryStatsConfig(
+ new BatteryStatsImpl.BatteryStatsConfig.Builder()
+ .setResetOnUnplugAfterSignificantCharge(false)
+ .build());
+
+ // Battery level dropped below 20%.
+ dischargeToLevel(15);
+
+ plugBattery(BatteryManager.BATTERY_PLUGGED_USB);
+ chargeToLevel(85);
+ unplugBattery();
+ // Reset should not occur after significant charge amount.
+ assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs);
+ }
+
+ @Test
+ public void testResetOnUnplug_manyPartialCharges() {
+ long expectedResetTimeUs = 0;
+
+ unplugBattery();
+ // Cumulative battery discharged: 60%.
+ dischargeToLevel(40);
+
+ plugBattery(BatteryManager.BATTERY_PLUGGED_USB);
+ chargeToLevel(80);
+ unplugBattery();
+ // Reset should not occur
+ assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs);
+
+ // Cumulative battery discharged: 100%.
+ dischargeToLevel(40);
+
+ plugBattery(BatteryManager.BATTERY_PLUGGED_USB);
+ chargeToLevel(80);
+ unplugBattery();
+ // Reset should not occur
+ assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs);
+
+ // Cumulative battery discharged: 140%.
+ dischargeToLevel(40);
+
+ plugBattery(BatteryManager.BATTERY_PLUGGED_USB);
+ chargeToLevel(80);
+ unplugBattery();
+ // Reset should not occur
+ assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs);
+
+ // Cumulative battery discharged: 180%.
+ dischargeToLevel(40);
+
+ plugBattery(BatteryManager.BATTERY_PLUGGED_USB);
+ chargeToLevel(80);
+ unplugBattery();
+ // Reset should not occur
+ assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs);
+
+ // Cumulative battery discharged: 220%.
+ dischargeToLevel(40);
+
+ plugBattery(BatteryManager.BATTERY_PLUGGED_USB);
+ chargeToLevel(80);
+ unplugBattery();
+ // Should reset after >200% of cumulative battery discharge
+ expectedResetTimeUs = mMockClock.elapsedRealtime() * 1000;
+ assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs);
+ }
+
+ @Test
+ public void testResetWhilePluggedIn_longPlugIn() {
+ // disable high battery level reset on unplug.
+ mBatteryStatsImpl.setBatteryStatsConfig(
+ new BatteryStatsImpl.BatteryStatsConfig.Builder()
+ .setResetOnUnplugHighBatteryLevel(false)
+ .setResetOnUnplugAfterSignificantCharge(false)
+ .build());
+ long expectedResetTimeUs = 0;
+
+ plugBattery(BatteryManager.BATTERY_PLUGGED_USB);
+ mBatteryStatsImpl.maybeResetWhilePluggedInLocked();
+ // Reset should not occur
+ assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs);
+
+ // Increment time a day
+ incTimeMs(24L * 60L * 60L * 1000L);
+ mBatteryStatsImpl.maybeResetWhilePluggedInLocked();
+ // Reset should still not occur
+ assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs);
+
+ // Increment time a day
+ incTimeMs(24L * 60L * 60L * 1000L);
+ mBatteryStatsImpl.maybeResetWhilePluggedInLocked();
+ // Reset 47 hour threshold crossed, reset should occur.
+ expectedResetTimeUs = mMockClock.elapsedRealtime() * 1000;
+ assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs);
+
+ // Increment time a day
+ incTimeMs(24L * 60L * 60L * 1000L);
+ mBatteryStatsImpl.maybeResetWhilePluggedInLocked();
+ // Reset should not occur
+ assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs);
+
+ // Increment time a day
+ incTimeMs(24L * 60L * 60L * 1000L);
+ mBatteryStatsImpl.maybeResetWhilePluggedInLocked();
+ // Reset another 47 hour threshold crossed, reset should occur.
+ expectedResetTimeUs = mMockClock.elapsedRealtime() * 1000;
+ assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs);
+
+ // Increment time a day
+ incTimeMs(24L * 60L * 60L * 1000L);
+ mBatteryStatsImpl.maybeResetWhilePluggedInLocked();
+ // Reset should not occur
+ assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs);
+
+ unplugBattery();
+ plugBattery(BatteryManager.BATTERY_PLUGGED_USB);
+
+ // Increment time a day
+ incTimeMs(24L * 60L * 60L * 1000L);
+ mBatteryStatsImpl.maybeResetWhilePluggedInLocked();
+ // Reset should not occur, since unplug occurred recently.
+ assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs);
+
+ // Increment time a day
+ incTimeMs(24L * 60L * 60L * 1000L);
+ mBatteryStatsImpl.maybeResetWhilePluggedInLocked();
+ // Reset another 47 hour threshold crossed, reset should occur.
+ expectedResetTimeUs = mMockClock.elapsedRealtime() * 1000;
+ assertThat(mBatteryStatsImpl.getStatsStartRealtime()).isEqualTo(expectedResetTimeUs);
+ }
+
+ private void dischargeToLevel(int targetLevel) {
+ mBatteryStatus = BatteryManager.BATTERY_STATUS_DISCHARGING;
+ for (int level = mBatteryLevel - 1; level >= targetLevel; level--) {
+ prepareBatteryLevel(level);
+ incTimeMs(5000); // Arbitrary discharge rate.
+ updateBatteryState();
+ }
+ }
+
+ private void chargeToLevel(int targetLevel) {
+ mBatteryStatus = BatteryManager.BATTERY_STATUS_CHARGING;
+ for (int level = mBatteryLevel + 1; level <= targetLevel; level++) {
+ if (level >= 100) mBatteryStatus = BatteryManager.BATTERY_STATUS_FULL;
+ prepareBatteryLevel(level);
+ incTimeMs(BATTERY_CHARGE_RATE_SECONDS_PER_LEVEL * 1000);
+ updateBatteryState();
+ }
+ }
+
+ private void unplugBattery() {
+ mBatteryPlugType = 0;
+ updateBatteryState();
+ }
+
+ private void plugBattery(int type) {
+ mBatteryPlugType |= type;
+ updateBatteryState();
+ }
+
+ private void prepareBatteryLevel(int level) {
+ mBatteryLevel = level;
+ mBatteryChargeUah = mBatteryLevel * mBatteryChargeFullUah / 100;
+ mBatteryChargeTimeToFullSeconds =
+ (100 - mBatteryLevel) * BATTERY_CHARGE_RATE_SECONDS_PER_LEVEL;
+ }
+
+ private void incTimeMs(long milliseconds) {
+ mMockClock.realtime += milliseconds;
+ mMockClock.uptime += milliseconds / 2; // Arbitrary slower uptime accumulation
+ mMockClock.currentTime += milliseconds;
+ }
+
+ private void updateBatteryState() {
+ mBatteryStatsImpl.setBatteryStateLocked(mBatteryStatus, mBatteryHealth, mBatteryPlugType,
+ mBatteryLevel, mBatteryTemp, mBatteryVoltageMv, mBatteryChargeUah,
+ mBatteryChargeFullUah, mBatteryChargeTimeToFullSeconds,
+ mMockClock.elapsedRealtime(), mMockClock.uptimeMillis(),
+ mMockClock.currentTimeMillis());
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java b/services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java
index 2f64506f16a9..5df0acb65249 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsProviderTest.java
@@ -371,7 +371,7 @@ public class BatteryUsageStatsProviderTest {
BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
mStatsRule.setCurrentTime(5 * MINUTE_IN_MS);
synchronized (batteryStats) {
- batteryStats.resetAllStatsCmdLocked();
+ batteryStats.resetAllStatsAndHistoryLocked(BatteryStatsImpl.RESET_REASON_ADB_COMMAND);
}
BatteryUsageStatsStore batteryUsageStatsStore = new BatteryUsageStatsStore(context,
batteryStats, new File(context.getCacheDir(), "BatteryUsageStatsProviderTest"),
@@ -391,7 +391,7 @@ public class BatteryUsageStatsProviderTest {
}
mStatsRule.setCurrentTime(25 * MINUTE_IN_MS);
synchronized (batteryStats) {
- batteryStats.resetAllStatsCmdLocked();
+ batteryStats.resetAllStatsAndHistoryLocked(BatteryStatsImpl.RESET_REASON_ADB_COMMAND);
}
synchronized (batteryStats) {
@@ -404,7 +404,7 @@ public class BatteryUsageStatsProviderTest {
}
mStatsRule.setCurrentTime(55 * MINUTE_IN_MS);
synchronized (batteryStats) {
- batteryStats.resetAllStatsCmdLocked();
+ batteryStats.resetAllStatsAndHistoryLocked(BatteryStatsImpl.RESET_REASON_ADB_COMMAND);
}
// This section should be ignored because the timestamp is out or range
@@ -418,7 +418,7 @@ public class BatteryUsageStatsProviderTest {
}
mStatsRule.setCurrentTime(75 * MINUTE_IN_MS);
synchronized (batteryStats) {
- batteryStats.resetAllStatsCmdLocked();
+ batteryStats.resetAllStatsAndHistoryLocked(BatteryStatsImpl.RESET_REASON_ADB_COMMAND);
}
// This section should be ignored because it represents the current stats session
diff --git a/services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsStoreTest.java b/services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsStoreTest.java
index 970020f152bb..b846e3a36656 100644
--- a/services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/stats/BatteryUsageStatsStoreTest.java
@@ -86,7 +86,7 @@ public class BatteryUsageStatsStoreTest {
mMockClock.realtime = 1_000_000;
mMockClock.uptime = 1_000_000;
- mBatteryStats.resetAllStatsCmdLocked();
+ mBatteryStats.resetAllStatsAndHistoryLocked(BatteryStatsImpl.RESET_REASON_ADB_COMMAND);
final long[] timestamps = mBatteryUsageStatsStore.listBatteryUsageStatsTimestamps();
assertThat(timestamps).hasLength(1);
@@ -116,7 +116,7 @@ public class BatteryUsageStatsStoreTest {
final int numberOfSnapshots =
(int) (MAX_BATTERY_STATS_SNAPSHOT_STORAGE_BYTES / snapshotFileSize);
for (int i = 0; i < numberOfSnapshots + 2; i++) {
- mBatteryStats.resetAllStatsCmdLocked();
+ mBatteryStats.resetAllStatsAndHistoryLocked(BatteryStatsImpl.RESET_REASON_ADB_COMMAND);
mMockClock.realtime += 10_000_000;
mMockClock.uptime += 10_000_000;
@@ -143,7 +143,7 @@ public class BatteryUsageStatsStoreTest {
mMockClock.currentTime += 10_000_000;
prepareBatteryStats();
- mBatteryStats.resetAllStatsCmdLocked();
+ mBatteryStats.resetAllStatsAndHistoryLocked(BatteryStatsImpl.RESET_REASON_ADB_COMMAND);
}
assertThat(getDirectorySize(mStoreDirectory)).isNotEqualTo(0);
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/NetworkTimeUpdateServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/NetworkTimeUpdateServiceTest.java
index 10014221f235..2f431bd8a416 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/NetworkTimeUpdateServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/NetworkTimeUpdateServiceTest.java
@@ -22,6 +22,7 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import android.app.time.UnixEpochTime;
@@ -60,7 +61,28 @@ public class NetworkTimeUpdateServiceTest {
}
@Test
- public void engineImpl_refreshIfRequiredAndReschedule_success() {
+ public void engineImpl_refreshAndRescheduleIfRequired_nullNetwork() {
+ mFakeElapsedRealtimeClock.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
+
+ int normalPollingIntervalMillis = 7777777;
+ int shortPollingIntervalMillis = 3333;
+ int tryAgainTimesMax = 5;
+ NetworkTimeUpdateService.Engine engine = new NetworkTimeUpdateService.EngineImpl(
+ mFakeElapsedRealtimeClock,
+ normalPollingIntervalMillis, shortPollingIntervalMillis, tryAgainTimesMax,
+ mMockNtpTrustedTime);
+
+ RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
+ // Trigger the engine's logic.
+ engine.refreshAndRescheduleIfRequired(null, "Test", mockCallback);
+
+ // Expect nothing to have happened.
+ verifyNoMoreInteractions(mMockNtpTrustedTime);
+ verifyNoMoreInteractions(mockCallback);
+ }
+
+ @Test
+ public void engineImpl_refreshAndRescheduleIfRequired_success() {
mFakeElapsedRealtimeClock.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
int normalPollingIntervalMillis = 7777777;
@@ -83,7 +105,7 @@ public class NetworkTimeUpdateServiceTest {
RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
// Trigger the engine's logic.
- engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+ engine.refreshAndRescheduleIfRequired(mDummyNetwork, "Test", mockCallback);
// Expect the refresh attempt to have been made.
verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
@@ -98,7 +120,7 @@ public class NetworkTimeUpdateServiceTest {
}
@Test
- public void engineImpl_refreshIfRequiredAndReschedule_failThenFailRepeatedly() {
+ public void engineImpl_refreshAndRescheduleIfRequired_failThenFailRepeatedly() {
mFakeElapsedRealtimeClock.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
int normalPollingIntervalMillis = 7777777;
@@ -120,7 +142,7 @@ public class NetworkTimeUpdateServiceTest {
RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
// Trigger the engine's logic.
- engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+ engine.refreshAndRescheduleIfRequired(mDummyNetwork, "Test", mockCallback);
// Expect a refresh attempt each time: there's no currently cached result.
verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
@@ -141,7 +163,7 @@ public class NetworkTimeUpdateServiceTest {
}
@Test
- public void engineImpl_refreshIfRequiredAndReschedule_successThenFailRepeatedly() {
+ public void engineImpl_refreshAndRescheduleIfRequired_successThenFailRepeatedly() {
mFakeElapsedRealtimeClock.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
int normalPollingIntervalMillis = 7777777;
@@ -168,7 +190,7 @@ public class NetworkTimeUpdateServiceTest {
RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
// Trigger the engine's logic.
- engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+ engine.refreshAndRescheduleIfRequired(mDummyNetwork, "Test", mockCallback);
// Expect the refresh attempt to have been made: there is no cached network time
// initially.
@@ -182,7 +204,7 @@ public class NetworkTimeUpdateServiceTest {
}
// Increment the current time by enough so that an attempt to refresh the time should be
- // made every time refreshIfRequiredAndReschedule() is called.
+ // made every time refreshAndRescheduleIfRequired() is called.
mFakeElapsedRealtimeClock.incrementMillis(normalPollingIntervalMillis);
// Test multiple follow-up calls.
@@ -195,7 +217,7 @@ public class NetworkTimeUpdateServiceTest {
RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
// Trigger the engine's logic.
- engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+ engine.refreshAndRescheduleIfRequired(mDummyNetwork, "Test", mockCallback);
// Expect a refresh attempt each time as the cached network time is too old.
verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
@@ -221,7 +243,7 @@ public class NetworkTimeUpdateServiceTest {
}
@Test
- public void engineImpl_refreshIfRequiredAndReschedule_successThenFail_tryAgainTimesZero() {
+ public void engineImpl_refreshAndRescheduleIfRequired_successThenFail_tryAgainTimesZero() {
mFakeElapsedRealtimeClock.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
int normalPollingIntervalMillis = 7777777;
@@ -248,7 +270,7 @@ public class NetworkTimeUpdateServiceTest {
RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
// Trigger the engine's logic.
- engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+ engine.refreshAndRescheduleIfRequired(mDummyNetwork, "Test", mockCallback);
// Expect the refresh attempt to have been made: there is no cached network time
// initially.
@@ -262,7 +284,7 @@ public class NetworkTimeUpdateServiceTest {
}
// Increment the current time by enough so that an attempt to refresh the time should be
- // made every time refreshIfRequiredAndReschedule() is called.
+ // made every time refreshAndRescheduleIfRequired() is called.
mFakeElapsedRealtimeClock.incrementMillis(normalPollingIntervalMillis);
// Test multiple follow-up calls.
@@ -275,7 +297,7 @@ public class NetworkTimeUpdateServiceTest {
RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
// Trigger the engine's logic.
- engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+ engine.refreshAndRescheduleIfRequired(mDummyNetwork, "Test", mockCallback);
// Expect a refresh attempt each time as the cached network time is too old.
verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
@@ -297,7 +319,7 @@ public class NetworkTimeUpdateServiceTest {
}
@Test
- public void engineImpl_refreshIfRequiredAndReschedule_successThenFail_tryAgainTimesNegative() {
+ public void engineImpl_refreshAndRescheduleIfRequired_successThenFail_tryAgainTimesNegative() {
mFakeElapsedRealtimeClock.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
int normalPollingIntervalMillis = 7777777;
@@ -324,7 +346,7 @@ public class NetworkTimeUpdateServiceTest {
RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
// Trigger the engine's logic.
- engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+ engine.refreshAndRescheduleIfRequired(mDummyNetwork, "Test", mockCallback);
// Expect the refresh attempt to have been made: there is no cached network time
// initially.
@@ -338,7 +360,7 @@ public class NetworkTimeUpdateServiceTest {
}
// Increment the current time by enough so that an attempt to refresh the time should be
- // made every time refreshIfRequiredAndReschedule() is called.
+ // made every time refreshAndRescheduleIfRequired() is called.
mFakeElapsedRealtimeClock.incrementMillis(normalPollingIntervalMillis);
// Test multiple follow-up calls.
@@ -351,7 +373,7 @@ public class NetworkTimeUpdateServiceTest {
RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
// Trigger the engine's logic.
- engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+ engine.refreshAndRescheduleIfRequired(mDummyNetwork, "Test", mockCallback);
// Expect a refresh attempt each time as the cached network time is too old.
verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
@@ -373,7 +395,7 @@ public class NetworkTimeUpdateServiceTest {
}
@Test
- public void engineImpl_refreshIfRequiredAndReschedule_successFailSuccess() {
+ public void engineImpl_refreshAndRescheduleIfRequired_successFailSuccess() {
mFakeElapsedRealtimeClock.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
int normalPollingIntervalMillis = 7777777;
@@ -398,7 +420,7 @@ public class NetworkTimeUpdateServiceTest {
RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
// Trigger the engine's logic.
- engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+ engine.refreshAndRescheduleIfRequired(mDummyNetwork, "Test", mockCallback);
// Expect the refresh attempt to have been made: there is no cached network time
// initially.
@@ -413,7 +435,7 @@ public class NetworkTimeUpdateServiceTest {
}
// Increment the current time by enough so that the cached time result is too old and an
- // attempt to refresh the time should be made every time refreshIfRequiredAndReschedule() is
+ // attempt to refresh the time should be made every time refreshAndRescheduleIfRequired() is
// called.
mFakeElapsedRealtimeClock.incrementMillis(normalPollingIntervalMillis);
@@ -426,7 +448,7 @@ public class NetworkTimeUpdateServiceTest {
RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
// Trigger the engine's logic.
- engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+ engine.refreshAndRescheduleIfRequired(mDummyNetwork, "Test", mockCallback);
// Expect the refresh attempt to have been made: the timeResult is too old.
verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
@@ -458,7 +480,7 @@ public class NetworkTimeUpdateServiceTest {
RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
// Trigger the engine's logic.
- engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+ engine.refreshAndRescheduleIfRequired(mDummyNetwork, "Test", mockCallback);
// Expect the refresh attempt to have been made: the timeResult is too old.
verify(mMockNtpTrustedTime).forceRefresh(mDummyNetwork);
@@ -473,12 +495,12 @@ public class NetworkTimeUpdateServiceTest {
}
/**
- * Confirms that if a refreshIfRequiredAndReschedule() call is made, e.g. for reasons besides
+ * Confirms that if a refreshAndRescheduleIfRequired() call is made, e.g. for reasons besides
* scheduled alerts, and the latest time is not too old, then an NTP refresh won't be attempted.
* A suggestion will still be made.
*/
@Test
- public void engineImpl_refreshIfRequiredAndReschedule_noRefreshIfLatestIsFresh() {
+ public void engineImpl_refreshAndRescheduleIfRequired_noRefreshIfLatestIsFresh() {
mFakeElapsedRealtimeClock.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
int normalPollingIntervalMillis = 7777777;
@@ -498,7 +520,7 @@ public class NetworkTimeUpdateServiceTest {
RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
// Trigger the engine's logic.
- engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+ engine.refreshAndRescheduleIfRequired(mDummyNetwork, "Test", mockCallback);
// Expect no refresh attempt to have been made.
verify(mMockNtpTrustedTime, never()).forceRefresh(any());
@@ -516,11 +538,11 @@ public class NetworkTimeUpdateServiceTest {
}
/**
- * Confirms that if a refreshIfRequiredAndReschedule() call is made, e.g. for reasons besides
+ * Confirms that if a refreshAndRescheduleIfRequired() call is made, e.g. for reasons besides
* scheduled alerts, and the latest time is too old, then an NTP refresh will be attempted.
*/
@Test
- public void engineImpl_refreshIfRequiredAndReschedule_failureHandlingAfterLatestIsTooOld() {
+ public void engineImpl_refreshAndRescheduleIfRequired_failureHandlingAfterLatestIsTooOld() {
mFakeElapsedRealtimeClock.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
int normalPollingIntervalMillis = 7777777;
@@ -541,7 +563,7 @@ public class NetworkTimeUpdateServiceTest {
RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
// Trigger the engine's logic.
- engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+ engine.refreshAndRescheduleIfRequired(mDummyNetwork, "Test", mockCallback);
// Expect a refresh attempt to have been made.
verify(mMockNtpTrustedTime, times(1)).forceRefresh(mDummyNetwork);
@@ -556,11 +578,11 @@ public class NetworkTimeUpdateServiceTest {
}
/**
- * Confirms that if a refreshIfRequiredAndReschedule() call is made and there was a recently
+ * Confirms that if a refreshAndRescheduleIfRequired() call is made and there was a recently
* failed refresh, then another won't be scheduled too soon.
*/
@Test
- public void engineImpl_refreshIfRequiredAndReschedule_minimumRefreshTimeEnforced() {
+ public void engineImpl_refreshAndRescheduleIfRequired_minimumRefreshTimeEnforced() {
mFakeElapsedRealtimeClock.setElapsedRealtimeMillis(ARBITRARY_ELAPSED_REALTIME_MILLIS);
int normalPollingIntervalMillis = 7777777;
@@ -574,7 +596,7 @@ public class NetworkTimeUpdateServiceTest {
NtpTrustedTime.TimeResult timeResult = createNtpTimeResult(
mFakeElapsedRealtimeClock.getElapsedRealtimeMillis());
- // Simulate an initial call to refreshIfRequiredAndReschedule() prime the "last refresh
+ // Simulate an initial call to refreshAndRescheduleIfRequired() prime the "last refresh
// attempt" time. A cached time value is available, but it's too old but the refresh
// attempt will fail.
long lastRefreshAttemptElapsedMillis;
@@ -586,7 +608,7 @@ public class NetworkTimeUpdateServiceTest {
RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
// Trigger the engine's logic.
- engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+ engine.refreshAndRescheduleIfRequired(mDummyNetwork, "Test", mockCallback);
// Expect a refresh attempt to have been made.
verify(mMockNtpTrustedTime, times(1)).forceRefresh(mDummyNetwork);
@@ -606,7 +628,7 @@ public class NetworkTimeUpdateServiceTest {
reset(mMockNtpTrustedTime);
}
- // Simulate a second call to refreshIfRequiredAndReschedule() very soon after the first, as
+ // Simulate a second call to refreshAndRescheduleIfRequired() very soon after the first, as
// might happen if there were a network state change.
// The cached time value is available, but it's still too old. Because the last call was so
// recent, no refresh should take place and the next scheduled refresh time should be
@@ -619,7 +641,7 @@ public class NetworkTimeUpdateServiceTest {
RefreshCallbacks mockCallback = mock(RefreshCallbacks.class);
// Trigger the engine's logic.
- engine.refreshIfRequiredAndReschedule(mDummyNetwork, "Test", mockCallback);
+ engine.refreshAndRescheduleIfRequired(mDummyNetwork, "Test", mockCallback);
// Expect no refresh attempt to have been made: time elapsed isn't enough.
verify(mMockNtpTrustedTime, never()).forceRefresh(any());
diff --git a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
index f040da8fa2d4..6bd280aae11d 100644
--- a/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/vibrator/VibratorManagerServiceTest.java
@@ -130,8 +130,10 @@ public class VibratorManagerServiceTest {
private static final PowerSaveState NORMAL_POWER_STATE = new PowerSaveState.Builder().build();
private static final PowerSaveState LOW_POWER_STATE = new PowerSaveState.Builder()
.setBatterySaverEnabled(true).build();
- private static final AudioAttributes AUDIO_ATTRS =
+ private static final AudioAttributes AUDIO_ALARM_ATTRS =
new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_ALARM).build();
+ private static final AudioAttributes AUDIO_NOTIFICATION_ATTRS =
+ new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION).build();
private static final VibrationAttributes ALARM_ATTRS =
new VibrationAttributes.Builder().setUsage(VibrationAttributes.USAGE_ALARM).build();
private static final VibrationAttributes HAPTIC_FEEDBACK_ATTRS =
@@ -142,6 +144,8 @@ public class VibratorManagerServiceTest {
private static final VibrationAttributes RINGTONE_ATTRS =
new VibrationAttributes.Builder().setUsage(
VibrationAttributes.USAGE_RINGTONE).build();
+ private static final VibrationAttributes UNKNOWN_ATTRS =
+ new VibrationAttributes.Builder().setUsage(VibrationAttributes.USAGE_UNKNOWN).build();
@Rule
public MockitoRule rule = MockitoJUnit.rule();
@@ -860,25 +864,79 @@ public class VibratorManagerServiceTest {
}
@Test
- public void vibrate_withNewRepeatingVibration_cancelsOngoingEffect() throws Exception {
+ public void vibrate_withNewSameImportanceVibrationAndBothRepeating_cancelsOngoingEffect()
+ throws Exception {
mockVibrators(1);
mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
VibratorManagerService service = createSystemReadyService();
- VibrationEffect alarmEffect = VibrationEffect.createWaveform(
- new long[]{10_000, 10_000}, new int[]{128, 255}, -1);
- vibrate(service, alarmEffect, ALARM_ATTRS);
+ VibrationEffect repeatingEffect = VibrationEffect.createWaveform(
+ new long[]{10_000, 10_000}, new int[]{128, 255}, 1);
+ vibrate(service, repeatingEffect, ALARM_ATTRS);
// VibrationThread will start this vibration async, wait until it has started.
assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getAllEffectSegments().isEmpty(),
service, TEST_TIMEOUT_MILLIS));
+ VibrationEffect repeatingEffect2 = VibrationEffect.createWaveform(
+ new long[]{10_000, 10_000}, new int[]{128, 255}, 1);
+ vibrate(service, repeatingEffect2, ALARM_ATTRS);
+
+ // VibrationThread will start this vibration async, so wait before checking it started.
+ assertTrue(waitUntil(s -> mVibratorProviders.get(1).getAllEffectSegments().size() == 2,
+ service, TEST_TIMEOUT_MILLIS));
+
+ // The second vibration should have recorded that the vibrators were turned on.
+ verify(mBatteryStatsMock, times(2)).noteVibratorOn(anyInt(), anyLong());
+
+ cancelVibrate(service); // Clean up repeating effect.
+ }
+
+ @Test
+ public void vibrate_withNewSameImportanceVibrationButOngoingIsRepeating_ignoreNewVibration()
+ throws Exception {
+ mockVibrators(1);
+ FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1);
+ VibratorManagerService service = createSystemReadyService();
+
VibrationEffect repeatingEffect = VibrationEffect.createWaveform(
- new long[]{10, 10}, new int[]{128, 255}, 1);
- vibrate(service, repeatingEffect, NOTIFICATION_ATTRS);
+ new long[]{10, 10_000}, new int[]{255, 0}, 1);
+ vibrate(service, repeatingEffect, ALARM_ATTRS);
+
+ // VibrationThread will start this vibration async, wait until the off waveform step.
+ assertTrue(waitUntil(s -> fakeVibrator.getOffCount() > 0, service, TEST_TIMEOUT_MILLIS));
+
+ vibrateAndWaitUntilFinished(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK),
+ ALARM_ATTRS);
+
+ // The second vibration shouldn't have recorded that the vibrators were turned on.
+ verify(mBatteryStatsMock, times(1)).noteVibratorOn(anyInt(), anyLong());
+ // The second vibration shouldn't have played any prebaked segment.
+ assertFalse(mVibratorProviders.get(1).getAllEffectSegments().stream()
+ .anyMatch(PrebakedSegment.class::isInstance));
+ cancelVibrate(service); // Clean up long effect.
+ }
+
+ @Test
+ public void vibrate_withNewUnknownUsageVibrationAndRepeating_cancelsOngoingEffect()
+ throws Exception {
+ mockVibrators(1);
+ VibratorManagerService service = createSystemReadyService();
+
+ VibrationEffect repeatingEffect = VibrationEffect.createWaveform(
+ new long[]{10_000, 10_000}, new int[]{128, 255}, 1);
+ vibrate(service, repeatingEffect, ALARM_ATTRS);
+
+ // VibrationThread will start this vibration async, wait until it has started.
+ assertTrue(waitUntil(s -> !mVibratorProviders.get(1).getAllEffectSegments().isEmpty(),
+ service, TEST_TIMEOUT_MILLIS));
+
+ VibrationEffect repeatingEffect2 = VibrationEffect.createWaveform(
+ new long[]{10_000, 10_000}, new int[]{128, 255}, 1);
+ vibrate(service, repeatingEffect2, UNKNOWN_ATTRS);
// VibrationThread will start this vibration async, so wait before checking it started.
- assertTrue(waitUntil(s -> mVibratorProviders.get(1).getAllEffectSegments().size() > 2,
+ assertTrue(waitUntil(s -> mVibratorProviders.get(1).getAllEffectSegments().size() == 2,
service, TEST_TIMEOUT_MILLIS));
// The second vibration should have recorded that the vibrators were turned on.
@@ -888,6 +946,31 @@ public class VibratorManagerServiceTest {
}
@Test
+ public void vibrate_withNewUnknownUsageVibrationAndNotRepeating_ignoreNewVibration()
+ throws Exception {
+ mockVibrators(1);
+ FakeVibratorControllerProvider fakeVibrator = mVibratorProviders.get(1);
+ VibratorManagerService service = createSystemReadyService();
+
+ VibrationEffect alarmEffect = VibrationEffect.createWaveform(
+ new long[]{10, 10_000}, new int[]{255, 0}, -1);
+ vibrate(service, alarmEffect, ALARM_ATTRS);
+
+ // VibrationThread will start this vibration async, wait until the off waveform step.
+ assertTrue(waitUntil(s -> fakeVibrator.getOffCount() > 0, service, TEST_TIMEOUT_MILLIS));
+
+ vibrateAndWaitUntilFinished(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK),
+ UNKNOWN_ATTRS);
+
+ // The second vibration shouldn't have recorded that the vibrators were turned on.
+ verify(mBatteryStatsMock, times(1)).noteVibratorOn(anyInt(), anyLong());
+ // The second vibration shouldn't have played any prebaked segment.
+ assertFalse(mVibratorProviders.get(1).getAllEffectSegments().stream()
+ .anyMatch(PrebakedSegment.class::isInstance));
+ cancelVibrate(service); // Clean up long effect.
+ }
+
+ @Test
public void vibrate_withOngoingHigherImportanceVibration_ignoresEffect() throws Exception {
mockVibrators(1);
mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_AMPLITUDE_CONTROL);
@@ -941,6 +1024,39 @@ public class VibratorManagerServiceTest {
}
@Test
+ public void vibrate_withOngoingLowerImportanceExternalVibration_cancelsOngoingVibration()
+ throws Exception {
+ mockVibrators(1);
+ mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL);
+ mVibratorProviders.get(1).setSupportedEffects(VibrationEffect.EFFECT_CLICK);
+ setRingerMode(AudioManager.RINGER_MODE_NORMAL);
+ VibratorManagerService service = createSystemReadyService();
+
+ IBinder firstToken = mock(IBinder.class);
+ IExternalVibrationController controller = mock(IExternalVibrationController.class);
+ ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME,
+ AUDIO_ALARM_ATTRS,
+ controller, firstToken);
+ int scale = mExternalVibratorService.onExternalVibrationStart(externalVibration);
+
+ vibrateAndWaitUntilFinished(service, VibrationEffect.get(VibrationEffect.EFFECT_CLICK),
+ RINGTONE_ATTRS);
+
+ assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale);
+ // The external vibration should have been cancelled
+ verify(controller).mute();
+ assertEquals(Arrays.asList(false, true, false),
+ mVibratorProviders.get(1).getExternalControlStates());
+ // The new vibration should have recorded that the vibrators were turned on.
+ verify(mBatteryStatsMock, times(1)).noteVibratorOn(anyInt(), anyLong());
+ // One segment played is the prebaked CLICK from the new vibration.
+ assertEquals(1,
+ mVibratorProviders.get(1).getAllEffectSegments().stream()
+ .filter(PrebakedSegment.class::isInstance)
+ .count());
+ }
+
+ @Test
public void vibrate_withOngoingSameImportancePipelinedVibration_continuesOngoingEffect()
throws Exception {
VibrationAttributes pipelineAttrs = new VibrationAttributes.Builder(HAPTIC_FEEDBACK_ATTRS)
@@ -1434,7 +1550,8 @@ public class VibratorManagerServiceTest {
createSystemReadyService();
IBinder binderToken = mock(IBinder.class);
- ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME, AUDIO_ATTRS,
+ ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME,
+ AUDIO_ALARM_ATTRS,
mock(IExternalVibrationController.class), binderToken);
int scale = mExternalVibratorService.onExternalVibrationStart(externalVibration);
assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale);
@@ -1452,7 +1569,8 @@ public class VibratorManagerServiceTest {
createSystemReadyService();
IBinder binderToken = mock(IBinder.class);
- ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME, AUDIO_ATTRS,
+ ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME,
+ AUDIO_ALARM_ATTRS,
mock(IExternalVibrationController.class), binderToken);
int scale = mExternalVibratorService.onExternalVibrationStart(externalVibration);
mExternalVibratorService.onExternalVibrationStop(externalVibration);
@@ -1477,7 +1595,8 @@ public class VibratorManagerServiceTest {
IBinder secondToken = mock(IBinder.class);
IExternalVibrationController firstController = mock(IExternalVibrationController.class);
IExternalVibrationController secondController = mock(IExternalVibrationController.class);
- ExternalVibration firstVibration = new ExternalVibration(UID, PACKAGE_NAME, AUDIO_ATTRS,
+ ExternalVibration firstVibration = new ExternalVibration(UID, PACKAGE_NAME,
+ AUDIO_ALARM_ATTRS,
firstController, firstToken);
int firstScale = mExternalVibratorService.onExternalVibrationStart(firstVibration);
@@ -1522,7 +1641,8 @@ public class VibratorManagerServiceTest {
// VibrationThread will start this vibration async, so wait until vibration is triggered.
assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
- ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME, AUDIO_ATTRS,
+ ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME,
+ AUDIO_ALARM_ATTRS,
mock(IExternalVibrationController.class));
int scale = mExternalVibratorService.onExternalVibrationStart(externalVibration);
assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale);
@@ -1534,6 +1654,87 @@ public class VibratorManagerServiceTest {
}
@Test
+ public void onExternalVibration_withOngoingHigherImportanceVibration_ignoreNewVibration()
+ throws Exception {
+ mockVibrators(1);
+ mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL,
+ IVibrator.CAP_AMPLITUDE_CONTROL);
+ VibratorManagerService service = createSystemReadyService();
+
+ VibrationEffect effect = VibrationEffect.createOneShot(10 * TEST_TIMEOUT_MILLIS, 100);
+ vibrate(service, effect, RINGTONE_ATTRS);
+
+ // VibrationThread will start this vibration async, so wait until vibration is triggered.
+ assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
+
+ ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME,
+ AUDIO_ALARM_ATTRS,
+ mock(IExternalVibrationController.class));
+ int scale = mExternalVibratorService.onExternalVibrationStart(externalVibration);
+ // External vibration is ignored.
+ assertEquals(IExternalVibratorService.SCALE_MUTE, scale);
+
+ // Vibration is not cancelled.
+ assertFalse(waitUntil(s -> !s.isVibrating(1), service, CLEANUP_TIMEOUT_MILLIS));
+ assertEquals(Arrays.asList(false), mVibratorProviders.get(1).getExternalControlStates());
+ cancelVibrate(service); // Clean up long effect.
+ }
+
+ @Test
+ public void onExternalVibration_withNewSameImportanceButRepeating_cancelsOngoingVibration()
+ throws Exception {
+ mockVibrators(1);
+ mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL,
+ IVibrator.CAP_AMPLITUDE_CONTROL);
+ VibratorManagerService service = createSystemReadyService();
+
+ VibrationEffect repeatingEffect = VibrationEffect.createWaveform(
+ new long[]{10, 10_000}, new int[]{255, 0}, 1);
+ vibrate(service, repeatingEffect, ALARM_ATTRS);
+
+ // VibrationThread will start this vibration async, so wait until vibration is triggered.
+ assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
+
+ ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME,
+ AUDIO_ALARM_ATTRS, mock(IExternalVibrationController.class));
+ int scale = mExternalVibratorService.onExternalVibrationStart(externalVibration);
+ assertNotEquals(IExternalVibratorService.SCALE_MUTE, scale);
+
+ // Vibration is cancelled.
+ assertTrue(waitUntil(s -> !s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
+ assertEquals(Arrays.asList(false, true),
+ mVibratorProviders.get(1).getExternalControlStates());
+ }
+
+ @Test
+ public void onExternalVibration_withNewSameImportanceButOngoingIsRepeating_ignoreNewVibration()
+ throws Exception {
+ mockVibrators(1);
+ mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL,
+ IVibrator.CAP_AMPLITUDE_CONTROL);
+ VibratorManagerService service = createSystemReadyService();
+
+ VibrationEffect repeatingEffect = VibrationEffect.createWaveform(
+ new long[]{10_000, 10_000}, new int[]{128, 255}, 1);
+ vibrate(service, repeatingEffect, NOTIFICATION_ATTRS);
+
+ // VibrationThread will start this vibration async, so wait until vibration is triggered.
+ assertTrue(waitUntil(s -> s.isVibrating(1), service, TEST_TIMEOUT_MILLIS));
+
+ ExternalVibration externalVibration = new ExternalVibration(UID, PACKAGE_NAME,
+ AUDIO_NOTIFICATION_ATTRS,
+ mock(IExternalVibrationController.class));
+ int scale = mExternalVibratorService.onExternalVibrationStart(externalVibration);
+ // New vibration is ignored.
+ assertEquals(IExternalVibratorService.SCALE_MUTE, scale);
+
+ // Vibration is not cancelled.
+ assertFalse(waitUntil(s -> !s.isVibrating(1), service, CLEANUP_TIMEOUT_MILLIS));
+ assertEquals(Arrays.asList(false), mVibratorProviders.get(1).getExternalControlStates());
+ cancelVibrate(service); // Clean up long effect.
+ }
+
+ @Test
public void onExternalVibration_withRingtone_usesRingerModeSettings() {
mockVibrators(1);
mVibratorProviders.get(1).setCapabilities(IVibrator.CAP_EXTERNAL_CONTROL);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 96ec2b83a496..f08d0f5f71a4 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -18,6 +18,8 @@ package com.android.server.notification;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
+import static android.app.ActivityManagerInternal.ServiceNotificationPolicy.NOT_FOREGROUND_SERVICE;
+import static android.app.ActivityManagerInternal.ServiceNotificationPolicy.SHOW_IMMEDIATELY;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.Notification.EXTRA_ALLOW_DURING_SETUP;
import static android.app.Notification.FLAG_AUTO_CANCEL;
@@ -175,7 +177,6 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
-import android.permission.PermissionCheckerManager;
import android.permission.PermissionManager;
import android.provider.DeviceConfig;
import android.provider.MediaStore;
@@ -441,6 +442,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
+ setDpmAppOppsExemptFromDismissal(false);
+
mService = new TestableNotificationManagerService(mContext, mNotificationRecordLogger,
mNotificationInstanceIdSequence);
@@ -1183,6 +1186,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
public void testEnqueuedBlockedNotifications_appBlockedChannelForegroundService()
throws Exception {
when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY);
NotificationChannel channel = new NotificationChannel("blocked", "name",
NotificationManager.IMPORTANCE_NONE);
@@ -1205,6 +1210,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
public void testEnqueuedBlockedNotifications_userBlockedChannelForegroundService()
throws Exception {
when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY);
NotificationChannel channel =
new NotificationChannel("blockedbyuser", "name", IMPORTANCE_HIGH);
@@ -1284,6 +1291,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
public void testEnqueuedBlockedNotifications_blockedAppForegroundService() throws Exception {
when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
when(mPermissionHelper.hasPermission(mUid)).thenReturn(false);
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY);
final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
@@ -1613,6 +1622,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testEnqueueNotificationWithTag_FgsAddsFlags_dismissalAllowed() throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY);
mContext.getTestablePermissions().setPermission(
android.Manifest.permission.USE_COLORIZED_NOTIFICATIONS, PERMISSION_GRANTED);
DeviceConfig.setProperty(
@@ -1643,6 +1654,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testEnqueueNotificationWithTag_FGSaddsFlags_dismissalNotAllowed() throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY);
mContext.getTestablePermissions().setPermission(
android.Manifest.permission.USE_COLORIZED_NOTIFICATIONS, PERMISSION_GRANTED);
DeviceConfig.setProperty(
@@ -1931,6 +1944,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCancelAllNotifications_IgnoreForegroundService() throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt())).thenReturn(SHOW_IMMEDIATELY);
final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
mBinderService.enqueueNotificationWithTag(PKG, PKG,
@@ -1945,7 +1960,27 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@Test
+ public void testCancelAllNotifications_FgsFlag_NoFgs_Allowed() throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(NOT_FOREGROUND_SERVICE);
+ final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
+ sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
+ mBinderService.enqueueNotificationWithTag(PKG, PKG,
+ "testCancelAllNotifications_IgnoreForegroundService",
+ sbn.getId(), sbn.getNotification(), sbn.getUserId());
+ mBinderService.cancelAllNotifications(PKG, sbn.getUserId());
+ waitForIdle();
+ StatusBarNotification[] notifs =
+ mBinderService.getActiveNotifications(sbn.getPackageName());
+ assertEquals(0, notifs.length);
+ }
+
+ @Test
public void testCancelAllNotifications_IgnoreOtherPackages() throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
final StatusBarNotification sbn = generateNotificationRecord(null).getSbn();
sbn.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
mBinderService.enqueueNotificationWithTag(PKG, PKG,
@@ -2033,6 +2068,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testRemoveForegroundServiceFlag_ImmediatelyAfterEnqueue() throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
Notification n =
new Notification.Builder(mContext, mTestNotificationChannel.getId())
.setSmallIcon(android.R.drawable.sym_def_app_icon)
@@ -2070,6 +2108,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCancelNotificationWithTag_fromApp_cannotCancelFgsChild()
throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
mService.isSystemUid = false;
final NotificationRecord parent = generateNotificationRecord(
mTestNotificationChannel, 1, "group", true);
@@ -2093,6 +2134,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCancelNotificationWithTag_fromApp_cannotCancelFgsParent()
throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
mService.isSystemUid = false;
final NotificationRecord parent = generateNotificationRecord(
mTestNotificationChannel, 1, "group", true);
@@ -2162,6 +2206,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCancelAllNotificationsFromApp_cannotCancelFgsChild()
throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
mService.isSystemUid = false;
final NotificationRecord parent = generateNotificationRecord(
mTestNotificationChannel, 1, "group", true);
@@ -2187,6 +2234,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCancelAllNotifications_fromApp_cannotCancelFgsParent()
throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
mService.isSystemUid = false;
final NotificationRecord parent = generateNotificationRecord(
mTestNotificationChannel, 1, "group", true);
@@ -2308,6 +2358,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCancelNotificationsFromListener_clearAll_GroupWithFgsParent()
throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
final NotificationRecord parent = generateNotificationRecord(
mTestNotificationChannel, 1, "group", true);
parent.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
@@ -2331,6 +2384,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCancelNotificationsFromListener_clearAll_GroupWithFgsChild()
throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
final NotificationRecord parent = generateNotificationRecord(
mTestNotificationChannel, 1, "group", true);
final NotificationRecord child = generateNotificationRecord(
@@ -2429,6 +2485,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCancelNotificationsFromListener_clearAll_Fgs()
throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
final NotificationRecord child2 = generateNotificationRecord(
mTestNotificationChannel, 3, null, false);
child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
@@ -2493,6 +2552,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCancelNotificationsFromListener_byKey_GroupWithFgsParent()
throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
final NotificationRecord parent = generateNotificationRecord(
mTestNotificationChannel, 1, "group", true);
parent.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
@@ -2518,6 +2580,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCancelNotificationsFromListener_byKey_GroupWithFgsChild()
throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
final NotificationRecord parent = generateNotificationRecord(
mTestNotificationChannel, 1, "group", true);
final NotificationRecord child = generateNotificationRecord(
@@ -2623,6 +2688,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCancelNotificationsFromListener_byKey_Fgs()
throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
final NotificationRecord child2 = generateNotificationRecord(
mTestNotificationChannel, 3, null, false);
child2.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
@@ -2789,6 +2857,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testUserInitiatedCancelAllWithGroup_ForegroundServiceFlag() throws Exception {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
final NotificationRecord parent = generateNotificationRecord(
mTestNotificationChannel, 1, "group", true);
final NotificationRecord child = generateNotificationRecord(
@@ -6249,6 +6320,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testRemoveForegroundServiceFlagFromNotification_enqueued() {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
Notification n = new Notification.Builder(mContext, "").build();
n.flags |= FLAG_FOREGROUND_SERVICE;
@@ -6268,6 +6342,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testRemoveForegroundServiceFlagFromNotification_posted() {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
Notification n = new Notification.Builder(mContext, "").build();
n.flags |= FLAG_FOREGROUND_SERVICE;
@@ -6291,6 +6368,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCannotRemoveForegroundFlagWhenOverLimit_enqueued() {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
Notification n = new Notification.Builder(mContext, "").build();
StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, i, null, mUid, 0,
@@ -6319,6 +6399,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCannotRemoveForegroundFlagWhenOverLimit_posted() {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
Notification n = new Notification.Builder(mContext, "").build();
StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, i, null, mUid, 0,
@@ -8327,7 +8410,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
assertNotNull(n.publicVersion.bigContentView);
assertNotNull(n.publicVersion.headsUpContentView);
- mService.fixNotification(n, PKG, "tag", 9, 0, mUid);
+ mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE);
assertNull(n.contentView);
assertNull(n.bigContentView);
@@ -9018,6 +9101,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCanPostFgsWhenOverLimit() throws RemoteException {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
i, null, false).getSbn();
@@ -9043,6 +9129,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
@Test
public void testCannotPostNonFgsWhenOverLimit() throws RemoteException {
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(SHOW_IMMEDIATELY);
for (int i = 0; i < NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS; i++) {
StatusBarNotification sbn = generateNotificationRecord(mTestNotificationChannel,
i, null, false).getSbn();
@@ -9065,6 +9154,17 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
"testCanPostFgsWhenOverLimit - non fgs over limit!",
sbn2.getId(), sbn2.getNotification(), sbn2.getUserId());
+
+ when(mAmi.applyForegroundServiceNotification(
+ any(), anyString(), anyInt(), anyString(), anyInt()))
+ .thenReturn(NOT_FOREGROUND_SERVICE);
+ final StatusBarNotification sbn3 = generateNotificationRecord(mTestNotificationChannel,
+ 101, null, false).getSbn();
+ sbn3.getNotification().flags |= FLAG_FOREGROUND_SERVICE;
+ mBinderService.enqueueNotificationWithTag(PKG, PKG,
+ "testCanPostFgsWhenOverLimit - fake fgs over limit!",
+ sbn3.getId(), sbn3.getNotification(), sbn3.getUserId());
+
waitForIdle();
StatusBarNotification[] notifs =
@@ -10137,7 +10237,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
.setFullScreenIntent(mock(PendingIntent.class), true)
.build();
- mService.fixNotification(n, PKG, "tag", 9, 0, mUid);
+ mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE);
final int stickyFlag = n.flags & Notification.FLAG_FSI_REQUESTED_BUT_DENIED;
@@ -10153,7 +10253,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
throws Exception {
verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI,
- /* permissionState= */ PermissionCheckerManager.PERMISSION_HARD_DENIED,
+ /* permissionState= */ PermissionManager.PERMISSION_HARD_DENIED,
/* isSticky= */ true);
}
@@ -10162,7 +10262,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
throws Exception {
verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI,
- /* permissionState= */ PermissionCheckerManager.PERMISSION_SOFT_DENIED,
+ /* permissionState= */ PermissionManager.PERMISSION_SOFT_DENIED,
/* isSticky= */ true);
}
@@ -10171,7 +10271,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
throws Exception {
verifyStickyHun(/* flag= */ SHOW_STICKY_HUN_FOR_DENIED_FSI,
- /* permissionState= */ PermissionCheckerManager.PERMISSION_GRANTED,
+ /* permissionState= */ PermissionManager.PERMISSION_GRANTED,
/* isSticky= */ false);
}
@@ -10180,7 +10280,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
throws Exception {
verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE,
- /* permissionState= */ PermissionCheckerManager.PERMISSION_HARD_DENIED,
+ /* permissionState= */ PermissionManager.PERMISSION_HARD_DENIED,
/* isSticky= */ true);
}
@@ -10189,7 +10289,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
throws Exception {
verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE,
- /* permissionState= */ PermissionCheckerManager.PERMISSION_SOFT_DENIED,
+ /* permissionState= */ PermissionManager.PERMISSION_SOFT_DENIED,
/* isSticky= */ true);
}
@@ -10198,13 +10298,40 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
throws Exception {
verifyStickyHun(/* flag= */ FSI_FORCE_DEMOTE,
- /* permissionState= */ PermissionCheckerManager.PERMISSION_GRANTED,
+ /* permissionState= */ PermissionManager.PERMISSION_GRANTED,
/* isSticky= */ true);
}
@Test
- public void fixSystemNotification_withOnGoingFlag_shouldBeNonDismissible()
+ public void fixNotification_withFgsFlag_butIsNotFgs() throws Exception {
+ final ApplicationInfo applicationInfo = new ApplicationInfo();
+ when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
+ .thenReturn(applicationInfo);
+
+ Notification n = new Notification.Builder(mContext, "test")
+ .setFlag(FLAG_FOREGROUND_SERVICE, true)
+ .setFlag(FLAG_CAN_COLORIZE, true)
+ .build();
+
+ mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE);
+
+ assertFalse(n.isForegroundService());
+ assertFalse(n.hasColorizedPermission());
+ }
+
+ @Test
+ public void fixSystemNotification_withOnGoingFlag_shouldBeDismissible()
throws Exception {
+ final ApplicationInfo ai = new ApplicationInfo();
+ ai.packageName = "pkg";
+ ai.uid = mUid;
+ ai.flags |= ApplicationInfo.FLAG_SYSTEM;
+
+ when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
+ .thenReturn(ai);
+ when(mAppOpsManager.checkOpNoThrow(
+ AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, ai.uid,
+ ai.packageName)).thenReturn(AppOpsManager.MODE_IGNORED);
// Given: a notification from an app on the system partition has the flag
// FLAG_ONGOING_EVENT set
// feature flag: ALLOW_DISMISS_ONGOING is on
@@ -10213,16 +10340,11 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
.setOngoing(true)
.build();
- final ApplicationInfo systemAppInfo = new ApplicationInfo();
- systemAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
- when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
- .thenReturn(systemAppInfo);
-
// When: fix the notification with NotificationManagerService
- mService.fixNotification(n, PKG, "tag", 9, 0, mUid);
+ mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE);
- // Then: the notification's flag FLAG_NO_DISMISS should be set
- assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS);
+ // Then: the notification's flag FLAG_NO_DISMISS should not be set
+ assertSame(0, n.flags & Notification.FLAG_NO_DISMISS);
}
@Test
@@ -10238,7 +10360,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
.build();
// When: fix the notification with NotificationManagerService
- mService.fixNotification(n, PKG, "tag", 9, 0, mUid);
+ mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE);
// Then: the notification's flag FLAG_NO_DISMISS should be set
assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS);
@@ -10254,7 +10376,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
.build();
// When: fix the notification with NotificationManagerService
- mService.fixNotification(n, PKG, "tag", 9, 0, mUid);
+ mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE);
// Then: the notification's flag FLAG_NO_DISMISS should not be set
assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
@@ -10272,53 +10394,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
n.flags |= Notification.FLAG_NO_DISMISS;
// When: fix the notification with NotificationManagerService
- mService.fixNotification(n, PKG, "tag", 9, 0, mUid);
-
- // Then: the notification's flag FLAG_NO_DISMISS should be cleared
- assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
- }
-
- @Test
- public void fixSystemNotification_withoutOnGoingFlag_shouldBeDismissible() throws Exception {
- // Given: a notification from an app on the system partition doesn't have the flag
- // FLAG_ONGOING_EVENT set
- // feature flag: ALLOW_DISMISS_ONGOING is on
- mTestFlagResolver.setFlagOverride(ALLOW_DISMISS_ONGOING, true);
- Notification n = new Notification.Builder(mContext, "test")
- .setOngoing(false)
- .build();
-
- final ApplicationInfo systemAppInfo = new ApplicationInfo();
- systemAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
- when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
- .thenReturn(systemAppInfo);
-
- // When: fix the notification with NotificationManagerService
- mService.fixNotification(n, PKG, "tag", 9, 0, mUid);
-
- // Then: the notification's flag FLAG_NO_DISMISS should not be set
- assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
- }
-
- @Test
- public void fixSystemNotification_withoutOnGoingFlag_withNoDismissFlag_shouldBeDismissible()
- throws Exception {
- // Given: a notification from an app on the system partition doesn't have the flag
- // FLAG_ONGOING_EVENT set, but has the flag FLAG_NO_DISMISS set
- // feature flag: ALLOW_DISMISS_ONGOING is on
- mTestFlagResolver.setFlagOverride(ALLOW_DISMISS_ONGOING, true);
- Notification n = new Notification.Builder(mContext, "test")
- .setOngoing(false)
- .build();
- n.flags |= Notification.FLAG_NO_DISMISS;
-
- final ApplicationInfo systemAppInfo = new ApplicationInfo();
- systemAppInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
- when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
- .thenReturn(systemAppInfo);
-
- // When: fix the notification with NotificationManagerService
- mService.fixNotification(n, PKG, "tag", 9, 0, mUid);
+ mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE);
// Then: the notification's flag FLAG_NO_DISMISS should be cleared
assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
@@ -10336,7 +10412,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
.build();
// When: fix the notification with NotificationManagerService
- mService.fixNotification(n, PKG, "tag", 9, 0, mUid);
+ mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE);
// Then: the notification's flag FLAG_NO_DISMISS should not be set
assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
@@ -10357,7 +10433,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
n.flags |= Notification.FLAG_NO_DISMISS;
// When: fix the notification with NotificationManagerService
- mService.fixNotification(n, PKG, "tag", 9, 0, mUid);
+ mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE);
// Then: the notification's flag FLAG_NO_DISMISS should be cleared
assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
@@ -10374,7 +10450,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
.build();
// When: fix the notification with NotificationManagerService
- mService.fixNotification(n, PKG, "tag", 9, 0, mUid);
+ mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE);
// Then: the notification's flag FLAG_NO_DISMISS should not be set
assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
@@ -10387,43 +10463,48 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
// Given: a notification has the flag FLAG_ONGOING_EVENT set
// feature flag: ALLOW_DISMISS_ONGOING is on
mTestFlagResolver.setFlagOverride(ALLOW_DISMISS_ONGOING, true);
- setSystemExemptFromDismissal(false);
+ setDpmAppOppsExemptFromDismissal(false);
Notification n = new Notification.Builder(mContext, "test")
.setOngoing(true)
.build();
// When: fix the notification with NotificationManagerService
- mService.fixNotification(n, PKG, "tag", 9, 0, mUid);
+ mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE);
// Then: the notification's flag FLAG_NO_DISMISS should be set
assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS);
}
@Test
- public void fixSystemExemptAppOpNotification_withFlag_shouldBeNonDismissible()
+ public void fixExemptAppOpNotification_withFlag_shouldBeNonDismissible()
throws Exception {
+ final ApplicationInfo ai = new ApplicationInfo();
+ ai.packageName = PKG;
+ ai.uid = mUid;
+ ai.flags |= ApplicationInfo.FLAG_SYSTEM;
+
+ when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
+ .thenReturn(ai);
when(mAppOpsManager.checkOpNoThrow(
AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, mUid,
PKG)).thenReturn(AppOpsManager.MODE_ALLOWED);
// Given: a notification has the flag FLAG_ONGOING_EVENT set
// feature flag: ALLOW_DISMISS_ONGOING is on
mTestFlagResolver.setFlagOverride(ALLOW_DISMISS_ONGOING, true);
- setSystemExemptFromDismissal(true);
+ setDpmAppOppsExemptFromDismissal(true);
Notification n = new Notification.Builder(mContext, "test")
.setOngoing(true)
.build();
// When: fix the notification with NotificationManagerService
- mService.fixNotification(n, PKG, "tag", 9, 0, mUid);
+ mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE);
- // Then: the notification's flag FLAG_NO_DISMISS should be set
- assertNotSame(0, n.flags & Notification.FLAG_NO_DISMISS);
-
- setSystemExemptFromDismissal(false);
+ // Then: the notification's flag FLAG_NO_DISMISS should be cleared
+ assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
}
@Test
- public void fixSystemExemptAppOpNotification_withoutFlag_shouldBeNonDismissible()
+ public void fixExemptAppOpNotification_withoutAppOpsFlag_shouldBeDismissible()
throws Exception {
when(mAppOpsManager.checkOpNoThrow(
AppOpsManager.OP_SYSTEM_EXEMPT_FROM_DISMISSIBLE_NOTIFICATIONS, mUid,
@@ -10431,19 +10512,19 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
// Given: a notification has the flag FLAG_ONGOING_EVENT set
// feature flag: ALLOW_DISMISS_ONGOING is on
mTestFlagResolver.setFlagOverride(ALLOW_DISMISS_ONGOING, true);
- setSystemExemptFromDismissal(false);
+ setDpmAppOppsExemptFromDismissal(false);
Notification n = new Notification.Builder(mContext, "test")
.setOngoing(true)
.build();
// When: fix the notification with NotificationManagerService
- mService.fixNotification(n, PKG, "tag", 9, 0, mUid);
+ mService.fixNotification(n, PKG, "tag", 9, 0, mUid, NOT_FOREGROUND_SERVICE);
// Then: the notification's flag FLAG_NO_DISMISS should not be set
- assertEquals(0, n.flags & Notification.FLAG_NO_DISMISS);
+ assertSame(0, n.flags & Notification.FLAG_NO_DISMISS);
}
- private void setSystemExemptFromDismissal(boolean isOn) {
+ private void setDpmAppOppsExemptFromDismissal(boolean isOn) {
DeviceConfig.setProperty(
DeviceConfig.NAMESPACE_DEVICE_POLICY_MANAGER,
/* name= */ "application_exemptions",
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index f0f9204c4e4e..1ecd4a1ffd7e 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -57,6 +57,7 @@ import static junit.framework.Assert.fail;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -1576,6 +1577,47 @@ public class PreferencesHelperTest extends UiServiceTestCase {
new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX), true, false));
}
+ @Test
+ public void testUpdateChannel_downgradeImportance() {
+ mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_DEFAULT),
+ true, false);
+
+ assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true, false));
+ }
+
+ @Test
+ public void testUpdateChannel_upgradeImportance_ignored() {
+ mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_DEFAULT),
+ true, false);
+
+ assertFalse(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX), true, false));
+ }
+
+ @Test
+ public void testUpdateChannel_badImportance() {
+ mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_DEFAULT),
+ true, false);
+
+ assertThrows(IllegalArgumentException.class,
+ () -> mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_NONE - 1), true,
+ false));
+
+ assertThrows(IllegalArgumentException.class,
+ () -> mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_UNSPECIFIED), true,
+ false));
+
+ assertThrows(IllegalArgumentException.class,
+ () -> mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX + 1), true,
+ false));
+ }
@Test
public void testUpdate() throws Exception {
diff --git a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
index ad47773747d4..3ecbbfeed254 100644
--- a/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
+++ b/services/tests/wmtests/src/com/android/server/policy/ModifierShortcutTests.java
@@ -16,37 +16,43 @@
package com.android.server.policy;
-import static android.view.KeyEvent.KEYCODE_A;
import static android.view.KeyEvent.KEYCODE_ALT_LEFT;
import static android.view.KeyEvent.KEYCODE_B;
import static android.view.KeyEvent.KEYCODE_C;
import static android.view.KeyEvent.KEYCODE_CTRL_LEFT;
import static android.view.KeyEvent.KEYCODE_E;
-import static android.view.KeyEvent.KEYCODE_L;
+import static android.view.KeyEvent.KEYCODE_K;
import static android.view.KeyEvent.KEYCODE_M;
import static android.view.KeyEvent.KEYCODE_META_LEFT;
import static android.view.KeyEvent.KEYCODE_N;
import static android.view.KeyEvent.KEYCODE_P;
import static android.view.KeyEvent.KEYCODE_S;
+import static android.view.KeyEvent.KEYCODE_SHIFT_LEFT;
import static android.view.KeyEvent.KEYCODE_SLASH;
import static android.view.KeyEvent.KEYCODE_SPACE;
import static android.view.KeyEvent.KEYCODE_TAB;
+import static android.view.KeyEvent.KEYCODE_U;
import static android.view.KeyEvent.KEYCODE_Z;
import android.content.Intent;
import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
import android.util.SparseArray;
+import androidx.test.filters.SmallTest;
+
import org.junit.Test;
+@Presubmit
+@SmallTest
public class ModifierShortcutTests extends ShortcutKeyTestBase {
private static final SparseArray<String> META_SHORTCUTS = new SparseArray<>();
static {
- META_SHORTCUTS.append(KEYCODE_A, Intent.CATEGORY_APP_CALCULATOR);
+ META_SHORTCUTS.append(KEYCODE_U, Intent.CATEGORY_APP_CALCULATOR);
META_SHORTCUTS.append(KEYCODE_B, Intent.CATEGORY_APP_BROWSER);
META_SHORTCUTS.append(KEYCODE_C, Intent.CATEGORY_APP_CONTACTS);
META_SHORTCUTS.append(KEYCODE_E, Intent.CATEGORY_APP_EMAIL);
- META_SHORTCUTS.append(KEYCODE_L, Intent.CATEGORY_APP_CALENDAR);
+ META_SHORTCUTS.append(KEYCODE_K, Intent.CATEGORY_APP_CALENDAR);
META_SHORTCUTS.append(KEYCODE_M, Intent.CATEGORY_APP_MAPS);
META_SHORTCUTS.append(KEYCODE_P, Intent.CATEGORY_APP_MUSIC);
META_SHORTCUTS.append(KEYCODE_S, Intent.CATEGORY_APP_MESSAGING);
@@ -82,7 +88,16 @@ public class ModifierShortcutTests extends ShortcutKeyTestBase {
@Test
public void testCtrlSpace() {
sendKeyCombination(new int[]{KEYCODE_CTRL_LEFT, KEYCODE_SPACE}, 0);
- mPhoneWindowManager.assertSwitchKeyboardLayout();
+ mPhoneWindowManager.assertSwitchKeyboardLayout(1);
+ }
+
+ /**
+ * CTRL + SHIFT + SPACE to switch keyboard layout backwards.
+ */
+ @Test
+ public void testCtrlShiftSpace() {
+ sendKeyCombination(new int[]{KEYCODE_CTRL_LEFT, KEYCODE_SHIFT_LEFT, KEYCODE_SPACE}, 0);
+ mPhoneWindowManager.assertSwitchKeyboardLayout(-1);
}
/**
@@ -91,7 +106,16 @@ public class ModifierShortcutTests extends ShortcutKeyTestBase {
@Test
public void testMetaSpace() {
sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_SPACE}, 0);
- mPhoneWindowManager.assertSwitchKeyboardLayout();
+ mPhoneWindowManager.assertSwitchKeyboardLayout(1);
+ }
+
+ /**
+ * META + SHIFT + SPACE to switch keyboard layout backwards.
+ */
+ @Test
+ public void testMetaShiftSpace() {
+ sendKeyCombination(new int[]{KEYCODE_META_LEFT, KEYCODE_SHIFT_LEFT, KEYCODE_SPACE}, 0);
+ mPhoneWindowManager.assertSwitchKeyboardLayout(-1);
}
/**
diff --git a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
index a76b82babe08..6da9d0c606cf 100644
--- a/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
+++ b/services/tests/wmtests/src/com/android/server/policy/TestPhoneWindowManager.java
@@ -237,6 +237,7 @@ class TestPhoneWindowManager {
overrideLaunchAccessibility();
doReturn(false).when(mPhoneWindowManager).keyguardOn();
doNothing().when(mContext).startActivityAsUser(any(), any());
+ Mockito.reset(mContext);
}
void tearDown() {
@@ -399,8 +400,12 @@ class TestPhoneWindowManager {
void assertLaunchCategory(String category) {
waitForIdle();
ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
- verify(mContext).startActivityAsUser(intentCaptor.capture(), any());
- Assert.assertTrue(intentCaptor.getValue().getSelector().hasCategory(category));
+ try {
+ verify(mContext).startActivityAsUser(intentCaptor.capture(), any());
+ Assert.assertTrue(intentCaptor.getValue().getSelector().hasCategory(category));
+ } catch (Throwable t) {
+ throw new AssertionError("failed to assert " + category, t);
+ }
// Reset verifier for next call.
Mockito.reset(mContext);
}
@@ -410,9 +415,9 @@ class TestPhoneWindowManager {
verify(mStatusBarManagerInternal).showRecentApps(anyBoolean());
}
- void assertSwitchKeyboardLayout() {
+ void assertSwitchKeyboardLayout(int direction) {
waitForIdle();
- verify(mWindowManagerFuncsImpl).switchKeyboardLayout(anyInt(), anyInt());
+ verify(mWindowManagerFuncsImpl).switchKeyboardLayout(anyInt(), eq(direction));
}
void assertTakeBugreport() {
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index 6bb77694b8cb..c694707743f6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -26,6 +26,7 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static android.view.WindowInsets.Type.navigationBars;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
+import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
import static android.view.WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
import static android.view.WindowManager.LayoutParams.FLAG_DIM_BEHIND;
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
@@ -46,13 +47,7 @@ import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
-import static org.mockito.ArgumentMatchers.anyInt;
-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;
import android.graphics.PixelFormat;
@@ -367,23 +362,24 @@ public class DisplayPolicyTests extends WindowTestsBase {
assertEquals(attrs.height - 10, navBarSource.getFrame().height());
}
+ @SetupWindows(addWindows = { W_ACTIVITY, W_NAVIGATION_BAR })
@Test
public void testCanSystemBarsBeShownByUser() {
((TestWindowManagerPolicy) mWm.mPolicy).mIsUserSetupComplete = true;
+ mAppWindow.mAttrs.insetsFlags.behavior = BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
+ mAppWindow.setRequestedVisibleTypes(0, navigationBars());
final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
- final WindowState windowState = mock(WindowState.class);
- final InsetsSourceProvider provider = mock(InsetsSourceProvider.class);
- final InsetsControlTarget controlTarget = mock(InsetsControlTarget.class);
- when(provider.getControlTarget()).thenReturn(controlTarget);
- when(windowState.getControllableInsetProvider()).thenReturn(provider);
- when(controlTarget.isRequestedVisible(anyInt())).thenReturn(true);
+ displayPolicy.addWindowLw(mNavBarWindow, mNavBarWindow.mAttrs);
+ final InsetsSourceProvider navBarProvider = mNavBarWindow.getControllableInsetProvider();
+ navBarProvider.updateControlForTarget(mAppWindow, false);
+ navBarProvider.getSource().setVisible(false);
displayPolicy.setCanSystemBarsBeShownByUser(false);
- displayPolicy.requestTransientBars(windowState, true);
- verify(controlTarget, never()).showInsets(anyInt(), anyBoolean(), any() /* statsToken */);
+ displayPolicy.requestTransientBars(mNavBarWindow, true);
+ assertFalse(mDisplayContent.getInsetsPolicy().isTransient(navigationBars()));
displayPolicy.setCanSystemBarsBeShownByUser(true);
- displayPolicy.requestTransientBars(windowState, true);
- verify(controlTarget).showInsets(anyInt(), anyBoolean(), any() /* statsToken */);
+ displayPolicy.requestTransientBars(mNavBarWindow, true);
+ assertTrue(mDisplayContent.getInsetsPolicy().isTransient(navigationBars()));
}
}
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 c9f758ce1f55..e9aca5666a93 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -279,7 +279,8 @@ public class SizeCompatTests extends WindowTestsBase {
public void testTranslucentActivitiesWhenUnfolding() {
mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true);
setUpDisplaySizeWithApp(2800, 1400);
- mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
+ mActivity.mDisplayContent.setIgnoreOrientationRequest(
+ true /* ignoreOrientationRequest */);
mActivity.mWmService.mLetterboxConfiguration.setLetterboxHorizontalPositionMultiplier(
1.0f /*letterboxVerticalPositionMultiplier*/);
prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
@@ -290,18 +291,23 @@ public class SizeCompatTests extends WindowTestsBase {
.build();
doReturn(false).when(translucentActivity).fillsParent();
mTask.addChild(translucentActivity);
+ assertEquals(translucentActivity.getBounds(), mActivity.getBounds());
mTask.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
spyOn(mActivity);
// Halffold
- setFoldablePosture(translucentActivity, true /* isHalfFolded */, false /* isTabletop */);
+ setFoldablePosture(translucentActivity, true /* isHalfFolded */,
+ false /* isTabletop */);
verify(mActivity).recomputeConfiguration();
+ assertEquals(translucentActivity.getBounds(), mActivity.getBounds());
clearInvocations(mActivity);
// Unfold
- setFoldablePosture(translucentActivity, false /* isHalfFolded */, false /* isTabletop */);
+ setFoldablePosture(translucentActivity, false /* isHalfFolded */,
+ false /* isTabletop */);
verify(mActivity).recomputeConfiguration();
+ assertEquals(translucentActivity.getBounds(), mActivity.getBounds());
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
index dab842c4aa5a..df3af7d2f4fa 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
@@ -24,6 +24,7 @@ import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
@@ -613,4 +614,34 @@ public class TaskFragmentTest extends WindowTestsBase {
assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, tf1.getOrientation(SCREEN_ORIENTATION_UNSET));
assertEquals(SCREEN_ORIENTATION_UNSPECIFIED, task.getOrientation(SCREEN_ORIENTATION_UNSET));
}
+
+ @Test
+ public void testUpdateImeParentForActivityEmbedding() {
+ // Setup two activities in ActivityEmbedding.
+ final Task task = createTask(mDisplayContent);
+ final TaskFragment tf0 = new TaskFragmentBuilder(mAtm)
+ .setParentTask(task)
+ .createActivityCount(1)
+ .setOrganizer(mOrganizer)
+ .setFragmentToken(new Binder())
+ .build();
+ final TaskFragment tf1 = new TaskFragmentBuilder(mAtm)
+ .setParentTask(task)
+ .createActivityCount(1)
+ .setOrganizer(mOrganizer)
+ .setFragmentToken(new Binder())
+ .build();
+ final ActivityRecord activity0 = tf0.getTopMostActivity();
+ final ActivityRecord activity1 = tf1.getTopMostActivity();
+ final WindowState win0 = createWindow(null, TYPE_BASE_APPLICATION, activity0, "win0");
+ final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity1, "win1");
+ doReturn(false).when(mDisplayContent).shouldImeAttachedToApp();
+
+ mDisplayContent.setImeInputTarget(win0);
+ mDisplayContent.setImeLayeringTarget(win1);
+
+ // The ImeParent should be the display.
+ assertEquals(mDisplayContent.getImeContainer().getParent().getSurfaceControl(),
+ mDisplayContent.computeImeParent());
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index 05ee2f24fbaf..3f14217b7a18 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -1018,6 +1018,10 @@ public class TransitionTests extends WindowTestsBase {
@Test
public void testDisplayRotationChange() {
+ final DisplayPolicy displayPolicy = mDisplayContent.getDisplayPolicy();
+ spyOn(displayPolicy);
+ // Simulate gesture navigation (non-movable) so it is not seamless.
+ doReturn(false).when(displayPolicy).navigationBarCanMove();
final Task task = createActivityRecord(mDisplayContent).getTask();
final WindowState statusBar = createWindow(null, TYPE_STATUS_BAR, "statusBar");
final WindowState navBar = createWindow(null, TYPE_NAVIGATION_BAR, "navBar");
@@ -1072,7 +1076,8 @@ public class TransitionTests extends WindowTestsBase {
// Navigation bar finishes drawing after the start transaction, so its fade-in animation
// can execute directly.
- asyncRotationController.handleFinishDrawing(navBar, mMockT);
+ navBar.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
+ asyncRotationController.updateTargetWindows();
assertFalse(asyncRotationController.isTargetToken(navBar.mToken));
assertNull(mDisplayContent.getAsyncRotationController());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
index 4dd5de3b999c..7d6cf4a63c43 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
@@ -49,12 +49,12 @@ import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -91,7 +91,6 @@ import com.android.compatibility.common.util.AdoptShellPermissionsRule;
import org.junit.Rule;
import org.junit.Test;
-import org.junit.rules.ExpectedException;
import org.junit.runner.RunWith;
/**
@@ -104,9 +103,6 @@ import org.junit.runner.RunWith;
public class WindowManagerServiceTests extends WindowTestsBase {
@Rule
- public ExpectedException mExpectedException = ExpectedException.none();
-
- @Rule
public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule(
InstrumentationRegistry.getInstrumentation().getUiAutomation(),
ADD_TRUSTED_DISPLAY);
@@ -198,16 +194,20 @@ public class WindowManagerServiceTests extends WindowTestsBase {
public void testRelayoutExitingWindow() {
final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, "appWin");
final WindowSurfaceController surfaceController = mock(WindowSurfaceController.class);
- doReturn(true).when(surfaceController).hasSurface();
- spyOn(win);
- doReturn(true).when(win).isAnimationRunningSelfOrParent();
win.mWinAnimator.mSurfaceController = surfaceController;
+ win.mWinAnimator.mDrawState = WindowStateAnimator.HAS_DRAWN;
+ doReturn(true).when(surfaceController).hasSurface();
+ spyOn(win.mTransitionController);
+ doReturn(true).when(win.mTransitionController).isShellTransitionsEnabled();
+ doReturn(true).when(win.mTransitionController).inTransition(
+ eq(win.mActivityRecord));
win.mViewVisibility = View.VISIBLE;
win.mHasSurface = true;
win.mActivityRecord.mAppStopped = true;
- win.mActivityRecord.setVisibleRequested(false);
- win.mActivityRecord.setVisible(false);
mWm.mWindowMap.put(win.mClient.asBinder(), win);
+ spyOn(mWm.mWindowPlacerLocked);
+ // Skip unnecessary operations of relayout.
+ doNothing().when(mWm.mWindowPlacerLocked).performSurfacePlacement(anyBoolean());
final int w = 100;
final int h = 200;
final ClientWindowFrames outFrames = new ClientWindowFrames();
@@ -218,6 +218,17 @@ public class WindowManagerServiceTests extends WindowTestsBase {
final Bundle outBundle = new Bundle();
mWm.relayoutWindow(win.mSession, win.mClient, win.mAttrs, w, h, View.GONE, 0, 0, 0,
outFrames, outConfig, outSurfaceControl, outInsetsState, outControls, outBundle);
+ // The window is in transition, so its destruction is deferred.
+ assertTrue(win.mAnimatingExit);
+ assertFalse(win.mDestroying);
+ assertTrue(win.mTransitionController.mAnimatingExitWindows.contains(win));
+
+ win.mAnimatingExit = false;
+ win.mViewVisibility = View.VISIBLE;
+ win.mActivityRecord.setVisibleRequested(false);
+ win.mActivityRecord.setVisible(false);
+ mWm.relayoutWindow(win.mSession, win.mClient, win.mAttrs, w, h, View.GONE, 0, 0, 0,
+ outFrames, outConfig, outSurfaceControl, outInsetsState, outControls, outBundle);
// Because the window is already invisible, it doesn't need to apply exiting animation
// and WMS#tryStartExitingAnimation() will destroy the surface directly.
assertFalse(win.mAnimatingExit);
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index 495a43370163..70af33796ad1 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -1647,11 +1647,16 @@ public class SoundTriggerService extends SystemService {
@Override
public List<ModuleProperties> listModuleProperties(Identity originatorIdentity) {
- Identity middlemanIdentity = new Identity();
- middlemanIdentity.packageName = ActivityThread.currentOpPackageName();
ArrayList<ModuleProperties> moduleList = new ArrayList<>();
- SoundTrigger.listModulesAsMiddleman(moduleList, middlemanIdentity,
- originatorIdentity);
+ try (SafeCloseable ignored = PermissionUtil.establishIdentityDirect(
+ originatorIdentity)) {
+ Identity middlemanIdentity = new Identity();
+ middlemanIdentity.uid = Binder.getCallingUid();
+ middlemanIdentity.pid = Binder.getCallingPid();
+ middlemanIdentity.packageName = ActivityThread.currentOpPackageName();
+ SoundTrigger.listModulesAsMiddleman(moduleList, middlemanIdentity,
+ originatorIdentity);
+ }
return moduleList;
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java
index afee94000edc..ec9bd2fbfa6d 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/DetectorSession.java
@@ -70,6 +70,7 @@ import android.os.RemoteException;
import android.os.SharedMemory;
import android.service.voice.HotwordDetectedResult;
import android.service.voice.HotwordDetectionService;
+import android.service.voice.HotwordDetectionServiceFailure;
import android.service.voice.HotwordDetector;
import android.service.voice.HotwordRejectedResult;
import android.service.voice.IDspHotwordDetectionCallback;
@@ -122,10 +123,16 @@ abstract class DetectorSession {
"Providing hotword detection result to VoiceInteractionService";
// The error codes are used for onError callback
- static final int HOTWORD_DETECTION_SERVICE_DIED = -1;
- static final int CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION = -2;
- static final int CALLBACK_DETECT_TIMEOUT = -3;
- static final int CALLBACK_ONDETECTED_STREAM_COPY_ERROR = -4;
+ static final int HOTWORD_DETECTION_SERVICE_DIED =
+ HotwordDetectionServiceFailure.ERROR_CODE_BINDING_DIED;
+ static final int CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION =
+ HotwordDetectionServiceFailure.ERROR_CODE_ON_DETECTED_SECURITY_EXCEPTION;
+ static final int CALLBACK_DETECT_TIMEOUT =
+ HotwordDetectionServiceFailure.ERROR_CODE_DETECT_TIMEOUT;
+ static final int CALLBACK_ONDETECTED_STREAM_COPY_ERROR =
+ HotwordDetectionServiceFailure.ERROR_CODE_ON_DETECTED_STREAM_COPY_FAILURE;
+ static final int CALLBACK_COPY_AUDIO_DATA_FAILURE =
+ HotwordDetectionServiceFailure.ERROR_CODE_COPY_AUDIO_DATA_FAILURE;
// TODO: These constants need to be refined.
private static final long MAX_UPDATE_TIMEOUT_MILLIS = 30000;
@@ -426,7 +433,9 @@ abstract class DetectorSession {
Slog.w(TAG, "Failed supplying audio data to validator", e);
try {
- callback.onError();
+ callback.onError(
+ new HotwordDetectionServiceFailure(CALLBACK_COPY_AUDIO_DATA_FAILURE,
+ "Copy audio data failure for external source detection."));
} catch (RemoteException ex) {
Slog.w(TAG, "Failed to report onError status: " + ex);
if (getDetectorType() != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
@@ -505,7 +514,10 @@ abstract class DetectorSession {
getDetectorType(),
EXTERNAL_SOURCE_DETECT_SECURITY_EXCEPTION,
mVoiceInteractionServiceUid);
- callback.onError();
+ callback.onError(new HotwordDetectionServiceFailure(
+ CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION,
+ "Security exception occurs in #onDetected"
+ + " method."));
return;
}
HotwordDetectedResult newResult;
@@ -514,7 +526,9 @@ abstract class DetectorSession {
.startCopyingAudioStreams(triggerResult);
} catch (IOException e) {
// TODO: Write event
- callback.onError();
+ callback.onError(new HotwordDetectionServiceFailure(
+ CALLBACK_ONDETECTED_STREAM_COPY_ERROR,
+ "Copy audio stream failure."));
return;
}
callback.onDetected(newResult, /* audioFormat= */ null,
@@ -569,9 +583,11 @@ abstract class DetectorSession {
mRemoteDetectionService = remoteDetectionService;
}
- void reportErrorLocked(int status) {
+ void reportErrorLocked(int errorCode, @NonNull String errorMessage) {
try {
- mCallback.onError(status);
+ // TODO: Use instanceof(this) to get different detector to set the right error source.
+ mCallback.onDetectionFailure(
+ new HotwordDetectionServiceFailure(errorCode, errorMessage));
} catch (RemoteException e) {
Slog.w(TAG, "Failed to report onError status: " + e);
if (getDetectorType() != HotwordDetector.DETECTOR_TYPE_VISUAL_QUERY_DETECTOR) {
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/DspTrustedHotwordDetectorSession.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/DspTrustedHotwordDetectorSession.java
index cb5b9300c197..63e0f466bb10 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/DspTrustedHotwordDetectorSession.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/DspTrustedHotwordDetectorSession.java
@@ -34,6 +34,7 @@ import android.os.RemoteException;
import android.os.SharedMemory;
import android.service.voice.HotwordDetectedResult;
import android.service.voice.HotwordDetectionService;
+import android.service.voice.HotwordDetectionServiceFailure;
import android.service.voice.HotwordDetector;
import android.service.voice.HotwordRejectedResult;
import android.service.voice.IDspHotwordDetectionCallback;
@@ -130,7 +131,9 @@ final class DspTrustedHotwordDetectorSession extends DetectorSession {
HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_DSP,
METRICS_KEYPHRASE_TRIGGERED_DETECT_SECURITY_EXCEPTION,
mVoiceInteractionServiceUid);
- externalCallback.onError(CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION);
+ externalCallback.onDetectionFailure(new HotwordDetectionServiceFailure(
+ CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION,
+ "Security exception occurs in #onDetected method."));
return;
}
saveProximityValueToBundle(result);
@@ -138,7 +141,9 @@ final class DspTrustedHotwordDetectorSession extends DetectorSession {
try {
newResult = mHotwordAudioStreamCopier.startCopyingAudioStreams(result);
} catch (IOException e) {
- externalCallback.onError(CALLBACK_ONDETECTED_STREAM_COPY_ERROR);
+ externalCallback.onDetectionFailure(new HotwordDetectionServiceFailure(
+ CALLBACK_ONDETECTED_STREAM_COPY_ERROR,
+ "Copy audio stream failure."));
return;
}
externalCallback.onKeyphraseDetected(recognitionEvent, newResult);
@@ -201,7 +206,9 @@ final class DspTrustedHotwordDetectorSession extends DetectorSession {
HOTWORD_DETECTOR_KEYPHRASE_TRIGGERED__RESULT__DETECT_TIMEOUT,
mVoiceInteractionServiceUid);
try {
- externalCallback.onError(CALLBACK_DETECT_TIMEOUT);
+ externalCallback.onDetectionFailure(
+ new HotwordDetectionServiceFailure(CALLBACK_DETECT_TIMEOUT,
+ "Timeout to response to the detection result."));
} catch (RemoteException e) {
Slog.w(TAG, "Failed to report onError status: ", e);
HotwordMetricsLogger.writeDetectorEvent(
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
index b672b00fa8c3..1ba397529bbd 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/HotwordDetectionConnection.java
@@ -690,8 +690,8 @@ final class HotwordDetectionConnection {
//TODO(b265535257): report error to either service only.
synchronized (HotwordDetectionConnection.this.mLock) {
runForEachDetectorSessionLocked((session) -> {
- session.reportErrorLocked(
- DetectorSession.HOTWORD_DETECTION_SERVICE_DIED);
+ session.reportErrorLocked(DetectorSession.HOTWORD_DETECTION_SERVICE_DIED,
+ "Detection service is dead.");
});
}
// Can improve to log exit reason if needed
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoftwareTrustedHotwordDetectorSession.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoftwareTrustedHotwordDetectorSession.java
index 3ad963d21943..522d832c41bc 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/SoftwareTrustedHotwordDetectorSession.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/SoftwareTrustedHotwordDetectorSession.java
@@ -33,6 +33,7 @@ import android.os.RemoteException;
import android.os.SharedMemory;
import android.service.voice.HotwordDetectedResult;
import android.service.voice.HotwordDetectionService;
+import android.service.voice.HotwordDetectionServiceFailure;
import android.service.voice.HotwordDetector;
import android.service.voice.HotwordRejectedResult;
import android.service.voice.IDspHotwordDetectionCallback;
@@ -121,7 +122,9 @@ final class SoftwareTrustedHotwordDetectorSession extends DetectorSession {
HotwordDetector.DETECTOR_TYPE_TRUSTED_HOTWORD_SOFTWARE,
METRICS_KEYPHRASE_TRIGGERED_DETECT_SECURITY_EXCEPTION,
mVoiceInteractionServiceUid);
- mSoftwareCallback.onError();
+ mSoftwareCallback.onError(new HotwordDetectionServiceFailure(
+ CALLBACK_ONDETECTED_GOT_SECURITY_EXCEPTION,
+ "Security exception occurs in #onDetected method."));
return;
}
saveProximityValueToBundle(result);
@@ -130,7 +133,9 @@ final class SoftwareTrustedHotwordDetectorSession extends DetectorSession {
newResult = mHotwordAudioStreamCopier.startCopyingAudioStreams(result);
} catch (IOException e) {
// TODO: Write event
- mSoftwareCallback.onError();
+ mSoftwareCallback.onError(new HotwordDetectionServiceFailure(
+ CALLBACK_ONDETECTED_STREAM_COPY_ERROR,
+ "Copy audio stream failure."));
return;
}
mSoftwareCallback.onDetected(newResult, null, null);
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VisualQueryDetectorSession.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VisualQueryDetectorSession.java
index 33150d8789eb..c397812b4158 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VisualQueryDetectorSession.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VisualQueryDetectorSession.java
@@ -16,6 +16,9 @@
package com.android.server.voiceinteraction;
+import static android.service.voice.VisualQueryDetectionServiceFailure.ERROR_CODE_ILLEGAL_ATTENTION_STATE;
+import static android.service.voice.VisualQueryDetectionServiceFailure.ERROR_CODE_ILLEGAL_STREAMING_STATE;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -30,6 +33,7 @@ import android.service.voice.IDetectorSessionVisualQueryDetectionCallback;
import android.service.voice.IMicrophoneHotwordDetectionVoiceInteractionCallback;
import android.service.voice.ISandboxedDetectionService;
import android.service.voice.IVisualQueryDetectionVoiceInteractionCallback;
+import android.service.voice.VisualQueryDetectionServiceFailure;
import android.util.Slog;
import com.android.internal.app.IHotwordRecognitionStatusCallback;
@@ -102,6 +106,13 @@ final class VisualQueryDetectorSession extends DetectorSession {
mAttentionListener.onAttentionGained();
} catch (RemoteException e) {
Slog.e(TAG, "Error delivering attention gained event.", e);
+ try {
+ callback.onDetectionFailure(new VisualQueryDetectionServiceFailure(
+ ERROR_CODE_ILLEGAL_ATTENTION_STATE,
+ "Attention listener failed to switch to GAINED state."));
+ } catch (RemoteException ex) {
+ Slog.v(TAG, "Fail to call onDetectionFailure");
+ }
return;
}
}
@@ -117,6 +128,13 @@ final class VisualQueryDetectorSession extends DetectorSession {
mAttentionListener.onAttentionLost();
} catch (RemoteException e) {
Slog.e(TAG, "Error delivering attention lost event.", e);
+ try {
+ callback.onDetectionFailure(new VisualQueryDetectionServiceFailure(
+ ERROR_CODE_ILLEGAL_ATTENTION_STATE,
+ "Attention listener failed to switch to LOST state."));
+ } catch (RemoteException ex) {
+ Slog.v(TAG, "Fail to call onDetectionFailure");
+ }
return;
}
}
@@ -127,6 +145,9 @@ final class VisualQueryDetectorSession extends DetectorSession {
Slog.v(TAG, "BinderCallback#onQueryDetected");
if (!mEgressingData) {
Slog.v(TAG, "Query should not be egressed within the unattention state.");
+ callback.onDetectionFailure(new VisualQueryDetectionServiceFailure(
+ ERROR_CODE_ILLEGAL_STREAMING_STATE,
+ "Cannot stream queries without attention signals."));
return;
}
mQueryStreaming = true;
@@ -140,6 +161,9 @@ final class VisualQueryDetectorSession extends DetectorSession {
if (!mQueryStreaming) {
Slog.v(TAG, "Query streaming state signal FINISHED is block since there is"
+ " no active query being streamed.");
+ callback.onDetectionFailure(new VisualQueryDetectionServiceFailure(
+ ERROR_CODE_ILLEGAL_STREAMING_STATE,
+ "Cannot send FINISHED signal with no query streamed."));
return;
}
callback.onQueryFinished();
@@ -152,6 +176,9 @@ final class VisualQueryDetectorSession extends DetectorSession {
if (!mQueryStreaming) {
Slog.v(TAG, "Query streaming state signal REJECTED is block since there is"
+ " no active query being streamed.");
+ callback.onDetectionFailure(new VisualQueryDetectionServiceFailure(
+ ERROR_CODE_ILLEGAL_STREAMING_STATE,
+ "Cannot send REJECTED signal with no query streamed."));
return;
}
callback.onQueryRejected();
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index d4374a9c2654..1a76295c251f 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -378,7 +378,7 @@ public class VoiceInteractionManagerService extends SystemService {
@Override
public @NonNull IVoiceInteractionSoundTriggerSession createSoundTriggerSessionAsOriginator(
@NonNull Identity originatorIdentity, IBinder client,
- @NonNull ModuleProperties moduleProperties) {
+ ModuleProperties moduleProperties) {
Objects.requireNonNull(originatorIdentity);
boolean forHotwordDetectionService;
synchronized (VoiceInteractionManagerServiceStub.this) {
@@ -1049,7 +1049,8 @@ public class VoiceInteractionManagerService extends SystemService {
@Override
public int startAssistantActivity(@NonNull IBinder token, @NonNull Intent intent,
- @Nullable String resolvedType, @Nullable String attributionTag) {
+ @Nullable String resolvedType, @NonNull String attributionTag,
+ @NonNull Bundle bundle) {
synchronized (this) {
if (mImpl == null) {
Slog.w(TAG, "startAssistantActivity without running voice interaction service");
@@ -1060,7 +1061,7 @@ public class VoiceInteractionManagerService extends SystemService {
final long caller = Binder.clearCallingIdentity();
try {
return mImpl.startAssistantActivityLocked(attributionTag, callingPid,
- callingUid, token, intent, resolvedType);
+ callingUid, token, intent, resolvedType, bundle);
} finally {
Binder.restoreCallingIdentity(caller);
}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
index ad0e9217c50b..96b69f8c4130 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -29,7 +29,6 @@ import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
-import android.app.ActivityOptions;
import android.app.ActivityTaskManager;
import android.app.AppGlobals;
import android.app.ApplicationExitInfo;
@@ -376,7 +375,8 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
@GuardedBy("this")
public int startAssistantActivityLocked(@Nullable String callingFeatureId, int callingPid,
- int callingUid, IBinder token, Intent intent, String resolvedType) {
+ int callingUid, IBinder token, Intent intent, String resolvedType,
+ @NonNull Bundle bundle) {
try {
if (mActiveSession == null || token != mActiveSession.mToken) {
Slog.w(TAG, "startAssistantActivity does not match active session");
@@ -388,10 +388,10 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
}
intent = new Intent(intent);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- final ActivityOptions options = ActivityOptions.makeBasic();
- options.setLaunchActivityType(ACTIVITY_TYPE_ASSISTANT);
+ // TODO: make the key public hidden
+ bundle.putInt("android.activity.activityType", ACTIVITY_TYPE_ASSISTANT);
return mAtm.startAssistantActivity(mComponent.getPackageName(), callingFeatureId,
- callingPid, callingUid, intent, resolvedType, options.toBundle(), mUser);
+ callingPid, callingUid, intent, resolvedType, bundle, mUser);
} catch (RemoteException e) {
throw new IllegalStateException("Unexpected remote error", e);
}
diff --git a/telecomm/java/android/telecom/CallControl.java b/telecomm/java/android/telecom/CallControl.java
index 2135e276e591..6b2bea032a00 100644
--- a/telecomm/java/android/telecom/CallControl.java
+++ b/telecomm/java/android/telecom/CallControl.java
@@ -147,10 +147,8 @@ public final class CallControl {
* <li>{@link DisconnectCause#REJECTED}</li>
* <li>{@link DisconnectCause#MISSED}</li>
* </ul>
- *
* @param executor The {@link Executor} on which the {@link OutcomeReceiver} callback
* will be called on.
- *
* @param callback That will be completed on the Telecom side that details success or
* failure of the requested operation.
*
@@ -254,6 +252,36 @@ public final class CallControl {
}
/**
+ * Raises an event to the {@link android.telecom.InCallService} implementations tracking this
+ * call via {@link android.telecom.Call.Callback#onConnectionEvent(Call, String, Bundle)}.
+ * These events and the associated extra keys for the {@code Bundle} parameter are defined
+ * in Android X. This API is used to relay additional information about a call other than
+ * what is specified in the {@link android.telecom.CallAttributes} to
+ * {@link android.telecom.InCallService}s. This might include, for example, a change to the list
+ * of participants in a meeting, or the name of the speakers who have their hand raised. Where
+ * appropriate, the {@link InCallService}s tracking this call may choose to render this
+ * additional information about the call. An automotive calling UX, for example may have enough
+ * screen real estate to indicate the number of participants in a meeting, but to prevent
+ * distractions could suppress the list of participants.
+ *
+ * @param event that is defined in AndroidX (ex. The number of participants changed)
+ * @param extras the updated value in relation to the event (ex. 4 participants)
+ */
+ public void sendEvent(@NonNull String event, @NonNull Bundle extras) {
+ Objects.requireNonNull(event);
+ Objects.requireNonNull(extras);
+ if (mServerInterface != null) {
+ try {
+ mServerInterface.sendEvent(mCallId, event, extras);
+ } catch (RemoteException e) {
+ throw e.rethrowAsRuntimeException();
+ }
+ } else {
+ throw new IllegalStateException(INTERFACE_ERROR_MSG);
+ }
+ }
+
+ /**
* Since {@link OutcomeReceiver}s cannot be passed via AIDL, a ResultReceiver (which can) must
* wrap the Clients {@link OutcomeReceiver} passed in and await for the Telecom Server side
* response in {@link ResultReceiver#onReceiveResult(int, Bundle)}.
diff --git a/telecomm/java/android/telecom/CallEventCallback.java b/telecomm/java/android/telecom/CallEventCallback.java
index bfe368560a22..d96c406c4294 100644
--- a/telecomm/java/android/telecom/CallEventCallback.java
+++ b/telecomm/java/android/telecom/CallEventCallback.java
@@ -17,6 +17,7 @@
package android.telecom;
import android.annotation.NonNull;
+import android.os.Bundle;
import java.util.List;
@@ -56,4 +57,17 @@ public interface CallEventCallback {
* @param reason Code to indicate the reason of this failure
*/
void onCallStreamingFailed(@CallStreamingService.StreamingFailedReason int reason);
+
+ /**
+ * Informs this {@link android.telecom.CallEventCallback} on events raised from a
+ * {@link android.telecom.InCallService} presenting this call. The event key and extra values
+ * are defined in AndroidX. This enables alternative calling surfaces, such as an automotive
+ * UI, to relay requests to perform other non-standard call actions to the app. For example,
+ * an automotive calling solution may offer the ability for the user to raise their hand
+ * during a meeting.
+ *
+ * @param event that is defined in AndroidX (ex. the number of participants changed)
+ * @param extras the updated value in relation to the event (ex. 4 participants)
+ */
+ void onEvent(@NonNull String event, @NonNull Bundle extras);
}
diff --git a/telecomm/java/com/android/internal/telecom/ClientTransactionalServiceWrapper.java b/telecomm/java/com/android/internal/telecom/ClientTransactionalServiceWrapper.java
index 7bba1eb07ebd..e44e2b31c189 100644
--- a/telecomm/java/com/android/internal/telecom/ClientTransactionalServiceWrapper.java
+++ b/telecomm/java/com/android/internal/telecom/ClientTransactionalServiceWrapper.java
@@ -19,6 +19,7 @@ package com.android.internal.telecom;
import static android.telecom.TelecomManager.TELECOM_TRANSACTION_SUCCESS;
import android.os.Binder;
+import android.os.Bundle;
import android.os.OutcomeReceiver;
import android.os.ResultReceiver;
import android.telecom.CallAttributes;
@@ -148,6 +149,7 @@ public class ClientTransactionalServiceWrapper {
private static final String ON_AVAILABLE_CALL_ENDPOINTS = "onAvailableCallEndpointsChanged";
private static final String ON_MUTE_STATE_CHANGED = "onMuteStateChanged";
private static final String ON_CALL_STREAMING_FAILED = "onCallStreamingFailed";
+ private static final String ON_EVENT = "onEvent";
private void handleHandshakeCallback(String action, String callId, int code,
ResultReceiver ackResultReceiver) {
@@ -314,5 +316,23 @@ public class ClientTransactionalServiceWrapper {
Log.i(TAG, TextUtils.formatSimple("oCSF: id=[%s], reason=[%s]", callId, reason));
handleEventCallback(callId, ON_CALL_STREAMING_FAILED, reason);
}
+
+ @Override
+ public void onEvent(String callId, String event, Bundle extras) {
+ // lookup the callEventCallback associated with the particular call
+ TransactionalCall call = mCallIdToTransactionalCall.get(callId);
+ if (call != null) {
+ CallEventCallback callback = call.getCallStateCallback();
+ Executor executor = call.getExecutor();
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ executor.execute(() -> {
+ callback.onEvent(event, extras);
+ });
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+ }
};
}
diff --git a/telecomm/java/com/android/internal/telecom/ICallControl.aidl b/telecomm/java/com/android/internal/telecom/ICallControl.aidl
index b78a77ec9756..3e651e92e612 100644
--- a/telecomm/java/com/android/internal/telecom/ICallControl.aidl
+++ b/telecomm/java/com/android/internal/telecom/ICallControl.aidl
@@ -16,6 +16,7 @@
package com.android.internal.telecom;
+import android.os.Bundle;
import android.telecom.CallControl;
import android.telecom.CallEndpoint;
import android.telecom.DisconnectCause;
@@ -30,4 +31,5 @@ oneway interface ICallControl {
void disconnect(String callId, in DisconnectCause disconnectCause, in ResultReceiver callback);
void startCallStreaming(String callId, in ResultReceiver callback);
void requestCallEndpointChange(in CallEndpoint callEndpoint, in ResultReceiver callback);
+ void sendEvent(String callId, String event, in Bundle extras);
} \ No newline at end of file
diff --git a/telecomm/java/com/android/internal/telecom/ICallEventCallback.aidl b/telecomm/java/com/android/internal/telecom/ICallEventCallback.aidl
index fef5e9e47dc5..dd61d173ef7e 100644
--- a/telecomm/java/com/android/internal/telecom/ICallEventCallback.aidl
+++ b/telecomm/java/com/android/internal/telecom/ICallEventCallback.aidl
@@ -16,6 +16,7 @@
package com.android.internal.telecom;
+import android.os.Bundle;
import android.telecom.CallControl;
import android.telecom.CallEndpoint;
import com.android.internal.telecom.ICallControl;
@@ -44,6 +45,8 @@ oneway interface ICallEventCallback {
void onCallEndpointChanged(String callId, in CallEndpoint endpoint);
void onAvailableCallEndpointsChanged(String callId, in List<CallEndpoint> endpoint);
void onMuteStateChanged(String callId, boolean isMuted);
+ // -- Events
+ void onEvent(String callId, String event, in Bundle extras);
// hidden methods that help with cleanup
void removeCallFromTransactionalServiceWrapper(String callId);
} \ No newline at end of file
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index d75e573a2e89..b418a02aed60 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2241,46 +2241,46 @@ public class SubscriptionManager {
}
/**
- * Get an array of subscription ids for specified logical SIM slot Index.
+ * Get an array of subscription ids for the specified logical SIM slot Index. The maximum size
+ * of the array is 1. This API was mistakenly designed to return multiple subscription ids,
+ * which is not possible in the current Android telephony architecture.
*
* @param slotIndex The logical SIM slot index.
*
- * @return subscription Ids or {@code null} if the given slot index is not valid or there are
- * no active subscription in the slot. In the implementation today, there will be no more
- * than one subscriptions per logical SIM slot.
+ * @return Subscription id of the active subscription on the specified logical SIM slot index.
+ * If SIM is absent on the slot, a single element array of {@link #INVALID_SUBSCRIPTION_ID} will
+ * be returned. {@code null} if the provided {@code slotIndex} is not valid.
*
* @deprecated Use {@link #getSubscriptionId(int)} instead.
*/
@Deprecated
@Nullable
public int[] getSubscriptionIds(int slotIndex) {
- int subId = getSubscriptionId(slotIndex);
- if (!isValidSubscriptionId(subId)) {
+ if (!isValidSlotIndex(slotIndex)) {
return null;
}
return new int[]{getSubscriptionId(slotIndex)};
}
- /** @hide */
- @UnsupportedAppUsage
+ /**
+ * Get an array of subscription ids for the specified logical SIM slot Index. The maximum size
+ * of the array is 1. This API was mistakenly designed to return multiple subscription ids,
+ * which is not possible in the current Android telephony architecture.
+ *
+ * @param slotIndex The logical SIM slot index.
+ *
+ * @return Subscription id of the active subscription on the specified logical SIM slot index.
+ * If SIM is absent on the slot, a single element array of {@link #INVALID_SUBSCRIPTION_ID} will
+ * be returned. {@code null} if the provided {@code slotIndex} is not valid.
+ *
+ * @deprecated Use {@link #getSubscriptionId(int)} instead.
+ * @hide
+ */
public static int[] getSubId(int slotIndex) {
if (!isValidSlotIndex(slotIndex)) {
- logd("[getSubId]- fail");
return null;
}
-
- int[] subId = null;
-
- try {
- ISub iSub = TelephonyManager.getSubscriptionService();
- if (iSub != null) {
- subId = iSub.getSubIds(slotIndex);
- }
- } catch (RemoteException ex) {
- // ignore it
- }
-
- return subId;
+ return new int[]{getSubscriptionId(slotIndex)};
}
/**
diff --git a/telephony/java/android/telephony/satellite/ISatelliteDatagramCallback.aidl b/telephony/java/android/telephony/satellite/ISatelliteDatagramCallback.aidl
index d6f8012201ab..c15374acea93 100644
--- a/telephony/java/android/telephony/satellite/ISatelliteDatagramCallback.aidl
+++ b/telephony/java/android/telephony/satellite/ISatelliteDatagramCallback.aidl
@@ -16,6 +16,7 @@
package android.telephony.satellite;
+import android.telephony.satellite.ISatelliteDatagramReceiverAck;
import android.telephony.satellite.SatelliteDatagram;
/**
@@ -24,8 +25,15 @@ import android.telephony.satellite.SatelliteDatagram;
*/
oneway interface ISatelliteDatagramCallback {
/**
- * Called when there are incoming datagrams to be received.
- * @param datagrams Array of datagrams to be received over satellite.
+ * Called when there is an incoming datagram to be received from satellite.
+ *
+ * @param datagramId An id that uniquely identifies incoming datagram.
+ * @param datagram Datagram received from satellite.
+ * @param pendingCount Number of datagrams yet to be received from satellite.
+ * @param callback This callback will be used by datagram receiver app to send ack back to
+ * Telephony. If the callback is not received within five minutes,
+ * Telephony will resend the datagrams.
*/
- void onSatelliteDatagrams(in SatelliteDatagram[] datagrams);
+ void onSatelliteDatagramReceived(long datagramId, in SatelliteDatagram datagram,
+ int pendingCount, ISatelliteDatagramReceiverAck callback);
}
diff --git a/telephony/java/android/telephony/satellite/ISatelliteDatagramReceiverAck.aidl b/telephony/java/android/telephony/satellite/ISatelliteDatagramReceiverAck.aidl
new file mode 100644
index 000000000000..eeb0ac56d6bf
--- /dev/null
+++ b/telephony/java/android/telephony/satellite/ISatelliteDatagramReceiverAck.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 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 android.telephony.satellite;
+
+import android.telephony.satellite.PointingInfo;
+import android.telephony.satellite.SatelliteDatagram;
+
+/**
+ * Interface for satellite datagram receiver acknowledgement.
+ * @hide
+ */
+oneway interface ISatelliteDatagramReceiverAck {
+ /**
+ * This callback will be used by datagram receiver app to send ack back to
+ * Telephony. If the callback is not received within five minutes,
+ * then Telephony will resend the datagram again.
+ *
+ * @param datagramId An id that uniquely identifies datagram
+ * received by satellite datagram receiver app.
+ * This should match with datagramId passed in
+ * {@link SatelliteDatagramCallback#onSatelliteDatagramReceived(
+ * long, SatelliteDatagram, int, ISatelliteDatagramReceiverAck)}.
+ * Upon receiving the ack, Telephony will remove the datagram from
+ * the persistent memory.
+ */
+ void acknowledgeSatelliteDatagramReceived(in long datagramId);
+}
diff --git a/telephony/java/android/telephony/satellite/ISatellitePositionUpdateCallback.aidl b/telephony/java/android/telephony/satellite/ISatellitePositionUpdateCallback.aidl
index 4478d0ae50e6..d3f1091acfa0 100644
--- a/telephony/java/android/telephony/satellite/ISatellitePositionUpdateCallback.aidl
+++ b/telephony/java/android/telephony/satellite/ISatellitePositionUpdateCallback.aidl
@@ -24,20 +24,20 @@ import android.telephony.satellite.PointingInfo;
*/
oneway interface ISatellitePositionUpdateCallback {
/**
- * Called when satellite datagram transfer state changes.
+ * Called when satellite datagram transfer state changed.
*
* @param state The new datagram transfer state.
* @param sendPendingCount The number of datagrams that are currently being sent.
* @param receivePendingCount The number of datagrams that are currently being received.
* @param errorCode If datagram transfer failed, the reason for failure.
*/
- void onDatagramTransferStateUpdate(in int state, in int sendPendingCount,
+ void onDatagramTransferStateChanged(in int state, in int sendPendingCount,
in int receivePendingCount, in int errorCode);
/**
- * Called when the satellite position changes.
+ * Called when the satellite position changed.
*
* @param pointingInfo The pointing info containing the satellite location.
*/
- void onSatellitePositionUpdate(in PointingInfo pointingInfo);
+ void onSatellitePositionChanged(in PointingInfo pointingInfo);
}
diff --git a/telephony/java/android/telephony/satellite/ISatelliteStateCallback.aidl b/telephony/java/android/telephony/satellite/ISatelliteStateCallback.aidl
index 8d1e3c2a77f6..98221c9ef2c5 100644
--- a/telephony/java/android/telephony/satellite/ISatelliteStateCallback.aidl
+++ b/telephony/java/android/telephony/satellite/ISatelliteStateCallback.aidl
@@ -33,5 +33,5 @@ oneway interface ISatelliteStateCallback {
*
* @param state The current satellite modem state.
*/
- void onSatelliteModemStateChange(in int state);
+ void onSatelliteModemStateChanged(in int state);
}
diff --git a/telephony/java/android/telephony/satellite/PointingInfo.java b/telephony/java/android/telephony/satellite/PointingInfo.java
index d6dd57aac63b..a3c3f1966c94 100644
--- a/telephony/java/android/telephony/satellite/PointingInfo.java
+++ b/telephony/java/android/telephony/satellite/PointingInfo.java
@@ -48,10 +48,10 @@ public final class PointingInfo implements Parcelable {
/**
* @hide
*/
- public PointingInfo(float satelliteAzimuthDegress, float satelliteElevationDegress,
+ public PointingInfo(float satelliteAzimuthDegrees, float satelliteElevationDegrees,
float antennaAzimuthDegrees, float antennaPitchDegrees, float antennaRollDegrees) {
- mSatelliteAzimuthDegrees = satelliteAzimuthDegress;
- mSatelliteElevationDegrees = satelliteElevationDegress;
+ mSatelliteAzimuthDegrees = satelliteAzimuthDegrees;
+ mSatelliteElevationDegrees = satelliteElevationDegrees;
mAntennaAzimuthDegrees = antennaAzimuthDegrees;
mAntennaPitchDegrees = antennaPitchDegrees;
mAntennaRollDegrees = antennaRollDegrees;
diff --git a/telephony/java/android/telephony/satellite/SatelliteCapabilities.java b/telephony/java/android/telephony/satellite/SatelliteCapabilities.java
index 74f6f571ae7a..889856b09ae6 100644
--- a/telephony/java/android/telephony/satellite/SatelliteCapabilities.java
+++ b/telephony/java/android/telephony/satellite/SatelliteCapabilities.java
@@ -30,7 +30,7 @@ public final class SatelliteCapabilities implements Parcelable {
/**
* List of technologies supported by the satellite modem.
*/
- private Set<Integer> mSupportedRadioTechnologies;
+ @NonNull @SatelliteManager.NTRadioTechnology private Set<Integer> mSupportedRadioTechnologies;
/**
* Whether satellite modem is always on.
@@ -53,7 +53,8 @@ public final class SatelliteCapabilities implements Parcelable {
*/
public SatelliteCapabilities(Set<Integer> supportedRadioTechnologies, boolean isAlwaysOn,
boolean needsPointingToSatellite, boolean needsSeparateSimProfile) {
- mSupportedRadioTechnologies = supportedRadioTechnologies;
+ mSupportedRadioTechnologies = supportedRadioTechnologies == null
+ ? new HashSet<>() : supportedRadioTechnologies;
mIsAlwaysOn = isAlwaysOn;
mNeedsPointingToSatellite = needsPointingToSatellite;
mNeedsSeparateSimProfile = needsSeparateSimProfile;
@@ -126,7 +127,8 @@ public final class SatelliteCapabilities implements Parcelable {
/**
* @return The list of technologies supported by the satellite modem.
*/
- @NonNull public Set<Integer> getSupportedRadioTechnologies() {
+ @NonNull @SatelliteManager.NTRadioTechnology public Set<Integer>
+ getSupportedRadioTechnologies() {
return mSupportedRadioTechnologies;
}
diff --git a/telephony/java/android/telephony/satellite/SatelliteDatagramCallback.java b/telephony/java/android/telephony/satellite/SatelliteDatagramCallback.java
index 484b783e35e8..8ccc99362b1b 100644
--- a/telephony/java/android/telephony/satellite/SatelliteDatagramCallback.java
+++ b/telephony/java/android/telephony/satellite/SatelliteDatagramCallback.java
@@ -38,10 +38,12 @@ public class SatelliteDatagramCallback {
}
@Override
- public void onSatelliteDatagrams(SatelliteDatagram[] datagrams) {
+ public void onSatelliteDatagramReceived(long datagramId, SatelliteDatagram datagram,
+ int pendingCount, ISatelliteDatagramReceiverAck callback) {
final long callingIdentity = Binder.clearCallingIdentity();
try {
- mExecutor.execute(() -> mLocalCallback.onSatelliteDatagrams(datagrams));
+ mExecutor.execute(() -> mLocalCallback.onSatelliteDatagramReceived(datagramId,
+ datagram, pendingCount, callback));
} finally {
restoreCallingIdentity(callingIdentity);
}
@@ -53,20 +55,25 @@ public class SatelliteDatagramCallback {
}
/**
- * Called when there are incoming datagrams to be received.
- * @param datagrams Datagrams to be received over satellite.
+ * Called when there is an incoming datagram to be received.
+ * @param datagramId An id that uniquely identifies incoming datagram.
+ * @param datagram Datagram to be received over satellite.
+ * @param pendingCount Number of datagrams yet to be received by the app.
+ * @param callback This callback will be used by datagram receiver app to send ack back to
+ * Telephony.
*/
- public void onSatelliteDatagrams(SatelliteDatagram[] datagrams) {
+ public void onSatelliteDatagramReceived(long datagramId, SatelliteDatagram datagram,
+ int pendingCount, ISatelliteDatagramReceiverAck callback) {
// Base Implementation
}
- /**@hide*/
+ /** @hide */
@NonNull
public final ISatelliteDatagramCallback getBinder() {
return mBinder;
}
- /**@hide*/
+ /** @hide */
public void setExecutor(@NonNull Executor executor) {
mBinder.setExecutor(executor);
}
diff --git a/telephony/java/android/telephony/satellite/SatelliteManager.java b/telephony/java/android/telephony/satellite/SatelliteManager.java
index 8fbf64070534..3009bec06a93 100644
--- a/telephony/java/android/telephony/satellite/SatelliteManager.java
+++ b/telephony/java/android/telephony/satellite/SatelliteManager.java
@@ -116,6 +116,13 @@ public class SatelliteManager {
/**
* Bundle key to get the response from
+ * {@link #requestIsSatelliteDemoModeEnabled(Executor, OutcomeReceiver)}.
+ * @hide
+ */
+ public static final String KEY_DEMO_MODE_ENABLED = "demo_mode_enabled";
+
+ /**
+ * Bundle key to get the response from
* {@link #requestIsSatelliteSupported(Executor, OutcomeReceiver)}.
* @hide
*/
@@ -130,7 +137,7 @@ public class SatelliteManager {
/**
* Bundle key to get the response from
- * {@link #requestMaxCharactersPerSatelliteTextMessage(Executor, OutcomeReceiver)}.
+ * {@link #requestMaxSizePerSendingDatagram(Executor, OutcomeReceiver)} .
* @hide
*/
public static final String KEY_MAX_CHARACTERS_PER_SATELLITE_TEXT =
@@ -159,6 +166,13 @@ public class SatelliteManager {
public static final String KEY_SATELLITE_NEXT_VISIBILITY = "satellite_next_visibility";
/**
+ * Bundle key to get the respoonse from
+ * {@link #sendSatelliteDatagram(long, int, SatelliteDatagram, Executor, OutcomeReceiver)}.
+ * @hide
+ */
+ public static final String KEY_SEND_SATELLITE_DATAGRAM = "send_satellite_datagram";
+
+ /**
* The request was successfully processed.
*/
public static final int SATELLITE_ERROR_NONE = 0;
@@ -277,6 +291,39 @@ public class SatelliteManager {
public @interface SatelliteError {}
/**
+ * 3GPP NB-IoT (Narrowband Internet of Things) over Non-Terrestrial-Networks technology.
+ */
+ public static final int NT_RADIO_TECHNOLOGY_NB_IOT_NTN = 0;
+ /**
+ * 3GPP 5G NR over Non-Terrestrial-Networks technology.
+ */
+ public static final int NT_RADIO_TECHNOLOGY_NR_NTN = 1;
+ /**
+ * 3GPP eMTC (enhanced Machine-Type Communication) over Non-Terrestrial-Networks technology.
+ */
+ public static final int NT_RADIO_TECHNOLOGY_EMTC_NTN = 2;
+ /**
+ * Proprietary technology.
+ */
+ public static final int NT_RADIO_TECHNOLOGY_PROPRIETARY = 3;
+ /**
+ * Unknown Non-Terrestrial radio technology. This generic radio technology should be used
+ * only when the radio technology cannot be mapped to other specific radio technologies.
+ */
+ public static final int NT_RADIO_TECHNOLOGY_UNKNOWN = -1;
+
+ /** @hide */
+ @IntDef(prefix = "NT_RADIO_TECHNOLOGY_", value = {
+ NT_RADIO_TECHNOLOGY_NB_IOT_NTN,
+ NT_RADIO_TECHNOLOGY_NR_NTN,
+ NT_RADIO_TECHNOLOGY_EMTC_NTN,
+ NT_RADIO_TECHNOLOGY_PROPRIETARY,
+ NT_RADIO_TECHNOLOGY_UNKNOWN
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface NTRadioTechnology {}
+
+ /**
* Request to enable or disable the satellite modem. If the satellite modem is enabled, this
* will also disable the cellular modem, and if the satellite modem is disabled, this will also
* re-enable the cellular modem.
@@ -370,6 +417,97 @@ public class SatelliteManager {
}
/**
+ * Request to enable or disable the satellite service demo mode.
+ *
+ * @param enable {@code true} to enable the satellite demo mode and {@code false} to disable.
+ * @param executor The executor on which the error code listener will be called.
+ * @param errorCodeListener Listener for the {@link SatelliteError} result of the operation.
+ *
+ * @throws SecurityException if the caller doesn't have required permission.
+ * @throws IllegalStateException if the Telephony process is not currently available.
+ */
+ @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+ public void requestSatelliteDemoModeEnabled(boolean enable,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull Consumer<Integer> errorCodeListener) {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(errorCodeListener);
+
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ IIntegerConsumer errorCallback = new IIntegerConsumer.Stub() {
+ @Override
+ public void accept(int result) {
+ executor.execute(() -> Binder.withCleanCallingIdentity(
+ () -> errorCodeListener.accept(result)));
+ }
+ };
+ telephony.requestSatelliteDemoModeEnabled(mSubId, enable, errorCallback);
+ } else {
+ throw new IllegalStateException("telephony service is null.");
+ }
+ } catch (RemoteException ex) {
+ Rlog.e(TAG, "requestSatelliteDemoModeEnabled() RemoteException: ", ex);
+ ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Request to get whether the satellite service demo mode is enabled.
+ *
+ * @param executor The executor on which the callback will be called.
+ * @param callback The callback object to which the result will be delivered.
+ * If the request is successful, {@link OutcomeReceiver#onResult(Object)}
+ * will return a {@code boolean} with value {@code true} if the satellite
+ * demo mode is enabled and {@code false} otherwise.
+ * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)}
+ * will return a {@link SatelliteException} with the {@link SatelliteError}.
+ *
+ * @throws SecurityException if the caller doesn't have required permission.
+ * @throws IllegalStateException if the Telephony process is not currently available.
+ */
+ @RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
+ public void requestIsSatelliteDemoModeEnabled(@NonNull @CallbackExecutor Executor executor,
+ @NonNull OutcomeReceiver<Boolean, SatelliteException> callback) {
+ Objects.requireNonNull(executor);
+ Objects.requireNonNull(callback);
+
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ ResultReceiver receiver = new ResultReceiver(null) {
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ if (resultCode == SATELLITE_ERROR_NONE) {
+ if (resultData.containsKey(KEY_DEMO_MODE_ENABLED)) {
+ boolean isDemoModeEnabled =
+ resultData.getBoolean(KEY_DEMO_MODE_ENABLED);
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onResult(isDemoModeEnabled)));
+ } else {
+ loge("KEY_DEMO_MODE_ENABLED does not exist.");
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onError(
+ new SatelliteException(SATELLITE_REQUEST_FAILED))));
+ }
+ } else {
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onError(new SatelliteException(resultCode))));
+ }
+ }
+ };
+ telephony.requestIsSatelliteDemoModeEnabled(mSubId, receiver);
+ } else {
+ throw new IllegalStateException("telephony service is null.");
+ }
+ } catch (RemoteException ex) {
+ loge("requestIsSatelliteDemoModeEnabled() RemoteException: " + ex);
+ ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Request to get whether the satellite service is supported on the device.
*
* @param executor The executor on which the callback will be called.
@@ -506,6 +644,12 @@ public class SatelliteManager {
* must be sent before reporting any additional datagram transfer state changes.
*/
public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_FAILED = 5;
+ /**
+ * The datagram transfer state is unknown. This generic datagram transfer state should be used
+ * only when the datagram transfer state cannot be mapped to other specific datagram transfer
+ * states.
+ */
+ public static final int SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN = -1;
/** @hide */
@IntDef(prefix = {"SATELLITE_DATAGRAM_TRANSFER_STATE_"}, value = {
@@ -514,46 +658,70 @@ public class SatelliteManager {
SATELLITE_DATAGRAM_TRANSFER_STATE_RECEIVING,
SATELLITE_DATAGRAM_TRANSFER_STATE_RETRYING,
SATELLITE_DATAGRAM_TRANSFER_STATE_SUCCESS,
- SATELLITE_DATAGRAM_TRANSFER_STATE_FAILED
+ SATELLITE_DATAGRAM_TRANSFER_STATE_FAILED,
+ SATELLITE_DATAGRAM_TRANSFER_STATE_UNKNOWN
})
+ @Retention(RetentionPolicy.SOURCE)
public @interface SatelliteDatagramTransferState {}
- /* Satellite modem is in idle state. */
+ /**
+ * Satellite modem is in idle state.
+ */
public static final int SATELLITE_MODEM_STATE_IDLE = 0;
-
- /* Satellite modem is listening for incoming datagrams. */
+ /**
+ * Satellite modem is listening for incoming datagrams.
+ */
public static final int SATELLITE_MODEM_STATE_LISTENING = 1;
-
- /* Satellite modem is sending and/or receiving datagrams. */
+ /**
+ * Satellite modem is sending and/or receiving datagrams.
+ */
public static final int SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING = 2;
-
- /* Satellite modem is powered off. */
- public static final int SATELLITE_MODEM_STATE_OFF = 3;
+ /**
+ * Satellite modem is retrying to send and/or receive datagrams.
+ */
+ public static final int SATELLITE_MODEM_STATE_DATAGRAM_RETRYING = 3;
+ /**
+ * Satellite modem is powered off.
+ */
+ public static final int SATELLITE_MODEM_STATE_OFF = 4;
+ /**
+ * Satellite modem state is unknown. This generic modem state should be used only when the
+ * modem state cannot be mapped to other specific modem states.
+ */
+ public static final int SATELLITE_MODEM_STATE_UNKNOWN = -1;
/** @hide */
- @IntDef(prefix = {"SATELLITE_STATE_"},
- value = {
- SATELLITE_MODEM_STATE_IDLE,
- SATELLITE_MODEM_STATE_LISTENING,
- SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING,
- SATELLITE_MODEM_STATE_OFF
- })
+ @IntDef(prefix = {"SATELLITE_MODEM_STATE_"}, value = {
+ SATELLITE_MODEM_STATE_IDLE,
+ SATELLITE_MODEM_STATE_LISTENING,
+ SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING,
+ SATELLITE_MODEM_STATE_DATAGRAM_RETRYING,
+ SATELLITE_MODEM_STATE_OFF,
+ SATELLITE_MODEM_STATE_UNKNOWN
+ })
@Retention(RetentionPolicy.SOURCE)
public @interface SatelliteModemState {}
- /** Datagram type indicating that the datagram to be sent or received is of type SOS SMS. */
- public static final int DATAGRAM_TYPE_SOS_SMS = 0;
-
- /** Datagram type indicating that the datagram to be sent or received is of type
- * location sharing. */
- public static final int DATAGRAM_TYPE_LOCATION_SHARING = 3;
+ /**
+ * Datagram type indicating that the datagram to be sent or received is of type SOS message.
+ */
+ public static final int DATAGRAM_TYPE_SOS_MESSAGE = 0;
+ /**
+ * Datagram type indicating that the datagram to be sent or received is of type
+ * location sharing.
+ */
+ public static final int DATAGRAM_TYPE_LOCATION_SHARING = 1;
+ /**
+ * Datagram type is unknown. This generic datagram type should be used only when the
+ * datagram type cannot be mapped to other specific datagram types.
+ */
+ public static final int DATAGRAM_TYPE_UNKNOWN = -1;
- @IntDef(
- prefix = "DATAGRAM_TYPE_",
- value = {
- DATAGRAM_TYPE_SOS_SMS,
- DATAGRAM_TYPE_LOCATION_SHARING,
- })
+ @IntDef(prefix = "DATAGRAM_TYPE_", value = {
+ DATAGRAM_TYPE_SOS_MESSAGE,
+ DATAGRAM_TYPE_LOCATION_SHARING,
+ DATAGRAM_TYPE_UNKNOWN
+ })
@Retention(RetentionPolicy.SOURCE)
public @interface DatagramType {}
@@ -651,19 +819,20 @@ public class SatelliteManager {
}
/**
- * Request to get the maximum number of characters per text message on satellite.
+ * Request to get the maximum number of bytes per datagram that can be sent to satellite.
*
* @param executor The executor on which the callback will be called.
* @param callback The callback object to which the result will be delivered.
* If the request is successful, {@link OutcomeReceiver#onResult(Object)}
- * will return the maximum number of characters per text message on satellite.
+ * will return the maximum number of bytes per datagram that can be sent to
+ * satellite.
* If the request is not successful, {@link OutcomeReceiver#onError(Throwable)}
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
*/
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
- public void requestMaxCharactersPerSatelliteTextMessage(
+ public void requestMaxSizePerSendingDatagram(
@NonNull @CallbackExecutor Executor executor,
@NonNull OutcomeReceiver<Integer, SatelliteException> callback) {
Objects.requireNonNull(executor);
@@ -693,7 +862,7 @@ public class SatelliteManager {
}
}
};
- telephony.requestMaxCharactersPerSatelliteTextMessage(mSubId, receiver);
+ telephony.requestMaxSizePerSendingDatagram(mSubId, receiver);
} else {
throw new IllegalStateException("telephony service is null.");
}
@@ -794,7 +963,7 @@ public class SatelliteManager {
}
/**
- * Register for the satellite provision state change.
+ * Registers for the satellite provision state changed.
*
* @param executor The executor on which the callback will be called.
* @param callback The callback to handle the satellite provision state changed event.
@@ -828,7 +997,7 @@ public class SatelliteManager {
}
/**
- * Unregister for the satellite provision state change.
+ * Unregisters for the satellite provision state changed.
* If callback was not registered before, the request will be ignored.
*
* @param callback The callback that was passed to
@@ -910,10 +1079,10 @@ public class SatelliteManager {
}
/**
- * Register for listening to satellite modem state changes.
+ * Registers for modem state changed from satellite modem.
*
* @param executor The executor on which the callback will be called.
- * @param callback The callback to handle the satellite modem state change event.
+ * @param callback The callback to handle the satellite modem state changed event.
*
* @return The {@link SatelliteError} result of the operation.
*
@@ -921,7 +1090,7 @@ public class SatelliteManager {
* @throws IllegalStateException if the Telephony process is not currently available.
*/
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
- @SatelliteError public int registerForSatelliteModemStateChange(
+ @SatelliteError public int registerForSatelliteModemStateChanged(
@NonNull @CallbackExecutor Executor executor,
@NonNull SatelliteStateCallback callback) {
Objects.requireNonNull(executor);
@@ -931,41 +1100,41 @@ public class SatelliteManager {
ITelephony telephony = getITelephony();
if (telephony != null) {
callback.setExecutor(executor);
- return telephony.registerForSatelliteModemStateChange(mSubId,
+ return telephony.registerForSatelliteModemStateChanged(mSubId,
callback.getBinder());
} else {
throw new IllegalStateException("telephony service is null.");
}
} catch (RemoteException ex) {
- loge("registerForSatelliteModemStateChange() RemoteException:" + ex);
+ loge("registerForSatelliteModemStateChanged() RemoteException:" + ex);
ex.rethrowFromSystemServer();
}
return SATELLITE_REQUEST_FAILED;
}
/**
- * Unregister to stop listening to satellite modem state changes.
+ * Unregisters for modem state changed from satellite modem.
* If callback was not registered before, the request will be ignored.
*
* @param callback The callback that was passed to
- * {@link #registerForSatelliteModemStateChange(Executor, SatelliteStateCallback)}.
+ * {@link #registerForSatelliteModemStateChanged(Executor, SatelliteStateCallback)}.
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
*/
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
- public void unregisterForSatelliteModemStateChange(@NonNull SatelliteStateCallback callback) {
+ public void unregisterForSatelliteModemStateChanged(@NonNull SatelliteStateCallback callback) {
Objects.requireNonNull(callback);
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- telephony.unregisterForSatelliteModemStateChange(mSubId, callback.getBinder());
+ telephony.unregisterForSatelliteModemStateChanged(mSubId, callback.getBinder());
} else {
throw new IllegalStateException("telephony service is null.");
}
} catch (RemoteException ex) {
- loge("unregisterForSatelliteModemStateChange() RemoteException:" + ex);
+ loge("unregisterForSatelliteModemStateChanged() RemoteException:" + ex);
ex.rethrowFromSystemServer();
}
}
@@ -1039,7 +1208,8 @@ public class SatelliteManager {
*
* This method requests modem to check if there are any pending datagrams to be received over
* satellite. If there are any incoming datagrams, they will be received via
- * {@link SatelliteDatagramCallback#onSatelliteDatagrams(SatelliteDatagram[])})}.
+ * {@link SatelliteDatagramCallback#onSatelliteDatagramReceived(long, SatelliteDatagram, int,
+ * ISatelliteDatagramReceiverAck)}
*
* @param executor The executor on which the result listener will be called.
* @param resultListener Listener for the {@link SatelliteError} result of the operation.
@@ -1076,39 +1246,60 @@ public class SatelliteManager {
/**
* Send datagram over satellite.
*
- * Gateway encodes SOS SMS or location sharing message into a datagram and passes it as input to
- * this method. Datagram received here will be passed down to modem without any encoding or
- * encryption.
+ * Gateway encodes SOS message or location sharing message into a datagram and passes it as
+ * input to this method. Datagram received here will be passed down to modem without any
+ * encoding or encryption.
*
+ * @param datagramId An id that uniquely identifies datagram requested to be sent.
* @param datagramType datagram type indicating whether the datagram is of type
* SOS_SMS or LOCATION_SHARING.
* @param datagram encoded gateway datagram which is encrypted by the caller.
* Datagram will be passed down to modem without any encoding or encryption.
* @param executor The executor on which the result listener will be called.
- * @param resultListener Listener for the {@link SatelliteError} result of the operation.
+ * @param callback The callback object to which the result will be returned.
+ * If datagram is sent successfully, then
+ * {@link OutcomeReceiver#onResult(Object)} will return datagramId.
+ * If the request is not successful, {@link OutcomeReceiver#onError(Throwable)}
+ * will return a {@link SatelliteException} with the {@link SatelliteError}.
*
* @throws SecurityException if the caller doesn't have required permission.
* @throws IllegalStateException if the Telephony process is not currently available.
*/
@RequiresPermission(Manifest.permission.SATELLITE_COMMUNICATION)
- public void sendSatelliteDatagram(@DatagramType int datagramType,
+ public void sendSatelliteDatagram(long datagramId, @DatagramType int datagramType,
@NonNull SatelliteDatagram datagram, @NonNull @CallbackExecutor Executor executor,
- @SatelliteError @NonNull Consumer<Integer> resultListener) {
+ @NonNull OutcomeReceiver<Long, SatelliteException> callback) {
Objects.requireNonNull(datagram);
Objects.requireNonNull(executor);
- Objects.requireNonNull(resultListener);
+ Objects.requireNonNull(callback);
try {
ITelephony telephony = getITelephony();
if (telephony != null) {
- IIntegerConsumer internalCallback = new IIntegerConsumer.Stub() {
+ ResultReceiver receiver = new ResultReceiver(null) {
@Override
- public void accept(int result) {
- executor.execute(() -> Binder.withCleanCallingIdentity(
- () -> resultListener.accept(result)));
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ if (resultCode == SATELLITE_ERROR_NONE) {
+ if (resultData.containsKey(KEY_SEND_SATELLITE_DATAGRAM)) {
+ long resultDatagramId = resultData
+ .getLong(KEY_SEND_SATELLITE_DATAGRAM);
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onResult(resultDatagramId)));
+ } else {
+ loge("KEY_SEND_SATELLITE_DATAGRAM does not exist.");
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onError(
+ new SatelliteException(SATELLITE_REQUEST_FAILED))));
+ }
+
+ } else {
+ executor.execute(() -> Binder.withCleanCallingIdentity(() ->
+ callback.onError(new SatelliteException(resultCode))));
+ }
}
};
- telephony.sendSatelliteDatagram(mSubId, datagramType, datagram, internalCallback);
+ telephony.sendSatelliteDatagram(mSubId, datagramId, datagramType, datagram,
+ receiver);
} else {
throw new IllegalStateException("telephony service is null.");
}
diff --git a/telephony/java/android/telephony/satellite/SatellitePositionUpdateCallback.java b/telephony/java/android/telephony/satellite/SatellitePositionUpdateCallback.java
index cda7a75ed955..e3e417178719 100644
--- a/telephony/java/android/telephony/satellite/SatellitePositionUpdateCallback.java
+++ b/telephony/java/android/telephony/satellite/SatellitePositionUpdateCallback.java
@@ -39,24 +39,24 @@ public class SatellitePositionUpdateCallback {
}
@Override
- public void onSatellitePositionUpdate(@NonNull PointingInfo pointingInfo) {
+ public void onSatellitePositionChanged(@NonNull PointingInfo pointingInfo) {
final long callingIdentity = Binder.clearCallingIdentity();
try {
mExecutor.execute(() ->
- mLocalCallback.onSatellitePositionUpdate(pointingInfo));
+ mLocalCallback.onSatellitePositionChanged(pointingInfo));
} finally {
restoreCallingIdentity(callingIdentity);
}
}
@Override
- public void onDatagramTransferStateUpdate(
+ public void onDatagramTransferStateChanged(
@SatelliteManager.SatelliteDatagramTransferState int state, int sendPendingCount,
int receivePendingCount, @SatelliteManager.SatelliteError int errorCode) {
final long callingIdentity = Binder.clearCallingIdentity();
try {
mExecutor.execute(() ->
- mLocalCallback.onDatagramTransferStateUpdate(
+ mLocalCallback.onDatagramTransferStateChanged(
state, sendPendingCount, receivePendingCount, errorCode));
} finally {
restoreCallingIdentity(callingIdentity);
@@ -69,23 +69,23 @@ public class SatellitePositionUpdateCallback {
}
/**
- * Called when the satellite position changes.
+ * Called when the satellite position changed.
*
* @param pointingInfo The pointing info containing the satellite location.
*/
- public void onSatellitePositionUpdate(@NonNull PointingInfo pointingInfo) {
+ public void onSatellitePositionChanged(@NonNull PointingInfo pointingInfo) {
// Base Implementation
}
/**
- * Called when satellite datagram transfer state changes.
+ * Called when satellite datagram transfer state changed.
*
* @param state The new datagram transfer state.
* @param sendPendingCount The number of datagrams that are currently being sent.
* @param receivePendingCount The number of datagrams that are currently being received.
* @param errorCode If datagram transfer failed, the reason for failure.
*/
- public void onDatagramTransferStateUpdate(
+ public void onDatagramTransferStateChanged(
@SatelliteManager.SatelliteDatagramTransferState int state, int sendPendingCount,
int receivePendingCount, @SatelliteManager.SatelliteError int errorCode) {
// Base Implementation
diff --git a/telephony/java/android/telephony/satellite/SatelliteStateCallback.java b/telephony/java/android/telephony/satellite/SatelliteStateCallback.java
index 81701a27764f..d24bee6be3e2 100644
--- a/telephony/java/android/telephony/satellite/SatelliteStateCallback.java
+++ b/telephony/java/android/telephony/satellite/SatelliteStateCallback.java
@@ -38,11 +38,11 @@ public class SatelliteStateCallback {
}
@Override
- public void onSatelliteModemStateChange(@SatelliteManager.SatelliteModemState int state) {
+ public void onSatelliteModemStateChanged(@SatelliteManager.SatelliteModemState int state) {
final long callingIdentity = Binder.clearCallingIdentity();
try {
mExecutor.execute(() ->
- mLocalCallback.onSatelliteModemStateChange(state));
+ mLocalCallback.onSatelliteModemStateChanged(state));
} finally {
restoreCallingIdentity(callingIdentity);
}
@@ -68,7 +68,7 @@ public class SatelliteStateCallback {
* Called when satellite modem state changes.
* @param state The new satellite modem state.
*/
- public void onSatelliteModemStateChange(@SatelliteManager.SatelliteModemState int state) {
+ public void onSatelliteModemStateChanged(@SatelliteManager.SatelliteModemState int state) {
// Base Implementation
}
diff --git a/telephony/java/android/telephony/satellite/stub/ISatellite.aidl b/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
index e0c31ed8608b..5dc1a6529151 100644
--- a/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
+++ b/telephony/java/android/telephony/satellite/stub/ISatellite.aidl
@@ -46,10 +46,11 @@ oneway interface ISatellite {
void setSatelliteListener(in ISatelliteListener listener, in IIntegerConsumer errorCallback);
/**
- * Enable or disable the satellite service listening mode.
+ * Request to enable or disable the satellite service listening mode.
* Listening mode allows the satellite service to listen for incoming pages.
*
* @param enable True to enable satellite listening mode and false to disable.
+ * @param isDemoMode Whether demo mode is enabled.
* @param errorCallback The callback to receive the error code result of the operation.
*
* Valid error codes returned:
@@ -62,7 +63,8 @@ oneway interface ISatellite {
* SatelliteError:REQUEST_NOT_SUPPORTED
* SatelliteError:NO_RESOURCES
*/
- void setSatelliteListeningEnabled(in boolean enable, in IIntegerConsumer errorCallback);
+ void requestSatelliteListeningEnabled(in boolean enable, in boolean isDemoMode,
+ in IIntegerConsumer errorCallback);
/**
* Request to enable or disable the satellite modem. If the satellite modem is enabled,
@@ -149,7 +151,7 @@ oneway interface ISatellite {
/**
* User started pointing to the satellite.
* The satellite service should report the satellite pointing info via
- * ISatelliteListener#onSatellitePointingInfoChanged as the user device/satellite moves.
+ * ISatelliteListener#onSatellitePositionChanged as the user device/satellite moves.
*
* @param errorCallback The callback to receive the error code result of the operation.
*
@@ -275,7 +277,7 @@ oneway interface ISatellite {
/**
* Poll the pending datagrams to be received over satellite.
* The satellite service should check if there are any pending datagrams to be received over
- * satellitea and report them via ISatelliteListener#onNewDatagrams.
+ * satellite and report them via ISatelliteListener#onSatelliteDatagramsReceived.
*
* @param errorCallback The callback to receive the error code result of the operation.
*
@@ -298,10 +300,9 @@ oneway interface ISatellite {
/**
* Send datagram over satellite.
- * Once sent, the satellite service should report whether the operation was successful via
- * SatelliteListener#onDatagramsDelivered.
*
* @param datagram Datagram to send in byte format.
+ * @param isDemoMode Whether demo mode is enabled.
* @param isEmergency Whether this is an emergency datagram.
* @param errorCallback The callback to receive the error code result of the operation.
*
@@ -321,8 +322,8 @@ oneway interface ISatellite {
* SatelliteError:SATELLITE_NOT_REACHABLE
* SatelliteError:NOT_AUTHORIZED
*/
- void sendSatelliteDatagram(in SatelliteDatagram datagram, in boolean isEmergency,
- in IIntegerConsumer errorCallback);
+ void sendSatelliteDatagram(in SatelliteDatagram datagram, in boolean isDemoMode,
+ in boolean isEmergency, in IIntegerConsumer errorCallback);
/**
* Request the current satellite modem state.
diff --git a/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl b/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl
index 5ecd44290f3a..e24e892e5b55 100644
--- a/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl
+++ b/telephony/java/android/telephony/satellite/stub/ISatelliteListener.aidl
@@ -19,6 +19,7 @@ package android.telephony.satellite.stub;
import android.telephony.satellite.stub.NTRadioTechnology;
import android.telephony.satellite.stub.PointingInfo;
import android.telephony.satellite.stub.SatelliteDatagram;
+import android.telephony.satellite.stub.SatelliteError;
import android.telephony.satellite.stub.SatelliteModemState;
/**
@@ -35,10 +36,10 @@ oneway interface ISatelliteListener {
/**
* Indicates that new datagrams have been received on the device.
*
- * @param datagrams New datagrams received.
+ * @param datagrams Array of new datagrams received.
* @param pendingCount The number of datagrams that are pending.
*/
- void onNewDatagrams(in SatelliteDatagram[] datagrams, in int pendingCount);
+ void onSatelliteDatagramsReceived(in SatelliteDatagram[] datagrams, in int pendingCount);
/**
* Indicates that the satellite has pending datagrams for the device to be pulled.
@@ -52,27 +53,19 @@ oneway interface ISatelliteListener {
*
* @param pointingInfo The current pointing info.
*/
- void onSatellitePointingInfoChanged(in PointingInfo pointingInfo);
+ void onSatellitePositionChanged(in PointingInfo pointingInfo);
/**
* Indicates that the satellite modem state has changed.
*
- * @param mode The current satellite modem state.
+ * @param state The current satellite modem state.
*/
- void onSatelliteModemStateChanged(in SatelliteModemState mode);
+ void onSatelliteModemStateChanged(in SatelliteModemState state);
/**
* Indicates that the satellite radio technology has changed.
*
- * @param technology The current satellite service mode.
+ * @param technology The current satellite radio technology.
*/
void onSatelliteRadioTechnologyChanged(in NTRadioTechnology technology);
-
- /**
- * Indicates that datagram transfer is complete and all datagrams have been delivered.
- *
- * @param delivered True means all datagrams have been delivered and false means there was an
- * error in delivering all datagrams.
- */
- void onDatagramsDelivered(in boolean delivered);
}
diff --git a/telephony/java/android/telephony/satellite/stub/NTRadioTechnology.aidl b/telephony/java/android/telephony/satellite/stub/NTRadioTechnology.aidl
index 64cfa8554123..33164084ea40 100644
--- a/telephony/java/android/telephony/satellite/stub/NTRadioTechnology.aidl
+++ b/telephony/java/android/telephony/satellite/stub/NTRadioTechnology.aidl
@@ -21,12 +21,25 @@ package android.telephony.satellite.stub;
*/
@Backing(type="int")
enum NTRadioTechnology {
- /* 3GPP NB-IoT (Narrowband Internet of Things) over Non-Terrestrial-Networks technology. */
- NB_IOT_NTN,
- /* 3GPP 5G NR over Non-Terrestrial-Networks technology. */
- NR_NTN,
- /* 3GPP eMTC (enhanced Machine-Type Communication) over Non-Terrestrial-Networks technology. */
- EMTC_NTN,
- /* Proprietary technology. */
- PROPRIETARY,
+ /**
+ * 3GPP NB-IoT (Narrowband Internet of Things) over Non-Terrestrial-Networks technology.
+ */
+ NB_IOT_NTN = 0,
+ /*
+ * 3GPP 5G NR over Non-Terrestrial-Networks technology.
+ */
+ NR_NTN = 1,
+ /**
+ * 3GPP eMTC (enhanced Machine-Type Communication) over Non-Terrestrial-Networks technology.
+ */
+ EMTC_NTN = 2,
+ /**
+ * Proprietary technology.
+ */
+ PROPRIETARY = 3,
+ /**
+ * Unknown Non-Terrestrial radio technology. This generic radio technology should be used
+ * only when the radio technology cannot be mapped to other specific radio technologies.
+ */
+ UNKNOWN = -1,
}
diff --git a/telephony/java/android/telephony/satellite/stub/PointingInfo.aidl b/telephony/java/android/telephony/satellite/stub/PointingInfo.aidl
index b515b3ec8c11..83392dd3585e 100644
--- a/telephony/java/android/telephony/satellite/stub/PointingInfo.aidl
+++ b/telephony/java/android/telephony/satellite/stub/PointingInfo.aidl
@@ -30,18 +30,20 @@ parcelable PointingInfo {
*/
float satelliteElevation;
- /** Antenna azimuth in degrees */
- float mAntennaAzimuthDegrees;
+ /**
+ * Antenna azimuth in degrees.
+ */
+ float antennaAzimuth;
/**
* Angle of rotation about the x axis. This value represents the angle between a plane
* parallel to the device's screen and a plane parallel to the ground.
*/
- float mAntennaPitchDegrees;
+ float antennaPitch;
/**
* Angle of rotation about the y axis. This value represents the angle between a plane
* perpendicular to the device's screen and a plane parallel to the ground.
*/
- float mAntennaRollDegrees;
+ float antennaRoll;
}
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java b/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
index 4140939c8469..df5143243812 100644
--- a/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteImplBase.java
@@ -16,7 +16,6 @@
package android.telephony.satellite.stub;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.os.IBinder;
import android.os.RemoteException;
@@ -26,8 +25,6 @@ import com.android.internal.telephony.IBooleanConsumer;
import com.android.internal.telephony.IIntegerConsumer;
import com.android.internal.telephony.util.TelephonyUtils;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
@@ -42,53 +39,6 @@ import java.util.concurrent.Executor;
public class SatelliteImplBase extends SatelliteService {
private static final String TAG = "SatelliteImplBase";
- /** @hide */
- @IntDef(prefix = "NT_RADIO_TECHNOLOGY_", value = {
- NT_RADIO_TECHNOLOGY_NB_IOT_NTN,
- NT_RADIO_TECHNOLOGY_NR_NTN,
- NT_RADIO_TECHNOLOGY_EMTC_NTN,
- NT_RADIO_TECHNOLOGY_PROPRIETARY
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface NTRadioTechnology {}
-
- /** 3GPP NB-IoT (Narrowband Internet of Things) over Non-Terrestrial-Networks technology. */
- public static final int NT_RADIO_TECHNOLOGY_NB_IOT_NTN =
- android.telephony.satellite.stub.NTRadioTechnology.NB_IOT_NTN;
- /** 3GPP 5G NR over Non-Terrestrial-Networks technology. */
- public static final int NT_RADIO_TECHNOLOGY_NR_NTN =
- android.telephony.satellite.stub.NTRadioTechnology.NR_NTN;
- /** 3GPP eMTC (enhanced Machine-Type Communication) over Non-Terrestrial-Networks technology. */
- public static final int NT_RADIO_TECHNOLOGY_EMTC_NTN =
- android.telephony.satellite.stub.NTRadioTechnology.EMTC_NTN;
- /** Proprietary technology. */
- public static final int NT_RADIO_TECHNOLOGY_PROPRIETARY =
- android.telephony.satellite.stub.NTRadioTechnology.PROPRIETARY;
-
- /** @hide */
- @IntDef(prefix = "SATELLITE_MODEM_STATE_", value = {
- SATELLITE_MODEM_STATE_IDLE,
- SATELLITE_MODEM_STATE_LISTENING,
- SATELLITE_MODEM_STATE_MESSAGE_TRANSFERRING,
- SATELLITE_MODEM_STATE_OFF
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface SatelliteModemState {}
-
- /** Satellite modem is in idle state. */
- public static final int SATELLITE_MODEM_STATE_IDLE =
- android.telephony.satellite.stub.SatelliteModemState.SATELLITE_MODEM_STATE_IDLE;
- /** Satellite modem is listening for incoming messages. */
- public static final int SATELLITE_MODEM_STATE_LISTENING =
- android.telephony.satellite.stub.SatelliteModemState.SATELLITE_MODEM_STATE_LISTENING;
- /** Satellite modem is sending and/or receiving messages. */
- public static final int SATELLITE_MODEM_STATE_MESSAGE_TRANSFERRING =
- android.telephony.satellite.stub.SatelliteModemState
- .SATELLITE_MODEM_STATE_MESSAGE_TRANSFERRING;
- /** Satellite modem is powered off. */
- public static final int SATELLITE_MODEM_STATE_OFF =
- android.telephony.satellite.stub.SatelliteModemState.SATELLITE_MODEM_STATE_OFF;
-
protected final Executor mExecutor;
/**
@@ -121,12 +71,12 @@ public class SatelliteImplBase extends SatelliteService {
}
@Override
- public void setSatelliteListeningEnabled(boolean enable, IIntegerConsumer errorCallback)
- throws RemoteException {
+ public void requestSatelliteListeningEnabled(boolean enable, boolean isDemoMode,
+ IIntegerConsumer errorCallback) throws RemoteException {
executeMethodAsync(
() -> SatelliteImplBase.this
- .setSatelliteListeningEnabled(enable, errorCallback),
- "setSatelliteListeningEnabled");
+ .requestSatelliteListeningEnabled(enable, isDemoMode, errorCallback),
+ "requestSatelliteListeningEnabled");
}
@Override
@@ -223,11 +173,12 @@ public class SatelliteImplBase extends SatelliteService {
}
@Override
- public void sendSatelliteDatagram(SatelliteDatagram datagram, boolean isEmergency,
- IIntegerConsumer errorCallback) throws RemoteException {
+ public void sendSatelliteDatagram(SatelliteDatagram datagram, boolean isDemoMode,
+ boolean isEmergency, IIntegerConsumer errorCallback) throws RemoteException {
executeMethodAsync(
() -> SatelliteImplBase.this
- .sendSatelliteDatagram(datagram, isEmergency, errorCallback),
+ .sendSatelliteDatagram(
+ datagram, isDemoMode, isEmergency, errorCallback),
"sendSatelliteDatagram");
}
@@ -296,10 +247,11 @@ public class SatelliteImplBase extends SatelliteService {
}
/**
- * Enable or disable the satellite service listening mode.
+ * Request to enable or disable the satellite service listening mode.
* Listening mode allows the satellite service to listen for incoming pages.
*
* @param enable True to enable satellite listening mode and false to disable.
+ * @param isDemoMode Whether demo mode is enabled.
* @param errorCallback The callback to receive the error code result of the operation.
*
* Valid error codes returned:
@@ -312,7 +264,7 @@ public class SatelliteImplBase extends SatelliteService {
* SatelliteError:REQUEST_NOT_SUPPORTED
* SatelliteError:NO_RESOURCES
*/
- public void setSatelliteListeningEnabled(boolean enable,
+ public void requestSatelliteListeningEnabled(boolean enable, boolean isDemoMode,
@NonNull IIntegerConsumer errorCallback) {
// stub implementation
}
@@ -411,7 +363,7 @@ public class SatelliteImplBase extends SatelliteService {
/**
* User started pointing to the satellite.
* The satellite service should report the satellite pointing info via
- * ISatelliteListener#onSatellitePointingInfoChanged as the user device/satellite moves.
+ * ISatelliteListener#onSatellitePositionChanged as the user device/satellite moves.
*
* @param errorCallback The callback to receive the error code result of the operation.
*
@@ -549,8 +501,9 @@ public class SatelliteImplBase extends SatelliteService {
}
/**
- * Poll the pending datagrams.
- * The satellite service should report the new datagrams via ISatelliteListener#onNewDatagrams.
+ * Poll the pending datagrams to be received over satellite.
+ * The satellite service should check if there are any pending datagrams to be received over
+ * satellite and report them via ISatelliteListener#onSatelliteDatagramsReceived.
*
* @param errorCallback The callback to receive the error code result of the operation.
*
@@ -575,10 +528,9 @@ public class SatelliteImplBase extends SatelliteService {
/**
* Send datagram over satellite.
- * Once sent, the satellite service should report whether the operation was successful via
- * SatelliteListener#onDatagramsDelivered.
*
* @param datagram Datagram to send in byte format.
+ * @param isDemoMode Whether demo mode is enabled.
* @param isEmergency Whether this is an emergency datagram.
* @param errorCallback The callback to receive the error code result of the operation.
*
@@ -598,8 +550,8 @@ public class SatelliteImplBase extends SatelliteService {
* SatelliteError:SATELLITE_NOT_REACHABLE
* SatelliteError:NOT_AUTHORIZED
*/
- public void sendSatelliteDatagram(@NonNull SatelliteDatagram datagram, boolean isEmergency,
- @NonNull IIntegerConsumer errorCallback) {
+ public void sendSatelliteDatagram(@NonNull SatelliteDatagram datagram, boolean isDemoMode,
+ boolean isEmergency, @NonNull IIntegerConsumer errorCallback) {
// stub implementation
}
diff --git a/telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl b/telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl
index 3f5ee561cbd7..5ee7f9abdcf1 100644
--- a/telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl
+++ b/telephony/java/android/telephony/satellite/stub/SatelliteModemState.aidl
@@ -21,12 +21,29 @@ package android.telephony.satellite.stub;
*/
@Backing(type="int")
enum SatelliteModemState {
- /* Satellite modem is in idle state. */
+ /**
+ * Satellite modem is in idle state.
+ */
SATELLITE_MODEM_STATE_IDLE = 0,
- /* Satellite modem is listening for incoming messages. */
+ /**
+ * Satellite modem is listening for incoming datagrams.
+ */
SATELLITE_MODEM_STATE_LISTENING = 1,
- /* Satellite modem is sending and/or receiving messages. */
- SATELLITE_MODEM_STATE_MESSAGE_TRANSFERRING = 2,
- /* Satellite modem is powered off. */
- SATELLITE_MODEM_STATE_OFF = 3,
+ /**
+ * Satellite modem is sending and/or receiving datagrams.
+ */
+ SATELLITE_MODEM_STATE_DATAGRAM_TRANSFERRING = 2,
+ /**
+ * Satellite modem is retrying to send and/or receive datagrams.
+ */
+ SATELLITE_MODEM_STATE_DATAGRAM_RETRYING = 3,
+ /**
+ * Satellite modem is powered off.
+ */
+ SATELLITE_MODEM_STATE_OFF = 4,
+ /**
+ * Satellite modem state is unknown. This generic modem state should be used only when the
+ * modem state cannot be mapped to other specific modem states.
+ */
+ SATELLITE_MODEM_STATE_UNKNOWN = -1,
}
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index af4edc443151..632a6874b5f5 100644
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -236,8 +236,6 @@ interface ISub {
int getSlotIndex(int subId);
- int[] getSubIds(int slotIndex);
-
int getSubId(int slotIndex);
int getDefaultSubId();
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 62e087f3ca34..f4801c2f002f 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2728,6 +2728,29 @@ interface ITelephony {
void requestIsSatelliteEnabled(int subId, in ResultReceiver receiver);
/**
+ * Request to enable or disable the satellite service demo mode.
+ *
+ * @param subId The subId of the subscription to enable or disable the satellite demo mode for.
+ * @param enable True to enable the satellite demo mode and false to disable.
+ * @param callback The callback to get the error code of the request.
+ */
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+ void requestSatelliteDemoModeEnabled(int subId, boolean enable, in IIntegerConsumer callback);
+
+ /**
+ * Request to get whether the satellite service demo mode is enabled.
+ *
+ * @param subId The subId of the subscription to request whether the satellite demo mode is
+ * enabled for.
+ * @param receiver Result receiver to get the error code of the request and whether the
+ * satellite demo mode is enabled.
+ */
+ @JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ + "android.Manifest.permission.SATELLITE_COMMUNICATION)")
+ void requestIsSatelliteDemoModeEnabled(int subId, in ResultReceiver receiver);
+
+ /**
* Request to get whether the satellite service is supported on the device.
*
* @param subId The subId of the subscription to check whether satellite is supported for.
@@ -2772,15 +2795,15 @@ interface ITelephony {
in ISatellitePositionUpdateCallback callback);
/**
- * Request to get the maximum number of characters per text message on satellite.
+ * Request to get the maximum number of bytes per datagram that can be sent to satellite.
*
* @param subId The subId of the subscription to get the maximum number of characters for.
* @param receiver Result receiver to get the error code of the request and the requested
- * maximum number of characters per text message on satellite.
+ * maximum number of bytes per datagram that can be sent to satellite.
*/
@JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ "android.Manifest.permission.SATELLITE_COMMUNICATION)")
- void requestMaxCharactersPerSatelliteTextMessage(int subId, in ResultReceiver receiver);
+ void requestMaxSizePerSendingDatagram(int subId, in ResultReceiver receiver);
/**
* Register the subscription with a satellite provider.
@@ -2815,9 +2838,9 @@ interface ITelephony {
/**
- * Register for the satellite provision state change.
+ * Registers for provision state changed from satellite modem.
*
- * @param subId The subId of the subscription to register for provision state changes.
+ * @param subId The subId of the subscription to register for provision state changed.
* @param callback The callback to handle the satellite provision state changed event.
*
* @return The {@link SatelliteError} result of the operation.
@@ -2828,10 +2851,10 @@ interface ITelephony {
in ISatelliteProvisionStateCallback callback);
/**
- * Unregister for the satellite provision state change.
+ * Unregisters for provision state changed from satellite modem.
* If callback was not registered before, the request will be ignored.
*
- * @param subId The subId of the subscription to unregister for provision state changes.
+ * @param subId The subId of the subscription to unregister for provision state changed.
* @param callback The callback that was passed to registerForSatelliteProvisionStateChanged.
*/
@JavaPassthrough(annotation="@android.annotation.RequiresPermission("
@@ -2851,27 +2874,27 @@ interface ITelephony {
void requestIsSatelliteProvisioned(int subId, in ResultReceiver receiver);
/**
- * Register for listening to satellite modem state changes.
+ * Registers for modem state changed from satellite modem.
*
- * @param subId The subId of the subscription to register for satellite modem state changes.
+ * @param subId The subId of the subscription to register for satellite modem state changed.
* @param callback The callback to handle the satellite modem state changed event.
*
* @return The {@link SatelliteError} result of the operation.
*/
@JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ "android.Manifest.permission.SATELLITE_COMMUNICATION)")
- int registerForSatelliteModemStateChange(int subId, ISatelliteStateCallback callback);
+ int registerForSatelliteModemStateChanged(int subId, ISatelliteStateCallback callback);
/**
- * Unregister to stop listening to satellite modem state changes.
+ * Unregisters for modem state changed from satellite modem.
* If callback was not registered before, the request will be ignored.
*
- * @param subId The subId of the subscription to unregister for satellite modem state changes.
- * @param callback The callback that was passed to registerForSatelliteStateChange.
+ * @param subId The subId of the subscription to unregister for satellite modem state changed.
+ * @param callback The callback that was passed to registerForSatelliteStateChanged.
*/
@JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ "android.Manifest.permission.SATELLITE_COMMUNICATION)")
- void unregisterForSatelliteModemStateChange(int subId, ISatelliteStateCallback callback);
+ void unregisterForSatelliteModemStateChanged(int subId, ISatelliteStateCallback callback);
/**
* Register to receive incoming datagrams over satellite.
@@ -2912,14 +2935,16 @@ interface ITelephony {
* Send datagram over satellite.
*
* @param subId The subId of the subscription to send satellite datagrams for.
+ * @param datagramId An id that uniquely identifies datagram requested to be sent.
* @param datagramType Type of datagram.
* @param datagram Datagram to send over satellite.
- * @param callback The callback to get the error code of the request.
+ * @param receiver Result receiver to get the datagramId if datagram is sent successfully else
+ * error code of the request.
*/
@JavaPassthrough(annotation="@android.annotation.RequiresPermission("
+ "android.Manifest.permission.SATELLITE_COMMUNICATION)")
- void sendSatelliteDatagram(int subId, int datagramType, in SatelliteDatagram datagram,
- IIntegerConsumer callback);
+ void sendSatelliteDatagram(int subId, long datagramId, int datagramType,
+ in SatelliteDatagram datagram, in ResultReceiver receiver);
/**
* Request to get whether satellite communication is allowed for the current location.
diff --git a/test-mock/src/android/test/mock/MockContentProvider.java b/test-mock/src/android/test/mock/MockContentProvider.java
index 7be42f4f36f5..7f084f896e3f 100644
--- a/test-mock/src/android/test/mock/MockContentProvider.java
+++ b/test-mock/src/android/test/mock/MockContentProvider.java
@@ -80,16 +80,22 @@ public class MockContentProvider extends ContentProvider {
}
@Override
- public String getType(Uri url) throws RemoteException {
+ public String getType(@NonNull AttributionSource attributionSource,
+ Uri url) throws RemoteException {
return MockContentProvider.this.getType(url);
}
@Override
- public void getTypeAsync(Uri uri, RemoteCallback callback) throws RemoteException {
+ public void getTypeAsync(@NonNull AttributionSource attributionSource,
+ Uri uri, RemoteCallback callback) throws RemoteException {
MockContentProvider.this.getTypeAsync(uri, callback);
}
@Override
+ public void getTypeAnonymousAsync(Uri uri, RemoteCallback callback) throws RemoteException {
+ MockContentProvider.this.getTypeAnonymousAsync(uri, callback);
+ }
+ @Override
public Uri insert(@NonNull AttributionSource attributionSource, Uri url,
ContentValues initialValues, Bundle extras) throws RemoteException {
return MockContentProvider.this.insert(url, initialValues, extras);
@@ -247,6 +253,23 @@ public class MockContentProvider extends ContentProvider {
}
@Override
+ public String getTypeAnonymous(Uri uri) {
+ throw new UnsupportedOperationException("unimplemented mock method");
+ }
+
+ /**
+ * @hide
+ */
+ @SuppressWarnings("deprecation")
+ public void getTypeAnonymousAsync(Uri uri, RemoteCallback remoteCallback) {
+ AsyncTask.SERIAL_EXECUTOR.execute(() -> {
+ final Bundle bundle = new Bundle();
+ bundle.putString(ContentResolver.REMOTE_CALLBACK_RESULT, getTypeAnonymous(uri));
+ remoteCallback.sendResult(bundle);
+ });
+ }
+
+ @Override
public Uri insert(Uri uri, ContentValues values) {
throw new UnsupportedOperationException("unimplemented mock method");
}
diff --git a/test-mock/src/android/test/mock/MockIContentProvider.java b/test-mock/src/android/test/mock/MockIContentProvider.java
index b81c70704d79..bb2996a2cb40 100644
--- a/test-mock/src/android/test/mock/MockIContentProvider.java
+++ b/test-mock/src/android/test/mock/MockIContentProvider.java
@@ -61,16 +61,30 @@ public class MockIContentProvider implements IContentProvider {
}
@Override
- public String getType(Uri url) {
+ public String getType(@NonNull AttributionSource attributionSource, Uri url) {
throw new UnsupportedOperationException("unimplemented mock method");
}
@Override
@SuppressWarnings("deprecation")
- public void getTypeAsync(Uri uri, RemoteCallback remoteCallback) {
+ public void getTypeAsync(@NonNull AttributionSource attributionSource,
+ Uri uri, RemoteCallback remoteCallback) {
AsyncTask.SERIAL_EXECUTOR.execute(() -> {
final Bundle bundle = new Bundle();
- bundle.putString(ContentResolver.REMOTE_CALLBACK_RESULT, getType(uri));
+ bundle.putString(ContentResolver.REMOTE_CALLBACK_RESULT, getType(attributionSource,
+ uri));
+ remoteCallback.sendResult(bundle);
+ });
+ }
+ public String getTypeAnonymous(Uri url) {
+ throw new UnsupportedOperationException("unimplemented mock method");
+ }
+ @Override
+ @SuppressWarnings("deprecation")
+ public void getTypeAnonymousAsync(Uri uri, RemoteCallback remoteCallback) {
+ AsyncTask.SERIAL_EXECUTOR.execute(() -> {
+ final Bundle bundle = new Bundle();
+ bundle.putString(ContentResolver.REMOTE_CALLBACK_RESULT, getTypeAnonymous(uri));
remoteCallback.sendResult(bundle);
});
}
diff --git a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
index 90ddb6ffb34a..d2a6bf288be4 100644
--- a/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
+++ b/tests/BackgroundDexOptServiceIntegrationTests/src/com/android/server/pm/BackgroundDexOptServiceIntegrationTests.java
@@ -31,6 +31,7 @@ import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -299,6 +300,8 @@ public final class BackgroundDexOptServiceIntegrationTests {
// Test that background dexopt under low storage conditions downgrades unused packages.
@Test
+ @Ignore("b/251438180: This test has been failing for a long time; temporarily disable it while"
+ + " we investigate this issue.")
public void testBackgroundDexOptDowngradeSuccessful() throws IOException {
// Should be more than DOWNGRADE_AFTER_DAYS.
long deltaDays = DOWNGRADE_AFTER_DAYS + 1;
diff --git a/tests/SilkFX/assets/gainmaps/granddam.jpg b/tests/SilkFX/assets/gainmaps/granddam.jpg
new file mode 100644
index 000000000000..823f14efcbb2
--- /dev/null
+++ b/tests/SilkFX/assets/gainmaps/granddam.jpg
Binary files differ
diff --git a/tests/SilkFX/assets/gainmaps/lightbulb.jpg b/tests/SilkFX/assets/gainmaps/lightbulb.jpg
new file mode 100644
index 000000000000..232c5f0937df
--- /dev/null
+++ b/tests/SilkFX/assets/gainmaps/lightbulb.jpg
Binary files differ
diff --git a/tests/SilkFX/assets/gainmaps/porsche911.jpg b/tests/SilkFX/assets/gainmaps/porsche911.jpg
new file mode 100644
index 000000000000..50f4fc83910e
--- /dev/null
+++ b/tests/SilkFX/assets/gainmaps/porsche911.jpg
Binary files differ
diff --git a/tools/processors/immutability/TEST_MAPPING b/tools/processors/immutability/TEST_MAPPING
deleted file mode 100644
index 4e8e2386ad8d..000000000000
--- a/tools/processors/immutability/TEST_MAPPING
+++ /dev/null
@@ -1,7 +0,0 @@
-{
- "presubmit": [
- {
- "name": "ImmutabilityAnnotationProcessorUnitTests"
- }
- ]
-}
diff --git a/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java b/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
index 13084f47efe6..f3af06247576 100644
--- a/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
+++ b/wifi/java/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityService.java
@@ -59,7 +59,7 @@ public abstract class SharedConnectivityService extends Service {
private static final String TAG = SharedConnectivityService.class.getSimpleName();
private static final boolean DEBUG = true;
- private final Handler mHandler;
+ private Handler mHandler;
private final List<ISharedConnectivityCallback> mCallbacks = new ArrayList<>();
// Used to find DeathRecipient when unregistering a callback to call unlinkToDeath.
private final Map<ISharedConnectivityCallback, DeathRecipient> mDeathRecipientMap =
@@ -71,14 +71,6 @@ public abstract class SharedConnectivityService extends Service {
private TetherNetworkConnectionStatus mTetherNetworkConnectionStatus;
private KnownNetworkConnectionStatus mKnownNetworkConnectionStatus;
- public SharedConnectivityService() {
- mHandler = new Handler(getMainLooper());
- }
-
- public SharedConnectivityService(@NonNull Handler handler) {
- mHandler = handler;
- }
-
private final class DeathRecipient implements IBinder.DeathRecipient {
ISharedConnectivityCallback mCallback;
@@ -97,6 +89,7 @@ public abstract class SharedConnectivityService extends Service {
@Nullable
public final IBinder onBind(@NonNull Intent intent) {
if (DEBUG) Log.i(TAG, "onBind intent=" + intent);
+ mHandler = new Handler(getMainLooper());
return new ISharedConnectivityService.Stub() {
@Override
public void registerCallback(ISharedConnectivityCallback callback) {
diff --git a/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java b/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java
index fb8d7bf95ea0..d7f7fea4df3e 100644
--- a/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java
+++ b/wifi/tests/src/android/net/wifi/sharedconnectivity/service/SharedConnectivityServiceTest.java
@@ -17,16 +17,21 @@
package android.net.wifi.sharedconnectivity.service;
import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.when;
+import android.content.Context;
import android.content.Intent;
import android.net.wifi.sharedconnectivity.app.KnownNetwork;
import android.net.wifi.sharedconnectivity.app.TetherNetwork;
-import android.os.Handler;
-import android.os.test.TestLooper;
+import android.os.Looper;
+import androidx.annotation.NonNull;
import androidx.test.filters.SmallTest;
+import org.junit.Before;
import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
/**
* Unit tests for {@link android.net.wifi.sharedconnectivity.service.SharedConnectivityService}.
@@ -34,6 +39,33 @@ import org.junit.Test;
@SmallTest
public class SharedConnectivityServiceTest {
+ @Mock
+ Context mContext;
+
+ static class FakeSharedConnectivityService extends SharedConnectivityService {
+ public void attachBaseContext(Context context) {
+ super.attachBaseContext(context);
+ }
+
+ @Override
+ public void onConnectTetherNetwork(@NonNull TetherNetwork network) {}
+
+ @Override
+ public void onDisconnectTetherNetwork(@NonNull TetherNetwork network) {}
+
+ @Override
+ public void onConnectKnownNetwork(@NonNull KnownNetwork network) {}
+
+ @Override
+ public void onForgetKnownNetwork(@NonNull KnownNetwork network) {}
+ }
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
+ }
+
/**
* Verifies service returns
*/
@@ -51,18 +83,8 @@ public class SharedConnectivityServiceTest {
}
private SharedConnectivityService createService() {
- return new SharedConnectivityService(new Handler(new TestLooper().getLooper())) {
- @Override
- public void onConnectTetherNetwork(TetherNetwork network) {}
-
- @Override
- public void onDisconnectTetherNetwork(TetherNetwork network) {}
-
- @Override
- public void onConnectKnownNetwork(KnownNetwork network) {}
-
- @Override
- public void onForgetKnownNetwork(KnownNetwork network) {}
- };
+ FakeSharedConnectivityService service = new FakeSharedConnectivityService();
+ service.attachBaseContext(mContext);
+ return service;
}
}