summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/test-current.txt50
-rw-r--r--cmds/bootanimation/BootAnimation.cpp5
-rw-r--r--cmds/statsd/src/atoms.proto59
-rw-r--r--cmds/statsd/src/external/PowerStatsPuller.cpp2
-rw-r--r--config/hiddenapi-greylist-packages.txt41
-rw-r--r--config/hiddenapi-greylist.txt712
-rw-r--r--core/java/android/app/ActivityManagerInternal.java2
-rw-r--r--core/java/android/app/StatusBarManager.java64
-rw-r--r--core/java/android/app/admin/DevicePolicyEventLogger.java18
-rw-r--r--core/java/android/bluetooth/BluetoothProfileConnector.java10
-rw-r--r--core/java/android/content/pm/PackageManager.java2
-rw-r--r--core/java/android/content/pm/ShortcutInfo.java18
-rw-r--r--core/java/android/content/rollback/IRollbackManager.aidl4
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java6
-rw-r--r--core/java/android/net/DnsResolver.java6
-rw-r--r--core/java/android/net/NetworkStats.java357
-rw-r--r--core/java/android/net/NetworkUtils.java5
-rwxr-xr-xcore/java/android/os/Build.java3
-rw-r--r--core/java/android/os/GraphicsEnvironment.java14
-rw-r--r--core/java/android/os/Parcel.java2
-rw-r--r--core/java/android/os/SystemProperties.java1
-rw-r--r--core/java/android/os/image/DynamicSystemClient.java12
-rw-r--r--core/java/android/provider/Settings.java11
-rw-r--r--core/java/android/service/notification/Adjustment.java14
-rw-r--r--core/java/android/service/notification/NotificationAssistantService.java11
-rw-r--r--core/java/android/util/FeatureFlagUtils.java2
-rw-r--r--core/java/android/view/Window.java2
-rw-r--r--core/java/android/widget/TextView.java2
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java273
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java8
-rw-r--r--core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java39
-rw-r--r--core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperationsRegistry.java17
-rw-r--r--core/java/com/android/internal/net/VpnInfo.java10
-rw-r--r--core/jni/android_media_AudioTrack.cpp13
-rw-r--r--core/jni/android_net_NetUtils.cpp18
-rw-r--r--core/jni/android_os_Debug.cpp2
-rw-r--r--core/proto/android/server/jobscheduler.proto93
-rw-r--r--core/proto/android/stats/location/location_enums.proto122
-rw-r--r--core/res/AndroidManifest.xml4
-rw-r--r--core/res/res/drawable/ic_audio_alarm.xml4
-rw-r--r--core/res/res/drawable/ic_audio_alarm_mute.xml4
-rw-r--r--core/res/res/drawable/ic_bluetooth_share_icon.xml2
-rw-r--r--core/res/res/drawable/ic_corp_badge.xml4
-rw-r--r--core/res/res/drawable/ic_file_copy.xml3
-rw-r--r--core/res/res/drawable/ic_qs_auto_rotate.xml4
-rw-r--r--core/res/res/drawable/ic_qs_battery_saver.xml4
-rw-r--r--core/res/res/drawable/ic_qs_flashlight.xml4
-rw-r--r--core/res/res/drawable/perm_group_activity_recognition.xml1
-rw-r--r--core/res/res/drawable/perm_group_aural.xml1
-rw-r--r--core/res/res/drawable/perm_group_calendar.xml5
-rw-r--r--core/res/res/drawable/perm_group_call_log.xml1
-rw-r--r--core/res/res/drawable/perm_group_camera.xml1
-rw-r--r--core/res/res/drawable/perm_group_contacts.xml1
-rw-r--r--core/res/res/drawable/perm_group_location.xml1
-rw-r--r--core/res/res/drawable/perm_group_microphone.xml1
-rw-r--r--core/res/res/drawable/perm_group_phone_calls.xml3
-rw-r--r--core/res/res/drawable/perm_group_sensors.xml1
-rw-r--r--core/res/res/drawable/perm_group_sms.xml1
-rw-r--r--core/res/res/drawable/perm_group_storage.xml1
-rw-r--r--core/res/res/drawable/perm_group_visual.xml3
-rw-r--r--core/res/res/layout/chooser_grid_preview_file.xml3
-rw-r--r--core/res/res/layout/chooser_grid_preview_image.xml1
-rw-r--r--core/res/res/values-mcc310-mnc030/config.xml (renamed from packages/SystemUI/res/values-mcc310-mnc030/config.xml)0
-rw-r--r--core/res/res/values-mcc310-mnc070/config.xml (renamed from packages/SystemUI/res/values-mcc310-mnc070/config.xml)0
-rw-r--r--core/res/res/values-mcc310-mnc170/config.xml (renamed from packages/SystemUI/res/values-mcc310-mnc170/config.xml)0
-rw-r--r--core/res/res/values-mcc310-mnc280/config.xml (renamed from packages/SystemUI/res/values-mcc310-mnc280/config.xml)0
-rw-r--r--core/res/res/values-mcc310-mnc380/config.xml (renamed from packages/SystemUI/res/values-mcc310-mnc380/config.xml)0
-rw-r--r--core/res/res/values-mcc310-mnc410/config.xml4
-rw-r--r--core/res/res/values-mcc310-mnc560/config.xml (renamed from packages/SystemUI/res/values-mcc310-mnc410/config.xml)0
-rw-r--r--core/res/res/values-mcc310-mnc950/config.xml (renamed from packages/SystemUI/res/values-mcc310-mnc560/config.xml)0
-rw-r--r--core/res/res/values-mcc311-mnc180/config.xml (renamed from packages/SystemUI/res/values-mcc310-mnc950/config.xml)0
-rwxr-xr-xcore/res/res/values-mcc311-mnc480/config.xml3
-rw-r--r--core/res/res/values/config.xml25
-rw-r--r--core/res/res/values/dimens.xml4
-rw-r--r--core/res/res/values/symbols.xml12
-rw-r--r--core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java54
-rw-r--r--core/tests/coretests/res/values/overlayable_icons_test.xml4
-rw-r--r--data/etc/car/Android.bp7
-rw-r--r--data/etc/car/android.car.cluster.xml24
-rw-r--r--data/etc/car/com.android.car.xml1
-rw-r--r--data/etc/car/com.google.android.car.kitchensink.xml1
-rw-r--r--data/etc/privapp-permissions-platform.xml1
-rw-r--r--graphics/java/android/graphics/Outline.java10
-rw-r--r--keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java12
-rw-r--r--libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp23
-rw-r--r--libs/hwui/pipeline/skia/SkiaRecordingCanvas.h2
-rw-r--r--media/java/android/media/AudioAttributes.java8
-rw-r--r--media/java/android/media/AudioManager.java32
-rw-r--r--media/java/android/media/AudioTrack.java136
-rw-r--r--media/java/android/media/ExifInterface.java10
-rw-r--r--media/java/android/media/IAudioService.aidl3
-rw-r--r--media/java/android/media/MediaFile.java1
-rw-r--r--media/java/android/media/MediaHTTPConnection.java61
-rw-r--r--media/java/android/media/MediaMetadataRetriever.java2
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CameraTest.java3
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestHelper.java12
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java6
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2SwitchPreviewTest.java7
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/CameraStressTest.java6
-rw-r--r--native/android/surface_control.cpp3
-rw-r--r--packages/CaptivePortalLogin/OWNERS7
-rw-r--r--packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java5
-rw-r--r--packages/CarSystemUI/res/layout/car_ongoing_privacy_chip.xml37
-rw-r--r--packages/CarSystemUI/res/layout/car_top_navigation_bar.xml2
-rw-r--r--packages/CarSystemUI/res/layout/notification_center_activity.xml2
-rw-r--r--packages/CarSystemUI/res/values/dimens.xml20
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java81
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/OngoingPrivacyChip.java228
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyApplication.java62
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyDialogBuilder.java59
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyItem.java46
-rw-r--r--packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyType.java53
-rw-r--r--packages/ExtServices/OWNERS4
-rw-r--r--packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java2
-rw-r--r--packages/NetworkPermissionConfig/OWNERS5
-rw-r--r--packages/NetworkStack/OWNERS9
-rw-r--r--packages/NetworkStack/src/com/android/server/NetworkStackService.java3
-rw-r--r--packages/NetworkStack/src/com/android/server/util/PermissionUtil.java34
-rw-r--r--packages/SettingsLib/res/values/strings.xml4
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/net/SignalStrengthUtil.java34
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java9
-rw-r--r--packages/Shell/AndroidManifest.xml6
-rw-r--r--packages/Shell/src/com/android/shell/BugreportProgressService.java7
-rw-r--r--packages/SystemUI/Android.bp2
-rw-r--r--packages/SystemUI/OWNERS3
-rw-r--r--packages/SystemUI/res-keyguard/drawable/bubble_hour_hand.xml2
-rw-r--r--packages/SystemUI/res-keyguard/drawable/bubble_minute_hand.xml2
-rw-r--r--packages/SystemUI/res/anim/lock_in.xml (renamed from core/res/res/anim/lock_in.xml)0
-rw-r--r--packages/SystemUI/res/anim/lock_in_circular.xml327
-rw-r--r--packages/SystemUI/res/anim/lock_in_filled.xml190
-rw-r--r--packages/SystemUI/res/anim/lock_in_rounded.xml336
-rw-r--r--packages/SystemUI/res/anim/lock_lock.xml (renamed from core/res/res/anim/lock_lock.xml)29
-rw-r--r--packages/SystemUI/res/anim/lock_lock_circular.xml320
-rw-r--r--packages/SystemUI/res/anim/lock_lock_filled.xml215
-rw-r--r--packages/SystemUI/res/anim/lock_lock_rounded.xml314
-rw-r--r--packages/SystemUI/res/anim/lock_scanning.xml (renamed from core/res/res/anim/lock_scanning.xml)0
-rw-r--r--packages/SystemUI/res/anim/lock_scanning_circular.xml537
-rw-r--r--packages/SystemUI/res/anim/lock_scanning_filled.xml339
-rw-r--r--packages/SystemUI/res/anim/lock_scanning_rounded.xml531
-rw-r--r--packages/SystemUI/res/anim/lock_to_error.xml (renamed from core/res/res/anim/lock_to_error.xml)0
-rw-r--r--packages/SystemUI/res/anim/lock_to_error_circular.xml276
-rw-r--r--packages/SystemUI/res/anim/lock_to_error_filled.xml188
-rw-r--r--packages/SystemUI/res/anim/lock_to_error_rounded.xml270
-rw-r--r--packages/SystemUI/res/anim/lock_unlock.xml (renamed from core/res/res/anim/lock_unlock.xml)0
-rw-r--r--packages/SystemUI/res/anim/lock_unlock_circular.xml298
-rw-r--r--packages/SystemUI/res/anim/lock_unlock_filled.xml204
-rw-r--r--packages/SystemUI/res/anim/lock_unlock_rounded.xml292
-rw-r--r--packages/SystemUI/res/drawable/corner_gesture_hint.xml25
-rw-r--r--packages/SystemUI/res/drawable/ic_emergency_star.xml28
-rw-r--r--packages/SystemUI/res/drawable/ic_info_outline.xml4
-rw-r--r--packages/SystemUI/res/drawable/ic_invert_colors.xml4
-rw-r--r--packages/SystemUI/res/drawable/ic_notifications_alert.xml14
-rw-r--r--packages/SystemUI/res/drawable/ic_notifications_silence.xml18
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_bluetooth_connecting.xml4
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_no_sim.xml4
-rw-r--r--packages/SystemUI/res/drawable/ic_screenshot_delete.xml4
-rw-r--r--packages/SystemUI/res/drawable/ic_volume_media.xml2
-rw-r--r--packages/SystemUI/res/drawable/ic_volume_media_bt.xml16
-rw-r--r--packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml14
-rw-r--r--packages/SystemUI/res/drawable/ic_volume_media_mute.xml5
-rw-r--r--packages/SystemUI/res/layout-land/global_actions_column.xml16
-rw-r--r--packages/SystemUI/res/layout-land/global_actions_column_seascape.xml16
-rw-r--r--packages/SystemUI/res/layout/global_actions_grid.xml126
-rw-r--r--packages/SystemUI/res/layout/invocation_lights.xml23
-rw-r--r--packages/SystemUI/res/layout/notification_info.xml8
-rw-r--r--packages/SystemUI/res/layout/quick_settings_header_info.xml1
-rw-r--r--packages/SystemUI/res/layout/rounded_corners.xml34
-rw-r--r--packages/SystemUI/res/layout/status_bar_notification_section_header.xml2
-rw-r--r--packages/SystemUI/res/values-mcc311-mnc180/config.xml26
-rw-r--r--packages/SystemUI/res/values-mcc311-mnc480/config.xml26
-rw-r--r--packages/SystemUI/res/values-night/colors.xml9
-rw-r--r--packages/SystemUI/res/values/colors.xml13
-rw-r--r--packages/SystemUI/res/values/config.xml7
-rw-r--r--packages/SystemUI/res/values/dimens.xml4
-rw-r--r--packages/SystemUI/res/values/strings.xml10
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java14
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/SystemGestureExclusionListenerCompat.java85
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java6
-rw-r--r--packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java7
-rw-r--r--packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java80
-rw-r--r--packages/SystemUI/src/com/android/systemui/BatteryMeterView.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/CornerHandleView.java160
-rw-r--r--packages/SystemUI/src/com/android/systemui/ScreenDecorations.java144
-rw-r--r--packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehavior.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java135
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java75
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistHandleOffBehavior.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java177
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/AssistManager.java96
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/ui/CircularCornerPathRenderer.java65
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/ui/CornerPathRenderer.java140
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java187
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/ui/DisplayUtils.java128
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/ui/EdgeLight.java99
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java194
-rw-r--r--packages/SystemUI/src/com/android/systemui/assist/ui/PerimeterPathGuide.java389
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java48
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java172
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java260
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java71
-rw-r--r--packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java23
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java63
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt75
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java94
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt37
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java34
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ButtonLinearLayout.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java77
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java46
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java102
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java34
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java57
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java46
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/AutoMarqueeTextView.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java33
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java20
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java62
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java28
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTest.java91
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTestCase.java31
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java80
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsGridLayoutTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/globalactions/ListGridLayoutTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/MediaArtworkProcessorTest.kt109
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java211
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java28
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java173
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java17
-rw-r--r--packages/overlays/Android.mk5
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_battery_80_24dp.xml (renamed from packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_battery_status_bad_24dp.xml)2
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bt_misc_hid.xml1
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_file_copy.xml2
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_lock.xml1
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_lock_open.xml1
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_lockscreen_ime.xml1
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_mode_edit.xml1
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_notifications_alerted.xml (renamed from packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_delete_accent.xml)10
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_phone.xml2
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_qs_battery_saver.xml2
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_qs_bluetooth.xml1
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_0_4_bar.xml52
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_1_4_bar.xml47
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_2_4_bar.xml42
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_3_4_bar.xml37
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_4_4_bar.xml32
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_activity_recognition.xml2
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_calendar.xml1
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_call_log.xml2
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_camera.xml2
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_contacts.xml2
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_location.xml2
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_microphone.xml2
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_phone_calls.xml2
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_sensors.xml2
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_sms.xml2
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_storage.xml2
-rw-r--r--packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_visual.xml2
-rw-r--r--packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_setting.xml1
-rw-r--r--packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_arrow_back.xml1
-rw-r--r--packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_battery_saver_accent_24dp.xml29
-rw-r--r--packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_battery_status_bad_24dp.xml28
-rw-r--r--packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_cellular_off.xml1
-rw-r--r--packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_chevron_right_24dp.xml1
-rw-r--r--packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_content_copy_grey600_24dp.xml2
-rw-r--r--packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_data_saver.xml19
-rw-r--r--packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_devices_other.xml1
-rw-r--r--packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_eject_24dp.xml1
-rw-r--r--packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_find_in_page_24px.xml32
-rw-r--r--packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_help_actionbar.xml1
-rw-r--r--packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_network_cell.xml33
-rw-r--r--packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_notifications_off_24dp.xml1
-rw-r--r--packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_data_usage.xml7
-rw-r--r--packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_language.xml26
-rw-r--r--packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_multiuser.xml (renamed from packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_battery_status_bad_24dp.xml)5
-rw-r--r--packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_wireless_white.xml34
-rw-r--r--packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_arrow_back.xml1
-rw-r--r--packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_brightness_thumb.xml2
-rw-r--r--packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_camera.xml4
-rw-r--r--packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_data_saver.xml22
-rw-r--r--packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_data_saver_off.xml7
-rw-r--r--packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_bluetooth_connecting.xml1
-rw-r--r--packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_volume_alarm_mute.xml1
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_battery_80_24dp.xml (renamed from packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_delete_accent.xml)8
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bt_misc_hid.xml1
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_file_copy.xml2
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_lock.xml1
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_lock_open.xml1
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_lockscreen_ime.xml1
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_mode_edit.xml1
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_notifications_alerted.xml (renamed from packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_wireless_white.xml)9
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_phone.xml2
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_qs_battery_saver.xml2
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_qs_bluetooth.xml1
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_activity_recognition.xml2
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_calendar.xml1
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_call_log.xml2
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_camera.xml2
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_contacts.xml2
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_location.xml2
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_microphone.xml2
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_phone_calls.xml2
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_sensors.xml2
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_sms.xml2
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_storage.xml2
-rw-r--r--packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_visual.xml2
-rw-r--r--packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_setting.xml1
-rw-r--r--packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_arrow_back.xml1
-rw-r--r--packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_cellular_off.xml1
-rw-r--r--packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_chevron_right_24dp.xml1
-rw-r--r--packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_content_copy_grey600_24dp.xml2
-rw-r--r--packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_data_saver.xml1
-rw-r--r--packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_devices_other.xml1
-rw-r--r--packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_eject_24dp.xml1
-rw-r--r--packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_find_in_page_24px.xml27
-rw-r--r--packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_help_actionbar.xml1
-rw-r--r--packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_network_cell.xml1
-rw-r--r--packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_notifications_off_24dp.xml1
-rw-r--r--packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_language.xml26
-rw-r--r--packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_multiuser.xml29
-rw-r--r--packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_arrow_back.xml1
-rw-r--r--packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_brightness_thumb.xml2
-rw-r--r--packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_camera.xml4
-rw-r--r--packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_cast_connected.xml4
-rw-r--r--packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_data_saver.xml4
-rw-r--r--packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_bluetooth_connecting.xml1
-rw-r--r--packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_volume_alarm_mute.xml1
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_battery_80_24dp.xml (renamed from packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_battery_saver_accent_24dp.xml)3
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_file_copy.xml2
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_lock.xml1
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_lock_open.xml1
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_lockscreen_ime.xml1
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_mode_edit.xml13
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_notifications_alerted.xml (renamed from packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_delete_accent.xml)10
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_phone.xml2
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_qs_battery_saver.xml2
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_qs_bluetooth.xml1
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_activity_recognition.xml2
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_calendar.xml1
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_call_log.xml2
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_camera.xml2
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_contacts.xml2
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_location.xml2
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_microphone.xml2
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_phone_calls.xml2
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_sensors.xml2
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_sms.xml2
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_storage.xml2
-rw-r--r--packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_visual.xml2
-rw-r--r--packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_setting.xml1
-rw-r--r--packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_arrow_back.xml1
-rw-r--r--packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_cellular_off.xml1
-rw-r--r--packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_chevron_right_24dp.xml1
-rw-r--r--packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_content_copy_grey600_24dp.xml2
-rw-r--r--packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_data_saver.xml19
-rw-r--r--packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_devices_other.xml1
-rw-r--r--packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_eject_24dp.xml1
-rw-r--r--packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_find_in_page_24px.xml32
-rw-r--r--packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_help_actionbar.xml1
-rw-r--r--packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_network_cell.xml1
-rw-r--r--packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_notifications_off_24dp.xml1
-rw-r--r--packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_data_usage.xml7
-rw-r--r--packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_language.xml26
-rw-r--r--packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_multiuser.xml (renamed from packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_battery_saver_accent_24dp.xml)6
-rw-r--r--packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_wireless_white.xml34
-rw-r--r--packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_arrow_back.xml1
-rw-r--r--packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_brightness_thumb.xml2
-rw-r--r--packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_camera.xml4
-rw-r--r--packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_cast_connected.xml4
-rw-r--r--packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_data_saver.xml22
-rw-r--r--packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_data_saver_off.xml7
-rw-r--r--packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_bluetooth_connecting.xml1
-rw-r--r--packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_volume_alarm_mute.xml1
-rw-r--r--packages/overlays/NavigationBarModeGesturalOverlay/res/values/dimens.xml2
-rw-r--r--packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/Android.mk30
-rw-r--r--packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/AndroidManifest.xml27
-rw-r--r--packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/config.xml48
-rw-r--r--packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/dimens.xml28
-rw-r--r--packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/strings.xml22
-rw-r--r--packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/Android.mk30
-rw-r--r--packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/AndroidManifest.xml27
-rw-r--r--packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/config.xml48
-rw-r--r--packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/dimens.xml28
-rw-r--r--packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/strings.xml22
-rw-r--r--packages/overlays/NavigationBarModeGesturalOverlayWideBack/Android.mk30
-rw-r--r--packages/overlays/NavigationBarModeGesturalOverlayWideBack/AndroidManifest.xml27
-rw-r--r--packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/config.xml48
-rw-r--r--packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/dimens.xml28
-rw-r--r--packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/strings.xml22
-rw-r--r--proto/src/metrics_constants/metrics_constants.proto12
-rw-r--r--services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java137
-rw-r--r--services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java15
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java1
-rw-r--r--services/core/java/com/android/server/AlarmManagerService.java2
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java109
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java92
-rw-r--r--services/core/java/com/android/server/LocationUsageLogger.java265
-rw-r--r--services/core/java/com/android/server/PackageWatchdog.java58
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java16
-rw-r--r--services/core/java/com/android/server/adb/AdbDebuggingManager.java20
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java7
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java17
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceBroker.java33
-rw-r--r--services/core/java/com/android/server/audio/AudioDeviceInventory.java56
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java66
-rw-r--r--services/core/java/com/android/server/audio/BtHelper.java6
-rw-r--r--services/core/java/com/android/server/clipboard/ClipboardService.java6
-rw-r--r--services/core/java/com/android/server/connectivity/AutodestructReference.java42
-rw-r--r--services/core/java/com/android/server/connectivity/NetworkAgentInfo.java18
-rw-r--r--services/core/java/com/android/server/connectivity/NetworkNotificationManager.java12
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java41
-rw-r--r--services/core/java/com/android/server/display/DisplayPowerController.java152
-rw-r--r--services/core/java/com/android/server/display/color/ColorDisplayService.java4
-rw-r--r--services/core/java/com/android/server/job/JobSchedulerService.java33
-rw-r--r--services/core/java/com/android/server/job/controllers/JobStatus.java12
-rw-r--r--services/core/java/com/android/server/job/controllers/QuotaController.java488
-rw-r--r--services/core/java/com/android/server/location/GnssVisibilityControl.java17
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java50
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsAccess.java2
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsFactory.java4
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsRecorder.java6
-rw-r--r--services/core/java/com/android/server/net/NetworkStatsService.java70
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java30
-rw-r--r--services/core/java/com/android/server/notification/NotificationRecord.java11
-rw-r--r--services/core/java/com/android/server/notification/PreferencesHelper.java41
-rw-r--r--services/core/java/com/android/server/notification/RankingConfig.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java19
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java6
-rw-r--r--services/core/java/com/android/server/pm/ShortcutPackage.java5
-rw-r--r--services/core/java/com/android/server/pm/StagingManager.java10
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java8
-rw-r--r--services/core/java/com/android/server/power/AttentionDetector.java20
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java3
-rw-r--r--services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java60
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java15
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarShellCommand.java13
-rw-r--r--services/core/java/com/android/server/telecom/TelecomLoaderService.java23
-rw-r--r--services/core/java/com/android/server/trust/TrustManagerService.java7
-rw-r--r--services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java4
-rw-r--r--services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java8
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskManagerService.java6
-rw-r--r--services/core/java/com/android/server/wm/AppWindowToken.java18
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java4
-rw-r--r--services/core/java/com/android/server/wm/RecentsAnimation.java5
-rw-r--r--services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java7
-rw-r--r--services/core/java/com/android/server/wm/TaskSnapshotController.java40
-rw-r--r--services/java/com/android/server/SystemServer.java2
-rw-r--r--services/net/java/android/net/NetworkMonitorManager.java201
-rw-r--r--services/net/java/android/net/NetworkStackClient.java169
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java51
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java227
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java28
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java29
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java61
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java69
-rw-r--r--services/usb/java/com/android/server/usb/UsbSerialReader.java24
-rwxr-xr-xtelephony/java/android/telephony/CarrierConfigManager.java22
-rw-r--r--telephony/java/android/telephony/ServiceState.java79
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java24
-rw-r--r--telephony/java/android/telephony/emergency/EmergencyNumber.java2
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl10
-rw-r--r--tests/PackageWatchdog/Android.bp7
-rw-r--r--tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java61
-rw-r--r--tests/RollbackTest/Android.bp2
-rw-r--r--tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java29
-rw-r--r--tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java46
-rw-r--r--tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java100
-rw-r--r--tests/net/java/android/net/NetworkStatsTest.java35
-rw-r--r--tests/net/java/com/android/server/connectivity/VpnTest.java90
-rw-r--r--tests/net/java/com/android/server/net/NetworkStatsAccessTest.java2
-rw-r--r--tests/net/java/com/android/server/net/NetworkStatsServiceTest.java423
510 files changed, 14258 insertions, 4339 deletions
diff --git a/api/test-current.txt b/api/test-current.txt
index 6e1eb552fad3..309ad4d15019 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -1917,6 +1917,10 @@ package android.os {
method public boolean hasSingleFileDescriptor();
}
+ public final class Parcel {
+ method public int readExceptionCode();
+ }
+
public class ParcelFileDescriptor implements java.io.Closeable android.os.Parcelable {
method public static java.io.File getFile(java.io.FileDescriptor) throws java.io.IOException;
}
@@ -1986,6 +1990,7 @@ package android.os {
public class SystemProperties {
method @NonNull public static String get(@NonNull String);
method @NonNull public static String get(@NonNull String, @Nullable String);
+ method public static boolean getBoolean(@NonNull String, boolean);
}
public final class UserHandle implements android.os.Parcelable {
@@ -2140,6 +2145,36 @@ package android.os.health {
}
+package android.os.image {
+
+ public class DynamicSystemClient {
+ ctor public DynamicSystemClient(@NonNull android.content.Context);
+ method @RequiresPermission("android.permission.INSTALL_DYNAMIC_SYSTEM") public void bind();
+ method public void setOnStatusChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.os.image.DynamicSystemClient.OnStatusChangedListener);
+ method public void setOnStatusChangedListener(@NonNull android.os.image.DynamicSystemClient.OnStatusChangedListener);
+ method @RequiresPermission("android.permission.INSTALL_DYNAMIC_SYSTEM") public void start(@NonNull android.net.Uri, long);
+ method @RequiresPermission("android.permission.INSTALL_DYNAMIC_SYSTEM") public void start(@NonNull android.net.Uri, long, long);
+ method @RequiresPermission("android.permission.INSTALL_DYNAMIC_SYSTEM") public void unbind();
+ field public static final int CAUSE_ERROR_EXCEPTION = 6; // 0x6
+ field public static final int CAUSE_ERROR_INVALID_URL = 4; // 0x4
+ field public static final int CAUSE_ERROR_IO = 3; // 0x3
+ field public static final int CAUSE_ERROR_IPC = 5; // 0x5
+ field public static final int CAUSE_INSTALL_CANCELLED = 2; // 0x2
+ field public static final int CAUSE_INSTALL_COMPLETED = 1; // 0x1
+ field public static final int CAUSE_NOT_SPECIFIED = 0; // 0x0
+ field public static final int STATUS_IN_PROGRESS = 2; // 0x2
+ field public static final int STATUS_IN_USE = 4; // 0x4
+ field public static final int STATUS_NOT_STARTED = 1; // 0x1
+ field public static final int STATUS_READY = 3; // 0x3
+ field public static final int STATUS_UNKNOWN = 0; // 0x0
+ }
+
+ public static interface DynamicSystemClient.OnStatusChangedListener {
+ method public void onStatusChanged(int, int, long, @Nullable Throwable);
+ }
+
+}
+
package android.os.storage {
public class StorageManager {
@@ -2946,6 +2981,21 @@ package android.util {
method public E valueAtUnchecked(int);
}
+ public class FeatureFlagUtils {
+ ctor public FeatureFlagUtils();
+ method public static java.util.Map<java.lang.String,java.lang.String> getAllFeatureFlags();
+ method public static boolean isEnabled(android.content.Context, String);
+ method public static void setEnabled(android.content.Context, String, boolean);
+ field public static final String DYNAMIC_SYSTEM = "settings_dynamic_system";
+ field public static final String FFLAG_OVERRIDE_PREFIX = "sys.fflag.override.";
+ field public static final String FFLAG_PREFIX = "sys.fflag.";
+ field public static final String HEARING_AID_SETTINGS = "settings_bluetooth_hearing_aid";
+ field public static final String PERSIST_PREFIX = "persist.sys.fflag.override.";
+ field public static final String PIXEL_WALLPAPER_CATEGORY_SWITCH = "settings_pixel_wallpaper_category_switch";
+ field public static final String SCREENRECORD_LONG_PRESS = "settings_screenrecord_long_press";
+ field public static final String SEAMLESS_TRANSFER = "settings_seamless_transfer";
+ }
+
public class TimeUtils {
method public static String formatDuration(long);
}
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 16af0719d9dd..30f4ad4c5c69 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -69,6 +69,7 @@ static const char OEM_BOOTANIMATION_FILE[] = "/oem/media/bootanimation.zip";
static const char PRODUCT_BOOTANIMATION_DARK_FILE[] = "/product/media/bootanimation-dark.zip";
static const char PRODUCT_BOOTANIMATION_FILE[] = "/product/media/bootanimation.zip";
static const char SYSTEM_BOOTANIMATION_FILE[] = "/system/media/bootanimation.zip";
+static const char APEX_BOOTANIMATION_FILE[] = "/apex/com.android.bootanimation/etc/bootanimation.zip";
static const char PRODUCT_ENCRYPTED_BOOTANIMATION_FILE[] = "/product/media/bootanimation-encrypted.zip";
static const char SYSTEM_ENCRYPTED_BOOTANIMATION_FILE[] = "/system/media/bootanimation-encrypted.zip";
static const char OEM_SHUTDOWNANIMATION_FILE[] = "/oem/media/shutdownanimation.zip";
@@ -358,10 +359,10 @@ void BootAnimation::findBootAnimationFile() {
const bool playDarkAnim = android::base::GetIntProperty("ro.boot.theme", 0) == 1;
static const char* bootFiles[] =
- {playDarkAnim ? PRODUCT_BOOTANIMATION_DARK_FILE : PRODUCT_BOOTANIMATION_FILE,
+ {APEX_BOOTANIMATION_FILE, playDarkAnim ? PRODUCT_BOOTANIMATION_DARK_FILE : PRODUCT_BOOTANIMATION_FILE,
OEM_BOOTANIMATION_FILE, SYSTEM_BOOTANIMATION_FILE};
static const char* shutdownFiles[] =
- {PRODUCT_SHUTDOWNANIMATION_FILE, OEM_SHUTDOWNANIMATION_FILE, SYSTEM_SHUTDOWNANIMATION_FILE};
+ {PRODUCT_SHUTDOWNANIMATION_FILE, OEM_SHUTDOWNANIMATION_FILE, SYSTEM_SHUTDOWNANIMATION_FILE, ""};
for (const char* f : (!mShuttingDown ? bootFiles : shutdownFiles)) {
if (access(f, R_OK) == 0) {
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 2899d49cf179..495a09f2e99a 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -48,6 +48,7 @@ import "frameworks/base/core/proto/android/stats/docsui/docsui_enums.proto";
import "frameworks/base/core/proto/android/stats/enums.proto";
import "frameworks/base/core/proto/android/stats/intelligence/enums.proto";
import "frameworks/base/core/proto/android/stats/launcher/launcher.proto";
+import "frameworks/base/core/proto/android/stats/location/location_enums.proto";
import "frameworks/base/core/proto/android/stats/mediametrics/mediametrics.proto";
import "frameworks/base/core/proto/android/stats/storage/storage_enums.proto";
import "frameworks/base/core/proto/android/stats/style/style_enums.proto";
@@ -301,6 +302,7 @@ message Atom {
ContentCaptureServiceEvents content_capture_service_events = 207;
ContentCaptureSessionEvents content_capture_session_events = 208;
ContentCaptureFlushed content_capture_flushed = 209;
+ LocationManagerApiUsageReported location_manager_api_usage_reported = 210;
}
// Pulled events will start at field 10000.
@@ -6485,3 +6487,60 @@ message AppOps {
// while the app was in the background (only for trusted requests)
optional int64 trusted_background_duration_millis = 9;
}
+
+/**
+ * Location Manager API Usage information(e.g. API under usage,
+ * API call's parameters).
+ * Logged from:
+ * frameworks/base/services/core/java/com/android/server/LocationManagerService.java
+ */
+message LocationManagerApiUsageReported {
+
+ // Indicating if usage starts or usage ends.
+ optional android.stats.location.UsageState state = 1;
+
+ // LocationManagerService's API in use.
+ // We can identify which API from LocationManager is
+ // invoking current LMS API by the combination of
+ // API parameter(e.g. is_listener_null, is_intent_null,
+ // is_location_request_null)
+ optional android.stats.location.LocationManagerServiceApi api_in_use = 2;
+
+ // Name of the package calling the API.
+ optional string calling_package_name = 3;
+
+ // Type of the location provider.
+ optional android.stats.location.ProviderType provider = 4;
+
+ // Quality of the location request
+ optional android.stats.location.LocationRequestQuality quality = 5;
+
+ // The desired interval for active location updates, in milliseconds.
+ // Bucketized to reduce cardinality.
+ optional android.stats.location.LocationRequestIntervalBucket bucketized_interval = 6;
+
+ // Minimum distance between location updates, in meters.
+ // Bucketized to reduce cardinality.
+ optional android.stats.location.SmallestDisplacementBucket
+ bucketized_smallest_displacement = 7;
+
+ // The number of location updates.
+ optional int64 num_updates = 8;
+
+ // The request expiration time, in millisecond since boot.
+ // Bucketized to reduce cardinality.
+ optional android.stats.location.ExpirationBucket
+ bucketized_expire_in = 9;
+
+ // Type of Callback passed in for this API.
+ optional android.stats.location.CallbackType callback_type = 10;
+
+ // The radius of the central point of the alert
+ // region, in meters. Only for API REQUEST_GEOFENCE.
+ // Bucketized to reduce cardinality.
+ optional android.stats.location.GeofenceRadiusBucket bucketized_radius = 11;
+
+ // Activity Importance of API caller.
+ // Categorized to 3 types that are interesting from location's perspective.
+ optional android.stats.location.ActivityImportance activiy_importance = 12;
+}
diff --git a/cmds/statsd/src/external/PowerStatsPuller.cpp b/cmds/statsd/src/external/PowerStatsPuller.cpp
index c56f9a27086e..b142caca3acc 100644
--- a/cmds/statsd/src/external/PowerStatsPuller.cpp
+++ b/cmds/statsd/src/external/PowerStatsPuller.cpp
@@ -85,7 +85,6 @@ bool PowerStatsPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
std::lock_guard<std::mutex> lock(gPowerStatsHalMutex);
if (!getPowerStatsHalLocked()) {
- ALOGE("power.stats Hal not loaded");
return false;
}
@@ -116,6 +115,7 @@ bool PowerStatsPuller::PullInternal(vector<shared_ptr<LogEvent>>* data) {
if (gRailInfo.empty()) {
ALOGE("power.stats has no rail information");
gPowerStatsExist = false; // No rail info, so never try again.
+ gPowerStatsHal = nullptr;
return false;
}
}
diff --git a/config/hiddenapi-greylist-packages.txt b/config/hiddenapi-greylist-packages.txt
index cae3bd94bc67..986d2591a007 100644
--- a/config/hiddenapi-greylist-packages.txt
+++ b/config/hiddenapi-greylist-packages.txt
@@ -1,2 +1,43 @@
+gov.nist.core
+gov.nist.core.net
+gov.nist.javax.sip
+gov.nist.javax.sip.address
+gov.nist.javax.sip.clientauthutils
+gov.nist.javax.sip.header
+gov.nist.javax.sip.header.extensions
+gov.nist.javax.sip.header.ims
+gov.nist.javax.sip.message
+gov.nist.javax.sip.parser
+gov.nist.javax.sip.parser.extensions
+gov.nist.javax.sip.parser.ims
+gov.nist.javax.sip.stack
+org.apache.xalan
+org.apache.xalan.extensions
+org.apache.xalan.processor
+org.apache.xalan.res
+org.apache.xalan.serialize
+org.apache.xalan.templates
+org.apache.xalan.transformer
+org.apache.xalan.xslt
+org.apache.xml.dtm
+org.apache.xml.dtm.ref
+org.apache.xml.dtm.ref.dom2dtm
+org.apache.xml.dtm.ref.sax2dtm
+org.apache.xml.res
+org.apache.xml.serializer
+org.apache.xml.serializer.dom3
+org.apache.xml.serializer.utils
+org.apache.xml.utils
+org.apache.xml.utils.res
+org.apache.xpath
+org.apache.xpath.axes
+org.apache.xpath.compiler
+org.apache.xpath.domapi
+org.apache.xpath.functions
+org.apache.xpath.jaxp
+org.apache.xpath.objects
+org.apache.xpath.operations
+org.apache.xpath.patterns
+org.apache.xpath.res
org.ccil.cowan.tagsoup
org.ccil.cowan.tagsoup.jaxp
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index 82d0fbe32993..10f25ea1c8d1 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -1774,715 +1774,3 @@ Lcom/google/android/mms/util/SqliteWrapper;->query(Landroid/content/Context;Land
Lcom/google/android/mms/util/SqliteWrapper;->requery(Landroid/content/Context;Landroid/database/Cursor;)Z
Lcom/google/android/mms/util/SqliteWrapper;->update(Landroid/content/Context;Landroid/content/ContentResolver;Landroid/net/Uri;Landroid/content/ContentValues;Ljava/lang/String;[Ljava/lang/String;)I
Lcom/google/android/util/AbstractMessageParser$Token$Type;->values()[Lcom/google/android/util/AbstractMessageParser$Token$Type;
-Lgov/nist/core/Debug;->printStackTrace(Ljava/lang/Exception;)V
-Lgov/nist/core/GenericObject;-><init>()V
-Lgov/nist/core/GenericObject;->dbgPrint()V
-Lgov/nist/core/GenericObject;->debugDump(I)Ljava/lang/String;
-Lgov/nist/core/GenericObject;->encode()Ljava/lang/String;
-Lgov/nist/core/GenericObject;->getMatcher()Lgov/nist/core/Match;
-Lgov/nist/core/GenericObject;->indentation:I
-Lgov/nist/core/GenericObject;->isMySubclass(Ljava/lang/Class;)Z
-Lgov/nist/core/GenericObject;->match(Ljava/lang/Object;)Z
-Lgov/nist/core/GenericObject;->matchExpression:Lgov/nist/core/Match;
-Lgov/nist/core/GenericObject;->merge(Ljava/lang/Object;)V
-Lgov/nist/core/GenericObject;->sprint(Ljava/lang/String;)V
-Lgov/nist/core/GenericObject;->stringRepresentation:Ljava/lang/String;
-Lgov/nist/core/GenericObjectList;-><init>()V
-Lgov/nist/core/GenericObjectList;-><init>(Ljava/lang/String;)V
-Lgov/nist/core/GenericObjectList;-><init>(Ljava/lang/String;Ljava/lang/Class;)V
-Lgov/nist/core/GenericObjectList;-><init>(Ljava/lang/String;Ljava/lang/String;)V
-Lgov/nist/core/GenericObjectList;->concatenate(Lgov/nist/core/GenericObjectList;)V
-Lgov/nist/core/GenericObjectList;->concatenate(Lgov/nist/core/GenericObjectList;Z)V
-Lgov/nist/core/GenericObjectList;->debugDump(I)Ljava/lang/String;
-Lgov/nist/core/GenericObjectList;->first()Lgov/nist/core/GenericObject;
-Lgov/nist/core/GenericObjectList;->getIndentation()Ljava/lang/String;
-Lgov/nist/core/GenericObjectList;->indentation:I
-Lgov/nist/core/GenericObjectList;->isMySubclass(Ljava/lang/Class;)Z
-Lgov/nist/core/GenericObjectList;->match(Ljava/lang/Object;)Z
-Lgov/nist/core/GenericObjectList;->myClass:Ljava/lang/Class;
-Lgov/nist/core/GenericObjectList;->next()Lgov/nist/core/GenericObject;
-Lgov/nist/core/GenericObjectList;->next(Ljava/util/ListIterator;)Lgov/nist/core/GenericObject;
-Lgov/nist/core/GenericObjectList;->setMyClass(Ljava/lang/Class;)V
-Lgov/nist/core/GenericObjectList;->stringRep:Ljava/lang/String;
-Lgov/nist/core/Host;-><init>()V
-Lgov/nist/core/Host;-><init>(Ljava/lang/String;)V
-Lgov/nist/core/Host;->encode()Ljava/lang/String;
-Lgov/nist/core/Host;->getAddress()Ljava/lang/String;
-Lgov/nist/core/Host;->getHostname()Ljava/lang/String;
-Lgov/nist/core/Host;->isIPv6Reference(Ljava/lang/String;)Z
-Lgov/nist/core/Host;->setAddress(Ljava/lang/String;)V
-Lgov/nist/core/Host;->setHostname(Ljava/lang/String;)V
-Lgov/nist/core/HostNameParser;-><init>(Lgov/nist/core/LexerCore;)V
-Lgov/nist/core/HostNameParser;-><init>(Ljava/lang/String;)V
-Lgov/nist/core/HostNameParser;->host()Lgov/nist/core/Host;
-Lgov/nist/core/HostNameParser;->hostPort(Z)Lgov/nist/core/HostPort;
-Lgov/nist/core/HostPort;-><init>()V
-Lgov/nist/core/HostPort;->encode()Ljava/lang/String;
-Lgov/nist/core/HostPort;->encode(Ljava/lang/StringBuffer;)Ljava/lang/StringBuffer;
-Lgov/nist/core/HostPort;->getHost()Lgov/nist/core/Host;
-Lgov/nist/core/HostPort;->getInetAddress()Ljava/net/InetAddress;
-Lgov/nist/core/HostPort;->getPort()I
-Lgov/nist/core/HostPort;->hasPort()Z
-Lgov/nist/core/HostPort;->removePort()V
-Lgov/nist/core/HostPort;->setHost(Lgov/nist/core/Host;)V
-Lgov/nist/core/HostPort;->setPort(I)V
-Lgov/nist/core/InternalErrorHandler;->handleException(Ljava/lang/Exception;)V
-Lgov/nist/core/InternalErrorHandler;->handleException(Ljava/lang/String;)V
-Lgov/nist/core/LexerCore;-><init>(Ljava/lang/String;Ljava/lang/String;)V
-Lgov/nist/core/LexerCore;->byteStringNoSemicolon()Ljava/lang/String;
-Lgov/nist/core/LexerCore;->byteStringNoSlash()Ljava/lang/String;
-Lgov/nist/core/LexerCore;->charAsString(I)Ljava/lang/String;
-Lgov/nist/core/LexerCore;->comment()Ljava/lang/String;
-Lgov/nist/core/LexerCore;->createParseException()Ljava/text/ParseException;
-Lgov/nist/core/LexerCore;->currentLexer:Ljava/util/Hashtable;
-Lgov/nist/core/LexerCore;->getBuffer()Ljava/lang/String;
-Lgov/nist/core/LexerCore;->getNextId()Ljava/lang/String;
-Lgov/nist/core/LexerCore;->getNextToken()Lgov/nist/core/Token;
-Lgov/nist/core/LexerCore;->getPtr()I
-Lgov/nist/core/LexerCore;->getRest()Ljava/lang/String;
-Lgov/nist/core/LexerCore;->getString(C)Ljava/lang/String;
-Lgov/nist/core/LexerCore;->isTokenChar(C)Z
-Lgov/nist/core/LexerCore;->lexerTables:Ljava/util/Hashtable;
-Lgov/nist/core/LexerCore;->markInputPosition()I
-Lgov/nist/core/LexerCore;->match(I)Lgov/nist/core/Token;
-Lgov/nist/core/LexerCore;->number()Ljava/lang/String;
-Lgov/nist/core/LexerCore;->peekNextToken()Lgov/nist/core/Token;
-Lgov/nist/core/LexerCore;->peekNextToken(I)[Lgov/nist/core/Token;
-Lgov/nist/core/LexerCore;->quotedString()Ljava/lang/String;
-Lgov/nist/core/LexerCore;->rewindInputPosition(I)V
-Lgov/nist/core/LexerCore;->selectLexer(Ljava/lang/String;)V
-Lgov/nist/core/LexerCore;->SPorHT()V
-Lgov/nist/core/LexerCore;->startsId()Z
-Lgov/nist/core/LexerCore;->ttoken()Ljava/lang/String;
-Lgov/nist/core/LexerCore;->ttokenSafe()Ljava/lang/String;
-Lgov/nist/core/Match;->match(Ljava/lang/String;)Z
-Lgov/nist/core/NameValue;-><init>()V
-Lgov/nist/core/NameValue;-><init>(Ljava/lang/String;Ljava/lang/Object;)V
-Lgov/nist/core/NameValue;-><init>(Ljava/lang/String;Ljava/lang/Object;Z)V
-Lgov/nist/core/NameValue;->encode()Ljava/lang/String;
-Lgov/nist/core/NameValue;->encode(Ljava/lang/StringBuffer;)Ljava/lang/StringBuffer;
-Lgov/nist/core/NameValue;->getName()Ljava/lang/String;
-Lgov/nist/core/NameValue;->getValueAsObject()Ljava/lang/Object;
-Lgov/nist/core/NameValue;->setName(Ljava/lang/String;)V
-Lgov/nist/core/NameValue;->setQuotedValue()V
-Lgov/nist/core/NameValue;->setSeparator(Ljava/lang/String;)V
-Lgov/nist/core/NameValue;->setValueAsObject(Ljava/lang/Object;)V
-Lgov/nist/core/NameValueList;-><init>()V
-Lgov/nist/core/NameValueList;-><init>(Z)V
-Lgov/nist/core/NameValueList;->delete(Ljava/lang/String;)Z
-Lgov/nist/core/NameValueList;->encode()Ljava/lang/String;
-Lgov/nist/core/NameValueList;->encode(Ljava/lang/StringBuffer;)Ljava/lang/StringBuffer;
-Lgov/nist/core/NameValueList;->getNames()Ljava/util/Iterator;
-Lgov/nist/core/NameValueList;->getNameValue(Ljava/lang/String;)Lgov/nist/core/NameValue;
-Lgov/nist/core/NameValueList;->getParameter(Ljava/lang/String;)Ljava/lang/String;
-Lgov/nist/core/NameValueList;->getValue(Ljava/lang/String;)Ljava/lang/Object;
-Lgov/nist/core/NameValueList;->hasNameValue(Ljava/lang/String;)Z
-Lgov/nist/core/NameValueList;->iterator()Ljava/util/Iterator;
-Lgov/nist/core/NameValueList;->set(Lgov/nist/core/NameValue;)V
-Lgov/nist/core/NameValueList;->set(Ljava/lang/String;Ljava/lang/Object;)V
-Lgov/nist/core/NameValueList;->setSeparator(Ljava/lang/String;)V
-Lgov/nist/core/net/DefaultNetworkLayer;->SINGLETON:Lgov/nist/core/net/DefaultNetworkLayer;
-Lgov/nist/core/net/NetworkLayer;->createDatagramSocket()Ljava/net/DatagramSocket;
-Lgov/nist/core/net/NetworkLayer;->createDatagramSocket(ILjava/net/InetAddress;)Ljava/net/DatagramSocket;
-Lgov/nist/core/net/NetworkLayer;->createServerSocket(IILjava/net/InetAddress;)Ljava/net/ServerSocket;
-Lgov/nist/core/net/NetworkLayer;->createSocket(Ljava/net/InetAddress;I)Ljava/net/Socket;
-Lgov/nist/core/net/NetworkLayer;->createSSLServerSocket(IILjava/net/InetAddress;)Ljavax/net/ssl/SSLServerSocket;
-Lgov/nist/core/net/NetworkLayer;->createSSLSocket(Ljava/net/InetAddress;I)Ljavax/net/ssl/SSLSocket;
-Lgov/nist/core/ParserCore;-><init>()V
-Lgov/nist/core/ParserCore;->lexer:Lgov/nist/core/LexerCore;
-Lgov/nist/core/StringTokenizer;->ptr:I
-Lgov/nist/core/ThreadAuditor$ThreadHandle;->getPingIntervalInMillisecs()J
-Lgov/nist/core/ThreadAuditor$ThreadHandle;->ping()V
-Lgov/nist/core/ThreadAuditor;-><init>()V
-Lgov/nist/core/ThreadAuditor;->addCurrentThread()Lgov/nist/core/ThreadAuditor$ThreadHandle;
-Lgov/nist/core/ThreadAuditor;->getPingIntervalInMillisecs()J
-Lgov/nist/core/ThreadAuditor;->isEnabled()Z
-Lgov/nist/core/ThreadAuditor;->setPingIntervalInMillisecs(J)V
-Lgov/nist/core/Token;-><init>()V
-Lgov/nist/core/Token;->getTokenType()I
-Lgov/nist/core/Token;->getTokenValue()Ljava/lang/String;
-Lgov/nist/javax/sip/address/GenericURI;-><init>()V
-Lgov/nist/javax/sip/address/GenericURI;->encode()Ljava/lang/String;
-Lgov/nist/javax/sip/address/GenericURI;->getScheme()Ljava/lang/String;
-Lgov/nist/javax/sip/address/SipUri;->getHost()Ljava/lang/String;
-Lgov/nist/javax/sip/address/SipUri;->getParameter(Ljava/lang/String;)Ljava/lang/String;
-Lgov/nist/javax/sip/address/SipUri;->getPort()I
-Lgov/nist/javax/sip/address/SipUri;->getUser()Ljava/lang/String;
-Lgov/nist/javax/sip/address/SipUri;->removeParameter(Ljava/lang/String;)V
-Lgov/nist/javax/sip/address/SipUri;->setParameter(Ljava/lang/String;Ljava/lang/String;)V
-Lgov/nist/javax/sip/address/SipUri;->setUserParam(Ljava/lang/String;)V
-Lgov/nist/javax/sip/parser/URLParser;-><init>(Ljava/lang/String;)V
-Lgov/nist/javax/sip/parser/URLParser;->sipURL(Z)Lgov/nist/javax/sip/address/SipUri;
-Lorg/apache/xalan/extensions/ExpressionContext;->getContextNode()Lorg/w3c/dom/Node;
-Lorg/apache/xalan/extensions/ExpressionContext;->getErrorListener()Ljavax/xml/transform/ErrorListener;
-Lorg/apache/xalan/extensions/ExpressionContext;->getVariableOrParam(Lorg/apache/xml/utils/QName;)Lorg/apache/xpath/objects/XObject;
-Lorg/apache/xalan/extensions/ExpressionContext;->getXPathContext()Lorg/apache/xpath/XPathContext;
-Lorg/apache/xalan/extensions/ExtensionHandler;-><init>(Ljava/lang/String;Ljava/lang/String;)V
-Lorg/apache/xalan/extensions/ExtensionHandler;->callFunction(Ljava/lang/String;Ljava/util/Vector;Ljava/lang/Object;Lorg/apache/xalan/extensions/ExpressionContext;)Ljava/lang/Object;
-Lorg/apache/xalan/extensions/ExtensionHandler;->getClassForName(Ljava/lang/String;)Ljava/lang/Class;
-Lorg/apache/xalan/extensions/ObjectFactory$ConfigurationError;-><init>(Ljava/lang/String;Ljava/lang/Exception;)V
-Lorg/apache/xalan/extensions/ObjectFactory;->findClassLoader()Ljava/lang/ClassLoader;
-Lorg/apache/xalan/extensions/ObjectFactory;->findProviderClass(Ljava/lang/String;Ljava/lang/ClassLoader;Z)Ljava/lang/Class;
-Lorg/apache/xalan/processor/TransformerFactoryImpl;-><init>()V
-Lorg/apache/xalan/res/XSLMessages;->createMessage(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
-Lorg/apache/xalan/res/XSLTErrorResources;-><init>()V
-Lorg/apache/xalan/serialize/SerializerUtils;->outputResultTreeFragment(Lorg/apache/xml/serializer/SerializationHandler;Lorg/apache/xpath/objects/XObject;Lorg/apache/xpath/XPathContext;)V
-Lorg/apache/xalan/templates/AVT;->evaluate(Lorg/apache/xpath/XPathContext;ILorg/apache/xml/utils/PrefixResolver;)Ljava/lang/String;
-Lorg/apache/xalan/templates/ElemElement;->execute(Lorg/apache/xalan/transformer/TransformerImpl;)V
-Lorg/apache/xalan/templates/ElemExsltFunction;->execute(Lorg/apache/xalan/transformer/TransformerImpl;[Lorg/apache/xpath/objects/XObject;)V
-Lorg/apache/xalan/templates/ElemExtensionCall;->getAttribute(Ljava/lang/String;Lorg/w3c/dom/Node;Lorg/apache/xalan/transformer/TransformerImpl;)Ljava/lang/String;
-Lorg/apache/xalan/templates/ElemLiteralResult;->getLiteralResultAttribute(Ljava/lang/String;)Lorg/apache/xalan/templates/AVT;
-Lorg/apache/xalan/templates/ElemTemplate;->getMatch()Lorg/apache/xpath/XPath;
-Lorg/apache/xalan/templates/ElemTemplate;->getName()Lorg/apache/xml/utils/QName;
-Lorg/apache/xalan/templates/ElemTemplateElement;->getFirstChildElem()Lorg/apache/xalan/templates/ElemTemplateElement;
-Lorg/apache/xalan/templates/ElemTemplateElement;->getNextSiblingElem()Lorg/apache/xalan/templates/ElemTemplateElement;
-Lorg/apache/xalan/templates/ElemTemplateElement;->getParentElem()Lorg/apache/xalan/templates/ElemTemplateElement;
-Lorg/apache/xalan/templates/ElemTemplateElement;->getStylesheetRoot()Lorg/apache/xalan/templates/StylesheetRoot;
-Lorg/apache/xalan/templates/ElemTemplateElement;->getXSLToken()I
-Lorg/apache/xalan/templates/ElemTextLiteral;->getChars()[C
-Lorg/apache/xalan/templates/KeyDeclaration;->getName()Lorg/apache/xml/utils/QName;
-Lorg/apache/xalan/templates/KeyDeclaration;->getUse()Lorg/apache/xpath/XPath;
-Lorg/apache/xalan/templates/StylesheetRoot;->getDefaultRootRule()Lorg/apache/xalan/templates/ElemTemplate;
-Lorg/apache/xalan/templates/StylesheetRoot;->getDefaultRule()Lorg/apache/xalan/templates/ElemTemplate;
-Lorg/apache/xalan/templates/StylesheetRoot;->getDefaultTextRule()Lorg/apache/xalan/templates/ElemTemplate;
-Lorg/apache/xalan/templates/StylesheetRoot;->getTemplateComposed(Lorg/apache/xml/utils/QName;)Lorg/apache/xalan/templates/ElemTemplate;
-Lorg/apache/xalan/transformer/ClonerToResultTree;->cloneToResultTree(IILorg/apache/xml/dtm/DTM;Lorg/apache/xml/serializer/SerializationHandler;Z)V
-Lorg/apache/xalan/transformer/DecimalToRoman;-><init>(JLjava/lang/String;JLjava/lang/String;)V
-Lorg/apache/xalan/transformer/DecimalToRoman;->m_postLetter:Ljava/lang/String;
-Lorg/apache/xalan/transformer/DecimalToRoman;->m_postValue:J
-Lorg/apache/xalan/transformer/DecimalToRoman;->m_preLetter:Ljava/lang/String;
-Lorg/apache/xalan/transformer/DecimalToRoman;->m_preValue:J
-Lorg/apache/xalan/transformer/MsgMgr;->error(Ljavax/xml/transform/SourceLocator;Lorg/w3c/dom/Node;Lorg/w3c/dom/Node;Ljava/lang/String;)V
-Lorg/apache/xalan/transformer/TransformerImpl;->createSerializationHandler(Ljavax/xml/transform/Result;Lorg/apache/xalan/templates/OutputProperties;)Lorg/apache/xml/serializer/SerializationHandler;
-Lorg/apache/xalan/transformer/TransformerImpl;->executeChildTemplates(Lorg/apache/xalan/templates/ElemTemplateElement;Lorg/w3c/dom/Node;Lorg/apache/xml/utils/QName;Lorg/xml/sax/ContentHandler;)V
-Lorg/apache/xalan/transformer/TransformerImpl;->executeChildTemplates(Lorg/apache/xalan/templates/ElemTemplateElement;Z)V
-Lorg/apache/xalan/transformer/TransformerImpl;->getCountersTable()Lorg/apache/xalan/transformer/CountersTable;
-Lorg/apache/xalan/transformer/TransformerImpl;->getCurrentTemplateElements()Lorg/apache/xml/utils/ObjectStack;
-Lorg/apache/xalan/transformer/TransformerImpl;->getCurrentTemplateElementsCount()I
-Lorg/apache/xalan/transformer/TransformerImpl;->getMatchedNode()I
-Lorg/apache/xalan/transformer/TransformerImpl;->getMatchedTemplate()Lorg/apache/xalan/templates/ElemTemplate;
-Lorg/apache/xalan/transformer/TransformerImpl;->getMode()Lorg/apache/xml/utils/QName;
-Lorg/apache/xalan/transformer/TransformerImpl;->getMsgMgr()Lorg/apache/xalan/transformer/MsgMgr;
-Lorg/apache/xalan/transformer/TransformerImpl;->getOutputFormat()Lorg/apache/xalan/templates/OutputProperties;
-Lorg/apache/xalan/transformer/TransformerImpl;->getResultTreeHandler()Lorg/apache/xml/serializer/SerializationHandler;
-Lorg/apache/xalan/transformer/TransformerImpl;->getSerializationHandler()Lorg/apache/xml/serializer/SerializationHandler;
-Lorg/apache/xalan/transformer/TransformerImpl;->getXPathContext()Lorg/apache/xpath/XPathContext;
-Lorg/apache/xalan/transformer/TransformerImpl;->m_attrSetStack:Ljava/util/Stack;
-Lorg/apache/xalan/transformer/TransformerImpl;->m_currentMatchedNodes:Lorg/apache/xml/utils/NodeVector;
-Lorg/apache/xalan/transformer/TransformerImpl;->m_currentMatchTemplates:Ljava/util/Stack;
-Lorg/apache/xalan/transformer/TransformerImpl;->m_currentTemplateElements:Lorg/apache/xml/utils/ObjectStack;
-Lorg/apache/xalan/transformer/TransformerImpl;->m_currentTemplateRuleIsNull:Lorg/apache/xml/utils/BoolStack;
-Lorg/apache/xalan/transformer/TransformerImpl;->m_inputContentHandler:Lorg/xml/sax/ContentHandler;
-Lorg/apache/xalan/transformer/TransformerImpl;->m_outputTarget:Ljavax/xml/transform/Result;
-Lorg/apache/xalan/transformer/TransformerImpl;->m_stringWriterObjectPool:Lorg/apache/xml/utils/ObjectPool;
-Lorg/apache/xalan/transformer/TransformerImpl;->m_urlOfSource:Ljava/lang/String;
-Lorg/apache/xalan/transformer/TransformerImpl;->m_xcontext:Lorg/apache/xpath/XPathContext;
-Lorg/apache/xalan/transformer/TransformerImpl;->popCurrentFuncResult()Ljava/lang/Object;
-Lorg/apache/xalan/transformer/TransformerImpl;->pushCurrentFuncResult(Ljava/lang/Object;)V
-Lorg/apache/xalan/transformer/TransformerImpl;->pushElemTemplateElement(Lorg/apache/xalan/templates/ElemTemplateElement;)V
-Lorg/apache/xalan/Version;->getVersion()Ljava/lang/String;
-Lorg/apache/xalan/xslt/EnvironmentCheck;-><init>()V
-Lorg/apache/xalan/xslt/EnvironmentCheck;->appendEnvironmentReport(Lorg/w3c/dom/Node;Lorg/w3c/dom/Document;Ljava/util/Hashtable;)V
-Lorg/apache/xalan/xslt/EnvironmentCheck;->getEnvironmentHash()Ljava/util/Hashtable;
-Lorg/apache/xalan/xslt/ObjectFactory;->findClassLoader()Ljava/lang/ClassLoader;
-Lorg/apache/xalan/xslt/ObjectFactory;->newInstance(Ljava/lang/String;Ljava/lang/ClassLoader;Z)Ljava/lang/Object;
-Lorg/apache/xml/dtm/Axis;->getNames(I)Ljava/lang/String;
-Lorg/apache/xml/dtm/Axis;->isReverse(I)Z
-Lorg/apache/xml/dtm/DTM;->getDocument()I
-Lorg/apache/xml/dtm/DTM;->getDocumentRoot(I)I
-Lorg/apache/xml/dtm/DTM;->getFirstChild(I)I
-Lorg/apache/xml/dtm/DTM;->getNextSibling(I)I
-Lorg/apache/xml/dtm/DTM;->getNode(I)Lorg/w3c/dom/Node;
-Lorg/apache/xml/dtm/DTM;->getNodeName(I)Ljava/lang/String;
-Lorg/apache/xml/dtm/DTM;->getNodeType(I)S
-Lorg/apache/xml/dtm/DTM;->getParent(I)I
-Lorg/apache/xml/dtm/DTM;->getSourceLocatorFor(I)Ljavax/xml/transform/SourceLocator;
-Lorg/apache/xml/dtm/DTM;->getStringValue(I)Lorg/apache/xml/utils/XMLString;
-Lorg/apache/xml/dtm/DTM;->migrateTo(Lorg/apache/xml/dtm/DTMManager;)V
-Lorg/apache/xml/dtm/DTMAxisIterator;->cloneIterator()Lorg/apache/xml/dtm/DTMAxisIterator;
-Lorg/apache/xml/dtm/DTMAxisIterator;->getLast()I
-Lorg/apache/xml/dtm/DTMAxisIterator;->getNodeByPosition(I)I
-Lorg/apache/xml/dtm/DTMAxisIterator;->getPosition()I
-Lorg/apache/xml/dtm/DTMAxisIterator;->gotoMark()V
-Lorg/apache/xml/dtm/DTMAxisIterator;->isReverse()Z
-Lorg/apache/xml/dtm/DTMAxisIterator;->next()I
-Lorg/apache/xml/dtm/DTMAxisIterator;->reset()Lorg/apache/xml/dtm/DTMAxisIterator;
-Lorg/apache/xml/dtm/DTMAxisIterator;->setMark()V
-Lorg/apache/xml/dtm/DTMAxisIterator;->setRestartable(Z)V
-Lorg/apache/xml/dtm/DTMAxisIterator;->setStartNode(I)Lorg/apache/xml/dtm/DTMAxisIterator;
-Lorg/apache/xml/dtm/DTMException;-><init>(Ljava/lang/String;)V
-Lorg/apache/xml/dtm/DTMFilter;->acceptNode(II)S
-Lorg/apache/xml/dtm/DTMIterator;->cloneWithReset()Lorg/apache/xml/dtm/DTMIterator;
-Lorg/apache/xml/dtm/DTMIterator;->getCurrentPos()I
-Lorg/apache/xml/dtm/DTMIterator;->getDTM(I)Lorg/apache/xml/dtm/DTM;
-Lorg/apache/xml/dtm/DTMIterator;->nextNode()I
-Lorg/apache/xml/dtm/DTMIterator;->runTo(I)V
-Lorg/apache/xml/dtm/DTMIterator;->setCurrentPos(I)V
-Lorg/apache/xml/dtm/DTMIterator;->setRoot(ILjava/lang/Object;)V
-Lorg/apache/xml/dtm/DTMIterator;->setShouldCacheNodes(Z)V
-Lorg/apache/xml/dtm/DTMManager;->getDTM(Ljavax/xml/transform/Source;ZLorg/apache/xml/dtm/DTMWSFilter;ZZ)Lorg/apache/xml/dtm/DTM;
-Lorg/apache/xml/dtm/DTMManager;->getXMLStringFactory()Lorg/apache/xml/utils/XMLStringFactory;
-Lorg/apache/xml/dtm/DTMManager;->release(Lorg/apache/xml/dtm/DTM;Z)Z
-Lorg/apache/xml/dtm/ref/CoroutineManager;-><init>()V
-Lorg/apache/xml/dtm/ref/CoroutineManager;->co_joinCoroutineSet(I)I
-Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;-><init>()V
-Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->includeSelf()Lorg/apache/xml/dtm/DTMAxisIterator;
-Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->reset()Lorg/apache/xml/dtm/DTMAxisIterator;
-Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->resetPosition()Lorg/apache/xml/dtm/DTMAxisIterator;
-Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->returnNode(I)I
-Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->setRestartable(Z)V
-Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->_includeSelf:Z
-Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->_isRestartable:Z
-Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->_last:I
-Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->_markedNode:I
-Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->_position:I
-Lorg/apache/xml/dtm/ref/DTMAxisIteratorBase;->_startNode:I
-Lorg/apache/xml/dtm/ref/DTMAxisIterNodeList;-><init>(Lorg/apache/xml/dtm/DTM;Lorg/apache/xml/dtm/DTMAxisIterator;)V
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->appendChild(IZZ)V
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->appendTextChild(Ljava/lang/String;)V
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->declareNamespaceInContext(II)V
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->documentRegistration()V
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->documentRelease()V
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->ensureSizeOfIndex(II)V
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->error(Ljava/lang/String;)V
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->findGTE([IIII)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->findInSortedSuballocatedIntVector(Lorg/apache/xml/utils/SuballocatedIntVector;I)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->findNamespaceContext(I)Lorg/apache/xml/utils/SuballocatedIntVector;
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDocument()I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDocumentAllDeclarationsProcessed()Z
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDocumentBaseURI()Ljava/lang/String;
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDocumentEncoding(I)Ljava/lang/String;
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDocumentRoot(I)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDocumentStandalone(I)Ljava/lang/String;
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDocumentSystemIdentifier(I)Ljava/lang/String;
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDocumentVersion(I)Ljava/lang/String;
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getDTMIDs()Lorg/apache/xml/utils/SuballocatedIntVector;
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getExpandedTypeID(I)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getExpandedTypeID(Ljava/lang/String;Ljava/lang/String;I)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getFirstChild(I)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getFirstNamespaceNode(IZ)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getLastChild(I)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getLevel(I)S
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getLocalNameFromExpandedNameID(I)Ljava/lang/String;
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getManager()Lorg/apache/xml/dtm/DTMManager;
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNamespaceFromExpandedNameID(I)Ljava/lang/String;
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNamespaceType(I)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNextAttribute(I)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNextNamespaceNode(IIZ)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNextSibling(I)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNode(I)Lorg/w3c/dom/Node;
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNodeHandle(I)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNodeIdent(I)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getNodeType(I)S
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getOwnerDocument(I)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getParent(I)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getPreviousSibling(I)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getShouldStripWhitespace()Z
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getStringValueChunk(II[I)[C
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->getStringValueChunkCount(I)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->hasChildNodes(I)Z
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->indexNode(II)V
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->isCharacterElementContentWhitespace(I)Z
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->isDocumentAllDeclarationsProcessed(I)Z
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->isNodeAfter(II)Z
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->isSupported(Ljava/lang/String;Ljava/lang/String;)Z
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->makeNodeHandle(I)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->makeNodeIdentity(I)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_expandedNameTable:Lorg/apache/xml/dtm/ref/ExpandedNameTable;
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_exptype:Lorg/apache/xml/utils/SuballocatedIntVector;
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_firstch:Lorg/apache/xml/utils/SuballocatedIntVector;
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_nextsib:Lorg/apache/xml/utils/SuballocatedIntVector;
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_parent:Lorg/apache/xml/utils/SuballocatedIntVector;
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_prevsib:Lorg/apache/xml/utils/SuballocatedIntVector;
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_size:I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_wsfilter:Lorg/apache/xml/dtm/DTMWSFilter;
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->m_xstrf:Lorg/apache/xml/utils/XMLStringFactory;
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->popShouldStripWhitespace()V
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->pushShouldStripWhitespace(Z)V
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->setDocumentBaseURI(Ljava/lang/String;)V
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->setFeature(Ljava/lang/String;Z)V
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->setShouldStripWhitespace(Z)V
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->supportsPreStripping()Z
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->_exptype(I)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->_firstch(I)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->_level(I)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->_nextsib(I)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->_parent(I)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->_prevsib(I)I
-Lorg/apache/xml/dtm/ref/DTMDefaultBase;->_type(I)S
-Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators$InternalAxisIteratorBase;-><init>(Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators;)V
-Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators$InternalAxisIteratorBase;->_currentNode:I
-Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators$NamespaceIterator;-><init>(Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators;)V
-Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators$NamespaceIterator;->next()I
-Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators$NamespaceIterator;->setStartNode(I)Lorg/apache/xml/dtm/DTMAxisIterator;
-Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators$NthDescendantIterator;-><init>(Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators;I)V
-Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators$SingletonIterator;-><init>(Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators;)V
-Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators$SingletonIterator;-><init>(Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators;I)V
-Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators;-><init>(Lorg/apache/xml/dtm/DTMManager;Ljavax/xml/transform/Source;ILorg/apache/xml/dtm/DTMWSFilter;Lorg/apache/xml/utils/XMLStringFactory;Z)V
-Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators;->getAxisIterator(I)Lorg/apache/xml/dtm/DTMAxisIterator;
-Lorg/apache/xml/dtm/ref/DTMDefaultBaseIterators;->getTypedAxisIterator(II)Lorg/apache/xml/dtm/DTMAxisIterator;
-Lorg/apache/xml/dtm/ref/DTMDefaultBaseTraversers;->getAxisTraverser(I)Lorg/apache/xml/dtm/DTMAxisTraverser;
-Lorg/apache/xml/dtm/ref/DTMManagerDefault;-><init>()V
-Lorg/apache/xml/dtm/ref/DTMManagerDefault;->addDTM(Lorg/apache/xml/dtm/DTM;I)V
-Lorg/apache/xml/dtm/ref/DTMManagerDefault;->addDTM(Lorg/apache/xml/dtm/DTM;II)V
-Lorg/apache/xml/dtm/ref/DTMManagerDefault;->getFirstFreeDTMID()I
-Lorg/apache/xml/dtm/ref/DTMManagerDefault;->getXMLReader(Ljavax/xml/transform/Source;)Lorg/xml/sax/XMLReader;
-Lorg/apache/xml/dtm/ref/DTMManagerDefault;->releaseXMLReader(Lorg/xml/sax/XMLReader;)V
-Lorg/apache/xml/dtm/ref/DTMNodeIterator;-><init>(Lorg/apache/xml/dtm/DTMIterator;)V
-Lorg/apache/xml/dtm/ref/DTMNodeIterator;->getDTMIterator()Lorg/apache/xml/dtm/DTMIterator;
-Lorg/apache/xml/dtm/ref/DTMNodeIterator;->getRoot()Lorg/w3c/dom/Node;
-Lorg/apache/xml/dtm/ref/DTMNodeList;-><init>(Lorg/apache/xml/dtm/DTMIterator;)V
-Lorg/apache/xml/dtm/ref/DTMNodeProxy;-><init>(Lorg/apache/xml/dtm/DTM;I)V
-Lorg/apache/xml/dtm/ref/DTMNodeProxy;->getDTM()Lorg/apache/xml/dtm/DTM;
-Lorg/apache/xml/dtm/ref/DTMNodeProxy;->getDTMNodeNumber()I
-Lorg/apache/xml/dtm/ref/DTMNodeProxy;->getStringValue()Ljava/lang/String;
-Lorg/apache/xml/dtm/ref/DTMStringPool;-><init>()V
-Lorg/apache/xml/dtm/ref/DTMStringPool;->indexToString(I)Ljava/lang/String;
-Lorg/apache/xml/dtm/ref/DTMStringPool;->m_intToString:Ljava/util/Vector;
-Lorg/apache/xml/dtm/ref/DTMStringPool;->removeAllElements()V
-Lorg/apache/xml/dtm/ref/DTMStringPool;->stringToIndex(Ljava/lang/String;)I
-Lorg/apache/xml/dtm/ref/ExpandedNameTable;->getExpandedTypeID(Ljava/lang/String;Ljava/lang/String;I)I
-Lorg/apache/xml/dtm/ref/ExpandedNameTable;->getExpandedTypeID(Ljava/lang/String;Ljava/lang/String;IZ)I
-Lorg/apache/xml/dtm/ref/ExpandedNameTable;->getLocalName(I)Ljava/lang/String;
-Lorg/apache/xml/dtm/ref/ExpandedNameTable;->getSize()I
-Lorg/apache/xml/dtm/ref/ExpandedNameTable;->getType(I)S
-Lorg/apache/xml/dtm/ref/IncrementalSAXSource;->deliverMoreNodes(Z)Ljava/lang/Object;
-Lorg/apache/xml/dtm/ref/IncrementalSAXSource;->setContentHandler(Lorg/xml/sax/ContentHandler;)V
-Lorg/apache/xml/dtm/ref/IncrementalSAXSource;->setLexicalHandler(Lorg/xml/sax/ext/LexicalHandler;)V
-Lorg/apache/xml/dtm/ref/IncrementalSAXSource;->startParse(Lorg/xml/sax/InputSource;)V
-Lorg/apache/xml/dtm/ref/IncrementalSAXSource_Filter;-><init>()V
-Lorg/apache/xml/dtm/ref/IncrementalSAXSource_Filter;->setXMLReader(Lorg/xml/sax/XMLReader;)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$AncestorIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$AncestorIterator;->next()I
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$AncestorIterator;->setStartNode(I)Lorg/apache/xml/dtm/DTMAxisIterator;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$AttributeIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$ChildrenIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$ChildrenIterator;->setStartNode(I)Lorg/apache/xml/dtm/DTMAxisIterator;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$DescendantIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$FollowingIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$FollowingSiblingIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$ParentIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$ParentIterator;->setNodeType(I)Lorg/apache/xml/dtm/DTMAxisIterator;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$PrecedingIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$PrecedingSiblingIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedAncestorIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedAttributeIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedChildrenIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedDescendantIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedFollowingIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedFollowingSiblingIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedPrecedingIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedPrecedingSiblingIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2$TypedSingletonIterator;-><init>(Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;I)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;-><init>(Lorg/apache/xml/dtm/DTMManager;Ljavax/xml/transform/Source;ILorg/apache/xml/dtm/DTMWSFilter;Lorg/apache/xml/utils/XMLStringFactory;ZIZZZ)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->copyAttribute(IILorg/apache/xml/serializer/SerializationHandler;)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->copyAttributes(ILorg/apache/xml/serializer/SerializationHandler;)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->copyElement(IILorg/apache/xml/serializer/SerializationHandler;)Ljava/lang/String;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->copyNS(ILorg/apache/xml/serializer/SerializationHandler;Z)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->copyTextNode(ILorg/apache/xml/serializer/SerializationHandler;)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->dispatchCharactersEvents(ILorg/xml/sax/ContentHandler;Z)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getFirstAttribute(I)I
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getIdForNamespace(Ljava/lang/String;)I
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getLocalName(I)Ljava/lang/String;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getNodeName(I)Ljava/lang/String;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getNodeNameX(I)Ljava/lang/String;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getNodeValue(I)Ljava/lang/String;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getStringValue()Ljava/lang/String;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getStringValue(I)Lorg/apache/xml/utils/XMLString;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->getStringValueX(I)Ljava/lang/String;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->m_buildIdIndex:Z
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->_exptype2(I)I
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->_exptype2Type(I)I
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->_firstch2(I)I
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM2;->_nextsib2(I)I
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->dispatchToEvents(ILorg/xml/sax/ContentHandler;)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getAttributeNode(ILjava/lang/String;Ljava/lang/String;)I
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getContentHandler()Lorg/xml/sax/ContentHandler;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getDeclHandler()Lorg/xml/sax/ext/DeclHandler;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getDocumentTypeDeclarationPublicIdentifier()Ljava/lang/String;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getDocumentTypeDeclarationSystemIdentifier()Ljava/lang/String;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getDTDHandler()Lorg/xml/sax/DTDHandler;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getEntityResolver()Lorg/xml/sax/EntityResolver;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getErrorHandler()Lorg/xml/sax/ErrorHandler;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getLexicalHandler()Lorg/xml/sax/ext/LexicalHandler;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getNamespaceURI(I)Ljava/lang/String;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getNumberOfNodes()I
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getPrefix(I)Ljava/lang/String;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getSourceLocatorFor(I)Ljavax/xml/transform/SourceLocator;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->getUnparsedEntityURI(Ljava/lang/String;)Ljava/lang/String;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->isAttributeSpecified(I)Z
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->migrateTo(Lorg/apache/xml/dtm/DTMManager;)V
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->m_idAttributes:Ljava/util/Hashtable;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->m_parents:Lorg/apache/xml/utils/IntStack;
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->m_previous:I
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->needsTwoThreads()Z
-Lorg/apache/xml/dtm/ref/sax2dtm/SAX2DTM;->setProperty(Ljava/lang/String;Ljava/lang/Object;)V
-Lorg/apache/xml/dtm/ref/SecuritySupport;->getContextClassLoader()Ljava/lang/ClassLoader;
-Lorg/apache/xml/dtm/ref/SecuritySupport;->getFileExists(Ljava/io/File;)Z
-Lorg/apache/xml/dtm/ref/SecuritySupport;->getFileInputStream(Ljava/io/File;)Ljava/io/FileInputStream;
-Lorg/apache/xml/dtm/ref/SecuritySupport;->getInstance()Lorg/apache/xml/dtm/ref/SecuritySupport;
-Lorg/apache/xml/dtm/ref/SecuritySupport;->getLastModified(Ljava/io/File;)J
-Lorg/apache/xml/dtm/ref/SecuritySupport;->getParentClassLoader(Ljava/lang/ClassLoader;)Ljava/lang/ClassLoader;
-Lorg/apache/xml/dtm/ref/SecuritySupport;->getResourceAsStream(Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/io/InputStream;
-Lorg/apache/xml/dtm/ref/SecuritySupport;->getSystemClassLoader()Ljava/lang/ClassLoader;
-Lorg/apache/xml/dtm/ref/SecuritySupport;->getSystemProperty(Ljava/lang/String;)Ljava/lang/String;
-Lorg/apache/xml/res/XMLErrorResources;-><init>()V
-Lorg/apache/xml/res/XMLMessages;->createXMLMessage(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
-Lorg/apache/xml/serializer/CharInfo$CharKey;-><init>(C)V
-Lorg/apache/xml/serializer/CharInfo;-><init>(Ljava/lang/String;Ljava/lang/String;Z)V
-Lorg/apache/xml/serializer/CharInfo;->get(I)Z
-Lorg/apache/xml/serializer/CharInfo;->getCharInfo(Ljava/lang/String;Ljava/lang/String;)Lorg/apache/xml/serializer/CharInfo;
-Lorg/apache/xml/serializer/CharInfo;->set(I)V
-Lorg/apache/xml/serializer/dom3/LSSerializerImpl;-><init>()V
-Lorg/apache/xml/serializer/DOMSerializer;->serialize(Lorg/w3c/dom/Node;)V
-Lorg/apache/xml/serializer/ElemContext;->m_elementName:Ljava/lang/String;
-Lorg/apache/xml/serializer/ElemContext;->m_elementURI:Ljava/lang/String;
-Lorg/apache/xml/serializer/ElemContext;->m_startTagOpen:Z
-Lorg/apache/xml/serializer/ElemContext;->push(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lorg/apache/xml/serializer/ElemContext;
-Lorg/apache/xml/serializer/ElemDesc;->isAttrFlagSet(Ljava/lang/String;I)Z
-Lorg/apache/xml/serializer/Encodings;->convertMime2JavaEncoding(Ljava/lang/String;)Ljava/lang/String;
-Lorg/apache/xml/serializer/Encodings;->getMimeEncoding(Ljava/lang/String;)Ljava/lang/String;
-Lorg/apache/xml/serializer/Encodings;->getWriter(Ljava/io/OutputStream;Ljava/lang/String;)Ljava/io/Writer;
-Lorg/apache/xml/serializer/NamespaceMappings;-><init>()V
-Lorg/apache/xml/serializer/NamespaceMappings;->generateNextPrefix()Ljava/lang/String;
-Lorg/apache/xml/serializer/NamespaceMappings;->lookupNamespace(Ljava/lang/String;)Ljava/lang/String;
-Lorg/apache/xml/serializer/NamespaceMappings;->lookupPrefix(Ljava/lang/String;)Ljava/lang/String;
-Lorg/apache/xml/serializer/OutputPropertiesFactory;->getDefaultMethodProperties(Ljava/lang/String;)Ljava/util/Properties;
-Lorg/apache/xml/serializer/OutputPropertyUtils;->getBooleanProperty(Ljava/lang/String;Ljava/util/Properties;)Z
-Lorg/apache/xml/serializer/OutputPropertyUtils;->getIntProperty(Ljava/lang/String;Ljava/util/Properties;)I
-Lorg/apache/xml/serializer/SerializationHandler;->close()V
-Lorg/apache/xml/serializer/SerializationHandler;->flushPending()V
-Lorg/apache/xml/serializer/SerializationHandler;->setEscaping(Z)Z
-Lorg/apache/xml/serializer/SerializationHandler;->setIndentAmount(I)V
-Lorg/apache/xml/serializer/SerializationHandler;->setNamespaceMappings(Lorg/apache/xml/serializer/NamespaceMappings;)V
-Lorg/apache/xml/serializer/Serializer;->asContentHandler()Lorg/xml/sax/ContentHandler;
-Lorg/apache/xml/serializer/Serializer;->asDOMSerializer()Lorg/apache/xml/serializer/DOMSerializer;
-Lorg/apache/xml/serializer/Serializer;->getOutputFormat()Ljava/util/Properties;
-Lorg/apache/xml/serializer/Serializer;->getOutputStream()Ljava/io/OutputStream;
-Lorg/apache/xml/serializer/Serializer;->getWriter()Ljava/io/Writer;
-Lorg/apache/xml/serializer/Serializer;->reset()Z
-Lorg/apache/xml/serializer/Serializer;->setOutputFormat(Ljava/util/Properties;)V
-Lorg/apache/xml/serializer/Serializer;->setOutputStream(Ljava/io/OutputStream;)V
-Lorg/apache/xml/serializer/Serializer;->setWriter(Ljava/io/Writer;)V
-Lorg/apache/xml/serializer/SerializerBase;->fireCharEvent([CII)V
-Lorg/apache/xml/serializer/SerializerBase;->fireCommentEvent([CII)V
-Lorg/apache/xml/serializer/SerializerBase;->fireEndDoc()V
-Lorg/apache/xml/serializer/SerializerBase;->fireEndElem(Ljava/lang/String;)V
-Lorg/apache/xml/serializer/SerializerBase;->fireEscapingEvent(Ljava/lang/String;Ljava/lang/String;)V
-Lorg/apache/xml/serializer/SerializerBase;->getDoctypePublic()Ljava/lang/String;
-Lorg/apache/xml/serializer/SerializerBase;->getDoctypeSystem()Ljava/lang/String;
-Lorg/apache/xml/serializer/SerializerBase;->getEncoding()Ljava/lang/String;
-Lorg/apache/xml/serializer/SerializerBase;->getPrefixPart(Ljava/lang/String;)Ljava/lang/String;
-Lorg/apache/xml/serializer/SerializerBase;->getVersion()Ljava/lang/String;
-Lorg/apache/xml/serializer/SerializerBase;->m_attributes:Lorg/apache/xml/serializer/AttributesImplSerializer;
-Lorg/apache/xml/serializer/SerializerBase;->m_charsBuff:[C
-Lorg/apache/xml/serializer/SerializerBase;->m_elemContext:Lorg/apache/xml/serializer/ElemContext;
-Lorg/apache/xml/serializer/SerializerBase;->m_needToCallStartDocument:Z
-Lorg/apache/xml/serializer/SerializerBase;->m_tracer:Lorg/apache/xml/serializer/SerializerTrace;
-Lorg/apache/xml/serializer/SerializerBase;->setDoctypePublic(Ljava/lang/String;)V
-Lorg/apache/xml/serializer/SerializerBase;->setDoctypeSystem(Ljava/lang/String;)V
-Lorg/apache/xml/serializer/SerializerBase;->setIndent(Z)V
-Lorg/apache/xml/serializer/SerializerBase;->setMediaType(Ljava/lang/String;)V
-Lorg/apache/xml/serializer/SerializerBase;->setOmitXMLDeclaration(Z)V
-Lorg/apache/xml/serializer/SerializerBase;->setStandalone(Ljava/lang/String;)V
-Lorg/apache/xml/serializer/SerializerBase;->setStandaloneInternal(Ljava/lang/String;)V
-Lorg/apache/xml/serializer/SerializerBase;->setVersion(Ljava/lang/String;)V
-Lorg/apache/xml/serializer/SerializerFactory;->getSerializer(Ljava/util/Properties;)Lorg/apache/xml/serializer/Serializer;
-Lorg/apache/xml/serializer/SerializerTraceWriter;-><init>(Ljava/io/Writer;Lorg/apache/xml/serializer/SerializerTrace;)V
-Lorg/apache/xml/serializer/ToHTMLStream;-><init>()V
-Lorg/apache/xml/serializer/ToHTMLStream;->getElemDesc(Ljava/lang/String;)Lorg/apache/xml/serializer/ElemDesc;
-Lorg/apache/xml/serializer/ToSAXHandler;-><init>(Lorg/xml/sax/ContentHandler;Ljava/lang/String;)V
-Lorg/apache/xml/serializer/ToSAXHandler;-><init>(Lorg/xml/sax/ContentHandler;Lorg/xml/sax/ext/LexicalHandler;Ljava/lang/String;)V
-Lorg/apache/xml/serializer/ToSAXHandler;->m_lexHandler:Lorg/xml/sax/ext/LexicalHandler;
-Lorg/apache/xml/serializer/ToSAXHandler;->m_saxHandler:Lorg/xml/sax/ContentHandler;
-Lorg/apache/xml/serializer/ToSAXHandler;->reset()Z
-Lorg/apache/xml/serializer/ToSAXHandler;->startDocumentInternal()V
-Lorg/apache/xml/serializer/ToSAXHandler;->startElement(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-Lorg/apache/xml/serializer/ToStream;->setCdataSectionElements(Ljava/lang/String;Ljava/util/Properties;)V
-Lorg/apache/xml/serializer/ToStream;->setEncoding(Ljava/lang/String;)V
-Lorg/apache/xml/serializer/ToStream;->setIndentAmount(I)V
-Lorg/apache/xml/serializer/ToTextSAXHandler;-><init>(Lorg/xml/sax/ContentHandler;Ljava/lang/String;)V
-Lorg/apache/xml/serializer/ToTextSAXHandler;-><init>(Lorg/xml/sax/ContentHandler;Lorg/xml/sax/ext/LexicalHandler;Ljava/lang/String;)V
-Lorg/apache/xml/serializer/ToTextStream;-><init>()V
-Lorg/apache/xml/serializer/ToUnknownStream;-><init>()V
-Lorg/apache/xml/serializer/ToXMLSAXHandler;-><init>(Lorg/xml/sax/ContentHandler;Ljava/lang/String;)V
-Lorg/apache/xml/serializer/ToXMLSAXHandler;-><init>(Lorg/xml/sax/ContentHandler;Lorg/xml/sax/ext/LexicalHandler;Ljava/lang/String;)V
-Lorg/apache/xml/serializer/ToXMLStream;-><init>()V
-Lorg/apache/xml/serializer/WriterToASCI;-><init>(Ljava/io/OutputStream;)V
-Lorg/apache/xml/serializer/WriterToUTF8Buffered;-><init>(Ljava/io/OutputStream;)V
-Lorg/apache/xml/utils/DefaultErrorHandler;-><init>()V
-Lorg/apache/xml/utils/DefaultErrorHandler;->printLocation(Ljava/io/PrintWriter;Ljava/lang/Throwable;)V
-Lorg/apache/xml/utils/DOMHelper;->isNodeAfter(Lorg/w3c/dom/Node;Lorg/w3c/dom/Node;)Z
-Lorg/apache/xml/utils/DOMHelper;->isNodeTheSame(Lorg/w3c/dom/Node;Lorg/w3c/dom/Node;)Z
-Lorg/apache/xml/utils/FastStringBuffer;->append(Ljava/lang/String;)V
-Lorg/apache/xml/utils/FastStringBuffer;->getString(II)Ljava/lang/String;
-Lorg/apache/xml/utils/FastStringBuffer;->length()I
-Lorg/apache/xml/utils/IntStack;->peek()I
-Lorg/apache/xml/utils/ObjectVector;->elementAt(I)Ljava/lang/Object;
-Lorg/apache/xml/utils/ObjectVector;->size()I
-Lorg/apache/xml/utils/PrefixResolverDefault;-><init>(Lorg/w3c/dom/Node;)V
-Lorg/apache/xml/utils/PrefixResolverDefault;->getNamespaceForPrefix(Ljava/lang/String;)Ljava/lang/String;
-Lorg/apache/xml/utils/QName;-><init>(Ljava/lang/String;)V
-Lorg/apache/xml/utils/QName;-><init>(Ljava/lang/String;Ljava/lang/String;)V
-Lorg/apache/xml/utils/QName;->getLocalName()Ljava/lang/String;
-Lorg/apache/xml/utils/SAXSourceLocator;-><init>(Lorg/xml/sax/SAXParseException;)V
-Lorg/apache/xml/utils/StringBufferPool;->free(Lorg/apache/xml/utils/FastStringBuffer;)V
-Lorg/apache/xml/utils/StringBufferPool;->get()Lorg/apache/xml/utils/FastStringBuffer;
-Lorg/apache/xml/utils/StringVector;->elementAt(I)Ljava/lang/String;
-Lorg/apache/xml/utils/StringVector;->size()I
-Lorg/apache/xml/utils/StylesheetPIHandler;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-Lorg/apache/xml/utils/StylesheetPIHandler;->getAssociatedStylesheet()Ljavax/xml/transform/Source;
-Lorg/apache/xml/utils/StylesheetPIHandler;->setBaseId(Ljava/lang/String;)V
-Lorg/apache/xml/utils/StylesheetPIHandler;->setURIResolver(Ljavax/xml/transform/URIResolver;)V
-Lorg/apache/xml/utils/SuballocatedIntVector;-><init>(I)V
-Lorg/apache/xml/utils/SuballocatedIntVector;->elementAt(I)I
-Lorg/apache/xml/utils/SuballocatedIntVector;->setElementAt(II)V
-Lorg/apache/xml/utils/SuballocatedIntVector;->size()I
-Lorg/apache/xml/utils/SystemIDResolver;->getAbsoluteURI(Ljava/lang/String;)Ljava/lang/String;
-Lorg/apache/xml/utils/SystemIDResolver;->getAbsoluteURI(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
-Lorg/apache/xml/utils/SystemIDResolver;->getAbsoluteURIFromRelative(Ljava/lang/String;)Ljava/lang/String;
-Lorg/apache/xml/utils/SystemIDResolver;->isAbsoluteURI(Ljava/lang/String;)Z
-Lorg/apache/xml/utils/URI$MalformedURIException;-><init>(Ljava/lang/String;)V
-Lorg/apache/xml/utils/URI;-><init>(Ljava/lang/String;)V
-Lorg/apache/xml/utils/URI;-><init>(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
-Lorg/apache/xml/utils/URI;-><init>(Lorg/apache/xml/utils/URI;)V
-Lorg/apache/xml/utils/URI;-><init>(Lorg/apache/xml/utils/URI;Ljava/lang/String;)V
-Lorg/apache/xml/utils/URI;->getFragment()Ljava/lang/String;
-Lorg/apache/xml/utils/URI;->getHost()Ljava/lang/String;
-Lorg/apache/xml/utils/URI;->getPath()Ljava/lang/String;
-Lorg/apache/xml/utils/URI;->getPort()I
-Lorg/apache/xml/utils/URI;->getQueryString()Ljava/lang/String;
-Lorg/apache/xml/utils/URI;->getScheme()Ljava/lang/String;
-Lorg/apache/xml/utils/URI;->getUserinfo()Ljava/lang/String;
-Lorg/apache/xml/utils/URI;->setFragment(Ljava/lang/String;)V
-Lorg/apache/xml/utils/URI;->setHost(Ljava/lang/String;)V
-Lorg/apache/xml/utils/URI;->setPort(I)V
-Lorg/apache/xml/utils/URI;->setScheme(Ljava/lang/String;)V
-Lorg/apache/xml/utils/URI;->setUserinfo(Ljava/lang/String;)V
-Lorg/apache/xml/utils/WrappedRuntimeException;-><init>(Ljava/lang/Exception;)V
-Lorg/apache/xml/utils/WrappedRuntimeException;->getException()Ljava/lang/Exception;
-Lorg/apache/xml/utils/XML11Char;->isXML11ValidNCName(Ljava/lang/String;)Z
-Lorg/apache/xml/utils/XML11Char;->isXML11ValidQName(Ljava/lang/String;)Z
-Lorg/apache/xml/utils/XMLReaderManager;->getInstance()Lorg/apache/xml/utils/XMLReaderManager;
-Lorg/apache/xml/utils/XMLReaderManager;->getXMLReader()Lorg/xml/sax/XMLReader;
-Lorg/apache/xml/utils/XMLReaderManager;->releaseXMLReader(Lorg/xml/sax/XMLReader;)V
-Lorg/apache/xml/utils/XMLString;->dispatchCharactersEvents(Lorg/xml/sax/ContentHandler;)V
-Lorg/apache/xml/utils/XMLString;->equals(Lorg/apache/xml/utils/XMLString;)Z
-Lorg/apache/xml/utils/XMLString;->fixWhiteSpace(ZZZ)Lorg/apache/xml/utils/XMLString;
-Lorg/apache/xml/utils/XMLStringDefault;-><init>(Ljava/lang/String;)V
-Lorg/apache/xml/utils/XMLStringFactory;-><init>()V
-Lorg/apache/xml/utils/XMLStringFactory;->emptystr()Lorg/apache/xml/utils/XMLString;
-Lorg/apache/xml/utils/XMLStringFactory;->newstr(Ljava/lang/String;)Lorg/apache/xml/utils/XMLString;
-Lorg/apache/xpath/axes/ChildTestIterator;-><init>(Lorg/apache/xml/dtm/DTMAxisTraverser;)V
-Lorg/apache/xpath/axes/DescendantIterator;-><init>()V
-Lorg/apache/xpath/axes/LocPathIterator;->getDTM(I)Lorg/apache/xml/dtm/DTM;
-Lorg/apache/xpath/axes/LocPathIterator;->getPrefixResolver()Lorg/apache/xml/utils/PrefixResolver;
-Lorg/apache/xpath/axes/LocPathIterator;->getXPathContext()Lorg/apache/xpath/XPathContext;
-Lorg/apache/xpath/axes/NodeSequence;->getContainedIter()Lorg/apache/xml/dtm/DTMIterator;
-Lorg/apache/xpath/axes/NodeSequence;->nextNode()I
-Lorg/apache/xpath/axes/OneStepIterator;-><init>(Lorg/apache/xml/dtm/DTMAxisIterator;I)V
-Lorg/apache/xpath/CachedXPathAPI;-><init>()V
-Lorg/apache/xpath/CachedXPathAPI;-><init>(Lorg/apache/xpath/CachedXPathAPI;)V
-Lorg/apache/xpath/CachedXPathAPI;->eval(Lorg/w3c/dom/Node;Ljava/lang/String;)Lorg/apache/xpath/objects/XObject;
-Lorg/apache/xpath/CachedXPathAPI;->getXPathContext()Lorg/apache/xpath/XPathContext;
-Lorg/apache/xpath/CachedXPathAPI;->selectNodeList(Lorg/w3c/dom/Node;Ljava/lang/String;)Lorg/w3c/dom/NodeList;
-Lorg/apache/xpath/CachedXPathAPI;->selectNodeList(Lorg/w3c/dom/Node;Ljava/lang/String;Lorg/w3c/dom/Node;)Lorg/w3c/dom/NodeList;
-Lorg/apache/xpath/CachedXPathAPI;->selectSingleNode(Lorg/w3c/dom/Node;Ljava/lang/String;)Lorg/w3c/dom/Node;
-Lorg/apache/xpath/CachedXPathAPI;->selectSingleNode(Lorg/w3c/dom/Node;Ljava/lang/String;Lorg/w3c/dom/Node;)Lorg/w3c/dom/Node;
-Lorg/apache/xpath/compiler/FunctionTable;-><init>()V
-Lorg/apache/xpath/compiler/FunctionTable;->installFunction(Ljava/lang/String;Ljava/lang/Class;)I
-Lorg/apache/xpath/Expression;->assertion(ZLjava/lang/String;)V
-Lorg/apache/xpath/Expression;->error(Lorg/apache/xpath/XPathContext;Ljava/lang/String;[Ljava/lang/Object;)V
-Lorg/apache/xpath/Expression;->exprGetParent()Lorg/apache/xpath/ExpressionNode;
-Lorg/apache/xpath/ExpressionNode;->exprGetParent()Lorg/apache/xpath/ExpressionNode;
-Lorg/apache/xpath/functions/FuncCurrent;-><init>()V
-Lorg/apache/xpath/functions/FuncExtFunction;->getFunctionName()Ljava/lang/String;
-Lorg/apache/xpath/functions/FuncExtFunction;->getMethodKey()Ljava/lang/Object;
-Lorg/apache/xpath/functions/Function;-><init>()V
-Lorg/apache/xpath/functions/WrongNumberArgsException;-><init>(Ljava/lang/String;)V
-Lorg/apache/xpath/NodeSet;-><init>()V
-Lorg/apache/xpath/NodeSet;-><init>(Lorg/w3c/dom/Node;)V
-Lorg/apache/xpath/NodeSet;-><init>(Lorg/w3c/dom/NodeList;)V
-Lorg/apache/xpath/NodeSet;-><init>(Lorg/w3c/dom/traversal/NodeIterator;)V
-Lorg/apache/xpath/NodeSet;->addElement(Lorg/w3c/dom/Node;)V
-Lorg/apache/xpath/NodeSet;->addNode(Lorg/w3c/dom/Node;)V
-Lorg/apache/xpath/NodeSet;->contains(Lorg/w3c/dom/Node;)Z
-Lorg/apache/xpath/NodeSet;->elementAt(I)Lorg/w3c/dom/Node;
-Lorg/apache/xpath/NodeSet;->setShouldCacheNodes(Z)V
-Lorg/apache/xpath/NodeSetDTM;-><init>(Lorg/w3c/dom/NodeList;Lorg/apache/xpath/XPathContext;)V
-Lorg/apache/xpath/NodeSetDTM;-><init>(Lorg/w3c/dom/traversal/NodeIterator;Lorg/apache/xpath/XPathContext;)V
-Lorg/apache/xpath/NodeSetDTM;->addNode(I)V
-Lorg/apache/xpath/NodeSetDTM;->detach()V
-Lorg/apache/xpath/NodeSetDTM;->getLength()I
-Lorg/apache/xpath/NodeSetDTM;->item(I)I
-Lorg/apache/xpath/objects/XBoolean;-><init>(Z)V
-Lorg/apache/xpath/objects/XBoolean;->bool()Z
-Lorg/apache/xpath/objects/XBoolean;->str()Ljava/lang/String;
-Lorg/apache/xpath/objects/XBooleanStatic;-><init>(Z)V
-Lorg/apache/xpath/objects/XNodeSet;-><init>(ILorg/apache/xml/dtm/DTMManager;)V
-Lorg/apache/xpath/objects/XNodeSet;-><init>(Lorg/apache/xml/dtm/DTMIterator;)V
-Lorg/apache/xpath/objects/XNodeSet;-><init>(Lorg/apache/xml/dtm/DTMManager;)V
-Lorg/apache/xpath/objects/XNodeSet;->iterRaw()Lorg/apache/xml/dtm/DTMIterator;
-Lorg/apache/xpath/objects/XNodeSet;->mutableNodeset()Lorg/apache/xpath/NodeSetDTM;
-Lorg/apache/xpath/objects/XNodeSet;->nodelist()Lorg/w3c/dom/NodeList;
-Lorg/apache/xpath/objects/XNumber;-><init>(D)V
-Lorg/apache/xpath/objects/XNumber;->num()D
-Lorg/apache/xpath/objects/XNumber;->str()Ljava/lang/String;
-Lorg/apache/xpath/objects/XObject;->bool()Z
-Lorg/apache/xpath/objects/XObject;->create(Ljava/lang/Object;)Lorg/apache/xpath/objects/XObject;
-Lorg/apache/xpath/objects/XObject;->getType()I
-Lorg/apache/xpath/objects/XObject;->getTypeString()Ljava/lang/String;
-Lorg/apache/xpath/objects/XObject;->iter()Lorg/apache/xml/dtm/DTMIterator;
-Lorg/apache/xpath/objects/XObject;->nodelist()Lorg/w3c/dom/NodeList;
-Lorg/apache/xpath/objects/XObject;->nodeset()Lorg/w3c/dom/traversal/NodeIterator;
-Lorg/apache/xpath/objects/XObject;->num()D
-Lorg/apache/xpath/objects/XObject;->object()Ljava/lang/Object;
-Lorg/apache/xpath/objects/XObject;->str()Ljava/lang/String;
-Lorg/apache/xpath/objects/XObject;->xstr()Lorg/apache/xml/utils/XMLString;
-Lorg/apache/xpath/objects/XRTreeFrag;-><init>(ILorg/apache/xpath/XPathContext;)V
-Lorg/apache/xpath/objects/XRTreeFrag;->asNodeIterator()Lorg/apache/xml/dtm/DTMIterator;
-Lorg/apache/xpath/objects/XRTreeFrag;->convertToNodeset()Lorg/w3c/dom/NodeList;
-Lorg/apache/xpath/objects/XString;-><init>(Ljava/lang/String;)V
-Lorg/apache/xpath/objects/XString;->num()D
-Lorg/apache/xpath/patterns/NodeTest;->setWhatToShow(I)V
-Lorg/apache/xpath/res/XPATHErrorResources;-><init>()V
-Lorg/apache/xpath/res/XPATHMessages;->createXPATHMessage(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
-Lorg/apache/xpath/XPath;-><init>(Ljava/lang/String;Ljavax/xml/transform/SourceLocator;Lorg/apache/xml/utils/PrefixResolver;I)V
-Lorg/apache/xpath/XPath;-><init>(Ljava/lang/String;Ljavax/xml/transform/SourceLocator;Lorg/apache/xml/utils/PrefixResolver;ILjavax/xml/transform/ErrorListener;)V
-Lorg/apache/xpath/XPath;->execute(Lorg/apache/xpath/XPathContext;ILorg/apache/xml/utils/PrefixResolver;)Lorg/apache/xpath/objects/XObject;
-Lorg/apache/xpath/XPath;->execute(Lorg/apache/xpath/XPathContext;Lorg/w3c/dom/Node;Lorg/apache/xml/utils/PrefixResolver;)Lorg/apache/xpath/objects/XObject;
-Lorg/apache/xpath/XPath;->getPatternString()Ljava/lang/String;
-Lorg/apache/xpath/XPathAPI;->selectNodeList(Lorg/w3c/dom/Node;Ljava/lang/String;)Lorg/w3c/dom/NodeList;
-Lorg/apache/xpath/XPathAPI;->selectNodeList(Lorg/w3c/dom/Node;Ljava/lang/String;Lorg/w3c/dom/Node;)Lorg/w3c/dom/NodeList;
-Lorg/apache/xpath/XPathAPI;->selectSingleNode(Lorg/w3c/dom/Node;Ljava/lang/String;)Lorg/w3c/dom/Node;
-Lorg/apache/xpath/XPathAPI;->selectSingleNode(Lorg/w3c/dom/Node;Ljava/lang/String;Lorg/w3c/dom/Node;)Lorg/w3c/dom/Node;
-Lorg/apache/xpath/XPathContext$XPathExpressionContext;->getDTMManager()Lorg/apache/xml/dtm/DTMManager;
-Lorg/apache/xpath/XPathContext$XPathExpressionContext;->getXPathContext()Lorg/apache/xpath/XPathContext;
-Lorg/apache/xpath/XPathContext;-><init>()V
-Lorg/apache/xpath/XPathContext;-><init>(Ljava/lang/Object;)V
-Lorg/apache/xpath/XPathContext;->getAxesIteratorStackStacks()Ljava/util/Stack;
-Lorg/apache/xpath/XPathContext;->getContextNodeList()Lorg/apache/xml/dtm/DTMIterator;
-Lorg/apache/xpath/XPathContext;->getContextNodeListsStack()Ljava/util/Stack;
-Lorg/apache/xpath/XPathContext;->getCurrentExpressionNodeStack()Lorg/apache/xml/utils/IntStack;
-Lorg/apache/xpath/XPathContext;->getCurrentNode()I
-Lorg/apache/xpath/XPathContext;->getCurrentNodeStack()Lorg/apache/xml/utils/IntStack;
-Lorg/apache/xpath/XPathContext;->getDTM(I)Lorg/apache/xml/dtm/DTM;
-Lorg/apache/xpath/XPathContext;->getDTMHandleFromNode(Lorg/w3c/dom/Node;)I
-Lorg/apache/xpath/XPathContext;->getDTMManager()Lorg/apache/xml/dtm/DTMManager;
-Lorg/apache/xpath/XPathContext;->getExpressionContext()Lorg/apache/xalan/extensions/ExpressionContext;
-Lorg/apache/xpath/XPathContext;->getNamespaceContext()Lorg/apache/xml/utils/PrefixResolver;
-Lorg/apache/xpath/XPathContext;->getOwnerObject()Ljava/lang/Object;
-Lorg/apache/xpath/XPathContext;->getSAXLocator()Ljavax/xml/transform/SourceLocator;
-Lorg/apache/xpath/XPathContext;->getVarStack()Lorg/apache/xpath/VariableStack;
-Lorg/apache/xpath/XPathContext;->m_dtmManager:Lorg/apache/xml/dtm/DTMManager;
-Lorg/apache/xpath/XPathContext;->popContextNodeList()V
-Lorg/apache/xpath/XPathContext;->popCurrentNode()V
-Lorg/apache/xpath/XPathContext;->pushContextNodeList(Lorg/apache/xml/dtm/DTMIterator;)V
-Lorg/apache/xpath/XPathContext;->pushCurrentNode(I)V
-Lorg/apache/xpath/XPathContext;->reset()V
-Lorg/apache/xpath/XPathContext;->setAxesIteratorStackStacks(Ljava/util/Stack;)V
-Lorg/apache/xpath/XPathContext;->setContextNodeListsStack(Ljava/util/Stack;)V
-Lorg/apache/xpath/XPathContext;->setCurrentExpressionNodeStack(Lorg/apache/xml/utils/IntStack;)V
-Lorg/apache/xpath/XPathContext;->setCurrentNodeStack(Lorg/apache/xml/utils/IntStack;)V
-Lorg/apache/xpath/XPathContext;->setSecureProcessing(Z)V
-Lorg/apache/xpath/XPathContext;->setVarStack(Lorg/apache/xpath/VariableStack;)V
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 500a04fc7be5..46a520a5289e 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -278,7 +278,7 @@ public abstract class ActivityManagerInternal {
String resolvedType, boolean fgRequired, String callingPackage, int userId,
boolean allowBackgroundActivityStarts) throws TransactionTooLargeException;
- public abstract void disconnectActivityFromServices(Object connectionHolder);
+ public abstract void disconnectActivityFromServices(Object connectionHolder, Object conns);
public abstract void cleanUpServices(int userId, ComponentName component, Intent baseIntent);
public abstract ActivityInfo getActivityInfoForUser(ActivityInfo aInfo, int userId);
public abstract void ensureBootCompleted();
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index af2d774508c4..205e7a13092b 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -433,6 +433,9 @@ public class StatusBarManager {
private boolean mNotificationPeeking;
private boolean mRecents;
private boolean mSearch;
+ private boolean mSystemIcons;
+ private boolean mClock;
+ private boolean mNotificationIcons;
/** @hide */
public DisableInfo(int flags1, int flags2) {
@@ -441,6 +444,9 @@ public class StatusBarManager {
mNotificationPeeking = (flags1 & DISABLE_NOTIFICATION_ALERTS) != 0;
mRecents = (flags1 & DISABLE_RECENT) != 0;
mSearch = (flags1 & DISABLE_SEARCH) != 0;
+ mSystemIcons = (flags1 & DISABLE_SYSTEM_INFO) != 0;
+ mClock = (flags1 & DISABLE_CLOCK) != 0;
+ mNotificationIcons = (flags1 & DISABLE_NOTIFICATION_ICONS) != 0;
}
/** @hide */
@@ -527,6 +533,48 @@ public class StatusBarManager {
}
/**
+ * @return {@code true} if system icons are disabled
+ *
+ * @hide
+ */
+ public boolean areSystemIconsDisabled() {
+ return mSystemIcons;
+ }
+
+ /** * @hide */
+ public void setSystemIconsDisabled(boolean disabled) {
+ mSystemIcons = disabled;
+ }
+
+ /**
+ * @return {@code true} if the clock icon is disabled
+ *
+ * @hide
+ */
+ public boolean isClockDisabled() {
+ return mClock;
+ }
+
+ /** * @hide */
+ public void setClockDisabled(boolean disabled) {
+ mClock = disabled;
+ }
+
+ /**
+ * @return {@code true} if notification icons are disabled
+ *
+ * @hide
+ */
+ public boolean areNotificationIconsDisabled() {
+ return mNotificationIcons;
+ }
+
+ /** * @hide */
+ public void setNotificationIconsDisabled(boolean disabled) {
+ mNotificationIcons = disabled;
+ }
+
+ /**
* @return {@code true} if no components are disabled (default state)
*
* @hide
@@ -535,7 +583,7 @@ public class StatusBarManager {
@TestApi
public boolean areAllComponentsEnabled() {
return !mStatusBarExpansion && !mNavigateHome && !mNotificationPeeking && !mRecents
- && !mSearch;
+ && !mSearch && !mSystemIcons && !mClock && !mNotificationIcons;
}
/** @hide */
@@ -545,6 +593,9 @@ public class StatusBarManager {
mNotificationPeeking = false;
mRecents = false;
mSearch = false;
+ mSystemIcons = false;
+ mClock = false;
+ mNotificationIcons = false;
}
/**
@@ -554,7 +605,7 @@ public class StatusBarManager {
*/
public boolean areAllComponentsDisabled() {
return mStatusBarExpansion && mNavigateHome && mNotificationPeeking
- && mRecents && mSearch;
+ && mRecents && mSearch && mSystemIcons && mClock && mNotificationIcons;
}
/** @hide */
@@ -564,6 +615,9 @@ public class StatusBarManager {
mNotificationPeeking = true;
mRecents = true;
mSearch = true;
+ mSystemIcons = true;
+ mClock = true;
+ mNotificationIcons = true;
}
@Override
@@ -576,6 +630,9 @@ public class StatusBarManager {
.append(mNotificationPeeking ? "disabled" : "enabled");
sb.append(" mRecents=").append(mRecents ? "disabled" : "enabled");
sb.append(" mSearch=").append(mSearch ? "disabled" : "enabled");
+ sb.append(" mSystemIcons=").append(mSystemIcons ? "disabled" : "enabled");
+ sb.append(" mClock=").append(mClock ? "disabled" : "enabled");
+ sb.append(" mNotificationIcons=").append(mNotificationIcons ? "disabled" : "enabled");
return sb.toString();
@@ -596,6 +653,9 @@ public class StatusBarManager {
if (mNotificationPeeking) disable1 |= DISABLE_NOTIFICATION_ALERTS;
if (mRecents) disable1 |= DISABLE_RECENT;
if (mSearch) disable1 |= DISABLE_SEARCH;
+ if (mSystemIcons) disable1 |= DISABLE_SYSTEM_INFO;
+ if (mClock) disable1 |= DISABLE_CLOCK;
+ if (mNotificationIcons) disable1 |= DISABLE_NOTIFICATION_ICONS;
return new Pair<Integer, Integer>(disable1, disable2);
}
diff --git a/core/java/android/app/admin/DevicePolicyEventLogger.java b/core/java/android/app/admin/DevicePolicyEventLogger.java
index 44ea21881e88..95a797392940 100644
--- a/core/java/android/app/admin/DevicePolicyEventLogger.java
+++ b/core/java/android/app/admin/DevicePolicyEventLogger.java
@@ -22,9 +22,10 @@ import android.stats.devicepolicy.nano.StringList;
import android.util.StatsLog;
import com.android.framework.protobuf.nano.MessageNano;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
+import java.util.Arrays;
+
/**
* A wrapper for logging managed device events using {@link StatsLog}.
* <p/>
@@ -45,7 +46,7 @@ import com.android.internal.util.Preconditions;
* @see StatsLog
* @hide
*/
-public final class DevicePolicyEventLogger {
+public class DevicePolicyEventLogger {
private final int mEventId;
private int mIntValue;
private boolean mBooleanValue;
@@ -71,7 +72,6 @@ public final class DevicePolicyEventLogger {
/**
* Returns the event id.
*/
- @VisibleForTesting
public int getEventId() {
return mEventId;
}
@@ -87,7 +87,6 @@ public final class DevicePolicyEventLogger {
/**
* Returns the generic <code>int</code> value.
*/
- @VisibleForTesting
public int getInt() {
return mIntValue;
}
@@ -103,7 +102,6 @@ public final class DevicePolicyEventLogger {
/**
* Returns the generic <code>boolean</code> value.
*/
- @VisibleForTesting
public boolean getBoolean() {
return mBooleanValue;
}
@@ -119,7 +117,6 @@ public final class DevicePolicyEventLogger {
/**
* Returns the time period in milliseconds.
*/
- @VisibleForTesting
public long getTimePeriod() {
return mTimePeriodMs;
}
@@ -162,11 +159,13 @@ public final class DevicePolicyEventLogger {
}
/**
- * Returns the generic <code>String[]</code> value.
+ * Returns a copy of the generic <code>String[]</code> value.
*/
- @VisibleForTesting
public String[] getStringArray() {
- return mStringArrayValue;
+ if (mStringArrayValue == null) {
+ return null;
+ }
+ return Arrays.copyOf(mStringArrayValue, mStringArrayValue.length);
}
/**
@@ -188,7 +187,6 @@ public final class DevicePolicyEventLogger {
/**
* Returns the package name of the admin application.
*/
- @VisibleForTesting
public String getAdminPackageName() {
return mAdminPackageName;
}
diff --git a/core/java/android/bluetooth/BluetoothProfileConnector.java b/core/java/android/bluetooth/BluetoothProfileConnector.java
index d9987249a6e2..863fd3698cbd 100644
--- a/core/java/android/bluetooth/BluetoothProfileConnector.java
+++ b/core/java/android/bluetooth/BluetoothProfileConnector.java
@@ -32,12 +32,12 @@ import android.util.Log;
* @hide
*/
public abstract class BluetoothProfileConnector<T> {
- private int mProfileId;
+ private final int mProfileId;
private BluetoothProfile.ServiceListener mServiceListener;
- private BluetoothProfile mProfileProxy;
+ private final BluetoothProfile mProfileProxy;
private Context mContext;
- private String mProfileName;
- private String mServiceName;
+ private final String mProfileName;
+ private final String mServiceName;
private volatile T mService;
private final IBluetoothStateChangeCallback mBluetoothStateChangeCallback =
@@ -65,7 +65,7 @@ public abstract class BluetoothProfileConnector<T> {
logDebug("Proxy object disconnected");
doUnbind();
if (mServiceListener != null) {
- mServiceListener.onServiceDisconnected(BluetoothProfile.A2DP);
+ mServiceListener.onServiceDisconnected(mProfileId);
}
}
};
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index b09eada27ce4..cb939f05ffc5 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -807,7 +807,7 @@ public abstract class PackageManager {
*
* @hide
*/
- public static final int INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS = 0x00000200;
+ public static final int INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS = 0x00400000;
/** {@hide} */
public static final int INSTALL_FORCE_VOLUME_UUID = 0x00000200;
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index 41be38a6e8dd..58aacc2c36c7 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -153,14 +153,21 @@ public final class ShortcutInfo implements Parcelable {
public static final int CLONE_REMOVE_RES_NAMES = 1 << 3;
/** @hide */
+ public static final int CLONE_REMOVE_PERSON = 1 << 4;
+
+ /** @hide */
public static final int CLONE_REMOVE_FOR_CREATOR = CLONE_REMOVE_ICON | CLONE_REMOVE_RES_NAMES;
/** @hide */
public static final int CLONE_REMOVE_FOR_LAUNCHER = CLONE_REMOVE_ICON | CLONE_REMOVE_INTENT
- | CLONE_REMOVE_RES_NAMES;
+ | CLONE_REMOVE_RES_NAMES | CLONE_REMOVE_PERSON;
/** @hide */
public static final int CLONE_REMOVE_FOR_LAUNCHER_APPROVAL = CLONE_REMOVE_INTENT
+ | CLONE_REMOVE_RES_NAMES | CLONE_REMOVE_PERSON;
+
+ /** @hide */
+ public static final int CLONE_REMOVE_FOR_APP_PREDICTION = CLONE_REMOVE_ICON
| CLONE_REMOVE_RES_NAMES;
/** @hide */
@@ -169,8 +176,11 @@ public final class ShortcutInfo implements Parcelable {
CLONE_REMOVE_INTENT,
CLONE_REMOVE_NON_KEY_INFO,
CLONE_REMOVE_RES_NAMES,
+ CLONE_REMOVE_PERSON,
CLONE_REMOVE_FOR_CREATOR,
- CLONE_REMOVE_FOR_LAUNCHER
+ CLONE_REMOVE_FOR_LAUNCHER,
+ CLONE_REMOVE_FOR_LAUNCHER_APPROVAL,
+ CLONE_REMOVE_FOR_APP_PREDICTION
})
@Retention(RetentionPolicy.SOURCE)
public @interface CloneFlags {}
@@ -548,7 +558,9 @@ public final class ShortcutInfo implements Parcelable {
mDisabledMessage = source.mDisabledMessage;
mDisabledMessageResId = source.mDisabledMessageResId;
mCategories = cloneCategories(source.mCategories);
- mPersons = clonePersons(source.mPersons);
+ if ((cloneFlags & CLONE_REMOVE_PERSON) == 0) {
+ mPersons = clonePersons(source.mPersons);
+ }
if ((cloneFlags & CLONE_REMOVE_INTENT) == 0) {
mIntents = cloneIntents(source.mIntents);
mIntentPersistableExtrases =
diff --git a/core/java/android/content/rollback/IRollbackManager.aidl b/core/java/android/content/rollback/IRollbackManager.aidl
index db9fcb6abdfa..1b84f2987a8f 100644
--- a/core/java/android/content/rollback/IRollbackManager.aidl
+++ b/core/java/android/content/rollback/IRollbackManager.aidl
@@ -30,9 +30,9 @@ interface IRollbackManager {
String callerPackageName, in IntentSender statusReceiver);
// Exposed for use from the system server only. Callback from the package
- // manager during the install flow when user data can be restored for a given
+ // manager during the install flow when user data can be backed up and restored for a given
// package.
- void restoreUserData(String packageName, in int[] userIds, int appId, long ceDataInode,
+ void snapshotAndRestoreUserData(String packageName, in int[] userIds, int appId, long ceDataInode,
String seInfo, int token);
// Exposed for test purposes only.
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index ab630fd7467b..82d4d1d10d7e 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -472,8 +472,12 @@ public class InputMethodService extends AbstractInputMethodService {
*/
@MainThread
@Override
- public final void initializeInternal(IBinder token, int displayId,
+ public final void initializeInternal(@NonNull IBinder token, int displayId,
IInputMethodPrivilegedOperations privilegedOperations) {
+ if (InputMethodPrivilegedOperationsRegistry.isRegistered(token)) {
+ Log.w(TAG, "The token has already registered, ignore this initialization.");
+ return;
+ }
mPrivOps.set(privilegedOperations);
InputMethodPrivilegedOperationsRegistry.put(token, mPrivOps);
updateInputMethodDisplay(displayId);
diff --git a/core/java/android/net/DnsResolver.java b/core/java/android/net/DnsResolver.java
index 4b2b4c35b292..7a85dcbfc830 100644
--- a/core/java/android/net/DnsResolver.java
+++ b/core/java/android/net/DnsResolver.java
@@ -16,7 +16,7 @@
package android.net;
-import static android.net.NetworkUtils.getDnsNetId;
+import static android.net.NetworkUtils.getDnsNetwork;
import static android.net.NetworkUtils.resNetworkCancel;
import static android.net.NetworkUtils.resNetworkQuery;
import static android.net.NetworkUtils.resNetworkResult;
@@ -333,7 +333,7 @@ public final class DnsResolver {
final Object lock = new Object();
final Network queryNetwork;
try {
- queryNetwork = (network != null) ? network : new Network(getDnsNetId());
+ queryNetwork = (network != null) ? network : getDnsNetwork();
} catch (ErrnoException e) {
executor.execute(() -> callback.onError(new DnsException(ERROR_SYSTEM, e)));
return;
@@ -433,7 +433,7 @@ public final class DnsResolver {
final FileDescriptor queryfd;
final Network queryNetwork;
try {
- queryNetwork = (network != null) ? network : new Network(getDnsNetId());
+ queryNetwork = (network != null) ? network : getDnsNetwork();
queryfd = resNetworkQuery(queryNetwork.getNetIdForResolv(), domain, CLASS_IN, nsType,
flags);
} catch (ErrnoException e) {
diff --git a/core/java/android/net/NetworkStats.java b/core/java/android/net/NetworkStats.java
index e892b650bf40..bb344e289657 100644
--- a/core/java/android/net/NetworkStats.java
+++ b/core/java/android/net/NetworkStats.java
@@ -18,6 +18,7 @@ package android.net;
import static android.os.Process.CLAT_UID;
+import android.annotation.NonNull;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -33,6 +34,7 @@ import libcore.util.EmptyArray;
import java.io.CharArrayWriter;
import java.io.PrintWriter;
import java.util.Arrays;
+import java.util.function.Predicate;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
@@ -993,23 +995,33 @@ public class NetworkStats implements Parcelable {
if (limitUid == UID_ALL && limitTag == TAG_ALL && limitIfaces == INTERFACES_ALL) {
return;
}
+ filter(e -> (limitUid == UID_ALL || limitUid == e.uid)
+ && (limitTag == TAG_ALL || limitTag == e.tag)
+ && (limitIfaces == INTERFACES_ALL
+ || ArrayUtils.contains(limitIfaces, e.iface)));
+ }
+
+ /**
+ * Only keep entries with {@link #set} value less than {@link #SET_DEBUG_START}.
+ *
+ * <p>This mutates the original structure in place.
+ */
+ public void filterDebugEntries() {
+ filter(e -> e.set < SET_DEBUG_START);
+ }
+ private void filter(Predicate<Entry> predicate) {
Entry entry = new Entry();
int nextOutputEntry = 0;
for (int i = 0; i < size; i++) {
entry = getValues(i, entry);
- final boolean matches =
- (limitUid == UID_ALL || limitUid == entry.uid)
- && (limitTag == TAG_ALL || limitTag == entry.tag)
- && (limitIfaces == INTERFACES_ALL
- || ArrayUtils.contains(limitIfaces, entry.iface));
-
- if (matches) {
- setValues(nextOutputEntry, entry);
+ if (predicate.test(entry)) {
+ if (nextOutputEntry != i) {
+ setValues(nextOutputEntry, entry);
+ }
nextOutputEntry++;
}
}
-
size = nextOutputEntry;
}
@@ -1175,133 +1187,221 @@ public class NetworkStats implements Parcelable {
/**
* VPN accounting. Move some VPN's underlying traffic to other UIDs that use tun0 iface.
*
- * This method should only be called on delta NetworkStats. Do not call this method on a
- * snapshot {@link NetworkStats} object because the tunUid and/or the underlyingIface may
- * change over time.
- *
- * This method performs adjustments for one active VPN package and one VPN iface at a time.
+ * <p>This method should only be called on delta NetworkStats. Do not call this method on a
+ * snapshot {@link NetworkStats} object because the tunUid and/or the underlyingIface may change
+ * over time.
*
- * It is possible for the VPN software to use multiple underlying networks. This method
- * only migrates traffic for the primary underlying network.
+ * <p>This method performs adjustments for one active VPN package and one VPN iface at a time.
*
* @param tunUid uid of the VPN application
* @param tunIface iface of the vpn tunnel
- * @param underlyingIface the primary underlying network iface used by the VPN application
- * @return true if it successfully adjusts the accounting for VPN, false otherwise
+ * @param underlyingIfaces underlying network ifaces used by the VPN application
*/
- public boolean migrateTun(int tunUid, String tunIface, String underlyingIface) {
- Entry tunIfaceTotal = new Entry();
- Entry underlyingIfaceTotal = new Entry();
+ public void migrateTun(int tunUid, @NonNull String tunIface,
+ @NonNull String[] underlyingIfaces) {
+ // Combined usage by all apps using VPN.
+ final Entry tunIfaceTotal = new Entry();
+ // Usage by VPN, grouped by its {@code underlyingIfaces}.
+ final Entry[] perInterfaceTotal = new Entry[underlyingIfaces.length];
+ // Usage by VPN, summed across all its {@code underlyingIfaces}.
+ final Entry underlyingIfacesTotal = new Entry();
+
+ for (int i = 0; i < perInterfaceTotal.length; i++) {
+ perInterfaceTotal[i] = new Entry();
+ }
- tunAdjustmentInit(tunUid, tunIface, underlyingIface, tunIfaceTotal, underlyingIfaceTotal);
+ tunAdjustmentInit(tunUid, tunIface, underlyingIfaces, tunIfaceTotal, perInterfaceTotal,
+ underlyingIfacesTotal);
- // If tunIface < underlyingIface, it leaves the overhead traffic in the VPN app.
- // If tunIface > underlyingIface, the VPN app doesn't get credit for data compression.
+ // If tunIface < underlyingIfacesTotal, it leaves the overhead traffic in the VPN app.
+ // If tunIface > underlyingIfacesTotal, the VPN app doesn't get credit for data compression.
// Negative stats should be avoided.
- Entry pool = tunGetPool(tunIfaceTotal, underlyingIfaceTotal);
- if (pool.isEmpty()) {
- return true;
- }
- Entry moved =
- addTrafficToApplications(tunUid, tunIface, underlyingIface, tunIfaceTotal, pool);
- deductTrafficFromVpnApp(tunUid, underlyingIface, moved);
-
- if (!moved.isEmpty()) {
- Slog.wtf(TAG, "Failed to deduct underlying network traffic from VPN package. Moved="
- + moved);
- return false;
- }
- return true;
+ final Entry[] moved =
+ addTrafficToApplications(tunUid, tunIface, underlyingIfaces, tunIfaceTotal,
+ perInterfaceTotal, underlyingIfacesTotal);
+ deductTrafficFromVpnApp(tunUid, underlyingIfaces, moved);
}
/**
* Initializes the data used by the migrateTun() method.
*
- * This is the first pass iteration which does the following work:
- * (1) Adds up all the traffic through the tunUid's underlyingIface
- * (both foreground and background).
- * (2) Adds up all the traffic through tun0 excluding traffic from the vpn app itself.
+ * <p>This is the first pass iteration which does the following work:
+ *
+ * <ul>
+ * <li>Adds up all the traffic through the tunUid's underlyingIfaces (both foreground and
+ * background).
+ * <li>Adds up all the traffic through tun0 excluding traffic from the vpn app itself.
+ * </ul>
+ *
+ * @param tunUid uid of the VPN application
+ * @param tunIface iface of the vpn tunnel
+ * @param underlyingIfaces underlying network ifaces used by the VPN application
+ * @param tunIfaceTotal output parameter; combined data usage by all apps using VPN
+ * @param perInterfaceTotal output parameter; data usage by VPN app, grouped by its {@code
+ * underlyingIfaces}
+ * @param underlyingIfacesTotal output parameter; data usage by VPN, summed across all of its
+ * {@code underlyingIfaces}
*/
- private void tunAdjustmentInit(int tunUid, String tunIface, String underlyingIface,
- Entry tunIfaceTotal, Entry underlyingIfaceTotal) {
- Entry recycle = new Entry();
+ private void tunAdjustmentInit(int tunUid, @NonNull String tunIface,
+ @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal,
+ @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) {
+ final Entry recycle = new Entry();
for (int i = 0; i < size; i++) {
getValues(i, recycle);
if (recycle.uid == UID_ALL) {
throw new IllegalStateException(
"Cannot adjust VPN accounting on an iface aggregated NetworkStats.");
- } if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) {
+ }
+ if (recycle.set == SET_DBG_VPN_IN || recycle.set == SET_DBG_VPN_OUT) {
throw new IllegalStateException(
"Cannot adjust VPN accounting on a NetworkStats containing SET_DBG_VPN_*");
}
-
- if (recycle.uid == tunUid && recycle.tag == TAG_NONE
- && Objects.equals(underlyingIface, recycle.iface)) {
- underlyingIfaceTotal.add(recycle);
+ if (recycle.tag != TAG_NONE) {
+ // TODO(b/123666283): Take all tags for tunUid into account.
+ continue;
}
- if (recycle.uid != tunUid && recycle.tag == TAG_NONE
- && Objects.equals(tunIface, recycle.iface)) {
+ if (recycle.uid == tunUid) {
+ // Add up traffic through tunUid's underlying interfaces.
+ for (int j = 0; j < underlyingIfaces.length; j++) {
+ if (Objects.equals(underlyingIfaces[j], recycle.iface)) {
+ perInterfaceTotal[j].add(recycle);
+ underlyingIfacesTotal.add(recycle);
+ break;
+ }
+ }
+ } else if (tunIface.equals(recycle.iface)) {
// Add up all tunIface traffic excluding traffic from the vpn app itself.
tunIfaceTotal.add(recycle);
}
}
}
- private static Entry tunGetPool(Entry tunIfaceTotal, Entry underlyingIfaceTotal) {
- Entry pool = new Entry();
- pool.rxBytes = Math.min(tunIfaceTotal.rxBytes, underlyingIfaceTotal.rxBytes);
- pool.rxPackets = Math.min(tunIfaceTotal.rxPackets, underlyingIfaceTotal.rxPackets);
- pool.txBytes = Math.min(tunIfaceTotal.txBytes, underlyingIfaceTotal.txBytes);
- pool.txPackets = Math.min(tunIfaceTotal.txPackets, underlyingIfaceTotal.txPackets);
- pool.operations = Math.min(tunIfaceTotal.operations, underlyingIfaceTotal.operations);
- return pool;
- }
+ /**
+ * Distributes traffic across apps that are using given {@code tunIface}, and returns the total
+ * traffic that should be moved off of {@code tunUid} grouped by {@code underlyingIfaces}.
+ *
+ * @param tunUid uid of the VPN application
+ * @param tunIface iface of the vpn tunnel
+ * @param underlyingIfaces underlying network ifaces used by the VPN application
+ * @param tunIfaceTotal combined data usage across all apps using {@code tunIface}
+ * @param perInterfaceTotal data usage by VPN app, grouped by its {@code underlyingIfaces}
+ * @param underlyingIfacesTotal data usage by VPN, summed across all of its {@code
+ * underlyingIfaces}
+ */
+ private Entry[] addTrafficToApplications(int tunUid, @NonNull String tunIface,
+ @NonNull String[] underlyingIfaces, @NonNull Entry tunIfaceTotal,
+ @NonNull Entry[] perInterfaceTotal, @NonNull Entry underlyingIfacesTotal) {
+ // Traffic that should be moved off of each underlying interface for tunUid (see
+ // deductTrafficFromVpnApp below).
+ final Entry[] moved = new Entry[underlyingIfaces.length];
+ for (int i = 0; i < underlyingIfaces.length; i++) {
+ moved[i] = new Entry();
+ }
- private Entry addTrafficToApplications(int tunUid, String tunIface, String underlyingIface,
- Entry tunIfaceTotal, Entry pool) {
- Entry moved = new Entry();
- Entry tmpEntry = new Entry();
- tmpEntry.iface = underlyingIface;
- for (int i = 0; i < size; i++) {
- // the vpn app is excluded from the redistribution but all moved traffic will be
- // deducted from the vpn app (see deductTrafficFromVpnApp below).
- if (Objects.equals(iface[i], tunIface) && uid[i] != tunUid) {
- if (tunIfaceTotal.rxBytes > 0) {
- tmpEntry.rxBytes = pool.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes;
- } else {
- tmpEntry.rxBytes = 0;
+ final Entry tmpEntry = new Entry();
+ final int origSize = size;
+ for (int i = 0; i < origSize; i++) {
+ if (!Objects.equals(iface[i], tunIface)) {
+ // Consider only entries that go onto the VPN interface.
+ continue;
+ }
+ if (uid[i] == tunUid) {
+ // Exclude VPN app from the redistribution, as it can choose to create packet
+ // streams by writing to itself.
+ continue;
+ }
+ tmpEntry.uid = uid[i];
+ tmpEntry.tag = tag[i];
+ tmpEntry.metered = metered[i];
+ tmpEntry.roaming = roaming[i];
+ tmpEntry.defaultNetwork = defaultNetwork[i];
+
+ // In a first pass, compute this entry's total share of data across all
+ // underlyingIfaces. This is computed on the basis of the share of this entry's usage
+ // over tunIface.
+ // TODO: Consider refactoring first pass into a separate helper method.
+ long totalRxBytes = 0;
+ if (tunIfaceTotal.rxBytes > 0) {
+ // Note - The multiplication below should not overflow since NetworkStatsService
+ // processes this every time device has transmitted/received amount equivalent to
+ // global threshold alert (~ 2MB) across all interfaces.
+ final long rxBytesAcrossUnderlyingIfaces =
+ underlyingIfacesTotal.rxBytes * rxBytes[i] / tunIfaceTotal.rxBytes;
+ // app must not be blamed for more than it consumed on tunIface
+ totalRxBytes = Math.min(rxBytes[i], rxBytesAcrossUnderlyingIfaces);
+ }
+ long totalRxPackets = 0;
+ if (tunIfaceTotal.rxPackets > 0) {
+ final long rxPacketsAcrossUnderlyingIfaces =
+ underlyingIfacesTotal.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets;
+ totalRxPackets = Math.min(rxPackets[i], rxPacketsAcrossUnderlyingIfaces);
+ }
+ long totalTxBytes = 0;
+ if (tunIfaceTotal.txBytes > 0) {
+ final long txBytesAcrossUnderlyingIfaces =
+ underlyingIfacesTotal.txBytes * txBytes[i] / tunIfaceTotal.txBytes;
+ totalTxBytes = Math.min(txBytes[i], txBytesAcrossUnderlyingIfaces);
+ }
+ long totalTxPackets = 0;
+ if (tunIfaceTotal.txPackets > 0) {
+ final long txPacketsAcrossUnderlyingIfaces =
+ underlyingIfacesTotal.txPackets * txPackets[i] / tunIfaceTotal.txPackets;
+ totalTxPackets = Math.min(txPackets[i], txPacketsAcrossUnderlyingIfaces);
+ }
+ long totalOperations = 0;
+ if (tunIfaceTotal.operations > 0) {
+ final long operationsAcrossUnderlyingIfaces =
+ underlyingIfacesTotal.operations * operations[i] / tunIfaceTotal.operations;
+ totalOperations = Math.min(operations[i], operationsAcrossUnderlyingIfaces);
+ }
+ // In a second pass, distribute these values across interfaces in the proportion that
+ // each interface represents of the total traffic of the underlying interfaces.
+ for (int j = 0; j < underlyingIfaces.length; j++) {
+ tmpEntry.iface = underlyingIfaces[j];
+ tmpEntry.rxBytes = 0;
+ // Reset 'set' to correct value since it gets updated when adding debug info below.
+ tmpEntry.set = set[i];
+ if (underlyingIfacesTotal.rxBytes > 0) {
+ tmpEntry.rxBytes =
+ totalRxBytes
+ * perInterfaceTotal[j].rxBytes
+ / underlyingIfacesTotal.rxBytes;
}
- if (tunIfaceTotal.rxPackets > 0) {
- tmpEntry.rxPackets = pool.rxPackets * rxPackets[i] / tunIfaceTotal.rxPackets;
- } else {
- tmpEntry.rxPackets = 0;
+ tmpEntry.rxPackets = 0;
+ if (underlyingIfacesTotal.rxPackets > 0) {
+ tmpEntry.rxPackets =
+ totalRxPackets
+ * perInterfaceTotal[j].rxPackets
+ / underlyingIfacesTotal.rxPackets;
}
- if (tunIfaceTotal.txBytes > 0) {
- tmpEntry.txBytes = pool.txBytes * txBytes[i] / tunIfaceTotal.txBytes;
- } else {
- tmpEntry.txBytes = 0;
+ tmpEntry.txBytes = 0;
+ if (underlyingIfacesTotal.txBytes > 0) {
+ tmpEntry.txBytes =
+ totalTxBytes
+ * perInterfaceTotal[j].txBytes
+ / underlyingIfacesTotal.txBytes;
}
- if (tunIfaceTotal.txPackets > 0) {
- tmpEntry.txPackets = pool.txPackets * txPackets[i] / tunIfaceTotal.txPackets;
- } else {
- tmpEntry.txPackets = 0;
+ tmpEntry.txPackets = 0;
+ if (underlyingIfacesTotal.txPackets > 0) {
+ tmpEntry.txPackets =
+ totalTxPackets
+ * perInterfaceTotal[j].txPackets
+ / underlyingIfacesTotal.txPackets;
}
- if (tunIfaceTotal.operations > 0) {
+ tmpEntry.operations = 0;
+ if (underlyingIfacesTotal.operations > 0) {
tmpEntry.operations =
- pool.operations * operations[i] / tunIfaceTotal.operations;
- } else {
- tmpEntry.operations = 0;
+ totalOperations
+ * perInterfaceTotal[j].operations
+ / underlyingIfacesTotal.operations;
}
- tmpEntry.uid = uid[i];
- tmpEntry.tag = tag[i];
- tmpEntry.set = set[i];
- tmpEntry.metered = metered[i];
- tmpEntry.roaming = roaming[i];
- tmpEntry.defaultNetwork = defaultNetwork[i];
+ // tmpEntry now contains the migrated data of the i-th entry for the j-th underlying
+ // interface. Add that data usage to this object.
combineValues(tmpEntry);
if (tag[i] == TAG_NONE) {
- moved.add(tmpEntry);
+ // Add the migrated data to moved so it is deducted from the VPN app later.
+ moved[j].add(tmpEntry);
// Add debug info
tmpEntry.set = SET_DBG_VPN_IN;
combineValues(tmpEntry);
@@ -1311,38 +1411,45 @@ public class NetworkStats implements Parcelable {
return moved;
}
- private void deductTrafficFromVpnApp(int tunUid, String underlyingIface, Entry moved) {
- // Add debug info
- moved.uid = tunUid;
- moved.set = SET_DBG_VPN_OUT;
- moved.tag = TAG_NONE;
- moved.iface = underlyingIface;
- moved.metered = METERED_ALL;
- moved.roaming = ROAMING_ALL;
- moved.defaultNetwork = DEFAULT_NETWORK_ALL;
- combineValues(moved);
-
- // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than
- // the TAG_NONE traffic.
- //
- // Relies on the fact that the underlying traffic only has state ROAMING_NO and METERED_NO,
- // which should be the case as it comes directly from the /proc file. We only blend in the
- // roaming data after applying these adjustments, by checking the NetworkIdentity of the
- // underlying iface.
- int idxVpnBackground = findIndex(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE,
- METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO);
- if (idxVpnBackground != -1) {
- tunSubtract(idxVpnBackground, this, moved);
- }
+ private void deductTrafficFromVpnApp(
+ int tunUid,
+ @NonNull String[] underlyingIfaces,
+ @NonNull Entry[] moved) {
+ for (int i = 0; i < underlyingIfaces.length; i++) {
+ moved[i].uid = tunUid;
+ // Add debug info
+ moved[i].set = SET_DBG_VPN_OUT;
+ moved[i].tag = TAG_NONE;
+ moved[i].iface = underlyingIfaces[i];
+ moved[i].metered = METERED_ALL;
+ moved[i].roaming = ROAMING_ALL;
+ moved[i].defaultNetwork = DEFAULT_NETWORK_ALL;
+ combineValues(moved[i]);
+
+ // Caveat: if the vpn software uses tag, the total tagged traffic may be greater than
+ // the TAG_NONE traffic.
+ //
+ // Relies on the fact that the underlying traffic only has state ROAMING_NO and
+ // METERED_NO, which should be the case as it comes directly from the /proc file.
+ // We only blend in the roaming data after applying these adjustments, by checking the
+ // NetworkIdentity of the underlying iface.
+ final int idxVpnBackground = findIndex(underlyingIfaces[i], tunUid, SET_DEFAULT,
+ TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO);
+ if (idxVpnBackground != -1) {
+ // Note - tunSubtract also updates moved[i]; whatever traffic that's left is removed
+ // from foreground usage.
+ tunSubtract(idxVpnBackground, this, moved[i]);
+ }
- int idxVpnForeground = findIndex(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE,
- METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO);
- if (idxVpnForeground != -1) {
- tunSubtract(idxVpnForeground, this, moved);
+ final int idxVpnForeground = findIndex(underlyingIfaces[i], tunUid, SET_FOREGROUND,
+ TAG_NONE, METERED_NO, ROAMING_NO, DEFAULT_NETWORK_NO);
+ if (idxVpnForeground != -1) {
+ tunSubtract(idxVpnForeground, this, moved[i]);
+ }
}
}
- private static void tunSubtract(int i, NetworkStats left, Entry right) {
+ private static void tunSubtract(int i, @NonNull NetworkStats left, @NonNull Entry right) {
long rxBytes = Math.min(left.rxBytes[i], right.rxBytes);
left.rxBytes[i] -= rxBytes;
right.rxBytes -= rxBytes;
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index a640f83ea5d2..d0f54b4c7f2d 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -158,10 +158,9 @@ public class NetworkUtils {
/**
* DNS resolver series jni method.
- * Attempts to get netid of network which resolver will
- * use if no network is explicitly selected.
+ * Attempts to get network which resolver will use if no network is explicitly selected.
*/
- public static native int getDnsNetId() throws ErrnoException;
+ public static native Network getDnsNetwork() throws ErrnoException;
/**
* Get the tcp repair window associated with the {@code fd}.
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index deb9eba1bc99..77d367f0d933 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -113,8 +113,7 @@ public class Build {
/**
* A hardware serial number, if available. Alphanumeric only, case-insensitive.
- * For apps targeting SDK higher than {@link Build.VERSION_CODES#O_MR1} this
- * field is set to {@link Build#UNKNOWN}.
+ * This field is always set to {@link Build#UNKNOWN}.
*
* @deprecated Use {@link #getSerial()} instead.
**/
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 5039b31ed9ff..24a147783669 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -231,13 +231,6 @@ public class GraphicsEnvironment {
}
/**
- * Check whether application is profileable
- */
- private static boolean isProfileable(Context context) {
- return context.getApplicationInfo().isProfileableByShell();
- }
-
- /**
* Store the layer paths available to the loader.
*/
public void setLayerPaths(ClassLoader classLoader,
@@ -287,11 +280,11 @@ public class GraphicsEnvironment {
String layerPaths = "";
// Only enable additional debug functionality if the following conditions are met:
- // 1. App is debuggable, profileable, or device is rooted
+ // 1. App is debuggable or device is rooted
// 2. ENABLE_GPU_DEBUG_LAYERS is true
// 3. Package name is equal to GPU_DEBUG_APP
- if (isDebuggable(context) || isProfileable(context) || (getCanLoadSystemLibraries() == 1)) {
+ if (isDebuggable(context) || (getCanLoadSystemLibraries() == 1)) {
final int enable = coreSettings.getInt(Settings.Global.ENABLE_GPU_DEBUG_LAYERS, 0);
@@ -473,9 +466,8 @@ public class GraphicsEnvironment {
*/
private String getAngleDebugPackage(Context context, Bundle coreSettings) {
final boolean appIsDebuggable = isDebuggable(context);
- final boolean appIsProfileable = isProfileable(context);
final boolean deviceIsDebuggable = getCanLoadSystemLibraries() == 1;
- if (appIsDebuggable || appIsProfileable || deviceIsDebuggable) {
+ if (appIsDebuggable || deviceIsDebuggable) {
String debugPackage;
if (coreSettings != null) {
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index de963c9927c2..fe2e948bfcd9 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -18,6 +18,7 @@ package android.os;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.text.TextUtils;
import android.util.ArrayMap;
@@ -2001,6 +2002,7 @@ public final class Parcel {
* @hide
*/
@UnsupportedAppUsage
+ @TestApi
public final int readExceptionCode() {
int code = readInt();
if (code == EX_HAS_REPLY_HEADER) {
diff --git a/core/java/android/os/SystemProperties.java b/core/java/android/os/SystemProperties.java
index edfdda8bb760..45384105cc8f 100644
--- a/core/java/android/os/SystemProperties.java
+++ b/core/java/android/os/SystemProperties.java
@@ -174,6 +174,7 @@ public class SystemProperties {
* @hide
*/
@SystemApi
+ @TestApi
public static boolean getBoolean(@NonNull String key, boolean def) {
if (TRACK_KEY_ACCESS) onKeyAccess(key);
return native_get_boolean(key, def);
diff --git a/core/java/android/os/image/DynamicSystemClient.java b/core/java/android/os/image/DynamicSystemClient.java
index f1f24fb4dd89..921f0f2ab1e2 100644
--- a/core/java/android/os/image/DynamicSystemClient.java
+++ b/core/java/android/os/image/DynamicSystemClient.java
@@ -22,6 +22,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -67,6 +68,7 @@ import java.util.concurrent.Executor;
* @hide
*/
@SystemApi
+@TestApi
public class DynamicSystemClient {
/** @hide */
@IntDef(prefix = { "STATUS_" }, value = {
@@ -283,6 +285,7 @@ public class DynamicSystemClient {
* @hide
*/
@SystemApi
+ @TestApi
public DynamicSystemClient(@NonNull Context context) {
mContext = context;
mConnection = new DynSystemServiceConnection();
@@ -314,8 +317,11 @@ public class DynamicSystemClient {
* Bind to {@code DynamicSystem} installation service. Binding to the installation service
* allows it to send status updates to {@link #OnStatusChangedListener}. It is recommanded
* to bind before calling {@link #start} and get status updates.
+ * @hide
*/
@RequiresPermission(android.Manifest.permission.INSTALL_DYNAMIC_SYSTEM)
+ @SystemApi
+ @TestApi
public void bind() {
if (!featureFlagEnabled()) {
Slog.w(TAG, FeatureFlagUtils.DYNAMIC_SYSTEM + " not enabled; bind() aborted.");
@@ -334,8 +340,11 @@ public class DynamicSystemClient {
/**
* Unbind from {@code DynamicSystem} installation service. Unbinding from the installation
* service stops it from sending following status updates.
+ * @hide
*/
@RequiresPermission(android.Manifest.permission.INSTALL_DYNAMIC_SYSTEM)
+ @SystemApi
+ @TestApi
public void unbind() {
if (!mBound) {
return;
@@ -367,8 +376,11 @@ public class DynamicSystemClient {
*
* @param systemUrl a network Uri, a file Uri or a content Uri pointing to a system image file.
* @param systemSize size of system image.
+ * @hide
*/
@RequiresPermission(android.Manifest.permission.INSTALL_DYNAMIC_SYSTEM)
+ @SystemApi
+ @TestApi
public void start(@NonNull Uri systemUrl, @BytesLong long systemSize) {
start(systemUrl, systemSize, DEFAULT_USERDATA_SIZE);
}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 66b9d168d71d..0db5c36eb961 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8081,6 +8081,15 @@ public final class Settings {
"lock_screen_show_silent_notifications";
/**
+ * Indicates whether snooze options should be shown on notifications
+ * <p>
+ * Type: int (0 for false, 1 for true)
+ *
+ * @hide
+ */
+ public static final String SHOW_NOTIFICATION_SNOOZE = "show_notification_snooze";
+
+ /**
* List of TV inputs that are currently hidden. This is a string
* containing the IDs of all hidden TV inputs. Each ID is encoded by
* {@link android.net.Uri#encode(String)} and separated by ':'.
@@ -8968,6 +8977,7 @@ public final class Settings {
LOCK_SCREEN_CUSTOM_CLOCK_FACE,
LOCK_SCREEN_SHOW_NOTIFICATIONS,
LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS,
+ SHOW_NOTIFICATION_SNOOZE,
ZEN_DURATION,
SHOW_ZEN_UPGRADE_NOTIFICATION,
SHOW_ZEN_SETTINGS_SUGGESTION,
@@ -9150,6 +9160,7 @@ public final class Settings {
VALIDATORS.put(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, BOOLEAN_VALIDATOR);
VALIDATORS.put(LOCK_SCREEN_SHOW_NOTIFICATIONS, BOOLEAN_VALIDATOR);
VALIDATORS.put(LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(SHOW_NOTIFICATION_SNOOZE, BOOLEAN_VALIDATOR);
VALIDATORS.put(ZEN_DURATION, ZEN_DURATION_VALIDATOR);
VALIDATORS.put(SHOW_ZEN_UPGRADE_NOTIFICATION, BOOLEAN_VALIDATOR);
VALIDATORS.put(SHOW_ZEN_SETTINGS_SUGGESTION, BOOLEAN_VALIDATOR);
diff --git a/core/java/android/service/notification/Adjustment.java b/core/java/android/service/notification/Adjustment.java
index e81ce7f85ac1..aa11445079cd 100644
--- a/core/java/android/service/notification/Adjustment.java
+++ b/core/java/android/service/notification/Adjustment.java
@@ -16,6 +16,7 @@
package android.service.notification;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.StringDef;
import android.annotation.SystemApi;
import android.annotation.TestApi;
@@ -48,6 +49,7 @@ public final class Adjustment implements Parcelable {
private final CharSequence mExplanation;
private final Bundle mSignals;
private final int mUser;
+ @Nullable private String mIssuer;
/** @hide */
@StringDef (prefix = { "KEY_" }, value = {
@@ -183,6 +185,7 @@ public final class Adjustment implements Parcelable {
}
mSignals = in.readBundle();
mUser = in.readInt();
+ mIssuer = in.readString();
}
public static final @android.annotation.NonNull Creator<Adjustment> CREATOR = new Creator<Adjustment>() {
@@ -251,6 +254,7 @@ public final class Adjustment implements Parcelable {
}
dest.writeBundle(mSignals);
dest.writeInt(mUser);
+ dest.writeString(mIssuer);
}
@Override
@@ -259,4 +263,14 @@ public final class Adjustment implements Parcelable {
+ "mSignals=" + mSignals
+ '}';
}
+
+ /** @hide */
+ public void setIssuer(@Nullable String issuer) {
+ mIssuer = issuer;
+ }
+
+ /** @hide */
+ public @Nullable String getIssuer() {
+ return mIssuer;
+ }
}
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index cafeb87691bd..12d3228e567d 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -236,6 +236,7 @@ public abstract class NotificationAssistantService extends NotificationListenerS
public final void adjustNotification(@NonNull Adjustment adjustment) {
if (!isBound()) return;
try {
+ setAdjustmentIssuer(adjustment);
getNotificationInterface().applyEnqueuedAdjustmentFromAssistant(mWrapper, adjustment);
} catch (android.os.RemoteException ex) {
Log.v(TAG, "Unable to contact notification manager", ex);
@@ -253,6 +254,9 @@ public abstract class NotificationAssistantService extends NotificationListenerS
public final void adjustNotifications(@NonNull List<Adjustment> adjustments) {
if (!isBound()) return;
try {
+ for (Adjustment adjustment : adjustments) {
+ setAdjustmentIssuer(adjustment);
+ }
getNotificationInterface().applyAdjustmentsFromAssistant(mWrapper, adjustments);
} catch (android.os.RemoteException ex) {
Log.v(TAG, "Unable to contact notification manager", ex);
@@ -366,6 +370,12 @@ public abstract class NotificationAssistantService extends NotificationListenerS
}
}
+ private void setAdjustmentIssuer(@Nullable Adjustment adjustment) {
+ if (adjustment != null) {
+ adjustment.setIssuer(getOpPackageName() + "/" + getClass().getName());
+ }
+ }
+
private final class MyHandler extends Handler {
public static final int MSG_ON_NOTIFICATION_ENQUEUED = 1;
public static final int MSG_ON_NOTIFICATION_SNOOZED = 2;
@@ -389,6 +399,7 @@ public abstract class NotificationAssistantService extends NotificationListenerS
NotificationChannel channel = (NotificationChannel) args.arg2;
args.recycle();
Adjustment adjustment = onNotificationEnqueued(sbn, channel);
+ setAdjustmentIssuer(adjustment);
if (adjustment != null) {
if (!isBound()) {
Log.w(TAG, "MSG_ON_NOTIFICATION_ENQUEUED: service not bound, skip.");
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index c42dc817bec4..324e02ceb1d5 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -16,6 +16,7 @@
package android.util;
+import android.annotation.TestApi;
import android.content.Context;
import android.os.SystemProperties;
import android.provider.Settings;
@@ -29,6 +30,7 @@ import java.util.Map;
*
* @hide
*/
+@TestApi
public class FeatureFlagUtils {
public static final String FFLAG_PREFIX = "sys.fflag.";
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 9436633c0c4b..73e0e4b2eb8b 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1301,7 +1301,7 @@ public abstract class Window {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public boolean shouldCloseOnTouch(Context context, MotionEvent event) {
final boolean isOutside =
- event.getAction() == MotionEvent.ACTION_DOWN && isOutOfBounds(context, event)
+ event.getAction() == MotionEvent.ACTION_UP && isOutOfBounds(context, event)
|| event.getAction() == MotionEvent.ACTION_OUTSIDE;
if (mCloseOnTouchOutside && peekDecorView() != null && isOutside) {
return true;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index cdbec293a96d..383d9b4e9c41 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -10578,7 +10578,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
// notifyAppeared was not sent.
// ContentCapture
- if (isLaidOut() && isImportantForContentCapture() && isTextEditable()) {
+ if (isLaidOut() && isImportantForContentCapture()) {
final ContentCaptureManager cm = mContext.getSystemService(ContentCaptureManager.class);
if (cm != null && cm.isContentCaptureEnabled()) {
final ContentCaptureSession session = getContentCaptureSession();
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index a88c51a28229..ee998371c941 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -185,7 +185,7 @@ public class ChooserActivity extends ResolverActivity {
private static final int SHARE_TARGET_QUERY_PACKAGE_LIMIT = 20;
private static final int QUERY_TARGET_SERVICE_LIMIT = 5;
- private static final int WATCHDOG_TIMEOUT_MILLIS = 3000;
+ private static final int WATCHDOG_TIMEOUT_MILLIS = 5000;
private static final int DEFAULT_SALT_EXPIRATION_DAYS = 7;
private int mMaxHashSaltDays = DeviceConfig.getInt(DeviceConfig.NAMESPACE_SYSTEMUI,
@@ -252,6 +252,123 @@ public class ChooserActivity extends ResolverActivity {
// Sorted list of DisplayResolveInfos for the alphabetical app section.
private List<ResolverActivity.DisplayResolveInfo> mSortedList = new ArrayList<>();
+ private ContentPreviewCoordinator mPreviewCoord;
+
+ private class ContentPreviewCoordinator {
+ private static final int IMAGE_LOAD_TIMEOUT_MILLIS = 300;
+ private static final int IMAGE_FADE_IN_MILLIS = 150;
+ private static final int IMAGE_LOAD_TIMEOUT = 1;
+ private static final int IMAGE_LOAD_INTO_VIEW = 2;
+
+ private final View mParentView;
+ private boolean mHideParentOnFail;
+ private boolean mAtLeastOneLoaded = false;
+
+ class LoadUriTask {
+ public final Uri mUri;
+ public final int mImageResourceId;
+ public final int mExtraCount;
+ public final Bitmap mBmp;
+
+ LoadUriTask(int imageResourceId, Uri uri, int extraCount, Bitmap bmp) {
+ this.mImageResourceId = imageResourceId;
+ this.mUri = uri;
+ this.mExtraCount = extraCount;
+ this.mBmp = bmp;
+ }
+ }
+
+ // If at least one image loads within the timeout period, allow other
+ // loads to continue. Otherwise terminate and optionally hide
+ // the parent area
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case IMAGE_LOAD_TIMEOUT:
+ maybeHideContentPreview();
+ break;
+
+ case IMAGE_LOAD_INTO_VIEW:
+ if (isFinishing()) break;
+
+ LoadUriTask task = (LoadUriTask) msg.obj;
+ RoundedRectImageView imageView = mParentView.findViewById(
+ task.mImageResourceId);
+ if (task.mBmp == null) {
+ imageView.setVisibility(View.GONE);
+ maybeHideContentPreview();
+ return;
+ }
+
+ mAtLeastOneLoaded = true;
+ imageView.setVisibility(View.VISIBLE);
+ imageView.setAlpha(0.0f);
+ imageView.setImageBitmap(task.mBmp);
+
+ ValueAnimator fadeAnim = ObjectAnimator.ofFloat(imageView, "alpha", 0.0f,
+ 1.0f);
+ fadeAnim.setInterpolator(new DecelerateInterpolator(1.0f));
+ fadeAnim.setDuration(IMAGE_FADE_IN_MILLIS);
+ fadeAnim.start();
+
+ if (task.mExtraCount > 0) {
+ imageView.setExtraImageCount(task.mExtraCount);
+ }
+ }
+ }
+ };
+
+ ContentPreviewCoordinator(View parentView, boolean hideParentOnFail) {
+ super();
+
+ this.mParentView = parentView;
+ this.mHideParentOnFail = hideParentOnFail;
+ }
+
+ private void loadUriIntoView(final int imageResourceId, final Uri uri,
+ final int extraImages) {
+ mHandler.sendEmptyMessageDelayed(IMAGE_LOAD_TIMEOUT, IMAGE_LOAD_TIMEOUT_MILLIS);
+
+ AsyncTask.THREAD_POOL_EXECUTOR.execute(() -> {
+ final Bitmap bmp = loadThumbnail(uri, new Size(200, 200));
+ final Message msg = Message.obtain();
+ msg.what = IMAGE_LOAD_INTO_VIEW;
+ msg.obj = new LoadUriTask(imageResourceId, uri, extraImages, bmp);
+ mHandler.sendMessage(msg);
+ });
+ }
+
+ private void cancelLoads() {
+ mHandler.removeMessages(IMAGE_LOAD_INTO_VIEW);
+ mHandler.removeMessages(IMAGE_LOAD_TIMEOUT);
+ }
+
+ private void maybeHideContentPreview() {
+ if (!mAtLeastOneLoaded && mHideParentOnFail) {
+ Log.i(TAG, "Hiding image preview area. Timed out waiting for preview to load"
+ + " within " + IMAGE_LOAD_TIMEOUT_MILLIS + "ms.");
+ collapseParentView();
+ if (mChooserRowAdapter != null) {
+ mChooserRowAdapter.hideContentPreview();
+ }
+ mHideParentOnFail = false;
+ }
+ }
+
+ private void collapseParentView() {
+ // This will effectively hide the content preview row by forcing the height
+ // to zero. It is faster than forcing a relayout of the listview
+ final View v = mParentView;
+ int widthSpec = MeasureSpec.makeMeasureSpec(v.getWidth(), MeasureSpec.EXACTLY);
+ int heightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.EXACTLY);
+ v.measure(widthSpec, heightSpec);
+ v.getLayoutParams().height = 0;
+ v.layout(v.getLeft(), v.getTop(), v.getRight(), v.getTop());
+ v.invalidate();
+ }
+ }
+
private final Handler mChooserHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
@@ -621,14 +738,15 @@ public class ChooserActivity extends ResolverActivity {
private ViewGroup displayContentPreview(@ContentPreviewType int previewType,
Intent targetIntent, LayoutInflater layoutInflater, ViewGroup convertView,
ViewGroup parent) {
+ if (convertView != null) return convertView;
+
switch (previewType) {
case CONTENT_PREVIEW_TEXT:
- return displayTextContentPreview(targetIntent, layoutInflater, convertView, parent);
+ return displayTextContentPreview(targetIntent, layoutInflater, parent);
case CONTENT_PREVIEW_IMAGE:
- return displayImageContentPreview(targetIntent, layoutInflater, convertView,
- parent);
+ return displayImageContentPreview(targetIntent, layoutInflater, parent);
case CONTENT_PREVIEW_FILE:
- return displayFileContentPreview(targetIntent, layoutInflater, convertView, parent);
+ return displayFileContentPreview(targetIntent, layoutInflater, parent);
default:
Log.e(TAG, "Unexpected content preview type: " + previewType);
}
@@ -637,10 +755,9 @@ public class ChooserActivity extends ResolverActivity {
}
private ViewGroup displayTextContentPreview(Intent targetIntent, LayoutInflater layoutInflater,
- ViewGroup convertView, ViewGroup parent) {
- ViewGroup contentPreviewLayout =
- convertView != null ? convertView : (ViewGroup) layoutInflater.inflate(
- R.layout.chooser_grid_preview_text, parent, false);
+ ViewGroup parent) {
+ ViewGroup contentPreviewLayout = (ViewGroup) layoutInflater.inflate(
+ R.layout.chooser_grid_preview_text, parent, false);
contentPreviewLayout.findViewById(R.id.copy_button).setOnClickListener(
this::onCopyButtonClicked);
@@ -677,12 +794,8 @@ public class ChooserActivity extends ResolverActivity {
if (previewThumbnail == null) {
previewThumbnailView.setVisibility(View.GONE);
} else {
- Bitmap bmp = loadThumbnail(previewThumbnail, new Size(100, 100));
- if (bmp == null) {
- previewThumbnailView.setVisibility(View.GONE);
- } else {
- previewThumbnailView.setImageBitmap(bmp);
- }
+ mPreviewCoord = new ContentPreviewCoordinator(contentPreviewLayout, false);
+ mPreviewCoord.loadUriIntoView(R.id.content_preview_thumbnail, previewThumbnail, 0);
}
}
@@ -690,15 +803,15 @@ public class ChooserActivity extends ResolverActivity {
}
private ViewGroup displayImageContentPreview(Intent targetIntent, LayoutInflater layoutInflater,
- ViewGroup convertView, ViewGroup parent) {
- ViewGroup contentPreviewLayout =
- convertView != null ? convertView : (ViewGroup) layoutInflater.inflate(
- R.layout.chooser_grid_preview_image, parent, false);
+ ViewGroup parent) {
+ ViewGroup contentPreviewLayout = (ViewGroup) layoutInflater.inflate(
+ R.layout.chooser_grid_preview_image, parent, false);
+ mPreviewCoord = new ContentPreviewCoordinator(contentPreviewLayout, true);
String action = targetIntent.getAction();
if (Intent.ACTION_SEND.equals(action)) {
Uri uri = targetIntent.getParcelableExtra(Intent.EXTRA_STREAM);
- loadUriIntoView(R.id.content_preview_image_1_large, uri, contentPreviewLayout);
+ mPreviewCoord.loadUriIntoView(R.id.content_preview_image_1_large, uri, 0);
} else {
ContentResolver resolver = getContentResolver();
@@ -717,21 +830,16 @@ public class ChooserActivity extends ResolverActivity {
return contentPreviewLayout;
}
- loadUriIntoView(R.id.content_preview_image_1_large, imageUris.get(0),
- contentPreviewLayout);
+ mPreviewCoord.loadUriIntoView(R.id.content_preview_image_1_large, imageUris.get(0), 0);
if (imageUris.size() == 2) {
- loadUriIntoView(R.id.content_preview_image_2_large, imageUris.get(1),
- contentPreviewLayout);
+ mPreviewCoord.loadUriIntoView(R.id.content_preview_image_2_large,
+ imageUris.get(1), 0);
} else if (imageUris.size() > 2) {
- loadUriIntoView(R.id.content_preview_image_2_small, imageUris.get(1),
- contentPreviewLayout);
- RoundedRectImageView imageView = loadUriIntoView(
- R.id.content_preview_image_3_small, imageUris.get(2), contentPreviewLayout);
-
- if (imageUris.size() > 3) {
- imageView.setExtraImageCount(imageUris.size() - 3);
- }
+ mPreviewCoord.loadUriIntoView(R.id.content_preview_image_2_small,
+ imageUris.get(1), 0);
+ mPreviewCoord.loadUriIntoView(R.id.content_preview_image_3_small,
+ imageUris.get(2), imageUris.size() - 3);
}
}
@@ -803,11 +911,10 @@ public class ChooserActivity extends ResolverActivity {
}
private ViewGroup displayFileContentPreview(Intent targetIntent, LayoutInflater layoutInflater,
- ViewGroup convertView, ViewGroup parent) {
+ ViewGroup parent) {
- ViewGroup contentPreviewLayout =
- convertView != null ? convertView : (ViewGroup) layoutInflater.inflate(
- R.layout.chooser_grid_preview_file, parent, false);
+ ViewGroup contentPreviewLayout = (ViewGroup) layoutInflater.inflate(
+ R.layout.chooser_grid_preview_file, parent, false);
// TODO(b/120417119): Disable file copy until after moving to sysui,
// due to permissions issues
@@ -839,6 +946,10 @@ public class ChooserActivity extends ResolverActivity {
R.id.content_preview_filename);
fileNameView.setText(fileName);
+ View thumbnailView = contentPreviewLayout.findViewById(
+ R.id.content_preview_file_thumbnail);
+ thumbnailView.setVisibility(View.GONE);
+
ImageView fileIconView = contentPreviewLayout.findViewById(
R.id.content_preview_file_icon);
fileIconView.setVisibility(View.VISIBLE);
@@ -849,32 +960,25 @@ public class ChooserActivity extends ResolverActivity {
return contentPreviewLayout;
}
- private void loadFileUriIntoView(Uri uri, View parent) {
+ private void loadFileUriIntoView(final Uri uri, final View parent) {
FileInfo fileInfo = extractFileInfo(uri, getContentResolver());
TextView fileNameView = parent.findViewById(R.id.content_preview_filename);
fileNameView.setText(fileInfo.name);
if (fileInfo.hasThumbnail) {
- loadUriIntoView(R.id.content_preview_file_thumbnail, uri, parent);
+ mPreviewCoord = new ContentPreviewCoordinator(parent, false);
+ mPreviewCoord.loadUriIntoView(R.id.content_preview_file_thumbnail, uri, 0);
} else {
+ View thumbnailView = parent.findViewById(R.id.content_preview_file_thumbnail);
+ thumbnailView.setVisibility(View.GONE);
+
ImageView fileIconView = parent.findViewById(R.id.content_preview_file_icon);
fileIconView.setVisibility(View.VISIBLE);
fileIconView.setImageResource(R.drawable.chooser_file_generic);
}
}
- private RoundedRectImageView loadUriIntoView(int imageResourceId, Uri uri, View parent) {
- RoundedRectImageView imageView = parent.findViewById(imageResourceId);
- Bitmap bmp = loadThumbnail(uri, new Size(200, 200));
- if (bmp != null) {
- imageView.setVisibility(View.VISIBLE);
- imageView.setImageBitmap(bmp);
- }
-
- return imageView;
- }
-
@VisibleForTesting
protected boolean isImageType(String mimeType) {
return mimeType != null && mimeType.startsWith("image/");
@@ -944,6 +1048,9 @@ public class ChooserActivity extends ResolverActivity {
mChooserHandler.removeMessages(CHOOSER_TARGET_SERVICE_RESULT);
mChooserHandler.removeMessages(SHORTCUT_MANAGER_SHARE_TARGET_RESULT);
mChooserHandler.removeMessages(SHORTCUT_MANAGER_SHARE_TARGET_RESULT_COMPLETED);
+
+ if (mPreviewCoord != null) mPreviewCoord.cancelLoads();
+
if (mAppPredictor != null) {
mAppPredictor.unregisterPredictionUpdates(mAppPredictorCallback);
mAppPredictor.destroy();
@@ -1327,6 +1434,22 @@ public class ChooserActivity extends ResolverActivity {
List<ShortcutManager.ShareShortcutInfo> resultList,
List<DisplayResolveInfo> driList,
@Nullable List<AppTarget> appTargets) {
+ if (appTargets != null && appTargets.size() != resultList.size()) {
+ throw new RuntimeException("resultList and appTargets must have the same size."
+ + " resultList.size()=" + resultList.size()
+ + " appTargets.size()=" + appTargets.size());
+ }
+
+ for (int i = resultList.size() - 1; i >= 0; i--) {
+ final String packageName = resultList.get(i).getTargetComponent().getPackageName();
+ if (!isPackageEnabled(packageName)) {
+ resultList.remove(i);
+ if (appTargets != null) {
+ appTargets.remove(i);
+ }
+ }
+ }
+
// Match ShareShortcutInfos with DisplayResolveInfos to be able to use the old code path
// for direct share targets. After ShareSheet is refactored we should use the
// ShareShortcutInfos directly.
@@ -1340,7 +1463,6 @@ public class ChooserActivity extends ResolverActivity {
ChooserTarget chooserTarget = convertToChooserTarget(shareShortcutInfo);
chooserTargets.add(chooserTarget);
if (mDirectShareAppTargetCache != null && appTargets != null) {
- // Note that appTargets.size() == resultList.size() is always true.
mDirectShareAppTargetCache.put(chooserTarget, appTargets.get(j));
}
}
@@ -1366,6 +1488,24 @@ public class ChooserActivity extends ResolverActivity {
mChooserHandler.sendMessage(msg);
}
+ private boolean isPackageEnabled(String packageName) {
+ if (TextUtils.isEmpty(packageName)) {
+ return false;
+ }
+ ApplicationInfo appInfo;
+ try {
+ appInfo = getPackageManager().getApplicationInfo(packageName, 0);
+ } catch (NameNotFoundException e) {
+ return false;
+ }
+
+ if (appInfo != null && appInfo.enabled
+ && (appInfo.flags & ApplicationInfo.FLAG_SUSPENDED) == 0) {
+ return true;
+ }
+ return false;
+ }
+
private ChooserTarget convertToChooserTarget(ShortcutManager.ShareShortcutInfo shareShortcut) {
ShortcutInfo shortcutInfo = shareShortcut.getShortcutInfo();
Bundle extras = new Bundle();
@@ -1496,7 +1636,8 @@ public class ChooserActivity extends ResolverActivity {
*/
@Nullable
private AppPredictor getAppPredictorForDirectShareIfEnabled() {
- return USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS ? getAppPredictor() : null;
+ return USE_PREDICTION_MANAGER_FOR_DIRECT_TARGETS && !ActivityManager.isLowRamDeviceStatic()
+ ? getAppPredictor() : null;
}
/**
@@ -2036,9 +2177,12 @@ public class ChooserActivity extends ResolverActivity {
}
int availableWidth = right - left - v.getPaddingLeft() - v.getPaddingRight();
- if (mChooserRowAdapter.calculateChooserTargetWidth(availableWidth)
+ if (mChooserRowAdapter.consumeLayoutRequest()
+ || mChooserRowAdapter.calculateChooserTargetWidth(availableWidth)
|| mAdapterView.getAdapter() == null) {
- mAdapterView.setAdapter(mChooserRowAdapter);
+ if (mAdapterView.getAdapter() == null) {
+ mAdapterView.setAdapter(mChooserRowAdapter);
+ }
getMainThreadHandler().post(() -> {
if (mResolverDrawerLayout == null || mChooserRowAdapter == null) {
@@ -2239,6 +2383,8 @@ public class ChooserActivity extends ResolverActivity {
@Override
public void onListRebuilt() {
+ updateAlphabeticalList();
+
// don't support direct share on low ram devices
if (ActivityManager.isLowRamDeviceStatic()) {
return;
@@ -2269,7 +2415,6 @@ public class ChooserActivity extends ResolverActivity {
queryTargetServices(this);
}
- updateAlphabeticalList();
}
@Override
@@ -2589,6 +2734,9 @@ public class ChooserActivity extends ResolverActivity {
private int mChooserTargetWidth = 0;
private boolean mShowAzLabelIfPoss;
+ private boolean mHideContentPreview = false;
+ private boolean mLayoutRequested = false;
+
private static final int VIEW_TYPE_DIRECT_SHARE = 0;
private static final int VIEW_TYPE_NORMAL = 1;
private static final int VIEW_TYPE_CONTENT_PREVIEW = 2;
@@ -2651,6 +2799,18 @@ public class ChooserActivity extends ResolverActivity {
return maxTargets;
}
+ public void hideContentPreview() {
+ mHideContentPreview = true;
+ mLayoutRequested = true;
+ notifyDataSetChanged();
+ }
+
+ public boolean consumeLayoutRequest() {
+ boolean oldValue = mLayoutRequested;
+ mLayoutRequested = false;
+ return oldValue;
+ }
+
@Override
public boolean areAllItemsEnabled() {
return false;
@@ -2684,7 +2844,8 @@ public class ChooserActivity extends ResolverActivity {
return 0;
}
- if (mChooserListAdapter == null || mChooserListAdapter.getCount() == 0) {
+ if (mHideContentPreview || mChooserListAdapter == null
+ || mChooserListAdapter.getCount() == 0) {
return 0;
}
@@ -2704,7 +2865,7 @@ public class ChooserActivity extends ResolverActivity {
// There can be at most one row in the listview, that is internally
// a ViewGroup with 2 rows
public int getServiceTargetRowCount() {
- if (isSendAction(getTargetIntent())) {
+ if (isSendAction(getTargetIntent()) && !ActivityManager.isLowRamDeviceStatic()) {
return 1;
}
return 0;
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 538c81d54129..0a01beba659f 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -383,9 +383,11 @@ public class ResolverActivity extends Activity {
mSystemWindowInsets.right, 0);
View emptyView = findViewById(R.id.empty);
- emptyView.setPadding(0, 0, 0, mSystemWindowInsets.bottom
- + getResources().getDimensionPixelSize(
- R.dimen.chooser_edge_margin_normal) * 2);
+ if (emptyView != null) {
+ emptyView.setPadding(0, 0, 0, mSystemWindowInsets.bottom
+ + getResources().getDimensionPixelSize(
+ R.dimen.chooser_edge_margin_normal) * 2);
+ }
if (mFooterSpacer == null) {
mFooterSpacer = new Space(getApplicationContext());
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index 14fe6ab7df1c..f1a1d44ea58b 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -113,5 +113,44 @@ public final class SystemUiDeviceConfigFlags {
*/
public static final String PROPERTY_PERMISSIONS_HUB_ENABLED = "permissions_hub_enabled";
+ // Flags related to Assistant Handles
+
+ /**
+ * (String) Which behavior mode for the Assistant Handles to use.
+ */
+ public static final String ASSIST_HANDLES_BEHAVIOR_MODE = "assist_handles_behavior_mode";
+
+ /**
+ * (long) How long, in milliseconds, to display Assist Handles when showing them temporarily.
+ */
+ public static final String ASSIST_HANDLES_SHOW_AND_GO_DURATION_MS =
+ "assist_handles_show_and_go_duration_ms";
+
+ /**
+ * (long) How long, in milliseconds, to wait before displaying Assist Handles temporarily after
+ * hiding them.
+ */
+ public static final String ASSIST_HANDLES_SHOWN_FREQUENCY_THRESHOLD_MS =
+ "assist_handles_shown_frequency_threshold_ms";
+ // Flag related to clock face
+
+ /**
+ * (String) Contains the clock plugin service names that are not allow to be shown.
+ * Each service name is seperated by a comma(",") in the string.
+ */
+ public static final String CLOCK_FACE_BLACKLIST = "clock_face_blacklist";
+
+ /**
+ * (long) How long, in milliseconds, for teaching behaviors to wait before considering the user
+ * taught.
+ */
+ public static final String ASSIST_HANDLES_LEARN_TIME_MS = "assist_handles_learn_time_ms";
+
+ /**
+ * (int) How many times for teaching behaviors to see the user perform an action to consider it
+ * taught.
+ */
+ public static final String ASSIST_HANDLES_LEARN_COUNT = "assist_handles_learn_count";
+
private SystemUiDeviceConfigFlags() { }
}
diff --git a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperationsRegistry.java b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperationsRegistry.java
index 1436aed5129a..049f952fceb8 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperationsRegistry.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodPrivilegedOperationsRegistry.java
@@ -132,4 +132,21 @@ public final class InputMethodPrivilegedOperationsRegistry {
}
}
}
+
+ /**
+ * Check the given IME token registration status.
+ *
+ * @param token IME token
+ * @return {@code true} when the IME token has already registered
+ * {@link InputMethodPrivilegedOperations}, {@code false} otherwise.
+ */
+ @AnyThread
+ public static boolean isRegistered(IBinder token) {
+ synchronized (sLock) {
+ if (sRegistry == null) {
+ return false;
+ }
+ return sRegistry.containsKey(token);
+ }
+ }
}
diff --git a/core/java/com/android/internal/net/VpnInfo.java b/core/java/com/android/internal/net/VpnInfo.java
index b1a412871bd2..e74af5eb50de 100644
--- a/core/java/com/android/internal/net/VpnInfo.java
+++ b/core/java/com/android/internal/net/VpnInfo.java
@@ -19,6 +19,8 @@ package com.android.internal.net;
import android.os.Parcel;
import android.os.Parcelable;
+import java.util.Arrays;
+
/**
* A lightweight container used to carry information of the ongoing VPN.
* Internal use only..
@@ -28,14 +30,14 @@ import android.os.Parcelable;
public class VpnInfo implements Parcelable {
public int ownerUid;
public String vpnIface;
- public String primaryUnderlyingIface;
+ public String[] underlyingIfaces;
@Override
public String toString() {
return "VpnInfo{"
+ "ownerUid=" + ownerUid
+ ", vpnIface='" + vpnIface + '\''
- + ", primaryUnderlyingIface='" + primaryUnderlyingIface + '\''
+ + ", underlyingIfaces='" + Arrays.toString(underlyingIfaces) + '\''
+ '}';
}
@@ -48,7 +50,7 @@ public class VpnInfo implements Parcelable {
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(ownerUid);
dest.writeString(vpnIface);
- dest.writeString(primaryUnderlyingIface);
+ dest.writeStringArray(underlyingIfaces);
}
public static final Parcelable.Creator<VpnInfo> CREATOR = new Parcelable.Creator<VpnInfo>() {
@@ -57,7 +59,7 @@ public class VpnInfo implements Parcelable {
VpnInfo info = new VpnInfo();
info.ownerUid = source.readInt();
info.vpnIface = source.readString();
- info.primaryUnderlyingIface = source.readString();
+ info.underlyingIfaces = source.readStringArray();
return info;
}
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index f9f28dabc694..daa63475f706 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -1301,18 +1301,6 @@ static void android_media_AudioTrack_set_delay_padding(JNIEnv *env, jobject thi
lpTrack->setParameters(param.toString());
}
-static void android_media_AudioTrack_set_eos(JNIEnv *env, jobject thiz) {
- sp<AudioTrack> lpTrack = getAudioTrack(env, thiz);
- if (lpTrack == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException",
- "AudioTrack not initialized");
- return;
- }
- AudioParameter param = AudioParameter();
- param.addInt(String8("EOS"), 1);
- lpTrack->setParameters(param.toString());
-}
-
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
static const JNINativeMethod gMethods[] = {
@@ -1389,7 +1377,6 @@ static const JNINativeMethod gMethods[] = {
{"native_setPresentation", "(II)I", (void *)android_media_AudioTrack_setPresentation},
{"native_getPortId", "()I", (void *)android_media_AudioTrack_get_port_id},
{"native_set_delay_padding", "(II)V", (void *)android_media_AudioTrack_set_delay_padding},
- {"native_set_eos", "()V", (void *)android_media_AudioTrack_set_eos},
};
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 00e0e3a74d70..08aa1d97fa1c 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -304,13 +304,19 @@ static void android_net_utils_resNetworkCancel(JNIEnv *env, jobject thiz, jobjec
jniSetFileDescriptorOfFD(env, javaFd, -1);
}
-static jint android_net_utils_getDnsNetId(JNIEnv *env, jobject thiz) {
- int dnsNetId = getNetworkForDns();
- if (dnsNetId < 0) {
- throwErrnoException(env, "getDnsNetId", -dnsNetId);
+static jobject android_net_utils_getDnsNetwork(JNIEnv *env, jobject thiz) {
+ unsigned dnsNetId = 0;
+ if (int res = getNetworkForDns(&dnsNetId) < 0) {
+ throwErrnoException(env, "getDnsNetId", -res);
+ return nullptr;
}
+ bool privateDnsBypass = dnsNetId & NETID_USE_LOCAL_NAMESERVERS;
- return dnsNetId;
+ static jclass class_Network = MakeGlobalRefOrDie(
+ env, FindClassOrDie(env, "android/net/Network"));
+ static jmethodID ctor = env->GetMethodID(class_Network, "<init>", "(IZ)V");
+ return env->NewObject(
+ class_Network, ctor, dnsNetId & ~NETID_USE_LOCAL_NAMESERVERS, privateDnsBypass);
}
static jobject android_net_utils_getTcpRepairWindow(JNIEnv *env, jobject thiz, jobject javaFd) {
@@ -369,7 +375,7 @@ static const JNINativeMethod gNetworkUtilMethods[] = {
{ "resNetworkQuery", "(ILjava/lang/String;III)Ljava/io/FileDescriptor;", (void*) android_net_utils_resNetworkQuery },
{ "resNetworkResult", "(Ljava/io/FileDescriptor;)Landroid/net/DnsResolver$DnsResponse;", (void*) android_net_utils_resNetworkResult },
{ "resNetworkCancel", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_resNetworkCancel },
- { "getDnsNetId", "()I", (void*) android_net_utils_getDnsNetId },
+ { "getDnsNetwork", "()Landroid/net/Network;", (void*) android_net_utils_getDnsNetwork },
};
int register_android_net_NetworkUtils(JNIEnv* env)
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index 69a7c4d80532..a67cb34e19dd 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -258,7 +258,7 @@ static void load_maps(int pid, stats_t* stats, bool* foundSwapPss)
} else if (base::StartsWith(name, "[anon:libc_malloc]")) {
which_heap = HEAP_NATIVE;
} else if (base::StartsWith(name, "[stack")) {
- which_heap = HEAP_NATIVE;
+ which_heap = HEAP_STACK;
} else if (base::EndsWith(name, ".so")) {
which_heap = HEAP_SO;
is_swappable = true;
diff --git a/core/proto/android/server/jobscheduler.proto b/core/proto/android/server/jobscheduler.proto
index 3f8ddff5327c..28733798b9ad 100644
--- a/core/proto/android/server/jobscheduler.proto
+++ b/core/proto/android/server/jobscheduler.proto
@@ -273,9 +273,11 @@ message ConstantsProto {
// The maximum number of jobs an app can run within this particular standby bucket's
// window size.
optional int32 max_job_count_rare = 11;
+ // The period of time used to rate limit recently run jobs.
+ optional int32 rate_limiting_window_ms = 19;
// The maximum number of jobs that should be allowed to run in the past
- // {@link QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS}.
- optional int32 max_job_count_per_allowed_time = 12;
+ // rate_limiting_window_ms.
+ optional int32 max_job_count_per_rate_limiting_window = 12;
// The maximum number of timing sessions an app can run within this particular standby
// bucket's window size.
optional int32 max_session_count_active = 13;
@@ -289,8 +291,8 @@ message ConstantsProto {
// bucket's window size.
optional int32 max_session_count_rare = 16;
// The maximum number of timing sessions that should be allowed to run in the past
- // {@link QUOTA_CONTROLLER_ALLOWED_TIME_PER_PERIOD_MS}.
- optional int32 max_session_count_per_allowed_time = 17;
+ // rate_limiting_window_ms.
+ optional int32 max_session_count_per_rate_limiting_window = 17;
// Treat two distinct {@link TimingSession}s as the same if they start and end within this
// amount of time of each other.
optional int64 timing_session_coalescing_duration_ms = 18;
@@ -517,63 +519,56 @@ message StateControllerProto {
optional int64 expiration_time_elapsed = 2;
optional int64 window_size_ms = 3;
- /** The total amount of time the app ran in its respective bucket window size. */
+ optional int32 job_count_limit = 14;
+ optional int32 session_count_limit = 15;
+
+ // The total amount of time the app ran in its respective bucket window size.
optional int64 execution_time_in_window_ms = 4;
optional int32 bg_job_count_in_window = 5;
- /**
- * The total amount of time the app ran in the last
- * {@link QuotaController#MAX_PERIOD_MS}.
- */
+ // The total amount of time the app ran in the last
+ // {@link QuotaController#MAX_PERIOD_MS}.
optional int64 execution_time_in_max_period_ms = 6;
optional int32 bg_job_count_in_max_period = 7;
- /**
- * The number of {@link TimingSession}s within the bucket window size. This will include
- * sessions that started before the window as long as they end within the window.
- */
+ // The number of {@link TimingSession}s within the bucket window size. This will include
+ // sessions that started before the window as long as they end within the window.
optional int32 session_count_in_window = 11;
- /**
- * The time after which the sum of all the app's sessions plus
- * ConstantsProto.QuotaController.in_quota_buffer_ms equals the quota. This is only
- * valid if
- * execution_time_in_window_ms >=
- * ConstantsProto.QuotaController.allowed_time_per_period_ms
- * or
- * execution_time_in_max_period_ms >=
- * ConstantsProto.QuotaController.max_execution_time_ms.
- */
- optional int64 quota_cutoff_time_elapsed = 8;
-
- /**
- * The time after which job_count_in_allowed_time should be considered invalid, in the
- * elapsed realtime timebase.
- */
+ // The time after which the app will be under the bucket quota. This is only valid if
+ // execution_time_in_window_ms >=
+ // ConstantsProto.QuotaController.allowed_time_per_period_ms
+ // or
+ // execution_time_in_max_period_ms >=
+ // ConstantsProto.QuotaController.max_execution_time_ms
+ // or
+ // bg_job_count_in_window >= job_count_limit
+ // or
+ // session_count_in_window >= session_count_limit.
+ optional int64 in_quota_time_elapsed = 8;
+
+ // The time after which job_count_in_rate_limiting_window should be considered invalid,
+ // in the elapsed realtime timebase.
optional int64 job_count_expiration_time_elapsed = 9;
- /**
- * The number of jobs that ran in at least the last
- * ConstantsProto.QuotaController.allowed_time_per_period_ms.
- * It may contain a few stale entries since cleanup won't happen exactly every
- * ConstantsProto.QuotaController.allowed_time_per_period_ms.
- */
- optional int32 job_count_in_allowed_time = 10;
-
- /**
- * The time after which {@link #timingSessionCountInAllowedTime} should be considered
- * invalid, in the elapsed realtime timebase.
- */
+ // The number of jobs that ran in at least the last
+ // ConstantsProto.QuotaController.rate_limiting_window_ms.
+ // It may contain a few stale entries since cleanup won't happen exactly every
+ // ConstantsProto.QuotaController.rate_limiting_window_ms. This should only be
+ // considered valid before elapsed realtime has reached
+ // job_count_expiration_time_elapsed.
+ optional int32 job_count_in_rate_limiting_window = 10;
+
+ // The time after which {@link #timingSessionCountInAllowedTime} should be considered
+ // invalid, in the elapsed realtime timebase.
optional int64 session_count_expiration_time_elapsed = 12;
- /**
- * The number of {@link TimingSession}s that ran in at least the last
- * {@link #mAllowedTimePerPeriodMs}. It may contain a few stale entries since cleanup won't
- * happen exactly every {@link #mAllowedTimePerPeriodMs}. This should only be considered
- * valid before elapsed realtime has reached
- * {@link #timingSessionCountExpirationTimeElapsed}.
- */
- optional int32 session_count_in_allowed_time = 13;
+ // The number of {@link TimingSession}s that ran in at least the last
+ // ConstantsProto.QuotaController.rate_limiting_window_ms. It may contain a few stale
+ // entries since cleanup won't happen exactly every
+ // ConstantsProto.QuotaController.rate_limiting_window_ms. This should only be considered
+ // valid before elapsed realtime has reached session_count_expiration_time_elapsed.
+ optional int32 session_count_in_rate_limiting_window = 13;
}
message Package {
diff --git a/core/proto/android/stats/location/location_enums.proto b/core/proto/android/stats/location/location_enums.proto
new file mode 100644
index 000000000000..553c01c5d0dd
--- /dev/null
+++ b/core/proto/android/stats/location/location_enums.proto
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+
+package android.stats.location;
+option java_outer_classname = "LocationStatsEnums";
+
+
+// APIs from LocationManagerService
+enum LocationManagerServiceApi {
+ API_UNKNOWN = 0;
+ API_REQUEST_LOCATION_UPDATES = 1;
+ API_ADD_GNSS_MEASUREMENTS_LISTENER = 2;
+ API_REGISTER_GNSS_STATUS_CALLBACK = 3;
+ API_REQUEST_GEOFENCE = 4;
+ API_SEND_EXTRA_COMMAND = 5;
+}
+
+enum UsageState {
+ USAGE_STARTED = 0;
+ USAGE_ENDED = 1;
+}
+
+// Type of location providers
+enum ProviderType {
+ PROVIDER_UNKNOWN = 0;
+ PROVIDER_NETWORK = 1;
+ PROVIDER_GPS = 2;
+ PROVIDER_PASSIVE = 3;
+ PROVIDER_FUSED = 4;
+}
+
+// Type of Callback passed in for this API
+enum CallbackType {
+ CALLBACK_UNKNOWN = 0;
+ // Current API does not need a callback, e.g. sendExtraCommand
+ CALLBACK_NOT_APPLICABLE = 1;
+ CALLBACK_LISTENER = 2;
+ CALLBACK_PENDING_INTENT = 3;
+}
+
+// Possible values for mQuality field in
+// frameworks/base/location/java/android/location/LocationRequest.java
+enum LocationRequestQuality {
+ QUALITY_UNKNOWN = 0;
+ ACCURACY_FINE = 100;
+ ACCURACY_BLOCK = 102;
+ ACCURACY_CITY = 104;
+ POWER_NONE = 200;
+ POWER_LOW = 201;
+ POWER_HIGH = 203;
+}
+
+// Bucketized values for interval field in
+// frameworks/base/location/java/android/location/LocationRequest.java
+enum LocationRequestIntervalBucket {
+ INTERVAL_UNKNOWN = 0;
+ INTERVAL_BETWEEN_0_SEC_AND_1_SEC = 1;
+ INTERVAL_BETWEEN_1_SEC_AND_5_SEC = 2;
+ INTERVAL_BETWEEN_5_SEC_AND_1_MIN = 3;
+ INTERVAL_BETWEEN_1_MIN_AND_10_MIN = 4;
+ INTERVAL_BETWEEN_10_MIN_AND_1_HOUR = 5;
+ INTERVAL_LARGER_THAN_1_HOUR = 6;
+}
+
+// Bucketized values for small displacement field in
+// frameworks/base/location/java/android/location/LocationRequest.java
+// Value in meters.
+enum SmallestDisplacementBucket {
+ DISTANCE_UNKNOWN = 0;
+ DISTANCE_ZERO = 1;
+ DISTANCE_BETWEEN_0_AND_100 = 2;
+ DISTANCE_LARGER_THAN_100 = 3;
+}
+
+// Bucketized values for expire_in field in
+// frameworks/base/location/java/android/location/LocationRequest.java
+enum ExpirationBucket {
+ EXPIRATION_UNKNOWN = 0;
+ EXPIRATION_BETWEEN_0_AND_20_SEC = 1;
+ EXPIRATION_BETWEEN_20_SEC_AND_1_MIN = 2;
+ EXPIRATION_BETWEEN_1_MIN_AND_10_MIN = 3;
+ EXPIRATION_BETWEEN_10_MIN_AND_1_HOUR = 4;
+ EXPIRATION_LARGER_THAN_1_HOUR = 5;
+ EXPIRATION_NO_EXPIRY = 6;
+}
+
+// Bucketized values for radius field in
+// frameworks/base/location/java/android/location/Geofence.java
+// Value in meters.
+enum GeofenceRadiusBucket {
+ RADIUS_UNKNOWN = 0;
+ RADIUS_BETWEEN_0_AND_100 = 1;
+ RADIUS_BETWEEN_100_AND_200 = 2;
+ RADIUS_BETWEEN_200_AND_300 = 3;
+ RADIUS_BETWEEN_300_AND_1000 = 4;
+ RADIUS_BETWEEN_1000_AND_10000 = 5;
+ RADIUS_LARGER_THAN_100000 = 6;
+ RADIUS_NEGATIVE = 7;
+}
+
+// Caller Activity Importance.
+enum ActivityImportance {
+ IMPORTANCE_UNKNOWN = 0;
+ IMPORTANCE_TOP = 1;
+ IMPORTANCE_FORGROUND_SERVICE = 2;
+ IMPORTANCE_BACKGROUND = 3;
+}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index ab7aed364401..890ad5e839f7 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2337,7 +2337,7 @@
The app can check whether it has this authorization by calling
{@link android.provider.Settings#canDrawOverlays
Settings.canDrawOverlays()}.
- <p>Protection level: signature -->
+ <p>Protection level: signature|preinstalled|appop|pre23|development -->
<permission android:name="android.permission.SYSTEM_ALERT_WINDOW"
android:label="@string/permlab_systemAlertWindow"
android:description="@string/permdesc_systemAlertWindow"
@@ -2522,7 +2522,7 @@
can check whether it has this authorization by calling {@link
android.provider.Settings.System#canWrite Settings.System.canWrite()}.
- <p>Protection level: signature
+ <p>Protection level: signature|preinstalled|appop|pre23
-->
<permission android:name="android.permission.WRITE_SETTINGS"
android:label="@string/permlab_writeSettings"
diff --git a/core/res/res/drawable/ic_audio_alarm.xml b/core/res/res/drawable/ic_audio_alarm.xml
index 96206ea3ce57..93f9f8f99cdc 100644
--- a/core/res/res/drawable/ic_audio_alarm.xml
+++ b/core/res/res/drawable/ic_audio_alarm.xml
@@ -14,8 +14,8 @@ Copyright (C) 2014 The Android Open Source Project
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="32.0dp"
- android:height="32.0dp"
+ android:width="24dp"
+ android:height="24dp"
android:viewportWidth="48.0"
android:viewportHeight="48.0"
android:tint="?attr/colorControlNormal">
diff --git a/core/res/res/drawable/ic_audio_alarm_mute.xml b/core/res/res/drawable/ic_audio_alarm_mute.xml
index 7f248c3b33e6..510a7c630fd2 100644
--- a/core/res/res/drawable/ic_audio_alarm_mute.xml
+++ b/core/res/res/drawable/ic_audio_alarm_mute.xml
@@ -14,8 +14,8 @@ Copyright (C) 2014 The Android Open Source Project
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="32.0dp"
- android:height="32.0dp"
+ android:width="24dp"
+ android:height="24dp"
android:viewportWidth="48.0"
android:viewportHeight="48.0"
android:tint="?attr/colorControlNormal">
diff --git a/core/res/res/drawable/ic_bluetooth_share_icon.xml b/core/res/res/drawable/ic_bluetooth_share_icon.xml
index 2152af55d5b6..6acfd57e669f 100644
--- a/core/res/res/drawable/ic_bluetooth_share_icon.xml
+++ b/core/res/res/drawable/ic_bluetooth_share_icon.xml
@@ -19,7 +19,7 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
- android:tint="@android:color/accent_device_default_light">
+ android:tint="@*android:color/accent_device_default_light">
<path
android:fillColor="@android:color/white"
diff --git a/core/res/res/drawable/ic_corp_badge.xml b/core/res/res/drawable/ic_corp_badge.xml
index 6a7ac4a20ff3..16df45290302 100644
--- a/core/res/res/drawable/ic_corp_badge.xml
+++ b/core/res/res/drawable/ic_corp_badge.xml
@@ -15,8 +15,8 @@ Copyright (C) 2018 The Android Open Source Project
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
+ android:width="24dp"
+ android:height="24dp"
android:tint="@*android:color/accent_device_default_light"
android:viewportWidth="24"
android:viewportHeight="24">
diff --git a/core/res/res/drawable/ic_file_copy.xml b/core/res/res/drawable/ic_file_copy.xml
index b6d5e7328c40..d05b55f1279f 100644
--- a/core/res/res/drawable/ic_file_copy.xml
+++ b/core/res/res/drawable/ic_file_copy.xml
@@ -16,9 +16,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
+ android:tint="@*android:color/material_grey_600"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M16,1L4,1c-1.1,0 -2,0.9 -2,2v14h2L4,3h12L16,1zM15,5l6,6v10c0,1.1 -0.9,2 -2,2L7.99,23C6.89,23 6,22.1 6,21l0.01,-14c0,-1.1 0.89,-2 1.99,-2h7zM14,12h5.5L14,6.5L14,12z"
- android:fillColor="#FF737373"/>
+ android:fillColor="@android:color/white"/>
</vector>
diff --git a/core/res/res/drawable/ic_qs_auto_rotate.xml b/core/res/res/drawable/ic_qs_auto_rotate.xml
index 47e1059fab44..8858e2b778bb 100644
--- a/core/res/res/drawable/ic_qs_auto_rotate.xml
+++ b/core/res/res/drawable/ic_qs_auto_rotate.xml
@@ -16,8 +16,8 @@
-->
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="48dp"
- android:width="48dp"
+ android:height="24dp"
+ android:width="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
diff --git a/core/res/res/drawable/ic_qs_battery_saver.xml b/core/res/res/drawable/ic_qs_battery_saver.xml
index 93975b61948e..6e1ced083ba7 100644
--- a/core/res/res/drawable/ic_qs_battery_saver.xml
+++ b/core/res/res/drawable/ic_qs_battery_saver.xml
@@ -15,8 +15,8 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:autoMirrored="true"
- android:width="32.0dp"
- android:height="32.0dp"
+ android:width="24dp"
+ android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?android:attr/colorControlNormal">
diff --git a/core/res/res/drawable/ic_qs_flashlight.xml b/core/res/res/drawable/ic_qs_flashlight.xml
index e63595300d5f..59b0ccd493dd 100644
--- a/core/res/res/drawable/ic_qs_flashlight.xml
+++ b/core/res/res/drawable/ic_qs_flashlight.xml
@@ -15,8 +15,8 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
+ android:width="24dp"
+ android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
diff --git a/core/res/res/drawable/perm_group_activity_recognition.xml b/core/res/res/drawable/perm_group_activity_recognition.xml
index 0ade6c674171..ef025acbcb0c 100644
--- a/core/res/res/drawable/perm_group_activity_recognition.xml
+++ b/core/res/res/drawable/perm_group_activity_recognition.xml
@@ -17,6 +17,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
diff --git a/core/res/res/drawable/perm_group_aural.xml b/core/res/res/drawable/perm_group_aural.xml
index b2737f24b86e..4b4c62cb73b6 100644
--- a/core/res/res/drawable/perm_group_aural.xml
+++ b/core/res/res/drawable/perm_group_aural.xml
@@ -16,6 +16,7 @@ Copyright (C) 2015 The Android Open Source Project
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
diff --git a/core/res/res/drawable/perm_group_calendar.xml b/core/res/res/drawable/perm_group_calendar.xml
index 4b46dd36e3b1..0dfb30150535 100644
--- a/core/res/res/drawable/perm_group_calendar.xml
+++ b/core/res/res/drawable/perm_group_calendar.xml
@@ -17,13 +17,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000000"
android:pathData="M19 4h-1V2h-2v2H8V2H6v2H5c-1.11 0-1.99 0.9 -1.99 2L3 20c0 1.1 0.89 2 2 2h14c1.1 0 2-0.9 2-2V6c0-1.1-0.9-2-2-2zm0 16H5V10h14v10zm-4.5-7c-1.38 0-2.5 1.12-2.5 2.5s1.12 2.5 2.5 2.5 2.5-1.12 2.5-2.5-1.12-2.5-2.5-2.5z" />
- <path
- android:pathData="M0 0h24v24H0V0z" />
-</vector> \ No newline at end of file
+</vector>
diff --git a/core/res/res/drawable/perm_group_call_log.xml b/core/res/res/drawable/perm_group_call_log.xml
index 0dfdbee4e600..a37ed88bebfc 100644
--- a/core/res/res/drawable/perm_group_call_log.xml
+++ b/core/res/res/drawable/perm_group_call_log.xml
@@ -18,6 +18,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
diff --git a/core/res/res/drawable/perm_group_camera.xml b/core/res/res/drawable/perm_group_camera.xml
index db7833f63faf..e65501c4efcc 100644
--- a/core/res/res/drawable/perm_group_camera.xml
+++ b/core/res/res/drawable/perm_group_camera.xml
@@ -17,6 +17,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
diff --git a/core/res/res/drawable/perm_group_contacts.xml b/core/res/res/drawable/perm_group_contacts.xml
index b834a27bac4b..dd6ae210181f 100644
--- a/core/res/res/drawable/perm_group_contacts.xml
+++ b/core/res/res/drawable/perm_group_contacts.xml
@@ -17,6 +17,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
diff --git a/core/res/res/drawable/perm_group_location.xml b/core/res/res/drawable/perm_group_location.xml
index a7fa52471ab4..a87fc0dc43df 100644
--- a/core/res/res/drawable/perm_group_location.xml
+++ b/core/res/res/drawable/perm_group_location.xml
@@ -17,6 +17,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
diff --git a/core/res/res/drawable/perm_group_microphone.xml b/core/res/res/drawable/perm_group_microphone.xml
index 9b532c1a7376..a1ed72510cf8 100644
--- a/core/res/res/drawable/perm_group_microphone.xml
+++ b/core/res/res/drawable/perm_group_microphone.xml
@@ -17,6 +17,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
diff --git a/core/res/res/drawable/perm_group_phone_calls.xml b/core/res/res/drawable/perm_group_phone_calls.xml
index 324d86492703..563222698b46 100644
--- a/core/res/res/drawable/perm_group_phone_calls.xml
+++ b/core/res/res/drawable/perm_group_phone_calls.xml
@@ -17,6 +17,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
@@ -25,4 +26,4 @@
.37 2.33 .57 3.57 .57 .55 0 1 .45 1 1V20c0 .55-.45 1-1 1-9.39 0-17-7.61-17-17
0-.55 .45 -1 1-1h3.5c.55 0 1 .45 1 1 0 1.25 .2 2.45 .57 3.57 .11 .35 .03 .74-.25
1.02l-2.2 2.2z" />
-</vector> \ No newline at end of file
+</vector>
diff --git a/core/res/res/drawable/perm_group_sensors.xml b/core/res/res/drawable/perm_group_sensors.xml
index e4663d7206fc..f800965b6058 100644
--- a/core/res/res/drawable/perm_group_sensors.xml
+++ b/core/res/res/drawable/perm_group_sensors.xml
@@ -17,6 +17,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
diff --git a/core/res/res/drawable/perm_group_sms.xml b/core/res/res/drawable/perm_group_sms.xml
index ebcf3d1fcd82..44ccdd6394e6 100644
--- a/core/res/res/drawable/perm_group_sms.xml
+++ b/core/res/res/drawable/perm_group_sms.xml
@@ -17,6 +17,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
diff --git a/core/res/res/drawable/perm_group_storage.xml b/core/res/res/drawable/perm_group_storage.xml
index 4b8965bd9ef8..fceda2b84885 100644
--- a/core/res/res/drawable/perm_group_storage.xml
+++ b/core/res/res/drawable/perm_group_storage.xml
@@ -17,6 +17,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
diff --git a/core/res/res/drawable/perm_group_visual.xml b/core/res/res/drawable/perm_group_visual.xml
index 9b21c279e30a..bf3edea74199 100644
--- a/core/res/res/drawable/perm_group_visual.xml
+++ b/core/res/res/drawable/perm_group_visual.xml
@@ -16,11 +16,10 @@ Copyright (C) 2015 The Android Open Source Project
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#000000"
android:pathData="M20,4v12H8V4H20 M20,2H8C6.9,2,6,2.9,6,4v12c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V4C22,2.9,21.1,2,20,2L20,2z M2,6v14 c0,1.1,0.9,2,2,2h14v-2H4V6H2z M15.67,11l-2.5,2.98L11.5,11.8L9,15h10L15.67,11z" />
- <path
- android:pathData="M0,0h24v24H0V0z" />
</vector>
diff --git a/core/res/res/layout/chooser_grid_preview_file.xml b/core/res/res/layout/chooser_grid_preview_file.xml
index 27c6041ba257..f7d60c91052d 100644
--- a/core/res/res/layout/chooser_grid_preview_file.xml
+++ b/core/res/res/layout/chooser_grid_preview_file.xml
@@ -44,8 +44,7 @@
android:adjustViewBounds="true"
android:layout_gravity="center_vertical"
android:gravity="center"
- android:scaleType="centerCrop"
- android:visibility="gone"/>
+ android:scaleType="centerCrop"/>
<ImageView
android:id="@+id/content_preview_file_icon"
android:layout_width="36dp"
diff --git a/core/res/res/layout/chooser_grid_preview_image.xml b/core/res/res/layout/chooser_grid_preview_image.xml
index ad31e0d0c194..79a0de4b271f 100644
--- a/core/res/res/layout/chooser_grid_preview_image.xml
+++ b/core/res/res/layout/chooser_grid_preview_image.xml
@@ -33,7 +33,6 @@
<view class="com.android.internal.app.ChooserActivity$RoundedRectImageView"
android:id="@+id/content_preview_image_1_large"
- android:visibility="gone"
android:layout_width="120dp"
android:layout_height="140dp"
android:layout_alignParentTop="true"
diff --git a/packages/SystemUI/res/values-mcc310-mnc030/config.xml b/core/res/res/values-mcc310-mnc030/config.xml
index 26b9192e0cc3..26b9192e0cc3 100644
--- a/packages/SystemUI/res/values-mcc310-mnc030/config.xml
+++ b/core/res/res/values-mcc310-mnc030/config.xml
diff --git a/packages/SystemUI/res/values-mcc310-mnc070/config.xml b/core/res/res/values-mcc310-mnc070/config.xml
index 26b9192e0cc3..26b9192e0cc3 100644
--- a/packages/SystemUI/res/values-mcc310-mnc070/config.xml
+++ b/core/res/res/values-mcc310-mnc070/config.xml
diff --git a/packages/SystemUI/res/values-mcc310-mnc170/config.xml b/core/res/res/values-mcc310-mnc170/config.xml
index 26b9192e0cc3..26b9192e0cc3 100644
--- a/packages/SystemUI/res/values-mcc310-mnc170/config.xml
+++ b/core/res/res/values-mcc310-mnc170/config.xml
diff --git a/packages/SystemUI/res/values-mcc310-mnc280/config.xml b/core/res/res/values-mcc310-mnc280/config.xml
index 26b9192e0cc3..26b9192e0cc3 100644
--- a/packages/SystemUI/res/values-mcc310-mnc280/config.xml
+++ b/core/res/res/values-mcc310-mnc280/config.xml
diff --git a/packages/SystemUI/res/values-mcc310-mnc380/config.xml b/core/res/res/values-mcc310-mnc380/config.xml
index 26b9192e0cc3..26b9192e0cc3 100644
--- a/packages/SystemUI/res/values-mcc310-mnc380/config.xml
+++ b/core/res/res/values-mcc310-mnc380/config.xml
diff --git a/core/res/res/values-mcc310-mnc410/config.xml b/core/res/res/values-mcc310-mnc410/config.xml
index 00ab7127c331..3fb3f0f7e9ff 100644
--- a/core/res/res/values-mcc310-mnc410/config.xml
+++ b/core/res/res/values-mcc310-mnc410/config.xml
@@ -48,4 +48,8 @@
<item>"#8"</item>
<item>"#9"</item>
</string-array>
+
+ <!-- Enable 5 bar signal strength icon -->
+ <bool name="config_inflateSignalStrength">true</bool>
+
</resources>
diff --git a/packages/SystemUI/res/values-mcc310-mnc410/config.xml b/core/res/res/values-mcc310-mnc560/config.xml
index 26b9192e0cc3..26b9192e0cc3 100644
--- a/packages/SystemUI/res/values-mcc310-mnc410/config.xml
+++ b/core/res/res/values-mcc310-mnc560/config.xml
diff --git a/packages/SystemUI/res/values-mcc310-mnc560/config.xml b/core/res/res/values-mcc310-mnc950/config.xml
index 26b9192e0cc3..26b9192e0cc3 100644
--- a/packages/SystemUI/res/values-mcc310-mnc560/config.xml
+++ b/core/res/res/values-mcc310-mnc950/config.xml
diff --git a/packages/SystemUI/res/values-mcc310-mnc950/config.xml b/core/res/res/values-mcc311-mnc180/config.xml
index 26b9192e0cc3..26b9192e0cc3 100644
--- a/packages/SystemUI/res/values-mcc310-mnc950/config.xml
+++ b/core/res/res/values-mcc311-mnc180/config.xml
diff --git a/core/res/res/values-mcc311-mnc480/config.xml b/core/res/res/values-mcc311-mnc480/config.xml
index db2f8d01f93a..336e30e45b00 100755
--- a/core/res/res/values-mcc311-mnc480/config.xml
+++ b/core/res/res/values-mcc311-mnc480/config.xml
@@ -40,4 +40,7 @@
<bool name="config_use_sim_language_file">true</bool>
+ <!-- Enable 5 bar signal strength icon -->
+ <bool name="config_inflateSignalStrength">true</bool>
+
</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 2de539721195..c8baa5578513 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1276,9 +1276,14 @@
meanings. -->
<integer name="config_defaultRingVibrationIntensity">2</integer>
+ <!-- Whether to use the strict phone number matcher by default. -->
<bool name="config_use_strict_phone_number_comparation">false</bool>
- <bool name="config_use_strict_phone_number_comparation_for_russian">true</bool>
+ <!-- Whether to use the strict phone number matcher in Russia. -->
+ <bool name="config_use_strict_phone_number_comparation_for_russia">true</bool>
+
+ <!-- Whether to use the strict phone number matcher in Kazakhstan. -->
+ <bool name="config_use_strict_phone_number_comparation_for_kazakhstan">true</bool>
<!-- Display low battery warning when battery level dips to this value.
Also, the battery stats are flushed to disk when we hit this level. -->
@@ -2311,7 +2316,7 @@
<!-- If the sensor that wakes up the lock screen is available or not. -->
<bool name="config_dozeWakeLockScreenSensorAvailable">false</bool>
- <integer name="config_dozeWakeLockScreenDebounce">1500</integer>
+ <integer name="config_dozeWakeLockScreenDebounce">300</integer>
<!-- Control whether the always on display mode is available. This should only be enabled on
devices where the display has been tuned to be power efficient in DOZE and/or DOZE_SUSPEND
@@ -3306,6 +3311,10 @@
(which normally prevents seamless rotation). -->
<bool name="config_allowSeamlessRotationDespiteNavBarMoving">false</bool>
+ <!-- Controls whether hints for gestural navigation are shown when the device is setup.
+ This should only be set when the device has gestural navigation enabled by default. -->
+ <bool name="config_showGesturalNavigationHints">false</bool>
+
<!-- Default insets [LEFT/RIGHTxTOP/BOTTOM] from the screen edge for picture-in-picture windows.
These values are in DPs and will be converted to pixel sizes internally. -->
<string translatable="false" name="config_defaultPictureInPictureScreenEdgeInsets">16x16</string>
@@ -3893,6 +3902,10 @@
{@see android.view.Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS} -->
<string name="config_secondaryHomeComponent" translatable="false">com.android.launcher3/com.android.launcher3.SecondaryDisplayLauncher</string>
+ <!-- Force secondary home launcher specified in config_secondaryHomeComponent always. If this is
+ not set, secondary home launcher can be replaced by user. -->
+ <bool name ="config_useSystemProvidedLauncherForSecondary">false</bool>
+
<!-- If device supports corner radius on windows.
This should be turned off on low-end devices to improve animation performance. -->
<bool name="config_supportsRoundedCornersOnWindows">true</bool>
@@ -4117,8 +4130,16 @@
<integer-array name="config_face_acquire_vendor_biometricprompt_ignorelist" translatable="false" >
</integer-array>
+ <!-- If face auth sends the user directly to home/last open app, or stays on keyguard -->
+ <bool name="config_faceAuthDismissesKeyguard">true</bool>
+
<!-- The component name for the default profile supervisor, which can be set as a profile owner
even after user setup is complete. The defined component should be used for supervision purposes
only. The component must be part of a system app. -->
<string name="config_defaultSupervisionProfileOwnerComponent" translatable="false"></string>
+
+ <!-- Whether to artificially interpret all signal strengths as
+ one bar higher than they actually are -->
+ <bool name="config_inflateSignalStrength">false</bool>
+
</resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index e0ab6c871700..5363ef920886 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -59,9 +59,7 @@
<!-- Height of the bottom navigation bar frame in landscape -->
<dimen name="navigation_bar_frame_height_landscape">@dimen/navigation_bar_frame_height</dimen>
- <!-- The height of the navigation gesture area; if the size is larger than the navigation bar
- frame width/height, then the difference is the spacing from the navigation bar window to
- the area that detects gestures. -->
+ <!-- The height of the navigation gesture area if the gesture is starting from the bottom. -->
<dimen name="navigation_bar_gesture_height">@dimen/navigation_bar_frame_height</dimen>
<!-- Height of the bottom navigation / system bar in car mode. -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6cdb3d67192c..0240cc5a588d 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -313,7 +313,8 @@
<java-symbol type="bool" name="config_ui_enableFadingMarquee" />
<java-symbol type="bool" name="config_enableHapticTextHandle" />
<java-symbol type="bool" name="config_use_strict_phone_number_comparation" />
- <java-symbol type="bool" name="config_use_strict_phone_number_comparation_for_russian" />
+ <java-symbol type="bool" name="config_use_strict_phone_number_comparation_for_russia" />
+ <java-symbol type="bool" name="config_use_strict_phone_number_comparation_for_kazakhstan" />
<java-symbol type="bool" name="config_single_volume" />
<java-symbol type="bool" name="config_voice_capable" />
<java-symbol type="bool" name="config_requireCallCapableAccountForHandle" />
@@ -2271,11 +2272,6 @@
<java-symbol type="anim" name="lock_screen_wallpaper_exit" />
<java-symbol type="anim" name="launch_task_behind_source" />
<java-symbol type="anim" name="wallpaper_open_exit" />
- <java-symbol type="anim" name="lock_to_error" />
- <java-symbol type="anim" name="lock_lock" />
- <java-symbol type="anim" name="lock_unlock" />
- <java-symbol type="anim" name="lock_in" />
- <java-symbol type="anim" name="lock_scanning" />
<java-symbol type="bool" name="config_alwaysUseCdmaRssi" />
<java-symbol type="dimen" name="status_bar_icon_size" />
@@ -2586,6 +2582,7 @@
<java-symbol type="array" name="config_face_acquire_vendor_keyguard_ignorelist" />
<java-symbol type="array" name="config_face_acquire_biometricprompt_ignorelist" />
<java-symbol type="array" name="config_face_acquire_vendor_biometricprompt_ignorelist" />
+ <java-symbol type="bool" name="config_faceAuthDismissesKeyguard" />
<!-- Face config -->
<java-symbol type="integer" name="config_faceMaxTemplatesPerUser" />
@@ -2880,6 +2877,7 @@
<java-symbol type="bool" name="config_allowSeamlessRotationDespiteNavBarMoving" />
<java-symbol type="dimen" name="config_backGestureInset" />
<java-symbol type="color" name="system_bar_background_semi_transparent" />
+ <java-symbol type="bool" name="config_showGesturalNavigationHints" />
<!-- EditText suggestion popup. -->
<java-symbol type="id" name="suggestionWindowContainer" />
@@ -3697,6 +3695,7 @@
<!-- For Secondary Launcher -->
<java-symbol type="string" name="config_secondaryHomeComponent" />
+ <java-symbol type="bool" name="config_useSystemProvidedLauncherForSecondary" />
<java-symbol type="string" name="battery_saver_notification_channel_name" />
<java-symbol type="string" name="battery_saver_sticky_disabled_notification_title" />
@@ -3797,4 +3796,5 @@
<java-symbol type="style" name="Animation.DeviceDefault.Activity.Resolver" />
<java-symbol type="string" name="config_defaultSupervisionProfileOwnerComponent" />
+ <java-symbol type="bool" name="config_inflateSignalStrength" />
</resources>
diff --git a/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java b/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java
index 1b6560322a13..707d7b30e09b 100644
--- a/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java
+++ b/core/tests/benchmarks/src/android/net/NetworkStatsBenchmark.java
@@ -19,13 +19,22 @@ package android.net;
import com.google.caliper.BeforeExperiment;
import com.google.caliper.Param;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
public class NetworkStatsBenchmark {
- private static final String UNDERLYING_IFACE = "wlan0";
+ private static final String[] UNDERLYING_IFACES = {"wlan0", "rmnet0"};
private static final String TUN_IFACE = "tun0";
private static final int TUN_UID = 999999999;
@Param({"100", "1000"})
private int mSize;
+ /**
+ * Should not be more than the length of {@link #UNDERLYING_IFACES}.
+ */
+ @Param({"1", "2"})
+ private int mNumUnderlyingIfaces;
private NetworkStats mNetworkStats;
@BeforeExperiment
@@ -33,8 +42,10 @@ public class NetworkStatsBenchmark {
mNetworkStats = new NetworkStats(0, mSize + 2);
int uid = 0;
NetworkStats.Entry recycle = new NetworkStats.Entry();
+ final List<String> allIfaces = getAllIfacesForBenchmark(); // also contains TUN_IFACE.
+ final int totalIfaces = allIfaces.size();
for (int i = 0; i < mSize; i++) {
- recycle.iface = (i < mSize / 2) ? TUN_IFACE : UNDERLYING_IFACE;
+ recycle.iface = allIfaces.get(i % totalIfaces);
recycle.uid = uid;
recycle.set = i % 2;
recycle.tag = NetworkStats.TAG_NONE;
@@ -48,22 +59,39 @@ public class NetworkStatsBenchmark {
uid++;
}
}
- recycle.iface = UNDERLYING_IFACE;
- recycle.uid = TUN_UID;
- recycle.set = NetworkStats.SET_FOREGROUND;
- recycle.tag = NetworkStats.TAG_NONE;
- recycle.rxBytes = 90000 * mSize;
- recycle.rxPackets = 40 * mSize;
- recycle.txBytes = 180000 * mSize;
- recycle.txPackets = 1200 * mSize;
- recycle.operations = 0;
- mNetworkStats.addValues(recycle);
+
+ for (int i = 0; i < mNumUnderlyingIfaces; i++) {
+ recycle.iface = UNDERLYING_IFACES[i];
+ recycle.uid = TUN_UID;
+ recycle.set = NetworkStats.SET_FOREGROUND;
+ recycle.tag = NetworkStats.TAG_NONE;
+ recycle.rxBytes = 90000 * mSize;
+ recycle.rxPackets = 40 * mSize;
+ recycle.txBytes = 180000 * mSize;
+ recycle.txPackets = 1200 * mSize;
+ recycle.operations = 0;
+ mNetworkStats.addValues(recycle);
+ }
+ }
+
+ private String[] getVpnUnderlyingIfaces() {
+ return Arrays.copyOf(UNDERLYING_IFACES, mNumUnderlyingIfaces);
+ }
+
+ /**
+ * Same as {@link #getVpnUnderlyingIfaces}, but also contains {@link #TUN_IFACE}.
+ */
+ private List<String> getAllIfacesForBenchmark() {
+ List<String> ifaces = new ArrayList<>();
+ ifaces.add(TUN_IFACE);
+ ifaces.addAll(Arrays.asList(getVpnUnderlyingIfaces()));
+ return ifaces;
}
public void timeMigrateTun(int reps) {
for (int i = 0; i < reps; i++) {
NetworkStats stats = mNetworkStats.clone();
- stats.migrateTun(TUN_UID, TUN_IFACE, UNDERLYING_IFACE);
+ stats.migrateTun(TUN_UID, TUN_IFACE, getVpnUnderlyingIfaces());
}
}
diff --git a/core/tests/coretests/res/values/overlayable_icons_test.xml b/core/tests/coretests/res/values/overlayable_icons_test.xml
index 68de2c0caf18..285db5005187 100644
--- a/core/tests/coretests/res/values/overlayable_icons_test.xml
+++ b/core/tests/coretests/res/values/overlayable_icons_test.xml
@@ -20,15 +20,18 @@
<array name="overlayable_icons">
<item>@*android:drawable/ic_audio_alarm</item>
<item>@*android:drawable/ic_audio_alarm_mute</item>
+ <item>@*android:drawable/ic_battery_80_24dp</item>
<item>@*android:drawable/ic_bluetooth_share_icon</item>
<item>@*android:drawable/ic_bt_headphones_a2dp</item>
<item>@*android:drawable/ic_bt_headset_hfp</item>
<item>@*android:drawable/ic_bt_hearing_aid</item>
<item>@*android:drawable/ic_bt_laptop</item>
+ <item>@*android:drawable/ic_bt_misc_hid</item>
<item>@*android:drawable/ic_bt_network_pan</item>
<item>@*android:drawable/ic_bt_pointing_hid</item>
<item>@*android:drawable/ic_corp_badge</item>
<item>@*android:drawable/ic_expand_more</item>
+ <item>@*android:drawable/ic_faster_emergency</item>
<item>@*android:drawable/ic_file_copy</item>
<item>@*android:drawable/ic_lock</item>
<item>@*android:drawable/ic_lock_bugreport</item>
@@ -36,6 +39,7 @@
<item>@*android:drawable/ic_lock_power_off</item>
<item>@*android:drawable/ic_lockscreen_ime</item>
<item>@*android:drawable/ic_mode_edit</item>
+ <item>@*android:drawable/ic_notifications_alerted</item>
<item>@*android:drawable/ic_phone</item>
<item>@*android:drawable/ic_qs_airplane</item>
<item>@*android:drawable/ic_qs_auto_rotate</item>
diff --git a/data/etc/car/Android.bp b/data/etc/car/Android.bp
index 37020fc8d79f..9272ea5e584b 100644
--- a/data/etc/car/Android.bp
+++ b/data/etc/car/Android.bp
@@ -31,6 +31,13 @@ prebuilt_etc {
}
prebuilt_etc {
+ name: "privapp_whitelist_android.car.cluster",
+ sub_dir: "permissions",
+ src: "android.car.cluster.xml",
+ filename_from_src: true,
+}
+
+prebuilt_etc {
name: "privapp_whitelist_android.car.usb.handler",
sub_dir: "permissions",
src: "android.car.usb.handler.xml",
diff --git a/data/etc/car/android.car.cluster.xml b/data/etc/car/android.car.cluster.xml
new file mode 100644
index 000000000000..d7f29da7a356
--- /dev/null
+++ b/data/etc/car/android.car.cluster.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<permissions>
+ <privapp-permissions package="android.car.cluster">
+ <permission name="android.permission.CONTROL_INCALL_EXPERIENCE"/>
+ <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+ <permission name="android.permission.MANAGE_USERS"/>
+ <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
+ </privapp-permissions>
+</permissions>
diff --git a/data/etc/car/com.android.car.xml b/data/etc/car/com.android.car.xml
index f1797deed075..19548bc404d1 100644
--- a/data/etc/car/com.android.car.xml
+++ b/data/etc/car/com.android.car.xml
@@ -24,6 +24,7 @@
<permission name="android.permission.PROVIDE_TRUST_AGENT"/>
<permission name="android.permission.REAL_GET_TASKS"/>
<permission name="android.permission.REBOOT"/>
+ <permission name="android.permission.READ_LOGS"/>
<permission name="android.permission.WRITE_SECURE_SETTINGS"/>
</privapp-permissions>
</permissions>
diff --git a/data/etc/car/com.google.android.car.kitchensink.xml b/data/etc/car/com.google.android.car.kitchensink.xml
index 6b26e8f3d5f2..d36a82684e9e 100644
--- a/data/etc/car/com.google.android.car.kitchensink.xml
+++ b/data/etc/car/com.google.android.car.kitchensink.xml
@@ -25,6 +25,7 @@
<permission name="android.permission.MODIFY_PHONE_STATE"/>
<permission name="android.permission.PROVIDE_TRUST_AGENT"/>
<permission name="android.permission.REAL_GET_TASKS"/>
+ <permission name="android.permission.READ_LOGS"/>
<permission name="android.permission.REBOOT"/>
<permission name="android.permission.WRITE_SECURE_SETTINGS"/>
</privapp-permissions>
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index b3856d501c72..a640122f2b32 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -196,6 +196,7 @@ applications that come with the platform
<permission name="android.permission.USE_RESERVED_DISK"/>
<permission name="android.permission.WRITE_MEDIA_STORAGE"/>
<permission name="android.permission.WATCH_APPOPS"/>
+ <permission name="android.permission.UPDATE_DEVICE_STATS"/>
</privapp-permissions>
<privapp-permissions package="com.android.providers.telephony">
diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java
index 98c990a71601..1fc056c3652f 100644
--- a/graphics/java/android/graphics/Outline.java
+++ b/graphics/java/android/graphics/Outline.java
@@ -273,8 +273,12 @@ public final class Outline {
}
/**
- * Sets the Constructs an Outline from a
+ * Sets the Outline to a
* {@link android.graphics.Path#isConvex() convex path}.
+ *
+ * @param convexPath used to construct the Outline. As of
+ * {@link android.os.Build.VERSION_CODES#Q}, it is no longer required to be
+ * convex.
*/
public void setConvexPath(@NonNull Path convexPath) {
if (convexPath.isEmpty()) {
@@ -282,10 +286,6 @@ public final class Outline {
return;
}
- if (!convexPath.isConvex()) {
- throw new IllegalArgumentException("path must be convex");
- }
-
if (mPath == null) {
mPath = new Path();
}
diff --git a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
index dbb79bcd5aea..e0304787142d 100644
--- a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
+++ b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
@@ -162,15 +162,15 @@ class KeyStoreCryptoOperationChunkedStreamer implements KeyStoreCryptoOperationS
}
if ((opResult.output != null) && (opResult.output.length > 0)) {
- if (inputLength > 0) {
+ if (inputLength + mBufferedLength > 0) {
// More output might be produced in this loop -- buffer the current output
if (bufferedOutput == null) {
bufferedOutput = new ByteArrayOutputStream();
- try {
- bufferedOutput.write(opResult.output);
- } catch (IOException e) {
- throw new ProviderException("Failed to buffer output", e);
- }
+ }
+ try {
+ bufferedOutput.write(opResult.output);
+ } catch (IOException e) {
+ throw new ProviderException("Failed to buffer output", e);
}
} else {
// No more output will be produced in this loop
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index 0a2894945dc8..16c8b8923074 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -161,8 +161,7 @@ void SkiaRecordingCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
// Recording Canvas draw operations: Bitmaps
// ----------------------------------------------------------------------------
-SkiaCanvas::PaintCoW&& SkiaRecordingCanvas::filterBitmap(PaintCoW&& paint,
- sk_sp<SkColorFilter> colorSpaceFilter) {
+SkiaCanvas::PaintCoW&& SkiaRecordingCanvas::filterBitmap(PaintCoW&& paint) {
bool fixBlending = false;
bool fixAA = false;
if (paint) {
@@ -172,23 +171,13 @@ SkiaCanvas::PaintCoW&& SkiaRecordingCanvas::filterBitmap(PaintCoW&& paint,
fixAA = paint->isAntiAlias();
}
- if (fixBlending || fixAA || colorSpaceFilter) {
+ if (fixBlending || fixAA) {
SkPaint& tmpPaint = paint.writeable();
if (fixBlending) {
tmpPaint.setBlendMode(SkBlendMode::kDstOut);
}
- if (colorSpaceFilter) {
- if (tmpPaint.getColorFilter()) {
- tmpPaint.setColorFilter(SkColorFilter::MakeComposeFilter(
- tmpPaint.refColorFilter(), std::move(colorSpaceFilter)));
- } else {
- tmpPaint.setColorFilter(std::move(colorSpaceFilter));
- }
- LOG_ALWAYS_FATAL_IF(!tmpPaint.getColorFilter());
- }
-
// disabling AA on bitmap draws matches legacy HWUI behavior
tmpPaint.setAntiAlias(false);
}
@@ -198,7 +187,7 @@ SkiaCanvas::PaintCoW&& SkiaRecordingCanvas::filterBitmap(PaintCoW&& paint,
void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const SkPaint* paint) {
sk_sp<SkImage> image = bitmap.makeImage();
- mRecorder.drawImage(image, left, top, filterPaint(paint), bitmap.palette());
+ mRecorder.drawImage(image, left, top, filterBitmap(paint), bitmap.palette());
// if image->unique() is true, then mRecorder.drawImage failed for some reason. It also means
// it is not safe to store a raw SkImage pointer, because the image object will be destroyed
// when this function ends.
@@ -212,7 +201,7 @@ void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, con
concat(matrix);
sk_sp<SkImage> image = bitmap.makeImage();
- mRecorder.drawImage(image, 0, 0, filterPaint(paint), bitmap.palette());
+ mRecorder.drawImage(image, 0, 0, filterBitmap(paint), bitmap.palette());
if (!bitmap.isImmutable() && image.get() && !image->unique()) {
mDisplayList->mMutableImages.push_back(image.get());
}
@@ -225,7 +214,7 @@ void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop
SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
sk_sp<SkImage> image = bitmap.makeImage();
- mRecorder.drawImageRect(image, srcRect, dstRect, filterPaint(paint),
+ mRecorder.drawImageRect(image, srcRect, dstRect, filterBitmap(paint),
SkCanvas::kFast_SrcRectConstraint, bitmap.palette());
if (!bitmap.isImmutable() && image.get() && !image->unique() && !srcRect.isEmpty() &&
!dstRect.isEmpty()) {
@@ -263,7 +252,7 @@ void SkiaRecordingCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& ch
filteredPaint.writeable().setFilterQuality(kLow_SkFilterQuality);
}
sk_sp<SkImage> image = bitmap.makeImage();
- mRecorder.drawImageLattice(image, lattice, dst, filterPaint(std::move(filteredPaint)),
+ mRecorder.drawImageLattice(image, lattice, dst, filterBitmap(std::move(filteredPaint)),
bitmap.palette());
if (!bitmap.isImmutable() && image.get() && !image->unique() && !dst.isEmpty()) {
mDisplayList->mMutableImages.push_back(image.get());
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
index afeccea3fb70..c42cea33211e 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
@@ -90,7 +90,7 @@ private:
*/
void initDisplayList(uirenderer::RenderNode* renderNode, int width, int height);
- PaintCoW&& filterBitmap(PaintCoW&& paint, sk_sp<SkColorFilter> colorSpaceFilter);
+ PaintCoW&& filterBitmap(PaintCoW&& paint);
};
} // namespace skiapipeline
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index dc3041fb4878..820d82dd3bd1 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -222,10 +222,10 @@ public final class AudioAttributes implements Parcelable {
public final static int SUPPRESSIBLE_MEDIA = 5;
/**
* @hide
- * Denotes a usage for all other sounds not caught in SUPPRESSIBLE_NOTIFICATION,
+ * Denotes a usage for sounds not caught in SUPPRESSIBLE_NOTIFICATION,
* SUPPRESSIBLE_CALL,SUPPRESSIBLE_NEVER, SUPPRESSIBLE_ALARM or SUPPRESSIBLE_MEDIA.
- * This includes system, sonification and unknown sounds.
- * These will be muted when the Zen priority mode doesn't allow sytem sounds
+ * This includes sonification sounds.
+ * These will be muted when the Zen priority mode doesn't allow system sounds
* @see #SUPPRESSIBLE_USAGES
*/
public final static int SUPPRESSIBLE_SYSTEM = 6;
@@ -248,6 +248,7 @@ public final class AudioAttributes implements Parcelable {
SUPPRESSIBLE_USAGES.put(USAGE_NOTIFICATION_EVENT, SUPPRESSIBLE_NOTIFICATION);
SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_ACCESSIBILITY, SUPPRESSIBLE_NEVER);
SUPPRESSIBLE_USAGES.put(USAGE_VOICE_COMMUNICATION, SUPPRESSIBLE_NEVER);
+ SUPPRESSIBLE_USAGES.put(USAGE_VOICE_COMMUNICATION_SIGNALLING, SUPPRESSIBLE_NEVER);
SUPPRESSIBLE_USAGES.put(USAGE_ALARM, SUPPRESSIBLE_ALARM);
SUPPRESSIBLE_USAGES.put(USAGE_MEDIA, SUPPRESSIBLE_MEDIA);
SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_NAVIGATION_GUIDANCE, SUPPRESSIBLE_MEDIA);
@@ -255,7 +256,6 @@ public final class AudioAttributes implements Parcelable {
SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANT, SUPPRESSIBLE_MEDIA);
/** default volume assignment is STREAM_MUSIC, handle unknown usage as media */
SUPPRESSIBLE_USAGES.put(USAGE_UNKNOWN, SUPPRESSIBLE_MEDIA);
- SUPPRESSIBLE_USAGES.put(USAGE_VOICE_COMMUNICATION_SIGNALLING, SUPPRESSIBLE_SYSTEM);
SUPPRESSIBLE_USAGES.put(USAGE_ASSISTANCE_SONIFICATION, SUPPRESSIBLE_SYSTEM);
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 2541982e5a5a..2d6cd242c702 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -4274,38 +4274,6 @@ public class AudioManager {
}
}
- /**
- * Indicate A2DP source or sink active device change and eventually suppress
- * the {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent.
- * This operation is asynchronous but its execution will still be sequentially scheduled
- * relative to calls to {@link #setBluetoothHearingAidDeviceConnectionState(BluetoothDevice,
- * int, boolean, int)} and
- * {@link #handleBluetoothA2dpDeviceConfigChange(BluetoothDevice)}.
- * @param device Bluetooth device connected/disconnected
- * @param state new connection state (BluetoothProfile.STATE_xxx)
- * @param profile profile for the A2DP device
- * (either {@link android.bluetooth.BluetoothProfile.A2DP} or
- * {@link android.bluetooth.BluetoothProfile.A2DP_SINK})
- * @param a2dpVolume New volume for the connecting device. Does nothing if
- * disconnecting. Pass value -1 in case you want this field to be ignored
- * @param suppressNoisyIntent if true the
- * {@link AudioManager.ACTION_AUDIO_BECOMING_NOISY} intent will not be sent.
- * @return a delay in ms that the caller should wait before broadcasting
- * BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED intent.
- * {@hide}
- */
- public void handleBluetoothA2dpActiveDeviceChange(
- BluetoothDevice device, int state, int profile,
- boolean suppressNoisyIntent, int a2dpVolume) {
- final IAudioService service = getService();
- try {
- service.handleBluetoothA2dpActiveDeviceChange(device,
- state, profile, suppressNoisyIntent, a2dpVolume);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
-
/** {@hide} */
public IRingtonePlayer getRingtonePlayer() {
try {
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index d9d614f7ead4..e29e5698439d 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -101,6 +101,20 @@ public class AudioTrack extends PlayerBase
public static final int PLAYSTATE_PAUSED = 2; // matches SL_PLAYSTATE_PAUSED
/** indicates AudioTrack state is playing */
public static final int PLAYSTATE_PLAYING = 3; // matches SL_PLAYSTATE_PLAYING
+ /**
+ * @hide
+ * indicates AudioTrack state is stopping waiting for NATIVE_EVENT_STREAM_END to
+ * transition to PLAYSTATE_STOPPED.
+ * Only valid for offload mode.
+ */
+ private static final int PLAYSTATE_STOPPING = 4;
+ /**
+ * @hide
+ * indicates AudioTrack state is paused from stopping state. Will transition to
+ * PLAYSTATE_STOPPING if play() is called.
+ * Only valid for offload mode.
+ */
+ private static final int PLAYSTATE_PAUSED_STOPPING = 5;
// keep these values in sync with android_media_AudioTrack.cpp
/**
@@ -303,6 +317,14 @@ public class AudioTrack extends PlayerBase
* One of PLAYSTATE_STOPPED, PLAYSTATE_PAUSED, or PLAYSTATE_PLAYING.
*/
private int mPlayState = PLAYSTATE_STOPPED;
+
+ /**
+ * Indicates that we are expecting an end of stream callback following a call
+ * to setOffloadEndOfStream() in a gapless track transition context. The native track
+ * will be restarted automatically.
+ */
+ private boolean mOffloadEosPending = false;
+
/**
* Lock to ensure mPlayState updates reflect the actual state of the object.
*/
@@ -1073,6 +1095,10 @@ public class AudioTrack extends PlayerBase
* Declares that the last write() operation on this track provided the last buffer of this
* stream.
* After the end of stream, previously set padding and delay values are ignored.
+ * Can only be called only if the AudioTrack is opened in offload mode
+ * {@see Builder#setOffloadedPlayback(boolean)}.
+ * Can only be called only if the AudioTrack is in state {@link #PLAYSTATE_PLAYING}
+ * {@see #getPlaystate()}.
* Use this method in the same thread as any write() operation.
*/
public void setOffloadEndOfStream() {
@@ -1082,7 +1108,20 @@ public class AudioTrack extends PlayerBase
if (mState == STATE_UNINITIALIZED) {
throw new IllegalStateException("Uninitialized track");
}
- native_set_eos();
+ if (mPlayState != PLAYSTATE_PLAYING) {
+ throw new IllegalStateException("EOS not supported if not playing");
+ }
+ synchronized (mStreamEventCbLock) {
+ if (mStreamEventCbInfoList.size() == 0) {
+ throw new IllegalStateException("EOS not supported without StreamEventCallback");
+ }
+ }
+
+ synchronized (mPlayStateLock) {
+ native_stop();
+ mOffloadEosPending = true;
+ mPlayState = PLAYSTATE_STOPPING;
+ }
}
/**
@@ -1366,7 +1405,11 @@ public class AudioTrack extends PlayerBase
}
baseRelease();
native_release();
- mState = STATE_UNINITIALIZED;
+ synchronized (mPlayStateLock) {
+ mState = STATE_UNINITIALIZED;
+ mPlayState = PLAYSTATE_STOPPED;
+ mPlayStateLock.notify();
+ }
}
@Override
@@ -1525,7 +1568,14 @@ public class AudioTrack extends PlayerBase
*/
public int getPlayState() {
synchronized (mPlayStateLock) {
- return mPlayState;
+ switch (mPlayState) {
+ case PLAYSTATE_STOPPING:
+ return PLAYSTATE_PLAYING;
+ case PLAYSTATE_PAUSED_STOPPING:
+ return PLAYSTATE_PAUSED;
+ default:
+ return mPlayState;
+ }
}
}
@@ -2260,7 +2310,12 @@ public class AudioTrack extends PlayerBase
synchronized(mPlayStateLock) {
baseStart();
native_start();
- mPlayState = PLAYSTATE_PLAYING;
+ if (mPlayState == PLAYSTATE_PAUSED_STOPPING) {
+ mPlayState = PLAYSTATE_STOPPING;
+ } else {
+ mPlayState = PLAYSTATE_PLAYING;
+ mOffloadEosPending = false;
+ }
}
}
@@ -2282,9 +2337,15 @@ public class AudioTrack extends PlayerBase
synchronized(mPlayStateLock) {
native_stop();
baseStop();
- mPlayState = PLAYSTATE_STOPPED;
- mAvSyncHeader = null;
- mAvSyncBytesRemaining = 0;
+ if (mOffloaded && mPlayState != PLAYSTATE_PAUSED_STOPPING) {
+ mPlayState = PLAYSTATE_STOPPING;
+ } else {
+ mPlayState = PLAYSTATE_STOPPED;
+ mOffloadEosPending = false;
+ mAvSyncHeader = null;
+ mAvSyncBytesRemaining = 0;
+ mPlayStateLock.notify();
+ }
}
}
@@ -2305,7 +2366,11 @@ public class AudioTrack extends PlayerBase
synchronized(mPlayStateLock) {
native_pause();
basePause();
- mPlayState = PLAYSTATE_PAUSED;
+ if (mPlayState == PLAYSTATE_STOPPING) {
+ mPlayState = PLAYSTATE_PAUSED_STOPPING;
+ } else {
+ mPlayState = PLAYSTATE_PAUSED;
+ }
}
}
@@ -2434,6 +2499,9 @@ public class AudioTrack extends PlayerBase
return ERROR_BAD_VALUE;
}
+ if (!blockUntilOffloadDrain(writeMode)) {
+ return 0;
+ }
final int ret = native_write_byte(audioData, offsetInBytes, sizeInBytes, mAudioFormat,
writeMode == WRITE_BLOCKING);
@@ -2544,6 +2612,10 @@ public class AudioTrack extends PlayerBase
return ERROR_BAD_VALUE;
}
+ if (!blockUntilOffloadDrain(writeMode)) {
+ return 0;
+ }
+
final int ret = native_write_short(audioData, offsetInShorts, sizeInShorts, mAudioFormat,
writeMode == WRITE_BLOCKING);
@@ -2632,6 +2704,10 @@ public class AudioTrack extends PlayerBase
return ERROR_BAD_VALUE;
}
+ if (!blockUntilOffloadDrain(writeMode)) {
+ return 0;
+ }
+
final int ret = native_write_float(audioData, offsetInFloats, sizeInFloats, mAudioFormat,
writeMode == WRITE_BLOCKING);
@@ -2706,6 +2782,10 @@ public class AudioTrack extends PlayerBase
return ERROR_BAD_VALUE;
}
+ if (!blockUntilOffloadDrain(writeMode)) {
+ return 0;
+ }
+
int ret = 0;
if (audioData.isDirect()) {
ret = native_write_native_bytes(audioData,
@@ -2790,6 +2870,10 @@ public class AudioTrack extends PlayerBase
return ERROR_BAD_VALUE;
}
+ if (!blockUntilOffloadDrain(writeMode)) {
+ return 0;
+ }
+
// create timestamp header if none exists
if (mAvSyncHeader == null) {
mAvSyncHeader = ByteBuffer.allocate(mOffset);
@@ -2859,6 +2943,25 @@ public class AudioTrack extends PlayerBase
return native_reload_static();
}
+ /**
+ * When an AudioTrack in offload mode is in STOPPING play state, wait until event STREAM_END is
+ * received if blocking write or return with 0 frames written if non blocking mode.
+ */
+ private boolean blockUntilOffloadDrain(int writeMode) {
+ synchronized (mPlayStateLock) {
+ while (mPlayState == PLAYSTATE_STOPPING || mPlayState == PLAYSTATE_PAUSED_STOPPING) {
+ if (writeMode == WRITE_NON_BLOCKING) {
+ return false;
+ }
+ try {
+ mPlayStateLock.wait();
+ } catch (InterruptedException e) {
+ }
+ }
+ return true;
+ }
+ }
+
//--------------------------------------------------------------------------
// Audio effects management
//--------------------
@@ -3293,6 +3396,22 @@ public class AudioTrack extends PlayerBase
public void handleMessage(Message msg) {
final LinkedList<StreamEventCbInfo> cbInfoList;
synchronized (mStreamEventCbLock) {
+ if (msg.what == NATIVE_EVENT_STREAM_END) {
+ synchronized (mPlayStateLock) {
+ if (mPlayState == PLAYSTATE_STOPPING) {
+ if (mOffloadEosPending) {
+ native_start();
+ mPlayState = PLAYSTATE_PLAYING;
+ } else {
+ mAvSyncHeader = null;
+ mAvSyncBytesRemaining = 0;
+ mPlayState = PLAYSTATE_STOPPED;
+ }
+ mOffloadEosPending = false;
+ mPlayStateLock.notify();
+ }
+ }
+ }
if (mStreamEventCbInfoList.size() == 0) {
return;
}
@@ -3560,7 +3679,6 @@ public class AudioTrack extends PlayerBase
private native int native_getPortId();
private native void native_set_delay_padding(int delayInFrames, int paddingInFrames);
- private native void native_set_eos();
//---------------------------------------------------------
// Utility methods
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index 58c6be9be4c7..5645ba5d7dac 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -1794,15 +1794,13 @@ public class ExifInterface {
// Set thumbnail image offset and length
setThumbnailData(inputStream);
mIsSupportedFile = true;
- } catch (IOException e) {
+ } catch (IOException | OutOfMemoryError e) {
// Ignore exceptions in order to keep the compatibility with the old versions of
// ExifInterface.
mIsSupportedFile = false;
- if (DEBUG) {
- Log.d(TAG, "Invalid image: ExifInterface got an unsupported image format file"
- + "(ExifInterface supports JPEG and some RAW image formats only) "
- + "or a corrupted JPEG file to ExifInterface.", e);
- }
+ Log.w(TAG, "Invalid image: ExifInterface got an unsupported image format file"
+ + "(ExifInterface supports JPEG and some RAW image formats only) "
+ + "or a corrupted JPEG file to ExifInterface.", e);
} finally {
addDefaultValuesForCompatibility();
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index a790441aa36e..71f52a1b7d8e 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -178,9 +178,6 @@ interface IAudioService {
void handleBluetoothA2dpDeviceConfigChange(in BluetoothDevice device);
- void handleBluetoothA2dpActiveDeviceChange(in BluetoothDevice device,
- int state, int profile, boolean suppressNoisyIntent, int a2dpVolume);
-
@UnsupportedAppUsage
AudioRoutesInfo startWatchingRoutes(in IAudioRoutesObserver observer);
diff --git a/media/java/android/media/MediaFile.java b/media/java/android/media/MediaFile.java
index 710b503d97fd..0b1ae34dccc4 100644
--- a/media/java/android/media/MediaFile.java
+++ b/media/java/android/media/MediaFile.java
@@ -220,7 +220,6 @@ public class MediaFile {
case "audio/mpegurl":
case "application/x-mpegurl":
case "application/vnd.apple.mpegurl":
- case "video/x-ms-asf":
case "audio/x-scpls":
return true;
default:
diff --git a/media/java/android/media/MediaHTTPConnection.java b/media/java/android/media/MediaHTTPConnection.java
index b5c4cca12ff7..8ee929e77899 100644
--- a/media/java/android/media/MediaHTTPConnection.java
+++ b/media/java/android/media/MediaHTTPConnection.java
@@ -38,6 +38,7 @@ import java.net.URL;
import java.net.UnknownServiceException;
import java.util.HashMap;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
/** @hide */
public class MediaHTTPConnection extends IMediaHTTPConnection.Stub {
@@ -83,6 +84,10 @@ public class MediaHTTPConnection extends IMediaHTTPConnection.Stub {
private final static int HTTP_TEMP_REDIRECT = 307;
private final static int MAX_REDIRECTS = 20;
+ // The number of threads that are currently running disconnect() (possibly
+ // not yet holding the synchronized lock).
+ private final AtomicInteger mNumDisconnectingThreads = new AtomicInteger(0);
+
@UnsupportedAppUsage
public MediaHTTPConnection() {
CookieHandler cookieHandler = CookieHandler.getDefault();
@@ -155,19 +160,24 @@ public class MediaHTTPConnection extends IMediaHTTPConnection.Stub {
@Override
@UnsupportedAppUsage
public void disconnect() {
- HttpURLConnection connectionToDisconnect = mConnection;
- // Call disconnect() before blocking for the lock in order to ensure that any
- // other thread that is blocked in readAt() will return quickly.
- if (connectionToDisconnect != null) {
- connectionToDisconnect.disconnect();
- }
- synchronized (this) {
- // It's unlikely but possible that while we were waiting to acquire the lock, another
- // thread concurrently started a new connection; if so, we're disconnecting that one
- // here, too.
- teardownConnection();
- mHeaders = null;
- mURL = null;
+ mNumDisconnectingThreads.incrementAndGet();
+ try {
+ HttpURLConnection connectionToDisconnect = mConnection;
+ // Call disconnect() before blocking for the lock in order to ensure that any
+ // other thread that is blocked in readAt() will return quickly.
+ if (connectionToDisconnect != null) {
+ connectionToDisconnect.disconnect();
+ }
+ synchronized (this) {
+ // It's possible that while we were waiting to acquire the lock, another thread
+ // concurrently started a new connection; if so, we're disconnecting that one
+ // here, too.
+ teardownConnection();
+ mHeaders = null;
+ mURL = null;
+ }
+ } finally {
+ mNumDisconnectingThreads.decrementAndGet();
}
}
@@ -224,11 +234,36 @@ public class MediaHTTPConnection extends IMediaHTTPConnection.Stub {
boolean noProxy = isLocalHost(url);
while (true) {
+ // If another thread is concurrently disconnect()ing, there's a race
+ // between them and us. Therefore, we check mNumDisconnectingThreads shortly
+ // (not atomically) before & after writing mConnection. This guarantees that
+ // we won't "lose" a disconnect by creating a new connection that might
+ // miss the disconnect.
+ //
+ // Note that throwing an instanceof IOException is also what this thread
+ // would have done if another thread disconnect()ed the connection while
+ // this thread was blocked reading from that connection further down in this
+ // loop.
+ if (mNumDisconnectingThreads.get() > 0) {
+ throw new IOException("concurrently disconnecting");
+ }
if (noProxy) {
mConnection = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY);
} else {
mConnection = (HttpURLConnection)url.openConnection();
}
+ // If another thread is concurrently disconnecting, throwing IOException will
+ // cause us to release the lock, giving the other thread a chance to acquire
+ // it. It also ensures that the catch block will run, which will tear down
+ // the connection even if the other thread happens to already be on its way
+ // out of disconnect().
+ if (mNumDisconnectingThreads.get() > 0) {
+ throw new IOException("concurrently disconnecting");
+ }
+ // If we get here without having thrown, we know that other threads
+ // will see our write to mConnection. Any disconnect() on that mConnection
+ // instance will cause our read from/write to that connection instance below
+ // to encounter an instanceof IOException.
mConnection.setConnectTimeout(CONNECT_TIMEOUT_MS);
// handle redirects ourselves if we do not allow cross-domain redirect
diff --git a/media/java/android/media/MediaMetadataRetriever.java b/media/java/android/media/MediaMetadataRetriever.java
index 112ce1dd1acc..c43b78cf4fc7 100644
--- a/media/java/android/media/MediaMetadataRetriever.java
+++ b/media/java/android/media/MediaMetadataRetriever.java
@@ -869,7 +869,7 @@ public class MediaMetadataRetriever implements AutoCloseable {
* This key retrieves the location information, if available.
* The location should be specified according to ISO-6709 standard, under
* a mp4/3gp box "@xyz". Location with longitude of -90 degrees and latitude
- * of 180 degrees will be retrieved as "-90.0000+180.0000", for instance.
+ * of 180 degrees will be retrieved as "+180.0000-90.0000/", for instance.
*/
public static final int METADATA_KEY_LOCATION = 23;
/**
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CameraTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CameraTest.java
index 7f23ba576fbb..9b643ad3c086 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CameraTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/CameraTest.java
@@ -25,7 +25,6 @@ import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.PreviewCallback;
import android.hardware.Camera.ShutterCallback;
import android.os.ConditionVariable;
-import android.os.Environment;
import android.os.Looper;
import android.test.ActivityInstrumentationTestCase;
import android.test.suitebuilder.annotation.LargeTest;
@@ -159,7 +158,7 @@ public class CameraTest extends ActivityInstrumentationTestCase<MediaFrameworkTe
if (rawData != null) {
int rawDataLength = rawData.length;
File rawoutput = new File(
- Environment.getExternalStorageDirectory().toString(), "/test.bmp");
+ mContext.getExternalFilesDir(null).getPath(), "/test.bmp");
FileOutputStream outstream = new FileOutputStream(rawoutput);
outstream.write(rawData);
Log.v(TAG, "JpegPictureCallback rawDataLength = " + rawDataLength);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestHelper.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestHelper.java
index 84153d6089e9..bd236a69fe84 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestHelper.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestHelper.java
@@ -22,10 +22,11 @@ import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.hardware.Camera.PictureCallback;
import android.hardware.Camera.ShutterCallback;
-import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
+import androidx.test.InstrumentationRegistry;
+
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@@ -70,7 +71,8 @@ public class CameraTestHelper {
try {
Log.v(TAG, "JPEG picture taken");
fos = new FileOutputStream(String.format("%s/%s/%s-%d.jpg",
- Environment.getExternalStorageDirectory(), CAMERA_STRESS_IMAGES_DIRECTORY,
+ InstrumentationRegistry.getInstrumentation().getTargetContext()
+ .getExternalFilesDir(null).getPath(), CAMERA_STRESS_IMAGES_DIRECTORY,
CAMERA_STRESS_IMAGES_PREFIX, System.currentTimeMillis()));
fos.write(data);
} catch (FileNotFoundException e) {
@@ -95,7 +97,8 @@ public class CameraTestHelper {
public void setupCameraTest() {
// Create the test images directory if it doesn't exist
File stressImagesDirectory = new File(String.format("%s/%s",
- Environment.getExternalStorageDirectory(), CAMERA_STRESS_IMAGES_DIRECTORY));
+ InstrumentationRegistry.getInstrumentation().getTargetContext()
+ .getExternalFilesDir(null).getPath(), CAMERA_STRESS_IMAGES_DIRECTORY));
if (!stressImagesDirectory.exists()) {
stressImagesDirectory.mkdir();
}
@@ -129,7 +132,8 @@ public class CameraTestHelper {
public void cleanupTestImages() {
try {
File stressImagesDirectory = new File(String.format("%s/%s",
- Environment.getExternalStorageDirectory(), CAMERA_STRESS_IMAGES_DIRECTORY));
+ InstrumentationRegistry.getInstrumentation().getTargetContext()
+ .getExternalFilesDir(null).getPath(), CAMERA_STRESS_IMAGES_DIRECTORY));
File[] stressImages = stressImagesDirectory.listFiles();
for (File f : stressImages) {
f.delete();
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java
index 0340cec7432d..0ae640dd7910 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/CameraTestUtils.java
@@ -54,7 +54,6 @@ import android.media.Image.Plane;
import android.media.ImageReader;
import android.media.ImageWriter;
import android.os.Build;
-import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.util.Pair;
@@ -63,6 +62,8 @@ import android.view.Display;
import android.view.Surface;
import android.view.WindowManager;
+import androidx.test.InstrumentationRegistry;
+
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Array;
@@ -128,7 +129,8 @@ public class CameraTestUtils extends Assert {
private static final Location sTestLocation2 = new Location(LocationManager.NETWORK_PROVIDER);
protected static final String DEBUG_FILE_NAME_BASE =
- Environment.getExternalStorageDirectory().getPath();
+ InstrumentationRegistry.getInstrumentation().getTargetContext()
+ .getExternalFilesDir(null).getPath();
static {
sTestLocation0.setTime(1199145600L);
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2SwitchPreviewTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2SwitchPreviewTest.java
index 11327ca301f3..a26ee2d1a668 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2SwitchPreviewTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/Camera2SwitchPreviewTest.java
@@ -104,7 +104,6 @@ public class Camera2SwitchPreviewTest extends Camera2SurfaceViewTestCase {
private static final double AE_COMPENSATION_ERROR_TOLERANCE = 0.2;
// 5 percent error margin for resulting metering regions
private static final float METERING_REGION_ERROR_PERCENT_DELTA = 0.05f;
- private final String VIDEO_FILE_PATH = Environment.getExternalStorageDirectory().getPath();
private static final boolean DEBUG_DUMP = Log.isLoggable(TAG, Log.DEBUG);
private static final int RECORDING_DURATION_MS = 3000;
@@ -137,10 +136,12 @@ public class Camera2SwitchPreviewTest extends Camera2SurfaceViewTestCase {
private int mVideoFrameRate;
private Size mVideoSize;
private long mRecordingStartTime;
+ private String mVideoFilePath;
@Override
protected void setUp() throws Exception {
super.setUp();
+ mVideoFilePath = mContext.getExternalFilesDir(null).getPath();
}
@Override
@@ -371,9 +372,9 @@ public class Camera2SwitchPreviewTest extends Camera2SurfaceViewTestCase {
}
// Configure preview and recording surfaces.
- mOutMediaFileName = VIDEO_FILE_PATH + "/test_video.mp4";
+ mOutMediaFileName = mVideoFilePath + "/test_video.mp4";
if (DEBUG_DUMP) {
- mOutMediaFileName = VIDEO_FILE_PATH + "/test_video_" + cameraId + "_"
+ mOutMediaFileName = mVideoFilePath + "/test_video_" + cameraId + "_"
+ videoSz.toString() + ".mp4";
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/CameraStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/CameraStressTest.java
index d1193deacecf..74244b9745f0 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/CameraStressTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/CameraStressTest.java
@@ -28,7 +28,6 @@ import java.util.concurrent.TimeUnit;
import java.util.List;
import android.hardware.Camera.Parameters;
-import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.test.ActivityInstrumentationTestCase2;
@@ -36,6 +35,8 @@ import android.test.suitebuilder.annotation.LargeTest;
import android.util.Log;
import android.view.SurfaceHolder;
+import androidx.test.InstrumentationRegistry;
+
/**
* Junit / Instrumentation test case for the following camera APIs:
* - camera zoom
@@ -85,7 +86,8 @@ public class CameraStressTest extends ActivityInstrumentationTestCase2<MediaFram
mCameraTestHelper = new CameraTestHelper();
File stressOutFile = new File(String.format("%s/%s",
- Environment.getExternalStorageDirectory(), CAMERA_STRESS_OUTPUT));
+ InstrumentationRegistry.getInstrumentation().getTargetContext()
+ .getExternalFilesDir(null).getPath(), CAMERA_STRESS_OUTPUT));
mOutput = new BufferedWriter(new FileWriter(stressOutFile, true));
mOutput.write(this.getName() + "\n");
}
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
index 7ee2f0a1db18..8fe4fecceeb5 100644
--- a/native/android/surface_control.cpp
+++ b/native/android/surface_control.cpp
@@ -384,6 +384,9 @@ void ASurfaceTransaction_setGeometry(ASurfaceTransaction* aSurfaceTransaction,
transaction->setCrop(surfaceControl, static_cast<const Rect&>(source));
transaction->setFrame(surfaceControl, static_cast<const Rect&>(destination));
transaction->setTransform(surfaceControl, transform);
+ bool transformToInverseDisplay = (NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY & transform) ==
+ NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY;
+ transaction->setTransformToDisplayInverse(surfaceControl, transformToInverseDisplay);
}
void ASurfaceTransaction_setBufferTransparency(ASurfaceTransaction* aSurfaceTransaction,
diff --git a/packages/CaptivePortalLogin/OWNERS b/packages/CaptivePortalLogin/OWNERS
index d3836d4c6c57..52193eb2a12b 100644
--- a/packages/CaptivePortalLogin/OWNERS
+++ b/packages/CaptivePortalLogin/OWNERS
@@ -1,8 +1,5 @@
set noparent
-codewiz@google.com
-jchalard@google.com
-junyulai@google.com
lorenzo@google.com
-reminv@google.com
-satk@google.com
+baligh@google.com
+delphij@google.com
diff --git a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
index bda5743d27f7..23fb7b6c8ba2 100644
--- a/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
+++ b/packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
@@ -485,7 +485,10 @@ public class CaptivePortalLoginActivity extends Activity {
if (request.isForMainFrame()) {
mMainFrameUrl = request.getUrl().toString();
}
- return false;
+ // Be careful that two shouldOverrideUrlLoading methods are overridden, but
+ // shouldOverrideUrlLoading(WebView view, String url) was deprecated in API level 24.
+ // TODO: delete deprecated one ??
+ return shouldOverrideUrlLoading(view, mMainFrameUrl);
}
// A web page consisting of a large broken lock icon to indicate SSL failure.
diff --git a/packages/CarSystemUI/res/layout/car_ongoing_privacy_chip.xml b/packages/CarSystemUI/res/layout/car_ongoing_privacy_chip.xml
deleted file mode 100644
index 918abd962dc2..000000000000
--- a/packages/CarSystemUI/res/layout/car_ongoing_privacy_chip.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2019 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<com.android.systemui.statusbar.car.privacy.OngoingPrivacyChip
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/car_privacy_chip"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_margin="@dimen/ongoing_appops_chip_margin"
- android:layout_toStartOf="@+id/clock_container"
- android:focusable="true"
- android:gravity="center_vertical|end"
- android:orientation="horizontal"
- android:paddingEnd="@dimen/ongoing_appops_chip_side_padding"
- android:paddingStart="@dimen/ongoing_appops_chip_side_padding"
- android:visibility="visible">
-
- <LinearLayout
- android:id="@+id/icons_container"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:gravity="center_vertical|start"/>
-</com.android.systemui.statusbar.car.privacy.OngoingPrivacyChip> \ No newline at end of file
diff --git a/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml b/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml
index cae89c16a03e..925ccb4a162a 100644
--- a/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml
+++ b/packages/CarSystemUI/res/layout/car_top_navigation_bar.xml
@@ -65,8 +65,6 @@
/>
</FrameLayout>
- <include layout="@layout/car_ongoing_privacy_chip"/>
-
<FrameLayout
android:id="@+id/clock_container"
android:layout_width="wrap_content"
diff --git a/packages/CarSystemUI/res/layout/notification_center_activity.xml b/packages/CarSystemUI/res/layout/notification_center_activity.xml
index 55b0d875de41..0af74c4462a6 100644
--- a/packages/CarSystemUI/res/layout/notification_center_activity.xml
+++ b/packages/CarSystemUI/res/layout/notification_center_activity.xml
@@ -38,7 +38,7 @@
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="vertical"
- android:paddingStart="@dimen/notification_shade_list_padding_bottom"
+ android:paddingBottom="@dimen/notification_shade_list_padding_bottom"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
diff --git a/packages/CarSystemUI/res/values/dimens.xml b/packages/CarSystemUI/res/values/dimens.xml
index 7027ce37f670..0358357b9c1a 100644
--- a/packages/CarSystemUI/res/values/dimens.xml
+++ b/packages/CarSystemUI/res/values/dimens.xml
@@ -59,16 +59,6 @@
<dimen name="car_keyline_1">24dp</dimen>
<dimen name="car_keyline_2">96dp</dimen>
<dimen name="car_keyline_3">128dp</dimen>
- <dimen name="privacy_chip_icon_height">36dp</dimen>
- <dimen name="privacy_chip_icon_padding_left">0dp</dimen>
- <dimen name="privacy_chip_icon_padding_right">0dp</dimen>
- <dimen name="privacy_chip_icon_padding_top">0dp</dimen>
- <dimen name="privacy_chip_icon_padding_bottom">0dp</dimen>
-
- <dimen name="privacy_chip_text_padding_left">0dp</dimen>
- <dimen name="privacy_chip_text_padding_right">0dp</dimen>
- <dimen name="privacy_chip_text_padding_top">0dp</dimen>
- <dimen name="privacy_chip_text_padding_bottom">0dp</dimen>
<dimen name="privacy_chip_icon_max_height">100dp</dimen>
@@ -86,16 +76,6 @@
<dimen name="ongoing_appops_chip_bg_padding">4dp</dimen>
<!-- Radius of Ongoing App Ops chip corners -->
<dimen name="ongoing_appops_chip_bg_corner_radius">12dp</dimen>
- <!-- Start padding for the app icon displayed in the dialog -->
- <dimen name="privacy_dialog_app_icon_padding_start">40dp</dimen>
- <!-- End padding for the app opps icon displayed in the dialog -->
- <dimen name="privacy_dialog_app_ops_icon_padding_end">40dp</dimen>
- <!-- Top padding for the list of application displayed in the dialog -->
- <dimen name="privacy_dialog_app_list_padding_top">20dp</dimen>
- <!-- Top padding for the dialog container-->
- <dimen name="privacy_dialog_container_padding_top">10dp</dimen>
- <!-- Top padding for the dialog title-->
- <dimen name="privacy_dialog_title_padding_start">10dp</dimen>
<!-- Car volume dimens. -->
<dimen name="car_volume_item_height">@*android:dimen/car_single_line_list_item_height</dimen>
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index b6b34c760594..7fbdc2ed844b 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -389,22 +389,18 @@ public class CarStatusBar extends StatusBar implements
}
}
});
+
+ // Attached to the Handle bar to close the notification shade
+ GestureDetector handleBarCloseNotificationGestureDetector = new GestureDetector(mContext,
+ new HandleBarCloseNotificationGestureListener());
+
mNavBarNotificationTouchListener =
(v, event) -> {
boolean consumed = navBarCloseNotificationGestureDetector.onTouchEvent(event);
if (consumed) {
return true;
}
- if (event.getActionMasked() == MotionEvent.ACTION_UP
- && mNotificationView.getVisibility() == View.VISIBLE) {
- if (mSettleClosePercentage < mPercentageFromBottom) {
- animateNotificationPanel(
- DEFAULT_FLING_VELOCITY, false);
- } else {
- animateNotificationPanel(DEFAULT_FLING_VELOCITY,
- true);
- }
- }
+ maybeCompleteAnimation(event);
return true;
};
@@ -418,15 +414,7 @@ public class CarStatusBar extends StatusBar implements
if (consumed) {
return true;
}
- if (event1.getActionMasked() == MotionEvent.ACTION_UP
- && mNotificationView.getVisibility() == View.VISIBLE) {
- if (mSettleOpenPercentage > mPercentageFromBottom) {
- animateNotificationPanel(DEFAULT_FLING_VELOCITY, true);
- } else {
- animateNotificationPanel(
- DEFAULT_FLING_VELOCITY, false);
- }
- }
+ maybeCompleteAnimation(event1);
return true;
}
);
@@ -498,6 +486,13 @@ public class CarStatusBar extends StatusBar implements
}
return false;
});
+
+ mHandleBar.setOnTouchListener((v, event) -> {
+ handleBarCloseNotificationGestureDetector.onTouchEvent(event);
+ maybeCompleteAnimation(event);
+ return true;
+ });
+
mNotificationList = mNotificationView.findViewById(R.id.notifications);
mNotificationList.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
@@ -612,6 +607,17 @@ public class CarStatusBar extends StatusBar implements
setPanelExpanded(false);
}
+ private void maybeCompleteAnimation(MotionEvent event) {
+ if (event.getActionMasked() == MotionEvent.ACTION_UP
+ && mNotificationView.getVisibility() == View.VISIBLE) {
+ if (mSettleClosePercentage < mPercentageFromBottom) {
+ animateNotificationPanel(DEFAULT_FLING_VELOCITY, false);
+ } else {
+ animateNotificationPanel(DEFAULT_FLING_VELOCITY, true);
+ }
+ }
+ }
+
/**
* Animates the notification shade from one position to other. This is used to either open or
* close the notification shade completely with a velocity. If the animation is to close the
@@ -1054,8 +1060,10 @@ public class CarStatusBar extends StatusBar implements
private static final int SWIPE_MAX_OFF_PATH = 75;
private static final int SWIPE_THRESHOLD_VELOCITY = 200;
- // Only responsible for open hooks. Since once the panel opens it covers all elements
- // there is no need to merge with close.
+ /**
+ * Only responsible for open hooks. Since once the panel opens it covers all elements
+ * there is no need to merge with close.
+ */
private abstract class OpenNotificationGestureListener extends
GestureDetector.SimpleOnGestureListener {
@@ -1098,7 +1106,9 @@ public class CarStatusBar extends StatusBar implements
protected abstract void openNotification();
}
- // to be installed on the open panel notification panel
+ /**
+ * To be installed on the open panel notification panel
+ */
private abstract class CloseNotificationGestureListener extends
GestureDetector.SimpleOnGestureListener {
@@ -1172,7 +1182,9 @@ public class CarStatusBar extends StatusBar implements
protected abstract void close();
}
- // To be installed on the nav bars.
+ /**
+ * To be installed on the nav bars.
+ */
private abstract class NavBarCloseNotificationGestureListener extends
CloseNotificationGestureListener {
@Override
@@ -1201,7 +1213,28 @@ public class CarStatusBar extends StatusBar implements
}
/**
- * SystemUi version onf the notification manager that overrides methods such that the
+ * To be installed on the handle bar.
+ */
+ private class HandleBarCloseNotificationGestureListener extends
+ GestureDetector.SimpleOnGestureListener {
+
+ @Override
+ public boolean onScroll(MotionEvent event1, MotionEvent event2, float distanceX,
+ float distanceY) {
+ calculatePercentageFromBottom(event2.getRawY());
+ // To prevent the jump in the clip bounds while closing the notification shade using
+ // the handle bar we should calculate the height using the diff of event1 and event2.
+ // This will help the notification shade to clip smoothly as the event2 value changes
+ // as event1 value will be fixed.
+ int clipHeight =
+ mNotificationView.getHeight() - (int) (event1.getRawY() - event2.getRawY());
+ setNotificationViewClipBounds(clipHeight);
+ return true;
+ }
+ }
+
+ /**
+ * SystemUi version of the notification manager that overrides methods such that the
* notifications end up in the status bar layouts instead of a standalone window.
*/
private class CarSystemUIHeadsUpNotificationManager extends CarHeadsUpNotificationManager {
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/OngoingPrivacyChip.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/OngoingPrivacyChip.java
deleted file mode 100644
index ead1de2bd352..000000000000
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/OngoingPrivacyChip.java
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.car.privacy;
-
-import android.app.ActivityManager;
-import android.app.AppOpsManager;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-
-import com.android.systemui.Dependency;
-import com.android.systemui.R;
-import com.android.systemui.appops.AppOpItem;
-import com.android.systemui.appops.AppOpsController;
-import com.android.systemui.plugins.ActivityStarter;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import java.util.stream.Collectors;
-
-/**
- * Layout defining the privacy chip that will be displayed in CarStatusRar with the information for
- * which applications are using AppOpps permission fpr camera, mic and location.
- */
-public class OngoingPrivacyChip extends LinearLayout implements View.OnClickListener {
-
- private Context mContext;
-
- private LinearLayout mIconsContainer;
- private List<PrivacyItem> mPrivacyItems;
- private static AppOpsController sAppOpsController;
- private UserManager mUserManager;
- private int mCurrentUser;
- private List<Integer> mCurrentUserIds;
- private boolean mListening = false;
- PrivacyDialogBuilder mPrivacyDialogBuilder;
- private LinearLayout mPrivacyChip;
- private ActivityStarter mActivityStarter;
-
- protected static final int[] OPS = new int[]{
- AppOpsManager.OP_CAMERA,
- AppOpsManager.OP_RECORD_AUDIO,
- AppOpsManager.OP_COARSE_LOCATION,
- AppOpsManager.OP_FINE_LOCATION
- };
-
- public OngoingPrivacyChip(Context context) {
- super(context, null);
- init(context);
- }
-
- public OngoingPrivacyChip(Context context, AttributeSet attr) {
- super(context, attr);
- init(context);
- }
-
- public OngoingPrivacyChip(Context context, AttributeSet attr, int defStyle) {
- super(context, attr, defStyle);
- init(context);
- }
-
- public OngoingPrivacyChip(Context context, AttributeSet attr, int defStyle, int a) {
- super(context, attr, defStyle, a);
- init(context);
- }
-
- private void init(Context context) {
- mContext = context;
- mPrivacyItems = new ArrayList<>();
- sAppOpsController = Dependency.get(AppOpsController.class);
- mUserManager = mContext.getSystemService(UserManager.class);
- mActivityStarter = Dependency.get(ActivityStarter.class);
- mCurrentUser = ActivityManager.getCurrentUser();
- mCurrentUserIds = mUserManager.getProfiles(mCurrentUser).stream().map(
- userInfo -> userInfo.id).collect(Collectors.toList());
-
- mPrivacyDialogBuilder = new PrivacyDialogBuilder(context, mPrivacyItems);
- }
-
- private AppOpsController.Callback mCallback = new AppOpsController.Callback() {
-
- @Override
- public void onActiveStateChanged(int code, int uid, String packageName, boolean active) {
- int userId = UserHandle.getUserId(uid);
- if (mCurrentUserIds.contains(userId)) {
- updatePrivacyList();
- }
- }
- };
-
- @Override
- public void onFinishInflate() {
- mIconsContainer = findViewById(R.id.icons_container);
- mPrivacyChip = (LinearLayout) findViewById(R.id.car_privacy_chip);
- if (mPrivacyChip != null) {
- mPrivacyChip.setOnClickListener(this);
- setListening(true);
- }
- }
-
- @Override
- public void onDetachedFromWindow() {
- if (mPrivacyChip != null) {
- setListening(false);
- }
- super.onDetachedFromWindow();
- }
-
- @Override
- public void onClick(View v) {
- updatePrivacyList();
- Handler mUiHandler = new Handler(Looper.getMainLooper());
- mUiHandler.post(() -> {
- mActivityStarter.postStartActivityDismissingKeyguard(
- new Intent(Intent.ACTION_REVIEW_ONGOING_PERMISSION_USAGE), 0);
- });
- }
-
- private void setListening(boolean listen) {
- if (mListening == listen) {
- return;
- }
- mListening = listen;
- if (mListening) {
- sAppOpsController.addCallback(OPS, mCallback);
- updatePrivacyList();
- } else {
- sAppOpsController.removeCallback(OPS, mCallback);
- }
- }
-
- private void updatePrivacyList() {
- mPrivacyItems = mCurrentUserIds.stream()
- .flatMap(item -> sAppOpsController.getActiveAppOpsForUser(item).stream())
- .filter(Objects::nonNull)
- .map(item -> toPrivacyItem(item))
- .filter(Objects::nonNull)
- .collect(Collectors.toList());
- mPrivacyDialogBuilder = new PrivacyDialogBuilder(mContext, mPrivacyItems);
-
- Handler refresh = new Handler(Looper.getMainLooper());
- refresh.post(new Runnable() {
- @Override
- public void run() {
- updateView();
- }
- });
- }
-
- private PrivacyItem toPrivacyItem(AppOpItem appOpItem) {
- PrivacyType type;
- switch (appOpItem.getCode()) {
- case AppOpsManager.OP_CAMERA:
- type = PrivacyType.TYPE_CAMERA;
- break;
- case AppOpsManager.OP_COARSE_LOCATION:
- type = PrivacyType.TYPE_LOCATION;
- break;
- case AppOpsManager.OP_FINE_LOCATION:
- type = PrivacyType.TYPE_LOCATION;
- break;
- case AppOpsManager.OP_RECORD_AUDIO:
- type = PrivacyType.TYPE_MICROPHONE;
- break;
- default:
- return null;
- }
- PrivacyApplication app = new PrivacyApplication(appOpItem.getPackageName(), mContext);
- return new PrivacyItem(type, app, appOpItem.getTimeStarted());
- }
-
- // Should only be called if the mPrivacyDialogBuilder icons or app changed
- private void updateView() {
- if (mPrivacyItems.isEmpty()) {
- mPrivacyChip.setVisibility(GONE);
- return;
- }
- mPrivacyChip.setVisibility(VISIBLE);
- setIcons(mPrivacyDialogBuilder);
-
- requestLayout();
- }
-
- private void setIcons(PrivacyDialogBuilder dialogBuilder) {
- mIconsContainer.removeAllViews();
- dialogBuilder.generateIcons().forEach(item -> {
- int size = mContext.getResources().getDimensionPixelSize(
- R.dimen.privacy_chip_icon_height);
- ImageView image = new ImageView(mContext);
- image.setImageDrawable(item);
- LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(size, size);
-
- int leftPadding = mContext.getResources().getDimensionPixelSize(
- R.dimen.privacy_chip_icon_padding_left);
- int topPadding = mContext.getResources().getDimensionPixelSize(
- R.dimen.privacy_chip_icon_padding_top);
- int rightPadding = mContext.getResources().getDimensionPixelSize(
- R.dimen.privacy_chip_icon_padding_right);
- int bottomPadding = mContext.getResources().getDimensionPixelSize(
- R.dimen.privacy_chip_icon_padding_bottom);
- image.setLayoutParams(layoutParams);
- image.setPadding(leftPadding, topPadding, rightPadding, bottomPadding);
- mIconsContainer.addView(image);
- });
- }
-}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyApplication.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyApplication.java
deleted file mode 100644
index 5ec7a77cb305..000000000000
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyApplication.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.car.privacy;
-
-import android.car.userlib.CarUserManagerHelper;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.graphics.drawable.Drawable;
-import android.util.Log;
-
-/**
- * Class to hold the data for the applications that are using the AppOps permissions.
- */
-public class PrivacyApplication {
- private static final String TAG = "PrivacyApplication";
-
- private Drawable mIcon;
- private String mApplicationName;
-
- public PrivacyApplication(String packageName, Context context) {
- try {
- CarUserManagerHelper carUserManagerHelper = new CarUserManagerHelper(context);
- ApplicationInfo app = context.getPackageManager()
- .getApplicationInfoAsUser(packageName, 0,
- carUserManagerHelper.getCurrentForegroundUserId());
- mIcon = context.getPackageManager().getApplicationIcon(app);
- mApplicationName = context.getPackageManager().getApplicationLabel(app).toString();
- } catch (PackageManager.NameNotFoundException e) {
- mApplicationName = packageName;
- Log.e(TAG, "Failed to to find package name", e);
- }
- }
-
- /**
- * Gets the application name.
- */
- public Drawable getIcon() {
- return mIcon;
- }
-
- /**
- * Gets the application name.
- */
- public String getApplicationName() {
- return mApplicationName;
- }
-}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyDialogBuilder.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyDialogBuilder.java
deleted file mode 100644
index 3b83e7cc0623..000000000000
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyDialogBuilder.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.car.privacy;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.stream.Collectors;
-
-/**
- * Helper class to build the {@link OngoingPrivacyDialog}
- */
-public class PrivacyDialogBuilder {
-
- private Map<PrivacyType, List<PrivacyItem>> mItemsByType;
- private PrivacyApplication mApplication;
- private Context mContext;
-
- public PrivacyDialogBuilder(Context context, List<PrivacyItem> itemsList) {
- mContext = context;
- mItemsByType = itemsList.stream().filter(Objects::nonNull).collect(
- Collectors.groupingBy(PrivacyItem::getPrivacyType));
- List<PrivacyApplication> apps = itemsList.stream().filter(Objects::nonNull).map(
- PrivacyItem::getPrivacyApplication).distinct().collect(Collectors.toList());
- mApplication = apps.size() == 1 ? apps.get(0) : null;
- }
-
- /**
- * Gets the icon id for all the {@link PrivacyItem} in the same order as of itemList.
- */
- public List<Drawable> generateIcons() {
- return mItemsByType.keySet().stream().map(item -> item.getIconId(mContext)).collect(
- Collectors.toList());
- }
-
- /**
- * Gets the application object.
- */
- public PrivacyApplication getApplication() {
- return mApplication;
- }
-}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyItem.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyItem.java
deleted file mode 100644
index fca137392d74..000000000000
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyItem.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.car.privacy;
-
-/**
- * Class for holding the data of each privacy item displayed in {@link OngoingPrivacyDialog}
- */
-public class PrivacyItem {
-
- private PrivacyType mPrivacyType;
- private PrivacyApplication mPrivacyApplication;
-
- public PrivacyItem(PrivacyType privacyType, PrivacyApplication privacyApplication,
- long timeStarted) {
- this.mPrivacyType = privacyType;
- this.mPrivacyApplication = privacyApplication;
- }
-
- /**
- * Gets the application object.
- */
- public PrivacyApplication getPrivacyApplication() {
- return mPrivacyApplication;
- }
-
- /**
- * Gets the privacy type for the application.
- */
- public PrivacyType getPrivacyType() {
- return mPrivacyType;
- }
-}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyType.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyType.java
deleted file mode 100644
index 8955c87bbff4..000000000000
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/privacy/PrivacyType.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.statusbar.car.privacy;
-
-import android.content.Context;
-import android.graphics.drawable.Drawable;
-
-import com.android.systemui.R;
-
-/**
- * Enum for storing data for camera, mic and location.
- */
-public enum PrivacyType {
- TYPE_CAMERA(R.string.privacy_type_camera, com.android.internal.R.drawable.ic_camera),
- TYPE_LOCATION(R.string.privacy_type_location, R.drawable.stat_sys_location),
- TYPE_MICROPHONE(R.string.privacy_type_microphone, R.drawable.ic_mic_white);
-
- private int mNameId;
- private int mIconId;
-
- PrivacyType(int nameId, int iconId) {
- mNameId = nameId;
- mIconId = iconId;
- }
-
- /**
- * Get the icon Id.
- */
- public Drawable getIconId(Context context) {
- return context.getResources().getDrawable(mIconId, null);
- }
-
- /**
- * Get the name Id.
- */
- public String getNameId(Context context) {
- return context.getResources().getString(mNameId);
- }
-}
diff --git a/packages/ExtServices/OWNERS b/packages/ExtServices/OWNERS
new file mode 100644
index 000000000000..bf52f35ee6e0
--- /dev/null
+++ b/packages/ExtServices/OWNERS
@@ -0,0 +1,4 @@
+set noparent
+
+baligh@google.com
+delphij@google.com
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index da3416b886ad..1b27b52f1fa1 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -638,7 +638,7 @@ public class ExternalStorageProvider extends FileSystemProvider {
final String docId = DocumentsContract.getDocumentId(documentUri);
try {
final Bundle out = new Bundle();
- final Uri uri = Uri.fromFile(getFileForDocId(docId));
+ final Uri uri = Uri.fromFile(getFileForDocId(docId, true));
out.putParcelable(DocumentsContract.EXTRA_URI, uri);
return out;
} catch (FileNotFoundException e) {
diff --git a/packages/NetworkPermissionConfig/OWNERS b/packages/NetworkPermissionConfig/OWNERS
new file mode 100644
index 000000000000..52193eb2a12b
--- /dev/null
+++ b/packages/NetworkPermissionConfig/OWNERS
@@ -0,0 +1,5 @@
+set noparent
+
+lorenzo@google.com
+baligh@google.com
+delphij@google.com
diff --git a/packages/NetworkStack/OWNERS b/packages/NetworkStack/OWNERS
index 0e1e65df818f..52193eb2a12b 100644
--- a/packages/NetworkStack/OWNERS
+++ b/packages/NetworkStack/OWNERS
@@ -1,6 +1,5 @@
-codewiz@google.com
-jchalard@google.com
-junyulai@google.com
+set noparent
+
lorenzo@google.com
-reminv@google.com
-satk@google.com
+baligh@google.com
+delphij@google.com
diff --git a/packages/NetworkStack/src/com/android/server/NetworkStackService.java b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
index 2fae0c703084..9bf44579127e 100644
--- a/packages/NetworkStack/src/com/android/server/NetworkStackService.java
+++ b/packages/NetworkStack/src/com/android/server/NetworkStackService.java
@@ -195,6 +195,7 @@ public class NetworkStackService extends Service {
@Override
public void makeNetworkMonitor(Network network, String name, INetworkMonitorCallbacks cb)
throws RemoteException {
+ checkNetworkStackCallingPermission();
updateSystemAidlVersion(cb.getInterfaceVersion());
final SharedLog log = addValidationLogs(network, name);
final NetworkMonitor nm = new NetworkMonitor(mContext, cb, network, log);
@@ -203,6 +204,7 @@ public class NetworkStackService extends Service {
@Override
public void makeIpClient(String ifName, IIpClientCallbacks cb) throws RemoteException {
+ checkNetworkStackCallingPermission();
updateSystemAidlVersion(cb.getInterfaceVersion());
final IpClient ipClient = new IpClient(mContext, ifName, cb, mObserverRegistry, this);
@@ -228,6 +230,7 @@ public class NetworkStackService extends Service {
@Override
public void fetchIpMemoryStore(@NonNull final IIpMemoryStoreCallbacks cb)
throws RemoteException {
+ checkNetworkStackCallingPermission();
updateSystemAidlVersion(cb.getInterfaceVersion());
cb.onIpMemoryStoreFetched(mIpMemoryStoreService);
}
diff --git a/packages/NetworkStack/src/com/android/server/util/PermissionUtil.java b/packages/NetworkStack/src/com/android/server/util/PermissionUtil.java
index 6fbeeadb7e72..670138411bae 100644
--- a/packages/NetworkStack/src/com/android/server/util/PermissionUtil.java
+++ b/packages/NetworkStack/src/com/android/server/util/PermissionUtil.java
@@ -16,30 +16,56 @@
package com.android.server.util;
+import static android.os.Binder.getCallingPid;
import static android.os.Binder.getCallingUid;
import android.os.Process;
import android.os.UserHandle;
+import java.util.concurrent.atomic.AtomicInteger;
+
/**
* Utility class to check calling permissions on the network stack.
*/
public final class PermissionUtil {
+ private static final AtomicInteger sSystemPid = new AtomicInteger(-1);
/**
* Check that the caller is allowed to communicate with the network stack.
* @throws SecurityException The caller is not allowed to communicate with the network stack.
*/
public static void checkNetworkStackCallingPermission() {
- // TODO: check that the calling PID is the system server.
final int caller = getCallingUid();
- if (caller != Process.SYSTEM_UID
- && UserHandle.getAppId(caller) != Process.BLUETOOTH_UID
- && UserHandle.getAppId(caller) != Process.PHONE_UID) {
+ if (caller == Process.SYSTEM_UID) {
+ checkConsistentSystemPid();
+ return;
+ }
+
+ if (UserHandle.getAppId(caller) != Process.BLUETOOTH_UID) {
throw new SecurityException("Invalid caller: " + caller);
}
}
+ private static void checkConsistentSystemPid() {
+ // Apart from the system server process, no process with a system UID should try to
+ // communicate with the network stack. This is to ensure that the network stack does not
+ // need to maintain behavior for clients it was not designed to work with.
+ // Checking that all calls from a system UID originate from the same PID loosely enforces
+ // this restriction as if another system process calls the network stack first, the system
+ // server would lose access to the network stack and cause obvious failures. If the system
+ // server calls the network stack first, other clients would lose access as expected.
+ final int systemPid = getCallingPid();
+ if (sSystemPid.compareAndSet(-1, systemPid)) {
+ // sSystemPid was unset (-1): this was the first call
+ return;
+ }
+
+ if (sSystemPid.get() != systemPid) {
+ throw new SecurityException("Invalid PID for the system server, expected "
+ + sSystemPid.get() + " but was called from " + systemPid);
+ }
+ }
+
/**
* Check that the caller is allowed to dump the network stack, e.g. dumpsys.
* @throws SecurityException The caller is not allowed to dump the network stack.
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 4c72f48da87f..0e9183940f22 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -578,6 +578,8 @@
<string name="wifi_display_certification">Wireless display certification</string>
<!-- Setting Checkbox title whether to enable WiFi Verbose Logging. [CHAR LIMIT=40] -->
<string name="wifi_verbose_logging">Enable Wi\u2011Fi Verbose Logging</string>
+ <!-- Setting Checkbox title whether to disable WiFi Scan Throttling. [CHAR LIMIT=40] -->
+ <string name="wifi_scan_throttling">Wi\u2011Fi scan throttling</string>
<!-- Setting Checkbox title whether to always keep mobile data active. [CHAR LIMIT=80] -->
<string name="mobile_data_always_on">Mobile data always active</string>
<!-- Setting Checkbox title whether to enable hardware acceleration for tethering. [CHAR LIMIT=80] -->
@@ -633,6 +635,8 @@
<string name="wifi_display_certification_summary">Show options for wireless display certification</string>
<!-- Setting Checkbox summary whether to enable Wifi verbose Logging [CHAR LIMIT=80] -->
<string name="wifi_verbose_logging_summary">Increase Wi\u2011Fi logging level, show per SSID RSSI in Wi\u2011Fi Picker</string>
+ <!-- Setting Checkbox summary whether to disable Wifi scan throttling [CHAR LIMIT=NONE] -->
+ <string name="wifi_scan_throttling_summary">Reduces battery drain &amp; improves network performance</string>
<!-- Label indicating network has been manually marked as metered -->
<string name="wifi_metered_label">Metered</string>
<!-- Label indicating network has been manually marked as unmetered -->
diff --git a/packages/SettingsLib/src/com/android/settingslib/net/SignalStrengthUtil.java b/packages/SettingsLib/src/com/android/settingslib/net/SignalStrengthUtil.java
new file mode 100644
index 000000000000..246f2ceac87c
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/net/SignalStrengthUtil.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.net;
+
+import android.content.Context;
+import android.telephony.SubscriptionManager;
+
+/**
+ * Utilities for dealing with signal strength.
+ */
+public class SignalStrengthUtil {
+ /**
+ * @return whether we should artificially inflate the signal strength and number of levels by 1
+ * bar for the subscription with the given id
+ */
+ public static boolean shouldInflateSignalStrength(Context context, int subscriptionId) {
+ return SubscriptionManager.getResourcesForSubId(context, subscriptionId)
+ .getBoolean(com.android.internal.R.bool.config_inflateSignalStrength);
+ }
+}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index f7132e368e94..d07bc327971a 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -3043,15 +3043,16 @@ public class SettingsProvider extends ContentProvider {
// Increment the generation first, so observers always see the new value
mGenerationRegistry.incrementGeneration(key);
- if (isGlobalSettingsKey(key)) {
+ if (isGlobalSettingsKey(key) || isConfigSettingsKey(key)) {
final long token = Binder.clearCallingIdentity();
try {
- if (Global.LOCATION_GLOBAL_KILL_SWITCH.equals(name)) {
+ if (Global.LOCATION_GLOBAL_KILL_SWITCH.equals(name)
+ && isGlobalSettingsKey(key)) {
// When the global kill switch is updated, send the
// change notification for the location setting.
notifyLocationChangeForRunningUsers();
}
- notifyGlobalSettingChangeForRunningUsers(key, name);
+ notifySettingChangeForRunningUsers(key, name);
} finally {
Binder.restoreCallingIdentity(token);
}
@@ -3091,7 +3092,7 @@ public class SettingsProvider extends ContentProvider {
}
}
- private void notifyGlobalSettingChangeForRunningUsers(int key, String name) {
+ private void notifySettingChangeForRunningUsers(int key, String name) {
// Important: No need to update generation for each user as there
// is a singleton generation entry for the global settings which
// is already incremented be the caller.
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index a2450860517e..da139d74f8ae 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -206,8 +206,9 @@
<uses-permission android:name="android.permission.INTERACT_ACROSS_PROFILES"/>
<application android:label="@string/app_label"
- android:defaultToDeviceProtectedStorage="true"
- android:directBootAware="true">
+ android:theme="@android:style/Theme.DeviceDefault.DayNight"
+ android:defaultToDeviceProtectedStorage="true"
+ android:directBootAware="true">
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.android.shell"
@@ -232,7 +233,6 @@
<activity
android:name=".BugreportWarningActivity"
- android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.Alert"
android:finishOnCloseSystemDialogs="true"
android:excludeFromRecents="true"
android:exported="false" />
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 1060c7b7ce79..e57a5ded0698 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -99,6 +99,7 @@ import android.util.Log;
import android.util.Pair;
import android.util.Patterns;
import android.util.SparseArray;
+import android.view.ContextThemeWrapper;
import android.view.IWindowManager;
import android.view.View;
import android.view.WindowManager;
@@ -1467,11 +1468,13 @@ public class BugreportProgressService extends Service {
void initialize(final Context context, BugreportInfo info) {
final String dialogTitle =
context.getString(R.string.bugreport_info_dialog_title, info.id);
+ final Context themedContext = new ContextThemeWrapper(
+ context, com.android.internal.R.style.Theme_DeviceDefault_DayNight);
// First initializes singleton.
if (mDialog == null) {
@SuppressLint("InflateParams")
// It's ok pass null ViewRoot on AlertDialogs.
- final View view = View.inflate(context, R.layout.dialog_bugreport_info, null);
+ final View view = View.inflate(themedContext, R.layout.dialog_bugreport_info, null);
mInfoName = (EditText) view.findViewById(R.id.name);
mInfoTitle = (EditText) view.findViewById(R.id.title);
@@ -1488,7 +1491,7 @@ public class BugreportProgressService extends Service {
}
});
- mDialog = new AlertDialog.Builder(context)
+ mDialog = new AlertDialog.Builder(themedContext)
.setView(view)
.setTitle(dialogTitle)
.setCancelable(true)
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index 94259416d274..91a8ab5f692f 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -58,6 +58,7 @@ android_library {
"androidx.arch.core_core-runtime",
"androidx.lifecycle_lifecycle-extensions",
"androidx.dynamicanimation_dynamicanimation",
+ "androidx-constraintlayout_constraintlayout",
"iconloader_base",
"SystemUI-tags",
"SystemUI-proto",
@@ -111,6 +112,7 @@ android_library {
"androidx.arch.core_core-runtime",
"androidx.lifecycle_lifecycle-extensions",
"androidx.dynamicanimation_dynamicanimation",
+ "androidx-constraintlayout_constraintlayout",
"SystemUI-tags",
"SystemUI-proto",
"metrics-helper-lib",
diff --git a/packages/SystemUI/OWNERS b/packages/SystemUI/OWNERS
index c071b8b15a43..83acfa06976f 100644
--- a/packages/SystemUI/OWNERS
+++ b/packages/SystemUI/OWNERS
@@ -12,6 +12,7 @@ cwren@google.com
dupin@google.com
ethibodeau@google.com
evanlaird@google.com
+hyunyoungs@google.com
jmonk@google.com
jaggies@google.com
jjaggi@google.com
@@ -24,6 +25,8 @@ kprevas@google.com
lynhan@google.com
madym@google.com
mankoff@google.com
+mrcasey@google.com
+mrenouf@google.com
nbenbernou@google.com
nesciosquid@google.com
ngmatthew@google.com
diff --git a/packages/SystemUI/res-keyguard/drawable/bubble_hour_hand.xml b/packages/SystemUI/res-keyguard/drawable/bubble_hour_hand.xml
index 65f7a0e29843..8c611f61dc23 100644
--- a/packages/SystemUI/res-keyguard/drawable/bubble_hour_hand.xml
+++ b/packages/SystemUI/res-keyguard/drawable/bubble_hour_hand.xml
@@ -6,5 +6,5 @@
<path
android:pathData="M170,40m-39,0a39,39 0,1 1,78 0a39,39 0,1 1,-78 0"
android:strokeColor="#000000"
- android:strokeWidth="2"/>
+ android:strokeWidth="3"/>
</vector>
diff --git a/packages/SystemUI/res-keyguard/drawable/bubble_minute_hand.xml b/packages/SystemUI/res-keyguard/drawable/bubble_minute_hand.xml
index 95b4b1ad0b9b..27bc43638f06 100644
--- a/packages/SystemUI/res-keyguard/drawable/bubble_minute_hand.xml
+++ b/packages/SystemUI/res-keyguard/drawable/bubble_minute_hand.xml
@@ -6,5 +6,5 @@
<path
android:pathData="M170,1L170,1A39,39 0,0 1,209 40L209,130A39,39 0,0 1,170 169L170,169A39,39 0,0 1,131 130L131,40A39,39 0,0 1,170 1z"
android:strokeColor="#000000"
- android:strokeWidth="2"/>
+ android:strokeWidth="3"/>
</vector>
diff --git a/core/res/res/anim/lock_in.xml b/packages/SystemUI/res/anim/lock_in.xml
index c7014e80d33e..c7014e80d33e 100644
--- a/core/res/res/anim/lock_in.xml
+++ b/packages/SystemUI/res/anim/lock_in.xml
diff --git a/packages/SystemUI/res/anim/lock_in_circular.xml b/packages/SystemUI/res/anim/lock_in_circular.xml
new file mode 100644
index 000000000000..d1e98db6e0e3
--- /dev/null
+++ b/packages/SystemUI/res/anim/lock_in_circular.xml
@@ -0,0 +1,327 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <aapt:attr name="android:drawable" >
+ <vector
+ android:height="32dp"
+ android:viewportHeight="32"
+ android:viewportWidth="32"
+ android:width="32dp" >
+ <group android:name="_R_G" >
+ <group
+ android:name="_R_G_L_2_G"
+ android:pivotX="9.583"
+ android:pivotY="8.916"
+ android:scaleX="0"
+ android:scaleY="0"
+ android:translateX="6.416"
+ android:translateY="10.416999999999998" >
+ <path
+ android:name="_R_G_L_2_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:fillType="nonZero"
+ android:pathData=" M17.42 1.75 C17.42,1.75 17.42,14.58 17.42,14.58 C17.42,15.41 16.74,16.08 15.92,16.08 C15.92,16.08 3.25,16.08 3.25,16.08 C2.42,16.08 1.75,15.41 1.75,14.58 C1.75,14.58 1.75,1.75 1.75,1.75 C1.75,1.75 17.42,1.75 17.42,1.75c M18.92 0.25 C18.92,0.25 0.25,0.25 0.25,0.25 C0.25,0.25 0.25,14.58 0.25,14.58 C0.25,16.24 1.59,17.58 3.25,17.58 C3.25,17.58 15.92,17.58 15.92,17.58 C17.57,17.58 18.92,16.24 18.92,14.58 C18.92,14.58 18.92,0.25 18.92,0.25c " />
+ </group>
+ <group
+ android:name="_R_G_L_1_G_N_3_T_0"
+ android:pivotX="9.583"
+ android:pivotY="8.916"
+ android:scaleX="0"
+ android:scaleY="0"
+ android:translateX="6.416"
+ android:translateY="10.416999999999998" >
+ <group
+ android:name="_R_G_L_1_G"
+ android:translateX="7.334"
+ android:translateY="5.333" >
+ <path
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:fillType="nonZero"
+ android:pathData=" M4.25 2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25 C3.35,0.25 4.25,1.15 4.25,2.25c " />
+ <path
+ android:name="_R_G_L_1_G_D_1_P_0"
+ android:pathData=" M2.25 2.25 C2.25,2.25 2.25,5.92 2.25,5.92 "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="1.5" />
+ </group>
+ </group>
+ <group
+ android:name="_R_G_L_0_G_N_3_T_0"
+ android:pivotX="9.583"
+ android:pivotY="8.916"
+ android:scaleX="0"
+ android:scaleY="0"
+ android:translateX="6.416"
+ android:translateY="10.416999999999998" >
+ <group
+ android:name="_R_G_L_0_G_T_1"
+ android:translateX="9.583"
+ android:translateY="-0.861" >
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="-8.083"
+ android:translateY="-8.173" >
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:pathData=" M12.42 12.6 C12.42,12.6 12.42,8.17 12.42,8.17 C12.42,5.83 10.48,3.75 8.08,3.75 C5.69,3.75 3.75,5.83 3.75,8.17 C3.75,8.17 3.75,12.6 3.75,12.6 "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="1.5"
+ android:trimPathEnd="0.9"
+ android:trimPathOffset="0"
+ android:trimPathStart="0.15" />
+ </group>
+ </group>
+ </group>
+ </group>
+ <group android:name="time_group" />
+ </vector>
+ </aapt:attr>
+
+ <target android:name="_R_G_L_2_G" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleX"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1.025"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleY"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1.025"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="scaleX"
+ android:startOffset="233"
+ android:valueFrom="1.025"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="scaleY"
+ android:startOffset="233"
+ android:valueFrom="1.025"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_N_3_T_0" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleX"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1.025"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleY"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1.025"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="scaleX"
+ android:startOffset="233"
+ android:valueFrom="1.025"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="scaleY"
+ android:startOffset="233"
+ android:valueFrom="1.025"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 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:duration="50"
+ android:propertyName="trimPathStart"
+ android:startOffset="0"
+ android:valueFrom="0.15"
+ android:valueTo="0.15"
+ 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:duration="67"
+ android:propertyName="trimPathStart"
+ android:startOffset="50"
+ android:valueFrom="0.15"
+ 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:duration="50"
+ android:propertyName="trimPathEnd"
+ android:startOffset="0"
+ android:valueFrom="0.9"
+ android:valueTo="0.9"
+ 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:duration="67"
+ android:propertyName="trimPathEnd"
+ android:startOffset="50"
+ android:valueFrom="0.9"
+ 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_T_1" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="150"
+ android:pathData="M 9.583,-0.861C 9.583,-1.32784640645981 9.583,-3.19515359354019 9.583,-3.662"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="0" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_N_3_T_0" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleX"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1.025"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleY"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1.025"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="scaleX"
+ android:startOffset="233"
+ android:valueFrom="1.025"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="scaleY"
+ android:startOffset="233"
+ android:valueFrom="1.025"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,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:duration="717"
+ android:propertyName="translateX"
+ 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/anim/lock_in_filled.xml b/packages/SystemUI/res/anim/lock_in_filled.xml
new file mode 100644
index 000000000000..4cde38d4f0dc
--- /dev/null
+++ b/packages/SystemUI/res/anim/lock_in_filled.xml
@@ -0,0 +1,190 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <aapt:attr name="android:drawable" >
+ <vector
+ android:height="32dp"
+ android:viewportHeight="32"
+ android:viewportWidth="32"
+ android:width="32dp" >
+ <group android:name="_R_G" >
+ <group
+ android:name="_R_G_L_1_G"
+ android:pivotX="10.917"
+ android:pivotY="9.583"
+ android:scaleX="0"
+ android:scaleY="0"
+ android:translateX="5.083"
+ android:translateY="10.417" >
+ <path
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:fillType="nonZero"
+ android:pathData=" M18.92 0.25 C18.92,0.25 2.92,0.25 2.92,0.25 C1.45,0.25 0.25,1.45 0.25,2.92 C0.25,2.92 0.25,16.25 0.25,16.25 C0.25,17.72 1.45,18.92 2.92,18.92 C2.92,18.92 18.92,18.92 18.92,18.92 C20.38,18.92 21.58,17.72 21.58,16.25 C21.58,16.25 21.58,2.92 21.58,2.92 C21.58,1.45 20.38,0.25 18.92,0.25c M10.92 12.25 C9.45,12.25 8.25,11.05 8.25,9.58 C8.25,8.12 9.45,6.92 10.92,6.92 C12.38,6.92 13.58,8.12 13.58,9.58 C13.58,11.05 12.38,12.25 10.92,12.25c " />
+ </group>
+ <group
+ android:name="_R_G_L_0_G_N_2_T_0"
+ android:pivotX="10.917"
+ android:pivotY="9.583"
+ android:scaleX="0"
+ android:scaleY="0"
+ android:translateX="5.083"
+ android:translateY="10.417" >
+ <group
+ android:name="_R_G_L_0_G_T_1"
+ android:translateX="10.917"
+ android:translateY="0.579" >
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="-9"
+ android:translateY="-9" >
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:pathData=" M13 13 C13,13 13,9 13,9 C13,6.79 11.21,5 9,5 C6.79,5 5,6.79 5,9 C5,9 5,13 5,13 "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="2" />
+ </group>
+ </group>
+ </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:duration="233"
+ android:propertyName="scaleX"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1.025"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleY"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1.025"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="scaleX"
+ android:startOffset="233"
+ android:valueFrom="1.025"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="scaleY"
+ android:startOffset="233"
+ android:valueFrom="1.025"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_T_1" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="150"
+ android:pathData="M 10.917,0.579C 10.917,-0.14248990631104008 10.917,-3.02851009368896 10.917,-3.75"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="0" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_N_2_T_0" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleX"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1.025"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleY"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1.025"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="scaleX"
+ android:startOffset="233"
+ android:valueFrom="1.025"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="scaleY"
+ android:startOffset="233"
+ android:valueFrom="1.025"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,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:duration="717"
+ android:propertyName="translateX"
+ 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/anim/lock_in_rounded.xml b/packages/SystemUI/res/anim/lock_in_rounded.xml
new file mode 100644
index 000000000000..7c8cf9d7b525
--- /dev/null
+++ b/packages/SystemUI/res/anim/lock_in_rounded.xml
@@ -0,0 +1,336 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <aapt:attr name="android:drawable" >
+ <vector
+ android:height="38dp"
+ android:viewportHeight="38"
+ android:viewportWidth="32"
+ android:width="32dp" >
+ <group android:name="_R_G" >
+ <group
+ android:name="_R_G_L_2_G"
+ android:pivotX="14.667"
+ android:pivotY="12.667"
+ android:scaleX="0"
+ android:scaleY="0"
+ android:translateX="1.3330000000000002"
+ android:translateY="10.333" >
+ <path
+ android:name="_R_G_L_2_G_D_0_P_0"
+ android:pathData=" M22.09 5 C22.09,5 6,5 6,5 C5.45,5 5,5.45 5,6 C5,6 5,19.33 5,19.33 C5,19.89 5.45,20.33 6,20.33 C6,20.33 23.33,20.33 23.33,20.33 C23.89,20.33 24.33,19.89 24.33,19.33 C24.33,19.33 24.33,6 24.33,6 C24.33,5.45 23.89,5 23.33,5 C23.33,5 22.09,5 22.09,5c "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="1.5" />
+ </group>
+ <group
+ android:name="_R_G_L_1_G_N_3_T_0"
+ android:pivotX="14.667"
+ android:pivotY="12.667"
+ android:scaleX="0"
+ android:scaleY="0"
+ android:translateX="1.3330000000000002"
+ android:translateY="10.333" >
+ <group
+ android:name="_R_G_L_1_G"
+ android:translateX="12.416"
+ android:translateY="10.417" >
+ <path
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:fillType="nonZero"
+ android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c " />
+ </group>
+ </group>
+ <group android:name="_R_G_L_0_G_N_3_T_0_M" >
+ <group
+ android:name="_R_G_L_0_G_N_3_T_0"
+ android:pivotX="14.667"
+ android:pivotY="12.667"
+ android:scaleX="0"
+ android:scaleY="0"
+ android:translateX="1.3330000000000002"
+ android:translateY="10.333" >
+ <group
+ android:name="_R_G_L_0_G_T_1"
+ android:translateX="14.666"
+ android:translateY="3.769" >
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="-9.333"
+ android:translateY="-9.713" >
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:pathData=" M13.67 13.8 C13.67,13.8 13.67,8.94 13.67,8.94 C13.63,6.75 11.69,5 9.33,5.04 C6.98,5 5.04,6.75 5,8.94 C5,8.94 5,13.8 5,13.8 "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="1.5"
+ android:trimPathEnd="0.9"
+ android:trimPathOffset="0"
+ android:trimPathStart="0.14" />
+ </group>
+ </group>
+ </group>
+ </group>
+ </group>
+ <group android:name="time_group" />
+ </vector>
+ </aapt:attr>
+
+ <target android:name="_R_G_L_2_G" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleX"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1.025"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleY"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1.025"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="scaleX"
+ android:startOffset="233"
+ android:valueFrom="1.025"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="scaleY"
+ android:startOffset="233"
+ android:valueFrom="1.025"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_N_3_T_0" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleX"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1.025"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleY"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1.025"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="scaleX"
+ android:startOffset="233"
+ android:valueFrom="1.025"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="scaleY"
+ android:startOffset="233"
+ android:valueFrom="1.025"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 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:duration="50"
+ android:propertyName="trimPathStart"
+ android:startOffset="0"
+ android:valueFrom="0.14"
+ android:valueTo="0.14"
+ 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:duration="67"
+ android:propertyName="trimPathStart"
+ android:startOffset="50"
+ android:valueFrom="0.14"
+ 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:duration="50"
+ android:propertyName="trimPathEnd"
+ android:startOffset="0"
+ android:valueFrom="0.9"
+ android:valueTo="0.9"
+ 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:duration="67"
+ android:propertyName="trimPathEnd"
+ android:startOffset="50"
+ android:valueFrom="0.9"
+ 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_T_1" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="150"
+ android:pathData="M 14.666,3.769C 14.666,3.18868762874603 14.666,0.8673123712539699 14.666,0.287"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="0" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_N_3_T_0" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleX"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1.025"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleY"
+ android:startOffset="0"
+ android:valueFrom="0"
+ android:valueTo="1.025"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="scaleX"
+ android:startOffset="233"
+ android:valueFrom="1.025"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="scaleY"
+ android:startOffset="233"
+ android:valueFrom="1.025"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_N_3_T_0_M" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="0"
+ android:propertyName="scaleX"
+ android:startOffset="50"
+ android:valueFrom="0"
+ android:valueTo="1"
+ android:valueType="floatType" />
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="time_group" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="717"
+ android:propertyName="translateX"
+ 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/core/res/res/anim/lock_lock.xml b/packages/SystemUI/res/anim/lock_lock.xml
index 3b8c4855fc8f..3167e7cd616d 100644
--- a/core/res/res/anim/lock_lock.xml
+++ b/packages/SystemUI/res/anim/lock_lock.xml
@@ -1,17 +1,18 @@
-<!-- Copyright (C) 2019 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
diff --git a/packages/SystemUI/res/anim/lock_lock_circular.xml b/packages/SystemUI/res/anim/lock_lock_circular.xml
new file mode 100644
index 000000000000..81694407b640
--- /dev/null
+++ b/packages/SystemUI/res/anim/lock_lock_circular.xml
@@ -0,0 +1,320 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <aapt:attr name="android:drawable" >
+ <vector
+ android:height="42dp"
+ android:viewportHeight="42"
+ android:viewportWidth="32"
+ android:width="32dp" >
+ <group android:name="_R_G" >
+ <group
+ android:name="_R_G_L_2_G_T_1"
+ android:translateX="15.999"
+ android:translateY="24.333" >
+ <group
+ android:name="_R_G_L_2_G"
+ android:translateX="-9.583"
+ android:translateY="-8.916" >
+ <path
+ android:name="_R_G_L_2_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:fillType="nonZero"
+ android:pathData=" M17.42 1.75 C17.42,1.75 17.42,14.58 17.42,14.58 C17.42,15.41 16.74,16.08 15.92,16.08 C15.92,16.08 3.25,16.08 3.25,16.08 C2.42,16.08 1.75,15.41 1.75,14.58 C1.75,14.58 1.75,1.75 1.75,1.75 C1.75,1.75 17.42,1.75 17.42,1.75c M18.92 0.25 C18.92,0.25 0.25,0.25 0.25,0.25 C0.25,0.25 0.25,14.58 0.25,14.58 C0.25,16.24 1.59,17.58 3.25,17.58 C3.25,17.58 15.92,17.58 15.92,17.58 C17.57,17.58 18.92,16.24 18.92,14.58 C18.92,14.58 18.92,0.25 18.92,0.25c " />
+ </group>
+ </group>
+ <group
+ android:name="_R_G_L_1_G_N_4_T_1"
+ android:translateX="15.999"
+ android:translateY="24.333" >
+ <group
+ android:name="_R_G_L_1_G_N_4_T_0"
+ android:translateX="-9.583"
+ android:translateY="-8.916" >
+ <group
+ android:name="_R_G_L_1_G"
+ android:pivotX="2.25"
+ android:pivotY="3.334"
+ android:scaleX="1"
+ android:scaleY="1"
+ android:translateX="7.334"
+ android:translateY="5.333" >
+ <path
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:fillType="nonZero"
+ android:pathData=" M4.25 2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25 C3.35,0.25 4.25,1.15 4.25,2.25c " />
+ <path
+ android:name="_R_G_L_1_G_D_1_P_0"
+ android:pathData=" M2.25 2.25 C2.25,2.25 2.25,5.92 2.25,5.92 "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="1.5" />
+ </group>
+ </group>
+ </group>
+ <group
+ android:name="_R_G_L_0_G_N_4_T_1"
+ android:translateX="15.999"
+ android:translateY="24.333" >
+ <group
+ android:name="_R_G_L_0_G_N_4_T_0"
+ android:translateX="-9.583"
+ android:translateY="-8.916" >
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="1.5"
+ android:translateY="-11.835" >
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:pathData=" M12.42 12.6 C12.42,12.6 12.41,8.16 12.41,8.16 C12.41,5.81 14.36,3.75 16.75,3.77 C19.15,3.78 21.07,5.71 21.07,8.05 C21.07,8.05 21.08,8.22 21.08,8.22 "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="1.5" />
+ </group>
+ </group>
+ </group>
+ </group>
+ <group android:name="time_group" />
+ </vector>
+ </aapt:attr>
+
+ <target android:name="_R_G_L_2_G_T_1" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="400"
+ android:propertyName="translateY"
+ android:startOffset="0"
+ android:valueFrom="24.333"
+ android:valueTo="24.333"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="translateY"
+ android:startOffset="400"
+ android:valueFrom="24.333"
+ android:valueTo="25.833"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="translateY"
+ android:startOffset="517"
+ android:valueFrom="25.833"
+ android:valueTo="24.333"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,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:duration="450"
+ android:propertyName="scaleX"
+ 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.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="450"
+ android:propertyName="scaleY"
+ 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.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ android:startOffset="450"
+ android:valueFrom="1"
+ android:valueTo="1.05"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ android:startOffset="450"
+ android:valueFrom="1"
+ android:valueTo="1.05"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="scaleX"
+ android:startOffset="533"
+ android:valueFrom="1.05"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="scaleY"
+ android:startOffset="533"
+ android:valueFrom="1.05"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_N_4_T_1" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="400"
+ android:propertyName="translateY"
+ android:startOffset="0"
+ android:valueFrom="24.333"
+ android:valueTo="24.333"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="translateY"
+ android:startOffset="400"
+ android:valueFrom="24.333"
+ android:valueTo="25.833"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="translateY"
+ android:startOffset="517"
+ android:valueFrom="25.833"
+ android:valueTo="24.333"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 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:duration="333"
+ android:propertyName="pathData"
+ android:startOffset="0"
+ android:valueFrom="M12.42 12.6 C12.42,12.6 12.41,8.16 12.41,8.16 C12.41,5.81 14.36,3.75 16.75,3.77 C19.15,3.78 21.07,5.71 21.07,8.05 C21.07,8.05 21.08,8.22 21.08,8.22 "
+ android:valueTo="M12.42 12.6 C12.42,12.6 12.4,5.86 12.4,5.86 C12.4,3.52 10.46,1.44 8.06,1.44 C5.67,1.44 3.73,3.52 3.73,5.86 C3.73,5.86 3.75,7.41 3.75,7.41 "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.635,0 0.43,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="67"
+ android:propertyName="pathData"
+ android:startOffset="333"
+ android:valueFrom="M12.42 12.6 C12.42,12.6 12.4,5.86 12.4,5.86 C12.4,3.52 10.46,1.44 8.06,1.44 C5.67,1.44 3.73,3.52 3.73,5.86 C3.73,5.86 3.75,7.41 3.75,7.41 "
+ android:valueTo="M12.42 12.6 C12.42,12.6 12.42,8.17 12.42,8.17 C12.42,5.83 10.48,3.75 8.08,3.75 C5.69,3.75 3.75,5.83 3.75,8.17 C3.75,8.17 3.75,12.6 3.75,12.6 "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.512,0 0.41,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_N_4_T_1" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="400"
+ android:propertyName="translateY"
+ android:startOffset="0"
+ android:valueFrom="24.333"
+ android:valueTo="24.333"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="translateY"
+ android:startOffset="400"
+ android:valueFrom="24.333"
+ android:valueTo="25.833"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="translateY"
+ android:startOffset="517"
+ android:valueFrom="25.833"
+ android:valueTo="24.333"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,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:duration="717"
+ android:propertyName="translateX"
+ 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/anim/lock_lock_filled.xml b/packages/SystemUI/res/anim/lock_lock_filled.xml
new file mode 100644
index 000000000000..017c3299c3b2
--- /dev/null
+++ b/packages/SystemUI/res/anim/lock_lock_filled.xml
@@ -0,0 +1,215 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <aapt:attr name="android:drawable" >
+ <vector
+ android:height="42dp"
+ android:viewportHeight="42"
+ android:viewportWidth="32"
+ android:width="32dp" >
+ <group android:name="_R_G" >
+ <group
+ android:name="_R_G_L_1_G_T_1"
+ android:translateX="16"
+ android:translateY="25" >
+ <group
+ android:name="_R_G_L_1_G"
+ android:translateX="-10.917"
+ android:translateY="-9.583" >
+ <path
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:fillType="nonZero"
+ android:pathData=" M18.92 0.25 C18.92,0.25 2.92,0.25 2.92,0.25 C1.45,0.25 0.25,1.45 0.25,2.92 C0.25,2.92 0.25,16.25 0.25,16.25 C0.25,17.72 1.45,18.92 2.92,18.92 C2.92,18.92 18.92,18.92 18.92,18.92 C20.38,18.92 21.58,17.72 21.58,16.25 C21.58,16.25 21.58,2.92 21.58,2.92 C21.58,1.45 20.38,0.25 18.92,0.25c M10.92 12.25 C9.45,12.25 8.25,11.05 8.25,9.58 C8.25,8.12 9.45,6.92 10.92,6.92 C12.38,6.92 13.58,8.12 13.58,9.58 C13.58,11.05 12.38,12.25 10.92,12.25c " />
+ </group>
+ </group>
+ <group
+ android:name="_R_G_L_0_G_N_3_T_1"
+ android:translateX="16"
+ android:translateY="25" >
+ <group
+ android:name="_R_G_L_0_G_N_3_T_0"
+ android:translateX="-10.917"
+ android:translateY="-9.583" >
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="9.917000000000002"
+ android:translateY="-12.75" >
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:pathData=" M13 9 C13,7.9 12.55,6.9 11.83,6.17 C11.1,5.45 10.11,5 9,5 C6.79,5 5,6.79 5,9 C5,9 5,13 5,13 "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="2" />
+ </group>
+ </group>
+ </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:duration="450"
+ android:propertyName="pathData"
+ android:startOffset="0"
+ android:valueFrom=" M18.92 0.25 C18.92,0.25 2.92,0.25 2.92,0.25 C1.45,0.25 0.25,1.45 0.25,2.92 C0.25,2.92 0.25,16.25 0.25,16.25 C0.25,17.72 1.45,18.92 2.92,18.92 C2.92,18.92 18.92,18.92 18.92,18.92 C20.38,18.92 21.58,17.72 21.58,16.25 C21.58,16.25 21.58,2.92 21.58,2.92 C21.58,1.45 20.38,0.25 18.92,0.25c M10.92 12.25 C9.45,12.25 8.25,11.05 8.25,9.58 C8.25,8.12 9.45,6.92 10.92,6.92 C12.38,6.92 13.58,8.12 13.58,9.58 C13.58,11.05 12.38,12.25 10.92,12.25c "
+ android:valueTo=" M18.92 0.25 C18.92,0.25 2.92,0.25 2.92,0.25 C1.45,0.25 0.25,1.45 0.25,2.92 C0.25,2.92 0.25,16.25 0.25,16.25 C0.25,17.72 1.45,18.92 2.92,18.92 C2.92,18.92 18.92,18.92 18.92,18.92 C20.38,18.92 21.58,17.72 21.58,16.25 C21.58,16.25 21.58,2.92 21.58,2.92 C21.58,1.45 20.38,0.25 18.92,0.25c M10.92 12.25 C9.45,12.25 8.25,11.05 8.25,9.58 C8.25,8.12 9.45,6.92 10.92,6.92 C12.38,6.92 13.58,8.12 13.58,9.58 C13.58,11.05 12.38,12.25 10.92,12.25c "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="pathData"
+ android:startOffset="450"
+ android:valueFrom=" M18.92 0.25 C18.92,0.25 2.92,0.25 2.92,0.25 C1.45,0.25 0.25,1.45 0.25,2.92 C0.25,2.92 0.25,16.25 0.25,16.25 C0.25,17.72 1.45,18.92 2.92,18.92 C2.92,18.92 18.92,18.92 18.92,18.92 C20.38,18.92 21.58,17.72 21.58,16.25 C21.58,16.25 21.58,2.92 21.58,2.92 C21.58,1.45 20.38,0.25 18.92,0.25c M10.92 12.25 C9.45,12.25 8.25,11.05 8.25,9.58 C8.25,8.12 9.45,6.92 10.92,6.92 C12.38,6.92 13.58,8.12 13.58,9.58 C13.58,11.05 12.38,12.25 10.92,12.25c "
+ android:valueTo=" M18.92 0.25 C18.92,0.25 2.92,0.25 2.92,0.25 C1.45,0.25 0.25,1.45 0.25,2.92 C0.25,2.92 0.25,16.25 0.25,16.25 C0.25,17.72 1.45,18.92 2.92,18.92 C2.92,18.92 18.92,18.92 18.92,18.92 C20.38,18.92 21.58,17.72 21.58,16.25 C21.58,16.25 21.58,2.92 21.58,2.92 C21.58,1.45 20.38,0.25 18.92,0.25c M10.92 12.58 C9.27,12.58 7.92,11.23 7.92,9.58 C7.92,7.93 9.27,6.58 10.92,6.58 C12.57,6.58 13.92,7.93 13.92,9.58 C13.92,11.23 12.57,12.58 10.92,12.58c "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="pathData"
+ android:startOffset="533"
+ android:valueFrom=" M18.92 0.25 C18.92,0.25 2.92,0.25 2.92,0.25 C1.45,0.25 0.25,1.45 0.25,2.92 C0.25,2.92 0.25,16.25 0.25,16.25 C0.25,17.72 1.45,18.92 2.92,18.92 C2.92,18.92 18.92,18.92 18.92,18.92 C20.38,18.92 21.58,17.72 21.58,16.25 C21.58,16.25 21.58,2.92 21.58,2.92 C21.58,1.45 20.38,0.25 18.92,0.25c M10.92 12.58 C9.27,12.58 7.92,11.23 7.92,9.58 C7.92,7.93 9.27,6.58 10.92,6.58 C12.57,6.58 13.92,7.93 13.92,9.58 C13.92,11.23 12.57,12.58 10.92,12.58c "
+ android:valueTo=" M18.92 0.25 C18.92,0.25 2.92,0.25 2.92,0.25 C1.45,0.25 0.25,1.45 0.25,2.92 C0.25,2.92 0.25,16.25 0.25,16.25 C0.25,17.72 1.45,18.92 2.92,18.92 C2.92,18.92 18.92,18.92 18.92,18.92 C20.38,18.92 21.58,17.72 21.58,16.25 C21.58,16.25 21.58,2.92 21.58,2.92 C21.58,1.45 20.38,0.25 18.92,0.25c M10.92 12.25 C9.45,12.25 8.25,11.05 8.25,9.58 C8.25,8.12 9.45,6.92 10.92,6.92 C12.38,6.92 13.58,8.12 13.58,9.58 C13.58,11.05 12.38,12.25 10.92,12.25c "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_T_1" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="400"
+ android:pathData="M 16,25C 16,25.27083334326744 16,25 16,25"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="0" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:pathData="M 16,25C 16,25.27083334326744 16,26.625 16,26.625"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="400" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:pathData="M 16,26.625C 16,26.625 16,25.27083334326744 16,25"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="517" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 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:duration="317"
+ android:propertyName="pathData"
+ android:startOffset="0"
+ android:valueFrom="M13 9 C13,7.9 12.55,6.9 11.83,6.17 C11.1,5.45 10.11,5 9,5 C6.79,5 5,6.79 5,9 C5,9 5,13 5,13 "
+ android:valueTo="M-3 6.73 C-3,5.62 -2.56,4.67 -1.84,4 C-1.11,3.32 -0.09,2.93 1.06,2.94 C3.27,2.96 5,4.54 5,6.75 C5,6.75 5,13 5,13 "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.637,0 0.437,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="pathData"
+ android:startOffset="317"
+ android:valueFrom="M-3 6.73 C-3,5.62 -2.56,4.67 -1.84,4 C-1.11,3.32 -0.09,2.93 1.06,2.94 C3.27,2.96 5,4.54 5,6.75 C5,6.75 5,13 5,13 "
+ android:valueTo="M-3 13.04 C-3,13.04 -3,9.04 -3,9.04 C-3,6.83 -1.25,5.05 0.69,5.01 C2.9,4.97 5,6.79 5,9 C5,9 5,13 5,13 "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.497,0 0.408,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_N_3_T_1" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="400"
+ android:pathData="M 16,25C 16,25.27083334326744 16,25 16,25"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="0" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:pathData="M 16,25C 16,25.27083334326744 16,26.625 16,26.625"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="400" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:pathData="M 16,26.625C 16,26.625 16,25.27083334326744 16,25"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="517" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,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:duration="717"
+ android:propertyName="translateX"
+ 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/anim/lock_lock_rounded.xml b/packages/SystemUI/res/anim/lock_lock_rounded.xml
new file mode 100644
index 000000000000..fc4545c4323d
--- /dev/null
+++ b/packages/SystemUI/res/anim/lock_lock_rounded.xml
@@ -0,0 +1,314 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <aapt:attr name="android:drawable" >
+ <vector
+ android:height="42dp"
+ android:viewportHeight="42"
+ android:viewportWidth="32"
+ android:width="32dp" >
+ <group android:name="_R_G" >
+ <group
+ android:name="_R_G_L_2_G_T_1"
+ android:translateX="16"
+ android:translateY="25" >
+ <group
+ android:name="_R_G_L_2_G"
+ android:translateX="-14.667"
+ android:translateY="-12.667" >
+ <path
+ android:name="_R_G_L_2_G_D_0_P_0"
+ android:pathData=" M22.09 5 C22.09,5 6,5 6,5 C5.45,5 5,5.45 5,6 C5,6 5,19.33 5,19.33 C5,19.89 5.45,20.33 6,20.33 C6,20.33 23.33,20.33 23.33,20.33 C23.89,20.33 24.33,19.89 24.33,19.33 C24.33,19.33 24.33,6 24.33,6 C24.33,5.45 23.89,5 23.33,5 C23.33,5 22.09,5 22.09,5c "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="1.5" />
+ </group>
+ </group>
+ <group
+ android:name="_R_G_L_1_G_N_5_T_1"
+ android:translateX="16"
+ android:translateY="25" >
+ <group
+ android:name="_R_G_L_1_G_N_5_T_0"
+ android:translateX="-14.667"
+ android:translateY="-12.667" >
+ <group
+ android:name="_R_G_L_1_G"
+ android:pivotX="2.25"
+ android:pivotY="2.25"
+ android:scaleX="1"
+ android:scaleY="1"
+ android:translateX="12.416"
+ android:translateY="10.417" >
+ <path
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:fillType="nonZero"
+ android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c " />
+ </group>
+ </group>
+ </group>
+ <group
+ android:name="_R_G_L_0_G_N_5_T_1"
+ android:translateX="16"
+ android:translateY="25" >
+ <group
+ android:name="_R_G_L_0_G_N_5_T_0"
+ android:translateX="-14.667"
+ android:translateY="-12.667" >
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="5.333"
+ android:translateY="-9.425999999999998" >
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:pathData=" M13.67 13.8 C13.67,13.8 13.67,8.94 13.67,8.94 C13.68,6.62 15.69,5.03 18.01,5.04 C20.46,5.04 22.32,6.89 22.34,8.85 C22.34,8.85 22.33,8.89 22.33,8.89 "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="1.5" />
+ </group>
+ </group>
+ </group>
+ </group>
+ <group android:name="time_group" />
+ </vector>
+ </aapt:attr>
+
+ <target android:name="_R_G_L_2_G_T_1" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="400"
+ android:pathData="M 16,25C 16,25.35416665673256 16,25 16,25"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="0" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:pathData="M 16,25C 16,25.35416665673256 16,27.125 16,27.125"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="400" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:pathData="M 16,27.125C 16,27.125 16,25.35416665673256 16,25"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="517" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,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:duration="450"
+ android:propertyName="scaleX"
+ 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.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="450"
+ android:propertyName="scaleY"
+ 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.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ android:startOffset="450"
+ android:valueFrom="1"
+ android:valueTo="1.12"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ android:startOffset="450"
+ android:valueFrom="1"
+ android:valueTo="1.12"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="scaleX"
+ android:startOffset="533"
+ android:valueFrom="1.12"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="scaleY"
+ android:startOffset="533"
+ android:valueFrom="1.12"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_N_5_T_1" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="400"
+ android:pathData="M 16,25C 16,25.35416665673256 16,25 16,25"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="0" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:pathData="M 16,25C 16,25.35416665673256 16,27.125 16,27.125"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="400" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:pathData="M 16,27.125C 16,27.125 16,25.35416665673256 16,25"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="517" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 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:duration="317"
+ android:propertyName="pathData"
+ android:startOffset="0"
+ android:valueFrom="M13.67 13.8 C13.67,13.8 13.67,8.94 13.67,8.94 C13.68,6.62 15.69,5.03 18.01,5.04 C20.46,5.04 22.32,6.89 22.34,8.85 C22.34,8.85 22.33,8.89 22.33,8.89 "
+ android:valueTo="M13.67 13.8 C13.67,13.8 13.69,5.06 13.69,5.06 C13.65,2.87 11.71,1.13 9.35,1.16 C7,1.13 5.06,2.87 5.02,5.06 C5.02,5.06 5,7.93 5,7.93 "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.825,0 0.321,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="pathData"
+ android:startOffset="317"
+ android:valueFrom="M13.67 13.8 C13.67,13.8 13.69,5.06 13.69,5.06 C13.65,2.87 11.71,1.13 9.35,1.16 C7,1.13 5.06,2.87 5.02,5.06 C5.02,5.06 5,7.93 5,7.93 "
+ android:valueTo="M13.67 13.8 C13.67,13.8 13.67,8.94 13.67,8.94 C13.63,6.75 11.69,5 9.33,5.04 C6.98,5 5.04,6.75 5,8.94 C5,8.94 5,13.8 5,13.8 "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.683,0 0.342,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_N_5_T_1" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="400"
+ android:pathData="M 16,25C 16,25.35416665673256 16,25 16,25"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="0" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:pathData="M 16,25C 16,25.35416665673256 16,27.125 16,27.125"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="400" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:pathData="M 16,27.125C 16,27.125 16,25.35416665673256 16,25"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="517" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,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:duration="717"
+ android:propertyName="translateX"
+ 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/core/res/res/anim/lock_scanning.xml b/packages/SystemUI/res/anim/lock_scanning.xml
index db7972f542b3..db7972f542b3 100644
--- a/core/res/res/anim/lock_scanning.xml
+++ b/packages/SystemUI/res/anim/lock_scanning.xml
diff --git a/packages/SystemUI/res/anim/lock_scanning_circular.xml b/packages/SystemUI/res/anim/lock_scanning_circular.xml
new file mode 100644
index 000000000000..9468213562f4
--- /dev/null
+++ b/packages/SystemUI/res/anim/lock_scanning_circular.xml
@@ -0,0 +1,537 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <aapt:attr name="android:drawable" >
+ <vector
+ android:height="42dp"
+ android:viewportHeight="42"
+ android:viewportWidth="32"
+ android:width="32dp" >
+ <group android:name="_R_G" >
+ <group
+ android:name="_R_G_L_2_G"
+ android:pivotX="9.583"
+ android:pivotY="8.916"
+ android:scaleX="1"
+ android:scaleY="1"
+ android:translateX="6.416"
+ android:translateY="15.416999999999998" >
+ <path
+ android:name="_R_G_L_2_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:fillType="nonZero"
+ android:pathData=" M17.42 1.75 C17.42,1.75 17.42,14.58 17.42,14.58 C17.42,15.41 16.74,16.08 15.92,16.08 C15.92,16.08 3.25,16.08 3.25,16.08 C2.42,16.08 1.75,15.41 1.75,14.58 C1.75,14.58 1.75,1.75 1.75,1.75 C1.75,1.75 17.42,1.75 17.42,1.75c M18.92 0.25 C18.92,0.25 0.25,0.25 0.25,0.25 C0.25,0.25 0.25,14.58 0.25,14.58 C0.25,16.24 1.59,17.58 3.25,17.58 C3.25,17.58 15.92,17.58 15.92,17.58 C17.57,17.58 18.92,16.24 18.92,14.58 C18.92,14.58 18.92,0.25 18.92,0.25c " />
+ </group>
+ <group
+ android:name="_R_G_L_1_G_N_3_T_0"
+ android:pivotX="9.583"
+ android:pivotY="8.916"
+ android:scaleX="1"
+ android:scaleY="1"
+ android:translateX="6.416"
+ android:translateY="15.416999999999998" >
+ <group
+ android:name="_R_G_L_1_G"
+ android:pivotX="2.25"
+ android:pivotY="3.334"
+ android:scaleX="1"
+ android:scaleY="1"
+ android:translateX="7.334"
+ android:translateY="5.333" >
+ <path
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:fillType="nonZero"
+ android:pathData=" M4.25 2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25 C3.35,0.25 4.25,1.15 4.25,2.25c " />
+ <path
+ android:name="_R_G_L_1_G_D_1_P_0"
+ android:pathData=" M2.25 2.25 C2.25,2.25 2.25,5.92 2.25,5.92 "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="1.5" />
+ </group>
+ </group>
+ <group
+ android:name="_R_G_L_0_G_N_3_T_0"
+ android:pivotX="9.583"
+ android:pivotY="8.916"
+ android:scaleX="1"
+ android:scaleY="1"
+ android:translateX="6.416"
+ android:translateY="15.416999999999998" >
+ <group
+ android:name="_R_G_L_0_G_T_1"
+ android:translateX="9.583"
+ android:translateY="-3.662" >
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="-8.083"
+ android:translateY="-8.173" >
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:pathData=" M12.42 12.6 C12.42,12.6 12.42,8.17 12.42,8.17 C12.42,5.83 10.48,3.75 8.08,3.75 C5.69,3.75 3.75,5.83 3.75,8.17 C3.75,8.17 3.75,12.6 3.75,12.6 "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="1.5" />
+ </group>
+ </group>
+ </group>
+ </group>
+ <group android:name="time_group" />
+ </vector>
+ </aapt:attr>
+
+ <target android:name="_R_G_L_2_G" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ 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.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ 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.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ android:startOffset="83"
+ android:valueFrom="1"
+ android:valueTo="0.9500000000000001"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ android:startOffset="83"
+ android:valueFrom="1"
+ android:valueTo="0.9500000000000001"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="183"
+ android:propertyName="scaleX"
+ android:startOffset="167"
+ android:valueFrom="0.9500000000000001"
+ android:valueTo="1.2"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.461,0 0.526,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="183"
+ android:propertyName="scaleY"
+ android:startOffset="167"
+ android:valueFrom="0.9500000000000001"
+ android:valueTo="1.2"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.461,0 0.526,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleX"
+ android:startOffset="350"
+ android:valueFrom="1.2"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.428,0 0.532,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleY"
+ android:startOffset="350"
+ android:valueFrom="1.2"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.428,0 0.532,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:duration="150"
+ android:propertyName="scaleX"
+ 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.613,0 0.396,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="150"
+ android:propertyName="scaleY"
+ 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.613,0 0.396,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="scaleX"
+ android:startOffset="150"
+ android:valueFrom="1"
+ android:valueTo="0.6"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.613,0 0.396,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="scaleY"
+ android:startOffset="150"
+ android:valueFrom="1"
+ android:valueTo="0.6"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.613,0 0.396,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="317"
+ android:propertyName="scaleX"
+ android:startOffset="267"
+ android:valueFrom="0.6"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.429,0 0.613,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="317"
+ android:propertyName="scaleY"
+ android:startOffset="267"
+ android:valueFrom="0.6"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.429,0 0.613,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_N_3_T_0" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ 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.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ 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.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ android:startOffset="83"
+ android:valueFrom="1"
+ android:valueTo="0.9500000000000001"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ android:startOffset="83"
+ android:valueFrom="1"
+ android:valueTo="0.9500000000000001"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="183"
+ android:propertyName="scaleX"
+ android:startOffset="167"
+ android:valueFrom="0.9500000000000001"
+ android:valueTo="1.2"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.461,0 0.526,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="183"
+ android:propertyName="scaleY"
+ android:startOffset="167"
+ android:valueFrom="0.9500000000000001"
+ android:valueTo="1.2"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.461,0 0.526,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleX"
+ android:startOffset="350"
+ android:valueFrom="1.2"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.428,0 0.532,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleY"
+ android:startOffset="350"
+ android:valueFrom="1.2"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.428,0 0.532,1 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:duration="83"
+ android:propertyName="pathData"
+ android:startOffset="0"
+ android:valueFrom="M12.42 12.6 C12.42,12.6 12.42,8.17 12.42,8.17 C12.42,5.83 10.48,3.75 8.08,3.75 C5.69,3.75 3.75,5.83 3.75,8.17 C3.75,8.17 3.75,12.6 3.75,12.6 "
+ android:valueTo="M12.42 12.6 C12.42,12.6 12.42,8.17 12.42,8.17 C12.42,5.83 10.48,3.75 8.08,3.75 C5.69,3.75 3.75,5.83 3.75,8.17 C3.75,8.17 3.75,12.6 3.75,12.6 "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="167"
+ android:propertyName="pathData"
+ android:startOffset="83"
+ android:valueFrom="M12.42 12.6 C12.42,12.6 12.42,8.17 12.42,8.17 C12.42,5.83 10.48,3.75 8.08,3.75 C5.69,3.75 3.75,5.83 3.75,8.17 C3.75,8.17 3.75,12.6 3.75,12.6 "
+ android:valueTo="M12.39 9.16 C12.39,9.16 12.42,8.17 12.42,8.17 C12.42,5.83 10.48,3.75 8.08,3.75 C5.69,3.75 3.75,5.83 3.75,8.17 C3.75,8.17 3.73,9.16 3.73,9.16 "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="pathData"
+ android:startOffset="250"
+ android:valueFrom="M12.39 9.16 C12.39,9.16 12.42,8.17 12.42,8.17 C12.42,5.83 10.48,3.75 8.08,3.75 C5.69,3.75 3.75,5.83 3.75,8.17 C3.75,8.17 3.73,9.16 3.73,9.16 "
+ android:valueTo="M12.42 12.6 C12.42,12.6 12.42,8.17 12.42,8.17 C12.42,5.83 10.48,3.75 8.08,3.75 C5.69,3.75 3.75,5.83 3.75,8.17 C3.75,8.17 3.75,12.6 3.75,12.6 "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_T_1" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="83"
+ android:pathData="M 9.583,-3.662C 9.583,-3.03073584985733 9.583,-3.662 9.583,-3.662"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="0" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="167"
+ android:pathData="M 9.583,-3.662C 9.583,-3.03073584985733 9.583,0.126 9.583,0.126"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="83" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:pathData="M 9.583,0.126C 9.583,0.126 9.583,-3.03073584985733 9.583,-3.662"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="250" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_N_3_T_0" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ 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.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ 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.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ android:startOffset="83"
+ android:valueFrom="1"
+ android:valueTo="0.9500000000000001"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ android:startOffset="83"
+ android:valueFrom="1"
+ android:valueTo="0.9500000000000001"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="183"
+ android:propertyName="scaleX"
+ android:startOffset="167"
+ android:valueFrom="0.9500000000000001"
+ android:valueTo="1.2"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.461,0 0.526,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="183"
+ android:propertyName="scaleY"
+ android:startOffset="167"
+ android:valueFrom="0.9500000000000001"
+ android:valueTo="1.2"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.461,0 0.526,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleX"
+ android:startOffset="350"
+ android:valueFrom="1.2"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.428,0 0.532,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleY"
+ android:startOffset="350"
+ android:valueFrom="1.2"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.428,0 0.532,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:duration="717"
+ android:propertyName="translateX"
+ 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/anim/lock_scanning_filled.xml b/packages/SystemUI/res/anim/lock_scanning_filled.xml
new file mode 100644
index 000000000000..83ac8ad205f7
--- /dev/null
+++ b/packages/SystemUI/res/anim/lock_scanning_filled.xml
@@ -0,0 +1,339 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <aapt:attr name="android:drawable" >
+ <vector
+ android:height="42dp"
+ android:viewportHeight="42"
+ android:viewportWidth="32"
+ android:width="32dp" >
+ <group android:name="_R_G" >
+ <group
+ android:name="_R_G_L_1_G"
+ android:pivotX="10.917"
+ android:pivotY="9.583"
+ android:scaleX="1"
+ android:scaleY="1"
+ android:translateX="5.083"
+ android:translateY="15.417" >
+ <path
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:fillType="nonZero"
+ android:pathData=" M18.92 0.25 C18.92,0.25 2.92,0.25 2.92,0.25 C1.45,0.25 0.25,1.45 0.25,2.92 C0.25,2.92 0.25,16.25 0.25,16.25 C0.25,17.72 1.45,18.92 2.92,18.92 C2.92,18.92 18.92,18.92 18.92,18.92 C20.38,18.92 21.58,17.72 21.58,16.25 C21.58,16.25 21.58,2.92 21.58,2.92 C21.58,1.45 20.38,0.25 18.92,0.25c M10.92 12.25 C9.45,12.25 8.25,11.05 8.25,9.58 C8.25,8.12 9.45,6.92 10.92,6.92 C12.38,6.92 13.58,8.12 13.58,9.58 C13.58,11.05 12.38,12.25 10.92,12.25c " />
+ </group>
+ <group
+ android:name="_R_G_L_0_G_N_2_T_0"
+ android:pivotX="10.917"
+ android:pivotY="9.583"
+ android:scaleX="1"
+ android:scaleY="1"
+ android:translateX="5.083"
+ android:translateY="15.417" >
+ <group
+ android:name="_R_G_L_0_G_T_1"
+ android:translateX="10.917"
+ android:translateY="-3.75" >
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="-9"
+ android:translateY="-9" >
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:pathData=" M13 13 C13,13 13,9 13,9 C13,6.79 11.21,5 9,5 C6.79,5 5,6.79 5,9 C5,9 5,13 5,13 "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="2" />
+ </group>
+ </group>
+ </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:duration="150"
+ android:propertyName="pathData"
+ android:startOffset="0"
+ android:valueFrom=" M18.92 0.25 C18.92,0.25 2.92,0.25 2.92,0.25 C1.45,0.25 0.25,1.45 0.25,2.92 C0.25,2.92 0.25,16.25 0.25,16.25 C0.25,17.72 1.45,18.92 2.92,18.92 C2.92,18.92 18.92,18.92 18.92,18.92 C20.38,18.92 21.58,17.72 21.58,16.25 C21.58,16.25 21.58,2.92 21.58,2.92 C21.58,1.45 20.38,0.25 18.92,0.25c M10.92 12.25 C9.45,12.25 8.25,11.05 8.25,9.58 C8.25,8.12 9.45,6.92 10.92,6.92 C12.38,6.92 13.58,8.12 13.58,9.58 C13.58,11.05 12.38,12.25 10.92,12.25c "
+ android:valueTo=" M18.92 0.25 C18.92,0.25 2.92,0.25 2.92,0.25 C1.45,0.25 0.25,1.45 0.25,2.92 C0.25,2.92 0.25,16.25 0.25,16.25 C0.25,17.72 1.45,18.92 2.92,18.92 C2.92,18.92 18.92,18.92 18.92,18.92 C20.38,18.92 21.58,17.72 21.58,16.25 C21.58,16.25 21.58,2.92 21.58,2.92 C21.58,1.45 20.38,0.25 18.92,0.25c M10.92 12.25 C9.45,12.25 8.25,11.05 8.25,9.58 C8.25,8.12 9.45,6.92 10.92,6.92 C12.38,6.92 13.58,8.12 13.58,9.58 C13.58,11.05 12.38,12.25 10.92,12.25c "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="pathData"
+ android:startOffset="150"
+ android:valueFrom=" M18.92 0.25 C18.92,0.25 2.92,0.25 2.92,0.25 C1.45,0.25 0.25,1.45 0.25,2.92 C0.25,2.92 0.25,16.25 0.25,16.25 C0.25,17.72 1.45,18.92 2.92,18.92 C2.92,18.92 18.92,18.92 18.92,18.92 C20.38,18.92 21.58,17.72 21.58,16.25 C21.58,16.25 21.58,2.92 21.58,2.92 C21.58,1.45 20.38,0.25 18.92,0.25c M10.92 12.25 C9.45,12.25 8.25,11.05 8.25,9.58 C8.25,8.12 9.45,6.92 10.92,6.92 C12.38,6.92 13.58,8.12 13.58,9.58 C13.58,11.05 12.38,12.25 10.92,12.25c "
+ android:valueTo=" M18.92 0.25 C18.92,0.25 2.92,0.25 2.92,0.25 C1.45,0.25 0.25,1.45 0.25,2.92 C0.25,2.92 0.25,16.25 0.25,16.25 C0.25,17.72 1.45,18.92 2.92,18.92 C2.92,18.92 18.92,18.92 18.92,18.92 C20.38,18.92 21.58,17.72 21.58,16.25 C21.58,16.25 21.58,2.92 21.58,2.92 C21.58,1.45 20.38,0.25 18.92,0.25c M10.92 11.4 C9.91,11.4 9.1,10.59 9.1,9.58 C9.1,8.58 9.91,7.76 10.92,7.76 C11.92,7.76 12.74,8.58 12.74,9.58 C12.74,10.59 11.92,11.4 10.92,11.4c "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="317"
+ android:propertyName="pathData"
+ android:startOffset="267"
+ android:valueFrom=" M18.92 0.25 C18.92,0.25 2.92,0.25 2.92,0.25 C1.45,0.25 0.25,1.45 0.25,2.92 C0.25,2.92 0.25,16.25 0.25,16.25 C0.25,17.72 1.45,18.92 2.92,18.92 C2.92,18.92 18.92,18.92 18.92,18.92 C20.38,18.92 21.58,17.72 21.58,16.25 C21.58,16.25 21.58,2.92 21.58,2.92 C21.58,1.45 20.38,0.25 18.92,0.25c M10.92 11.4 C9.91,11.4 9.1,10.59 9.1,9.58 C9.1,8.58 9.91,7.76 10.92,7.76 C11.92,7.76 12.74,8.58 12.74,9.58 C12.74,10.59 11.92,11.4 10.92,11.4c "
+ android:valueTo=" M18.92 0.25 C18.92,0.25 2.92,0.25 2.92,0.25 C1.45,0.25 0.25,1.45 0.25,2.92 C0.25,2.92 0.25,16.25 0.25,16.25 C0.25,17.72 1.45,18.92 2.92,18.92 C2.92,18.92 18.92,18.92 18.92,18.92 C20.38,18.92 21.58,17.72 21.58,16.25 C21.58,16.25 21.58,2.92 21.58,2.92 C21.58,1.45 20.38,0.25 18.92,0.25c M10.92 12.25 C9.45,12.25 8.25,11.05 8.25,9.58 C8.25,8.12 9.45,6.92 10.92,6.92 C12.38,6.92 13.58,8.12 13.58,9.58 C13.58,11.05 12.38,12.25 10.92,12.25c "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,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:duration="83"
+ android:propertyName="scaleX"
+ 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.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ 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.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ android:startOffset="83"
+ android:valueFrom="1"
+ android:valueTo="0.9500000000000001"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ android:startOffset="83"
+ android:valueFrom="1"
+ android:valueTo="0.9500000000000001"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="183"
+ android:propertyName="scaleX"
+ android:startOffset="167"
+ android:valueFrom="0.9500000000000001"
+ android:valueTo="1.2"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.461,0 0.526,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="183"
+ android:propertyName="scaleY"
+ android:startOffset="167"
+ android:valueFrom="0.9500000000000001"
+ android:valueTo="1.2"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.461,0 0.526,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleX"
+ android:startOffset="350"
+ android:valueFrom="1.2"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.428,0 0.532,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleY"
+ android:startOffset="350"
+ android:valueFrom="1.2"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.428,0 0.532,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_T_1" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="83"
+ android:pathData="M 10.917,-3.75C 10.917,-3.13846284151077 10.917,-3.75 10.917,-3.75"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="0" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="167"
+ android:pathData="M 10.917,-3.75C 10.917,-3.13846284151077 10.917,-0.081 10.917,-0.081"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="83" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:pathData="M 10.917,-0.081C 10.917,-0.081 10.917,-3.13846284151077 10.917,-3.75"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="250" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_N_2_T_0" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ 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.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ 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.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ android:startOffset="83"
+ android:valueFrom="1"
+ android:valueTo="0.9500000000000001"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ android:startOffset="83"
+ android:valueFrom="1"
+ android:valueTo="0.9500000000000001"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="183"
+ android:propertyName="scaleX"
+ android:startOffset="167"
+ android:valueFrom="0.9500000000000001"
+ android:valueTo="1.2"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.461,0 0.526,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="183"
+ android:propertyName="scaleY"
+ android:startOffset="167"
+ android:valueFrom="0.9500000000000001"
+ android:valueTo="1.2"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.461,0 0.526,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleX"
+ android:startOffset="350"
+ android:valueFrom="1.2"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.428,0 0.532,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleY"
+ android:startOffset="350"
+ android:valueFrom="1.2"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.428,0 0.532,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:duration="717"
+ android:propertyName="translateX"
+ 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/anim/lock_scanning_rounded.xml b/packages/SystemUI/res/anim/lock_scanning_rounded.xml
new file mode 100644
index 000000000000..983549230b54
--- /dev/null
+++ b/packages/SystemUI/res/anim/lock_scanning_rounded.xml
@@ -0,0 +1,531 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <aapt:attr name="android:drawable" >
+ <vector
+ android:height="38dp"
+ android:viewportHeight="38"
+ android:viewportWidth="32"
+ android:width="32dp" >
+ <group android:name="_R_G" >
+ <group
+ android:name="_R_G_L_2_G"
+ android:pivotX="14.667"
+ android:pivotY="12.667"
+ android:scaleX="1"
+ android:scaleY="1"
+ android:translateX="1.3330000000000002"
+ android:translateY="10.333" >
+ <path
+ android:name="_R_G_L_2_G_D_0_P_0"
+ android:pathData=" M22.09 5 C22.09,5 6,5 6,5 C5.45,5 5,5.45 5,6 C5,6 5,19.33 5,19.33 C5,19.89 5.45,20.33 6,20.33 C6,20.33 23.33,20.33 23.33,20.33 C23.89,20.33 24.33,19.89 24.33,19.33 C24.33,19.33 24.33,6 24.33,6 C24.33,5.45 23.89,5 23.33,5 C23.33,5 22.09,5 22.09,5c "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="1.5" />
+ </group>
+ <group
+ android:name="_R_G_L_1_G_N_4_T_0"
+ android:pivotX="14.667"
+ android:pivotY="12.667"
+ android:scaleX="1"
+ android:scaleY="1"
+ android:translateX="1.3330000000000002"
+ android:translateY="10.333" >
+ <group
+ android:name="_R_G_L_1_G"
+ android:pivotX="2.25"
+ android:pivotY="2.25"
+ android:scaleX="1"
+ android:scaleY="1"
+ android:translateX="12.416"
+ android:translateY="10.417" >
+ <path
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:fillType="nonZero"
+ android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c " />
+ </group>
+ </group>
+ <group
+ android:name="_R_G_L_0_G_N_4_T_0"
+ android:pivotX="14.667"
+ android:pivotY="12.667"
+ android:scaleX="1"
+ android:scaleY="1"
+ android:translateX="1.3330000000000002"
+ android:translateY="10.333" >
+ <group
+ android:name="_R_G_L_0_G_T_1"
+ android:translateX="14.666"
+ android:translateY="0.287" >
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="-9.333"
+ android:translateY="-9.713" >
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:pathData=" M13.67 13.8 C13.67,13.8 13.67,8.94 13.67,8.94 C13.63,6.75 11.69,5 9.33,5.04 C6.98,5 5.04,6.75 5,8.94 C5,8.94 5,13.8 5,13.8 "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="1.5" />
+ </group>
+ </group>
+ </group>
+ </group>
+ <group android:name="time_group" />
+ </vector>
+ </aapt:attr>
+
+ <target android:name="_R_G_L_2_G" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ 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.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ 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.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ android:startOffset="83"
+ android:valueFrom="1"
+ android:valueTo="0.9500000000000001"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ android:startOffset="83"
+ android:valueFrom="1"
+ android:valueTo="0.9500000000000001"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="183"
+ android:propertyName="scaleX"
+ android:startOffset="167"
+ android:valueFrom="0.9500000000000001"
+ android:valueTo="1.2"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.461,0 0.526,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="183"
+ android:propertyName="scaleY"
+ android:startOffset="167"
+ android:valueFrom="0.9500000000000001"
+ android:valueTo="1.2"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.461,0 0.526,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleX"
+ android:startOffset="350"
+ android:valueFrom="1.2"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.428,0 0.397,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleY"
+ android:startOffset="350"
+ android:valueFrom="1.2"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.428,0 0.397,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:duration="150"
+ android:propertyName="scaleX"
+ 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.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="150"
+ android:propertyName="scaleY"
+ 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.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="scaleX"
+ android:startOffset="150"
+ android:valueFrom="1"
+ android:valueTo="0.8"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="117"
+ android:propertyName="scaleY"
+ android:startOffset="150"
+ android:valueFrom="1"
+ android:valueTo="0.8"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="317"
+ android:propertyName="scaleX"
+ android:startOffset="267"
+ android:valueFrom="0.8"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="317"
+ android:propertyName="scaleY"
+ android:startOffset="267"
+ android:valueFrom="0.8"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_N_4_T_0" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ 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.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ 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.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ android:startOffset="83"
+ android:valueFrom="1"
+ android:valueTo="0.9500000000000001"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ android:startOffset="83"
+ android:valueFrom="1"
+ android:valueTo="0.9500000000000001"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="183"
+ android:propertyName="scaleX"
+ android:startOffset="167"
+ android:valueFrom="0.9500000000000001"
+ android:valueTo="1.2"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.461,0 0.526,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="183"
+ android:propertyName="scaleY"
+ android:startOffset="167"
+ android:valueFrom="0.9500000000000001"
+ android:valueTo="1.2"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.461,0 0.526,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleX"
+ android:startOffset="350"
+ android:valueFrom="1.2"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.428,0 0.397,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleY"
+ android:startOffset="350"
+ android:valueFrom="1.2"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.428,0 0.397,1 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:duration="83"
+ android:propertyName="pathData"
+ android:startOffset="0"
+ android:valueFrom="M13.67 13.8 C13.67,13.8 13.67,8.94 13.67,8.94 C13.63,6.75 11.69,5 9.33,5.04 C6.98,5 5.04,6.75 5,8.94 C5,8.94 5,13.8 5,13.8 "
+ android:valueTo="M13.67 13.8 C13.67,13.8 13.67,8.94 13.67,8.94 C13.63,6.75 11.69,5 9.33,5.04 C6.98,5 5.04,6.75 5,8.94 C5,8.94 5,13.8 5,13.8 "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="167"
+ android:propertyName="pathData"
+ android:startOffset="83"
+ android:valueFrom="M13.67 13.8 C13.67,13.8 13.67,8.94 13.67,8.94 C13.63,6.75 11.69,5 9.33,5.04 C6.98,5 5.04,6.75 5,8.94 C5,8.94 5,13.8 5,13.8 "
+ android:valueTo="M13.7 10.21 C13.7,10.21 13.67,8.94 13.67,8.94 C13.63,6.75 11.69,5 9.33,5.04 C6.98,5 5.04,6.75 5,8.94 C5,8.94 5.03,10.21 5.03,10.21 "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="pathData"
+ android:startOffset="250"
+ android:valueFrom="M13.7 10.21 C13.7,10.21 13.67,8.94 13.67,8.94 C13.63,6.75 11.69,5 9.33,5.04 C6.98,5 5.04,6.75 5,8.94 C5,8.94 5.03,10.21 5.03,10.21 "
+ android:valueTo="M13.67 13.8 C13.67,13.8 13.67,8.94 13.67,8.94 C13.63,6.75 11.69,5 9.33,5.04 C6.98,5 5.04,6.75 5,8.94 C5,8.94 5,13.8 5,13.8 "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_T_1" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="83"
+ android:pathData="M 14.666,0.287C 14.666,0.8689466710090599 14.666,0.287 14.666,0.287"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="0" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="167"
+ android:pathData="M 14.666,0.287C 14.666,0.8689466710090599 14.666,3.779 14.666,3.779"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="83" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:pathData="M 14.666,3.779C 14.666,3.779 14.666,0.8689466710090599 14.666,0.287"
+ android:propertyName="translateXY"
+ android:propertyXName="translateX"
+ android:propertyYName="translateY"
+ android:startOffset="250" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_N_4_T_0" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ 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.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ 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.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleX"
+ android:startOffset="83"
+ android:valueFrom="1"
+ android:valueTo="0.9500000000000001"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="scaleY"
+ android:startOffset="83"
+ android:valueFrom="1"
+ android:valueTo="0.9500000000000001"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.36,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="183"
+ android:propertyName="scaleX"
+ android:startOffset="167"
+ android:valueFrom="0.9500000000000001"
+ android:valueTo="1.2"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.461,0 0.526,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="183"
+ android:propertyName="scaleY"
+ android:startOffset="167"
+ android:valueFrom="0.9500000000000001"
+ android:valueTo="1.2"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.461,0 0.526,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleX"
+ android:startOffset="350"
+ android:valueFrom="1.2"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.428,0 0.397,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="233"
+ android:propertyName="scaleY"
+ android:startOffset="350"
+ android:valueFrom="1.2"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.428,0 0.397,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:duration="717"
+ android:propertyName="translateX"
+ 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/core/res/res/anim/lock_to_error.xml b/packages/SystemUI/res/anim/lock_to_error.xml
index e356f26dde59..e356f26dde59 100644
--- a/core/res/res/anim/lock_to_error.xml
+++ b/packages/SystemUI/res/anim/lock_to_error.xml
diff --git a/packages/SystemUI/res/anim/lock_to_error_circular.xml b/packages/SystemUI/res/anim/lock_to_error_circular.xml
new file mode 100644
index 000000000000..9a847232d80b
--- /dev/null
+++ b/packages/SystemUI/res/anim/lock_to_error_circular.xml
@@ -0,0 +1,276 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <aapt:attr name="android:drawable" >
+ <vector
+ android:height="32dp"
+ android:viewportHeight="32"
+ android:viewportWidth="32"
+ android:width="32dp" >
+ <group android:name="_R_G" >
+ <group
+ android:name="_R_G_L_2_G"
+ android:pivotX="9.583"
+ android:pivotY="8.916"
+ android:rotation="0"
+ android:translateX="6.416"
+ android:translateY="10.416999999999998" >
+ <path
+ android:name="_R_G_L_2_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:fillType="nonZero"
+ android:pathData=" M17.42 1.75 C17.42,1.75 17.42,14.58 17.42,14.58 C17.42,15.41 16.74,16.08 15.92,16.08 C15.92,16.08 3.25,16.08 3.25,16.08 C2.42,16.08 1.75,15.41 1.75,14.58 C1.75,14.58 1.75,1.75 1.75,1.75 C1.75,1.75 17.42,1.75 17.42,1.75c M18.92 0.25 C18.92,0.25 0.25,0.25 0.25,0.25 C0.25,0.25 0.25,14.58 0.25,14.58 C0.25,16.24 1.59,17.58 3.25,17.58 C3.25,17.58 15.92,17.58 15.92,17.58 C17.57,17.58 18.92,16.24 18.92,14.58 C18.92,14.58 18.92,0.25 18.92,0.25c " />
+ </group>
+ <group
+ android:name="_R_G_L_1_G_N_3_T_0"
+ android:pivotX="9.583"
+ android:pivotY="8.916"
+ android:rotation="0"
+ android:translateX="6.416"
+ android:translateY="10.416999999999998" >
+ <group
+ android:name="_R_G_L_1_G"
+ android:translateX="7.334"
+ android:translateY="5.333" >
+ <path
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:fillType="nonZero"
+ android:pathData=" M4.25 2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25 C3.35,0.25 4.25,1.15 4.25,2.25c " />
+ <path
+ android:name="_R_G_L_1_G_D_1_P_0"
+ android:pathData=" M2.25 2.25 C2.25,2.25 2.25,5.92 2.25,5.92 "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="1.5" />
+ </group>
+ </group>
+ <group
+ android:name="_R_G_L_0_G_N_3_T_0"
+ android:pivotX="9.583"
+ android:pivotY="8.916"
+ android:rotation="0"
+ android:translateX="6.416"
+ android:translateY="10.416999999999998" >
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="1.5"
+ android:translateY="-11.835" >
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:pathData=" M12.42 12.6 C12.42,12.6 12.42,8.17 12.42,8.17 C12.42,5.83 10.48,3.75 8.08,3.75 C5.69,3.75 3.75,5.83 3.75,8.17 C3.75,8.17 3.75,12.6 3.75,12.6 "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="1.5" />
+ </group>
+ </group>
+ </group>
+ <group android:name="time_group" />
+ </vector>
+ </aapt:attr>
+
+ <target android:name="_R_G_L_2_G" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="rotation"
+ 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.44,0 0.601,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="120"
+ android:propertyName="rotation"
+ android:startOffset="133"
+ android:valueFrom="0"
+ android:valueTo="-10"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.44,0 0.601,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="97"
+ android:propertyName="rotation"
+ android:startOffset="253"
+ android:valueFrom="-10"
+ android:valueTo="10"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.531,0 0.389,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="rotation"
+ android:startOffset="350"
+ android:valueFrom="10"
+ android:valueTo="-5"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.499,0 0.489,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="167"
+ android:propertyName="rotation"
+ android:startOffset="450"
+ android:valueFrom="-5"
+ android:valueTo="0"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.293,0 0.689,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_N_3_T_0" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="rotation"
+ 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.44,0 0.601,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="120"
+ android:propertyName="rotation"
+ android:startOffset="133"
+ android:valueFrom="0"
+ android:valueTo="-10"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.44,0 0.601,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="97"
+ android:propertyName="rotation"
+ android:startOffset="253"
+ android:valueFrom="-10"
+ android:valueTo="10"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.531,0 0.389,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="rotation"
+ android:startOffset="350"
+ android:valueFrom="10"
+ android:valueTo="-5"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.499,0 0.489,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="167"
+ android:propertyName="rotation"
+ android:startOffset="450"
+ android:valueFrom="-5"
+ android:valueTo="0"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.293,0 0.689,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_N_3_T_0" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="rotation"
+ 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.44,0 0.601,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="120"
+ android:propertyName="rotation"
+ android:startOffset="133"
+ android:valueFrom="0"
+ android:valueTo="-10"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.44,0 0.601,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="97"
+ android:propertyName="rotation"
+ android:startOffset="253"
+ android:valueFrom="-10"
+ android:valueTo="10"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.531,0 0.389,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="rotation"
+ android:startOffset="350"
+ android:valueFrom="10"
+ android:valueTo="-5"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.499,0 0.489,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="167"
+ android:propertyName="rotation"
+ android:startOffset="450"
+ android:valueFrom="-5"
+ android:valueTo="0"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.293,0 0.689,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:duration="717"
+ android:propertyName="translateX"
+ 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/anim/lock_to_error_filled.xml b/packages/SystemUI/res/anim/lock_to_error_filled.xml
new file mode 100644
index 000000000000..6eb7425d9002
--- /dev/null
+++ b/packages/SystemUI/res/anim/lock_to_error_filled.xml
@@ -0,0 +1,188 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <aapt:attr name="android:drawable" >
+ <vector
+ android:height="32dp"
+ android:viewportHeight="32"
+ android:viewportWidth="32"
+ android:width="32dp" >
+ <group android:name="_R_G" >
+ <group
+ android:name="_R_G_L_1_G"
+ android:pivotX="10.917"
+ android:pivotY="9.583"
+ android:rotation="0"
+ android:translateX="5.083"
+ android:translateY="10.417" >
+ <path
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:fillType="nonZero"
+ android:pathData=" M18.92 0.25 C18.92,0.25 2.92,0.25 2.92,0.25 C1.45,0.25 0.25,1.45 0.25,2.92 C0.25,2.92 0.25,16.25 0.25,16.25 C0.25,17.72 1.45,18.92 2.92,18.92 C2.92,18.92 18.92,18.92 18.92,18.92 C20.38,18.92 21.58,17.72 21.58,16.25 C21.58,16.25 21.58,2.92 21.58,2.92 C21.58,1.45 20.38,0.25 18.92,0.25c M10.92 12.25 C9.45,12.25 8.25,11.05 8.25,9.58 C8.25,8.12 9.45,6.92 10.92,6.92 C12.38,6.92 13.58,8.12 13.58,9.58 C13.58,11.05 12.38,12.25 10.92,12.25c " />
+ </group>
+ <group
+ android:name="_R_G_L_0_G_N_2_T_0"
+ android:pivotX="10.917"
+ android:pivotY="9.583"
+ android:rotation="0"
+ android:translateX="5.083"
+ android:translateY="10.417" >
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="1.9169999999999998"
+ android:translateY="-12.75" >
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:pathData=" M13 13 C13,13 13,9 13,9 C13,6.79 11.21,5 9,5 C6.79,5 5,6.79 5,9 C5,9 5,13 5,13 "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="2" />
+ </group>
+ </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:duration="133"
+ android:propertyName="rotation"
+ 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.44,0 0.601,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="120"
+ android:propertyName="rotation"
+ android:startOffset="133"
+ android:valueFrom="0"
+ android:valueTo="-10"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.44,0 0.601,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="97"
+ android:propertyName="rotation"
+ android:startOffset="253"
+ android:valueFrom="-10"
+ android:valueTo="10"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.531,0 0.389,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="rotation"
+ android:startOffset="350"
+ android:valueFrom="10"
+ android:valueTo="-5"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.499,0 0.489,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="167"
+ android:propertyName="rotation"
+ android:startOffset="450"
+ android:valueFrom="-5"
+ android:valueTo="0"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.293,0 0.689,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_N_2_T_0" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="rotation"
+ 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.44,0 0.601,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="120"
+ android:propertyName="rotation"
+ android:startOffset="133"
+ android:valueFrom="0"
+ android:valueTo="-10"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.44,0 0.601,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="97"
+ android:propertyName="rotation"
+ android:startOffset="253"
+ android:valueFrom="-10"
+ android:valueTo="10"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.531,0 0.389,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="rotation"
+ android:startOffset="350"
+ android:valueFrom="10"
+ android:valueTo="-5"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.499,0 0.489,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="167"
+ android:propertyName="rotation"
+ android:startOffset="450"
+ android:valueFrom="-5"
+ android:valueTo="0"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.293,0 0.689,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:duration="717"
+ android:propertyName="translateX"
+ 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/anim/lock_to_error_rounded.xml b/packages/SystemUI/res/anim/lock_to_error_rounded.xml
new file mode 100644
index 000000000000..46043caf8862
--- /dev/null
+++ b/packages/SystemUI/res/anim/lock_to_error_rounded.xml
@@ -0,0 +1,270 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <aapt:attr name="android:drawable" >
+ <vector
+ android:height="32dp"
+ android:viewportHeight="32"
+ android:viewportWidth="32"
+ android:width="32dp" >
+ <group android:name="_R_G" >
+ <group
+ android:name="_R_G_L_2_G"
+ android:pivotX="14.667"
+ android:pivotY="12.667"
+ android:rotation="0"
+ android:translateX="1.3330000000000002"
+ android:translateY="7.333" >
+ <path
+ android:name="_R_G_L_2_G_D_0_P_0"
+ android:pathData=" M22.09 5 C22.09,5 6,5 6,5 C5.45,5 5,5.45 5,6 C5,6 5,19.33 5,19.33 C5,19.89 5.45,20.33 6,20.33 C6,20.33 23.33,20.33 23.33,20.33 C23.89,20.33 24.33,19.89 24.33,19.33 C24.33,19.33 24.33,6 24.33,6 C24.33,5.45 23.89,5 23.33,5 C23.33,5 22.09,5 22.09,5c "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="1.5" />
+ </group>
+ <group
+ android:name="_R_G_L_1_G_N_4_T_0"
+ android:pivotX="14.667"
+ android:pivotY="12.667"
+ android:rotation="0"
+ android:translateX="1.3330000000000002"
+ android:translateY="7.333" >
+ <group
+ android:name="_R_G_L_1_G"
+ android:translateX="12.416"
+ android:translateY="10.417" >
+ <path
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:fillType="nonZero"
+ android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c " />
+ </group>
+ </group>
+ <group
+ android:name="_R_G_L_0_G_N_4_T_0"
+ android:pivotX="14.667"
+ android:pivotY="12.667"
+ android:rotation="0"
+ android:translateX="1.3330000000000002"
+ android:translateY="7.333" >
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="5.333"
+ android:translateY="-9.425999999999998" >
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:pathData=" M13.67 13.8 C13.67,13.8 13.67,8.94 13.67,8.94 C13.63,6.75 11.69,5 9.33,5.04 C6.98,5 5.04,6.75 5,8.94 C5,8.94 5,13.8 5,13.8 "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="1.5" />
+ </group>
+ </group>
+ </group>
+ <group android:name="time_group" />
+ </vector>
+ </aapt:attr>
+
+ <target android:name="_R_G_L_2_G" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="rotation"
+ 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.44,0 0.601,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="120"
+ android:propertyName="rotation"
+ android:startOffset="133"
+ android:valueFrom="0"
+ android:valueTo="-10"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.44,0 0.601,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="97"
+ android:propertyName="rotation"
+ android:startOffset="253"
+ android:valueFrom="-10"
+ android:valueTo="10"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.531,0 0.389,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="rotation"
+ android:startOffset="350"
+ android:valueFrom="10"
+ android:valueTo="-5"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.499,0 0.489,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="167"
+ android:propertyName="rotation"
+ android:startOffset="450"
+ android:valueFrom="-5"
+ android:valueTo="0"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.293,0 0.689,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_N_4_T_0" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="rotation"
+ 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.44,0 0.601,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="120"
+ android:propertyName="rotation"
+ android:startOffset="133"
+ android:valueFrom="0"
+ android:valueTo="-10"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.44,0 0.601,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="97"
+ android:propertyName="rotation"
+ android:startOffset="253"
+ android:valueFrom="-10"
+ android:valueTo="10"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.531,0 0.389,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="rotation"
+ android:startOffset="350"
+ android:valueFrom="10"
+ android:valueTo="-5"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.499,0 0.489,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="167"
+ android:propertyName="rotation"
+ android:startOffset="450"
+ android:valueFrom="-5"
+ android:valueTo="0"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.293,0 0.689,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_N_4_T_0" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="rotation"
+ 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.44,0 0.601,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="120"
+ android:propertyName="rotation"
+ android:startOffset="133"
+ android:valueFrom="0"
+ android:valueTo="-10"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.44,0 0.601,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="97"
+ android:propertyName="rotation"
+ android:startOffset="253"
+ android:valueFrom="-10"
+ android:valueTo="10"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.531,0 0.389,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="rotation"
+ android:startOffset="350"
+ android:valueFrom="10"
+ android:valueTo="-5"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.499,0 0.489,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="167"
+ android:propertyName="rotation"
+ android:startOffset="450"
+ android:valueFrom="-5"
+ android:valueTo="0"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.293,0 0.689,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:duration="717"
+ android:propertyName="translateX"
+ 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/core/res/res/anim/lock_unlock.xml b/packages/SystemUI/res/anim/lock_unlock.xml
index 91d44320d8c2..91d44320d8c2 100644
--- a/core/res/res/anim/lock_unlock.xml
+++ b/packages/SystemUI/res/anim/lock_unlock.xml
diff --git a/packages/SystemUI/res/anim/lock_unlock_circular.xml b/packages/SystemUI/res/anim/lock_unlock_circular.xml
new file mode 100644
index 000000000000..5fc8576e6687
--- /dev/null
+++ b/packages/SystemUI/res/anim/lock_unlock_circular.xml
@@ -0,0 +1,298 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <aapt:attr name="android:drawable" >
+ <vector
+ android:height="42dp"
+ android:viewportHeight="42"
+ android:viewportWidth="32"
+ android:width="32dp" >
+ <group android:name="_R_G" >
+ <group
+ android:name="_R_G_L_2_G_T_1"
+ android:translateX="15.999"
+ android:translateY="24.333" >
+ <group
+ android:name="_R_G_L_2_G"
+ android:translateX="-9.583"
+ android:translateY="-8.916" >
+ <path
+ android:name="_R_G_L_2_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:fillType="nonZero"
+ android:pathData=" M17.42 1.75 C17.42,1.75 17.42,14.58 17.42,14.58 C17.42,15.41 16.74,16.08 15.92,16.08 C15.92,16.08 3.25,16.08 3.25,16.08 C2.42,16.08 1.75,15.41 1.75,14.58 C1.75,14.58 1.75,1.75 1.75,1.75 C1.75,1.75 17.42,1.75 17.42,1.75c M18.92 0.25 C18.92,0.25 0.25,0.25 0.25,0.25 C0.25,0.25 0.25,14.58 0.25,14.58 C0.25,16.24 1.59,17.58 3.25,17.58 C3.25,17.58 15.92,17.58 15.92,17.58 C17.57,17.58 18.92,16.24 18.92,14.58 C18.92,14.58 18.92,0.25 18.92,0.25c " />
+ </group>
+ </group>
+ <group
+ android:name="_R_G_L_1_G_N_3_T_1"
+ android:translateX="15.999"
+ android:translateY="24.333" >
+ <group
+ android:name="_R_G_L_1_G_N_3_T_0"
+ android:translateX="-9.583"
+ android:translateY="-8.916" >
+ <group
+ android:name="_R_G_L_1_G"
+ android:pivotX="2.25"
+ android:pivotY="3.334"
+ android:scaleX="1"
+ android:scaleY="1"
+ android:translateX="7.334"
+ android:translateY="5.333" >
+ <path
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:fillType="nonZero"
+ android:pathData=" M4.25 2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25 C3.35,0.25 4.25,1.15 4.25,2.25c " />
+ <path
+ android:name="_R_G_L_1_G_D_1_P_0"
+ android:pathData=" M2.25 2.25 C2.25,2.25 2.25,5.92 2.25,5.92 "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="1.5" />
+ </group>
+ </group>
+ </group>
+ <group
+ android:name="_R_G_L_0_G_N_3_T_1"
+ android:translateX="15.999"
+ android:translateY="24.333" >
+ <group
+ android:name="_R_G_L_0_G_N_3_T_0"
+ android:translateX="-9.583"
+ android:translateY="-8.916" >
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="1.5"
+ android:translateY="-11.835" >
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:pathData=" M12.42 12.6 C12.42,12.6 12.42,8.17 12.42,8.17 C12.42,5.83 10.48,3.75 8.08,3.75 C5.69,3.75 3.75,5.83 3.75,8.17 C3.75,8.17 3.75,12.6 3.75,12.6 "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="1.5" />
+ </group>
+ </group>
+ </group>
+ </group>
+ <group android:name="time_group" />
+ </vector>
+ </aapt:attr>
+
+ <target android:name="_R_G_L_2_G_T_1" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="translateY"
+ android:startOffset="0"
+ android:valueFrom="24.333"
+ android:valueTo="22.458"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.705,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="translateY"
+ android:startOffset="133"
+ android:valueFrom="22.458"
+ android:valueTo="25.333"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.289,0 0.724,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="translateY"
+ android:startOffset="267"
+ android:valueFrom="25.333"
+ android:valueTo="24.333"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.624,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:duration="100"
+ android:propertyName="scaleX"
+ android:startOffset="0"
+ android:valueFrom="1"
+ android:valueTo="0.9"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="scaleY"
+ android:startOffset="0"
+ android:valueFrom="1"
+ android:valueTo="0.9"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="283"
+ android:propertyName="scaleX"
+ android:startOffset="100"
+ android:valueFrom="0.9"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="283"
+ android:propertyName="scaleY"
+ android:startOffset="100"
+ android:valueFrom="0.9"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_N_3_T_1" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="translateY"
+ android:startOffset="0"
+ android:valueFrom="24.333"
+ android:valueTo="22.458"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.705,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="translateY"
+ android:startOffset="133"
+ android:valueFrom="22.458"
+ android:valueTo="25.333"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.289,0 0.724,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="translateY"
+ android:startOffset="267"
+ android:valueFrom="25.333"
+ android:valueTo="24.333"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.624,1 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:duration="67"
+ android:propertyName="pathData"
+ android:startOffset="0"
+ android:valueFrom="M12.42 12.6 C12.42,12.6 12.42,8.17 12.42,8.17 C12.42,5.83 10.48,3.75 8.08,3.75 C5.69,3.75 3.75,5.83 3.75,8.17 C3.75,8.17 3.75,12.6 3.75,12.6 "
+ android:valueTo="M12.42 12.6 C12.42,12.6 12.4,5.86 12.4,5.86 C12.4,3.52 10.46,1.44 8.06,1.44 C5.67,1.44 3.73,3.52 3.73,5.86 C3.73,5.86 3.75,7.41 3.75,7.41 "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.59,0 0.488,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="pathData"
+ android:startOffset="67"
+ android:valueFrom="M12.42 12.6 C12.42,12.6 12.4,5.86 12.4,5.86 C12.4,3.52 10.46,1.44 8.06,1.44 C5.67,1.44 3.73,3.52 3.73,5.86 C3.73,5.86 3.75,7.41 3.75,7.41 "
+ android:valueTo="M12.42 12.6 C12.42,12.6 12.41,8.16 12.41,8.16 C12.41,5.81 14.36,3.75 16.75,3.77 C19.15,3.78 21.07,5.71 21.07,8.05 C21.07,8.05 21.08,8.22 21.08,8.22 "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.57,0 0.365,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_N_3_T_1" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="translateY"
+ android:startOffset="0"
+ android:valueFrom="24.333"
+ android:valueTo="22.458"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.705,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="translateY"
+ android:startOffset="133"
+ android:valueFrom="22.458"
+ android:valueTo="25.333"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.289,0 0.724,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="translateY"
+ android:startOffset="267"
+ android:valueFrom="25.333"
+ android:valueTo="24.333"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.624,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:duration="717"
+ android:propertyName="translateX"
+ 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/anim/lock_unlock_filled.xml b/packages/SystemUI/res/anim/lock_unlock_filled.xml
new file mode 100644
index 000000000000..2bf2d89e5c12
--- /dev/null
+++ b/packages/SystemUI/res/anim/lock_unlock_filled.xml
@@ -0,0 +1,204 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <aapt:attr name="android:drawable" >
+ <vector
+ android:height="42dp"
+ android:viewportHeight="42"
+ android:viewportWidth="32"
+ android:width="32dp" >
+ <group android:name="_R_G" >
+ <group
+ android:name="_R_G_L_1_G_T_1"
+ android:translateX="16"
+ android:translateY="25" >
+ <group
+ android:name="_R_G_L_1_G"
+ android:translateX="-10.917"
+ android:translateY="-9.583" >
+ <path
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:fillType="nonZero"
+ android:pathData=" M18.92 0.25 C18.92,0.25 2.92,0.25 2.92,0.25 C1.45,0.25 0.25,1.45 0.25,2.92 C0.25,2.92 0.25,16.25 0.25,16.25 C0.25,17.72 1.45,18.92 2.92,18.92 C2.92,18.92 18.92,18.92 18.92,18.92 C20.38,18.92 21.58,17.72 21.58,16.25 C21.58,16.25 21.58,2.92 21.58,2.92 C21.58,1.45 20.38,0.25 18.92,0.25c M10.92 12.25 C9.45,12.25 8.25,11.05 8.25,9.58 C8.25,8.12 9.45,6.92 10.92,6.92 C12.38,6.92 13.58,8.12 13.58,9.58 C13.58,11.05 12.38,12.25 10.92,12.25c " />
+ </group>
+ </group>
+ <group
+ android:name="_R_G_L_0_G_N_3_T_1"
+ android:translateX="16"
+ android:translateY="25" >
+ <group
+ android:name="_R_G_L_0_G_N_3_T_0"
+ android:translateX="-10.917"
+ android:translateY="-9.583" >
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="9.917000000000002"
+ android:translateY="-12.75" >
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:pathData=" M-3 13.04 C-3,13.04 -3,9.04 -3,9.04 C-3,6.83 -1.03,5.04 0.91,5 C3.12,4.96 5,6.79 5,9 C5,9 5,13 5,13 "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="2" />
+ </group>
+ </group>
+ </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:duration="100"
+ android:propertyName="pathData"
+ android:startOffset="0"
+ android:valueFrom=" M18.92 0.25 C18.92,0.25 2.92,0.25 2.92,0.25 C1.45,0.25 0.25,1.45 0.25,2.92 C0.25,2.92 0.25,16.25 0.25,16.25 C0.25,17.72 1.45,18.92 2.92,18.92 C2.92,18.92 18.92,18.92 18.92,18.92 C20.38,18.92 21.58,17.72 21.58,16.25 C21.58,16.25 21.58,2.92 21.58,2.92 C21.58,1.45 20.38,0.25 18.92,0.25c M10.92 12.25 C9.45,12.25 8.25,11.05 8.25,9.58 C8.25,8.12 9.45,6.92 10.92,6.92 C12.38,6.92 13.58,8.12 13.58,9.58 C13.58,11.05 12.38,12.25 10.92,12.25c "
+ android:valueTo=" M18.92 0.25 C18.92,0.25 2.92,0.25 2.92,0.25 C1.45,0.25 0.25,1.45 0.25,2.92 C0.25,2.92 0.25,16.25 0.25,16.25 C0.25,17.72 1.45,18.92 2.92,18.92 C2.92,18.92 18.92,18.92 18.92,18.92 C20.38,18.92 21.58,17.72 21.58,16.25 C21.58,16.25 21.58,2.92 21.58,2.92 C21.58,1.45 20.38,0.25 18.92,0.25c M10.92 11.78 C9.71,11.78 8.72,10.79 8.72,9.58 C8.72,8.37 9.71,7.38 10.92,7.38 C12.13,7.38 13.12,8.37 13.12,9.58 C13.12,10.79 12.13,11.78 10.92,11.78c "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="283"
+ android:propertyName="pathData"
+ android:startOffset="100"
+ android:valueFrom=" M18.92 0.25 C18.92,0.25 2.92,0.25 2.92,0.25 C1.45,0.25 0.25,1.45 0.25,2.92 C0.25,2.92 0.25,16.25 0.25,16.25 C0.25,17.72 1.45,18.92 2.92,18.92 C2.92,18.92 18.92,18.92 18.92,18.92 C20.38,18.92 21.58,17.72 21.58,16.25 C21.58,16.25 21.58,2.92 21.58,2.92 C21.58,1.45 20.38,0.25 18.92,0.25c M10.92 11.78 C9.71,11.78 8.72,10.79 8.72,9.58 C8.72,8.37 9.71,7.38 10.92,7.38 C12.13,7.38 13.12,8.37 13.12,9.58 C13.12,10.79 12.13,11.78 10.92,11.78c "
+ android:valueTo=" M18.92 0.25 C18.92,0.25 2.92,0.25 2.92,0.25 C1.45,0.25 0.25,1.45 0.25,2.92 C0.25,2.92 0.25,16.25 0.25,16.25 C0.25,17.72 1.45,18.92 2.92,18.92 C2.92,18.92 18.92,18.92 18.92,18.92 C20.38,18.92 21.58,17.72 21.58,16.25 C21.58,16.25 21.58,2.92 21.58,2.92 C21.58,1.45 20.38,0.25 18.92,0.25c M10.92 12.25 C9.45,12.25 8.25,11.05 8.25,9.58 C8.25,8.12 9.45,6.92 10.92,6.92 C12.38,6.92 13.58,8.12 13.58,9.58 C13.58,11.05 12.38,12.25 10.92,12.25c "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_T_1" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="translateY"
+ android:startOffset="0"
+ android:valueFrom="25"
+ android:valueTo="23"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.32,0 0.803,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="translateY"
+ android:startOffset="133"
+ android:valueFrom="23"
+ android:valueTo="26.5"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.223,0 0.761,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="translateY"
+ android:startOffset="267"
+ android:valueFrom="26.5"
+ android:valueTo="25"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.311,0 0.633,1 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:duration="67"
+ android:propertyName="pathData"
+ android:startOffset="0"
+ android:valueFrom="M-3 13.04 C-3,13.04 -3,9.04 -3,9.04 C-3,6.83 -1.03,5.04 0.91,5 C3.12,4.96 5,6.79 5,9 C5,9 5,13 5,13 "
+ android:valueTo="M-3 6.73 C-3,5.62 -2.56,4.67 -1.84,4 C-1.11,3.32 -0.09,2.93 1.06,2.94 C3.27,2.96 5,4.54 5,6.75 C5,6.75 5,13 5,13 "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.592,0 0.503,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="pathData"
+ android:startOffset="67"
+ android:valueFrom="M-3 6.73 C-3,5.62 -2.56,4.67 -1.84,4 C-1.11,3.32 -0.09,2.93 1.06,2.94 C3.27,2.96 5,4.54 5,6.75 C5,6.75 5,13 5,13 "
+ android:valueTo="M13 9 C13,7.9 12.55,6.9 11.83,6.17 C11.1,5.45 10.11,5 9,5 C6.79,5 5,6.79 5,9 C5,9 5,13 5,13 "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.563,0 0.363,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_N_3_T_1" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="translateY"
+ android:startOffset="0"
+ android:valueFrom="25"
+ android:valueTo="23"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.32,0 0.803,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="translateY"
+ android:startOffset="133"
+ android:valueFrom="23"
+ android:valueTo="26.5"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.223,0 0.761,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="translateY"
+ android:startOffset="267"
+ android:valueFrom="26.5"
+ android:valueTo="25"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.311,0 0.633,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:duration="717"
+ android:propertyName="translateX"
+ 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/anim/lock_unlock_rounded.xml b/packages/SystemUI/res/anim/lock_unlock_rounded.xml
new file mode 100644
index 000000000000..7c558513c7f9
--- /dev/null
+++ b/packages/SystemUI/res/anim/lock_unlock_rounded.xml
@@ -0,0 +1,292 @@
+<?xml version="1.0" encoding="utf-8"?>
+<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
+ xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <aapt:attr name="android:drawable" >
+ <vector
+ android:height="42dp"
+ android:viewportHeight="42"
+ android:viewportWidth="32"
+ android:width="32dp" >
+ <group android:name="_R_G" >
+ <group
+ android:name="_R_G_L_2_G_T_1"
+ android:translateX="16"
+ android:translateY="25" >
+ <group
+ android:name="_R_G_L_2_G"
+ android:translateX="-14.667"
+ android:translateY="-12.667" >
+ <path
+ android:name="_R_G_L_2_G_D_0_P_0"
+ android:pathData=" M22.09 5 C22.09,5 6,5 6,5 C5.45,5 5,5.45 5,6 C5,6 5,19.33 5,19.33 C5,19.89 5.45,20.33 6,20.33 C6,20.33 23.33,20.33 23.33,20.33 C23.89,20.33 24.33,19.89 24.33,19.33 C24.33,19.33 24.33,6 24.33,6 C24.33,5.45 23.89,5 23.33,5 C23.33,5 22.09,5 22.09,5c "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="1.5" />
+ </group>
+ </group>
+ <group
+ android:name="_R_G_L_1_G_N_4_T_1"
+ android:translateX="16"
+ android:translateY="25" >
+ <group
+ android:name="_R_G_L_1_G_N_4_T_0"
+ android:translateX="-14.667"
+ android:translateY="-12.667" >
+ <group
+ android:name="_R_G_L_1_G"
+ android:pivotX="2.25"
+ android:pivotY="2.25"
+ android:scaleX="1"
+ android:scaleY="1"
+ android:translateX="12.416"
+ android:translateY="10.417" >
+ <path
+ android:name="_R_G_L_1_G_D_0_P_0"
+ android:fillAlpha="1"
+ android:fillColor="#ffffff"
+ android:fillType="nonZero"
+ android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c " />
+ </group>
+ </group>
+ </group>
+ <group
+ android:name="_R_G_L_0_G_N_4_T_1"
+ android:translateX="16"
+ android:translateY="25" >
+ <group
+ android:name="_R_G_L_0_G_N_4_T_0"
+ android:translateX="-14.667"
+ android:translateY="-12.667" >
+ <group
+ android:name="_R_G_L_0_G"
+ android:translateX="5.333"
+ android:translateY="-9.425999999999998" >
+ <path
+ android:name="_R_G_L_0_G_D_0_P_0"
+ android:pathData=" M13.67 13.8 C13.67,13.8 13.67,8.94 13.67,8.94 C13.63,6.75 11.69,5 9.33,5.04 C6.98,5 5.04,6.75 5,8.94 C5,8.94 5,13.8 5,13.8 "
+ android:strokeAlpha="1"
+ android:strokeColor="#ffffff"
+ android:strokeLineCap="round"
+ android:strokeLineJoin="round"
+ android:strokeWidth="1.5" />
+ </group>
+ </group>
+ </group>
+ </group>
+ <group android:name="time_group" />
+ </vector>
+ </aapt:attr>
+
+ <target android:name="_R_G_L_2_G_T_1" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="translateY"
+ android:startOffset="0"
+ android:valueFrom="25"
+ android:valueTo="23.5"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="translateY"
+ android:startOffset="133"
+ android:valueFrom="23.5"
+ android:valueTo="26"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="translateY"
+ android:startOffset="267"
+ android:valueFrom="26"
+ android:valueTo="25"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,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:duration="100"
+ android:propertyName="scaleX"
+ android:startOffset="0"
+ android:valueFrom="1"
+ android:valueTo="0.85"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.346,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="scaleY"
+ android:startOffset="0"
+ android:valueFrom="1"
+ android:valueTo="0.85"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.346,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="283"
+ android:propertyName="scaleX"
+ android:startOffset="100"
+ android:valueFrom="0.85"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.423,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="283"
+ android:propertyName="scaleY"
+ android:startOffset="100"
+ android:valueFrom="0.85"
+ android:valueTo="1"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.423,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_1_G_N_4_T_1" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="translateY"
+ android:startOffset="0"
+ android:valueFrom="25"
+ android:valueTo="23.5"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="translateY"
+ android:startOffset="133"
+ android:valueFrom="23.5"
+ android:valueTo="26"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="translateY"
+ android:startOffset="267"
+ android:valueFrom="26"
+ android:valueTo="25"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 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:duration="67"
+ android:propertyName="pathData"
+ android:startOffset="0"
+ android:valueFrom="M13.67 13.8 C13.67,13.8 13.67,8.94 13.67,8.94 C13.63,6.75 11.69,5 9.33,5.04 C6.98,5 5.04,6.75 5,8.94 C5,8.94 5,13.8 5,13.8 "
+ android:valueTo="M13.67 13.8 C13.67,13.8 13.69,5.06 13.69,5.06 C13.65,2.87 11.71,1.13 9.35,1.16 C7,1.13 5.06,2.87 5.02,5.06 C5.02,5.06 5,7.93 5,7.93 "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.658,0 0.317,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="333"
+ android:propertyName="pathData"
+ android:startOffset="67"
+ android:valueFrom="M13.67 13.8 C13.67,13.8 13.69,5.06 13.69,5.06 C13.65,2.87 11.71,1.13 9.35,1.16 C7,1.13 5.06,2.87 5.02,5.06 C5.02,5.06 5,7.93 5,7.93 "
+ android:valueTo="M13.67 13.8 C13.67,13.8 13.67,8.94 13.67,8.94 C13.68,6.62 15.69,5.03 18.01,5.04 C20.46,5.04 22.32,6.89 22.34,8.85 C22.34,8.85 22.33,8.89 22.33,8.89 "
+ android:valueType="pathType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.679,0 0.175,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ </set>
+ </aapt:attr>
+ </target>
+ <target android:name="_R_G_L_0_G_N_4_T_1" >
+ <aapt:attr name="android:animation" >
+ <set android:ordering="together" >
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="translateY"
+ android:startOffset="0"
+ android:valueFrom="25"
+ android:valueTo="23.5"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="133"
+ android:propertyName="translateY"
+ android:startOffset="133"
+ android:valueFrom="23.5"
+ android:valueTo="26"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
+ </aapt:attr>
+ </objectAnimator>
+ <objectAnimator
+ android:duration="100"
+ android:propertyName="translateY"
+ android:startOffset="267"
+ android:valueFrom="26"
+ android:valueTo="25"
+ android:valueType="floatType" >
+ <aapt:attr name="android:interpolator" >
+ <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,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:duration="717"
+ android:propertyName="translateX"
+ 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/corner_gesture_hint.xml b/packages/SystemUI/res/drawable/corner_gesture_hint.xml
deleted file mode 100644
index 3f4abb0e0dd4..000000000000
--- a/packages/SystemUI/res/drawable/corner_gesture_hint.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-<!--
- Copyright (C) 2019 The Android Open Source Project
-
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="12dp"
- android:width="12dp"
- android:viewportWidth="12"
- android:viewportHeight="12">
-
- <path android:fillColor="#00000000"
- android:pathData="M 1.18 10.65 C 1.18 5.58 5.41 1.18 10.65 1.18"
- android:strokeColor="#000"
- android:strokeLineCap="round"
- android:strokeWidth="1.3" />
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_emergency_star.xml b/packages/SystemUI/res/drawable/ic_emergency_star.xml
new file mode 100644
index 000000000000..148f250ddf11
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_emergency_star.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M9.321,2l0,5.359l-4.641,-2.68l-2.68,4.641l4.641,2.679l-4.641,2.68l2.68,4.641l4.641,-2.68l0,5.359l5.359,0l0,-5.359l4.641,2.68l2.68,-4.641l-4.641,-2.68l4.641,-2.679l-2.68,-4.641l-4.641,2.679l0,-5.359z"
+ android:strokeColor="#00000000"
+ android:fillColor="#EA4335"
+ android:strokeWidth="1"/>
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_info_outline.xml b/packages/SystemUI/res/drawable/ic_info_outline.xml
index a4a3e9aab239..44e09f6faa51 100644
--- a/packages/SystemUI/res/drawable/ic_info_outline.xml
+++ b/packages/SystemUI/res/drawable/ic_info_outline.xml
@@ -15,8 +15,8 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="32dp"
- android:height="32dp"
+ android:width="24dp"
+ android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
diff --git a/packages/SystemUI/res/drawable/ic_invert_colors.xml b/packages/SystemUI/res/drawable/ic_invert_colors.xml
index 77d491810ccc..37ea0800a51e 100644
--- a/packages/SystemUI/res/drawable/ic_invert_colors.xml
+++ b/packages/SystemUI/res/drawable/ic_invert_colors.xml
@@ -15,8 +15,8 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="48dp"
- android:height="48dp"
+ android:width="24dp"
+ android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
diff --git a/packages/SystemUI/res/drawable/ic_notifications_alert.xml b/packages/SystemUI/res/drawable/ic_notifications_alert.xml
index eb7b8eeb9251..d53d698e1bcb 100644
--- a/packages/SystemUI/res/drawable/ic_notifications_alert.xml
+++ b/packages/SystemUI/res/drawable/ic_notifications_alert.xml
@@ -14,11 +14,11 @@ Copyright (C) 2018 The Android Open Source Project
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
<path
- android:pathData="M7.58 4.08L6.15 2.65C3.75 4.48 2.17 7.3 2.03 10.5h2c.15-2.65 1.51-4.97 3.55-6.42zm12.39 6.42h2c-.15-3.2-1.73-6.02-4.12-7.85l-1.42 1.43c2.02 1.45 3.39 3.77 3.54 6.42zM18 11c0-3.07-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68C7.63 5.36 6 7.92 6 11v5l-2 2v1h16v-1l-2-2v-5zm-6 11c.14 0 .27-.01.4-.04.65-.14 1.18-.58 1.44-1.18.1-.24.15-.5.15-.78h-4c.01 1.1.9 2 2.01 2z"
- android:fillColor="#FF000000"/>
-</vector>
+ android:fillColor="@android:color/white"
+ android:pathData="M18 17v-6c0-3.07-1.63-5.64-4.5-6.32V4c0-0.83-0.67-1.5-1.5-1.5s-1.5 0.67 -1.5 1.5v0.68C7.64 5.36 6 7.92 6 11v6H4v2h16v-2h-2zm-2 0H8v-6c0-2.48 1.51-4.5 4-4.5s4 2.02 4 4.5v6zm-6 3h4c0 1.1-0.9 2-2 2s-2-0.9-2-2zm12-9h-2c0-2.74-1.23-5.19-3.16-6.84l1.41-1.41C20.54 4.77 22 7.71 22 11zM5.75 2.75l1.41 1.41C5.23 5.81 4 8.26 4 11H2c0-3.29 1.46-6.23 3.75-8.25z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_notifications_silence.xml b/packages/SystemUI/res/drawable/ic_notifications_silence.xml
index ff136eb44aac..a6cc81b5fdf7 100644
--- a/packages/SystemUI/res/drawable/ic_notifications_silence.xml
+++ b/packages/SystemUI/res/drawable/ic_notifications_silence.xml
@@ -14,15 +14,11 @@ Copyright (C) 2018 The Android Open Source Project
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0">
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
<path
- android:pathData="M0 0h24v24H0z"
- />
- <path
- android:pathData="M20 18.69L7.84 6.14 5.27 3.49 4 4.76l2.8 2.8v.01c-.52.99-.8 2.16-.8 3.42v5l-2 2v1h13.73l2 2L21 19.72l-1-1.03zM12 22c1.11 0 2-.89 2-2h-4c0 1.11.89 2 2 2zm6-7.32V11c0-3.08-1.64-5.64-4.5-6.32V4c0-.83-.67-1.5-1.5-1.5s-1.5.67-1.5 1.5v.68c-.15.03-.29.08-.42.12-.1.03-.2.07-.3.11h-.01c-.01 0-.01 0-.02.01-.23.09-.46.2-.68.31 0 0-.01 0-.01.01L18 14.68z"
- android:fillColor="#FF000000"
- />
-</vector>
+ android:fillColor="@android:color/white"
+ android:pathData="M12 22c1.1 0 2-0.9 2-2h-4c0 1.1 0.9 2 2 2zm4-6L2.81 2.81 1.39 4.22l4.85 4.85C6.09 9.68 6 10.33 6 11v6H4v2h12.17l3.61 3.61 1.41-1.41L16 16zm-8 1l0.01-6.16L14.17 17H8zm4-10.5c2.49 0 4 2.02 4 4.5v2.17l2 2V11c0-3.07-1.63-5.64-4.5-6.32V4c0-0.83-0.67-1.5-1.5-1.5s-1.5 0.67 -1.5 1.5v0.68c-0.78 0.18 -1.45 0.52 -2.04 0.95 L9.93 7.1c0.58-0.37 1.27-0.6 2.07-0.6z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_qs_bluetooth_connecting.xml b/packages/SystemUI/res/drawable/ic_qs_bluetooth_connecting.xml
index fbd92dead675..d2ee2839d701 100644
--- a/packages/SystemUI/res/drawable/ic_qs_bluetooth_connecting.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_bluetooth_connecting.xml
@@ -14,8 +14,8 @@ Copyright (C) 2017 The Android Open Source Project
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="64dp"
- android:height="64dp"
+ android:width="24dp"
+ android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?android:attr/colorControlNormal" >
diff --git a/packages/SystemUI/res/drawable/ic_qs_no_sim.xml b/packages/SystemUI/res/drawable/ic_qs_no_sim.xml
index 22e12cc10405..6cabcaf4bcb4 100644
--- a/packages/SystemUI/res/drawable/ic_qs_no_sim.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_no_sim.xml
@@ -14,8 +14,8 @@ Copyright (C) 2017 The Android Open Source Project
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="32dp"
- android:height="32dp"
+ android:width="24dp"
+ android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
diff --git a/packages/SystemUI/res/drawable/ic_screenshot_delete.xml b/packages/SystemUI/res/drawable/ic_screenshot_delete.xml
index d60ee414888d..4cf578a92826 100644
--- a/packages/SystemUI/res/drawable/ic_screenshot_delete.xml
+++ b/packages/SystemUI/res/drawable/ic_screenshot_delete.xml
@@ -14,8 +14,8 @@ Copyright (C) 2015 The Android Open Source Project
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="32dp"
- android:height="32dp"
+ android:width="24dp"
+ android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
diff --git a/packages/SystemUI/res/drawable/ic_volume_media.xml b/packages/SystemUI/res/drawable/ic_volume_media.xml
index c8fa3fbdd50b..99be7b6e8fea 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media.xml
@@ -22,6 +22,6 @@
<path
android:fillColor="#FFFFFFFF"
- android:pathData="M12,3l0.01,10.55c-0.59,-0.34 -1.27,-0.55 -2,-0.55C7.79,13 6,14.79 6,17c0,2.21 1.79,4 4.01,4S14,19.21 14,17V7h4V3H12zM10.01,19c-1.1,0 -2,-0.9 -2,-2c0,-1.1 0.9,-2 2,-2s2,0.9 2,2C12.01,18.1 11.11,19 10.01,19z"/>
+ android:pathData="M12 3l0.01 10.55c-0.59-0.34-1.27-0.55-2-0.55C7.79 13 6 14.79 6 17s1.79 4 4.01 4S14 19.21 14 17V7h4V3h-6z" />
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_bt.xml b/packages/SystemUI/res/drawable/ic_volume_media_bt.xml
index 9f7744e3c1bf..23cb206085ea 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media_bt.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media_bt.xml
@@ -14,14 +14,12 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24.0dp"
- android:height="24.0dp"
- android:viewportWidth="24.0"
- android:viewportHeight="24.0"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
android:tint="?android:attr/colorControlNormal">
-
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M9,3l0.01,10.55C8.41,13.21 7.73,13 7.01,13C4.79,13 3,14.79 3,17c0,2.21 1.79,4 4.01,4S11,19.21 11,17V7h4V3H9zM7.01,19c-1.1,0 -2,-0.9 -2,-2c0,-1.1 0.9,-2 2,-2s2,0.9 2,2C9.01,18.1 8.11,19 7.01,19zM21,12.43L17.57,9h-0.6v4.55l-2.75,-2.75l-0.85,0.85L16.73,15l-3.35,3.35l0.85,0.85l2.75,-2.75V21h0.6L21,17.57L18.42,15L21,12.43zM18.17,11.3l1.13,1.13l-1.13,1.13V11.3zM19.3,17.57l-1.13,1.13v-2.26L19.3,17.57z"/>
-
-</vector>
+ android:fillColor="@android:color/white"
+ android:pathData="M9 3l0.01 10.55c-0.6-0.34-1.28-0.55-2-0.55C4.79 13 3 14.79 3 17s1.79 4 4.01 4S11 19.21 11 17V7h4V3H9zm12 9.43L17.57 9h-0.6v4.55l-2.75-2.75-0.85 0.85 L16.73 15l-3.35 3.35 0.85 0.85 2.75-2.75V21h0.6L21 17.57 18.42 15 21 12.43zm-2.83-1.13l1.13 1.13-1.13 1.13V11.3zm1.13 6.27l-1.13 1.13v-2.26l1.13 1.13z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml b/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml
index 12e0f2ee02c9..2469ddc4860f 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml
@@ -14,14 +14,12 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="24dp"
- android:viewportHeight="24.0"
- android:viewportWidth="24.0"
android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
android:tint="?android:attr/colorControlNormal">
-
<path
- android:fillColor="#FFFFFFFF"
- android:pathData="M9,6.17L9,3h6v4h-4v1.17L9,6.17zM19.42,15L22,17.57l-0.8,0.8l-6.78,-6.78l0.8,-0.8l2.75,2.75V9h0.6L22,12.43L19.42,15zM19.17,13.55l1.13,-1.13l-1.13,-1.13V13.55zM17.21,17.21l3.98,3.98l-1.41,1.41l-3.98,-3.98l-0.58,0.58l-0.85,-0.85l0.58,-0.58L11,13.83V17c0,2.21 -1.78,4 -3.99,4S3,19.21 3,17c0,-2.21 1.79,-4 4.01,-4c0.73,0 1.41,0.21 2,0.55l0,-1.72L1.39,4.22l1.41,-1.41l13.56,13.56L17.21,17.21zM9.01,17c0,-1.1 -0.9,-2 -2,-2s-2,0.9 -2,2c0,1.1 0.9,2 2,2S9.01,18.1 9.01,17z"/>
-
-</vector>
+ android:fillColor="@android:color/white"
+ android:pathData="M9 6.17V3h6v4h-4v1.17l-2-2zM19.42 15L22 17.57l-0.8 0.8 -6.78-6.78 0.8 -0.8 2.75 2.75V9h0.6L22 12.43 19.42 15zm-0.25-1.45l1.13-1.13-1.13-1.13v2.26zm-1.96 3.66l3.98 3.98-1.41 1.41-3.98-3.98-0.58 0.58 -0.85-0.85 0.58 -0.58L11 13.83V17c0 2.21-1.78 4-3.99 4S3 19.21 3 17s1.79-4 4.01-4c0.73 0 1.41 0.21 2 0.55v-1.72L1.39 4.22 2.8 2.81l13.56 13.56 0.85 0.84z" />
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_mute.xml b/packages/SystemUI/res/drawable/ic_volume_media_mute.xml
index 45b5b87e8ab5..3a495963fc76 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media_mute.xml
@@ -22,9 +22,6 @@
<path
android:fillColor="#FFFFFFFF"
- android:pathData="M21.19,21.19L14,14l-2,-2l-9.2,-9.2L1.39,4.22l8.79,8.79c-0.06,0 -0.12,-0.01 -0.18,-0.01C7.79,13 6,14.79 6,17c0,2.21 1.79,4 4.01,4S14,19.21 14,17v-0.17l5.78,5.78L21.19,21.19zM10.01,19c-1.1,0 -2,-0.9 -2,-2c0,-1.1 0.9,-2 2,-2s2,0.9 2,2C12.01,18.1 11.11,19 10.01,19z"/>
- <path
- android:fillColor="#FFffffff"
- android:pathData="M14,11.17l0,-4.17l4,0l0,-4l-6,0l0,6.17z"/>
+ android:pathData="M21.19 21.19L14 14l-2-2-9.2-9.2-1.41 1.42 8.79 8.79c-0.06 0-0.12-0.01-0.18-0.01-2.21 0-4 1.79-4 4s1.79 4 4.01 4S14 19.21 14 17v-0.17l5.78 5.78 1.41-1.42zM14 11.17V7h4V3h-6v6.17z" />
</vector>
diff --git a/packages/SystemUI/res/layout-land/global_actions_column.xml b/packages/SystemUI/res/layout-land/global_actions_column.xml
index 99a4e13d2064..98cb0d0d4c23 100644
--- a/packages/SystemUI/res/layout-land/global_actions_column.xml
+++ b/packages/SystemUI/res/layout-land/global_actions_column.xml
@@ -42,10 +42,10 @@
android:orientation="horizontal"
android:layout_marginTop="@dimen/global_actions_grid_side_margin"
android:translationZ="@dimen/global_actions_translate"
- android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
- android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
- android:paddingTop="@dimen/global_actions_grid_vertical_padding"
- android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
+ android:paddingLeft="@dimen/global_actions_grid_vertical_padding"
+ android:paddingRight="@dimen/global_actions_grid_vertical_padding"
+ android:paddingTop="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingBottom="@dimen/global_actions_grid_horizontal_padding"
android:background="?android:attr/colorBackgroundFloating"
/>
<!-- For separated items-->
@@ -55,10 +55,10 @@
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/global_actions_grid_side_margin"
android:layout_marginTop="@dimen/global_actions_grid_side_margin"
- android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
- android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
- android:paddingTop="@dimen/global_actions_grid_vertical_padding"
- android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
+ android:paddingLeft="@dimen/global_actions_grid_vertical_padding"
+ android:paddingRight="@dimen/global_actions_grid_vertical_padding"
+ android:paddingTop="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingBottom="@dimen/global_actions_grid_horizontal_padding"
android:orientation="horizontal"
android:background="?android:attr/colorBackgroundFloating"
android:translationZ="@dimen/global_actions_translate"
diff --git a/packages/SystemUI/res/layout-land/global_actions_column_seascape.xml b/packages/SystemUI/res/layout-land/global_actions_column_seascape.xml
index 0f8613194959..5e7604c31731 100644
--- a/packages/SystemUI/res/layout-land/global_actions_column_seascape.xml
+++ b/packages/SystemUI/res/layout-land/global_actions_column_seascape.xml
@@ -41,10 +41,10 @@
android:orientation="horizontal"
android:layout_marginBottom="@dimen/global_actions_grid_side_margin"
android:translationZ="@dimen/global_actions_translate"
- android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
- android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
- android:paddingTop="@dimen/global_actions_grid_vertical_padding"
- android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
+ android:paddingLeft="@dimen/global_actions_grid_vertical_padding"
+ android:paddingRight="@dimen/global_actions_grid_vertical_padding"
+ android:paddingTop="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingBottom="@dimen/global_actions_grid_horizontal_padding"
android:background="?android:attr/colorBackgroundFloating"
/>
<!-- For separated items-->
@@ -55,10 +55,10 @@
android:layout_height="wrap_content"
android:layout_marginRight="@dimen/global_actions_grid_side_margin"
android:layout_marginBottom="@dimen/global_actions_grid_side_margin"
- android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
- android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
- android:paddingTop="@dimen/global_actions_grid_vertical_padding"
- android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
+ android:paddingLeft="@dimen/global_actions_grid_vertical_padding"
+ android:paddingRight="@dimen/global_actions_grid_vertical_padding"
+ android:paddingTop="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingBottom="@dimen/global_actions_grid_horizontal_padding"
android:orientation="horizontal"
android:background="?android:attr/colorBackgroundFloating"
android:translationZ="@dimen/global_actions_translate"
diff --git a/packages/SystemUI/res/layout/global_actions_grid.xml b/packages/SystemUI/res/layout/global_actions_grid.xml
index 3928062e43d2..456553d404dc 100644
--- a/packages/SystemUI/res/layout/global_actions_grid.xml
+++ b/packages/SystemUI/res/layout/global_actions_grid.xml
@@ -1,73 +1,95 @@
<?xml version="1.0" encoding="utf-8"?>
-<com.android.systemui.globalactions.GlobalActionsGridLayout
+<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@id/global_actions_view"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/global_actions_grid_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:orientation="horizontal"
- android:theme="@style/qs_theme"
- android:gravity="bottom | center_horizontal"
android:clipChildren="false"
android:clipToPadding="false"
- android:paddingBottom="@dimen/global_actions_grid_container_shadow_offset"
android:layout_marginBottom="@dimen/global_actions_grid_container_negative_shadow_offset"
>
- <LinearLayout
+
+ <FrameLayout
+ android:id="@+id/global_actions_panel_container"
+ android:layout_width="match_parent"
+ android:layout_height="0dp"
+ app:layout_constraintTop_toTopOf="parent"
+ app:layout_constraintBottom_toTopOf="@id/global_actions_view"
+ />
+
+ <com.android.systemui.globalactions.GlobalActionsGridLayout
+ android:id="@id/global_actions_view"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:layoutDirection="ltr"
+ android:orientation="horizontal"
+ android:theme="@style/qs_theme"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ android:gravity="bottom | center_horizontal"
android:clipChildren="false"
android:clipToPadding="false"
- android:layout_marginBottom="@dimen/global_actions_grid_container_bottom_margin"
+ android:paddingBottom="@dimen/global_actions_grid_container_shadow_offset"
+ android:layout_marginBottom="@dimen/global_actions_grid_container_negative_shadow_offset"
>
- <!-- For separated items-->
<LinearLayout
- android:id="@+id/separated_button"
- android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:layout_marginLeft="@dimen/global_actions_grid_side_margin"
- android:layout_marginRight="@dimen/global_actions_grid_side_margin"
- android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
- android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
- android:paddingTop="@dimen/global_actions_grid_vertical_padding"
- android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
- android:orientation="vertical"
- android:gravity="center"
- android:translationZ="@dimen/global_actions_translate"
- />
- <!-- Grid of action items -->
- <com.android.systemui.globalactions.ListGridLayout
- android:id="@android:id/list"
- android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:orientation="vertical"
- android:gravity="right"
- android:layout_marginRight="@dimen/global_actions_grid_side_margin"
- android:translationZ="@dimen/global_actions_translate"
- android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
- android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
- android:paddingTop="@dimen/global_actions_grid_vertical_padding"
- android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
+ android:layout_width="wrap_content"
+ android:layoutDirection="ltr"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:layout_marginBottom="@dimen/global_actions_grid_container_bottom_margin"
>
+ <!-- For separated items-->
<LinearLayout
+ android:id="@+id/separated_button"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:visibility="gone"
- android:layoutDirection="locale"
- />
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:visibility="gone"
- android:layoutDirection="locale"
+ android:layout_height="match_parent"
+ android:layout_marginLeft="@dimen/global_actions_grid_side_margin"
+ android:layout_marginRight="@dimen/global_actions_grid_side_margin"
+ android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingTop="@dimen/global_actions_grid_vertical_padding"
+ android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
+ android:orientation="vertical"
+ android:gravity="center"
+ android:translationZ="@dimen/global_actions_translate"
/>
- <LinearLayout
+ <!-- Grid of action items -->
+ <com.android.systemui.globalactions.ListGridLayout
+ android:id="@android:id/list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:visibility="gone"
- android:layoutDirection="locale"
- />
- </com.android.systemui.globalactions.ListGridLayout>
- </LinearLayout>
+ android:orientation="vertical"
+ android:gravity="right"
+ android:layout_marginRight="@dimen/global_actions_grid_side_margin"
+ android:translationZ="@dimen/global_actions_translate"
+ android:paddingLeft="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingRight="@dimen/global_actions_grid_horizontal_padding"
+ android:paddingTop="@dimen/global_actions_grid_vertical_padding"
+ android:paddingBottom="@dimen/global_actions_grid_vertical_padding"
+ >
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:layoutDirection="locale"
+ />
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:layoutDirection="locale"
+ />
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:visibility="gone"
+ android:layoutDirection="locale"
+ />
+ </com.android.systemui.globalactions.ListGridLayout>
+ </LinearLayout>
-</com.android.systemui.globalactions.GlobalActionsGridLayout>
+ </com.android.systemui.globalactions.GlobalActionsGridLayout>
+</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/invocation_lights.xml b/packages/SystemUI/res/layout/invocation_lights.xml
new file mode 100644
index 000000000000..ff78670d0719
--- /dev/null
+++ b/packages/SystemUI/res/layout/invocation_lights.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<com.android.systemui.assist.ui.InvocationLightsView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="bottom"
+ android:visibility="gone"/>
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index 8ffa2d83cfa2..87de9d4d3b51 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -219,7 +219,7 @@ asked for it -->
android:gravity="center"
android:orientation="vertical">
- <LinearLayout
+ <com.android.systemui.statusbar.notification.row.ButtonLinearLayout
android:id="@+id/alert"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -268,9 +268,9 @@ asked for it -->
android:ellipsize="end"
android:maxLines="2"
android:textAppearance="@style/TextAppearance.NotificationImportanceDetail"/>
- </LinearLayout>
+ </com.android.systemui.statusbar.notification.row.ButtonLinearLayout>
- <LinearLayout
+ <com.android.systemui.statusbar.notification.row.ButtonLinearLayout
android:id="@+id/silence"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -321,7 +321,7 @@ asked for it -->
android:ellipsize="end"
android:maxLines="2"
android:textAppearance="@style/TextAppearance.NotificationImportanceDetail"/>
- </LinearLayout>
+ </com.android.systemui.statusbar.notification.row.ButtonLinearLayout>
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/quick_settings_header_info.xml b/packages/SystemUI/res/layout/quick_settings_header_info.xml
index c812489ac085..683e86728e91 100644
--- a/packages/SystemUI/res/layout/quick_settings_header_info.xml
+++ b/packages/SystemUI/res/layout/quick_settings_header_info.xml
@@ -21,6 +21,7 @@
android:layout_below="@id/quick_status_bar_system_icons"
android:paddingStart="@dimen/status_bar_padding_start"
android:paddingEnd="@dimen/status_bar_padding_end"
+ android:visibility="invisible"
android:theme="@style/QSHeaderTheme">
<com.android.systemui.qs.QSHeaderInfoLayout
diff --git a/packages/SystemUI/res/layout/rounded_corners.xml b/packages/SystemUI/res/layout/rounded_corners.xml
index 02651a212816..b409c8f2ba5a 100644
--- a/packages/SystemUI/res/layout/rounded_corners.xml
+++ b/packages/SystemUI/res/layout/rounded_corners.xml
@@ -18,36 +18,30 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
+ <com.android.systemui.CornerHandleView
+ android:id="@+id/assist_hint_left"
+ android:layout_width="36dp"
+ android:layout_height="36dp"
+ android:layout_gravity="left|top"
+ android:visibility="gone"/>
+ <com.android.systemui.CornerHandleView
+ android:id="@+id/assist_hint_right"
+ android:layout_width="36dp"
+ android:layout_height="36dp"
+ android:layout_gravity="right|bottom"
+ android:visibility="gone"/>
<ImageView
android:id="@+id/left"
android:layout_width="12dp"
android:layout_height="12dp"
android:layout_gravity="left|top"
android:tint="#ff000000"
- android:src="@drawable/rounded" />
+ android:src="@drawable/rounded"/>
<ImageView
android:id="@+id/right"
android:layout_width="12dp"
android:layout_height="12dp"
android:tint="#ff000000"
android:layout_gravity="right|bottom"
- android:src="@drawable/rounded" />
- <ImageView
- android:id="@+id/assist_hint_left"
- android:layout_width="32dp"
- android:layout_height="32dp"
- android:padding="6dp"
- android:layout_gravity="left|top"
- android:src="@drawable/corner_gesture_hint"
- android:tint="#ffffffff"
- android:visibility="gone" />
- <ImageView
- android:id="@+id/assist_hint_right"
- android:layout_width="32dp"
- android:layout_height="32dp"
- android:padding="6dp"
- android:layout_gravity="right|bottom"
- android:src="@drawable/corner_gesture_hint"
- android:tint="#ffffffff"
- android:visibility="gone" />
+ android:src="@drawable/rounded"/>
</com.android.systemui.RegionInterceptingFrameLayout>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_section_header.xml b/packages/SystemUI/res/layout/status_bar_notification_section_header.xml
index 0c3c597a7b3a..d3eb9aeb1710 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_section_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_section_header.xml
@@ -44,6 +44,8 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="@dimen/notification_section_header_padding_left"
+ android:gravity="start"
+ android:textAlignment="gravity"
android:text="@string/notification_section_header_gentle"
android:textSize="12sp"
android:textColor="@color/notification_section_header_label_color"
diff --git a/packages/SystemUI/res/values-mcc311-mnc180/config.xml b/packages/SystemUI/res/values-mcc311-mnc180/config.xml
deleted file mode 100644
index 26b9192e0cc3..000000000000
--- a/packages/SystemUI/res/values-mcc311-mnc180/config.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2019, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources>
- <!-- Enable 5 bar signal strength icon -->
- <bool name="config_inflateSignalStrength">true</bool>
-</resources>
-
diff --git a/packages/SystemUI/res/values-mcc311-mnc480/config.xml b/packages/SystemUI/res/values-mcc311-mnc480/config.xml
deleted file mode 100644
index 7dadae7f9107..000000000000
--- a/packages/SystemUI/res/values-mcc311-mnc480/config.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2017, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-** http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
--->
-
-<!-- These resources are around just to allow their values to be customized
- for different hardware and product builds. -->
-<resources>
- <!-- Enable 5 bar signal strength icon -->
- <bool name="config_inflateSignalStrength">true</bool>
-</resources>
-
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index dd3073fb5e65..7b55d18676da 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -31,7 +31,10 @@
<color name="notification_divider_color">#212121</color>
<!-- The background color of the notification shade -->
- <color name="notification_shade_background_color">#181818</color>
+ <color name="notification_shade_background_color">@color/GM2_grey_900</color>
+
+ <!-- The color of the gear shown behind a notification -->
+ <color name="notification_gear_color">@color/GM2_grey_500</color>
<!-- The color of the ripples on the untinted notifications -->
<color name="notification_ripple_untinted_color">#30ffffff</color>
@@ -43,7 +46,7 @@
<color name="notification_primary_text_color">@*android:color/notification_primary_text_color_dark</color>
<color name="notification_guts_link_icon_tint">@color/GM2_grey_500</color>
- <color name="notification_guts_sub_text_color">@color/GM2_grey_500</color>
+ <color name="notification_guts_sub_text_color">@color/GM2_grey_300</color>
<color name="notification_guts_header_text_color">@color/GM2_grey_200</color>
<color name="notification_guts_info_button_color">@color/GM2_blue_300</color>
<color name="notification_guts_priority_button_content_color">@color/GM2_grey_500</color>
@@ -51,7 +54,7 @@
<color name="notification_guts_priority_button_bg_fill_color">@color/transparent</color>
<color name="notification_guts_priority_button_bg_fill_color_selected">@color/GM2_grey_800</color>
<color name="notification_guts_priority_button_bg_stroke_color">@color/GM2_grey_700</color>
- <color name="notification_guts_priority_button_bg_stroke_color_selected">@color/GM2_grey_700</color>
+ <color name="notification_guts_priority_button_bg_stroke_color_selected">@color/GM2_blue_300</color>
<color name="notification_section_header_label_color">@color/GM2_grey_200</color>
<color name="notification_section_clear_all_btn_color">@color/GM2_grey_500</color>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 3f84b32ee0c2..e7a1a660abc2 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -74,7 +74,7 @@
<color name="notification_divider_color">#FF616161</color>
<!-- The background color of the notification shade -->
- <color name="notification_shade_background_color">#ffeeeeee</color>
+ <color name="notification_shade_background_color">@color/GM2_grey_200</color>
<!-- The color of the ripples on the untinted notifications -->
<color name="notification_ripple_untinted_color">#28000000</color>
@@ -83,7 +83,7 @@
<color name="notification_ripple_tinted_color">#30ffffff</color>
<!-- The color of the gear shown behind a notification -->
- <color name="notification_gear_color">#ff757575</color>
+ <color name="notification_gear_color">@color/GM2_grey_700</color>
<!-- The color of the text inside a notification -->
<color name="notification_primary_text_color">@*android:color/notification_primary_text_color_light</color>
@@ -166,14 +166,17 @@
<color name="smart_reply_button_stroke">#ffdadce0</color>
<!-- Biometric dialog colors -->
- <color name="biometric_dialog_dim_color">#80000000</color> <!-- 50% black -->
+ <color name="biometric_dialog_dim_color">#80000000</color> <!-- 50% black -->
<color name="biometric_dialog_gray">#ff757575</color>
- <color name="biometric_dialog_accent">#ff008577</color> <!-- dark teal -->
- <color name="biometric_dialog_error">#ffd93025</color> <!-- red 600 -->
+ <color name="biometric_dialog_accent">#ff008577</color> <!-- dark teal -->
+ <color name="biometric_dialog_error">#ffd93025</color> <!-- red 600 -->
<!-- Logout button -->
<color name="logout_button_bg_color">#ccffffff</color>
+ <!-- Color for the Assistant invocation lights -->
+ <color name="default_invocation_lights_color">#ffffffff</color> <!-- white -->
+
<!-- GM2 colors -->
<color name="GM2_grey_50">#F8F9FA</color>
<color name="GM2_grey_100">#F1F3F4</color>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 27431f7257f2..6039568cab3a 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -40,9 +40,6 @@
<!-- Whether or not we show the number in the bar. -->
<bool name="config_statusBarShowNumber">false</bool>
- <!-- If the lock screen should be dismissed after biometric auth. -->
- <bool name="config_faceAuthDismissesKeyguard">false</bool>
-
<!-- Vibrator pattern for camera gesture launch. -->
<integer-array translatable="false" name="config_cameraLaunchGestureVibePattern">
<item>0</item>
@@ -417,10 +414,6 @@
it has been expanded to reveal its children. -->
<bool name="config_showGroupNotificationBgWhenExpanded">false</bool>
- <!-- Whether to artificially interpret all signal strengths as
- one bar higher than they actually are -->
- <bool name="config_inflateSignalStrength">false</bool>
-
<!-- Should we vibrate on an icon animation of the shelf. This should only be active if the
vibrator is capable of subtle vibrations -->
<bool name="config_vibrateOnIconAnimation">false</bool>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 19874948cb54..c5e4662f6d45 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -38,7 +38,6 @@
<dimen name="navigation_handle_sample_horizontal_margin">10dp</dimen>
<dimen name="navigation_home_handle_width">72dp</dimen>
-
<!-- Size of the nav bar edge panels, should be greater to the
edge sensitivity + the drag threshold -->
<dimen name="navigation_edge_panel_width">70dp</dimen>
@@ -57,6 +56,9 @@
<!-- Luminance change threshold that allows applying new value if difference was exceeded -->
<item name="navigation_luminance_change_threshold" type="dimen" format="float">0.05</item>
+ <dimen name="floating_rotation_button_diameter">40dp</dimen>
+ <dimen name="floating_rotation_button_min_margin">4dp</dimen>
+
<!-- Height of notification icons in the status bar -->
<dimen name="status_bar_icon_size">@*android:dimen/status_bar_icon_size</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 8bc84c6d4a44..3fe24929a778 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -495,6 +495,9 @@
<!-- Content description of the battery level icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_battery_level">Battery <xliff:g id="number">%d</xliff:g> percent.</string>
+ <!-- Content description of the battery level icon for accessibility, including the estimated time remaining before the phone runs out of battery (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_battery_level_with_estimate">Battery <xliff:g id="percentage" example="95%">%1$s</xliff:g> percent, about <xliff:g id="time" example="Until 3:15pm">%2$s</xliff:g> left based on your usage</string>
+
<!-- Content description of the battery level icon for accessibility while the device is charging (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_battery_level_charging">Battery charging, <xliff:g id="battery_percentage">%d</xliff:g> percent.</string>
@@ -2459,4 +2462,11 @@
<string name="bubble_accessibility_action_move_bottom_right">Move bottom right</string>
<!-- Text used for the bubble dismiss area. Bubbles dragged to, or flung towards, this area will go away. [CHAR LIMIT=20] -->
<string name="bubble_dismiss_text">Dismiss</string>
+
+ <!-- Notification content text when the system navigation mode changes as a result of changing the default launcher [CHAR LIMIT=NONE] -->
+ <string name="notification_content_system_nav_changed">System navigation updated. To make changes, go to Settings.</string>
+
+ <!-- Notification content text when switching to a default launcher that supports gesture navigation [CHAR LIMIT=NONE] -->
+ <string name="notification_content_gesture_nav_available">Go to Settings to update system navigation</string>
+
</resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java
index 6567b6ad1171..2b1fce8a4cf5 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/InputChannelCompat.java
@@ -18,7 +18,6 @@ package com.android.systemui.shared.system;
import android.os.Bundle;
import android.os.Looper;
-import android.util.Pair;
import android.view.BatchedInputEventReceiver;
import android.view.Choreographer;
import android.view.InputChannel;
@@ -42,19 +41,6 @@ public class InputChannelCompat {
}
/**
- * Creates a dispatcher and receiver pair to better handle events across threads.
- */
- public static Pair<InputEventDispatcher, InputEventReceiver> createPair(String name,
- Looper looper, Choreographer choreographer, InputEventListener listener) {
- InputChannel[] channels = InputChannel.openInputChannelPair(name);
-
- InputEventDispatcher dispatcher = new InputEventDispatcher(channels[0], looper);
- InputEventReceiver receiver = new InputEventReceiver(channels[1], looper, choreographer,
- listener);
- return Pair.create(dispatcher, receiver);
- }
-
- /**
* Creates a dispatcher from the extras received as part on onInitialize
*/
public static InputEventReceiver fromBundle(Bundle params, String key,
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SystemGestureExclusionListenerCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SystemGestureExclusionListenerCompat.java
new file mode 100644
index 000000000000..9fdecfbd44a0
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SystemGestureExclusionListenerCompat.java
@@ -0,0 +1,85 @@
+/**
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.shared.system;
+
+import android.graphics.Region;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.ISystemGestureExclusionListener;
+import android.view.WindowManagerGlobal;
+
+/**
+ * Utility class to listen for exclusion rect changes.
+ */
+public abstract class SystemGestureExclusionListenerCompat {
+
+ private static final String TAG = "SGEListenerCompat";
+
+ private final int mDisplayId;
+
+ private ISystemGestureExclusionListener mGestureExclusionListener =
+ new ISystemGestureExclusionListener.Stub() {
+ @Override
+ public void onSystemGestureExclusionChanged(int displayId,
+ Region systemGestureExclusion) {
+ if (displayId == mDisplayId) {
+ onExclusionChanged(systemGestureExclusion);
+ }
+ }
+ };
+ private boolean mRegistered;
+
+ public SystemGestureExclusionListenerCompat(int displayId) {
+ mDisplayId = displayId;
+ }
+
+ /**
+ * Called when the exclusion region has changed
+ */
+ public abstract void onExclusionChanged(Region systemGestureExclusion);
+
+ /**
+ * Registers the listener for getting exclusion rect changes.
+ */
+ public void register() {
+ if (!mRegistered) {
+ try {
+ WindowManagerGlobal.getWindowManagerService()
+ .registerSystemGestureExclusionListener(
+ mGestureExclusionListener, mDisplayId);
+ mRegistered = true;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to register window manager callbacks", e);
+ }
+ }
+ }
+
+ /**
+ * Unregisters the receiver if previously registered
+ */
+ public void unregister() {
+ if (mRegistered) {
+ try {
+ WindowManagerGlobal.getWindowManagerService()
+ .unregisterSystemGestureExclusionListener(
+ mGestureExclusionListener, mDisplayId);
+ mRegistered = false;
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to unregister window manager callbacks", e);
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 873874f30875..26d3d86778e4 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -111,6 +111,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
private static final String TAG = "KeyguardUpdateMonitor";
private static final boolean DEBUG = KeyguardConstants.DEBUG;
private static final boolean DEBUG_SIM_STATES = KeyguardConstants.DEBUG_SIM_STATES;
+ private static final boolean DEBUG_FACE = true;
private static final int LOW_BATTERY_THRESHOLD = 20;
private static final String ACTION_FACE_UNLOCK_STARTED
@@ -182,6 +183,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
* Prudently disable lockscreen.
*/
public static final boolean CORE_APPS_ONLY;
+
static {
try {
CORE_APPS_ONLY = IPackageManager.Stub.asInterface(
@@ -734,6 +736,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
if (acquireInfo != FaceManager.FACE_ACQUIRED_GOOD) {
return;
}
+ if (DEBUG_FACE) Log.d(TAG, "Face acquired");
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -760,6 +763,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
Log.d(TAG, "Face authentication disabled by DPM for userId: " + userId);
return;
}
+ if (DEBUG_FACE) Log.d(TAG, "Face auth succeeded for user " + userId);
onFaceAuthenticated(userId);
} finally {
setFaceRunningState(BIOMETRIC_STATE_STOPPED);
@@ -768,6 +772,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
private void handleFaceHelp(int msgId, String helpString) {
+ if (DEBUG_FACE) Log.d(TAG, "Face help received: " + helpString);
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
@@ -786,6 +791,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
};
private void handleFaceError(int msgId, String errString) {
+ if (DEBUG_FACE) Log.d(TAG, "Face error received: " + errString);
if (msgId == FaceManager.FACE_ERROR_CANCELED
&& mFaceRunningState == BIOMETRIC_STATE_CANCELLING_RESTARTING) {
setFaceRunningState(BIOMETRIC_STATE_STOPPED);
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
index 61a6952cacac..bd1e64a5f1c6 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
@@ -170,9 +170,10 @@ public class BubbleClockController implements ClockPlugin {
return;
}
final int length = colorPalette.length;
- final int color = colorPalette[Math.max(0, length - 3)];
- mLockClock.setTextColor(color);
- mAnalogClock.setClockColors(color, color);
+ final int primaryColor = colorPalette[Math.max(0, length - 2)];
+ final int secondaryColor = colorPalette[Math.max(0, length - 5)];
+ mLockClock.setTextColor(primaryColor);
+ mAnalogClock.setClockColors(secondaryColor, primaryColor);
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
index 9f4c403ed787..9edb54c146df 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
@@ -15,6 +15,8 @@
*/
package com.android.keyguard.clock;
+import static com.android.internal.config.sysui.SystemUiDeviceConfigFlags.CLOCK_FACE_BLACKLIST;
+
import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.Context;
@@ -24,9 +26,12 @@ import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.UserHandle;
+import android.provider.DeviceConfig;
import android.provider.Settings;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.view.LayoutInflater;
import androidx.annotation.VisibleForTesting;
@@ -42,10 +47,12 @@ import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.util.InjectionInflationController;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Supplier;
+import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -67,6 +74,8 @@ public final class ClockManager {
private final Handler mMainHandler = new Handler(Looper.getMainLooper());
private final CurrentUserObservable mCurrentUserObservable;
+ private final ArraySet<String> mBlacklistedClockPlugins = new ArraySet<>();
+
/**
* Observe settings changes to know when to switch the clock face.
*/
@@ -155,6 +164,41 @@ public final class ClockManager {
DisplayMetrics dm = res.getDisplayMetrics();
mWidth = dm.widthPixels;
mHeight = dm.heightPixels;
+
+ updateBlackList();
+ registerDeviceConfigListener();
+ }
+
+ private void updateBlackList() {
+ String blacklist = getBlackListFromConfig();
+
+ mBlacklistedClockPlugins.clear();
+ if (blacklist != null && !blacklist.isEmpty()) {
+ mBlacklistedClockPlugins.addAll(Arrays.asList(blacklist.split(",")));
+ }
+ }
+
+ String getBlackListFromConfig() {
+ return DeviceConfig.getString(
+ DeviceConfig.NAMESPACE_SYSTEMUI, CLOCK_FACE_BLACKLIST, null);
+ }
+
+ private void registerDeviceConfigListener() {
+ DeviceConfig.addOnPropertiesChangedListener(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ r -> mMainHandler.post(r),
+ properties -> onDeviceConfigPropertiesChanged(properties.getNamespace()));
+ }
+
+ void onDeviceConfigPropertiesChanged(String namespace) {
+ if (!DeviceConfig.NAMESPACE_SYSTEMUI.equals(namespace)) {
+ Log.e(TAG, "Received update from DeviceConfig for unrelated namespace: "
+ + namespace);
+ return;
+ }
+
+ updateBlackList();
+ reload();
}
/**
@@ -240,9 +284,9 @@ public final class ClockManager {
}
private void reload() {
- mPreviewClocks.reload();
+ mPreviewClocks.reloadCurrentClock();
mListeners.forEach((listener, clocks) -> {
- clocks.reload();
+ clocks.reloadCurrentClock();
ClockPlugin clock = clocks.getCurrentClock();
if (clock instanceof DefaultClockController) {
listener.onClockChanged(null);
@@ -287,20 +331,13 @@ public final class ClockManager {
@Override
public void onPluginConnected(ClockPlugin plugin, Context pluginContext) {
addClockPlugin(plugin);
- reload();
- if (plugin == mCurrentClock) {
- ClockManager.this.reload();
- }
+ reloadIfNeeded(plugin);
}
@Override
public void onPluginDisconnected(ClockPlugin plugin) {
- boolean isCurrentClock = plugin == mCurrentClock;
removeClockPlugin(plugin);
- reload();
- if (isCurrentClock) {
- ClockManager.this.reload();
- }
+ reloadIfNeeded(plugin);
}
/**
@@ -313,10 +350,12 @@ public final class ClockManager {
}
/**
- * Get information about available clock faces.
+ * Get information about clock faces which are available and not in blacklist.
*/
List<ClockInfo> getInfo() {
- return mClockInfo;
+ return mClockInfo.stream()
+ .filter(info -> !mBlacklistedClockPlugins.contains(info.getId()))
+ .collect(Collectors.toList());
}
/**
@@ -347,10 +386,19 @@ public final class ClockManager {
}
}
+ private void reloadIfNeeded(ClockPlugin plugin) {
+ final boolean wasCurrentClock = plugin == mCurrentClock;
+ reloadCurrentClock();
+ final boolean isCurrentClock = plugin == mCurrentClock;
+ if (wasCurrentClock || isCurrentClock) {
+ ClockManager.this.reload();
+ }
+ }
+
/**
* Update the current clock.
*/
- void reload() {
+ void reloadCurrentClock() {
mCurrentClock = getClockPlugin();
}
@@ -359,7 +407,7 @@ public final class ClockManager {
if (ClockManager.this.isDocked()) {
final String name = mSettingsWrapper.getDockedClockFace(
mCurrentUserObservable.getCurrentUser().getValue());
- if (name != null) {
+ if (name != null && !mBlacklistedClockPlugins.contains(name)) {
plugin = mClocks.get(name);
if (plugin != null) {
return plugin;
@@ -368,7 +416,7 @@ public final class ClockManager {
}
final String name = mSettingsWrapper.getLockScreenCustomClockFace(
mCurrentUserObservable.getCurrentUser().getValue());
- if (name != null) {
+ if (name != null && !mBlacklistedClockPlugins.contains(name)) {
plugin = mClocks.get(name);
}
return plugin;
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index de4c79839f25..f66463e4ef9b 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -322,9 +322,6 @@ public class BatteryMeterView extends LinearLayout implements
mCharging = pluggedIn;
mLevel = level;
updatePercentText();
- setContentDescription(
- getContext().getString(charging ? R.string.accessibility_battery_level_charging
- : R.string.accessibility_battery_level, level));
}
@Override
@@ -358,6 +355,9 @@ public class BatteryMeterView extends LinearLayout implements
mBatteryController.getEstimatedTimeRemainingString((String estimate) -> {
if (estimate != null) {
mBatteryPercentView.setText(estimate);
+ setContentDescription(getContext().getString(
+ R.string.accessibility_battery_level_with_estimate,
+ mLevel, estimate));
} else {
setPercentTextAtCurrentLevel();
}
@@ -371,6 +371,9 @@ public class BatteryMeterView extends LinearLayout implements
private void setPercentTextAtCurrentLevel() {
mBatteryPercentView.setText(
NumberFormat.getPercentInstance().format(mLevel / 100f));
+ setContentDescription(
+ getContext().getString(mCharging ? R.string.accessibility_battery_level_charging
+ : R.string.accessibility_battery_level, mLevel));
}
private void updateShowPercent() {
diff --git a/packages/SystemUI/src/com/android/systemui/CornerHandleView.java b/packages/SystemUI/src/com/android/systemui/CornerHandleView.java
new file mode 100644
index 000000000000..691c3f98825d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/CornerHandleView.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.animation.ArgbEvaluator;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.os.SystemProperties;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.view.ContextThemeWrapper;
+import android.view.View;
+
+import com.android.settingslib.Utils;
+
+/**
+ * CornerHandleView draws an inset arc intended to be displayed within the screen decoration
+ * corners.
+ */
+public class CornerHandleView extends View {
+ private static final boolean ALLOW_TUNING = false;
+ private static final int ANGLE_DEGREES = 50;
+ private static final float STROKE_DP = 2.5f;
+ // Radius to use if none is available.
+ private static final int FALLBACK_RADIUS_DP = 15;
+
+ private Paint mPaint;
+ private int mLightColor;
+ private int mDarkColor;
+ private RectF mOval;
+
+
+ public CornerHandleView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ mPaint = new Paint();
+ mPaint.setAntiAlias(true);
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setStrokeCap(Paint.Cap.ROUND);
+ mPaint.setStrokeWidth(getStrokePx());
+
+ final int dualToneDarkTheme = Utils.getThemeAttr(mContext,
+ R.attr.darkIconTheme);
+ final int dualToneLightTheme = Utils.getThemeAttr(mContext,
+ R.attr.lightIconTheme);
+ Context lightContext = new ContextThemeWrapper(mContext, dualToneLightTheme);
+ Context darkContext = new ContextThemeWrapper(mContext, dualToneDarkTheme);
+ mLightColor = Utils.getColorAttrDefaultColor(lightContext,
+ R.attr.singleToneColor);
+ mDarkColor = Utils.getColorAttrDefaultColor(darkContext,
+ R.attr.singleToneColor);
+
+ updateOval();
+ }
+
+ /**
+ * Receives an intensity from 0 (lightest) to 1 (darkest) and sets the handle color
+ * appropriately. Intention is to match the home handle color.
+ */
+ public void updateDarkness(float darkIntensity) {
+ mPaint.setColor((int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
+ mLightColor,
+ mDarkColor));
+ invalidate();
+ }
+
+ @Override
+ public void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ if (ALLOW_TUNING) {
+ mPaint.setStrokeWidth(getStrokePx());
+ updateOval();
+ }
+
+ canvas.drawArc(mOval, 180 + ((90 - getAngle()) / 2), getAngle(), false,
+ mPaint);
+ }
+
+ // TODO(b/133834204): Remove tweaking of corner handles
+ private static float convertDpToPixel(float dp, Context context) {
+ return dp * ((float) context.getResources().getDisplayMetrics().densityDpi
+ / DisplayMetrics.DENSITY_DEFAULT);
+ }
+
+ private void updateOval() {
+ mOval = new RectF(getMarginPx() - (getStrokePx() / 2.f),
+ getMarginPx() - (getStrokePx() / 2.f),
+ getMarginPx() + (2 * (getRadiusPx()) + (getStrokePx() / 2.f)),
+ getMarginPx() + 2 * getRadiusPx() + (getStrokePx() / 2.f));
+ }
+
+ private int getAngle() {
+ if (ALLOW_TUNING) {
+ return SystemProperties.getInt("CORNER_HANDLE_ANGLE_DEGREES", ANGLE_DEGREES);
+ } else {
+ return ANGLE_DEGREES;
+ }
+ }
+
+ private int getMarginPx() {
+ // Hand-derived function to map radiusPx to the margin amount.
+ // https://www.wolframalpha.com/input/?i=0.001402+*+x+%5E2%E2%88%920.08661+*+x%2B17.20+from+40+to+180
+ int radius = getRadiusPx();
+ int marginPx = (int) (0.001402f * radius * radius - 0.08661f * radius + 17.2f);
+ if (ALLOW_TUNING) {
+ return SystemProperties.getInt("CORNER_HANDLE_MARGIN_PX", marginPx);
+ } else {
+ return marginPx;
+ }
+ }
+
+ private int getRadiusPx() {
+ // Attempt to get the bottom corner radius, otherwise fall back on the generic or top
+ // values. If none are available, use the FALLBACK_RADIUS_DP.
+ int radius = getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.rounded_corner_radius_bottom);
+ if (radius == 0) {
+ radius = getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.rounded_corner_radius);
+ }
+ if (radius == 0) {
+ radius = getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.rounded_corner_radius_top);
+ }
+ if (radius == 0) {
+ radius = (int) convertDpToPixel(FALLBACK_RADIUS_DP, mContext);
+ }
+ if (ALLOW_TUNING) {
+ return SystemProperties.getInt("CORNER_HANDLE_RADIUS_PX", radius);
+ } else {
+ return radius;
+ }
+ }
+
+ private int getStrokePx() {
+ if (ALLOW_TUNING) {
+ return SystemProperties.getInt("CORNER_HANDLE_STROKE_PX",
+ (int) convertDpToPixel(STROKE_DP, getContext()));
+ } else {
+ return (int) convertDpToPixel(STROKE_DP, getContext());
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 390a9e65c1b4..4aaf85adfce6 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -60,6 +60,12 @@ import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
+import android.view.animation.Animation;
+import android.view.animation.AnimationSet;
+import android.view.animation.OvershootInterpolator;
+import android.view.animation.PathInterpolator;
+import android.view.animation.ScaleAnimation;
+import android.view.animation.TranslateAnimation;
import android.widget.FrameLayout;
import android.widget.ImageView;
@@ -72,6 +78,7 @@ import com.android.systemui.fragments.FragmentHostManager.FragmentListener;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.SecureSetting;
import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
+import com.android.systemui.statusbar.phone.NavigationBarTransitions;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.tuner.TunablePadding;
import com.android.systemui.tuner.TunerService;
@@ -85,7 +92,8 @@ import java.util.List;
* An overlay that draws screen decorations in software (e.g for rounded corners or display cutout)
* for antialiasing and emulation purposes.
*/
-public class ScreenDecorations extends SystemUI implements Tunable {
+public class ScreenDecorations extends SystemUI implements Tunable,
+ NavigationBarTransitions.DarkIntensityListener {
private static final boolean DEBUG = false;
private static final String TAG = "ScreenDecorations";
@@ -93,13 +101,17 @@ public class ScreenDecorations extends SystemUI implements Tunable {
public static final String PADDING = "sysui_rounded_content_padding";
private static final boolean DEBUG_SCREENSHOT_ROUNDED_CORNERS =
SystemProperties.getBoolean("debug.screenshot_rounded_corners", false);
+ private static final boolean VERBOSE = false;
private DisplayManager mDisplayManager;
private DisplayManager.DisplayListener mDisplayListener;
- @VisibleForTesting protected int mRoundedDefault;
- @VisibleForTesting protected int mRoundedDefaultTop;
- @VisibleForTesting protected int mRoundedDefaultBottom;
+ @VisibleForTesting
+ protected int mRoundedDefault;
+ @VisibleForTesting
+ protected int mRoundedDefaultTop;
+ @VisibleForTesting
+ protected int mRoundedDefaultBottom;
private View mOverlay;
private View mBottomOverlay;
private float mDensity;
@@ -111,6 +123,8 @@ public class ScreenDecorations extends SystemUI implements Tunable {
private SecureSetting mColorInversionSetting;
private boolean mPendingRotationChange;
private Handler mHandler;
+ private boolean mAssistHintBlocked = false;
+ private boolean mIsReceivingNavBarColor = false;
/**
* Converts a set of {@link Rect}s into a {@link Region}
@@ -137,15 +151,32 @@ public class ScreenDecorations extends SystemUI implements Tunable {
putComponent(ScreenDecorations.class, this);
}
- private void fade(View view, boolean fadeIn) {
+ private void fade(View view, boolean fadeIn, boolean isLeft) {
if (fadeIn) {
view.animate().cancel();
- view.setAlpha(0f);
+ view.setAlpha(1f);
view.setVisibility(View.VISIBLE);
- view.animate().alpha(1f);
+
+ AnimationSet anim = new AnimationSet(true);
+ anim.setDuration(900);
+
+ Animation scaleAnimation = new ScaleAnimation(2f, 1f, 2f, 1f,
+ ScaleAnimation.RELATIVE_TO_SELF, 0.5f, ScaleAnimation.RELATIVE_TO_SELF, 0.5f);
+ anim.addAnimation(scaleAnimation);
+ anim.setInterpolator(new PathInterpolator(0.02f, 0.44f, 0.67f, 1.00f));
+
+ Animation translateAnimation = new TranslateAnimation(
+ TranslateAnimation.RELATIVE_TO_SELF, isLeft ? -0.2f : 0.2f,
+ TranslateAnimation.RELATIVE_TO_SELF,
+ 0f,
+ TranslateAnimation.RELATIVE_TO_SELF, 0.2f, TranslateAnimation.RELATIVE_TO_SELF,
+ 0f);
+ anim.addAnimation(translateAnimation);
+ anim.setInterpolator(new OvershootInterpolator());
+ view.startAnimation(anim);
} else {
view.animate().cancel();
- view.animate().alpha(0f).withEndAction(() -> view.setVisibility(View.INVISIBLE));
+ view.animate().setDuration(400).alpha(0f);
}
}
@@ -161,35 +192,59 @@ public class ScreenDecorations extends SystemUI implements Tunable {
return;
}
+ if (mAssistHintBlocked && visible) {
+ if (VERBOSE) {
+ Log.v(TAG, "Assist hint blocked, cannot make it visible");
+ }
+ return;
+ }
+
if (mAssistHintVisible != visible) {
mAssistHintVisible = visible;
- View assistHintTopLeft = mOverlay.findViewById(R.id.assist_hint_left);
- View assistHintTopRight = mOverlay.findViewById(R.id.assist_hint_right);
- View assistHintBottomLeft = mBottomOverlay.findViewById(R.id.assist_hint_left);
- View assistHintBottomRight = mBottomOverlay.findViewById(R.id.assist_hint_right);
+ CornerHandleView assistHintTopLeft = mOverlay.findViewById(R.id.assist_hint_left);
+ CornerHandleView assistHintTopRight = mOverlay.findViewById(R.id.assist_hint_right);
+ CornerHandleView assistHintBottomLeft = mBottomOverlay.findViewById(
+ R.id.assist_hint_left);
+ CornerHandleView assistHintBottomRight = mBottomOverlay.findViewById(
+ R.id.assist_hint_right);
switch (mRotation) {
case RotationUtils.ROTATION_NONE:
- fade(assistHintBottomLeft, mAssistHintVisible);
- fade(assistHintBottomRight, mAssistHintVisible);
+ fade(assistHintBottomLeft, mAssistHintVisible, /* isLeft = */ true);
+ fade(assistHintBottomRight, mAssistHintVisible, /* isLeft = */ false);
break;
case RotationUtils.ROTATION_LANDSCAPE:
- fade(assistHintTopRight, mAssistHintVisible);
- fade(assistHintBottomRight, mAssistHintVisible);
+ fade(assistHintTopRight, mAssistHintVisible, /* isLeft = */ true);
+ fade(assistHintBottomRight, mAssistHintVisible, /* isLeft = */ false);
break;
case RotationUtils.ROTATION_SEASCAPE:
- fade(assistHintTopLeft, mAssistHintVisible);
- fade(assistHintBottomLeft, mAssistHintVisible);
+ fade(assistHintTopLeft, mAssistHintVisible, /* isLeft = */ false);
+ fade(assistHintBottomLeft, mAssistHintVisible, /* isLeft = */ true);
break;
case RotationUtils.ROTATION_UPSIDE_DOWN:
- fade(assistHintTopLeft, mAssistHintVisible);
- fade(assistHintTopRight, mAssistHintVisible);
+ fade(assistHintTopLeft, mAssistHintVisible, /* isLeft = */ false);
+ fade(assistHintTopRight, mAssistHintVisible, /* isLeft = */ true);
break;
}
}
}
+ /**
+ * Prevents the assist hint from becoming visible even if `mAssistHintVisible` is true.
+ */
+ public void setAssistHintBlocked(boolean blocked) {
+ if (!mHandler.getLooper().isCurrentThread()) {
+ mHandler.post(() -> setAssistHintBlocked(blocked));
+ return;
+ }
+
+ mAssistHintBlocked = blocked;
+ if (mAssistHintVisible && mAssistHintBlocked) {
+ setAssistHintVisible(false);
+ }
+ }
+
@VisibleForTesting
Handler startHandlerThread() {
HandlerThread thread = new HandlerThread("ScreenDecorations");
@@ -253,12 +308,12 @@ public class ScreenDecorations extends SystemUI implements Tunable {
.inflate(R.layout.rounded_corners, null);
mCutoutTop = new DisplayCutoutView(mContext, true,
this::updateWindowVisibilities, this);
- ((ViewGroup)mOverlay).addView(mCutoutTop);
+ ((ViewGroup) mOverlay).addView(mCutoutTop);
mBottomOverlay = LayoutInflater.from(mContext)
.inflate(R.layout.rounded_corners, null);
mCutoutBottom = new DisplayCutoutView(mContext, false,
this::updateWindowVisibilities, this);
- ((ViewGroup)mBottomOverlay).addView(mCutoutBottom);
+ ((ViewGroup) mBottomOverlay).addView(mCutoutBottom);
mOverlay.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
mOverlay.setAlpha(0);
@@ -378,10 +433,26 @@ public class ScreenDecorations extends SystemUI implements Tunable {
if (mOverlay != null) {
updateLayoutParams();
updateViews();
+ if (mAssistHintVisible) {
+ // If assist handles are visible, hide them without animation and then make them
+ // show once again (with corrected rotation).
+ hideAssistHandles();
+ setAssistHintVisible(true);
+ }
}
}
}
+ private void hideAssistHandles() {
+ if (mOverlay != null && mBottomOverlay != null) {
+ mOverlay.findViewById(R.id.assist_hint_left).setVisibility(View.GONE);
+ mOverlay.findViewById(R.id.assist_hint_right).setVisibility(View.GONE);
+ mBottomOverlay.findViewById(R.id.assist_hint_left).setVisibility(View.GONE);
+ mBottomOverlay.findViewById(R.id.assist_hint_right).setVisibility(View.GONE);
+ mAssistHintVisible = false;
+ }
+ }
+
private void updateRoundedCornerRadii() {
final int newRoundedDefault = mContext.getResources().getDimensionPixelSize(
com.android.internal.R.dimen.rounded_corner_radius);
@@ -416,7 +487,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
} else if (mRotation == RotationUtils.ROTATION_LANDSCAPE) {
updateView(topLeft, Gravity.TOP | Gravity.LEFT, 0);
updateView(topRight, Gravity.BOTTOM | Gravity.LEFT, 270);
- updateView(bottomLeft, Gravity.TOP | Gravity.RIGHT, 90);;
+ updateView(bottomLeft, Gravity.TOP | Gravity.RIGHT, 90);
updateView(bottomRight, Gravity.BOTTOM | Gravity.RIGHT, 180);
} else if (mRotation == RotationUtils.ROTATION_UPSIDE_DOWN) {
updateView(topLeft, Gravity.BOTTOM | Gravity.LEFT, 270);
@@ -477,7 +548,7 @@ public class ScreenDecorations extends SystemUI implements Tunable {
}
private void updateView(View v, int gravity, int rotation) {
- ((FrameLayout.LayoutParams)v.getLayoutParams()).gravity = gravity;
+ ((FrameLayout.LayoutParams) v.getLayoutParams()).gravity = gravity;
v.setRotation(rotation);
}
@@ -613,6 +684,10 @@ public class ScreenDecorations extends SystemUI implements Tunable {
setSize(mOverlay.findViewById(R.id.right), sizeTop);
setSize(mBottomOverlay.findViewById(R.id.left), sizeBottom);
setSize(mBottomOverlay.findViewById(R.id.right), sizeBottom);
+ setSize(mOverlay.findViewById(R.id.assist_hint_left), sizeTop * 2);
+ setSize(mOverlay.findViewById(R.id.assist_hint_right), sizeTop * 2);
+ setSize(mBottomOverlay.findViewById(R.id.assist_hint_left), sizeBottom * 2);
+ setSize(mBottomOverlay.findViewById(R.id.assist_hint_right), sizeBottom * 2);
}
});
}
@@ -624,6 +699,27 @@ public class ScreenDecorations extends SystemUI implements Tunable {
view.setLayoutParams(params);
}
+ @Override
+ public void onDarkIntensity(float darkIntensity) {
+ if (mOverlay != null) {
+ CornerHandleView assistHintTopLeft = mOverlay.findViewById(R.id.assist_hint_left);
+ CornerHandleView assistHintTopRight = mOverlay.findViewById(R.id.assist_hint_right);
+
+ assistHintTopLeft.updateDarkness(darkIntensity);
+ assistHintTopRight.updateDarkness(darkIntensity);
+ }
+
+ if (mBottomOverlay != null) {
+ CornerHandleView assistHintBottomLeft = mBottomOverlay.findViewById(
+ R.id.assist_hint_left);
+ CornerHandleView assistHintBottomRight = mBottomOverlay.findViewById(
+ R.id.assist_hint_right);
+
+ assistHintBottomLeft.updateDarkness(darkIntensity);
+ assistHintBottomRight.updateDarkness(darkIntensity);
+ }
+ }
+
@VisibleForTesting
static class TunablePaddingTagListener implements FragmentListener {
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
index 3fc6689b2f19..49bd5bd09220 100644
--- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
@@ -100,6 +100,13 @@ public class AppOpsControllerImpl implements AppOpsController,
} else {
mAppOps.stopWatchingActive(this);
mAppOps.stopWatchingNoted(this);
+ mBGHandler.removeCallbacksAndMessages(null); // null removes all
+ synchronized (mActiveItems) {
+ mActiveItems.clear();
+ }
+ synchronized (mNotedItems) {
+ mNotedItems.clear();
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehavior.java
index e2c731314246..2eda3d784382 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehavior.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehavior.java
@@ -16,31 +16,10 @@
package com.android.systemui.assist;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController;
-
public enum AssistHandleBehavior {
- TEST(new AssistHandleOffBehavior()),
- OFF(new AssistHandleOffBehavior()),
- LIKE_HOME(new AssistHandleLikeHomeBehavior()),
- REMINDER_EXP(new AssistHandleReminderExpBehavior());
-
- private BehaviorController mController;
-
- AssistHandleBehavior(BehaviorController controller) {
- mController = controller;
- }
-
- BehaviorController getController() {
- return mController;
- }
-
- @VisibleForTesting
- void setTestController(BehaviorController controller) {
- if (this.equals(TEST)) {
- mController = controller;
- }
- }
+ TEST,
+ OFF,
+ LIKE_HOME,
+ REMINDER_EXP;
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java
index 0203d9ed2376..01deb03c466b 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleBehaviorController.java
@@ -16,24 +16,27 @@
package com.android.systemui.assist;
-import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Build;
import android.os.Handler;
import android.os.SystemClock;
-import android.os.SystemProperties;
+import android.provider.DeviceConfig;
import android.util.Log;
+import androidx.annotation.Nullable;
+
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.app.AssistUtils;
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
+import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.Dependency;
import com.android.systemui.ScreenDecorations;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.statusbar.phone.NavigationModeController;
-import java.util.Locale;
+import java.util.EnumMap;
+import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
@@ -46,60 +49,76 @@ import java.util.function.Supplier;
public final class AssistHandleBehaviorController implements AssistHandleCallbacks {
private static final String TAG = "AssistHandleBehavior";
- private static final boolean IS_DEBUG_DEVICE =
- Build.TYPE.toLowerCase(Locale.ROOT).contains("debug")
- || Build.TYPE.toLowerCase(Locale.ROOT).equals("eng");
- private static final String SHOWN_FREQUENCY_THRESHOLD_KEY =
- "ASSIST_HANDLES_SHOWN_FREQUENCY_THRESHOLD_MS";
private static final long DEFAULT_SHOWN_FREQUENCY_THRESHOLD_MS = TimeUnit.SECONDS.toMillis(10);
- private static final String SHOW_AND_GO_DURATION_KEY = "ASSIST_HANDLES_SHOW_AND_GO_DURATION_MS";
private static final long DEFAULT_SHOW_AND_GO_DURATION_MS = TimeUnit.SECONDS.toMillis(3);
- private static final String BEHAVIOR_KEY = "behavior";
- private static final String SET_BEHAVIOR_ACTION =
- "com.android.systemui.SET_ASSIST_HANDLE_BEHAVIOR";
+
+ /**
+ * This is the default behavior that will be used once the system is up. It will be set once the
+ * behavior dependencies are available. This ensures proper behavior lifecycle.
+ */
+ private static final AssistHandleBehavior DEFAULT_BEHAVIOR = AssistHandleBehavior.REMINDER_EXP;
private final Context mContext;
+ private final AssistUtils mAssistUtils;
private final Handler mHandler;
private final Runnable mHideHandles = this::hideHandles;
private final Supplier<ScreenDecorations> mScreenDecorationsSupplier;
+ private final Map<AssistHandleBehavior, BehaviorController> mBehaviorMap =
+ new EnumMap<>(AssistHandleBehavior.class);
private boolean mHandlesShowing = false;
private long mHandlesLastHiddenAt;
+ /**
+ * This should always be initialized as {@link AssistHandleBehavior#OFF} to ensure proper
+ * behavior lifecycle.
+ */
private AssistHandleBehavior mCurrentBehavior = AssistHandleBehavior.OFF;
private boolean mInGesturalMode;
- AssistHandleBehaviorController(Context context, Handler handler) {
- this(context, handler, () ->
- SysUiServiceProvider.getComponent(context, ScreenDecorations.class));
+ AssistHandleBehaviorController(Context context, AssistUtils assistUtils, Handler handler) {
+ this(
+ context,
+ assistUtils,
+ handler, () -> SysUiServiceProvider.getComponent(context, ScreenDecorations.class),
+ /* testBehavior = */ null);
}
@VisibleForTesting
AssistHandleBehaviorController(
Context context,
+ AssistUtils assistUtils,
Handler handler,
- Supplier<ScreenDecorations> screenDecorationsSupplier) {
+ Supplier<ScreenDecorations> screenDecorationsSupplier,
+ @Nullable BehaviorController testBehavior) {
mContext = context;
+ mAssistUtils = assistUtils;
mHandler = handler;
mScreenDecorationsSupplier = screenDecorationsSupplier;
+ mBehaviorMap.put(AssistHandleBehavior.OFF, new AssistHandleOffBehavior());
+ mBehaviorMap.put(AssistHandleBehavior.LIKE_HOME, new AssistHandleLikeHomeBehavior());
+ mBehaviorMap.put(AssistHandleBehavior.REMINDER_EXP, new AssistHandleReminderExpBehavior());
+ if (testBehavior != null) {
+ mBehaviorMap.put(AssistHandleBehavior.TEST, testBehavior);
+ }
+
mInGesturalMode = QuickStepContract.isGesturalMode(
Dependency.get(NavigationModeController.class)
.addListener(this::handleNavigationModeChange));
- if (IS_DEBUG_DEVICE) {
- context.registerReceiver(new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String behaviorString = intent.getExtras().getString(BEHAVIOR_KEY);
- try {
- setBehavior(AssistHandleBehavior.valueOf(behaviorString));
- } catch (IllegalArgumentException e) {
- Log.e(TAG, "Invalid behavior identifier: " + behaviorString);
+ setBehavior(DeviceConfig.getString(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.ASSIST_HANDLES_BEHAVIOR_MODE,
+ DEFAULT_BEHAVIOR.toString()));
+ DeviceConfig.addOnPropertyChangedListener(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ mHandler::post,
+ (namespace, name, value) -> {
+ if (SystemUiDeviceConfigFlags.ASSIST_HANDLES_BEHAVIOR_MODE.equals(name)) {
+ setBehavior(value);
}
- }
- }, new IntentFilter(SET_BEHAVIOR_ACTION));
- }
+ });
}
@Override
@@ -123,26 +142,56 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
mHandler.post(() -> maybeShowHandles(/* ignoreThreshold = */ true));
}
+ void onAssistantGesturePerformed() {
+ mBehaviorMap.get(mCurrentBehavior).onAssistantGesturePerformed();
+ }
+
void setBehavior(AssistHandleBehavior behavior) {
if (mCurrentBehavior == behavior) {
return;
}
+ if (!mBehaviorMap.containsKey(behavior)) {
+ Log.e(TAG, "Unsupported behavior requested: " + behavior.toString());
+ return;
+ }
+
if (mInGesturalMode) {
- mCurrentBehavior.getController().onModeDeactivated();
- behavior.getController().onModeActivated(mContext, this);
+ mBehaviorMap.get(mCurrentBehavior).onModeDeactivated();
+ mBehaviorMap.get(behavior).onModeActivated(mContext, /* callbacks = */ this);
}
mCurrentBehavior = behavior;
}
- private static long getShownFrequencyThreshold() {
- return SystemProperties.getLong(
- SHOWN_FREQUENCY_THRESHOLD_KEY, DEFAULT_SHOWN_FREQUENCY_THRESHOLD_MS);
+ private void setBehavior(@Nullable String behavior) {
+ try {
+ setBehavior(AssistHandleBehavior.valueOf(behavior));
+ } catch (IllegalArgumentException | NullPointerException e) {
+ Log.e(TAG, "Invalid behavior: " + behavior, e);
+ }
+ }
+
+ private boolean handlesUnblocked(boolean ignoreThreshold) {
+ long timeSinceHidden = SystemClock.elapsedRealtime() - mHandlesLastHiddenAt;
+ boolean notThrottled = ignoreThreshold || timeSinceHidden > getShownFrequencyThreshold();
+ ComponentName assistantComponent =
+ mAssistUtils.getAssistComponentForUser(KeyguardUpdateMonitor.getCurrentUser());
+ return notThrottled && assistantComponent != null;
+ }
+
+ private long getShownFrequencyThreshold() {
+ return DeviceConfig.getLong(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOWN_FREQUENCY_THRESHOLD_MS,
+ DEFAULT_SHOWN_FREQUENCY_THRESHOLD_MS);
}
- private static long getShowAndGoDuration() {
- return SystemProperties.getLong(SHOW_AND_GO_DURATION_KEY, DEFAULT_SHOW_AND_GO_DURATION_MS);
+ private long getShowAndGoDuration() {
+ return DeviceConfig.getLong(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.ASSIST_HANDLES_SHOW_AND_GO_DURATION_MS,
+ DEFAULT_SHOW_AND_GO_DURATION_MS);
}
private void maybeShowHandles(boolean ignoreThreshold) {
@@ -150,8 +199,7 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
return;
}
- long timeSinceHidden = SystemClock.elapsedRealtime() - mHandlesLastHiddenAt;
- if (ignoreThreshold || timeSinceHidden > getShownFrequencyThreshold()) {
+ if (handlesUnblocked(ignoreThreshold)) {
mHandlesShowing = true;
ScreenDecorations screenDecorations = mScreenDecorationsSupplier.get();
if (screenDecorations == null) {
@@ -185,9 +233,9 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
mInGesturalMode = inGesturalMode;
if (mInGesturalMode) {
- mCurrentBehavior.getController().onModeActivated(mContext, this);
+ mBehaviorMap.get(mCurrentBehavior).onModeActivated(mContext, /* callbacks = */ this);
} else {
- mCurrentBehavior.getController().onModeDeactivated();
+ mBehaviorMap.get(mCurrentBehavior).onModeDeactivated();
hide();
}
}
@@ -199,6 +247,7 @@ public final class AssistHandleBehaviorController implements AssistHandleCallbac
interface BehaviorController {
void onModeActivated(Context context, AssistHandleCallbacks callbacks);
- void onModeDeactivated();
+ default void onModeDeactivated() {}
+ default void onAssistantGesturePerformed() {}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java
index e89e93c0adf0..05e504c93b82 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleLikeHomeBehavior.java
@@ -16,17 +16,15 @@
package com.android.systemui.assist;
-import android.app.StatusBarManager;
import android.content.Context;
import androidx.annotation.Nullable;
import com.android.systemui.Dependency;
-import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.NavigationBarController;
-import com.android.systemui.statusbar.phone.NavigationBarFragment;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.recents.OverviewProxyService;
+import com.android.systemui.shared.system.QuickStepContract;
/**
* Assistant Handle behavior that makes Assistant handles show/hide when the home handle is
@@ -34,47 +32,68 @@ import com.android.systemui.statusbar.phone.NavigationBarFragment;
*/
final class AssistHandleLikeHomeBehavior implements BehaviorController {
- private final CommandQueue.Callbacks mCallbacks = new CommandQueue.Callbacks() {
+ private final StatusBarStateController.StateListener mStatusBarStateListener =
+ new StatusBarStateController.StateListener() {
+ @Override
+ public void onDozingChanged(boolean isDozing) {
+ handleDozingChanged(isDozing);
+ }
+ };
+ private final OverviewProxyService.OverviewProxyListener mOverviewProxyListener =
+ new OverviewProxyService.OverviewProxyListener() {
@Override
- public void setWindowState(int displayId, int window, int state) {
- if (mNavBarDisplayId == displayId
- && window == StatusBarManager.WINDOW_NAVIGATION_BAR) {
- handleWindowStateChanged(state);
- }
+ public void onSystemUiStateChanged(int sysuiStateFlags) {
+ handleSystemUiStateChange(sysuiStateFlags);
}
};
+ private final StatusBarStateController mStatusBarStateController;
+ private final OverviewProxyService mOverviewProxyService;
- private CommandQueue mCommandQueue;
- private int mNavBarDisplayId;
- private boolean mIsNavBarWindowVisible;
+ private boolean mIsDozing;
+ private boolean mIsHomeHandleHiding;
@Nullable private AssistHandleCallbacks mAssistHandleCallbacks;
+ AssistHandleLikeHomeBehavior() {
+ mStatusBarStateController = Dependency.get(StatusBarStateController.class);
+ mOverviewProxyService = Dependency.get(OverviewProxyService.class);
+ }
+
@Override
public void onModeActivated(Context context, AssistHandleCallbacks callbacks) {
mAssistHandleCallbacks = callbacks;
- NavigationBarFragment navigationBarFragment =
- Dependency.get(NavigationBarController.class).getDefaultNavigationBarFragment();
- mNavBarDisplayId = navigationBarFragment.mDisplayId;
- mIsNavBarWindowVisible = navigationBarFragment.isNavBarWindowVisible();
- mCommandQueue = SysUiServiceProvider.getComponent(context, CommandQueue.class);
- mCommandQueue.addCallback(mCallbacks);
+ mIsDozing = mStatusBarStateController.isDozing();
+ mStatusBarStateController.addCallback(mStatusBarStateListener);
+ mOverviewProxyService.addCallback(mOverviewProxyListener);
callbackForCurrentState();
}
@Override
public void onModeDeactivated() {
mAssistHandleCallbacks = null;
- mCommandQueue.removeCallback(mCallbacks);
+ mOverviewProxyService.removeCallback(mOverviewProxyListener);
+ }
+
+ private static boolean isHomeHandleHiding(int sysuiStateFlags) {
+ return (sysuiStateFlags & QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN) != 0;
+ }
+
+ private void handleDozingChanged(boolean isDozing) {
+ if (mIsDozing == isDozing) {
+ return;
+ }
+
+ mIsDozing = isDozing;
+ callbackForCurrentState();
}
- private void handleWindowStateChanged(int state) {
- boolean newVisibility = state == StatusBarManager.WINDOW_STATE_SHOWING;
- if (mIsNavBarWindowVisible == newVisibility) {
+ private void handleSystemUiStateChange(int sysuiStateFlags) {
+ boolean isHomeHandleHiding = isHomeHandleHiding(sysuiStateFlags);
+ if (mIsHomeHandleHiding == isHomeHandleHiding) {
return;
}
- mIsNavBarWindowVisible = newVisibility;
+ mIsHomeHandleHiding = isHomeHandleHiding;
callbackForCurrentState();
}
@@ -83,10 +102,10 @@ final class AssistHandleLikeHomeBehavior implements BehaviorController {
return;
}
- if (mIsNavBarWindowVisible) {
- mAssistHandleCallbacks.showAndStay();
- } else {
+ if (mIsHomeHandleHiding || mIsDozing) {
mAssistHandleCallbacks.hide();
+ } else {
+ mAssistHandleCallbacks.showAndStay();
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleOffBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleOffBehavior.java
index ebf15ae8755c..f4130aeb1d08 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleOffBehavior.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleOffBehavior.java
@@ -27,9 +27,4 @@ final class AssistHandleOffBehavior implements BehaviorController {
public void onModeActivated(Context context, AssistHandleCallbacks callbacks) {
callbacks.hide();
}
-
- @Override
- public void onModeDeactivated() {
- // Do nothing
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
index 4a5e0e85107e..4b6a6dcee91d 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistHandleReminderExpBehavior.java
@@ -16,24 +16,27 @@
package com.android.systemui.assist;
+import android.app.ActivityManager;
import android.content.ComponentName;
import android.content.Context;
-import android.graphics.Rect;
-import android.view.View;
-import android.view.WindowManager;
+import android.os.SystemClock;
+import android.provider.DeviceConfig;
+import android.provider.Settings;
import androidx.annotation.Nullable;
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
import com.android.systemui.Dependency;
-import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.assist.AssistHandleBehaviorController.BehaviorController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.TaskStackChangeListener;
-import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.StatusBarState;
+import java.util.concurrent.TimeUnit;
+
/**
* Assistant handle behavior that hides the handles when the phone is dozing or in immersive mode,
* shows the handles when on lockscreen, and shows the handles temporarily when changing tasks or
@@ -41,6 +44,11 @@ import com.android.systemui.statusbar.StatusBarState;
*/
final class AssistHandleReminderExpBehavior implements BehaviorController {
+ private static final String LEARNING_TIME_ELAPSED_KEY = "reminder_exp_learning_time_elapsed";
+ private static final String LEARNING_EVENT_COUNT_KEY = "reminder_exp_learning_event_count";
+ private static final long DEFAULT_LEARNING_TIME_MS = TimeUnit.DAYS.toMillis(3);
+ private static final int DEFAULT_LEARNING_COUNT = 3;
+
private final StatusBarStateController.StateListener mStatusBarStateListener =
new StatusBarStateController.StateListener() {
@Override
@@ -65,66 +73,95 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
handleTaskStackTopChanged(taskId);
}
};
- private final CommandQueue.Callbacks mCallbacks = new CommandQueue.Callbacks() {
- @Override
- public void setSystemUiVisibility(int displayId, int vis,
- int fullscreenStackVis, int dockedStackVis, int mask,
- Rect fullscreenStackBounds, Rect dockedStackBounds,
- boolean navbarColorManagedByIme) {
- if (mStatusBarDisplayId == displayId) {
- handleSystemUiVisibilityChange(vis, mask);
- }
- }
- };
private final OverviewProxyService.OverviewProxyListener mOverviewProxyListener =
new OverviewProxyService.OverviewProxyListener() {
@Override
public void onOverviewShown(boolean fromHome) {
handleOverviewShown();
}
+
+ @Override
+ public void onSystemUiStateChanged(int sysuiStateFlags) {
+ handleSystemUiStateChanged(sysuiStateFlags);
+ }
};
- private StatusBarStateController mStatusBarStateController;
- private ActivityManagerWrapper mActivityManagerWrapper;
- private OverviewProxyService mOverviewProxyService;
- private int mStatusBarDisplayId;
- private CommandQueue mCommandQueue;
+ private final StatusBarStateController mStatusBarStateController;
+ private final ActivityManagerWrapper mActivityManagerWrapper;
+ private final OverviewProxyService mOverviewProxyService;
+
private boolean mOnLockscreen;
private boolean mIsDozing;
private int mRunningTaskId;
- private boolean mIsImmersive;
+ private boolean mIsNavBarHidden;
+ /** Whether user has learned the gesture. */
+ private boolean mIsLearned;
+ private long mLastLearningTimestamp;
+ /** Uptime while in this behavior. */
+ private long mLearningTimeElapsed;
+ /** Number of successful Assistant invocations while in this behavior. */
+ private int mLearningCount;
+
+ @Nullable private Context mContext;
@Nullable private AssistHandleCallbacks mAssistHandleCallbacks;
+ AssistHandleReminderExpBehavior() {
+ mStatusBarStateController = Dependency.get(StatusBarStateController.class);
+ mActivityManagerWrapper = ActivityManagerWrapper.getInstance();
+ mOverviewProxyService = Dependency.get(OverviewProxyService.class);
+ }
+
@Override
public void onModeActivated(Context context, AssistHandleCallbacks callbacks) {
+ mContext = context;
mAssistHandleCallbacks = callbacks;
- mStatusBarStateController = Dependency.get(StatusBarStateController.class);
mOnLockscreen = onLockscreen(mStatusBarStateController.getState());
mIsDozing = mStatusBarStateController.isDozing();
mStatusBarStateController.addCallback(mStatusBarStateListener);
- mActivityManagerWrapper = ActivityManagerWrapper.getInstance();
- mRunningTaskId = mActivityManagerWrapper.getRunningTask().taskId;
+ ActivityManager.RunningTaskInfo runningTaskInfo = mActivityManagerWrapper.getRunningTask();
+ mRunningTaskId = runningTaskInfo == null ? 0 : runningTaskInfo.taskId;
mActivityManagerWrapper.registerTaskStackListener(mTaskStackChangeListener);
- mStatusBarDisplayId =
- ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE))
- .getDefaultDisplay().getDisplayId();
- mCommandQueue = SysUiServiceProvider.getComponent(context, CommandQueue.class);
- mCommandQueue.addCallback(mCallbacks);
- mOverviewProxyService = Dependency.get(OverviewProxyService.class);
mOverviewProxyService.addCallback(mOverviewProxyListener);
- callbackForCurrentState();
+
+ mLearningTimeElapsed = Settings.Secure.getLong(
+ context.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, /* default = */ 0);
+ mLearningCount = Settings.Secure.getInt(
+ context.getContentResolver(), LEARNING_EVENT_COUNT_KEY, /* default = */ 0);
+ mLastLearningTimestamp = SystemClock.uptimeMillis();
+
+ callbackForCurrentState(/* justUnlocked = */ false);
}
@Override
public void onModeDeactivated() {
mAssistHandleCallbacks = null;
+ if (mContext != null) {
+ Settings.Secure.putLong(
+ mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, mLearningTimeElapsed);
+ Settings.Secure.putInt(
+ mContext.getContentResolver(), LEARNING_EVENT_COUNT_KEY, mLearningCount);
+ mContext = null;
+ }
mStatusBarStateController.removeCallback(mStatusBarStateListener);
mActivityManagerWrapper.unregisterTaskStackListener(mTaskStackChangeListener);
- mCommandQueue.removeCallback(mCallbacks);
mOverviewProxyService.removeCallback(mOverviewProxyListener);
}
+ @Override
+ public void onAssistantGesturePerformed() {
+ if (mContext == null) {
+ return;
+ }
+
+ Settings.Secure.putLong(
+ mContext.getContentResolver(), LEARNING_EVENT_COUNT_KEY, ++mLearningCount);
+ }
+
+ private static boolean isNavBarHidden(int sysuiStateFlags) {
+ return (sysuiStateFlags & QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN) != 0;
+ }
+
private void handleStatusBarStateChanged(int newState) {
boolean onLockscreen = onLockscreen(newState);
if (mOnLockscreen == onLockscreen) {
@@ -132,7 +169,7 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
}
mOnLockscreen = onLockscreen;
- callbackForCurrentState();
+ callbackForCurrentState(!onLockscreen);
}
private void handleDozingChanged(boolean isDozing) {
@@ -141,7 +178,7 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
}
mIsDozing = isDozing;
- callbackForCurrentState();
+ callbackForCurrentState(/* justUnlocked = */ false);
}
private void handleTaskStackTopChanged(int taskId) {
@@ -150,21 +187,21 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
}
mRunningTaskId = taskId;
- callbackForCurrentState();
+ callbackForCurrentState(/* justUnlocked = */ false);
}
- private void handleSystemUiVisibilityChange(int vis, int mask) {
- boolean isImmersive = isImmersive(vis, mask);
- if (mIsImmersive == isImmersive) {
+ private void handleSystemUiStateChanged(int sysuiStateFlags) {
+ boolean isNavBarHidden = isNavBarHidden(sysuiStateFlags);
+ if (mIsNavBarHidden == isNavBarHidden) {
return;
}
- mIsImmersive = isImmersive;
- callbackForCurrentState();
+ mIsNavBarHidden = isNavBarHidden;
+ callbackForCurrentState(/* justUnlocked = */ false);
}
private void handleOverviewShown() {
- callbackForCurrentState();
+ callbackForCurrentState(/* justUnlocked = */ false);
}
private boolean onLockscreen(int statusBarState) {
@@ -172,17 +209,34 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
|| statusBarState == StatusBarState.SHADE_LOCKED;
}
- private boolean isImmersive(int vis, int mask) {
- return ((vis & mask)
- & (View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)) != 0;
+ private void callbackForCurrentState(boolean justUnlocked) {
+ updateLearningStatus();
+
+ if (mIsLearned) {
+ callbackForLearnedState(justUnlocked);
+ } else {
+ callbackForUnlearnedState();
+ }
+ }
+
+ private void callbackForLearnedState(boolean justUnlocked) {
+ if (mAssistHandleCallbacks == null) {
+ return;
+ }
+
+ if (mIsDozing || mIsNavBarHidden || mOnLockscreen) {
+ mAssistHandleCallbacks.hide();
+ } else if (justUnlocked) {
+ mAssistHandleCallbacks.showAndGo();
+ }
}
- private void callbackForCurrentState() {
+ private void callbackForUnlearnedState() {
if (mAssistHandleCallbacks == null) {
return;
}
- if (mIsDozing || mIsImmersive) {
+ if (mIsDozing || mIsNavBarHidden) {
mAssistHandleCallbacks.hide();
} else if (mOnLockscreen) {
mAssistHandleCallbacks.showAndStay();
@@ -190,4 +244,33 @@ final class AssistHandleReminderExpBehavior implements BehaviorController {
mAssistHandleCallbacks.showAndGo();
}
}
+
+ private void updateLearningStatus() {
+ if (mContext == null) {
+ return;
+ }
+
+ long currentTimestamp = SystemClock.uptimeMillis();
+ mLearningTimeElapsed += currentTimestamp - mLastLearningTimestamp;
+ mLastLearningTimestamp = currentTimestamp;
+ Settings.Secure.putLong(
+ mContext.getContentResolver(), LEARNING_TIME_ELAPSED_KEY, mLearningTimeElapsed);
+
+ mIsLearned =
+ mLearningCount >= getLearningCount() || mLearningTimeElapsed >= getLearningTimeMs();
+ }
+
+ private long getLearningTimeMs() {
+ return DeviceConfig.getLong(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.ASSIST_HANDLES_LEARN_TIME_MS,
+ DEFAULT_LEARNING_TIME_MS);
+ }
+
+ private int getLearningCount() {
+ return DeviceConfig.getInt(
+ DeviceConfig.NAMESPACE_SYSTEMUI,
+ SystemUiDeviceConfigFlags.ASSIST_HANDLES_LEARN_COUNT,
+ DEFAULT_LEARNING_COUNT);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 2c38e513d7de..2fc79d618546 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -40,8 +40,11 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.settingslib.applications.InterestingConfigChanges;
import com.android.systemui.ConfigurationChangedReceiver;
+import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.assist.ui.DefaultUiController;
+import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -50,6 +53,40 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController;
*/
public class AssistManager implements ConfigurationChangedReceiver {
+ /**
+ * Controls the UI for showing Assistant invocation progress.
+ */
+ public interface UiController {
+ /**
+ * Updates the invocation progress.
+ *
+ * @param type one of INVOCATION_TYPE_GESTURE, INVOCATION_TYPE_ACTIVE_EDGE,
+ * INVOCATION_TYPE_VOICE, INVOCATION_TYPE_QUICK_SEARCH_BAR,
+ * INVOCATION_HOME_BUTTON_LONG_PRESS
+ * @param progress a float between 0 and 1 inclusive. 0 represents the beginning of the
+ * gesture; 1 represents the end.
+ */
+ void onInvocationProgress(int type, float progress);
+
+ /**
+ * Called when an invocation gesture completes.
+ *
+ * @param velocity the speed of the invocation gesture, in pixels per millisecond. For
+ * drags, this is 0.
+ */
+ void onGestureCompletion(float velocity);
+
+ /**
+ * Called with the Bundle from VoiceInteractionSessionListener.onSetUiHints.
+ */
+ void processBundle(Bundle hints);
+
+ /**
+ * Hides the UI.
+ */
+ void hide();
+ }
+
private static final String TAG = "AssistManager";
// Note that VERBOSE logging may leak PII (e.g. transcription contents).
@@ -76,6 +113,7 @@ public class AssistManager implements ConfigurationChangedReceiver {
private final InterestingConfigChanges mInterestingConfigChanges;
private final PhoneStateMonitor mPhoneStateMonitor;
private final AssistHandleBehaviorController mHandleController;
+ private final UiController mUiController;
private AssistOrbContainer mView;
private final DeviceProvisionedController mDeviceProvisionedController;
@@ -85,16 +123,16 @@ public class AssistManager implements ConfigurationChangedReceiver {
private IVoiceInteractionSessionShowCallback mShowCallback =
new IVoiceInteractionSessionShowCallback.Stub() {
- @Override
- public void onFailed() throws RemoteException {
- mView.post(mHideRunnable);
- }
+ @Override
+ public void onFailed() throws RemoteException {
+ mView.post(mHideRunnable);
+ }
- @Override
- public void onShown() throws RemoteException {
- mView.post(mHideRunnable);
- }
- };
+ @Override
+ public void onShown() throws RemoteException {
+ mView.post(mHideRunnable);
+ }
+ };
private Runnable mHideRunnable = new Runnable() {
@Override
@@ -111,7 +149,8 @@ public class AssistManager implements ConfigurationChangedReceiver {
mAssistUtils = new AssistUtils(context);
mAssistDisclosure = new AssistDisclosure(context, new Handler());
mPhoneStateMonitor = new PhoneStateMonitor(context);
- mHandleController = new AssistHandleBehaviorController(context, new Handler());
+ mHandleController =
+ new AssistHandleBehaviorController(context, mAssistUtils, new Handler());
registerVoiceInteractionSessionListener();
mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION
@@ -119,6 +158,23 @@ public class AssistManager implements ConfigurationChangedReceiver {
| ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS);
onConfigurationChanged(context.getResources().getConfiguration());
mShouldEnableOrb = !ActivityManager.isLowRamDeviceStatic();
+
+ mUiController = new DefaultUiController(mContext);
+
+ OverviewProxyService overviewProxy = Dependency.get(OverviewProxyService.class);
+ overviewProxy.addCallback(new OverviewProxyService.OverviewProxyListener() {
+ @Override
+ public void onAssistantProgress(float progress) {
+ // Progress goes from 0 to 1 to indicate how close the assist gesture is to
+ // completion.
+ onInvocationProgress(INVOCATION_TYPE_GESTURE, progress);
+ }
+
+ @Override
+ public void onAssistantGestureCompletion(float velocity) {
+ onGestureCompletion(velocity);
+ }
+ });
}
protected void registerVoiceInteractionSessionListener() {
@@ -191,26 +247,32 @@ public class AssistManager implements ConfigurationChangedReceiver {
if (args == null) {
args = new Bundle();
}
+ int invocationType = args.getInt(INVOCATION_TYPE_KEY, 0);
+ if (invocationType == INVOCATION_TYPE_GESTURE) {
+ mHandleController.onAssistantGesturePerformed();
+ }
args.putInt(INVOCATION_PHONE_STATE_KEY, mPhoneStateMonitor.getPhoneState());
args.putLong(INVOCATION_TIME_MS_KEY, SystemClock.uptimeMillis());
// Logs assistant start with invocation type.
MetricsLogger.action(
new LogMaker(MetricsEvent.ASSISTANT)
- .setType(MetricsEvent.TYPE_OPEN).setSubtype(args.getInt(INVOCATION_TYPE_KEY)));
+ .setType(MetricsEvent.TYPE_OPEN).setSubtype(
+ invocationType));
startAssistInternal(args, assistComponent, isService);
}
/** Called when the user is performing an assistant invocation action (e.g. Active Edge) */
public void onInvocationProgress(int type, float progress) {
- // intentional no-op, vendor's AssistManager implementation should override if needed.
+ mUiController.onInvocationProgress(type, progress);
}
- /** Called when the user has invoked the assistant with the incoming velocity, in pixels per
+ /**
+ * Called when the user has invoked the assistant with the incoming velocity, in pixels per
* millisecond. For invocations without a velocity (e.g. slow drag), the velocity is set to
* zero.
*/
- public void onAssistantGestureCompletion(float velocity) {
- // intentional no-op, vendor's AssistManager implementation should override if needed.
+ public void onGestureCompletion(float velocity) {
+ mUiController.onGestureCompletion(velocity);
}
public void hideAssist() {
@@ -264,7 +326,7 @@ public class AssistManager implements ConfigurationChangedReceiver {
Settings.Secure.ASSIST_STRUCTURE_ENABLED, 1, UserHandle.USER_CURRENT) != 0;
final SearchManager searchManager =
- (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
+ (SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE);
if (searchManager == null) {
return;
}
@@ -329,7 +391,7 @@ public class AssistManager implements ConfigurationChangedReceiver {
// Look for the search icon specified in the activity meta-data
Bundle metaData = isService
? packageManager.getServiceInfo(
- component, PackageManager.GET_META_DATA).metaData
+ component, PackageManager.GET_META_DATA).metaData
: packageManager.getActivityInfo(
component, PackageManager.GET_META_DATA).metaData;
if (metaData != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/CircularCornerPathRenderer.java b/packages/SystemUI/src/com/android/systemui/assist/ui/CircularCornerPathRenderer.java
new file mode 100644
index 000000000000..162e09e4d23d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/CircularCornerPathRenderer.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.assist.ui;
+
+import android.graphics.Path;
+
+/**
+ * Describes paths for circular rounded device corners.
+ */
+public final class CircularCornerPathRenderer extends CornerPathRenderer {
+
+ private final int mCornerRadiusBottom;
+ private final int mCornerRadiusTop;
+ private final int mHeight;
+ private final int mWidth;
+ private final Path mPath = new Path();
+
+ public CircularCornerPathRenderer(int cornerRadiusBottom, int cornerRadiusTop,
+ int width, int height) {
+ mCornerRadiusBottom = cornerRadiusBottom;
+ mCornerRadiusTop = cornerRadiusTop;
+ mHeight = height;
+ mWidth = width;
+ }
+
+ @Override // CornerPathRenderer
+ public Path getCornerPath(Corner corner) {
+ mPath.reset();
+ switch (corner) {
+ case BOTTOM_LEFT:
+ mPath.moveTo(0, mHeight - mCornerRadiusBottom);
+ mPath.arcTo(0, mHeight - mCornerRadiusBottom * 2, mCornerRadiusBottom * 2, mHeight,
+ 180, -90, true);
+ break;
+ case BOTTOM_RIGHT:
+ mPath.moveTo(mWidth - mCornerRadiusBottom, mHeight);
+ mPath.arcTo(mWidth - mCornerRadiusBottom * 2, mHeight - mCornerRadiusBottom * 2,
+ mWidth, mHeight, 90, -90, true);
+ break;
+ case TOP_RIGHT:
+ mPath.moveTo(mWidth, mCornerRadiusTop);
+ mPath.arcTo(mWidth - mCornerRadiusTop, 0, mWidth, mCornerRadiusTop, 0, -90, true);
+ break;
+ case TOP_LEFT:
+ mPath.moveTo(mCornerRadiusTop, 0);
+ mPath.arcTo(0, 0, mCornerRadiusTop, mCornerRadiusTop, 270, -90, true);
+ break;
+ }
+ return mPath;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/CornerPathRenderer.java b/packages/SystemUI/src/com/android/systemui/assist/ui/CornerPathRenderer.java
new file mode 100644
index 000000000000..2b40e6501fdd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/CornerPathRenderer.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.assist.ui;
+
+import android.graphics.Path;
+import android.graphics.PointF;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Handles paths along device corners.
+ */
+public abstract class CornerPathRenderer {
+
+ // The maximum delta between the corner curve and points approximating the corner curve.
+ private static final float ACCEPTABLE_ERROR = 0.1f;
+
+ /**
+ * For convenience, labels the four device corners.
+ *
+ * Corners must be listed in CCW order, otherwise we'll break rotation.
+ */
+ public enum Corner {
+ BOTTOM_LEFT,
+ BOTTOM_RIGHT,
+ TOP_RIGHT,
+ TOP_LEFT
+ }
+
+ /**
+ * Returns the path along the inside of a corner (centered insetAmountPx from the corner's
+ * edge).
+ */
+ public Path getInsetPath(Corner corner, float insetAmountPx) {
+ return approximateInnerPath(getCornerPath(corner), -insetAmountPx);
+ }
+
+ /**
+ * Returns the path of a corner (centered on the exact corner). Must be implemented by extending
+ * classes, based on the device-specific rounded corners. A default implementation for circular
+ * corners is provided by CircularCornerPathRenderer.
+ */
+ public abstract Path getCornerPath(Corner corner);
+
+ private Path approximateInnerPath(Path input, float delta) {
+ List<PointF> points = shiftBy(getApproximatePoints(input), delta);
+ return toPath(points);
+ }
+
+ private ArrayList<PointF> getApproximatePoints(Path path) {
+ float[] rawInput = path.approximate(ACCEPTABLE_ERROR);
+
+ ArrayList<PointF> output = new ArrayList<>();
+
+ for (int i = 0; i < rawInput.length; i = i + 3) {
+ output.add(new PointF(rawInput[i + 1], rawInput[i + 2]));
+ }
+
+ return output;
+ }
+
+ private ArrayList<PointF> shiftBy(ArrayList<PointF> input, float delta) {
+ ArrayList<PointF> output = new ArrayList<>();
+
+ for (int i = 0; i < input.size(); i++) {
+ PointF point = input.get(i);
+ PointF normal = normalAt(input, i);
+ PointF shifted =
+ new PointF(point.x + (normal.x * delta), point.y + (normal.y * delta));
+ output.add(shifted);
+ }
+ return output;
+ }
+
+ private Path toPath(List<PointF> points) {
+ Path path = new Path();
+ if (points.size() > 0) {
+ path.moveTo(points.get(0).x, points.get(0).y);
+ for (PointF point : points.subList(1, points.size())) {
+ path.lineTo(point.x, point.y);
+ }
+ }
+ return path;
+ }
+
+ private PointF normalAt(List<PointF> points, int index) {
+ PointF d1;
+ if (index == 0) {
+ d1 = new PointF(0, 0);
+ } else {
+ PointF point = points.get(index);
+ PointF previousPoint = points.get(index - 1);
+ d1 = new PointF((point.x - previousPoint.x), (point.y - previousPoint.y));
+ }
+
+ PointF d2;
+ if (index == (points.size() - 1)) {
+ d2 = new PointF(0, 0);
+ } else {
+ PointF point = points.get(index);
+ PointF nextPoint = points.get(index + 1);
+ d2 = new PointF((nextPoint.x - point.x), (nextPoint.y - point.y));
+ }
+
+ return rotate90Ccw(normalize(new PointF(d1.x + d2.x, d1.y + d2.y)));
+ }
+
+ private PointF rotate90Ccw(PointF input) {
+ return new PointF(-input.y, input.x);
+ }
+
+ private float magnitude(PointF point) {
+ return (float) Math.sqrt((point.x * point.x) + (point.y * point.y));
+ }
+
+ private PointF normalize(PointF point) {
+ float magnitude = magnitude(point);
+ if (magnitude == 0.f) {
+ return point;
+ }
+
+ float normal = 1 / magnitude;
+ return new PointF((point.x * normal), (point.y * normal));
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java b/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
new file mode 100644
index 000000000000..b1be811be9cf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/DefaultUiController.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.assist.ui;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ValueAnimator;
+import android.annotation.ColorInt;
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.metrics.LogMaker;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.WindowManager;
+import android.view.animation.PathInterpolator;
+import android.widget.FrameLayout;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.Dependency;
+import com.android.systemui.R;
+import com.android.systemui.ScreenDecorations;
+import com.android.systemui.SysUiServiceProvider;
+import com.android.systemui.assist.AssistManager;
+
+/**
+ * Default UiController implementation. Shows white edge lights along the bottom of the phone,
+ * expanding from the corners to meet in the center.
+ */
+public class DefaultUiController implements AssistManager.UiController {
+
+ private static final String TAG = "DefaultUiController";
+
+ private static final long ANIM_DURATION_MS = 200;
+
+ protected final FrameLayout mRoot;
+
+ private final WindowManager mWindowManager;
+ private final WindowManager.LayoutParams mLayoutParams;
+ private final PathInterpolator mProgressInterpolator = new PathInterpolator(.83f, 0, .84f, 1);
+
+ private boolean mAttached = false;
+ private boolean mInvocationInProgress = false;
+ private float mLastInvocationProgress = 0;
+
+ private ValueAnimator mInvocationAnimator = new ValueAnimator();
+ private InvocationLightsView mInvocationLightsView;
+
+ public DefaultUiController(Context context) {
+ mRoot = new FrameLayout(context);
+ mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+
+ mLayoutParams = new WindowManager.LayoutParams(
+ WindowManager.LayoutParams.MATCH_PARENT,
+ WindowManager.LayoutParams.WRAP_CONTENT, 0, 0,
+ WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL,
+ WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+ | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
+ | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+ | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
+ PixelFormat.TRANSLUCENT);
+ mLayoutParams.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
+ mLayoutParams.gravity = Gravity.BOTTOM;
+ mLayoutParams.setTitle("Assist");
+
+ mInvocationLightsView = (InvocationLightsView)
+ LayoutInflater.from(context).inflate(R.layout.invocation_lights, mRoot, false);
+ mRoot.addView(mInvocationLightsView);
+ }
+
+ @Override // AssistManager.UiController
+ public void processBundle(Bundle bundle) {
+ Log.e(TAG, "Bundle received but handling is not implemented; ignoring");
+ }
+
+ @Override // AssistManager.UiController
+ public void onInvocationProgress(int type, float progress) {
+ if (progress == 1) {
+ animateInvocationCompletion(type, 0);
+ } else if (progress == 0) {
+ hide();
+ } else {
+ if (!mInvocationInProgress) {
+ attach();
+ mInvocationInProgress = true;
+ updateAssistHandleVisibility();
+ }
+ setProgressInternal(type, progress);
+ }
+ mLastInvocationProgress = progress;
+
+ // Logs assistant invocation start.
+ if (!mInvocationInProgress && progress > 0.f) {
+ MetricsLogger.action(new LogMaker(MetricsEvent.ASSISTANT)
+ .setType(MetricsEvent.TYPE_ACTION));
+ }
+ // Logs assistant invocation cancelled.
+ if (mInvocationInProgress && progress == 0f) {
+ MetricsLogger.action(new LogMaker(MetricsEvent.ASSISTANT)
+ .setType(MetricsEvent.TYPE_DISMISS).setSubtype(0));
+ }
+ }
+
+ @Override // AssistManager.UiController
+ public void onGestureCompletion(float velocity) {
+ animateInvocationCompletion(AssistManager.INVOCATION_TYPE_GESTURE, velocity);
+ }
+
+ @Override // AssistManager.UiController
+ public void hide() {
+ Dependency.get(AssistManager.class).hideAssist();
+ detach();
+ if (mInvocationAnimator.isRunning()) {
+ mInvocationAnimator.cancel();
+ }
+ mInvocationLightsView.hide();
+ mInvocationInProgress = false;
+ updateAssistHandleVisibility();
+ }
+
+ /**
+ * Sets the colors of the four invocation lights, from left to right.
+ */
+ public void setInvocationColors(@ColorInt int color1, @ColorInt int color2,
+ @ColorInt int color3, @ColorInt int color4) {
+ mInvocationLightsView.setColors(color1, color2, color3, color4);
+ }
+
+ private void updateAssistHandleVisibility() {
+ ScreenDecorations decorations = SysUiServiceProvider.getComponent(mRoot.getContext(),
+ ScreenDecorations.class);
+ decorations.setAssistHintBlocked(mInvocationInProgress);
+ }
+
+ private void attach() {
+ if (!mAttached) {
+ mWindowManager.addView(mRoot, mLayoutParams);
+ mAttached = true;
+ }
+ }
+
+ private void detach() {
+ if (mAttached) {
+ mWindowManager.removeViewImmediate(mRoot);
+ mAttached = false;
+ }
+ }
+
+ private void setProgressInternal(int type, float progress) {
+ mInvocationLightsView.onInvocationProgress(
+ mProgressInterpolator.getInterpolation(progress));
+ }
+
+ private void animateInvocationCompletion(int type, float velocity) {
+ mInvocationAnimator = ValueAnimator.ofFloat(mLastInvocationProgress, 1);
+ mInvocationAnimator.setStartDelay(1);
+ mInvocationAnimator.setDuration(ANIM_DURATION_MS);
+ mInvocationAnimator.addUpdateListener(
+ animation -> setProgressInternal(type, (float) animation.getAnimatedValue()));
+ mInvocationAnimator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ super.onAnimationEnd(animation);
+ mInvocationInProgress = false;
+ mLastInvocationProgress = 0;
+ hide();
+ }
+ });
+ mInvocationAnimator.start();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/DisplayUtils.java b/packages/SystemUI/src/com/android/systemui/assist/ui/DisplayUtils.java
new file mode 100644
index 000000000000..251229f42da3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/DisplayUtils.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.assist.ui;
+
+import android.content.Context;
+import android.util.DisplayMetrics;
+import android.view.Display;
+import android.view.Surface;
+
+/**
+ * Utility class for determining screen and corner dimensions.
+ */
+public class DisplayUtils {
+ /**
+ * Converts given distance from dp to pixels.
+ */
+ public static int convertDpToPx(float dp, Context context) {
+ Display d = context.getDisplay();
+
+ DisplayMetrics dm = new DisplayMetrics();
+ d.getRealMetrics(dm);
+
+ return (int) Math.ceil(dp * dm.density);
+ }
+
+ /**
+ * The width of the display.
+ *
+ * - Not affected by rotation.
+ * - Includes system decor.
+ */
+ public static int getWidth(Context context) {
+ Display d = context.getDisplay();
+
+ DisplayMetrics dm = new DisplayMetrics();
+ d.getRealMetrics(dm);
+
+ int rotation = d.getRotation();
+ if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
+ return dm.widthPixels;
+ } else {
+ return dm.heightPixels;
+ }
+ }
+
+ /**
+ * The height of the display.
+ *
+ * - Not affected by rotation.
+ * - Includes system decor.
+ */
+ public static int getHeight(Context context) {
+ Display d = context.getDisplay();
+
+ DisplayMetrics dm = new DisplayMetrics();
+ d.getRealMetrics(dm);
+
+ int rotation = d.getRotation();
+ if (rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) {
+ return dm.heightPixels;
+ } else {
+ return dm.widthPixels;
+ }
+ }
+
+ /**
+ * Returns the radius of the bottom corners (the distance from the true corner to the point
+ * where the curve ends), in pixels.
+ */
+ public static int getCornerRadiusBottom(Context context) {
+ int radius = 0;
+
+ int resourceId = context.getResources().getIdentifier("rounded_corner_radius_bottom",
+ "dimen", "android");
+ if (resourceId > 0) {
+ radius = context.getResources().getDimensionPixelSize(resourceId);
+ }
+
+ if (radius == 0) {
+ radius = getCornerRadiusDefault(context);
+ }
+ return radius;
+ }
+
+ /**
+ * Returns the radius of the top corners (the distance from the true corner to the point where
+ * the curve ends), in pixels.
+ */
+ public static int getCornerRadiusTop(Context context) {
+ int radius = 0;
+
+ int resourceId = context.getResources().getIdentifier("rounded_corner_radius_top",
+ "dimen", "android");
+ if (resourceId > 0) {
+ radius = context.getResources().getDimensionPixelSize(resourceId);
+ }
+
+ if (radius == 0) {
+ radius = getCornerRadiusDefault(context);
+ }
+ return radius;
+ }
+
+ private static int getCornerRadiusDefault(Context context) {
+ int radius = 0;
+
+ int resourceId = context.getResources().getIdentifier("rounded_corner_radius", "dimen",
+ "android");
+ if (resourceId > 0) {
+ radius = context.getResources().getDimensionPixelSize(resourceId);
+ }
+ return radius;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/EdgeLight.java b/packages/SystemUI/src/com/android/systemui/assist/ui/EdgeLight.java
new file mode 100644
index 000000000000..9ae02c5e3104
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/EdgeLight.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.assist.ui;
+
+import androidx.annotation.ColorInt;
+
+/**
+ * Represents a line drawn on the perimeter of the display.
+ *
+ * Offsets and lengths are both normalized to the perimeter of the display – ex. a length of 1
+ * is equal to the perimeter of the display. Positions move counter-clockwise as values increase.
+ *
+ * If there is no bottom corner radius, the origin is the bottom-left corner.
+ * If there is a bottom corner radius, the origin is immediately after the bottom corner radius,
+ * counter-clockwise.
+ */
+public final class EdgeLight {
+ @ColorInt
+ private int mColor;
+ private float mOffset;
+ private float mLength;
+
+ /** Copies a list of EdgeLights. */
+ public static EdgeLight[] copy(EdgeLight[] array) {
+ EdgeLight[] copy = new EdgeLight[array.length];
+ for (int i = 0; i < array.length; i++) {
+ copy[i] = new EdgeLight(array[i]);
+ }
+ return copy;
+ }
+
+ public EdgeLight(@ColorInt int color, float offset, float length) {
+ mColor = color;
+ mOffset = offset;
+ mLength = length;
+ }
+
+ public EdgeLight(EdgeLight sourceLight) {
+ mColor = sourceLight.getColor();
+ mOffset = sourceLight.getOffset();
+ mLength = sourceLight.getLength();
+ }
+
+ /** Returns the current edge light color. */
+ @ColorInt
+ public int getColor() {
+ return mColor;
+ }
+
+ /** Sets the edge light color. */
+ public void setColor(@ColorInt int color) {
+ mColor = color;
+ }
+
+ /** Returns the edge light length, in units of the total device perimeter. */
+ public float getLength() {
+ return mLength;
+ }
+
+ /** Sets the edge light length, in units of the total device perimeter. */
+ public void setLength(float length) {
+ mLength = length;
+ }
+
+ /**
+ * Returns the current offset, in units of the total device perimeter and measured from the
+ * bottom-left corner (see class description).
+ */
+ public float getOffset() {
+ return mOffset;
+ }
+
+ /**
+ * Sets the current offset, in units of the total device perimeter and measured from the
+ * bottom-left corner (see class description).
+ */
+ public void setOffset(float offset) {
+ mOffset = offset;
+ }
+
+ /** Returns the center, measured from the bottom-left corner (see class description). */
+ public float getCenter() {
+ return mOffset + (mLength / 2.f);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java b/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
new file mode 100644
index 000000000000..de1d7c8c0a04
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.assist.ui;
+
+import android.annotation.ColorInt;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.MathUtils;
+import android.view.View;
+
+import com.android.systemui.R;
+
+import java.util.ArrayList;
+
+/**
+ * Shows lights at the bottom of the phone, marking the invocation progress.
+ */
+public class InvocationLightsView extends View {
+
+ private static final String TAG = "InvocationLightsView";
+
+ private static final int LIGHT_HEIGHT_DP = 3;
+ // minimum light length as a fraction of the corner length
+ private static final float MINIMUM_CORNER_RATIO = .6f;
+
+ protected final ArrayList<EdgeLight> mAssistInvocationLights = new ArrayList<>();
+ protected final PerimeterPathGuide mGuide;
+
+ private final Paint mPaint = new Paint();
+ // Path used to render lights. One instance is used to draw all lights and is cached to avoid
+ // allocation on each frame.
+ private final Path mPath = new Path();
+ private final int mViewHeight;
+
+ // Allocate variable for screen location lookup to avoid memory alloc onDraw()
+ private int[] mScreenLocation = new int[2];
+
+ public InvocationLightsView(Context context) {
+ this(context, null);
+ }
+
+ public InvocationLightsView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public InvocationLightsView(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public InvocationLightsView(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+
+ int strokeWidth = DisplayUtils.convertDpToPx(LIGHT_HEIGHT_DP, context);
+ mPaint.setStrokeWidth(strokeWidth);
+ mPaint.setStyle(Paint.Style.STROKE);
+ mPaint.setStrokeJoin(Paint.Join.MITER);
+ mPaint.setAntiAlias(true);
+
+ int cornerRadiusBottom = DisplayUtils.getCornerRadiusBottom(context);
+ int cornerRadiusTop = DisplayUtils.getCornerRadiusTop(context);
+ int displayWidth = DisplayUtils.getWidth(context);
+ int displayHeight = DisplayUtils.getHeight(context);
+ CircularCornerPathRenderer cornerPathRenderer = new CircularCornerPathRenderer(
+ cornerRadiusBottom, cornerRadiusTop, displayWidth, displayHeight);
+ mGuide = new PerimeterPathGuide(context, cornerPathRenderer,
+ strokeWidth / 2, displayWidth, displayHeight);
+
+ mViewHeight = Math.max(cornerRadiusBottom, cornerRadiusTop);
+
+ @ColorInt int lightColor = getResources().getColor(R.color.default_invocation_lights_color);
+ for (int i = 0; i < 4; i++) {
+ mAssistInvocationLights.add(new EdgeLight(lightColor, 0, 0));
+ }
+ }
+
+ /**
+ * Updates positions of the invocation lights based on the progress (a float between 0 and 1).
+ * The lights begin at the device corners and expand inward until they meet at the center.
+ */
+ public void onInvocationProgress(float progress) {
+ if (progress == 0) {
+ setVisibility(View.GONE);
+ } else {
+ float cornerLengthNormalized =
+ mGuide.getRegionWidth(PerimeterPathGuide.Region.BOTTOM_LEFT);
+ float arcLengthNormalized = cornerLengthNormalized * MINIMUM_CORNER_RATIO;
+ float arcOffsetNormalized = (cornerLengthNormalized - arcLengthNormalized) / 2f;
+
+ float minLightLength = arcLengthNormalized / 2;
+ float maxLightLength = mGuide.getRegionWidth(PerimeterPathGuide.Region.BOTTOM) / 4f;
+
+ float lightLength = MathUtils.lerp(minLightLength, maxLightLength, progress);
+
+ float leftStart = (-cornerLengthNormalized + arcOffsetNormalized) * (1 - progress);
+ float rightStart = mGuide.getRegionWidth(PerimeterPathGuide.Region.BOTTOM)
+ + (cornerLengthNormalized - arcOffsetNormalized) * (1 - progress);
+
+ setLight(0, leftStart, lightLength);
+ setLight(1, leftStart + lightLength, lightLength);
+ setLight(2, rightStart - (lightLength * 2), lightLength);
+ setLight(3, rightStart - lightLength, lightLength);
+ setVisibility(View.VISIBLE);
+ }
+ invalidate();
+ }
+
+ /**
+ * Hides and resets the invocation lights.
+ */
+ public void hide() {
+ setVisibility(GONE);
+ for (EdgeLight light : mAssistInvocationLights) {
+ light.setLength(0);
+ }
+ }
+
+ /**
+ * Sets the invocation light colors, from left to right.
+ */
+ public void setColors(@ColorInt int color1, @ColorInt int color2,
+ @ColorInt int color3, @ColorInt int color4) {
+ mAssistInvocationLights.get(0).setColor(color1);
+ mAssistInvocationLights.get(1).setColor(color2);
+ mAssistInvocationLights.get(2).setColor(color3);
+ mAssistInvocationLights.get(3).setColor(color4);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ getLayoutParams().height = mViewHeight;
+ requestLayout();
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+
+ int rotation = getContext().getDisplay().getRotation();
+ mGuide.setRotation(rotation);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ // If the view doesn't take up the whole screen, offset the canvas by its translation
+ // distance such that PerimeterPathGuide's paths are drawn properly based upon the actual
+ // screen edges.
+ getLocationOnScreen(mScreenLocation);
+ canvas.translate(-mScreenLocation[0], -mScreenLocation[1]);
+
+ // if the lights are different colors, the inner ones need to be drawn last and with a
+ // square cap so that the join between lights is straight
+ mPaint.setStrokeCap(Paint.Cap.ROUND);
+ renderLight(mAssistInvocationLights.get(0), canvas);
+ renderLight(mAssistInvocationLights.get(3), canvas);
+
+ mPaint.setStrokeCap(Paint.Cap.SQUARE);
+ renderLight(mAssistInvocationLights.get(1), canvas);
+ renderLight(mAssistInvocationLights.get(2), canvas);
+ }
+
+ protected void setLight(int index, float offset, float length) {
+ if (index < 0 || index >= 4) {
+ Log.w(TAG, "invalid invocation light index: " + index);
+ }
+ mAssistInvocationLights.get(index).setOffset(offset);
+ mAssistInvocationLights.get(index).setLength(length);
+ }
+
+ private void renderLight(EdgeLight light, Canvas canvas) {
+ mGuide.strokeSegment(mPath, light.getOffset(), light.getOffset() + light.getLength());
+ mPaint.setColor(light.getColor());
+ canvas.drawPath(mPath, mPaint);
+ }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/PerimeterPathGuide.java b/packages/SystemUI/src/com/android/systemui/assist/ui/PerimeterPathGuide.java
new file mode 100644
index 000000000000..8eea36892aa7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/PerimeterPathGuide.java
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.assist.ui;
+
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_180;
+import static android.view.Surface.ROTATION_270;
+import static android.view.Surface.ROTATION_90;
+
+import android.content.Context;
+import android.graphics.Matrix;
+import android.graphics.Path;
+import android.graphics.PathMeasure;
+import android.util.Log;
+import android.util.Pair;
+import android.view.Surface;
+
+import androidx.core.math.MathUtils;
+
+/**
+ * PerimeterPathGuide establishes a coordinate system for drawing paths along the perimeter of the
+ * screen. All positions around the perimeter have a coordinate [0, 1). The origin is the bottom
+ * left corner of the screen, to the right of the curved corner, if any. Coordinates increase
+ * counter-clockwise around the screen.
+ *
+ * Non-square screens require PerimeterPathGuide to be notified when the rotation changes, such that
+ * it can recompute the edge lengths for the coordinate system.
+ */
+public class PerimeterPathGuide {
+
+ private static final String TAG = "PerimeterPathGuide";
+
+ /**
+ * For convenience, labels sections of the device perimeter.
+ *
+ * Must be listed in CCW order.
+ */
+ public enum Region {
+ BOTTOM,
+ BOTTOM_RIGHT,
+ RIGHT,
+ TOP_RIGHT,
+ TOP,
+ TOP_LEFT,
+ LEFT,
+ BOTTOM_LEFT
+ }
+
+ private final int mDeviceWidthPx;
+ private final int mDeviceHeightPx;
+ private final int mTopCornerRadiusPx;
+ private final int mBottomCornerRadiusPx;
+
+ private class RegionAttributes {
+ public float absoluteLength;
+ public float normalizedLength;
+ public float endCoordinate;
+ public Path path;
+ }
+
+ // Allocate a Path and PathMeasure for use by intermediate operations that would otherwise have
+ // to allocate. reset() must be called before using this path, this ensures state from previous
+ // operations is cleared.
+ private final Path mScratchPath = new Path();
+ private final CornerPathRenderer mCornerPathRenderer;
+ private final PathMeasure mScratchPathMeasure = new PathMeasure(mScratchPath, false);
+ private RegionAttributes[] mRegions;
+ private final int mEdgeInset;
+ private int mRotation = ROTATION_0;
+
+ public PerimeterPathGuide(Context context, CornerPathRenderer cornerPathRenderer,
+ int edgeInset, int screenWidth, int screenHeight) {
+ mCornerPathRenderer = cornerPathRenderer;
+ mDeviceWidthPx = screenWidth;
+ mDeviceHeightPx = screenHeight;
+ mTopCornerRadiusPx = DisplayUtils.getCornerRadiusTop(context);
+ mBottomCornerRadiusPx = DisplayUtils.getCornerRadiusBottom(context);
+ mEdgeInset = edgeInset;
+
+ mRegions = new RegionAttributes[8];
+ for (int i = 0; i < mRegions.length; i++) {
+ mRegions[i] = new RegionAttributes();
+ }
+ computeRegions();
+ }
+
+ /**
+ * Sets the rotation.
+ *
+ * @param rotation one of Surface.ROTATION_0, Surface.ROTATION_90, Surface.ROTATION_180,
+ * Surface.ROTATION_270
+ */
+ public void setRotation(int rotation) {
+ if (rotation != mRotation) {
+ switch (rotation) {
+ case ROTATION_0:
+ case ROTATION_90:
+ case ROTATION_180:
+ case ROTATION_270:
+ mRotation = rotation;
+ computeRegions();
+ break;
+ default:
+ Log.e(TAG, "Invalid rotation provided: " + rotation);
+ }
+ }
+ }
+
+ /**
+ * Sets path to the section of the perimeter between startCoord and endCoord (measured
+ * counter-clockwise from the bottom left).
+ */
+ public void strokeSegment(Path path, float startCoord, float endCoord) {
+ path.reset();
+
+ startCoord = ((startCoord % 1) + 1) % 1; // Wrap to the range [0, 1).
+ endCoord = ((endCoord % 1) + 1) % 1; // Wrap to the range [0, 1).
+ boolean outOfOrder = startCoord > endCoord;
+
+ if (outOfOrder) {
+ strokeSegmentInternal(path, startCoord, 1f);
+ startCoord = 0;
+ }
+ strokeSegmentInternal(path, startCoord, endCoord);
+ }
+
+ /**
+ * Returns the device perimeter in pixels.
+ */
+ public float getPerimeterPx() {
+ float total = 0;
+ for (RegionAttributes region : mRegions) {
+ total += region.absoluteLength;
+ }
+ return total;
+ }
+
+ /**
+ * Returns the bottom corner radius in pixels.
+ */
+ public float getBottomCornerRadiusPx() {
+ return mBottomCornerRadiusPx;
+ }
+
+ /**
+ * Given a region and a progress value [0,1] indicating the counter-clockwise progress within
+ * that region, compute the global [0,1) coordinate.
+ */
+ public float getCoord(Region region, float progress) {
+ RegionAttributes regionAttributes = mRegions[region.ordinal()];
+ progress = MathUtils.clamp(progress, 0, 1);
+ return regionAttributes.endCoordinate - (1 - progress) * regionAttributes.normalizedLength;
+ }
+
+ /**
+ * Returns the center of the provided region, relative to the entire perimeter.
+ */
+ public float getRegionCenter(Region region) {
+ return getCoord(region, 0.5f);
+ }
+
+ /**
+ * Returns the width of the provided region, in units relative to the entire perimeter.
+ */
+ public float getRegionWidth(Region region) {
+ return mRegions[region.ordinal()].normalizedLength;
+ }
+
+ /**
+ * Points are expressed in terms of their relative position on the perimeter of the display,
+ * moving counter-clockwise. This method converts a point to clockwise, assisting use cases
+ * such as animating to a point clockwise instead of counter-clockwise.
+ *
+ * @param point A point in the range from 0 to 1.
+ * @return A point in the range of -1 to 0 that represents the same location as {@code point}.
+ */
+ public static float makeClockwise(float point) {
+ return point - 1;
+ }
+
+ private int getPhysicalCornerRadius(CircularCornerPathRenderer.Corner corner) {
+ if (corner == CircularCornerPathRenderer.Corner.BOTTOM_LEFT
+ || corner == CircularCornerPathRenderer.Corner.BOTTOM_RIGHT) {
+ return mBottomCornerRadiusPx;
+ }
+ return mTopCornerRadiusPx;
+ }
+
+ // Populate mRegions based upon the current rotation value.
+ private void computeRegions() {
+ int screenWidth = mDeviceWidthPx;
+ int screenHeight = mDeviceHeightPx;
+
+ int rotateMatrix = 0;
+
+ switch (mRotation) {
+ case ROTATION_90:
+ rotateMatrix = -90;
+ break;
+ case ROTATION_180:
+ rotateMatrix = -180;
+ break;
+ case Surface.ROTATION_270:
+ rotateMatrix = -270;
+ break;
+ }
+
+ Matrix matrix = new Matrix();
+ matrix.postRotate(rotateMatrix, mDeviceWidthPx / 2, mDeviceHeightPx / 2);
+
+ if (mRotation == ROTATION_90 || mRotation == Surface.ROTATION_270) {
+ screenHeight = mDeviceWidthPx;
+ screenWidth = mDeviceHeightPx;
+ matrix.postTranslate((mDeviceHeightPx
+ - mDeviceWidthPx) / 2, (mDeviceWidthPx - mDeviceHeightPx) / 2);
+ }
+
+ CircularCornerPathRenderer.Corner screenBottomLeft = getRotatedCorner(
+ CircularCornerPathRenderer.Corner.BOTTOM_LEFT);
+ CircularCornerPathRenderer.Corner screenBottomRight = getRotatedCorner(
+ CircularCornerPathRenderer.Corner.BOTTOM_RIGHT);
+ CircularCornerPathRenderer.Corner screenTopLeft = getRotatedCorner(
+ CircularCornerPathRenderer.Corner.TOP_LEFT);
+ CircularCornerPathRenderer.Corner screenTopRight = getRotatedCorner(
+ CircularCornerPathRenderer.Corner.TOP_RIGHT);
+
+ mRegions[Region.BOTTOM_LEFT.ordinal()].path =
+ mCornerPathRenderer.getInsetPath(screenBottomLeft, mEdgeInset);
+ mRegions[Region.BOTTOM_RIGHT.ordinal()].path =
+ mCornerPathRenderer.getInsetPath(screenBottomRight, mEdgeInset);
+ mRegions[Region.TOP_RIGHT.ordinal()].path =
+ mCornerPathRenderer.getInsetPath(screenTopRight, mEdgeInset);
+ mRegions[Region.TOP_LEFT.ordinal()].path =
+ mCornerPathRenderer.getInsetPath(screenTopLeft, mEdgeInset);
+
+ mRegions[Region.BOTTOM_LEFT.ordinal()].path.transform(matrix);
+ mRegions[Region.BOTTOM_RIGHT.ordinal()].path.transform(matrix);
+ mRegions[Region.TOP_RIGHT.ordinal()].path.transform(matrix);
+ mRegions[Region.TOP_LEFT.ordinal()].path.transform(matrix);
+
+
+ Path bottomPath = new Path();
+ bottomPath.moveTo(getPhysicalCornerRadius(screenBottomLeft), screenHeight - mEdgeInset);
+ bottomPath.lineTo(screenWidth - getPhysicalCornerRadius(screenBottomRight),
+ screenHeight - mEdgeInset);
+ mRegions[Region.BOTTOM.ordinal()].path = bottomPath;
+
+ Path topPath = new Path();
+ topPath.moveTo(screenWidth - getPhysicalCornerRadius(screenTopRight), mEdgeInset);
+ topPath.lineTo(getPhysicalCornerRadius(screenTopLeft), mEdgeInset);
+ mRegions[Region.TOP.ordinal()].path = topPath;
+
+ Path rightPath = new Path();
+ rightPath.moveTo(screenWidth - mEdgeInset,
+ screenHeight - getPhysicalCornerRadius(screenBottomRight));
+ rightPath.lineTo(screenWidth - mEdgeInset, getPhysicalCornerRadius(screenTopRight));
+ mRegions[Region.RIGHT.ordinal()].path = rightPath;
+
+ Path leftPath = new Path();
+ leftPath.moveTo(mEdgeInset,
+ getPhysicalCornerRadius(screenTopLeft));
+ leftPath.lineTo(mEdgeInset, screenHeight - getPhysicalCornerRadius(screenBottomLeft));
+ mRegions[Region.LEFT.ordinal()].path = leftPath;
+
+ float perimeterLength = 0;
+ PathMeasure pathMeasure = new PathMeasure();
+ for (int i = 0; i < mRegions.length; i++) {
+ pathMeasure.setPath(mRegions[i].path, false);
+ mRegions[i].absoluteLength = pathMeasure.getLength();
+ perimeterLength += mRegions[i].absoluteLength;
+ }
+
+ float accum = 0;
+ for (int i = 0; i < mRegions.length; i++) {
+ mRegions[i].normalizedLength = mRegions[i].absoluteLength / perimeterLength;
+ accum += mRegions[i].normalizedLength;
+ mRegions[i].endCoordinate = accum;
+ }
+ }
+
+ private CircularCornerPathRenderer.Corner getRotatedCorner(
+ CircularCornerPathRenderer.Corner screenCorner) {
+ int corner = screenCorner.ordinal();
+ switch (mRotation) {
+ case ROTATION_90:
+ corner += 3;
+ break;
+ case ROTATION_180:
+ corner += 2;
+ break;
+ case Surface.ROTATION_270:
+ corner += 1;
+ break;
+ }
+ return CircularCornerPathRenderer.Corner.values()[corner % 4];
+ }
+
+ private void strokeSegmentInternal(Path path, float startCoord, float endCoord) {
+ Pair<Region, Float> startPoint = placePoint(startCoord);
+ Pair<Region, Float> endPoint = placePoint(endCoord);
+
+ if (startPoint.first.equals(endPoint.first)) {
+ strokeRegion(path, startPoint.first, startPoint.second, endPoint.second);
+ } else {
+ strokeRegion(path, startPoint.first, startPoint.second, 1f);
+ boolean hitStart = false;
+ for (Region r : Region.values()) {
+ if (r.equals(startPoint.first)) {
+ hitStart = true;
+ continue;
+ }
+ if (hitStart) {
+ if (!r.equals(endPoint.first)) {
+ strokeRegion(path, r, 0f, 1f);
+ } else {
+ strokeRegion(path, r, 0f, endPoint.second);
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ private void strokeRegion(Path path, Region r, float relativeStart, float relativeEnd) {
+ if (relativeStart == relativeEnd) {
+ return;
+ }
+
+ mScratchPathMeasure.setPath(mRegions[r.ordinal()].path, false);
+ mScratchPathMeasure.getSegment(relativeStart * mScratchPathMeasure.getLength(),
+ relativeEnd * mScratchPathMeasure.getLength(), path, true);
+ }
+
+ /**
+ * Return the Region where the point is located, and its relative position within that region
+ * (from 0 to 1).
+ * Note that we move counterclockwise around the perimeter; for example, a relative position of
+ * 0 in
+ * the BOTTOM region is on the left side of the screen, but in the TOP region it’s on the
+ * right.
+ */
+ private Pair<Region, Float> placePoint(float coord) {
+ if (0 > coord || coord > 1) {
+ coord = ((coord % 1) + 1)
+ % 1; // Wrap to the range [0, 1). Inputs of exactly 1 are preserved.
+ }
+
+ Region r = getRegionForPoint(coord);
+ if (r.equals(Region.BOTTOM)) {
+ return Pair.create(r, coord / mRegions[r.ordinal()].normalizedLength);
+ } else {
+ float coordOffsetInRegion = coord - mRegions[r.ordinal() - 1].endCoordinate;
+ float coordRelativeToRegion =
+ coordOffsetInRegion / mRegions[r.ordinal()].normalizedLength;
+ return Pair.create(r, coordRelativeToRegion);
+ }
+ }
+
+ private Region getRegionForPoint(float coord) {
+ // If coord is outside of [0,1], wrap to [0,1).
+ if (coord < 0 || coord > 1) {
+ coord = ((coord % 1) + 1) % 1;
+ }
+
+ for (Region region : Region.values()) {
+ if (coord <= mRegions[region.ordinal()].endCoordinate) {
+ return region;
+ }
+ }
+
+ // Should never happen.
+ Log.e(TAG, "Fell out of getRegionForPoint");
+ return Region.BOTTOM;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 6cfbb2232b66..a23c99ef01fe 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -16,6 +16,7 @@
package com.android.systemui.bubbles;
+import static android.app.Notification.FLAG_BUBBLE;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
@@ -40,8 +41,6 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
-import android.app.ActivityTaskManager;
-import android.app.IActivityTaskManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -53,6 +52,7 @@ import android.graphics.Rect;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Settings;
+import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
import android.service.notification.ZenModeConfig;
import android.util.Log;
@@ -138,7 +138,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
private final Context mContext;
private final NotificationEntryManager mNotificationEntryManager;
- private final IActivityTaskManager mActivityTaskManager;
private final BubbleTaskStackListener mTaskStackListener;
private BubbleStateChangeListener mStateChangeListener;
private BubbleExpandListener mExpandListener;
@@ -250,7 +249,6 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
mStatusBarStateListener = new StatusBarStateListener();
Dependency.get(StatusBarStateController.class).addCallback(mStatusBarStateListener);
- mActivityTaskManager = ActivityTaskManager.getService();
mTaskStackListener = new BubbleTaskStackListener();
ActivityManagerWrapper.getInstance().registerTaskStackListener(mTaskStackListener);
@@ -509,6 +507,12 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
updateBubble(entry);
}
}
+
+ @Override
+ public void onNotificationRankingUpdated(RankingMap rankingMap) {
+ // Forward to BubbleData to block any bubbles which should no longer be shown
+ mBubbleData.notificationRankingUpdated(rankingMap);
+ }
};
@SuppressWarnings("FieldCanBeLocal")
@@ -547,8 +551,11 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
mNotificationEntryManager.performRemoveNotification(bubble.entry.notification,
UNDEFINED_DISMISS_REASON);
} else {
- // The notification is still in the shade but we've removed the bubble so
- // lets make sure NoMan knows it's not a bubble anymore
+ // Update the flag for SysUI
+ bubble.entry.notification.getNotification().flags &= ~FLAG_BUBBLE;
+
+ // Make sure NoMan knows it's not a bubble anymore so anyone querying it will
+ // get right result back
try {
mBarService.onNotificationBubbleChanged(bubble.getKey(),
false /* isBubble */);
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
index 6ab973eb3065..5575b35a12ae 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
@@ -22,6 +22,8 @@ import static java.util.stream.Collectors.toList;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.Context;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.NotificationListenerService.RankingMap;
import android.util.Log;
import android.util.Pair;
@@ -114,6 +116,8 @@ public class BubbleData {
// State tracked during an operation -- keeps track of what listener events to dispatch.
private Update mStateChange;
+ private NotificationListenerService.Ranking mTmpRanking;
+
private TimeSource mTimeSource = System::currentTimeMillis;
@Nullable
@@ -193,6 +197,31 @@ public class BubbleData {
dispatchPendingChanges();
}
+ /**
+ * Called when NotificationListener has received adjusted notification rank and reapplied
+ * filtering and sorting. This is used to dismiss any bubbles which should no longer be shown
+ * due to changes in permissions on the notification channel or the global setting.
+ *
+ * @param rankingMap the updated ranking map from NotificationListenerService
+ */
+ public void notificationRankingUpdated(RankingMap rankingMap) {
+ if (mTmpRanking == null) {
+ mTmpRanking = new NotificationListenerService.Ranking();
+ }
+
+ String[] orderedKeys = rankingMap.getOrderedKeys();
+ for (int i = 0; i < orderedKeys.length; i++) {
+ String key = orderedKeys[i];
+ if (hasBubbleWithKey(key)) {
+ rankingMap.getRanking(key, mTmpRanking);
+ if (!mTmpRanking.canBubble()) {
+ doRemove(key, BubbleController.DISMISS_BLOCKED);
+ }
+ }
+ }
+ dispatchPendingChanges();
+ }
+
private void doAdd(Bubble bubble) {
if (DEBUG) {
Log.d(TAG, "doAdd: " + bubble);
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index b61fa6f2deb6..f87bcef5fde2 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -330,9 +330,7 @@ public class BubbleStackView extends FrameLayout {
mSurfaceSynchronizer = synchronizer != null ? synchronizer : DEFAULT_SURFACE_SYNCHRONIZER;
mBubbleContainer = new PhysicsAnimationLayout(context);
- mBubbleContainer.setMaxRenderedChildren(
- getResources().getInteger(R.integer.bubbles_max_rendered));
- mBubbleContainer.setController(mStackAnimationController);
+ mBubbleContainer.setActiveController(mStackAnimationController);
mBubbleContainer.setElevation(elevation);
mBubbleContainer.setClipChildren(false);
addView(mBubbleContainer, new FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT));
@@ -728,11 +726,10 @@ public class BubbleStackView extends FrameLayout {
public void updateBubbleOrder(List<Bubble> bubbles) {
for (int i = 0; i < bubbles.size(); i++) {
Bubble bubble = bubbles.get(i);
- mBubbleContainer.moveViewTo(bubble.iconView, i);
+ mBubbleContainer.reorderView(bubble.iconView, i);
}
}
-
/**
* Changes the currently selected bubble. If the stack is already expanded, the newly selected
* bubble will be shown immediately. This does not change the expanded state or change the
@@ -921,19 +918,17 @@ public class BubbleStackView extends FrameLayout {
};
if (shouldExpand) {
- mBubbleContainer.setController(mExpandedAnimationController);
- mExpandedAnimationController.expandFromStack(
- mStackAnimationController.getStackPositionAlongNearestHorizontalEdge()
- /* collapseTo */,
- () -> {
- updatePointerPosition();
- updateAfter.run();
- } /* after */);
+ mBubbleContainer.setActiveController(mExpandedAnimationController);
+ mExpandedAnimationController.expandFromStack(() -> {
+ updatePointerPosition();
+ updateAfter.run();
+ } /* after */);
} else {
mBubbleContainer.cancelAllAnimations();
mExpandedAnimationController.collapseBackToStack(
+ mStackAnimationController.getStackPositionAlongNearestHorizontalEdge(),
() -> {
- mBubbleContainer.setController(mStackAnimationController);
+ mBubbleContainer.setActiveController(mStackAnimationController);
updateAfter.run();
});
}
@@ -1022,7 +1017,7 @@ public class BubbleStackView extends FrameLayout {
}
mStackAnimationController.cancelStackPositionAnimations();
- mBubbleContainer.setController(mStackAnimationController);
+ mBubbleContainer.setActiveController(mStackAnimationController);
hideFlyoutImmediate();
mDraggingInDismissTarget = false;
@@ -1120,6 +1115,10 @@ public class BubbleStackView extends FrameLayout {
/** Called when a gesture is completed or cancelled. */
void onGestureFinished() {
mIsGestureInProgress = false;
+
+ if (mIsExpanded) {
+ mExpandedAnimationController.onGestureFinished();
+ }
}
/** Prepares and starts the desaturate/darken animation on the bubble stack. */
@@ -1210,6 +1209,7 @@ public class BubbleStackView extends FrameLayout {
*/
void magnetToStackIfNeededThenAnimateDismissal(
View touchedView, float velX, float velY, Runnable after) {
+ final View draggedOutBubble = mExpandedAnimationController.getDraggedOutBubble();
final Runnable animateDismissal = () -> {
mAfterMagnet = null;
@@ -1227,7 +1227,7 @@ public class BubbleStackView extends FrameLayout {
resetDesaturationAndDarken();
});
} else {
- mExpandedAnimationController.dismissDraggedOutBubble(() -> {
+ mExpandedAnimationController.dismissDraggedOutBubble(draggedOutBubble, () -> {
mAnimatingMagnet = false;
mShowingDismiss = false;
mDraggingInDismissTarget = false;
@@ -1394,10 +1394,18 @@ public class BubbleStackView extends FrameLayout {
};
// Post in case layout isn't complete and getWidth returns 0.
- post(() -> mFlyout.showFlyout(
- updateMessage, mStackAnimationController.getStackPosition(), getWidth(),
- mStackAnimationController.isStackOnLeftSide(),
- bubble.iconView.getBadgeColor(), mAfterFlyoutHides));
+ post(() -> {
+ // An auto-expanding bubble could have been posted during the time it takes to
+ // layout.
+ if (isExpanded()) {
+ return;
+ }
+
+ mFlyout.showFlyout(
+ updateMessage, mStackAnimationController.getStackPosition(), getWidth(),
+ mStackAnimationController.isStackOnLeftSide(),
+ bubble.iconView.getBadgeColor(), mAfterFlyoutHides);
+ });
}
mFlyout.removeCallbacks(mHideFlyout);
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
index 24337a3c3312..1fa0e12452e1 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
@@ -22,6 +22,7 @@ import android.graphics.PointF;
import android.view.View;
import android.view.WindowInsets;
+import androidx.annotation.Nullable;
import androidx.dynamicanimation.animation.DynamicAnimation;
import androidx.dynamicanimation.animation.SpringForce;
@@ -63,12 +64,16 @@ public class ExpandedAnimationController
private Point mDisplaySize;
/** Size of dismiss target at bottom of screen. */
private float mPipDismissHeight;
- /** Max number of bubbles shown in row above expanded view.*/
- private int mBubblesMaxRendered;
/** Whether the dragged-out bubble is in the dismiss target. */
private boolean mIndividualBubbleWithinDismissTarget = false;
+ private boolean mAnimatingExpand = false;
+ private boolean mAnimatingCollapse = false;
+ private Runnable mAfterExpand;
+ private Runnable mAfterCollapse;
+ private PointF mCollapsePoint;
+
/**
* Whether the dragged out bubble is springing towards the touch point, rather than using the
* default behavior of moving directly to the touch point.
@@ -97,56 +102,60 @@ public class ExpandedAnimationController
private View mBubbleDraggingOut;
/**
- * Drag velocities for the dragging-out bubble when the drag finished. These are used by
- * {@link #onChildRemoved} to animate out the bubble while respecting touch velocity.
+ * Animates expanding the bubbles into a row along the top of the screen.
*/
- private float mBubbleDraggingOutVelX;
- private float mBubbleDraggingOutVelY;
+ public void expandFromStack(Runnable after) {
+ mAnimatingCollapse = false;
+ mAnimatingExpand = true;
+ mAfterExpand = after;
- @Override
- protected void setLayout(PhysicsAnimationLayout layout) {
- super.setLayout(layout);
+ startOrUpdateExpandAnimation();
+ }
- final Resources res = layout.getResources();
- mStackOffsetPx = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
- mBubblePaddingPx = res.getDimensionPixelSize(R.dimen.bubble_padding);
- mBubbleSizePx = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
- mStatusBarHeight =
- res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
- mPipDismissHeight = res.getDimensionPixelSize(R.dimen.pip_dismiss_gradient_height);
- mBubblesMaxRendered = res.getInteger(R.integer.bubbles_max_rendered);
+ /** Animate collapsing the bubbles back to their stacked position. */
+ public void collapseBackToStack(PointF collapsePoint, Runnable after) {
+ mAnimatingExpand = false;
+ mAnimatingCollapse = true;
+ mAfterCollapse = after;
+ mCollapsePoint = collapsePoint;
+
+ startOrUpdateCollapseAnimation();
}
- /**
- * Animates expanding the bubbles into a row along the top of the screen.
- */
- public void expandFromStack(PointF collapseTo, Runnable after) {
+ private void startOrUpdateExpandAnimation() {
animationsForChildrenFromIndex(
0, /* startIndex */
- new ChildAnimationConfigurator() {
- @Override
- public void configureAnimationForChildAtIndex(
- int index, PhysicsAnimationLayout.PhysicsPropertyAnimator animation) {
- animation.position(getBubbleLeft(index), getExpandedY());
+ (index, animation) -> animation.position(getBubbleLeft(index), getExpandedY()))
+ .startAll(() -> {
+ mAnimatingExpand = false;
+
+ if (mAfterExpand != null) {
+ mAfterExpand.run();
}
- })
- .startAll(after);
- mCollapseToPoint = collapseTo;
+ mAfterExpand = null;
+ });
}
- /** Animate collapsing the bubbles back to their stacked position. */
- public void collapseBackToStack(Runnable after) {
+ private void startOrUpdateCollapseAnimation() {
// Stack to the left if we're going to the left, or right if not.
- final float sideMultiplier = mLayout.isFirstChildXLeftOfCenter(mCollapseToPoint.x) ? -1 : 1;
-
+ final float sideMultiplier = mLayout.isFirstChildXLeftOfCenter(mCollapsePoint.x) ? -1 : 1;
animationsForChildrenFromIndex(
0, /* startIndex */
- (index, animation) ->
+ (index, animation) -> {
animation.position(
- mCollapseToPoint.x + (sideMultiplier * index * mStackOffsetPx),
- mCollapseToPoint.y))
- .startAll(after /* endAction */);
+ mCollapsePoint.x + (sideMultiplier * index * mStackOffsetPx),
+ mCollapsePoint.y);
+ })
+ .startAll(() -> {
+ mAnimatingCollapse = false;
+
+ if (mAfterCollapse != null) {
+ mAfterCollapse.run();
+ }
+
+ mAfterCollapse = null;
+ });
}
/** Prepares the given bubble to be dragged out. */
@@ -190,10 +199,10 @@ public class ExpandedAnimationController
}
/** Plays a dismiss animation on the dragged out bubble. */
- public void dismissDraggedOutBubble(Runnable after) {
+ public void dismissDraggedOutBubble(View bubble, Runnable after) {
mIndividualBubbleWithinDismissTarget = false;
- animationForChild(mBubbleDraggingOut)
+ animationForChild(bubble)
.withStiffness(SpringForce.STIFFNESS_HIGH)
.scaleX(1.1f)
.scaleY(1.1f)
@@ -203,6 +212,10 @@ public class ExpandedAnimationController
updateBubblePositions();
}
+ @Nullable public View getDraggedOutBubble() {
+ return mBubbleDraggingOut;
+ }
+
/** Magnets the given bubble to the dismiss target. */
public void magnetBubbleToDismiss(
View bubbleView, float velX, float velY, float destY, Runnable after) {
@@ -241,24 +254,17 @@ public class ExpandedAnimationController
final int index = mLayout.indexOfChild(bubbleView);
animationForChildAtIndex(index)
- .position(getBubbleLeft(index), getExpandedY())
- .withPositionStartVelocities(velX, velY)
- .start(() -> bubbleView.setTranslationZ(0f) /* after */);
+ .position(getBubbleLeft(index), getExpandedY())
+ .withPositionStartVelocities(velX, velY)
+ .start(() -> bubbleView.setTranslationZ(0f) /* after */);
- mBubbleDraggingOut = null;
- mBubbleDraggedOutEnough = false;
updateBubblePositions();
}
- /**
- * Sets configuration variables so that when the given bubble is removed, the animations are
- * started with the given velocities.
- */
- public void prepareForDismissalWithVelocity(View bubbleView, float velX, float velY) {
- mBubbleDraggingOut = bubbleView;
- mBubbleDraggingOutVelX = velX;
- mBubbleDraggingOutVelY = velY;
+ /** Resets bubble drag out gesture flags. */
+ public void onGestureFinished() {
mBubbleDraggedOutEnough = false;
+ mBubbleDraggingOut = null;
}
/**
@@ -297,6 +303,23 @@ public class ExpandedAnimationController
}
@Override
+ void onActiveControllerForLayout(PhysicsAnimationLayout layout) {
+ final Resources res = layout.getResources();
+ mStackOffsetPx = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
+ mBubblePaddingPx = res.getDimensionPixelSize(R.dimen.bubble_padding);
+ mBubbleSizePx = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
+ mStatusBarHeight =
+ res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+ mPipDismissHeight = res.getDimensionPixelSize(R.dimen.pip_dismiss_gradient_height);
+
+ // Ensure that all child views are at 1x scale, and visible, in case they were animating
+ // in.
+ mLayout.setVisibility(View.VISIBLE);
+ animationsForChildrenFromIndex(0 /* startIndex */, (index, animation) ->
+ animation.scaleX(1f).scaleY(1f).alpha(1f)).startAll();
+ }
+
+ @Override
Set<DynamicAnimation.ViewProperty> getAnimatedProperties() {
return Sets.newHashSet(
DynamicAnimation.TRANSLATION_X,
@@ -325,14 +348,21 @@ public class ExpandedAnimationController
@Override
void onChildAdded(View child, int index) {
- child.setTranslationX(getXForChildAtIndex(index));
-
- animationForChild(child)
- .translationY(
- getExpandedY() - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR, /* from */
- getExpandedY() /* to */)
- .start();
- updateBubblePositions();
+ // If a bubble is added while the expand/collapse animations are playing, update the
+ // animation to include the new bubble.
+ if (mAnimatingExpand) {
+ startOrUpdateExpandAnimation();
+ } else if (mAnimatingCollapse) {
+ startOrUpdateCollapseAnimation();
+ } else {
+ child.setTranslationX(getXForChildAtIndex(index));
+ animationForChild(child)
+ .translationY(
+ getExpandedY() - mBubbleSizePx * ANIMATE_TRANSLATION_FACTOR, /* from */
+ getExpandedY() /* to */)
+ .start();
+ updateBubblePositions();
+ }
}
@Override
@@ -357,19 +387,15 @@ public class ExpandedAnimationController
}
@Override
- protected void setChildVisibility(View child, int index, int visibility) {
- if (visibility == View.VISIBLE) {
- // Set alpha to 0 but then become visible immediately so the animation is visible.
- child.setAlpha(0f);
- child.setVisibility(View.VISIBLE);
- }
-
- animationForChild(child)
- .alpha(visibility == View.GONE ? 0f : 1f)
- .start(() -> super.setChildVisibility(child, index, visibility) /* after */);
+ void onChildReordered(View child, int oldIndex, int newIndex) {
+ updateBubblePositions();
}
private void updateBubblePositions() {
+ if (mAnimatingExpand || mAnimatingCollapse) {
+ return;
+ }
+
for (int i = 0; i < mLayout.getChildCount(); i++) {
final View bubble = mLayout.getChildAt(i);
@@ -378,6 +404,7 @@ public class ExpandedAnimationController
if (bubble.equals(mBubbleDraggingOut)) {
return;
}
+
animationForChild(bubble)
.translationX(getBubbleLeft(i))
.start();
@@ -403,10 +430,7 @@ public class ExpandedAnimationController
return 0;
}
int bubbleCount = mLayout.getChildCount();
- if (bubbleCount > mBubblesMaxRendered) {
- // Only shown bubbles are relevant for calculating position.
- bubbleCount = mBubblesMaxRendered;
- }
+
// Width calculations.
double bubble = bubbleCount * mBubbleSizePx;
float gap = (bubbleCount - 1) * mBubblePaddingPx;
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java
index 997d2c4627d8..3a3339249d5b 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayout.java
@@ -17,10 +17,12 @@
package com.android.systemui.bubbles.animation;
import android.content.Context;
+import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
+import androidx.annotation.Nullable;
import androidx.dynamicanimation.animation.DynamicAnimation;
import androidx.dynamicanimation.animation.SpringAnimation;
import androidx.dynamicanimation.animation.SpringForce;
@@ -137,12 +139,33 @@ public class PhysicsAnimationLayout extends FrameLayout {
*/
abstract void onChildRemoved(View child, int index, Runnable finishRemoval);
+ /** Called when a child view has been reordered in the view hierachy. */
+ abstract void onChildReordered(View child, int oldIndex, int newIndex);
+
+ /**
+ * Called when the controller is set as the active animation controller for the given
+ * layout. Once active, the controller can start animations using the animator instances
+ * returned by {@link #animationForChild}.
+ *
+ * While all animations started by the previous controller will be cancelled, the new
+ * controller should not make any assumptions about the state of the layout or its children.
+ * Their translation, alpha, scale, etc. values may have been changed by the previous
+ * controller and should be reset here if relevant.
+ */
+ abstract void onActiveControllerForLayout(PhysicsAnimationLayout layout);
+
protected PhysicsAnimationLayout mLayout;
PhysicsAnimationController() { }
+ /** Whether this controller is the currently active controller for its associated layout. */
+ protected boolean isActiveController() {
+ return this == mLayout.mController;
+ }
+
protected void setLayout(PhysicsAnimationLayout layout) {
this.mLayout = layout;
+ onActiveControllerForLayout(layout);
}
protected PhysicsAnimationLayout getLayout() {
@@ -150,15 +173,6 @@ public class PhysicsAnimationLayout extends FrameLayout {
}
/**
- * Sets the child's visibility when it moves beyond or within the limits set by a call to
- * {@link PhysicsAnimationLayout#setMaxRenderedChildren}. This can be overridden to animate
- * this transition.
- */
- protected void setChildVisibility(View child, int index, int visibility) {
- child.setVisibility(visibility);
- }
-
- /**
* Returns a {@link PhysicsPropertyAnimator} instance for the given child view.
*/
protected PhysicsPropertyAnimator animationForChild(View child) {
@@ -170,6 +184,9 @@ public class PhysicsAnimationLayout extends FrameLayout {
child.setTag(R.id.physics_animator_tag, animator);
}
+ animator.clearAnimator();
+ animator.setAssociatedController(this);
+
return animator;
}
@@ -235,32 +252,17 @@ public class PhysicsAnimationLayout extends FrameLayout {
new HashMap<>();
/** The currently active animation controller. */
- private PhysicsAnimationController mController;
-
- /**
- * The maximum number of children to render and animate at a time. See
- * {@link #setMaxRenderedChildren}.
- */
- private int mMaxRenderedChildren = 5;
+ @Nullable protected PhysicsAnimationController mController;
public PhysicsAnimationLayout(Context context) {
super(context);
}
/**
- * The maximum number of children to render and animate at a time. Any child views added beyond
- * this limit will be set to {@link View#GONE}. If any animations attempt to run on the view,
- * the corresponding property will be set with no animation.
- */
- public void setMaxRenderedChildren(int max) {
- this.mMaxRenderedChildren = max;
- }
-
- /**
* Sets the animation controller and constructs or reconfigures the layout's physics animations
* to meet the controller's specifications.
*/
- public void setController(PhysicsAnimationController controller) {
+ public void setActiveController(PhysicsAnimationController controller) {
cancelAllAnimations();
mEndActionForProperty.clear();
@@ -312,42 +314,11 @@ public class PhysicsAnimationLayout extends FrameLayout {
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
- super.addView(child, index, params);
-
- // Set up animations for the new view, if the controller is set. If it isn't set, we'll be
- // setting up animations for all children when setController is called.
- if (mController != null) {
- for (DynamicAnimation.ViewProperty property : mController.getAnimatedProperties()) {
- setUpAnimationForChild(property, child, index);
- }
-
- mController.onChildAdded(child, index);
- }
-
- setChildrenVisibility();
+ addViewInternal(child, index, params, false /* isReorder */);
}
@Override
public void removeView(View view) {
- removeViewAndThen(view, /* callback */ null);
- }
-
- @Override
- public void removeViewAt(int index) {
- removeView(getChildAt(index));
- }
-
- /** Immediately moves the view from wherever it currently is, to the given index. */
- public void moveViewTo(View view, int index) {
- super.removeView(view);
- addView(view, index);
- }
-
- /**
- * Let the controller know that this view should be removed, and then call the callback once the
- * controller has finished any removal animations and the view has actually been removed.
- */
- public void removeViewAndThen(View view, Runnable callback) {
if (mController != null) {
final int index = indexOfChild(view);
@@ -355,8 +326,6 @@ public class PhysicsAnimationLayout extends FrameLayout {
super.removeView(view);
addTransientView(view, index);
- setChildrenVisibility();
-
// Tell the controller to animate this view out, and call the callback when it's
// finished.
mController.onChildRemoved(view, index, () -> {
@@ -364,19 +333,28 @@ public class PhysicsAnimationLayout extends FrameLayout {
// any are still running and then remove it.
cancelAnimationsOnView(view);
removeTransientView(view);
-
- if (callback != null) {
- callback.run();
- }
});
} else {
// Without a controller, nobody will animate this view out, so it gets an unceremonious
// departure.
super.removeView(view);
+ }
+ }
- if (callback != null) {
- callback.run();
- }
+ @Override
+ public void removeViewAt(int index) {
+ removeView(getChildAt(index));
+ }
+
+ /** Immediately re-orders the view to the given index. */
+ public void reorderView(View view, int index) {
+ final int oldIndex = indexOfChild(view);
+
+ super.removeView(view);
+ addViewInternal(view, index, view.getLayoutParams(), true /* isReorder */);
+
+ if (mController != null) {
+ mController.onChildReordered(view, oldIndex, index);
}
}
@@ -427,6 +405,10 @@ public class PhysicsAnimationLayout extends FrameLayout {
}
}
+ protected boolean isActiveController(PhysicsAnimationController controller) {
+ return mController == controller;
+ }
+
/** Whether the first child would be left of center if translated to the given x value. */
protected boolean isFirstChildXLeftOfCenter(float x) {
if (getChildCount() > 0) {
@@ -454,6 +436,26 @@ public class PhysicsAnimationLayout extends FrameLayout {
}
/**
+ * Adds a view to the layout. If this addition is not the result of a call to
+ * {@link #reorderView}, this will also notify the controller via
+ * {@link PhysicsAnimationController#onChildAdded} and set up animations for the view.
+ */
+ private void addViewInternal(
+ View child, int index, ViewGroup.LayoutParams params, boolean isReorder) {
+ super.addView(child, index, params);
+
+ // Set up animations for the new view, if the controller is set. If it isn't set, we'll be
+ // setting up animations for all children when setActiveController is called.
+ if (mController != null && !isReorder) {
+ for (DynamicAnimation.ViewProperty property : mController.getAnimatedProperties()) {
+ setUpAnimationForChild(property, child, index);
+ }
+
+ mController.onChildAdded(child, index);
+ }
+ }
+
+ /**
* Retrieves the animation of the given property from the view at the given index via the view
* tag system.
*/
@@ -481,33 +483,16 @@ public class PhysicsAnimationLayout extends FrameLayout {
SpringAnimation newAnim = new SpringAnimation(child, property);
newAnim.addUpdateListener((animation, value, velocity) -> {
final int indexOfChild = indexOfChild(child);
- final int nextAnimInChain =
- mController.getNextAnimationInChain(property, indexOfChild);
+ final int nextAnimInChain = mController.getNextAnimationInChain(property, indexOfChild);
if (nextAnimInChain == PhysicsAnimationController.NONE || indexOfChild < 0) {
return;
}
- final int animIndex = indexOfChild(child);
- final float offset =
- mController.getOffsetForChainedPropertyAnimation(property);
-
- // If this property's animations should be chained, then check to see if there is a
- // subsequent animation within the rendering limit, and if so, tell it to animate to
- // this animation's new value (plus the offset).
- if (nextAnimInChain < Math.min(getChildCount(), mMaxRenderedChildren)) {
- getAnimationAtIndex(property, animIndex + 1)
+ final float offset = mController.getOffsetForChainedPropertyAnimation(property);
+ if (nextAnimInChain < getChildCount()) {
+ getAnimationAtIndex(property, nextAnimInChain)
.animateToFinalPosition(value + offset);
- } else if (nextAnimInChain < getChildCount()) {
- // If the next child view is not rendered, update the property directly without
- // animating it, so that the view is still in the correct state if it later
- // becomes visible.
- for (int i = nextAnimInChain; i < getChildCount(); i++) {
- // 'value' here is the value of the last child within the rendering limit,
- // not the first child's value - so we want to subtract the last child's
- // index when calculating the offset.
- property.setValue(getChildAt(i), value + offset * (i - animIndex));
- }
}
});
@@ -516,22 +501,6 @@ public class PhysicsAnimationLayout extends FrameLayout {
child.setTag(getTagIdForProperty(property), newAnim);
}
- /** Hides children beyond the max rendering count. */
- private void setChildrenVisibility() {
- for (int i = 0; i < getChildCount(); i++) {
- final int targetVisibility = i < mMaxRenderedChildren ? View.VISIBLE : View.GONE;
- final View targetView = getChildAt(i);
-
- if (targetView.getVisibility() != targetVisibility) {
- if (mController != null) {
- mController.setChildVisibility(targetView, i, targetVisibility);
- } else {
- targetView.setVisibility(targetVisibility);
- }
- }
- }
- }
-
/** Return a stable ID to use as a tag key for the given property's animations. */
private int getTagIdForProperty(DynamicAnimation.ViewProperty property) {
if (property.equals(DynamicAnimation.TRANSLATION_X)) {
@@ -592,7 +561,7 @@ public class PhysicsAnimationLayout extends FrameLayout {
private View mView;
/** Start velocity to use for all property animations. */
- private float mDefaultStartVelocity = 0f;
+ private float mDefaultStartVelocity = -Float.MAX_VALUE;
/** Start delay to use when start is called. */
private long mStartDelay = 0;
@@ -625,6 +594,15 @@ public class PhysicsAnimationLayout extends FrameLayout {
*/
private Map<DynamicAnimation.ViewProperty, Float> mAnimatedProperties = new HashMap<>();
+ /**
+ * All of the initial property values that have been set. These values will be instantly set
+ * when {@link #start} is called, just before the animation begins.
+ */
+ private Map<DynamicAnimation.ViewProperty, Float> mInitialPropertyValues = new HashMap<>();
+
+ /** The animation controller that last retrieved this animator instance. */
+ private PhysicsAnimationController mAssociatedController;
+
protected PhysicsPropertyAnimator(View view) {
this.mView = view;
}
@@ -644,7 +622,7 @@ public class PhysicsAnimationLayout extends FrameLayout {
/** Set the view's alpha value to 'from', then animate it to the given value. */
public PhysicsPropertyAnimator alpha(float from, float to, Runnable... endActions) {
- mView.setAlpha(from);
+ mInitialPropertyValues.put(DynamicAnimation.ALPHA, from);
return alpha(to, endActions);
}
@@ -656,7 +634,7 @@ public class PhysicsAnimationLayout extends FrameLayout {
/** Set the view's translationX value to 'from', then animate it to the given value. */
public PhysicsPropertyAnimator translationX(
float from, float to, Runnable... endActions) {
- mView.setTranslationX(from);
+ mInitialPropertyValues.put(DynamicAnimation.TRANSLATION_X, from);
return translationX(to, endActions);
}
@@ -668,7 +646,7 @@ public class PhysicsAnimationLayout extends FrameLayout {
/** Set the view's translationY value to 'from', then animate it to the given value. */
public PhysicsPropertyAnimator translationY(
float from, float to, Runnable... endActions) {
- mView.setTranslationY(from);
+ mInitialPropertyValues.put(DynamicAnimation.TRANSLATION_Y, from);
return translationY(to, endActions);
}
@@ -690,7 +668,7 @@ public class PhysicsAnimationLayout extends FrameLayout {
/** Set the view's scaleX value to 'from', then animate it to the given value. */
public PhysicsPropertyAnimator scaleX(float from, float to, Runnable... endActions) {
- mView.setScaleX(from);
+ mInitialPropertyValues.put(DynamicAnimation.SCALE_X, from);
return scaleX(to, endActions);
}
@@ -701,7 +679,7 @@ public class PhysicsAnimationLayout extends FrameLayout {
/** Set the view's scaleY value to 'from', then animate it to the given value. */
public PhysicsPropertyAnimator scaleY(float from, float to, Runnable... endActions) {
- mView.setScaleY(from);
+ mInitialPropertyValues.put(DynamicAnimation.SCALE_Y, from);
return scaleY(to, endActions);
}
@@ -750,6 +728,13 @@ public class PhysicsAnimationLayout extends FrameLayout {
* animated property on every child (including chained animations) have ended.
*/
public void start(Runnable... after) {
+ if (!isActiveController(mAssociatedController)) {
+ Log.w(TAG, "Only the active animation controller is allowed to start animations. "
+ + "Use PhysicsAnimationLayout#setActiveController to set the active "
+ + "animation controller.");
+ return;
+ }
+
final Set<DynamicAnimation.ViewProperty> properties = getAnimatedProperties();
// If there are end actions, set an end listener on the layout for all the properties
@@ -791,6 +776,10 @@ public class PhysicsAnimationLayout extends FrameLayout {
// Actually start the animations.
for (DynamicAnimation.ViewProperty property : properties) {
+ if (mInitialPropertyValues.containsKey(property)) {
+ property.setValue(mView, mInitialPropertyValues.get(property));
+ }
+
final SpringForce defaultSpringForce = mController.getSpringForce(property, mView);
animateValueForChild(
property,
@@ -803,14 +792,7 @@ public class PhysicsAnimationLayout extends FrameLayout {
mEndActionsForProperty.get(property));
}
- // Clear out the animator.
- mAnimatedProperties.clear();
- mPositionStartVelocities.clear();
- mDefaultStartVelocity = 0;
- mStartDelay = 0;
- mStiffness = -1;
- mDampingRatio = -1;
- mEndActionsForProperty.clear();
+ clearAnimator();
}
/** Returns the set of properties that will animate once {@link #start} is called. */
@@ -847,20 +829,50 @@ public class PhysicsAnimationLayout extends FrameLayout {
});
}
- animation.getSpring().setStiffness(stiffness);
- animation.getSpring().setDampingRatio(dampingRatio);
+ final SpringForce animationSpring = animation.getSpring();
- if (startVel > 0) {
- animation.setStartVelocity(startVel);
+ if (animationSpring == null) {
+ return;
}
+ final Runnable configureAndStartAnimation = () -> {
+ animationSpring.setStiffness(stiffness);
+ animationSpring.setDampingRatio(dampingRatio);
+
+ if (startVel > -Float.MAX_VALUE) {
+ animation.setStartVelocity(startVel);
+ }
+
+ animationSpring.setFinalPosition(value);
+ animation.start();
+ };
+
if (startDelay > 0) {
- postDelayed(() -> animation.animateToFinalPosition(value), startDelay);
+ postDelayed(configureAndStartAnimation, startDelay);
} else {
- animation.animateToFinalPosition(value);
+ configureAndStartAnimation.run();
}
}
}
+
+ private void clearAnimator() {
+ mInitialPropertyValues.clear();
+ mAnimatedProperties.clear();
+ mPositionStartVelocities.clear();
+ mDefaultStartVelocity = -Float.MAX_VALUE;
+ mStartDelay = 0;
+ mStiffness = -1;
+ mDampingRatio = -1;
+ mEndActionsForProperty.clear();
+ }
+
+ /**
+ * Sets the controller that last retrieved this animator instance, so that we can prevent
+ * {@link #start} from actually starting animations if called by a non-active controller.
+ */
+ private void setAssociatedController(PhysicsAnimationController controller) {
+ mAssociatedController = controller;
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
index b9cdc844eef9..ab8752e4195f 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/StackAnimationController.java
@@ -154,21 +154,6 @@ public class StackAnimationController extends
/** Height of the status bar. */
private float mStatusBarHeight;
- @Override
- protected void setLayout(PhysicsAnimationLayout layout) {
- super.setLayout(layout);
-
- Resources res = layout.getResources();
- mStackOffset = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
- mIndividualBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
- mBubblePadding = res.getDimensionPixelSize(R.dimen.bubble_padding);
- mBubbleOffscreen = res.getDimensionPixelSize(R.dimen.bubble_stack_offscreen);
- mStackStartingVerticalOffset =
- res.getDimensionPixelSize(R.dimen.bubble_stack_starting_offset_y);
- mStatusBarHeight =
- res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
- }
-
/**
* Instantly move the first bubble to the given point, and animate the rest of the stack behind
* it with the 'following' effect.
@@ -286,6 +271,8 @@ public class StackAnimationController extends
},
DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
+ // If we're flinging now, there's no more touch event to catch up to.
+ mFirstBubbleSpringingToTouch = false;
mIsMovingFromFlinging = true;
return destinationRelativeX;
}
@@ -656,19 +643,38 @@ public class StackAnimationController extends
if (mLayout.getChildCount() > 0) {
animationForChildAtIndex(0).translationX(mStackPosition.x).start();
+ } else {
+ // Set the start position back to the default since we're out of bubbles. New bubbles
+ // will then animate in from the start position.
+ mStackPosition = getDefaultStartPosition();
}
}
+ @Override
+ void onChildReordered(View child, int oldIndex, int newIndex) {}
+
+ @Override
+ void onActiveControllerForLayout(PhysicsAnimationLayout layout) {
+ Resources res = layout.getResources();
+ mStackOffset = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
+ mIndividualBubbleSize = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
+ mBubblePadding = res.getDimensionPixelSize(R.dimen.bubble_padding);
+ mBubbleOffscreen = res.getDimensionPixelSize(R.dimen.bubble_stack_offscreen);
+ mStackStartingVerticalOffset =
+ res.getDimensionPixelSize(R.dimen.bubble_stack_starting_offset_y);
+ mStatusBarHeight =
+ res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+ }
+
/** Moves the stack, without any animation, to the starting position. */
private void moveStackToStartPosition() {
// Post to ensure that the layout's width and height have been calculated.
mLayout.setVisibility(View.INVISIBLE);
mLayout.post(() -> {
+ setStackPosition(mRestingStackPosition == null
+ ? getDefaultStartPosition()
+ : mRestingStackPosition);
mStackMovedToStartPosition = true;
- setStackPosition(
- mRestingStackPosition == null
- ? getDefaultStartPosition()
- : mRestingStackPosition);
mLayout.setVisibility(View.VISIBLE);
// Animate in the top bubble now that we're visible.
@@ -707,15 +713,20 @@ public class StackAnimationController extends
Log.d(TAG, String.format("Setting position to (%f, %f).", pos.x, pos.y));
mStackPosition.set(pos.x, pos.y);
- mLayout.cancelAllAnimations();
- cancelStackPositionAnimations();
-
- // Since we're not using the chained animations, apply the offsets manually.
- final float xOffset = getOffsetForChainedPropertyAnimation(DynamicAnimation.TRANSLATION_X);
- final float yOffset = getOffsetForChainedPropertyAnimation(DynamicAnimation.TRANSLATION_Y);
- for (int i = 0; i < mLayout.getChildCount(); i++) {
- mLayout.getChildAt(i).setTranslationX(pos.x + (i * xOffset));
- mLayout.getChildAt(i).setTranslationY(pos.y + (i * yOffset));
+ // If we're not the active controller, we don't want to physically move the bubble views.
+ if (isActiveController()) {
+ mLayout.cancelAllAnimations();
+ cancelStackPositionAnimations();
+
+ // Since we're not using the chained animations, apply the offsets manually.
+ final float xOffset = getOffsetForChainedPropertyAnimation(
+ DynamicAnimation.TRANSLATION_X);
+ final float yOffset = getOffsetForChainedPropertyAnimation(
+ DynamicAnimation.TRANSLATION_Y);
+ for (int i = 0; i < mLayout.getChildCount(); i++) {
+ mLayout.getChildAt(i).setTranslationX(pos.x + (i * xOffset));
+ mLayout.getChildAt(i).setTranslationY(pos.y + (i * yOffset));
+ }
}
}
@@ -732,6 +743,10 @@ public class StackAnimationController extends
/** Animates in the given bubble. */
private void animateInBubble(View child) {
+ if (!isActiveController()) {
+ return;
+ }
+
child.setTranslationY(mStackPosition.y);
float xOffset = getOffsetForChainedPropertyAnimation(DynamicAnimation.TRANSLATION_X);
diff --git a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
index 05665b5ae4a2..835ffc976e9f 100644
--- a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
+++ b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
@@ -16,6 +16,7 @@
package com.android.systemui.colorextraction;
+import android.annotation.ColorInt;
import android.app.WallpaperColors;
import android.app.WallpaperManager;
import android.content.Context;
@@ -113,7 +114,11 @@ public class SysuiColorExtractor extends ColorExtractor implements Dumpable,
super.onColorsChanged(colors, which);
if ((which & WallpaperManager.FLAG_SYSTEM) != 0) {
+ @ColorInt int oldColor = mWpHiddenColors.getMainColor();
updateDefaultGradients(colors);
+ if (oldColor != mWpHiddenColors.getMainColor()) {
+ triggerColorsChanged(WallpaperManager.FLAG_SYSTEM);
+ }
}
}
@@ -121,6 +126,7 @@ public class SysuiColorExtractor extends ColorExtractor implements Dumpable,
public void onUiModeChanged() {
WallpaperColors systemColors = getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
updateDefaultGradients(systemColors);
+ triggerColorsChanged(WallpaperManager.FLAG_SYSTEM);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 831d07446e7c..2c85eff2c198 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -536,7 +536,7 @@ public class DozeSensors {
mHandler.post(mWakeLock.wrap(() -> {
final long now = SystemClock.uptimeMillis();
if (now < mDebounceFrom + mDebounce) {
- if (DEBUG) Log.d(TAG, "onSensorEvent dropped: " + triggerEventToString(event));
+ Log.d(TAG, "onSensorEvent dropped: " + triggerEventToString(event));
return;
}
if (DEBUG) Log.d(TAG, "onSensorEvent: " + triggerEventToString(event));
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index ff16ed0f1477..dc977547b024 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -551,7 +551,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
private class EmergencyDialerAction extends EmergencyAction {
private EmergencyDialerAction() {
- super(R.drawable.ic_faster_emergency,
+ super(com.android.systemui.R.drawable.ic_emergency_star,
R.string.global_action_emergency);
}
@@ -1588,17 +1588,13 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
// Disable rotation suggestions, if enabled
setRotationSuggestionsEnabled(false);
- FrameLayout panelContainer = new FrameLayout(mContext);
+ FrameLayout panelContainer =
+ findViewById(com.android.systemui.R.id.global_actions_panel_container);
FrameLayout.LayoutParams panelParams =
new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
- FrameLayout.LayoutParams.WRAP_CONTENT);
+ FrameLayout.LayoutParams.MATCH_PARENT);
panelContainer.addView(mPanelController.getPanelContent(), panelParams);
- addContentView(
- panelContainer,
- new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT));
mBackgroundDrawable = mPanelController.getBackgroundDrawable();
mScrimAlpha = 1f;
}
@@ -1606,8 +1602,10 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
private void initializeLayout() {
setContentView(getGlobalActionsLayoutId(mContext));
+ fixNavBarClipping();
mGlobalActionsLayout = findViewById(com.android.systemui.R.id.global_actions_view);
mGlobalActionsLayout.setOutsideTouchListener(view -> dismiss());
+ ((View) mGlobalActionsLayout.getParent()).setOnClickListener(view -> dismiss());
mGlobalActionsLayout.setListViewAccessibilityDelegate(new View.AccessibilityDelegate() {
@Override
public boolean dispatchPopulateAccessibilityEvent(
@@ -1630,6 +1628,15 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener,
getWindow().setBackgroundDrawable(mBackgroundDrawable);
}
+ private void fixNavBarClipping() {
+ ViewGroup content = findViewById(android.R.id.content);
+ content.setClipChildren(false);
+ content.setClipToPadding(false);
+ ViewGroup contentParent = (ViewGroup) content.getParent();
+ contentParent.setClipChildren(false);
+ contentParent.setClipToPadding(false);
+ }
+
private int getGlobalActionsLayoutId(Context context) {
int rotation = RotationUtils.getRotation(context);
boolean useGridLayout = isForceGridEnabled(context)
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java
index 03165f47c472..e1462d15c887 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java
@@ -42,8 +42,6 @@ public class GlobalActionsGridLayout extends GlobalActionsLayout {
listView.setReverseSublists(shouldReverseSublists());
listView.setReverseItems(shouldReverseListItems());
listView.setSwapRowsAndColumns(shouldSwapRowsAndColumns());
-
- fixNavBarClipping();
}
@Override
@@ -75,19 +73,6 @@ public class GlobalActionsGridLayout extends GlobalActionsLayout {
}
}
- /**
- * Allows the dialog to clip over the navbar, which prevents shadows and animations from being
- * cut off.
- */
- private void fixNavBarClipping() {
- ViewGroup parent = (ViewGroup) this.getParent();
- ViewGroup parentParent = (ViewGroup) parent.getParent();
- parent.setClipChildren(false);
- parent.setClipToPadding(false);
- parentParent.setClipChildren(false);
- parentParent.setClipToPadding(false);
- }
-
@Override
protected ListGridLayout getListView() {
return (ListGridLayout) super.getListView();
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 35b8d203cbe2..d4c73668d0ed 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -56,6 +56,8 @@ import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.NextAlarmControllerImpl;
import com.android.systemui.statusbar.policy.ZenModeController;
import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
+import com.android.systemui.util.wakelock.SettableWakeLock;
+import com.android.systemui.util.wakelock.WakeLock;
import java.util.Date;
import java.util.HashSet;
@@ -101,6 +103,8 @@ public class KeyguardSliceProvider extends SliceProvider implements
private final Handler mHandler;
private final AlarmManager.OnAlarmListener mUpdateNextAlarm = this::updateNextAlarm;
private final HashSet<Integer> mMediaInvisibleStates;
+ private final Object mMediaToken = new Object();
+ private SettableWakeLock mMediaWakeLock;
private ZenModeController mZenModeController;
private String mDatePattern;
private DateFormat mDateFormat;
@@ -114,7 +118,8 @@ public class KeyguardSliceProvider extends SliceProvider implements
private PendingIntent mPendingIntent;
protected NotificationMediaManager mMediaManager;
private StatusBarStateController mStatusBarStateController;
- protected MediaMetadata mMediaMetaData;
+ private CharSequence mMediaTitle;
+ private CharSequence mMediaArtist;
protected boolean mDozing;
private boolean mMediaIsVisible;
@@ -218,24 +223,18 @@ public class KeyguardSliceProvider extends SliceProvider implements
}
protected boolean needsMediaLocked() {
- return mMediaMetaData != null && mMediaIsVisible && mDozing;
+ return !TextUtils.isEmpty(mMediaTitle) && mMediaIsVisible && mDozing;
}
protected void addMediaLocked(ListBuilder listBuilder) {
- if (mMediaMetaData == null) {
+ if (TextUtils.isEmpty(mMediaTitle)) {
return;
}
+ listBuilder.setHeader(new ListBuilder.HeaderBuilder(mHeaderUri).setTitle(mMediaTitle));
- CharSequence title = mMediaMetaData.getText(MediaMetadata.METADATA_KEY_TITLE);
- if (TextUtils.isEmpty(title)) {
- title = getContext().getResources().getString(R.string.music_controls_no_title);
- }
- listBuilder.setHeader(new ListBuilder.HeaderBuilder(mHeaderUri).setTitle(title));
-
- CharSequence album = mMediaMetaData.getText(MediaMetadata.METADATA_KEY_ARTIST);
- if (!TextUtils.isEmpty(album)) {
+ if (!TextUtils.isEmpty(mMediaArtist)) {
RowBuilder albumBuilder = new RowBuilder(mMediaUri);
- albumBuilder.setTitle(album);
+ albumBuilder.setTitle(mMediaArtist);
Icon mediaIcon = mMediaManager == null ? null : mMediaManager.getMediaIcon();
IconCompat mediaIconCompat = mediaIcon == null ? null
@@ -306,6 +305,8 @@ public class KeyguardSliceProvider extends SliceProvider implements
mZenModeController.addCallback(this);
mDatePattern = getContext().getString(R.string.system_ui_aod_date_pattern);
mPendingIntent = PendingIntent.getActivity(getContext(), 0, new Intent(), 0);
+ mMediaWakeLock = new SettableWakeLock(WakeLock.createPartial(getContext(), "media"),
+ "media");
KeyguardSliceProvider.sInstance = this;
registerClockUpdate();
updateClockLocked();
@@ -425,12 +426,42 @@ public class KeyguardSliceProvider extends SliceProvider implements
public void onMetadataOrStateChanged(MediaMetadata metadata, @PlaybackState.State int state) {
synchronized (this) {
boolean nextVisible = !mMediaInvisibleStates.contains(state);
- if (nextVisible == mMediaIsVisible && metadata == mMediaMetaData) {
- return;
+ mHandler.removeCallbacksAndMessages(mMediaToken);
+ if (mMediaIsVisible && !nextVisible) {
+ // We need to delay this event for a few millis when stopping to avoid jank in the
+ // animation. The media app might not send its update when buffering, and the slice
+ // would end up without a header for 0.5 second.
+ mMediaWakeLock.setAcquired(true);
+ mHandler.postDelayed(() -> {
+ updateMediaStateLocked(metadata, state);
+ mMediaWakeLock.setAcquired(false);
+ }, mMediaToken, 2000);
+ } else {
+ mMediaWakeLock.setAcquired(false);
+ updateMediaStateLocked(metadata, state);
}
- mMediaMetaData = metadata;
- mMediaIsVisible = nextVisible;
}
+ }
+
+ private void updateMediaStateLocked(MediaMetadata metadata, @PlaybackState.State int state) {
+ boolean nextVisible = !mMediaInvisibleStates.contains(state);
+ CharSequence title = null;
+ if (metadata != null) {
+ title = metadata.getText(MediaMetadata.METADATA_KEY_TITLE);
+ if (TextUtils.isEmpty(title)) {
+ title = getContext().getResources().getString(R.string.music_controls_no_title);
+ }
+ }
+ CharSequence artist = metadata == null ? null : metadata.getText(
+ MediaMetadata.METADATA_KEY_ARTIST);
+
+ if (nextVisible == mMediaIsVisible && TextUtils.equals(title, mMediaTitle)
+ && TextUtils.equals(artist, mMediaArtist)) {
+ return;
+ }
+ mMediaTitle = title;
+ mMediaArtist = artist;
+ mMediaIsVisible = nextVisible;
notifyChange();
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index ec6cfe9d8e55..9616f0a29021 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1930,12 +1930,6 @@ public class KeyguardViewMediator extends SystemUI {
+ " --> flags=0x" + Integer.toHexString(flags));
}
- // TODO(b/113914868): investigation log for disappearing home button
- Log.d(TAG, "adjustStatusBarLocked (b/113914868): flags=" + flags
- + "mShowing=" + mShowing + " mStatusBarManager=" + mStatusBarManager
- + " mOccluded=" + mOccluded + " isSecure=" + isSecure()
- + " force=" + forceHideHomeRecentsButtons);
-
mStatusBarManager.disable(flags);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 984274817fef..410a13ee4730 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -461,6 +461,11 @@ public class QuickStatusBarHeader extends RelativeLayout implements
if (mHeaderTextContainerAlphaAnimator != null) {
mHeaderTextContainerAlphaAnimator.setPosition(keyguardExpansionFraction);
+ if (keyguardExpansionFraction > 0) {
+ mHeaderTextContainerView.setVisibility(VISIBLE);
+ } else {
+ mHeaderTextContainerView.setVisibility(INVISIBLE);
+ }
}
if (mPrivacyChipAlphaAnimator != null) {
mPrivacyChip.setExpanded(expansionFraction > 0.5);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 25bde3bbe2fa..812c1bb54472 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -741,13 +741,5 @@ public class KeyguardIndicationController implements StateListener,
updateIndication(false);
}
}
-
- @Override
- public void onKeyguardBouncerChanged(boolean bouncer) {
- if (mLockIcon == null) {
- return;
- }
- mLockIcon.setBouncerVisible(bouncer);
- }
- };
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt
index 4b2d13121f6b..aaf48490d7b0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt
@@ -25,6 +25,7 @@ import android.renderscript.Allocation
import android.renderscript.Element
import android.renderscript.RenderScript
import android.renderscript.ScriptIntrinsicBlur
+import android.util.Log
import android.util.MathUtils
import com.android.internal.graphics.ColorUtils
import com.android.systemui.statusbar.notification.MediaNotificationProcessor
@@ -32,6 +33,7 @@ import com.android.systemui.statusbar.notification.MediaNotificationProcessor
import javax.inject.Inject
import javax.inject.Singleton
+private const val TAG = "MediaArtworkProcessor"
private const val COLOR_ALPHA = (255 * 0.7f).toInt()
private const val BLUR_RADIUS = 25f
private const val DOWNSAMPLE = 6
@@ -42,45 +44,54 @@ class MediaArtworkProcessor @Inject constructor() {
private val mTmpSize = Point()
private var mArtworkCache: Bitmap? = null
- fun processArtwork(context: Context, artwork: Bitmap): Bitmap {
+ fun processArtwork(context: Context, artwork: Bitmap): Bitmap? {
if (mArtworkCache != null) {
- return mArtworkCache!!
+ return mArtworkCache
}
-
- context.display.getSize(mTmpSize)
val renderScript = RenderScript.create(context)
- val rect = Rect(0, 0, artwork.width, artwork.height)
- MathUtils.fitRect(rect, Math.max(mTmpSize.x / DOWNSAMPLE, mTmpSize.y / DOWNSAMPLE))
- var inBitmap = Bitmap.createScaledBitmap(artwork, rect.width(), rect.height(),
- true /* filter */)
- // Render script blurs only support ARGB_8888, we need a conversion if we got a
- // different bitmap config.
- if (inBitmap.config != Bitmap.Config.ARGB_8888) {
- val oldIn = inBitmap
- inBitmap = oldIn.copy(Bitmap.Config.ARGB_8888, false /* isMutable */)
- oldIn.recycle()
- }
- val input = Allocation.createFromBitmap(renderScript, inBitmap,
- Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_GRAPHICS_TEXTURE)
- val outBitmap = Bitmap.createBitmap(inBitmap.width, inBitmap.height,
- Bitmap.Config.ARGB_8888)
- val output = Allocation.createFromBitmap(renderScript, outBitmap)
val blur = ScriptIntrinsicBlur.create(renderScript, Element.U8_4(renderScript))
- blur.setRadius(BLUR_RADIUS)
- blur.setInput(input)
- blur.forEach(output)
- output.copyTo(outBitmap)
+ var input: Allocation? = null
+ var output: Allocation? = null
+ var inBitmap: Bitmap? = null
+ try {
+ context.display.getSize(mTmpSize)
+ val rect = Rect(0, 0, artwork.width, artwork.height)
+ MathUtils.fitRect(rect, Math.max(mTmpSize.x / DOWNSAMPLE, mTmpSize.y / DOWNSAMPLE))
+ inBitmap = Bitmap.createScaledBitmap(artwork, rect.width(), rect.height(),
+ true /* filter */)
+ // Render script blurs only support ARGB_8888, we need a conversion if we got a
+ // different bitmap config.
+ if (inBitmap.config != Bitmap.Config.ARGB_8888) {
+ val oldIn = inBitmap
+ inBitmap = oldIn.copy(Bitmap.Config.ARGB_8888, false /* isMutable */)
+ oldIn.recycle()
+ }
+ val outBitmap = Bitmap.createBitmap(inBitmap.width, inBitmap.height,
+ Bitmap.Config.ARGB_8888)
- val swatch = MediaNotificationProcessor.findBackgroundSwatch(artwork)
+ input = Allocation.createFromBitmap(renderScript, inBitmap,
+ Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_GRAPHICS_TEXTURE)
+ output = Allocation.createFromBitmap(renderScript, outBitmap)
- input.destroy()
- output.destroy()
- inBitmap.recycle()
- blur.destroy()
+ blur.setRadius(BLUR_RADIUS)
+ blur.setInput(input)
+ blur.forEach(output)
+ output.copyTo(outBitmap)
- val canvas = Canvas(outBitmap)
- canvas.drawColor(ColorUtils.setAlphaComponent(swatch.rgb, COLOR_ALPHA))
- return outBitmap
+ val swatch = MediaNotificationProcessor.findBackgroundSwatch(artwork)
+
+ val canvas = Canvas(outBitmap)
+ canvas.drawColor(ColorUtils.setAlphaComponent(swatch.rgb, COLOR_ALPHA))
+ return outBitmap
+ } catch (ex: IllegalArgumentException) {
+ Log.e(TAG, "error while processing artwork", ex)
+ return null
+ } finally {
+ input?.destroy()
+ output?.destroy()
+ blur.destroy()
+ inBitmap?.recycle()
+ }
}
fun clearCache() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
index 9d5871eb595c..c375574f023d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationListener.java
@@ -169,6 +169,5 @@ public class NotificationListener extends NotificationListenerWithPlugins {
public interface NotificationSettingsListener {
default void onStatusBarIconsBehaviorChanged(boolean hideSilentStatusIcons) { }
-
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index d202190724f5..1779b325359e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -294,17 +294,17 @@ public class NotificationShelf extends ActivatableNotificationView implements
int backgroundTop = 0;
int clipTopAmount = 0;
float firstElementRoundness = 0.0f;
- ExpandableNotificationRow previousRow = null;
+ ActivatableNotificationView previousRow = null;
for (int i = 0; i < mHostLayout.getChildCount(); i++) {
ExpandableView child = (ExpandableView) mHostLayout.getChildAt(i);
- if (!(child instanceof ExpandableNotificationRow)
- || child.getVisibility() == GONE) {
+ if (!(child instanceof ActivatableNotificationView)
+ || child.getVisibility() == GONE || child == this) {
continue;
}
- ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+ ActivatableNotificationView row = (ActivatableNotificationView) child;
float notificationClipEnd;
boolean aboveShelf = ViewState.getFinalTranslationZ(row) > baseZHeight
|| row.isPinned();
@@ -324,43 +324,55 @@ public class NotificationShelf extends ActivatableNotificationView implements
}
int clipTop = updateNotificationClipHeight(row, notificationClipEnd, notGoneIndex);
clipTopAmount = Math.max(clipTop, clipTopAmount);
- float inShelfAmount = updateIconAppearance(row, expandAmount, scrolling, scrollingFast,
- expandingAnimated, isLastChild);
- numViewsInShelf += inShelfAmount;
- int ownColorUntinted = row.getBackgroundColorWithoutTint();
- if (rowTranslationY >= shelfStart && mNotGoneIndex == -1) {
- mNotGoneIndex = notGoneIndex;
- setTintColor(previousColor);
- setOverrideTintColor(colorTwoBefore, transitionAmount);
-
- } else if (mNotGoneIndex == -1) {
- colorTwoBefore = previousColor;
- transitionAmount = inShelfAmount;
- }
- if (isLastChild) {
- if (colorOfViewBeforeLast == NO_COLOR) {
+
+ // If the current row is an ExpandableNotificationRow, update its color, roundedness,
+ // and icon state.
+ if (row instanceof ExpandableNotificationRow) {
+ ExpandableNotificationRow expandableRow = (ExpandableNotificationRow) row;
+
+ float inShelfAmount = updateIconAppearance(expandableRow, expandAmount, scrolling,
+ scrollingFast,
+ expandingAnimated, isLastChild);
+ numViewsInShelf += inShelfAmount;
+ int ownColorUntinted = row.getBackgroundColorWithoutTint();
+ if (rowTranslationY >= shelfStart && mNotGoneIndex == -1) {
+ mNotGoneIndex = notGoneIndex;
+ setTintColor(previousColor);
+ setOverrideTintColor(colorTwoBefore, transitionAmount);
+
+ } else if (mNotGoneIndex == -1) {
+ colorTwoBefore = previousColor;
+ transitionAmount = inShelfAmount;
+ }
+ if (isLastChild) {
+ if (colorOfViewBeforeLast == NO_COLOR) {
+ colorOfViewBeforeLast = ownColorUntinted;
+ }
+ row.setOverrideTintColor(colorOfViewBeforeLast, inShelfAmount);
+ } else {
colorOfViewBeforeLast = ownColorUntinted;
+ row.setOverrideTintColor(NO_COLOR, 0 /* overrideAmount */);
}
- row.setOverrideTintColor(colorOfViewBeforeLast, inShelfAmount);
- } else {
- colorOfViewBeforeLast = ownColorUntinted;
- row.setOverrideTintColor(NO_COLOR, 0 /* overrideAmount */);
- }
- if (notGoneIndex != 0 || !aboveShelf) {
- row.setAboveShelf(false);
- }
- if (notGoneIndex == 0) {
- StatusBarIconView icon = row.getEntry().expandedIcon;
- NotificationIconContainer.IconState iconState = getIconState(icon);
- // The icon state might be null in rare cases where the notification is actually
- // added to the layout, but not to the shelf. An example are replied messages, since
- // they don't show up on AOD
- if (iconState != null && iconState.clampedAppearAmount == 1.0f) {
- // only if the first icon is fully in the shelf we want to clip to it!
- backgroundTop = (int) (row.getTranslationY() - getTranslationY());
- firstElementRoundness = row.getCurrentTopRoundness();
+ if (notGoneIndex != 0 || !aboveShelf) {
+ expandableRow.setAboveShelf(false);
}
+ if (notGoneIndex == 0) {
+ StatusBarIconView icon = expandableRow.getEntry().expandedIcon;
+ NotificationIconContainer.IconState iconState = getIconState(icon);
+ // The icon state might be null in rare cases where the notification is actually
+ // added to the layout, but not to the shelf. An example are replied messages,
+ // since they don't show up on AOD
+ if (iconState != null && iconState.clampedAppearAmount == 1.0f) {
+ // only if the first icon is fully in the shelf we want to clip to it!
+ backgroundTop = (int) (row.getTranslationY() - getTranslationY());
+ firstElementRoundness = row.getCurrentTopRoundness();
+ }
+ }
+
+ previousColor = ownColorUntinted;
+ notGoneIndex++;
}
+
if (row.isFirstInSection() && previousRow != null && previousRow.isLastInSection()) {
// If the top of the shelf is between the view before a gap and the view after a gap
// then we need to adjust the shelf's top roundness.
@@ -379,8 +391,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
backgroundTop = (int) distanceToGapBottom;
}
}
- notGoneIndex++;
- previousColor = ownColorUntinted;
previousRow = row;
}
clipTransientViews();
@@ -453,7 +463,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
private void updateContinuousClipping(final ExpandableNotificationRow row) {
StatusBarIconView icon = row.getEntry().expandedIcon;
- boolean needsContinuousClipping = ViewState.isAnimatingY(icon) && !mAmbientState.isDark();
+ boolean needsContinuousClipping = ViewState.isAnimatingY(icon) && !mAmbientState.isDozing();
boolean isContinuousClipping = icon.getTag(TAG_CONTINUOUS_CLIPPING) != null;
if (needsContinuousClipping && !isContinuousClipping) {
final ViewTreeObserver observer = icon.getViewTreeObserver();
@@ -497,7 +507,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
* Update the clipping of this view.
* @return the amount that our own top should be clipped
*/
- private int updateNotificationClipHeight(ExpandableNotificationRow row,
+ private int updateNotificationClipHeight(ActivatableNotificationView row,
float notificationClipEnd, int childIndex) {
float viewEnd = row.getTranslationY() + row.getActualHeight();
boolean isPinned = (row.isPinned() || row.isHeadsUpAnimatingAway())
@@ -829,7 +839,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
private void setOpenedAmount(float openedAmount) {
mNoAnimationsInThisFrame = openedAmount == 1.0f && mOpenedAmount == 0.0f;
mOpenedAmount = openedAmount;
- if (!mAmbientState.isPanelFullWidth() || mAmbientState.isDark()) {
+ if (!mAmbientState.isPanelFullWidth() || mAmbientState.isDozing()) {
// We don't do a transformation at all, lets just assume we are fully opened
openedAmount = 1.0f;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
index a5a6d87c2030..1aa6bc9ae5f9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.notification;
import android.annotation.Nullable;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.StatusBarNotification;
import com.android.internal.statusbar.NotificationVisibility;
@@ -98,4 +100,14 @@ public interface NotificationEntryListener {
@Nullable NotificationVisibility visibility,
boolean removedByUser) {
}
+
+ /**
+ * Called whenever notification ranking changes, in response to
+ * {@link NotificationListenerService#onNotificationRankingUpdate}. This is called after
+ * NotificationData has processed the update and notifications have been re-sorted and filtered.
+ *
+ * @param rankingMap provides access to ranking information on currently active notifications
+ */
+ default void onNotificationRankingUpdated(RankingMap rankingMap) {
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 3ac5768f091a..879a8dfa2875 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -355,10 +355,10 @@ public class NotificationEntryManager implements
// a child we're keeping around for reply!
continue;
}
- entry.setKeepInParent(true);
+ childEntry.setKeepInParent(true);
// we need to set this state earlier as otherwise we might generate some weird
// animations
- entry.removeRow();
+ childEntry.removeRow();
}
}
}
@@ -483,6 +483,10 @@ public class NotificationEntryManager implements
}
updateNotifications();
+
+ for (NotificationEntryListener listener : mNotificationEntryListeners) {
+ listener.onNotificationRankingUpdated(rankingMap);
+ }
}
private void updateRankingOfPendingNotifications(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
index c65e90ea7bea..3613f9f3ea5f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationWakeUpCoordinator.kt
@@ -22,11 +22,12 @@ import android.util.FloatProperty
import com.android.systemui.Interpolators
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.AmbientPulseManager
-import com.android.systemui.statusbar.SysuiStatusBarStateController
+import com.android.systemui.statusbar.StatusBarState
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
import com.android.systemui.statusbar.notification.stack.StackStateAnimator
import com.android.systemui.statusbar.phone.DozeParameters
+import com.android.systemui.statusbar.phone.KeyguardBypassController
import javax.inject.Inject
import javax.inject.Singleton
@@ -35,7 +36,8 @@ import javax.inject.Singleton
class NotificationWakeUpCoordinator @Inject constructor(
private val mContext: Context,
private val mAmbientPulseManager: AmbientPulseManager,
- private val mStatusBarStateController: StatusBarStateController)
+ private val mStatusBarStateController: StatusBarStateController,
+ private val mBypassController: KeyguardBypassController)
: AmbientPulseManager.OnAmbientChangedListener, StatusBarStateController.StateListener {
private val mNotificationVisibility
@@ -65,7 +67,7 @@ class NotificationWakeUpCoordinator @Inject constructor(
private val mDozeParameters: DozeParameters;
var willWakeUp = false
set(value) {
- if (value && mDozeAmount != 0.0f) {
+ if (!value || mDozeAmount != 0.0f) {
field = value
}
}
@@ -137,22 +139,47 @@ class NotificationWakeUpCoordinator @Inject constructor(
}
override fun onDozeAmountChanged(linear: Float, eased: Float) {
+ if (updateDozeAmountIfBypass()) {
+ return
+ }
if (linear != 1.0f && linear != 0.0f
&& (mLinearDozeAmount == 0.0f || mLinearDozeAmount == 1.0f)) {
// Let's notify the scroller that an animation started
notifyAnimationStart(mLinearDozeAmount == 1.0f)
}
+ setDozeAmount(linear, eased)
+ }
+
+ fun setDozeAmount(linear: Float, eased: Float) {
+ val changed = linear != mLinearDozeAmount
mLinearDozeAmount = linear
mDozeAmount = eased
mStackScroller.setDozeAmount(mDozeAmount)
updateDarkAmount()
- if (linear == 0.0f) {
+ if (changed && linear == 0.0f) {
setNotificationsVisible(visible = false, animate = false, increaseSpeed = false);
setNotificationsVisibleForExpansion(visible = false, animate = false,
increaseSpeed = false)
}
}
+ override fun onStateChanged(newState: Int) {
+ updateDozeAmountIfBypass();
+ }
+
+ private fun updateDozeAmountIfBypass(): Boolean {
+ if (mBypassController.bypassEnabled) {
+ var amount = 1.0f;
+ if (mStatusBarStateController.state == StatusBarState.SHADE
+ || mStatusBarStateController.state == StatusBarState.SHADE_LOCKED) {
+ amount = 0.0f;
+ }
+ setDozeAmount(amount, amount)
+ return true
+ }
+ return false
+ }
+
private fun startVisibilityAnimation(increaseSpeed: Boolean) {
if (mNotificationVisibleAmount == 0f || mNotificationVisibleAmount == 1f) {
mVisibilityInterpolator = if (mNotificationsVisible)
@@ -228,7 +255,7 @@ class NotificationWakeUpCoordinator @Inject constructor(
// if we animate, we see the shelf briefly visible. Instead we fully animate
// the notification and its background out
animate = false
- } else {
+ } else if (!mWakingUp && !willWakeUp){
entry.setAmbientGoingAway(true)
mEntrySetToClearWhenFinished.add(entry)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
index 04ff58b36c94..64b2f048ce2e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationData.java
@@ -25,6 +25,7 @@ import android.service.notification.NotificationListenerService.RankingMap;
import android.service.notification.SnoozeCriterion;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
+import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
@@ -69,7 +70,8 @@ public class NotificationData {
mHeadsUpManager = headsUpManager;
}
- private final Comparator<NotificationEntry> mRankingComparator =
+ @VisibleForTesting
+ protected final Comparator<NotificationEntry> mRankingComparator =
new Comparator<NotificationEntry>() {
private final Ranking mRankingA = new Ranking();
private final Ranking mRankingB = new Ranking();
@@ -120,6 +122,8 @@ public class NotificationData {
} else if (aSystemMax != bSystemMax) {
// Upsort PRIORITY_MAX system notifications
return aSystemMax ? -1 : 1;
+ } else if (a.isHighPriority() != b.isHighPriority()) {
+ return -1 * Boolean.compare(a.isHighPriority(), b.isHighPriority());
} else if (aRank != bRank) {
return aRank - bRank;
} else {
@@ -231,17 +235,14 @@ public class NotificationData {
/**
* Returns true if this notification should be displayed in the high-priority notifications
- * section (and on the lockscreen and status bar).
+ * section
*/
public boolean isHighPriority(StatusBarNotification statusBarNotification) {
if (mRankingMap != null) {
getRanking(statusBarNotification.getKey(), mTmpRanking);
if (mTmpRanking.getImportance() >= NotificationManager.IMPORTANCE_DEFAULT
- || isImportantOngoing(statusBarNotification.getNotification())
- || statusBarNotification.getNotification().hasMediaSession()
- || hasPerson(statusBarNotification.getNotification())
- || hasStyle(statusBarNotification.getNotification(),
- Notification.MessagingStyle.class)) {
+ || hasHighPriorityCharacteristics(
+ mTmpRanking.getChannel(), statusBarNotification)) {
return true;
}
if (mGroupManager.isSummaryOfGroup(statusBarNotification)) {
@@ -257,6 +258,25 @@ public class NotificationData {
return false;
}
+ private boolean hasHighPriorityCharacteristics(NotificationChannel channel,
+ StatusBarNotification statusBarNotification) {
+
+ if (isImportantOngoing(statusBarNotification.getNotification())
+ || statusBarNotification.getNotification().hasMediaSession()
+ || hasPerson(statusBarNotification.getNotification())
+ || hasStyle(statusBarNotification.getNotification(),
+ Notification.MessagingStyle.class)) {
+ // Users who have long pressed and demoted to silent should not see the notification
+ // in the top section
+ if (channel != null && channel.hasUserSetImportance()) {
+ return false;
+ }
+ return true;
+ }
+
+ return false;
+ }
+
private boolean isImportantOngoing(Notification notification) {
return notification.isForegroundService()
&& mTmpRanking.getImportance() >= NotificationManager.IMPORTANCE_LOW;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index a3e18efa1915..92c261c4cad7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -122,7 +122,6 @@ public final class NotificationEntry {
public boolean suspended;
private NotificationEntry parent; // our parent (if we're in a group)
- private ArrayList<NotificationEntry> children = new ArrayList<NotificationEntry>();
private ExpandableNotificationRow row; // the outer expanded view
private int mCachedContrastColor = COLOR_INVALID;
@@ -277,10 +276,20 @@ public final class NotificationEntry {
@Nullable
public List<NotificationEntry> getChildren() {
- if (children.size() <= 0) {
+ if (row == null) {
return null;
}
+ List<ExpandableNotificationRow> rowChildren = row.getNotificationChildren();
+ if (rowChildren == null) {
+ return null;
+ }
+
+ ArrayList<NotificationEntry> children = new ArrayList<>();
+ for (ExpandableNotificationRow child : rowChildren) {
+ children.add(child.getEntry());
+ }
+
return children;
}
@@ -740,7 +749,9 @@ public final class NotificationEntry {
if (notification == null || !notification.isClearable()) {
return false;
}
- if (children.size() > 0) {
+
+ List<NotificationEntry> children = getChildren();
+ if (children != null && children.size() > 0) {
for (int i = 0; i < children.size(); i++) {
NotificationEntry child = children.get(i);
if (!child.isClearable()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ButtonLinearLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ButtonLinearLayout.java
new file mode 100644
index 000000000000..94bdd81401bb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ButtonLinearLayout.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.row;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.Button;
+import android.widget.LinearLayout;
+
+public class ButtonLinearLayout extends LinearLayout {
+
+ public ButtonLinearLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ public CharSequence getAccessibilityClassName() {
+ return Button.class.getName();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt
index b89b5cb34d7a..83a4319fd24c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorDialogController.kt
@@ -223,6 +223,8 @@ class ChannelEditorDialogController @Inject constructor(
dialog = Dialog(context)
dialog.window?.requestFeature(Window.FEATURE_NO_TITLE)
+ // Prevent a11y readers from reading the first element in the dialog twice
+ dialog.setTitle("\u00A0")
dialog.apply {
setContentView(R.layout.notif_half_shelf)
setCanceledOnTouchOutside(true)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt
index 4d4976085ba9..6fe14777e41f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ChannelEditorListView.kt
@@ -143,7 +143,7 @@ class ChannelRow(c: Context, attrs: AttributeSet) : LinearLayout(c, attrs) {
private fun updateViews() {
val nc = channel ?: return
- channelName.text = nc.name ?: "(missing)"
+ channelName.text = nc.name ?: ""
nc.group?.let { groupId ->
channelDescription.text = controller.groupNameForId(groupId)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index dbc9a8b9c21d..d625b318487d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -648,6 +648,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
if (!getShowingLayout().isDimmable()) {
return false;
}
+ if (showingAmbientPulsing()) {
+ return false;
+ }
return super.isDimmable();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
index ecbb2161a0cf..d911e1a05029 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.notification.row;
+import static android.provider.Settings.Secure.SHOW_NOTIFICATION_SNOOZE;
+
import static com.android.systemui.SwipeHelper.SWIPED_FAR_ENOUGH_SIZE_FRACTION;
import android.animation.Animator;
@@ -29,6 +31,7 @@ import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
+import android.provider.Settings;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
import android.view.LayoutInflater;
@@ -255,9 +258,13 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
mVertSpaceForIcons = res.getDimensionPixelSize(R.dimen.notification_min_height);
mLeftMenuItems.clear();
mRightMenuItems.clear();
+
+ boolean showSnooze = Settings.Secure.getInt(mContext.getContentResolver(),
+ SHOW_NOTIFICATION_SNOOZE, 0) == 1;
+
// Construct the menu items based on the notification
- if (!isForeground) {
- // Only show snooze for non-foreground notifications
+ if (!isForeground && showSnooze) {
+ // Only show snooze for non-foreground notifications, and if the setting is on
mSnoozeItem = createSnoozeItem(mContext);
}
mAppOpsItem = createAppOpsItem(mContext);
@@ -268,7 +275,7 @@ public class NotificationMenuRow implements NotificationMenuRowPlugin, View.OnCl
}
if (!mIsUsingBidirectionalSwipe) {
- if (!isForeground) {
+ if (!isForeground && showSnooze) {
mRightMenuItems.add(mSnoozeItem);
}
mRightMenuItems.add(mInfoItem);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
index 91c43a142db5..4526eafe8ab5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapper.java
@@ -25,6 +25,7 @@ import android.media.MediaMetadata;
import android.media.session.MediaController;
import android.media.session.MediaSession;
import android.media.session.PlaybackState;
+import android.metrics.LogMaker;
import android.os.Handler;
import android.text.format.DateUtils;
import android.util.Log;
@@ -35,6 +36,9 @@ import android.widget.SeekBar;
import android.widget.TextView;
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;
import com.android.systemui.Dependency;
import com.android.systemui.statusbar.NotificationMediaManager;
import com.android.systemui.statusbar.TransformableView;
@@ -62,8 +66,11 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi
private NotificationMediaManager mMediaManager;
private View mSeekBarView;
private Context mContext;
+ private MetricsLogger mMetricsLogger;
- private SeekBar.OnSeekBarChangeListener mSeekListener = new SeekBar.OnSeekBarChangeListener() {
+ @VisibleForTesting
+ protected SeekBar.OnSeekBarChangeListener mSeekListener =
+ new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
@@ -76,6 +83,7 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi
public void onStopTrackingTouch(SeekBar seekBar) {
if (mMediaController != null && canSeekMedia()) {
mMediaController.getTransportControls().seekTo(mSeekBar.getProgress());
+ mMetricsLogger.write(newLog(MetricsEvent.TYPE_UPDATE));
}
}
};
@@ -93,7 +101,8 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi
// Update the UI once, in case playback info changed while we were paused
mUpdatePlaybackUi.run();
clearTimer();
- } else if (mSeekBarTimer == null) {
+ } else if (mSeekBarTimer == null && mSeekBarView != null
+ && mSeekBarView.getVisibility() != View.GONE) {
startTimer();
}
}
@@ -104,6 +113,7 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi
super(ctx, view, row);
mContext = ctx;
mMediaManager = Dependency.get(NotificationMediaManager.class);
+ mMetricsLogger = Dependency.get(MetricsLogger.class);
}
private void resolveViews() {
@@ -121,11 +131,13 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi
}
// Check for existing media controller and clean up / create as necessary
+ boolean controllerUpdated = false;
if (mMediaController == null || !mMediaController.getSessionToken().equals(token)) {
if (mMediaController != null) {
mMediaController.unregisterCallback(mMediaCallback);
}
mMediaController = new MediaController(mContext, token);
+ controllerUpdated = true;
}
if (mMediaController.getMetadata() != null) {
@@ -134,14 +146,21 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi
if (duration <= 0) {
// Don't include the seekbar if this is a livestream
Log.d(TAG, "removing seekbar");
- if (mSeekBarView != null) {
+ if (mSeekBarView != null && mSeekBarView.getVisibility() != View.GONE) {
mSeekBarView.setVisibility(View.GONE);
+ mMetricsLogger.write(newLog(MetricsEvent.TYPE_CLOSE));
+ clearTimer();
+ } else if (mSeekBarView == null && controllerUpdated) {
+ // Only log if the controller changed, otherwise we would log multiple times for
+ // the same notification when user pauses/resumes
+ mMetricsLogger.write(newLog(MetricsEvent.TYPE_CLOSE));
}
return;
} else {
// Otherwise, make sure the seekbar is visible
- if (mSeekBarView != null) {
+ if (mSeekBarView != null && mSeekBarView.getVisibility() == View.GONE) {
mSeekBarView.setVisibility(View.VISIBLE);
+ mMetricsLogger.write(newLog(MetricsEvent.TYPE_OPEN));
}
}
}
@@ -153,6 +172,7 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi
stub.setLayoutInflater(layoutInflater);
stub.setLayoutResource(R.layout.notification_material_media_seekbar);
mSeekBarView = stub.inflate();
+ mMetricsLogger.write(newLog(MetricsEvent.TYPE_OPEN));
mSeekBar = mSeekBarView.findViewById(R.id.notification_media_progress_bar);
mSeekBar.setOnSeekBarChangeListener(mSeekListener);
@@ -161,17 +181,14 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi
mSeekBarTotalTime = mSeekBarView.findViewById(R.id.notification_media_total_time);
if (mSeekBarTimer == null) {
- // Disable seeking if it is not supported for this media session
- if (!canSeekMedia()) {
- mSeekBar.getThumb().setAlpha(0);
- mSeekBar.setEnabled(false);
+ if (canSeekMedia()) {
+ // Log initial state, since it will not be updated
+ mMetricsLogger.write(newLog(MetricsEvent.TYPE_DETAIL, 1));
} else {
- mSeekBar.getThumb().setAlpha(255);
- mSeekBar.setEnabled(true);
+ setScrubberVisible(false);
}
startTimer();
-
mMediaController.registerCallback(mMediaCallback);
}
}
@@ -209,6 +226,16 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi
return ((actions & PlaybackState.ACTION_SEEK_TO) != 0);
}
+ private void setScrubberVisible(boolean isVisible) {
+ if (mSeekBar == null || mSeekBar.isEnabled() == isVisible) {
+ return;
+ }
+
+ mSeekBar.getThumb().setAlpha(isVisible ? 255 : 0);
+ mSeekBar.setEnabled(isVisible);
+ mMetricsLogger.write(newLog(MetricsEvent.TYPE_DETAIL, isVisible ? 1 : 0));
+ }
+
protected final Runnable mUpdatePlaybackUi = new Runnable() {
@Override
public void run() {
@@ -228,6 +255,9 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi
mSeekBar.setProgress((int) position);
mSeekBarElapsedTime.setText(millisecondsToTimeString(position));
+
+ // Update scrubber in case available actions have changed
+ setScrubberVisible(canSeekMedia());
} else {
Log.d(TAG, "Controller missing data " + metadata + " " + playbackState);
clearTimer();
@@ -265,6 +295,7 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi
int tintColor = getNotificationHeader().getOriginalIconColor();
mSeekBarElapsedTime.setTextColor(tintColor);
mSeekBarTotalTime.setTextColor(tintColor);
+ mSeekBarTotalTime.setShadowLayer(1.5f, 1.5f, 1.5f, mBackgroundColor);
ColorStateList tintList = ColorStateList.valueOf(tintColor);
mSeekBar.setThumbTintList(tintList);
@@ -293,4 +324,28 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi
public boolean shouldClipToRounding(boolean topRounded, boolean bottomRounded) {
return true;
}
+
+ /**
+ * Returns an initialized LogMaker for logging changes to the seekbar
+ * @return new LogMaker
+ */
+ private LogMaker newLog(int event) {
+ String packageName = mRow.getEntry().notification.getPackageName();
+
+ return new LogMaker(MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR)
+ .setType(event)
+ .setPackageName(packageName);
+ }
+
+ /**
+ * Returns an initialized LogMaker for logging changes with subtypes
+ * @return new LogMaker
+ */
+ private LogMaker newLog(int event, int subtype) {
+ String packageName = mRow.getEntry().notification.getPackageName();
+ return new LogMaker(MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR)
+ .setType(event)
+ .setSubtype(subtype)
+ .setPackageName(packageName);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
index e5fbf6396667..d9162c0d6071 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/AmbientState.java
@@ -52,7 +52,7 @@ public class AmbientState {
private float mOverScrollTopAmount;
private float mOverScrollBottomAmount;
private int mSpeedBumpIndex = -1;
- private boolean mDark;
+ private boolean mDozing;
private boolean mHideSensitive;
private AmbientPulseManager mAmbientPulseManager = Dependency.get(AmbientPulseManager.class);
private float mStackTranslation;
@@ -181,8 +181,8 @@ public class AmbientState {
}
/** In dark mode, we draw as little as possible, assuming a black background */
- public void setDark(boolean dark) {
- mDark = dark;
+ public void setDozing(boolean dozing) {
+ mDozing = dozing;
}
/** Dark ratio of the status bar **/
@@ -212,11 +212,13 @@ public class AmbientState {
}
public boolean isDimmed() {
- return mDimmed;
+ // While we are expanding from pulse, we want the notifications not to be dimmed, otherwise
+ // you'd see the difference to the pulsing notification
+ return mDimmed && !(isPulseExpanding() && mDozeAmount == 1.0f);
}
- public boolean isDark() {
- return mDark;
+ public boolean isDozing() {
+ return mDozing;
}
public boolean isHideSensitive() {
@@ -459,7 +461,7 @@ public class AmbientState {
* @return whether a row is dozing and not pulsing right now
*/
public boolean isDozingAndNotPulsing(ExpandableNotificationRow row) {
- return isDark() && !isPulsing(row.getEntry());
+ return isDozing() && !isPulsing(row.getEntry());
}
public void setExpandAnimationTopChange(int expandAnimationTopChange) {
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 dccf404f0483..6ce604b8f36d 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
@@ -770,7 +770,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
if (mShouldDrawNotificationBackground
&& (mSections[0].getCurrentBounds().top
< mSections[NUM_SECTIONS - 1].getCurrentBounds().bottom
- || mAmbientState.isDark())) {
+ || mAmbientState.isDozing())) {
drawBackground(canvas);
} else if (mInHeadsUpPinnedMode || mHeadsUpAnimatingAway) {
drawHeadsUpBackground(canvas);
@@ -804,7 +804,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
canvas.drawLine(0, y, getWidth(), y, mDebugPaint);
}
canvas.drawText(Integer.toString(getMaxNegativeScrollAmount()), getWidth() - 100,
- getIntrinsicPadding() + 30, mDebugPaint);
+ getTopPadding() + 30, mDebugPaint);
canvas.drawText(Integer.toString(getMaxPositiveScrollAmount()), getWidth() - 100,
getHeight() - 30, mDebugPaint);
}
@@ -842,7 +842,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
break;
}
}
- if (!mAmbientState.isDark() || anySectionHasVisibleChild) {
+ if (!mAmbientState.isDozing() || anySectionHasVisibleChild) {
drawBackgroundRects(canvas, left, right, top, backgroundTopAnimationOffset);
}
@@ -939,18 +939,11 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
return;
}
- float alpha =
- BACKGROUND_ALPHA_DIMMED + (1 - BACKGROUND_ALPHA_DIMMED) * (1.0f - mDimAmount);
- alpha *= 1f - mInterpolatedDarkAmount;
- // We need to manually blend in the background color.
- int scrimColor = mScrimController.getBackgroundColor();
- int awakeColor = ColorUtils.blendARGB(scrimColor, mBgColor, alpha);
-
// Interpolate between semi-transparent notification panel background color
// and white AOD separator.
float colorInterpolation = MathUtils.smoothStep(0.4f /* start */, 1f /* end */,
mLinearDarkAmount);
- int color = ColorUtils.blendARGB(awakeColor, Color.WHITE, colorInterpolation);
+ int color = ColorUtils.blendARGB(mBgColor, Color.WHITE, colorInterpolation);
if (mCachedBackgroundColor != color) {
mCachedBackgroundColor = color;
@@ -1438,7 +1431,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
int notGoneChildCount = getNotGoneChildCount();
if (mEmptyShadeView.getVisibility() == GONE && notGoneChildCount != 0) {
if (isHeadsUpTransition()
- || (mHeadsUpManager.hasPinnedHeadsUp() && !mAmbientState.isDark())) {
+ || (mHeadsUpManager.hasPinnedHeadsUp() && !mAmbientState.isDozing())) {
appearPosition = getTopHeadsUpPinnedHeight();
} else {
appearPosition = 0;
@@ -2403,7 +2396,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
mIntrinsicContentHeight = height;
- mContentHeight = height + mTopPadding + mBottomMargin;
+ // The topPadding can be bigger than the regular padding when qs is expanded, in that
+ // state the maxPanelHeight and the contentHeight should be bigger
+ mContentHeight = height + Math.max(mIntrinsicPadding, mTopPadding) + mBottomMargin;
updateScrollability();
clampScrollPosition();
mAmbientState.setLayoutMaxHeight(mContentHeight);
@@ -2783,12 +2778,9 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
*
* @param qsHeight the top padding imposed by the quick settings panel
* @param animate whether to animate the change
- * @param ignoreIntrinsicPadding if true, {@link #getIntrinsicPadding()} is ignored and
- * {@code qsHeight} is the final top padding
*/
@ShadeViewRefactor(RefactorComponent.COORDINATOR)
- public void updateTopPadding(float qsHeight, boolean animate,
- boolean ignoreIntrinsicPadding) {
+ public void updateTopPadding(float qsHeight, boolean animate) {
int topPadding = (int) qsHeight;
int minStackHeight = getLayoutMinHeight();
if (topPadding + minStackHeight > getHeight()) {
@@ -2796,8 +2788,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
} else {
mTopPaddingOverflow = 0;
}
- setTopPadding(ignoreIntrinsicPadding ? topPadding : clampPadding(topPadding),
- animate);
+ setTopPadding(topPadding, animate);
setExpandedHeight(mExpandedHeight);
}
@@ -3532,7 +3523,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
private void generateTopPaddingEvent() {
if (mTopPaddingNeedsAnimation) {
AnimationEvent event;
- if (mAmbientState.isDark()) {
+ if (mAmbientState.isDozing()) {
event = new AnimationEvent(null /* view */,
AnimationEvent.ANIMATION_TYPE_TOP_PADDING_CHANGED,
KeyguardSliceView.DEFAULT_ANIM_DURATION);
@@ -4712,21 +4703,19 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
}
/**
- * See {@link AmbientState#setDark}.
+ * See {@link AmbientState#setDozing}.
*/
@ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
- public void setDark(boolean dark, boolean animate, @Nullable PointF touchWakeUpScreenLocation) {
- if (mAmbientState.isDark() == dark) {
+ public void setDozing(boolean dozing, boolean animate,
+ @Nullable PointF touchWakeUpScreenLocation) {
+ if (mAmbientState.isDozing() == dozing) {
return;
}
- mAmbientState.setDark(dark);
+ mAmbientState.setDozing(dozing);
if (animate && mAnimationsEnabled) {
mDarkNeedsAnimation = true;
mDarkAnimationOriginIndex = findDarkAnimationOriginIndex(touchWakeUpScreenLocation);
mNeedsAnimation = true;
- } else {
- setDarkAmount(dark ? 1f : 0f);
- updateBackground();
}
requestChildrenUpdate();
updateWillNotDraw();
@@ -5709,6 +5698,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
view.setTranslationY(wakeUplocation);
}
}
+ mDimmedNeedsAnimation = true;
}
@Override
@@ -6348,7 +6338,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
(int) (dragLengthY / mDisplayMetrics.density),
0 /* velocityDp - N/A */);
- if (!mAmbientState.isDark() || startingChild != null) {
+ if (!mAmbientState.isDozing() || startingChild != null) {
// We have notifications, go to locked shade.
mShadeController.goToLockedShade(startingChild);
if (startingChild instanceof ExpandableNotificationRow) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 60061c6a9ad2..2980ee4ac45e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -255,7 +255,7 @@ public class StackScrollAlgorithm {
state.paddingMap.clear();
int notGoneIndex = 0;
ExpandableView lastView = null;
- int firstHiddenIndex = ambientState.isDark()
+ int firstHiddenIndex = ambientState.isDozing()
? (ambientState.hasPulsingNotifications() ? 1 : 0)
: childCount;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 6159f6ca7d1e..d67795210f0c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -23,7 +23,6 @@ import android.os.Handler;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.Trace;
-import android.provider.Settings;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -34,7 +33,6 @@ import com.android.keyguard.KeyguardConstants;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.Dependency;
-import com.android.systemui.R;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.ScreenLifecycle;
import com.android.systemui.keyguard.WakefulnessLifecycle;
@@ -272,7 +270,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback {
Trace.endSection();
};
- if (!delayWakeUp) {
+ if (!delayWakeUp && mMode != MODE_NONE) {
wakeUp.run();
}
switch (mMode) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index f2218651d7c7..05a86fa9d7ea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -33,13 +33,14 @@ import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;
import android.util.MathUtils;
-import android.view.Choreographer;
import android.view.Gravity;
import android.view.IPinnedStackController;
import android.view.IPinnedStackListener;
import android.view.ISystemGestureExclusionListener;
+import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputEvent;
+import android.view.InputEventReceiver;
import android.view.InputMonitor;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
@@ -53,7 +54,6 @@ import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.recents.OverviewProxyService;
-import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver;
import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.WindowManagerWrapper;
@@ -165,12 +165,14 @@ public class EdgeBackGestureHandler implements DisplayListener {
mEdgeWidth = res.getDimensionPixelSize(
com.android.internal.R.dimen.config_backGestureInset);
- mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+ // Reduce the default touch slop to ensure that we can intercept the gesture
+ // before the app starts to react to it.
+ // TODO(b/130352502) Tune this value and extract into a constant
+ mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop() * 0.75f;
mLongPressTimeout = ViewConfiguration.getLongPressTimeout();
mNavBarHeight = res.getDimensionPixelSize(R.dimen.navigation_bar_frame_height);
- mMinArrowPosition = res.getDimensionPixelSize(
- R.dimen.navigation_edge_arrow_min_y);
+ mMinArrowPosition = res.getDimensionPixelSize(R.dimen.navigation_edge_arrow_min_y);
mFingerOffset = res.getDimensionPixelSize(R.dimen.navigation_edge_finger_offset);
}
@@ -250,9 +252,8 @@ public class EdgeBackGestureHandler implements DisplayListener {
// Register input event receiver
mInputMonitor = InputManager.getInstance().monitorGestureInput(
"edge-swipe", mDisplayId);
- mInputEventReceiver = new InputEventReceiver(mInputMonitor.getInputChannel(),
- Looper.getMainLooper(), Choreographer.getMainThreadInstance(),
- this::onInputEvent);
+ mInputEventReceiver = new SysUiInputEventReceiver(
+ mInputMonitor.getInputChannel(), Looper.getMainLooper());
// Add a nav bar panel window
mEdgePanel = new NavigationBarEdgePanel(mContext);
@@ -440,4 +441,15 @@ public class EdgeBackGestureHandler implements DisplayListener {
}
InputManager.getInstance().injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
}
+
+ class SysUiInputEventReceiver extends InputEventReceiver {
+ SysUiInputEventReceiver(InputChannel channel, Looper looper) {
+ super(channel, looper);
+ }
+
+ public void onInputEvent(InputEvent event) {
+ EdgeBackGestureHandler.this.onInputEvent(event);
+ finishInputEvent(event, true);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
index 215aa77920d9..a4965ba59c6a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FloatingRotationButton.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.phone;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.view.ContextThemeWrapper;
import android.view.Gravity;
@@ -35,6 +36,8 @@ public class FloatingRotationButton implements RotationButton {
private final Context mContext;
private final WindowManager mWindowManager;
private final KeyButtonView mKeyButtonView;
+ private final int mDiameter;
+ private final int mMargin;
private KeyButtonDrawable mKeyButtonDrawable;
private boolean mIsShowing;
private boolean mCanShow = true;
@@ -46,6 +49,12 @@ public class FloatingRotationButton implements RotationButton {
mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
mKeyButtonView = (KeyButtonView) LayoutInflater.from(mContext).inflate(
R.layout.rotate_suggestion, null);
+ mKeyButtonView.setVisibility(View.VISIBLE);
+
+ Resources res = mContext.getResources();
+ mDiameter = res.getDimensionPixelSize(R.dimen.floating_rotation_button_diameter);
+ mMargin = Math.max(res.getDimensionPixelSize(R.dimen.floating_rotation_button_min_margin),
+ res.getDimensionPixelSize(R.dimen.rounded_corner_content_padding));
}
@Override
@@ -66,11 +75,8 @@ public class FloatingRotationButton implements RotationButton {
mIsShowing = true;
int flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
- float density = mContext.getResources().getDisplayMetrics().density;
- int diameter = (int) density * 48;
- int margin = (int) density * 4;
- final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(diameter, diameter,
- margin, margin, WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, flags,
+ final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(mDiameter, mDiameter,
+ mMargin, mMargin, WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL, flags,
PixelFormat.TRANSLUCENT);
lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
lp.setTitle("FloatingRotationButton");
@@ -131,7 +137,10 @@ public class FloatingRotationButton implements RotationButton {
@Override
public void setOnClickListener(View.OnClickListener onClickListener) {
- mKeyButtonView.setOnClickListener(onClickListener);
+ mKeyButtonView.setOnClickListener(view -> {
+ hide();
+ onClickListener.onClick(view);
+ });
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index b7a154d67c10..a0cda693822f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -22,8 +22,6 @@ import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Rect;
-import android.graphics.Region;
-import android.graphics.Region.Op;
import android.util.Log;
import android.util.Pools;
import android.view.DisplayCutout;
@@ -78,6 +76,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
private int[] mTmpTwoArray = new int[2];
private boolean mHeadsUpGoingAway;
private int mStatusBarState;
+ private Rect mTouchableRegion = new Rect();
private AnimationStateHandler mAnimationStateHandler;
@@ -297,10 +296,13 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
@Nullable
public void updateTouchableRegion(ViewTreeObserver.InternalInsetsInfo info) {
info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
+ info.touchableRegion.set(calculateTouchableRegion());
+ }
+ public Rect calculateTouchableRegion() {
if (!hasPinnedHeadsUp()) {
- info.touchableRegion.set(0, 0, mStatusBarWindowView.getWidth(), mStatusBarHeight);
- updateRegionForNotch(info.touchableRegion);
+ mTouchableRegion.set(0, 0, mStatusBarWindowView.getWidth(), mStatusBarHeight);
+ updateRegionForNotch(mTouchableRegion);
} else {
NotificationEntry topEntry = getTopEntry();
if (topEntry.isChildInGroup()) {
@@ -315,11 +317,12 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
int minX = mTmpTwoArray[0];
int maxX = mTmpTwoArray[0] + topRow.getWidth();
int height = topRow.getIntrinsicHeight();
- info.touchableRegion.set(minX, 0, maxX, mHeadsUpInset + height);
+ mTouchableRegion.set(minX, 0, maxX, mHeadsUpInset + height);
}
+ return mTouchableRegion;
}
- private void updateRegionForNotch(Region region) {
+ private void updateRegionForNotch(Rect region) {
DisplayCutout cutout = mStatusBarWindowView.getRootWindowInsets().getDisplayCutout();
if (cutout == null) {
return;
@@ -330,7 +333,7 @@ public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
Rect bounds = new Rect();
ScreenDecorations.DisplayCutoutView.boundsFromDirection(cutout, Gravity.TOP, bounds);
bounds.offset(0, mDisplayCutoutTouchableRegionSize);
- region.op(bounds, Op.UNION);
+ region.union(bounds);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index bbae62e935c5..0b994ff46f29 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -285,8 +285,6 @@ public class KeyguardBouncer {
}
public void hide(boolean destroyView) {
- // TODO(b/113914868): investigation log for disappearing home button
- Log.i(TAG, "KeyguardBouncer.hide (b/113914868): destroyView=" + destroyView);
if (isShowing()) {
StatsLog.write(StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED,
StatsLog.KEYGUARD_BOUNCER_STATE_CHANGED__STATE__HIDDEN);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
index 5b5eb767e184..5abf39e781f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
@@ -17,10 +17,10 @@
package com.android.systemui.statusbar.phone
import android.content.Context
+import android.hardware.face.FaceManager
import android.provider.Settings
import com.android.internal.annotations.VisibleForTesting
import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.systemui.R
import com.android.systemui.tuner.TunerService
import javax.inject.Inject
@@ -32,8 +32,13 @@ class KeyguardBypassController {
@Inject
constructor(context: Context,
tunerService: TunerService) {
- val dismissByDefault = if (context.getResources().getBoolean(
- R.bool.config_faceAuthDismissesKeyguard)) 1 else 0
+ val faceManager = context.getSystemService(FaceManager::class.java)
+ if (faceManager?.isHardwareDetected != true) {
+ return
+ }
+
+ val dismissByDefault = if (context.resources.getBoolean(
+ com.android.internal.R.bool.config_faceAuthDismissesKeyguard)) 1 else 0
tunerService.addTunable(
object : TunerService.Tunable {
override fun onTuningChanged(key: String?, newValue: String?) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index bc2d00f53186..579d1abe7650 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -112,6 +112,12 @@ public class KeyguardClockPositionAlgorithm {
private float mEmptyDragAmount;
/**
+ * If true the clock should always be positioned like it's dark. Used in the bypass, where
+ * notifications don't expand on the lock screen and should be kept stable
+ */
+ private boolean mPositionLikeDark;
+
+ /**
* Refreshes the dimension values.
*/
public void loadDimens(Resources res) {
@@ -132,7 +138,8 @@ public class KeyguardClockPositionAlgorithm {
public void setup(int minTopMargin, int maxShadeBottom, int notificationStackHeight,
float panelExpansion, int parentHeight, int keyguardStatusHeight, int clockPreferredY,
- boolean hasCustomClock, boolean hasVisibleNotifs, float dark, float emptyDragAmount) {
+ boolean hasCustomClock, boolean hasVisibleNotifs, float dark, float emptyDragAmount,
+ boolean positionLikeDark) {
mMinTopMargin = minTopMargin + mContainerTopPadding;
mMaxShadeBottom = maxShadeBottom;
mNotificationStackHeight = notificationStackHeight;
@@ -144,13 +151,15 @@ public class KeyguardClockPositionAlgorithm {
mHasVisibleNotifs = hasVisibleNotifs;
mDarkAmount = dark;
mEmptyDragAmount = emptyDragAmount;
+ mPositionLikeDark = positionLikeDark;
}
public void run(Result result) {
- final int y = getClockY();
+ final int y = getClockY(mPanelExpansion);
result.clockY = y;
result.clockAlpha = getClockAlpha(y);
result.stackScrollerPadding = y + mKeyguardStatusHeight;
+ result.stackScrollerPaddingExpanded = getClockY(1.0f) + mKeyguardStatusHeight;
result.clockX = (int) interpolate(0, burnInPreventionOffsetX(), mDarkAmount);
}
@@ -195,7 +204,7 @@ public class KeyguardClockPositionAlgorithm {
return (int) y;
}
- private int getClockY() {
+ private int getClockY(float panelExpansion) {
// Dark: Align the bottom edge of the clock at about half of the screen:
float clockYDark = (mHasCustomClock ? getPreferredClockY() : getMaxClockY())
+ burnInPreventionOffsetY();
@@ -205,11 +214,12 @@ public class KeyguardClockPositionAlgorithm {
float clockYBouncer = -mKeyguardStatusHeight;
// Move clock up while collapsing the shade
- float shadeExpansion = Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(mPanelExpansion);
+ float shadeExpansion = Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(panelExpansion);
float clockY = MathUtils.lerp(clockYBouncer, clockYRegular, shadeExpansion);
clockYDark = MathUtils.lerp(clockYBouncer, clockYDark, shadeExpansion);
- return (int) (MathUtils.lerp(clockY, clockYDark, mDarkAmount) + mEmptyDragAmount);
+ float darkAmount = mPositionLikeDark ? 1.0f : mDarkAmount;
+ return (int) (MathUtils.lerp(clockY, clockYDark, darkAmount) + mEmptyDragAmount);
}
/**
@@ -257,5 +267,10 @@ public class KeyguardClockPositionAlgorithm {
* The top padding of the stack scroller, in pixels.
*/
public int stackScrollerPadding;
+
+ /**
+ * The top padding of the stack scroller, in pixels when fully expanded.
+ */
+ public int stackScrollerPaddingExpanded;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index 61a394092761..3143971241d8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -19,6 +19,7 @@ package com.android.systemui.statusbar.phone;
import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
+import android.annotation.IntDef;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
@@ -30,6 +31,8 @@ import android.graphics.drawable.Drawable;
import android.hardware.biometrics.BiometricSourceType;
import android.os.Handler;
import android.os.Trace;
+import android.provider.Settings;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -50,6 +53,9 @@ import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
import javax.inject.Inject;
import javax.inject.Named;
@@ -84,11 +90,9 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
private int mDensity;
private boolean mPulsing;
private boolean mDozing;
- private boolean mBouncerVisible;
private boolean mDocked;
private boolean mLastDozing;
private boolean mLastPulsing;
- private boolean mLastBouncerVisible;
private int mIconColor;
private float mDozeAmount;
private int mIconRes;
@@ -246,12 +250,12 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
int state = getState();
mIsFaceUnlockState = state == STATE_SCANNING_FACE;
if (state != mLastState || mLastDozing != mDozing || mLastPulsing != mPulsing
- || mLastScreenOn != mScreenOn || mLastBouncerVisible != mBouncerVisible || force) {
- int iconAnimRes = getAnimationResForTransition(mLastState, state, mLastPulsing,
- mPulsing, mLastDozing, mDozing, mBouncerVisible);
- boolean isAnim = iconAnimRes != -1;
+ || mLastScreenOn != mScreenOn || force) {
+ @LockAnimIndex final int lockAnimIndex = getAnimationIndexForTransition(mLastState,
+ state, mLastPulsing, mPulsing, mLastDozing, mDozing);
+ boolean isAnim = lockAnimIndex != -1;
- int iconRes = isAnim ? iconAnimRes : getIconForState(state);
+ int iconRes = isAnim ? getThemedAnimationResId(lockAnimIndex) : getIconForState(state);
if (iconRes != mIconRes) {
mIconRes = iconRes;
@@ -272,7 +276,7 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
@Override
public void onAnimationEnd(Drawable drawable) {
if (getDrawable() == animation && state == getState()
- && doesAnimationLoop(iconAnimRes)) {
+ && doesAnimationLoop(lockAnimIndex)) {
animation.start();
} else {
Trace.endAsyncSection("LockIcon#Animation", state);
@@ -296,7 +300,6 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
mLastScreenOn = mScreenOn;
mLastDozing = mDozing;
mLastPulsing = mPulsing;
- mLastBouncerVisible = mBouncerVisible;
}
boolean onAodNotPulsingOrDocked = mDozing && (!mPulsing || mDocked);
@@ -360,13 +363,12 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
return iconRes;
}
- private boolean doesAnimationLoop(int resourceId) {
- return resourceId == com.android.internal.R.anim.lock_scanning;
+ private boolean doesAnimationLoop(@LockAnimIndex int lockAnimIndex) {
+ return lockAnimIndex == SCANNING;
}
- private int getAnimationResForTransition(int oldState, int newState,
- boolean wasPulsing, boolean pulsing, boolean wasDozing, boolean dozing,
- boolean bouncerVisible) {
+ private int getAnimationIndexForTransition(int oldState, int newState,
+ boolean wasPulsing, boolean pulsing, boolean wasDozing, boolean dozing) {
// Never animate when screen is off
if (dozing && !pulsing && !mWasPulsingOnThisFrame) {
@@ -380,19 +382,68 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
boolean turningOn = wasDozing && !dozing && !mWasPulsingOnThisFrame;
if (isError) {
- return com.android.internal.R.anim.lock_to_error;
+ return ERROR;
} else if (justUnlocked) {
- return com.android.internal.R.anim.lock_unlock;
+ return UNLOCK;
} else if (justLocked) {
- return com.android.internal.R.anim.lock_lock;
- } else if (newState == STATE_SCANNING_FACE && bouncerVisible) {
- return com.android.internal.R.anim.lock_scanning;
+ return LOCK;
+ } else if (newState == STATE_SCANNING_FACE) {
+ return SCANNING;
} else if ((nowPulsing || turningOn) && newState != STATE_LOCK_OPEN) {
- return com.android.internal.R.anim.lock_in;
+ return LOCK_IN;
}
return -1;
}
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({ERROR, UNLOCK, LOCK, SCANNING, LOCK_IN})
+ @interface LockAnimIndex {}
+ private static final int ERROR = 0, UNLOCK = 1, LOCK = 2, SCANNING = 3, LOCK_IN = 4;
+ private static final int[][] LOCK_ANIM_RES_IDS = new int[][] {
+ {
+ R.anim.lock_to_error,
+ R.anim.lock_unlock,
+ R.anim.lock_lock,
+ R.anim.lock_scanning,
+ R.anim.lock_in,
+ },
+ {
+ R.anim.lock_to_error_circular,
+ R.anim.lock_unlock_circular,
+ R.anim.lock_lock_circular,
+ R.anim.lock_scanning_circular,
+ R.anim.lock_in_circular,
+ },
+ {
+ R.anim.lock_to_error_filled,
+ R.anim.lock_unlock_filled,
+ R.anim.lock_lock_filled,
+ R.anim.lock_scanning_filled,
+ R.anim.lock_in_filled,
+ },
+ {
+ R.anim.lock_to_error_rounded,
+ R.anim.lock_unlock_rounded,
+ R.anim.lock_lock_rounded,
+ R.anim.lock_scanning_rounded,
+ R.anim.lock_in_rounded,
+ },
+ };
+
+ private int getThemedAnimationResId(@LockAnimIndex int lockAnimIndex) {
+ final String setting = TextUtils.emptyIfNull(
+ Settings.Secure.getString(getContext().getContentResolver(),
+ Settings.Secure.THEME_CUSTOMIZATION_OVERLAY_PACKAGES));
+ if (setting.contains("com.android.theme.icon_pack.circular.android")) {
+ return LOCK_ANIM_RES_IDS[1][lockAnimIndex];
+ } else if (setting.contains("com.android.theme.icon_pack.filled.android")) {
+ return LOCK_ANIM_RES_IDS[2][lockAnimIndex];
+ } else if (setting.contains("com.android.theme.icon_pack.rounded.android")) {
+ return LOCK_ANIM_RES_IDS[3][lockAnimIndex];
+ }
+ return LOCK_ANIM_RES_IDS[0][lockAnimIndex];
+ }
+
private int getState() {
KeyguardUpdateMonitor updateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
if (mTransientBiometricsError) {
@@ -441,17 +492,6 @@ public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChange
setImageTintList(ColorStateList.valueOf(color));
}
- /**
- * If bouncer is visible or not.
- */
- public void setBouncerVisible(boolean bouncerVisible) {
- if (mBouncerVisible == bouncerVisible) {
- return;
- }
- mBouncerVisible = bouncerVisible;
- update();
- }
-
@Override
public void onDensityOrFontScaleChanged() {
ViewGroup.LayoutParams lp = getLayoutParams();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 337c6b167cdf..d94a33556a43 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -86,6 +86,7 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.util.LatencyTracker;
import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.ScreenDecorations;
import com.android.systemui.SysUiServiceProvider;
import com.android.systemui.assist.AssistManager;
import com.android.systemui.fragments.FragmentHostManager;
@@ -170,6 +171,7 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
public int mDisplayId;
private boolean mIsOnDefaultDisplay;
public boolean mHomeBlockedThisTouch;
+ private ScreenDecorations mScreenDecorations;
private Handler mHandler = Dependency.get(Dependency.MAIN_HANDLER);
@@ -348,12 +350,17 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
mDisabledFlags2 |= StatusBarManager.DISABLE2_ROTATE_SUGGESTIONS;
}
setDisabled2Flags(mDisabledFlags2);
+
+ mScreenDecorations = SysUiServiceProvider.getComponent(getContext(),
+ ScreenDecorations.class);
+ getBarTransitions().addDarkIntensityListener(mScreenDecorations);
}
@Override
public void onDestroyView() {
super.onDestroyView();
if (mNavigationBarView != null) {
+ mNavigationBarView.getBarTransitions().removeDarkIntensityListener(mScreenDecorations);
mNavigationBarView.getBarTransitions().destroy();
mNavigationBarView.getLightTransitionsController().destroy(getContext());
}
@@ -1020,7 +1027,7 @@ public class NavigationBarFragment extends LifecycleFragment implements Callback
getBarTransitions().transitionTo(barMode, animate);
}
- private BarTransitions getBarTransitions() {
+ public NavigationBarTransitions getBarTransitions() {
return mNavigationBarView.getBarTransitions();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index 8a28c6fbff29..2b5a28e60082 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -36,9 +36,23 @@ import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.Dependency;
import com.android.systemui.R;
+import java.util.ArrayList;
+import java.util.List;
+
public final class NavigationBarTransitions extends BarTransitions implements
LightBarTransitionsController.DarkIntensityApplier {
+ /**
+ * Notified when the color of nav bar elements changes.
+ */
+ public interface DarkIntensityListener {
+ /**
+ * Called when the color of nav bar elements changes.
+ * @param darkIntensity 0 is the lightest color, 1 is the darkest.
+ */
+ void onDarkIntensity(float darkIntensity);
+ }
+
private final NavigationBarView mView;
private final IStatusBarService mBarService;
private final LightBarTransitionsController mLightTransitionsController;
@@ -49,6 +63,7 @@ public final class NavigationBarTransitions extends BarTransitions implements
private boolean mAutoDim;
private View mNavButtons;
private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
+ private List<DarkIntensityListener> mDarkIntensityListeners;
private final Handler mHandler = Handler.getMain();
private final IWallpaperVisibilityListener mWallpaperVisibilityListener =
@@ -69,6 +84,7 @@ public final class NavigationBarTransitions extends BarTransitions implements
mLightTransitionsController = new LightBarTransitionsController(view.getContext(), this);
mAllowAutoDimWallpaperNotVisible = view.getContext().getResources()
.getBoolean(R.bool.config_navigation_bar_enable_auto_dim_no_visible_wallpaper);
+ mDarkIntensityListeners = new ArrayList();
IWindowManager windowManagerService = Dependency.get(IWindowManager.class);
try {
@@ -168,12 +184,16 @@ public final class NavigationBarTransitions extends BarTransitions implements
applyDarkIntensity(mLightTransitionsController.getCurrentDarkIntensity());
}
+ @Override
public void applyDarkIntensity(float darkIntensity) {
SparseArray<ButtonDispatcher> buttonDispatchers = mView.getButtonDispatchers();
for (int i = buttonDispatchers.size() - 1; i >= 0; i--) {
buttonDispatchers.valueAt(i).setDarkIntensity(darkIntensity);
}
mView.getRotationButtonController().setDarkIntensity(darkIntensity);
+ for (DarkIntensityListener listener : mDarkIntensityListeners) {
+ listener.onDarkIntensity(darkIntensity);
+ }
if (mAutoDim) {
applyLightsOut(false, true);
}
@@ -190,4 +210,18 @@ public final class NavigationBarTransitions extends BarTransitions implements
public void onNavigationModeChanged(int mode) {
mNavBarMode = mode;
}
+
+ /**
+ * Register {@code listener} to be notified when the color of nav bar elements changes.
+ */
+ public void addDarkIntensityListener(DarkIntensityListener listener) {
+ mDarkIntensityListeners.add(listener);
+ }
+
+ /**
+ * Remove {@code listener} from being notified when the color of nav bar elements changes.
+ */
+ public void removeDarkIntensityListener(DarkIntensityListener listener) {
+ mDarkIntensityListeners.remove(listener);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 7682e8a594ce..3ec16090ea87 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -299,7 +299,7 @@ public class NavigationBarView extends FrameLayout implements
return mTintController;
}
- public BarTransitions getBarTransitions() {
+ public NavigationBarTransitions getBarTransitions() {
return mBarTransitions;
}
@@ -597,10 +597,6 @@ public class NavigationBarView extends FrameLayout implements
boolean disableHome = isGesturalMode(mNavBarMode)
|| ((mDisabledFlags & View.STATUS_BAR_DISABLE_HOME) != 0);
- // TODO(b/113914868): investigation log for disappearing home button
- Log.i(TAG, "updateNavButtonIcons (b/113914868): home disabled=" + disableHome
- + " mDisabledFlags=" + mDisabledFlags);
-
// Always disable recents when alternate car mode UI is active and for secondary displays.
boolean disableRecent = isRecentsButtonDisabled();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index bb490f52b045..e8ca3eef24de 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -1,7 +1,5 @@
package com.android.systemui.statusbar.phone;
-import static com.android.systemui.doze.util.BurnInHelperKt.getBurnInOffset;
-
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Color;
@@ -17,7 +15,6 @@ import androidx.collection.ArrayMap;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.StatusBarIcon;
import com.android.internal.util.ContrastColorUtil;
-import com.android.internal.widget.ViewClippingUtil;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.DarkIconDispatcher;
@@ -86,17 +83,6 @@ public class NotificationIconAreaController implements DarkReceiver,
* Ratio representing being awake or in ambient mode, where 1 is dark and 0 awake.
*/
private float mDarkAmount;
- /**
- * Maximum translation to avoid burn in.
- */
- private int mBurnInOffset;
- /**
- * Height of the keyguard status bar (not the one after unlocking.)
- */
- private int mKeyguardStatusBarHeight;
-
- private final ViewClippingUtil.ClippingParameters mClippingParameters =
- view -> view instanceof StatusBarWindowView;
public NotificationIconAreaController(Context context, StatusBar statusBar,
StatusBarStateController statusBarStateController,
@@ -166,9 +152,6 @@ public class NotificationIconAreaController implements DarkReceiver,
Resources res = context.getResources();
mIconSize = res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_icon_size);
mIconHPadding = res.getDimensionPixelSize(R.dimen.status_bar_icon_padding);
- mBurnInOffset = res.getDimensionPixelSize(R.dimen.default_burn_in_prevention_offset);
- mKeyguardStatusBarHeight = res
- .getDimensionPixelSize(R.dimen.status_bar_header_height_keyguard);
}
/**
@@ -479,49 +462,9 @@ public class NotificationIconAreaController implements DarkReceiver,
mNotificationIcons.setIsolatedIconLocation(iconDrawingRect, requireStateUpdate);
}
- /**
- * Moves icons whenever the device wakes up in AOD, to avoid burn in.
- */
- public void dozeTimeTick() {
- if (mNotificationIcons.getVisibility() != View.VISIBLE) {
- return;
- }
-
- if (mDarkAmount == 0 && !mStatusBarStateController.isDozing()) {
- mNotificationIcons.setTranslationX(0);
- mNotificationIcons.setTranslationY(0);
- mCenteredIcon.setTranslationX(0);
- mCenteredIcon.setTranslationY(0);
- return;
- }
-
- int yOffset = (mKeyguardStatusBarHeight - getHeight()) / 2;
- int translationX = getBurnInOffset(mBurnInOffset, true /* xAxis */);
- int translationY = getBurnInOffset(mBurnInOffset, false /* xAxis */) + yOffset;
- mNotificationIcons.setTranslationX(translationX);
- mNotificationIcons.setTranslationY(translationY);
- mCenteredIcon.setTranslationX(translationX);
- mCenteredIcon.setTranslationY(translationY);
- }
-
- @Override
- public void onDozingChanged(boolean isDozing) {
- dozeTimeTick();
- }
-
@Override
public void onDozeAmountChanged(float linear, float eased) {
- boolean wasOrIsAwake = mDarkAmount == 0 || linear == 0;
- boolean wasOrIsDozing = mDarkAmount == 1 || linear == 1;
mDarkAmount = linear;
- if (wasOrIsAwake) {
- ViewClippingUtil.setClippingDeactivated(mNotificationIcons, mDarkAmount != 0,
- mClippingParameters);
- }
- if (wasOrIsAwake || wasOrIsDozing) {
- dozeTimeTick();
- }
-
boolean fullyDark = mDarkAmount == 1f;
if (mFullyDark != fullyDark) {
mFullyDark = fullyDark;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index d303ade9a32a..b3cbf083e4a8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -100,6 +100,7 @@ import com.android.systemui.util.InjectionInflationController;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
@@ -141,6 +142,7 @@ public class NotificationPanelView extends PanelView implements
private static final String COUNTER_PANEL_OPEN_PEEK = "panel_open_peek";
private static final Rect mDummyDirtyRect = new Rect(0, 0, 1, 1);
+ private static final Rect mEmptyRect = new Rect();
private static final AnimationProperties CLOCK_ANIMATION_PROPERTIES = new AnimationProperties()
.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
@@ -150,6 +152,7 @@ public class NotificationPanelView extends PanelView implements
private final AccessibilityManager mAccessibilityManager;
private final NotificationWakeUpCoordinator mWakeUpCoordinator;
private final PulseExpansionHandler mPulseExpansionHandler;
+ private final KeyguardBypassController mKeyguardBypassController;
@VisibleForTesting
protected KeyguardAffordanceHelper mAffordanceHelper;
@@ -348,7 +351,8 @@ public class NotificationPanelView extends PanelView implements
InjectionInflationController injectionInflationController,
NotificationWakeUpCoordinator coordinator,
PulseExpansionHandler pulseExpansionHandler,
- DynamicPrivacyController dynamicPrivacyController) {
+ DynamicPrivacyController dynamicPrivacyController,
+ KeyguardBypassController bypassController) {
super(context, attrs);
setWillNotDraw(!DEBUG);
mInjectionInflationController = injectionInflationController;
@@ -363,6 +367,7 @@ public class NotificationPanelView extends PanelView implements
mDisplayId = context.getDisplayId();
mPulseExpansionHandler = pulseExpansionHandler;
mThemeResId = context.getThemeResId();
+ mKeyguardBypassController = bypassController;
dynamicPrivacyController.addListener(this);
}
@@ -596,6 +601,25 @@ public class NotificationPanelView extends PanelView implements
mQs.setHeightOverride(mQs.getDesiredHeight());
}
updateMaxHeadsUpTranslation();
+ updateGestureExclusionRect();
+ }
+
+ private void updateGestureExclusionRect() {
+ Rect exclusionRect = calculateGestureExclusionRect();
+ setSystemGestureExclusionRects(exclusionRect.isEmpty()
+ ? Collections.EMPTY_LIST
+ : Collections.singletonList(exclusionRect));
+ }
+
+ private Rect calculateGestureExclusionRect() {
+ Rect exclusionRect = null;
+ if (isFullyCollapsed()) {
+ // Note: The heads up manager also calculates the non-pinned touchable region
+ exclusionRect = mHeadsUpManager.calculateTouchableRegion();
+ }
+ return exclusionRect != null
+ ? exclusionRect
+ : mEmptyRect;
}
private void setIsFullWidth(boolean isFullWidth) {
@@ -655,14 +679,15 @@ public class NotificationPanelView extends PanelView implements
hasCustomClock(),
mNotificationStackScroller.getVisibleNotificationCount() != 0,
mInterpolatedDarkAmount,
- mEmptyDragAmount);
+ mEmptyDragAmount,
+ mKeyguardBypassController.getBypassEnabled());
mClockPositionAlgorithm.run(mClockPositionResult);
PropertyAnimator.setProperty(mKeyguardStatusView, AnimatableProperty.X,
mClockPositionResult.clockX, CLOCK_ANIMATION_PROPERTIES, animateClock);
PropertyAnimator.setProperty(mKeyguardStatusView, AnimatableProperty.Y,
mClockPositionResult.clockY, CLOCK_ANIMATION_PROPERTIES, animateClock);
updateClock();
- stackScrollerPadding = mClockPositionResult.stackScrollerPadding;
+ stackScrollerPadding = mClockPositionResult.stackScrollerPaddingExpanded;
}
mNotificationStackScroller.setIntrinsicPadding(stackScrollerPadding);
mNotificationStackScroller.setAntiBurnInOffsetX(mClockPositionResult.clockX);
@@ -1595,7 +1620,7 @@ public class NotificationPanelView extends PanelView implements
} else if (mKeyguardShowing) {
// We can only do the smoother transition on Keyguard when we also are not collapsing
// from a scrolled quick settings.
- return MathUtils.lerp((float) mNotificationStackScroller.getIntrinsicPadding(),
+ return MathUtils.lerp((float) mClockPositionResult.stackScrollerPadding,
(float) (mQsMaxExpansionHeight + mQsNotificationTopPadding),
getQsExpansionFraction());
} else {
@@ -1604,9 +1629,7 @@ public class NotificationPanelView extends PanelView implements
}
protected void requestScrollerTopPaddingUpdate(boolean animate) {
- mNotificationStackScroller.updateTopPadding(calculateQsTopPadding(),
- animate, mKeyguardShowing
- && (mQsExpandImmediate || mIsExpanding && mQsExpandedWhenExpandingStarted));
+ mNotificationStackScroller.updateTopPadding(calculateQsTopPadding(), animate);
}
private void trackMovement(MotionEvent event) {
@@ -1798,6 +1821,7 @@ public class NotificationPanelView extends PanelView implements
updateHeader();
updateNotificationTranslucency();
updatePanelExpanded();
+ updateGestureExclusionRect();
if (DEBUG) {
invalidate();
}
@@ -2568,6 +2592,7 @@ public class NotificationPanelView extends PanelView implements
mNotificationStackScroller.runAfterAnimationFinished(
mHeadsUpExistenceChangedRunnable);
}
+ updateGestureExclusionRect();
}
public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) {
@@ -2863,7 +2888,7 @@ public class NotificationPanelView extends PanelView implements
public void setDozing(boolean dozing, boolean animate, PointF wakeUpTouchLocation) {
if (dozing == mDozing) return;
mDozing = dozing;
- mNotificationStackScroller.setDark(mDozing, animate, wakeUpTouchLocation);
+ mNotificationStackScroller.setDozing(mDozing, animate, wakeUpTouchLocation);
mKeyguardBottomArea.setDozing(mDozing, animate);
if (mBarState == StatusBarState.KEYGUARD
@@ -2871,8 +2896,8 @@ public class NotificationPanelView extends PanelView implements
updateDozingVisibilities(animate);
}
- final float darkAmount = dozing ? 1 : 0;
- mStatusBarStateController.setDozeAmount(darkAmount, animate);
+ final float dozeAmount = dozing ? 1 : 0;
+ mStatusBarStateController.setDozeAmount(dozeAmount, animate);
}
@Override
@@ -2992,6 +3017,7 @@ public class NotificationPanelView extends PanelView implements
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
super.dump(fd, pw, args);
+ pw.println(" gestureExclusionRect: " + calculateGestureExclusionRect());
if (mKeyguardStatusBar != null) {
mKeyguardStatusBar.dump(fd, pw, args);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
index f1460a62903d..b117dec44cb4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/RotationContextButton.java
@@ -66,7 +66,9 @@ public class RotationContextButton extends ContextualButton implements
@Override
public void onDestroy() {
- mRotationButtonController.cleanUp();
+ if (mRotationButtonController != null) {
+ mRotationButtonController.cleanUp();
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 5fca4f8478cb..2c7d204efc33 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1313,7 +1313,6 @@ public class StatusBar extends SystemUI implements DemoMode,
&& !mDozing
&& !ONLY_CORE_APPS;
mNotificationPanel.setQsExpansionEnabled(expandEnabled);
- // STOPSHIP(kozynski, b/129405675) Remove log
Log.d(TAG, "updateQsExpansionEnabled - QS Expand enabled: " + expandEnabled);
}
@@ -4019,7 +4018,6 @@ public class StatusBar extends SystemUI implements DemoMode,
@Override
public void dozeTimeTick() {
mNotificationPanel.dozeTimeTick();
- mNotificationIconAreaController.dozeTimeTick();
if (mAmbientIndicationContainer instanceof DozeReceiver) {
((DozeReceiver) mAmbientIndicationContainer).dozeTimeTick();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
index e949ade28b59..3d25749265f1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
@@ -26,7 +26,6 @@ import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
import com.android.systemui.Dependency;
-import com.android.systemui.assist.AssistManager;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
@@ -38,7 +37,6 @@ import com.android.systemui.statusbar.policy.ConfigurationController.Configurati
public final class StatusBarTouchableRegionManager implements
OnComputeInternalInsetsListener, ConfigurationListener {
- private final AssistManager mAssistManager = Dependency.get(AssistManager.class);
private final BubbleController mBubbleController = Dependency.get(BubbleController.class);
private final Context mContext;
private final HeadsUpManagerPhone mHeadsUpManager;
@@ -48,6 +46,7 @@ public final class StatusBarTouchableRegionManager implements
private int mStatusBarHeight;
private final View mStatusBarWindowView;
private boolean mForceCollapsedUntilLayout = false;
+ private final StatusBarWindowController mStatusBarWindowController;
public StatusBarTouchableRegionManager(@NonNull Context context,
HeadsUpManagerPhone headsUpManager,
@@ -57,12 +56,17 @@ public final class StatusBarTouchableRegionManager implements
mHeadsUpManager = headsUpManager;
mStatusBar = statusBar;
mStatusBarWindowView = statusBarWindowView;
+ mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
initResources();
mBubbleController.setBubbleStateChangeListener((hasBubbles) -> {
updateTouchableRegion();
});
+
+ mStatusBarWindowController.setForcePluginOpenListener((forceOpen) -> {
+ updateTouchableRegion();
+ });
Dependency.get(ConfigurationController.class).addCallback(this);
}
@@ -77,7 +81,8 @@ public final class StatusBarTouchableRegionManager implements
mHeadsUpManager.hasPinnedHeadsUp() || mHeadsUpManager.isHeadsUpGoingAway()
|| mBubbleController.hasBubbles()
|| mForceCollapsedUntilLayout
- || hasCutoutInset;
+ || hasCutoutInset
+ || mStatusBarWindowController.getForcePluginOpen();
if (shouldObserve == mShouldAdjustInsets) {
return;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index 631920c16a2c..f08db1b5c76c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -80,6 +80,7 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
private float mScreenBrightnessDoze;
private final State mCurrentState = new State();
private OtherwisedCollapsedListener mListener;
+ private ForcePluginOpenListener mForcePluginOpenListener;
private final SysuiColorExtractor mColorExtractor = Dependency.get(SysuiColorExtractor.class);
@@ -477,6 +478,16 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
public void setForcePluginOpen(boolean forcePluginOpen) {
mCurrentState.forcePluginOpen = forcePluginOpen;
apply(mCurrentState);
+ if (mForcePluginOpenListener != null) {
+ mForcePluginOpenListener.onChange(forcePluginOpen);
+ }
+ }
+
+ /**
+ * The forcePluginOpen state for the status bar.
+ */
+ public boolean getForcePluginOpen() {
+ return mCurrentState.forcePluginOpen;
}
public void setNotTouchable(boolean notTouchable) {
@@ -525,6 +536,10 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
mListener = listener;
}
+ public void setForcePluginOpenListener(ForcePluginOpenListener listener) {
+ mForcePluginOpenListener = listener;
+ }
+
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("StatusBarWindowController state:");
pw.println(mCurrentState);
@@ -637,4 +652,14 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
public interface OtherwisedCollapsedListener {
void setWouldOtherwiseCollapse(boolean otherwiseCollapse);
}
+
+ /**
+ * Listener to indicate forcePluginOpen has changed
+ */
+ public interface ForcePluginOpenListener {
+ /**
+ * Called when mState.forcePluginOpen is changed
+ */
+ void onChange(boolean forceOpen);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index c08390fa53a2..2afe485eff8e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -38,6 +38,7 @@ import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.cdma.EriInfo;
import com.android.settingslib.Utils;
import com.android.settingslib.graph.SignalDrawable;
+import com.android.settingslib.net.SignalStrengthUtil;
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.NetworkController.IconState;
import com.android.systemui.statusbar.policy.NetworkController.SignalCallback;
@@ -248,9 +249,8 @@ public class MobileSignalController extends SignalController<
}
private void updateInflateSignalStrength() {
- mInflateSignalStrengths = SubscriptionManager.getResourcesForSubId(mContext,
- mSubscriptionInfo.getSubscriptionId())
- .getBoolean(R.bool.config_inflateSignalStrength);
+ mInflateSignalStrengths = SignalStrengthUtil.shouldInflateSignalStrength(mContext,
+ mSubscriptionInfo.getSubscriptionId());
}
private int getNumLevels() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index b8a14efa4935..b2972fcd1286 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -1140,7 +1140,8 @@ public class NetworkControllerImpl extends BroadcastReceiver
res.getBoolean(com.android.internal.R.bool.config_alwaysUseCdmaRssi);
config.hspaDataDistinguishable =
res.getBoolean(R.bool.config_hspa_data_distinguishable);
- config.inflateSignalStrengths = res.getBoolean(R.bool.config_inflateSignalStrength);
+ config.inflateSignalStrengths = res.getBoolean(
+ com.android.internal.R.bool.config_inflateSignalStrength);
CarrierConfigManager configMgr = (CarrierConfigManager)
context.getSystemService(Context.CARRIER_CONFIG_SERVICE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index f726321db963..395add76dda4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -111,7 +111,9 @@ public class UserSwitcherController implements Dumpable {
public UserSwitcherController(Context context, KeyguardMonitor keyguardMonitor,
@Named(MAIN_HANDLER_NAME) Handler handler, ActivityStarter activityStarter) {
mContext = context;
- mGuestResumeSessionReceiver.register(context);
+ if (!UserManager.isGuestUserEphemeral()) {
+ mGuestResumeSessionReceiver.register(context);
+ }
mKeyguardMonitor = keyguardMonitor;
mHandler = handler;
mActivityStarter = activityStarter;
diff --git a/packages/SystemUI/src/com/android/systemui/util/AutoMarqueeTextView.java b/packages/SystemUI/src/com/android/systemui/util/AutoMarqueeTextView.java
index d9d410dc4b89..09dbfee5e0a4 100644
--- a/packages/SystemUI/src/com/android/systemui/util/AutoMarqueeTextView.java
+++ b/packages/SystemUI/src/com/android/systemui/util/AutoMarqueeTextView.java
@@ -49,6 +49,11 @@ public class AutoMarqueeTextView extends TextView {
}
@Override
+ protected void onFinishInflate() {
+ onVisibilityAggregated(isVisibleToUser());
+ }
+
+ @Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
setSelected(true);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
index 3330d1e6d0a8..6891f562a3c4 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
@@ -20,12 +20,14 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.ContentResolver;
import android.database.ContentObserver;
import android.net.Uri;
+import android.provider.DeviceConfig;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
@@ -50,6 +52,8 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.util.List;
+
@SmallTest
@RunWith(AndroidTestingRunner.class)
// Need to run tests on main looper because LiveData operations such as setData, observe,
@@ -63,7 +67,7 @@ public final class ClockManagerTest extends SysuiTestCase {
private static final int SECONDARY_USER_ID = 11;
private static final Uri SETTINGS_URI = null;
- private ClockManager mClockManager;
+ ClockManager mClockManager;
private ContentObserver mContentObserver;
private DockManagerFake mFakeDockManager;
private MutableLiveData<Integer> mCurrentUser;
@@ -140,6 +144,33 @@ public final class ClockManagerTest extends SysuiTestCase {
}
@Test
+ public void getCurrentClock_inBlackList() {
+ mClockManager = spy(mClockManager);
+ // GIVEN that settings is set to the bubble clock face
+ when(mMockSettingsWrapper.getLockScreenCustomClockFace(anyInt())).thenReturn(BUBBLE_CLOCK);
+ // WHEN settings change event is fired
+ mContentObserver.onChange(false, SETTINGS_URI, MAIN_USER_ID);
+ // GIVEN that bubble clock is in blacklist
+ when(mClockManager.getBlackListFromConfig()).thenReturn(BUBBLE_CLOCK);
+ // WHEN device config change of systemui is fired
+ mClockManager.onDeviceConfigPropertiesChanged(DeviceConfig.NAMESPACE_SYSTEMUI);
+ // THEN the result is null, indicated the current clock should be reset to the default one.
+ assertThat(mClockManager.getCurrentClock()).isNull();
+ }
+
+ @Test
+ public void getClockInfo_inBlackList() {
+ mClockManager = spy(mClockManager);
+ // GIVEN that bubble clock is in blacklist
+ when(mClockManager.getBlackListFromConfig()).thenReturn(BUBBLE_CLOCK);
+ // WHEN device config change of systemui is fired
+ mClockManager.onDeviceConfigPropertiesChanged(DeviceConfig.NAMESPACE_SYSTEMUI);
+ // THEN the ClockInfo should not contain bubble clock
+ List<ClockInfo> clocks = mClockManager.getClockInfos();
+ assertThat(clocks.stream().anyMatch(info -> BUBBLE_CLOCK.equals(info.getId()))).isFalse();
+ }
+
+ @Test
public void onClockChanged_customClock() {
// GIVEN that settings is set to the bubble clock face
when(mMockSettingsWrapper.getLockScreenCustomClockFace(anyInt())).thenReturn(BUBBLE_CLOCK);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
index b9afea155ccf..cc31531c90a7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
@@ -16,7 +16,10 @@
package com.android.systemui.appops;
+import static junit.framework.TestCase.assertFalse;
+
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -189,4 +192,21 @@ public class AppOpsControllerTest extends SysuiTestCase {
AppOpsManager.MODE_ALLOWED);
verify(mMockHandler).scheduleRemoval(any(AppOpItem.class), anyLong());
}
+
+ @Test
+ public void noItemsAfterStopListening() {
+ mController.setBGHandler(mMockHandler);
+
+ mController.setListening(true);
+ mController.onOpActiveChanged(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
+ true);
+ mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
+ AppOpsManager.MODE_ALLOWED);
+ assertFalse(mController.getActiveAppOps().isEmpty());
+
+ mController.setListening(false);
+
+ verify(mMockHandler).removeCallbacksAndMessages(null);
+ assertTrue(mController.getActiveAppOps().isEmpty());
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java
index 13c92b605c03..18f114a71a8d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/assist/AssistHandleBehaviorControllerTest.java
@@ -18,21 +18,27 @@ package com.android.systemui.assist;
import static org.mockito.AdditionalAnswers.answerVoid;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+import android.content.ComponentName;
import android.os.Handler;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper.RunWithLooper;
import androidx.test.filters.SmallTest;
+import com.android.internal.app.AssistUtils;
import com.android.systemui.ScreenDecorations;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.recents.OverviewProxyService;
import org.junit.Before;
import org.junit.Test;
@@ -46,29 +52,35 @@ import org.mockito.MockitoAnnotations;
@RunWithLooper
public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
- private final AssistHandleBehavior mTestBehavior = AssistHandleBehavior.TEST;
+ private static final ComponentName COMPONENT_NAME = new ComponentName("", "");
private AssistHandleBehaviorController mAssistHandleBehaviorController;
@Mock private ScreenDecorations mMockScreenDecorations;
+ @Mock private AssistUtils mMockAssistUtils;
@Mock private Handler mMockHandler;
@Mock private AssistHandleBehaviorController.BehaviorController mMockBehaviorController;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
+ mDependency.injectMockDependency(StatusBarStateController.class);
+ mDependency.injectMockDependency(OverviewProxyService.class);
doAnswer(answerVoid(Runnable::run)).when(mMockHandler).post(any(Runnable.class));
doAnswer(answerVoid(Runnable::run)).when(mMockHandler)
.postDelayed(any(Runnable.class), anyLong());
- mTestBehavior.setTestController(mMockBehaviorController);
mAssistHandleBehaviorController =
new AssistHandleBehaviorController(
- mContext, mMockHandler, () -> mMockScreenDecorations);
+ mContext,
+ mMockAssistUtils,
+ mMockHandler, () -> mMockScreenDecorations,
+ mMockBehaviorController);
}
@Test
public void hide_hidesHandlesWhenShowing() {
// Arrange
+ when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
mAssistHandleBehaviorController.showAndStay();
reset(mMockScreenDecorations);
@@ -83,6 +95,7 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
@Test
public void hide_doesNothingWhenHiding() {
// Arrange
+ when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
mAssistHandleBehaviorController.hide();
reset(mMockScreenDecorations);
@@ -96,6 +109,7 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
@Test
public void showAndStay_showsHandlesWhenHiding() {
// Arrange
+ when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
mAssistHandleBehaviorController.hide();
reset(mMockScreenDecorations);
@@ -110,6 +124,7 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
@Test
public void showAndStay_doesNothingWhenShowing() {
// Arrange
+ when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
mAssistHandleBehaviorController.showAndStay();
reset(mMockScreenDecorations);
@@ -121,8 +136,23 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
}
@Test
+ public void showAndStay_doesNothingWhenThereIsNoAssistant() {
+ // Arrange
+ when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(null);
+ mAssistHandleBehaviorController.hide();
+ reset(mMockScreenDecorations);
+
+ // Act
+ mAssistHandleBehaviorController.showAndStay();
+
+ // Assert
+ verifyNoMoreInteractions(mMockScreenDecorations);
+ }
+
+ @Test
public void showAndGo_showsThenHidesHandlesWhenHiding() {
// Arrange
+ when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
mAssistHandleBehaviorController.hide();
reset(mMockScreenDecorations);
@@ -139,6 +169,7 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
@Test
public void showAndGo_hidesHandlesAfterTimeoutWhenShowing() {
// Arrange
+ when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
mAssistHandleBehaviorController.showAndStay();
reset(mMockScreenDecorations);
@@ -153,6 +184,7 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
@Test
public void showAndGo_doesNothingIfRecentlyHidden() {
// Arrange
+ when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
mAssistHandleBehaviorController.showAndGo();
reset(mMockScreenDecorations);
@@ -164,12 +196,27 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
}
@Test
+ public void showAndGo_doesNothingWhenThereIsNoAssistant() {
+ // Arrange
+ when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(null);
+ mAssistHandleBehaviorController.hide();
+ reset(mMockScreenDecorations);
+
+ // Act
+ mAssistHandleBehaviorController.showAndGo();
+
+ // Assert
+ verifyNoMoreInteractions(mMockScreenDecorations);
+ }
+
+ @Test
public void setBehavior_activatesTheBehaviorWhenInGesturalMode() {
// Arrange
+ when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
mAssistHandleBehaviorController.setInGesturalModeForTest(true);
// Act
- mAssistHandleBehaviorController.setBehavior(mTestBehavior);
+ mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.TEST);
// Assert
verify(mMockBehaviorController).onModeActivated(mContext, mAssistHandleBehaviorController);
@@ -179,8 +226,10 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
@Test
public void setBehavior_deactivatesThePreviousBehaviorWhenInGesturalMode() {
// Arrange
- mAssistHandleBehaviorController.setBehavior(mTestBehavior);
+ when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
+ mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.TEST);
mAssistHandleBehaviorController.setInGesturalModeForTest(true);
+ reset(mMockBehaviorController);
// Act
mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.OFF);
@@ -193,10 +242,11 @@ public class AssistHandleBehaviorControllerTest extends SysuiTestCase {
@Test
public void setBehavior_doesNothingWhenNotInGesturalMode() {
// Arrange
+ when(mMockAssistUtils.getAssistComponentForUser(anyInt())).thenReturn(COMPONENT_NAME);
mAssistHandleBehaviorController.setInGesturalModeForTest(false);
// Act
- mAssistHandleBehaviorController.setBehavior(mTestBehavior);
+ mAssistHandleBehaviorController.setBehavior(AssistHandleBehavior.TEST);
// Assert
verifyNoMoreInteractions(mMockBehaviorController);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
index 756cf3e138f6..b324235106c2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
@@ -60,8 +60,8 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC
@Before
public void setUp() throws Exception {
super.setUp();
- addOneMoreThanRenderLimitBubbles();
- mLayout.setController(mExpandedController);
+ addOneMoreThanBubbleLimitBubbles();
+ mLayout.setActiveController(mExpandedController);
Resources res = mLayout.getResources();
mStackOffset = res.getDimensionPixelSize(R.dimen.bubble_stack_offset);
@@ -73,14 +73,14 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC
@Test
public void testExpansionAndCollapse() throws InterruptedException {
Runnable afterExpand = Mockito.mock(Runnable.class);
- mExpandedController.expandFromStack(mExpansionPoint, afterExpand);
+ mExpandedController.expandFromStack(afterExpand);
waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
testBubblesInCorrectExpandedPositions();
verify(afterExpand).run();
Runnable afterCollapse = Mockito.mock(Runnable.class);
- mExpandedController.collapseBackToStack(afterCollapse);
+ mExpandedController.collapseBackToStack(mExpansionPoint, afterCollapse);
waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
testStackedAtPosition(mExpansionPoint.x, mExpansionPoint.y, -1);
@@ -139,7 +139,6 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC
assertEquals(500f, draggedBubble.getTranslationY(), 1f);
// Snap it back and make sure it made it back correctly.
- mExpandedController.prepareForDismissalWithVelocity(draggedBubble, 0f, 0f);
mLayout.removeView(draggedBubble);
waitForLayoutMessageQueue();
waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
@@ -169,7 +168,7 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC
// Dismiss the now-magneted bubble, verify that the callback was called.
final Runnable afterDismiss = Mockito.mock(Runnable.class);
- mExpandedController.dismissDraggedOutBubble(afterDismiss);
+ mExpandedController.dismissDraggedOutBubble(draggedOutView, afterDismiss);
waitForPropertyAnimations(DynamicAnimation.ALPHA);
verify(after).run();
@@ -224,7 +223,7 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC
/** Expand the stack and wait for animations to finish. */
private void expand() throws InterruptedException {
- mExpandedController.expandFromStack(mExpansionPoint, Mockito.mock(Runnable.class));
+ mExpandedController.expandFromStack(Mockito.mock(Runnable.class));
waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y);
}
@@ -236,26 +235,19 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC
assertEquals(x + i * offsetMultiplier * mStackOffset,
mLayout.getChildAt(i).getTranslationX(), 2f);
assertEquals(y, mLayout.getChildAt(i).getTranslationY(), 2f);
-
- if (i < mMaxRenderedBubbles) {
- assertEquals(1f, mLayout.getChildAt(i).getAlpha(), .01f);
- }
+ assertEquals(1f, mLayout.getChildAt(i).getAlpha(), .01f);
}
}
/** Check that children are in the correct positions for being expanded. */
private void testBubblesInCorrectExpandedPositions() {
// Check all the visible bubbles to see if they're in the right place.
- for (int i = 0; i < Math.min(mLayout.getChildCount(), mMaxRenderedBubbles); i++) {
+ for (int i = 0; i < mLayout.getChildCount(); i++) {
assertEquals(getBubbleLeft(i),
mLayout.getChildAt(i).getTranslationX(),
2f);
assertEquals(mExpandedController.getExpandedY(),
mLayout.getChildAt(i).getTranslationY(), 2f);
-
- if (i < mMaxRenderedBubbles) {
- assertEquals(1f, mLayout.getChildAt(i).getAlpha(), .01f);
- }
}
}
@@ -273,9 +265,7 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC
return 0;
}
int bubbleCount = mLayout.getChildCount();
- if (bubbleCount > mMaxRenderedBubbles) {
- bubbleCount = mMaxRenderedBubbles;
- }
+
// Width calculations.
double bubble = bubbleCount * mBubbleSize;
float gap = (bubbleCount - 1) * mBubblePadding;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTest.java
index eef6ddcf6d6b..f8b32c213109 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTest.java
@@ -23,7 +23,6 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.inOrder;
-import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -77,21 +76,9 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase {
}
@Test
- public void testRenderVisibility() throws InterruptedException {
- mLayout.setController(mTestableController);
- addOneMoreThanRenderLimitBubbles();
-
- // The last child should be GONE, the rest VISIBLE.
- for (int i = 0; i < mMaxRenderedBubbles + 1; i++) {
- assertEquals(i == mMaxRenderedBubbles ? View.GONE : View.VISIBLE,
- mLayout.getChildAt(i).getVisibility());
- }
- }
-
- @Test
public void testHierarchyChanges() throws InterruptedException {
- mLayout.setController(mTestableController);
- addOneMoreThanRenderLimitBubbles();
+ mLayout.setActiveController(mTestableController);
+ addOneMoreThanBubbleLimitBubbles();
// Make sure the controller was notified of all the views we added.
for (View mView : mViews) {
@@ -115,8 +102,8 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase {
@Test
public void testUpdateValueNotChained() throws InterruptedException {
- mLayout.setController(mTestableController);
- addOneMoreThanRenderLimitBubbles();
+ mLayout.setActiveController(mTestableController);
+ addOneMoreThanBubbleLimitBubbles();
// Don't chain any values.
mTestableController.setChainedProperties(Sets.newHashSet());
@@ -146,8 +133,8 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase {
@Test
public void testSetEndActions() throws InterruptedException {
- mLayout.setController(mTestableController);
- addOneMoreThanRenderLimitBubbles();
+ mLayout.setActiveController(mTestableController);
+ addOneMoreThanBubbleLimitBubbles();
mTestableController.setChainedProperties(Sets.newHashSet());
final CountDownLatch xLatch = new CountDownLatch(1);
@@ -189,8 +176,8 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase {
@Test
public void testRemoveEndListeners() throws InterruptedException {
- mLayout.setController(mTestableController);
- addOneMoreThanRenderLimitBubbles();
+ mLayout.setActiveController(mTestableController);
+ addOneMoreThanBubbleLimitBubbles();
mTestableController.setChainedProperties(Sets.newHashSet());
final CountDownLatch xLatch = new CountDownLatch(1);
@@ -229,8 +216,8 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase {
public void testSetController() throws InterruptedException {
// Add the bubbles, then set the controller, to make sure that a controller added to an
// already-initialized view works correctly.
- addOneMoreThanRenderLimitBubbles();
- mLayout.setController(mTestableController);
+ addOneMoreThanBubbleLimitBubbles();
+ mLayout.setActiveController(mTestableController);
testChainedTranslationAnimations();
TestableAnimationController secondController =
@@ -243,7 +230,7 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase {
DynamicAnimation.SCALE_X, 10f);
secondController.setRemoveImmediately(true);
- mLayout.setController(secondController);
+ mLayout.setActiveController(secondController);
mTestableController.animationForChildAtIndex(0)
.scaleX(1.5f)
.start();
@@ -266,7 +253,7 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase {
Mockito.verify(secondController, Mockito.atLeastOnce())
.getOffsetForChainedPropertyAnimation(eq(DynamicAnimation.SCALE_X));
- mLayout.setController(mTestableController);
+ mLayout.setActiveController(mTestableController);
mTestableController.animationForChildAtIndex(0)
.translationX(100f)
.start();
@@ -283,8 +270,8 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase {
@Test
public void testArePropertiesAnimating() throws InterruptedException {
- mLayout.setController(mTestableController);
- addOneMoreThanRenderLimitBubbles();
+ mLayout.setActiveController(mTestableController);
+ addOneMoreThanBubbleLimitBubbles();
assertFalse(mLayout.arePropertiesAnimating(
DynamicAnimation.TRANSLATION_X, DynamicAnimation.TRANSLATION_Y));
@@ -307,8 +294,8 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase {
@Test
public void testCancelAllAnimations() throws InterruptedException {
- mLayout.setController(mTestableController);
- addOneMoreThanRenderLimitBubbles();
+ mLayout.setActiveController(mTestableController);
+ addOneMoreThanBubbleLimitBubbles();
mTestableController.animationForChildAtIndex(0)
.position(1000, 1000)
@@ -321,29 +308,10 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase {
assertTrue(mViews.get(0).getTranslationY() < 1000);
}
- @Test
- public void testSetChildVisibility() throws InterruptedException {
- mLayout.setController(mTestableController);
- addOneMoreThanRenderLimitBubbles();
-
- // The last view should have been set to GONE by the controller, since we added one more
- // than the limit and it got pushed off. None of the first children should have been set
- // VISIBLE, since they would have been animated in by onChildAdded.
- Mockito.verify(mTestableController).setChildVisibility(
- mViews.get(mViews.size() - 1), 5, View.GONE);
- Mockito.verify(mTestableController, never()).setChildVisibility(
- any(View.class), anyInt(), eq(View.VISIBLE));
-
- // Remove the first view, which should cause the last view to become visible again.
- mLayout.removeView(mViews.get(0));
- Mockito.verify(mTestableController).setChildVisibility(
- mViews.get(mViews.size() - 1), 4, View.VISIBLE);
- }
-
/** Standard test of chained translation animations. */
private void testChainedTranslationAnimations() throws InterruptedException {
- mLayout.setController(mTestableController);
- addOneMoreThanRenderLimitBubbles();
+ mLayout.setActiveController(mTestableController);
+ addOneMoreThanBubbleLimitBubbles();
assertEquals(0, mLayout.getChildAt(0).getTranslationX(), .1f);
assertEquals(0, mLayout.getChildAt(1).getTranslationX(), .1f);
@@ -354,11 +322,7 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase {
waitForPropertyAnimations(DynamicAnimation.TRANSLATION_X);
- // Since we enabled chaining, animating the first view to 100 should animate the second to
- // 115 (since we set the offset to 15) and the third to 130, etc. Despite the sixth bubble
- // not being visible, or animated, make sure that it has the appropriate chained
- // translation.
- for (int i = 0; i < mMaxRenderedBubbles + 1; i++) {
+ for (int i = 0; i < mLayout.getChildCount(); i++) {
assertEquals(
100 + i * TEST_TRANSLATION_X_OFFSET,
mLayout.getChildAt(i).getTranslationX(), .1f);
@@ -383,8 +347,8 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase {
@Test
public void testPhysicsAnimator() throws InterruptedException {
- mLayout.setController(mTestableController);
- addOneMoreThanRenderLimitBubbles();
+ mLayout.setActiveController(mTestableController);
+ addOneMoreThanBubbleLimitBubbles();
Runnable afterAll = Mockito.mock(Runnable.class);
Runnable after = Mockito.spy(new Runnable() {
@@ -430,9 +394,9 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase {
// Don't chain since we're going to invoke each animation independently.
mTestableController.setChainedProperties(new HashSet<>());
- mLayout.setController(mTestableController);
+ mLayout.setActiveController(mTestableController);
- addOneMoreThanRenderLimitBubbles();
+ addOneMoreThanBubbleLimitBubbles();
Runnable allEnd = Mockito.mock(Runnable.class);
@@ -452,7 +416,7 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase {
@Test
public void testAnimationsForChildrenFromIndex_noChildren() {
- mLayout.setController(mTestableController);
+ mLayout.setActiveController(mTestableController);
final Runnable after = Mockito.mock(Runnable.class);
mTestableController
@@ -523,8 +487,9 @@ public class PhysicsAnimationLayoutTest extends PhysicsAnimationLayoutTestCase {
}
@Override
- protected void setChildVisibility(View child, int index, int visibility) {
- super.setChildVisibility(child, index, visibility);
- }
+ void onChildReordered(View child, int oldIndex, int newIndex) {}
+
+ @Override
+ void onActiveControllerForLayout(PhysicsAnimationLayout layout) {}
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTestCase.java
index c6acef5d4907..f633f3996d13 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/PhysicsAnimationLayoutTestCase.java
@@ -56,7 +56,6 @@ public class PhysicsAnimationLayoutTestCase extends SysuiTestCase {
Handler mMainThreadHandler;
- int mMaxRenderedBubbles;
int mSystemWindowInsetSize = 50;
int mCutoutInsetSize = 100;
@@ -69,6 +68,8 @@ public class PhysicsAnimationLayoutTestCase extends SysuiTestCase {
@Mock
private DisplayCutout mCutout;
+ private int mMaxBubbles;
+
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
@@ -79,7 +80,7 @@ public class PhysicsAnimationLayoutTestCase extends SysuiTestCase {
mLayout.setTop(0);
mLayout.setBottom(mHeight);
- mMaxRenderedBubbles =
+ mMaxBubbles =
getContext().getResources().getInteger(R.integer.bubbles_max_rendered);
mMainThreadHandler = new Handler(Looper.getMainLooper());
@@ -96,8 +97,8 @@ public class PhysicsAnimationLayoutTestCase extends SysuiTestCase {
}
/** Add one extra bubble over the limit, so we can make sure it's gone/chains appropriately. */
- void addOneMoreThanRenderLimitBubbles() throws InterruptedException {
- for (int i = 0; i < mMaxRenderedBubbles + 1; i++) {
+ void addOneMoreThanBubbleLimitBubbles() throws InterruptedException {
+ for (int i = 0; i < mMaxBubbles + 1; i++) {
final View newView = new FrameLayout(mContext);
mLayout.addView(newView, 0);
mViews.add(0, newView);
@@ -138,6 +139,13 @@ public class PhysicsAnimationLayoutTestCase extends SysuiTestCase {
}
@Override
+ protected boolean isActiveController(PhysicsAnimationController controller) {
+ // Return true since otherwise all test controllers will be seen as inactive since they
+ // are wrapped by MainThreadAnimationControllerWrapper.
+ return true;
+ }
+
+ @Override
public boolean post(Runnable action) {
return mMainThreadHandler.post(action);
}
@@ -148,9 +156,9 @@ public class PhysicsAnimationLayoutTestCase extends SysuiTestCase {
}
@Override
- public void setController(PhysicsAnimationController controller) {
+ public void setActiveController(PhysicsAnimationController controller) {
runOnMainThreadAndBlock(
- () -> super.setController(
+ () -> super.setActiveController(
new MainThreadAnimationControllerWrapper(controller)));
}
@@ -267,8 +275,15 @@ public class PhysicsAnimationLayoutTestCase extends SysuiTestCase {
}
@Override
- protected void setChildVisibility(View child, int index, int visibility) {
- mWrappedController.setChildVisibility(child, index, visibility);
+ void onChildReordered(View child, int oldIndex, int newIndex) {
+ runOnMainThreadAndBlock(
+ () -> mWrappedController.onChildReordered(child, oldIndex, newIndex));
+ }
+
+ @Override
+ void onActiveControllerForLayout(PhysicsAnimationLayout layout) {
+ runOnMainThreadAndBlock(
+ () -> mWrappedController.onActiveControllerForLayout(layout));
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
index 9218a8b93f66..31a7d5a45b68 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/StackAnimationControllerTest.java
@@ -54,8 +54,8 @@ public class StackAnimationControllerTest extends PhysicsAnimationLayoutTestCase
@Before
public void setUp() throws Exception {
super.setUp();
- mLayout.setController(mStackController);
- addOneMoreThanRenderLimitBubbles();
+ mLayout.setActiveController(mStackController);
+ addOneMoreThanBubbleLimitBubbles();
mStackOffset = mLayout.getResources().getDimensionPixelSize(R.dimen.bubble_stack_offset);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java b/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java
index 67df60a3dcfc..9c2c82257173 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java
@@ -19,6 +19,7 @@ package com.android.systemui.colorextraction;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
@@ -36,8 +37,10 @@ import com.android.internal.colorextraction.types.Tonal;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.policy.ConfigurationController;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.MockitoAnnotations;
/**
* Tests color extraction generation.
@@ -54,62 +57,68 @@ public class SysuiColorExtractorTests extends SysuiTestCase {
ColorExtractor.TYPE_DARK,
ColorExtractor.TYPE_EXTRA_DARK};
+ private ColorExtractor.GradientColors mColors;
+ private SysuiColorExtractor mColorExtractor;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mColors = new ColorExtractor.GradientColors();
+ mColors.setMainColor(Color.RED);
+ mColors.setSecondaryColor(Color.RED);
+ mColorExtractor = new SysuiColorExtractor(getContext(),
+ (inWallpaperColors, outGradientColorsNormal, outGradientColorsDark,
+ outGradientColorsExtraDark) -> {
+ outGradientColorsNormal.set(mColors);
+ outGradientColorsDark.set(mColors);
+ outGradientColorsExtraDark.set(mColors);
+ }, mock(ConfigurationController.class), false);
+ }
+
@Test
public void getColors_usesGreyIfWallpaperNotVisible() {
- ColorExtractor.GradientColors colors = new ColorExtractor.GradientColors();
- colors.setMainColor(Color.RED);
- colors.setSecondaryColor(Color.RED);
+ simulateEvent(mColorExtractor);
+ mColorExtractor.setWallpaperVisible(false);
- SysuiColorExtractor extractor = getTestableExtractor(colors);
- simulateEvent(extractor);
- extractor.setWallpaperVisible(false);
-
- ColorExtractor.GradientColors fallbackColors = extractor.getNeutralColors();
+ ColorExtractor.GradientColors fallbackColors = mColorExtractor.getNeutralColors();
for (int type : sTypes) {
assertEquals("Not using fallback!",
- extractor.getColors(WallpaperManager.FLAG_SYSTEM, type), fallbackColors);
+ mColorExtractor.getColors(WallpaperManager.FLAG_SYSTEM, type), fallbackColors);
assertNotEquals("Wallpaper visibility event should not affect lock wallpaper.",
- extractor.getColors(WallpaperManager.FLAG_LOCK, type), fallbackColors);
+ mColorExtractor.getColors(WallpaperManager.FLAG_LOCK, type), fallbackColors);
}
}
@Test
public void getColors_doesntUseFallbackIfVisible() {
- ColorExtractor.GradientColors colors = new ColorExtractor.GradientColors();
- colors.setMainColor(Color.RED);
- colors.setSecondaryColor(Color.RED);
+ mColors.setMainColor(Color.RED);
+ mColors.setSecondaryColor(Color.RED);
- SysuiColorExtractor extractor = getTestableExtractor(colors);
- simulateEvent(extractor);
- extractor.setWallpaperVisible(true);
+ simulateEvent(mColorExtractor);
+ mColorExtractor.setWallpaperVisible(true);
for (int which : sWhich) {
for (int type : sTypes) {
assertEquals("Not using extracted colors!",
- extractor.getColors(which, type), colors);
+ mColorExtractor.getColors(which, type), mColors);
}
}
}
@Test
public void getColors_fallbackWhenMediaIsVisible() {
- ColorExtractor.GradientColors colors = new ColorExtractor.GradientColors();
- colors.setMainColor(Color.RED);
- colors.setSecondaryColor(Color.RED);
-
- SysuiColorExtractor extractor = getTestableExtractor(colors);
- simulateEvent(extractor);
- extractor.setWallpaperVisible(true);
- extractor.setHasBackdrop(true);
+ simulateEvent(mColorExtractor);
+ mColorExtractor.setWallpaperVisible(true);
+ mColorExtractor.setHasBackdrop(true);
- ColorExtractor.GradientColors fallbackColors = extractor.getNeutralColors();
+ ColorExtractor.GradientColors fallbackColors = mColorExtractor.getNeutralColors();
for (int type : sTypes) {
assertEquals("Not using fallback!",
- extractor.getColors(WallpaperManager.FLAG_LOCK, type), fallbackColors);
+ mColorExtractor.getColors(WallpaperManager.FLAG_LOCK, type), fallbackColors);
assertNotEquals("Media visibility should not affect system wallpaper.",
- extractor.getColors(WallpaperManager.FLAG_SYSTEM, type), fallbackColors);
+ mColorExtractor.getColors(WallpaperManager.FLAG_SYSTEM, type), fallbackColors);
}
}
@@ -126,14 +135,13 @@ public class SysuiColorExtractorTests extends SysuiTestCase {
verify(tonal).applyFallback(any(), any());
}
- private SysuiColorExtractor getTestableExtractor(ColorExtractor.GradientColors colors) {
- return new SysuiColorExtractor(getContext(),
- (inWallpaperColors, outGradientColorsNormal, outGradientColorsDark,
- outGradientColorsExtraDark) -> {
- outGradientColorsNormal.set(colors);
- outGradientColorsDark.set(colors);
- outGradientColorsExtraDark.set(colors);
- }, mock(ConfigurationController.class), false);
+ @Test
+ public void onUiModeChanged_notifiesListener() {
+ ColorExtractor.OnColorsChangedListener listener = mock(
+ ColorExtractor.OnColorsChangedListener.class);
+ mColorExtractor.addOnColorsChangedListener(listener);
+ mColorExtractor.onUiModeChanged();
+ verify(listener).onColorsChanged(any(), anyInt());
}
private void simulateEvent(SysuiColorExtractor extractor) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsGridLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsGridLayoutTest.java
index a396f3e8bf46..ea478597ef77 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsGridLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsGridLayoutTest.java
@@ -48,8 +48,9 @@ public class GlobalActionsGridLayoutTest extends SysuiTestCase {
@Before
public void setUp() throws Exception {
- mGridLayout = spy((GlobalActionsGridLayout)
- LayoutInflater.from(mContext).inflate(R.layout.global_actions_grid, null));
+ mGridLayout = spy(LayoutInflater.from(mContext)
+ .inflate(R.layout.global_actions_grid, null)
+ .requireViewById(R.id.global_actions_view));
mListGrid = spy(mGridLayout.getListView());
doReturn(mListGrid).when(mGridLayout).getListView();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/ListGridLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/ListGridLayoutTest.java
index 746140fc725d..74e8cc280979 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/ListGridLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/ListGridLayoutTest.java
@@ -43,8 +43,9 @@ public class ListGridLayoutTest extends SysuiTestCase {
@Before
public void setUp() throws Exception {
- GlobalActionsGridLayout globalActions = (GlobalActionsGridLayout)
- LayoutInflater.from(mContext).inflate(R.layout.global_actions_grid, null);
+ GlobalActionsGridLayout globalActions = LayoutInflater.from(mContext)
+ .inflate(R.layout.global_actions_grid, null)
+ .requireViewById(R.id.global_actions_view);
mListGridLayout = globalActions.getListView();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/MediaArtworkProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/MediaArtworkProcessorTest.kt
new file mode 100644
index 000000000000..72e6df27a254
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/MediaArtworkProcessorTest.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar
+
+import com.google.common.truth.Truth.assertThat
+
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.graphics.Color
+import android.graphics.Point
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import org.junit.After
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+private const val WIDTH = 200
+private const val HEIGHT = 200
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class MediaArtworkProcessorTest : SysuiTestCase() {
+
+ private var screenWidth = 0
+ private var screenHeight = 0
+
+ private lateinit var processor: MediaArtworkProcessor
+
+ @Before
+ fun setUp() {
+ processor = MediaArtworkProcessor()
+
+ val point = Point()
+ context.display.getSize(point)
+ screenWidth = point.x
+ screenHeight = point.y
+ }
+
+ @After
+ fun tearDown() {
+ processor.clearCache()
+ }
+
+ @Test
+ fun testProcessArtwork() {
+ // GIVEN some "artwork", which is just a solid blue image
+ val artwork = Bitmap.createBitmap(WIDTH, HEIGHT, Bitmap.Config.ARGB_8888)
+ Canvas(artwork).drawColor(Color.BLUE)
+ // WHEN the background is created from the artwork
+ val background = processor.processArtwork(context, artwork)!!
+ // THEN the background has the size of the screen that has been downsamples
+ assertThat(background.height).isLessThan(screenHeight)
+ assertThat(background.width).isLessThan(screenWidth)
+ assertThat(background.config).isEqualTo(Bitmap.Config.ARGB_8888)
+ }
+
+ @Test
+ fun testCache() {
+ // GIVEN a solid blue image
+ val artwork = Bitmap.createBitmap(WIDTH, HEIGHT, Bitmap.Config.ARGB_8888)
+ Canvas(artwork).drawColor(Color.BLUE)
+ // WHEN the background is processed twice
+ val background1 = processor.processArtwork(context, artwork)!!
+ val background2 = processor.processArtwork(context, artwork)!!
+ // THEN the two bitmaps are the same
+ // Note: This is currently broken and trying to use caching causes issues
+ assertThat(background1).isNotSameAs(background2)
+ }
+
+ @Test
+ fun testConfig() {
+ // GIVEN some which is not ARGB_8888
+ val artwork = Bitmap.createBitmap(WIDTH, HEIGHT, Bitmap.Config.ALPHA_8)
+ Canvas(artwork).drawColor(Color.BLUE)
+ // WHEN the background is created from the artwork
+ val background = processor.processArtwork(context, artwork)!!
+ // THEN the background has Config ARGB_8888
+ assertThat(background.config).isEqualTo(Bitmap.Config.ARGB_8888)
+ }
+
+ @Test
+ fun testRecycledArtwork() {
+ // GIVEN some "artwork", which is just a solid blue image
+ val artwork = Bitmap.createBitmap(WIDTH, HEIGHT, Bitmap.Config.ARGB_8888)
+ Canvas(artwork).drawColor(Color.BLUE)
+ // AND the artwork is recycled
+ artwork.recycle()
+ // WHEN the background is created from the artwork
+ val background = processor.processArtwork(context, artwork)
+ // THEN the processed bitmap is null
+ assertThat(background).isNull()
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index 4d593c101706..72f3a62f30a7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -402,6 +402,7 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
verify(mRow).setEntry(eq(mEntry));
assertEquals(1, mEntry.systemGeneratedSmartActions.size());
assertEquals("action", mEntry.systemGeneratedSmartActions.get(0).title);
+ verify(mEntryListener).onNotificationRankingUpdated(mRankingMap);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java
index 79a6ac4cb0c7..6e0ddbf0cc46 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationDataTest.java
@@ -28,6 +28,7 @@ import static android.app.NotificationManager.IMPORTANCE_MIN;
import static com.android.systemui.statusbar.notification.collection.NotificationDataTest.TestableNotificationData.OVERRIDE_CHANNEL;
import static com.android.systemui.statusbar.notification.collection.NotificationDataTest.TestableNotificationData.OVERRIDE_IMPORTANCE;
+import static com.android.systemui.statusbar.notification.collection.NotificationDataTest.TestableNotificationData.OVERRIDE_RANK;
import static com.android.systemui.statusbar.notification.collection.NotificationDataTest.TestableNotificationData.OVERRIDE_VIS_EFFECTS;
import static junit.framework.Assert.assertEquals;
@@ -61,16 +62,12 @@ import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
import android.util.ArraySet;
-import androidx.test.filters.SmallTest;
-
import com.android.systemui.Dependency;
import com.android.systemui.ForegroundServiceController;
import com.android.systemui.InitController;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.NotificationTestHelper;
-import com.android.systemui.statusbar.notification.collection.NotificationData;
import com.android.systemui.statusbar.notification.collection.NotificationData.KeyguardEnvironment;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.ShadeController;
@@ -83,7 +80,11 @@ import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
+
+import androidx.test.filters.SmallTest;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@@ -137,7 +138,9 @@ public class NotificationDataTest extends SysuiTestCase {
@Test
public void testChannelSetWhenAdded() {
- mNotificationData.rankingOverrides.putParcelable(OVERRIDE_CHANNEL, NOTIFICATION_CHANNEL);
+ Bundle override = new Bundle();
+ override.putParcelable(OVERRIDE_CHANNEL, NOTIFICATION_CHANNEL);
+ mNotificationData.rankingOverrides.put(mRow.getEntry().key, override);
mNotificationData.add(mRow.getEntry());
assertEquals(NOTIFICATION_CHANNEL, mRow.getEntry().channel);
}
@@ -229,7 +232,9 @@ public class NotificationDataTest extends SysuiTestCase {
n.flags = Notification.FLAG_FOREGROUND_SERVICE;
NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification);
mNotificationData.add(entry);
- mNotificationData.rankingOverrides.putInt(OVERRIDE_VIS_EFFECTS, 255);
+ Bundle override = new Bundle();
+ override.putInt(OVERRIDE_VIS_EFFECTS, 255);
+ mNotificationData.rankingOverrides.put(entry.key, override);
assertTrue(entry.isExemptFromDndVisualSuppression());
assertFalse(entry.shouldSuppressAmbient());
@@ -245,7 +250,9 @@ public class NotificationDataTest extends SysuiTestCase {
when(mMockStatusBarNotification.getNotification()).thenReturn(n);
NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification);
mNotificationData.add(entry);
- mNotificationData.rankingOverrides.putInt(OVERRIDE_VIS_EFFECTS, 255);
+ Bundle override = new Bundle();
+ override.putInt(OVERRIDE_VIS_EFFECTS, 255);
+ mNotificationData.rankingOverrides.put(entry.key, override);
assertTrue(entry.isExemptFromDndVisualSuppression());
assertFalse(entry.shouldSuppressAmbient());
@@ -257,7 +264,9 @@ public class NotificationDataTest extends SysuiTestCase {
NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification);
entry.mIsSystemNotification = true;
mNotificationData.add(entry);
- mNotificationData.rankingOverrides.putInt(OVERRIDE_VIS_EFFECTS, 255);
+ Bundle override = new Bundle();
+ override.putInt(OVERRIDE_VIS_EFFECTS, 255);
+ mNotificationData.rankingOverrides.put(entry.key, override);
assertTrue(entry.isExemptFromDndVisualSuppression());
assertFalse(entry.shouldSuppressAmbient());
@@ -268,8 +277,9 @@ public class NotificationDataTest extends SysuiTestCase {
initStatusBarNotification(false);
NotificationEntry entry = new NotificationEntry(mMockStatusBarNotification);
entry.mIsSystemNotification = true;
- mNotificationData.rankingOverrides.putInt(OVERRIDE_VIS_EFFECTS,
- NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT);
+ Bundle override = new Bundle();
+ override.putInt(OVERRIDE_VIS_EFFECTS, NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT);
+ mNotificationData.rankingOverrides.put(entry.key, override);
mNotificationData.add(entry);
when(mMockStatusBarNotification.getNotification()).thenReturn(
@@ -395,11 +405,13 @@ public class NotificationDataTest extends SysuiTestCase {
Notification notification = mock(Notification.class);
when(notification.isForegroundService()).thenReturn(true);
- mNotificationData.rankingOverrides.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_MIN);
-
StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
notification, mContext.getUser(), "", 0);
+ Bundle override = new Bundle();
+ override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_MIN);
+ mNotificationData.rankingOverrides.put(sbn.getKey(), override);
+
assertFalse(mNotificationData.isHighPriority(sbn));
}
@@ -408,14 +420,114 @@ public class NotificationDataTest extends SysuiTestCase {
Notification notification = mock(Notification.class);
when(notification.isForegroundService()).thenReturn(true);
- mNotificationData.rankingOverrides.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
-
StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
notification, mContext.getUser(), "", 0);
+ Bundle override = new Bundle();
+ override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
+ mNotificationData.rankingOverrides.put(sbn.getKey(), override);
+
assertTrue(mNotificationData.isHighPriority(sbn));
}
+ @Test
+ public void userChangeTrumpsHighPriorityCharacteristics() {
+ Person person = new Person.Builder()
+ .setName("name")
+ .setKey("abc")
+ .setUri("uri")
+ .setBot(true)
+ .build();
+
+ Notification notification = new Notification.Builder(mContext, "test")
+ .addPerson(person)
+ .setStyle(new Notification.MessagingStyle(""))
+ .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
+ .build();
+
+ StatusBarNotification sbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
+ notification, mContext.getUser(), "", 0);
+
+ NotificationChannel channel = new NotificationChannel("a", "a", IMPORTANCE_LOW);
+ channel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
+
+ Bundle override = new Bundle();
+ override.putParcelable(OVERRIDE_CHANNEL, channel);
+ mNotificationData.rankingOverrides.put(sbn.getKey(), override);
+
+ assertFalse(mNotificationData.isHighPriority(sbn));
+ }
+
+ @Test
+ public void testSort_highPriorityTrumpsNMSRank() {
+ // NMS rank says A and then B. But A is not high priority and B is, so B should sort in
+ // front
+ Notification aN = new Notification.Builder(mContext, "test")
+ .setStyle(new Notification.MessagingStyle(""))
+ .build();
+ StatusBarNotification aSbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
+ aN, mContext.getUser(), "", 0);
+ NotificationEntry a = new NotificationEntry(aSbn);
+ a.setRow(mock(ExpandableNotificationRow.class));
+ a.setIsHighPriority(false);
+
+ Bundle override = new Bundle();
+ override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
+ override.putInt(OVERRIDE_RANK, 1);
+ mNotificationData.rankingOverrides.put(a.key, override);
+
+ Notification bN = new Notification.Builder(mContext, "test")
+ .setStyle(new Notification.MessagingStyle(""))
+ .build();
+ StatusBarNotification bSbn = new StatusBarNotification("pkg2", "pkg2", 0, "tag", 0, 0,
+ bN, mContext.getUser(), "", 0);
+ NotificationEntry b = new NotificationEntry(bSbn);
+ b.setIsHighPriority(true);
+ b.setRow(mock(ExpandableNotificationRow.class));
+
+ Bundle bOverride = new Bundle();
+ bOverride.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
+ bOverride.putInt(OVERRIDE_RANK, 2);
+ mNotificationData.rankingOverrides.put(b.key, bOverride);
+
+ assertEquals(1, mNotificationData.mRankingComparator.compare(a, b));
+ }
+
+ @Test
+ public void testSort_samePriorityUsesNMSRank() {
+ // NMS rank says A and then B. But A is not high priority and B is, so B should sort in
+ // front
+ Notification aN = new Notification.Builder(mContext, "test")
+ .setStyle(new Notification.MessagingStyle(""))
+ .build();
+ StatusBarNotification aSbn = new StatusBarNotification("pkg", "pkg", 0, "tag", 0, 0,
+ aN, mContext.getUser(), "", 0);
+ NotificationEntry a = new NotificationEntry(aSbn);
+ a.setRow(mock(ExpandableNotificationRow.class));
+ a.setIsHighPriority(false);
+
+ Bundle override = new Bundle();
+ override.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
+ override.putInt(OVERRIDE_RANK, 1);
+ mNotificationData.rankingOverrides.put(a.key, override);
+
+ Notification bN = new Notification.Builder(mContext, "test")
+ .setStyle(new Notification.MessagingStyle(""))
+ .build();
+ StatusBarNotification bSbn = new StatusBarNotification("pkg2", "pkg2", 0, "tag", 0, 0,
+ bN, mContext.getUser(), "", 0);
+ NotificationEntry b = new NotificationEntry(bSbn);
+ b.setRow(mock(ExpandableNotificationRow.class));
+ b.setIsHighPriority(false);
+
+ Bundle bOverride = new Bundle();
+ bOverride.putInt(OVERRIDE_IMPORTANCE, IMPORTANCE_LOW);
+ bOverride.putInt(OVERRIDE_RANK, 2);
+ mNotificationData.rankingOverrides.put(b.key, bOverride);
+
+ assertEquals(-1, mNotificationData.mRankingComparator.compare(a, b));
+ }
+
private void initStatusBarNotification(boolean allowDuringSetup) {
Bundle bundle = new Bundle();
bundle.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, allowDuringSetup);
@@ -449,7 +561,7 @@ public class NotificationDataTest extends SysuiTestCase {
public static final String OVERRIDE_SMART_REPLIES = "sr";
public static final String OVERRIDE_BUBBLE = "cb";
- public Bundle rankingOverrides = new Bundle();
+ public Map<String, Bundle> rankingOverrides = new HashMap<>();
@Override
protected boolean getRanking(String key, Ranking outRanking) {
@@ -475,40 +587,41 @@ public class NotificationDataTest extends SysuiTestCase {
currentReplies.addAll(outRanking.getSmartReplies());
}
- outRanking.populate(key,
- rankingOverrides.getInt(OVERRIDE_RANK, outRanking.getRank()),
- rankingOverrides.getBoolean(OVERRIDE_DND,
- outRanking.matchesInterruptionFilter()),
- rankingOverrides.getInt(OVERRIDE_VIS_OVERRIDE,
- outRanking.getVisibilityOverride()),
- rankingOverrides.getInt(OVERRIDE_VIS_EFFECTS,
- outRanking.getSuppressedVisualEffects()),
- rankingOverrides.getInt(OVERRIDE_IMPORTANCE, outRanking.getImportance()),
- rankingOverrides.getCharSequence(OVERRIDE_IMP_EXP,
- outRanking.getImportanceExplanation()),
- rankingOverrides.getString(OVERRIDE_GROUP, outRanking.getOverrideGroupKey()),
- rankingOverrides.containsKey(OVERRIDE_CHANNEL)
- ? (NotificationChannel) rankingOverrides.getParcelable(OVERRIDE_CHANNEL)
- : outRanking.getChannel(),
- rankingOverrides.containsKey(OVERRIDE_PEOPLE)
- ? rankingOverrides.getStringArrayList(OVERRIDE_PEOPLE)
- : currentAdditionalPeople,
- rankingOverrides.containsKey(OVERRIDE_SNOOZE_CRITERIA)
- ? rankingOverrides.getParcelableArrayList(OVERRIDE_SNOOZE_CRITERIA)
- : currentSnooze,
- rankingOverrides.getBoolean(OVERRIDE_BADGE, outRanking.canShowBadge()),
- rankingOverrides.getInt(OVERRIDE_USER_SENTIMENT, outRanking.getUserSentiment()),
- rankingOverrides.getBoolean(OVERRIDE_HIDDEN, outRanking.isSuspended()),
- rankingOverrides.getLong(OVERRIDE_LAST_ALERTED,
- outRanking.getLastAudiblyAlertedMillis()),
- rankingOverrides.getBoolean(OVERRIDE_NOISY, outRanking.isNoisy()),
- rankingOverrides.containsKey(OVERRIDE_SMART_ACTIONS)
- ? rankingOverrides.getParcelableArrayList(OVERRIDE_SMART_ACTIONS)
- : currentActions,
- rankingOverrides.containsKey(OVERRIDE_SMART_REPLIES)
- ? rankingOverrides.getCharSequenceArrayList(OVERRIDE_SMART_REPLIES)
- : currentReplies,
- rankingOverrides.getBoolean(OVERRIDE_BUBBLE, outRanking.canBubble()));
+ if (rankingOverrides.get(key) != null) {
+ Bundle overrides = rankingOverrides.get(key);
+ outRanking.populate(key,
+ overrides.getInt(OVERRIDE_RANK, outRanking.getRank()),
+ overrides.getBoolean(OVERRIDE_DND, outRanking.matchesInterruptionFilter()),
+ overrides.getInt(OVERRIDE_VIS_OVERRIDE, outRanking.getVisibilityOverride()),
+ overrides.getInt(OVERRIDE_VIS_EFFECTS,
+ outRanking.getSuppressedVisualEffects()),
+ overrides.getInt(OVERRIDE_IMPORTANCE, outRanking.getImportance()),
+ overrides.getCharSequence(OVERRIDE_IMP_EXP,
+ outRanking.getImportanceExplanation()),
+ overrides.getString(OVERRIDE_GROUP, outRanking.getOverrideGroupKey()),
+ overrides.containsKey(OVERRIDE_CHANNEL)
+ ? (NotificationChannel) overrides.getParcelable(OVERRIDE_CHANNEL)
+ : outRanking.getChannel(),
+ overrides.containsKey(OVERRIDE_PEOPLE)
+ ? overrides.getStringArrayList(OVERRIDE_PEOPLE)
+ : currentAdditionalPeople,
+ overrides.containsKey(OVERRIDE_SNOOZE_CRITERIA)
+ ? overrides.getParcelableArrayList(OVERRIDE_SNOOZE_CRITERIA)
+ : currentSnooze,
+ overrides.getBoolean(OVERRIDE_BADGE, outRanking.canShowBadge()),
+ overrides.getInt(OVERRIDE_USER_SENTIMENT, outRanking.getUserSentiment()),
+ overrides.getBoolean(OVERRIDE_HIDDEN, outRanking.isSuspended()),
+ overrides.getLong(OVERRIDE_LAST_ALERTED,
+ outRanking.getLastAudiblyAlertedMillis()),
+ overrides.getBoolean(OVERRIDE_NOISY, outRanking.isNoisy()),
+ overrides.containsKey(OVERRIDE_SMART_ACTIONS)
+ ? overrides.getParcelableArrayList(OVERRIDE_SMART_ACTIONS)
+ : currentActions,
+ overrides.containsKey(OVERRIDE_SMART_REPLIES)
+ ? overrides.getCharSequenceArrayList(OVERRIDE_SMART_REPLIES)
+ : currentReplies,
+ overrides.getBoolean(OVERRIDE_BUBBLE, outRanking.canBubble()));
+ }
return true;
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
index 43ea92f13c8d..13b9d56e5a14 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationMenuRowTest.java
@@ -15,6 +15,7 @@
package com.android.systemui.statusbar.notification.row;
import static android.provider.Settings.Secure.NOTIFICATION_NEW_INTERRUPTION_MODEL;
+import static android.provider.Settings.Secure.SHOW_NOTIFICATION_SNOOZE;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
@@ -100,8 +101,31 @@ public class NotificationMenuRowTest extends LeakCheckedTest {
@Test
public void testNoAppOpsInSlowSwipe() {
- Settings.Secure.putInt(mContext.getContentResolver(),
- NOTIFICATION_NEW_INTERRUPTION_MODEL, 0);
+ Settings.Secure.putInt(mContext.getContentResolver(), SHOW_NOTIFICATION_SNOOZE, 0);
+
+ NotificationMenuRow row = new NotificationMenuRow(mContext);
+ row.createMenu(mRow, null);
+
+ ViewGroup container = (ViewGroup) row.getMenuView();
+ // noti blocking
+ assertEquals(1, container.getChildCount());
+ }
+
+ @Test
+ public void testNoSnoozeInSlowSwipe() {
+ Settings.Secure.putInt(mContext.getContentResolver(), SHOW_NOTIFICATION_SNOOZE, 0);
+
+ NotificationMenuRow row = new NotificationMenuRow(mContext);
+ row.createMenu(mRow, null);
+
+ ViewGroup container = (ViewGroup) row.getMenuView();
+ // just for noti blocking
+ assertEquals(1, container.getChildCount());
+ }
+
+ @Test
+ public void testSnoozeInSlowSwipe() {
+ Settings.Secure.putInt(mContext.getContentResolver(), SHOW_NOTIFICATION_SNOOZE, 1);
NotificationMenuRow row = new NotificationMenuRow(mContext);
row.createMenu(mRow, null);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java
new file mode 100644
index 000000000000..df41a8424fda
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.row.wrapper;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.argThat;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.app.Notification;
+import android.media.MediaMetadata;
+import android.media.session.MediaSession;
+import android.media.session.PlaybackState;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.View;
+import android.widget.RemoteViews;
+import android.widget.SeekBar;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.NotificationTestHelper;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+public class NotificationMediaTemplateViewWrapperTest extends SysuiTestCase {
+
+ private ExpandableNotificationRow mRow;
+ private Notification mNotif;
+ private View mView;
+ private NotificationMediaTemplateViewWrapper mWrapper;
+
+ @Mock
+ private MetricsLogger mMetricsLogger;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
+
+ mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
+ }
+
+ private void makeTestNotification(long duration, boolean allowSeeking) throws Exception {
+ Notification.Builder builder = new Notification.Builder(mContext)
+ .setSmallIcon(R.drawable.ic_person)
+ .setContentTitle("Title")
+ .setContentText("Text");
+
+ MediaMetadata metadata = new MediaMetadata.Builder()
+ .putLong(MediaMetadata.METADATA_KEY_DURATION, duration)
+ .build();
+ MediaSession session = new MediaSession(mContext, "TEST_CHANNEL");
+ session.setMetadata(metadata);
+
+ PlaybackState playbackState = new PlaybackState.Builder()
+ .setActions(allowSeeking ? PlaybackState.ACTION_SEEK_TO : 0)
+ .build();
+
+ session.setPlaybackState(playbackState);
+
+ builder.setStyle(new Notification.MediaStyle()
+ .setMediaSession(session.getSessionToken())
+ );
+
+ mNotif = builder.build();
+ assertTrue(mNotif.hasMediaSession());
+
+ mRow = new NotificationTestHelper(mContext).createRow(mNotif);
+
+ RemoteViews views = new RemoteViews(mContext.getPackageName(),
+ com.android.internal.R.layout.notification_template_material_big_media);
+ mView = views.apply(mContext, null);
+ mWrapper = new NotificationMediaTemplateViewWrapper(mContext,
+ mView, mRow);
+ mWrapper.onContentUpdated(mRow);
+ }
+
+ @Test
+ public void testLogging_NoSeekbar() throws Exception {
+ // Media sessions with duration <= 0 should not include a seekbar
+ makeTestNotification(0, false);
+
+ verify(mMetricsLogger).write(argThat(logMaker ->
+ logMaker.getCategory() == MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR
+ && logMaker.getType() == MetricsEvent.TYPE_CLOSE
+ ));
+
+ verify(mMetricsLogger, times(0)).write(argThat(logMaker ->
+ logMaker.getCategory() == MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR
+ && logMaker.getType() == MetricsEvent.TYPE_OPEN
+ ));
+ }
+
+ @Test
+ public void testLogging_HasSeekbarNoScrubber() throws Exception {
+ // Media sessions that do not support seeking should have a seekbar, but no scrubber
+ makeTestNotification(1000, false);
+
+ verify(mMetricsLogger).write(argThat(logMaker ->
+ logMaker.getCategory() == MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR
+ && logMaker.getType() == MetricsEvent.TYPE_OPEN
+ ));
+
+ // Ensure the callback runs at least once
+ mWrapper.mUpdatePlaybackUi.run();
+
+ verify(mMetricsLogger).write(argThat(logMaker ->
+ logMaker.getCategory() == MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR
+ && logMaker.getType() == MetricsEvent.TYPE_DETAIL
+ && logMaker.getSubtype() == 0
+ ));
+ }
+
+ @Test
+ public void testLogging_HasSeekbarAndScrubber() throws Exception {
+ makeTestNotification(1000, true);
+
+ verify(mMetricsLogger).write(argThat(logMaker ->
+ logMaker.getCategory() == MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR
+ && logMaker.getType() == MetricsEvent.TYPE_OPEN
+ ));
+
+ verify(mMetricsLogger).write(argThat(logMaker ->
+ logMaker.getCategory() == MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR
+ && logMaker.getType() == MetricsEvent.TYPE_DETAIL
+ && logMaker.getSubtype() == 1
+ ));
+ }
+
+ @Test
+ public void testLogging_UpdateSeekbar() throws Exception {
+ makeTestNotification(1000, true);
+
+ SeekBar seekbar = mView.findViewById(
+ com.android.internal.R.id.notification_media_progress_bar);
+ assertTrue(seekbar != null);
+
+ mWrapper.mSeekListener.onStopTrackingTouch(seekbar);
+
+ verify(mMetricsLogger).write(argThat(logMaker ->
+ logMaker.getCategory() == MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR
+ && logMaker.getType() == MetricsEvent.TYPE_UPDATE));
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 56265d08c131..662edd2d58cd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -194,9 +194,9 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
public void testAntiBurnInOffset() {
final int burnInOffset = 30;
mStackScroller.setAntiBurnInOffsetX(burnInOffset);
- mStackScroller.setDark(false /* dark */, false /* animated */, null /* touch */);
+ mStackScroller.setDarkAmount(0.0f, 0.0f);
Assert.assertEquals(0 /* expected */, mStackScroller.getTranslationX(), 0.01 /* delta */);
- mStackScroller.setDark(true /* dark */, false /* animated */, null /* touch */);
+ mStackScroller.setDarkAmount(1.0f, 1.0f);
Assert.assertEquals(burnInOffset /* expected */, mStackScroller.getTranslationX(),
0.01 /* delta */);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
index f8394f01a081..66c61ce9b7e8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
@@ -383,7 +383,7 @@ public class KeyguardClockPositionAlgorithmTest extends SysuiTestCase {
private void positionClock() {
mClockPositionAlgorithm.setup(EMPTY_MARGIN, SCREEN_HEIGHT, mNotificationStackHeight,
mPanelExpansion, SCREEN_HEIGHT, mKeyguardStatusHeight, mPreferredClockY,
- mHasCustomClock, mHasVisibleNotifs, mDark, ZERO_DRAG);
+ mHasCustomClock, mHasVisibleNotifs, mDark, ZERO_DRAG, false /* positionLikeDark */);
mClockPositionAlgorithm.run(mClockPosition);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
index 4181d38ad2c5..faf5a9706735 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarFragmentTest.java
@@ -268,7 +268,7 @@ public class NavigationBarFragmentTest extends SysuiBaseFragmentTest {
when(view.getRecentsButton()).thenReturn(mock(ButtonDispatcher.class));
when(view.getAccessibilityButton()).thenReturn(mock(ButtonDispatcher.class));
when(view.getRotateSuggestionButton()).thenReturn(mock(RotationContextButton.class));
- when(view.getBarTransitions()).thenReturn(mock(BarTransitions.class));
+ when(view.getBarTransitions()).thenReturn(mock(NavigationBarTransitions.class));
when(view.getLightTransitionsController()).thenReturn(
mock(LightBarTransitionsController.class));
when(view.getRotationButtonController()).thenReturn(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index 1b7ca952dbfe..e0e4a25a9f90 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -49,6 +49,7 @@ import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.InjectionInflationController;
import org.junit.Before;
@@ -111,12 +112,16 @@ public class NotificationPanelViewTest extends SysuiTestCase {
mDependency.injectMockDependency(NotificationLockscreenUserManager.class);
mDependency.injectMockDependency(ConfigurationController.class);
mDependency.injectMockDependency(ZenModeController.class);
+ KeyguardBypassController bypassController = new KeyguardBypassController(mContext,
+ mock(TunerService.class));
NotificationWakeUpCoordinator coordinator =
new NotificationWakeUpCoordinator(mContext,
new AmbientPulseManager(mContext),
- new StatusBarStateControllerImpl());
+ new StatusBarStateControllerImpl(),
+ bypassController);
PulseExpansionHandler expansionHandler = new PulseExpansionHandler(mContext, coordinator);
- mNotificationPanelView = new TestableNotificationPanelView(coordinator, expansionHandler);
+ mNotificationPanelView = new TestableNotificationPanelView(coordinator, expansionHandler,
+ bypassController);
mNotificationPanelView.setHeadsUpManager(mHeadsUpManager);
mNotificationPanelView.setBar(mPanelBar);
@@ -128,7 +133,7 @@ public class NotificationPanelViewTest extends SysuiTestCase {
public void testSetDozing_notifiesNsslAndStateController() {
mNotificationPanelView.setDozing(true /* dozing */, true /* animate */, null /* touch */);
InOrder inOrder = inOrder(mNotificationStackScrollLayout, mStatusBarStateController);
- inOrder.verify(mNotificationStackScrollLayout).setDark(eq(true), eq(true), eq(null));
+ inOrder.verify(mNotificationStackScrollLayout).setDozing(eq(true), eq(true), eq(null));
inOrder.verify(mStatusBarStateController).setDozeAmount(eq(1f), eq(true));
}
@@ -178,11 +183,13 @@ public class NotificationPanelViewTest extends SysuiTestCase {
private class TestableNotificationPanelView extends NotificationPanelView {
TestableNotificationPanelView(NotificationWakeUpCoordinator coordinator,
- PulseExpansionHandler expansionHandler) {
+ PulseExpansionHandler expansionHandler,
+ KeyguardBypassController bypassController) {
super(NotificationPanelViewTest.this.mContext, null,
new InjectionInflationController(
SystemUIFactory.getInstance().getRootComponent()),
- coordinator, expansionHandler, mock(DynamicPrivacyController.class));
+ coordinator, expansionHandler, mock(DynamicPrivacyController.class),
+ bypassController);
mNotificationStackScroller = mNotificationStackScrollLayout;
mKeyguardStatusView = NotificationPanelViewTest.this.mKeyguardStatusView;
mKeyguardStatusBar = NotificationPanelViewTest.this.mKeyguardStatusBar;
diff --git a/packages/overlays/Android.mk b/packages/overlays/Android.mk
index 2675e900fd6d..3f16c128f664 100644
--- a/packages/overlays/Android.mk
+++ b/packages/overlays/Android.mk
@@ -49,7 +49,10 @@ LOCAL_REQUIRED_MODULES := \
IconShapeTeardropOverlay \
NavigationBarMode3ButtonOverlay \
NavigationBarMode2ButtonOverlay \
- NavigationBarModeGesturalOverlay
+ NavigationBarModeGesturalOverlay \
+ NavigationBarModeGesturalOverlayNarrowBack \
+ NavigationBarModeGesturalOverlayWideBack \
+ NavigationBarModeGesturalOverlayExtraWideBack
include $(BUILD_PHONY_PACKAGE)
include $(CLEAR_VARS)
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_battery_status_bad_24dp.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_battery_80_24dp.xml
index 22e183c694d5..4d8dbdba9207 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_battery_status_bad_24dp.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_battery_80_24dp.xml
@@ -21,5 +21,5 @@
android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M10,2v2H8.33C7.6,4,7,4.6,7,5.33v15.33C7,21.4,7.6,22,8.33,22h7.33C16.4,22,17,21.4,17,20.67V5.33C17,4.6,16.4,4,15.67,4 H14V2H10z M15,13c0,0.55-0.45,1-1,1h-1v1c0,0.55-0.45,1-1,1s-1-0.45-1-1v-1h-1c-0.55,0-1-0.45-1-1s0.45-1,1-1h1v-1 c0-0.55,0.45-1,1-1s1,0.45,1,1v1h1C14.55,12,15,12.45,15,13z" />
+ android:pathData="M18,19V7c0-1.66-1.34-3-3-3h-1c0-0.55-0.45-1-1-1h-2c-0.55,0-1,0.45-1,1H9C7.34,4,6,5.34,6,7v12c0,1.66,1.34,3,3,3h6 C16.66,22,18,20.66,18,19z M9,5.5h6c0.83,0,1.5,0.67,1.5,1.5v1h-9V7C7.5,6.17,8.17,5.5,9,5.5z" />
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bt_misc_hid.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bt_misc_hid.xml
index e182886d4252..5096f2f0f2e9 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bt_misc_hid.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_bt_misc_hid.xml
@@ -20,7 +20,6 @@
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
- <path android:pathData="M0,0h24v24H0V0z" />
<path
android:fillColor="@android:color/white"
android:pathData="M9,16.5V20c0,1.1,0.9,2,2,2h2c1.1,0,2-0.9,2-2v-3.5l-3-3L9,16.5z M13.5,20c0,0.28-0.22,0.5-0.5,0.5h-2 c-0.28,0-0.5-0.22-0.5-0.5v-2.88l1.5-1.5l1.5,1.5V20z M15,7.5V4c0-1.1-0.9-2-2-2h-2C9.9,2,9,2.9,9,4v3.5l3,3L15,7.5z M10.5,4 c0-0.28,0.22-0.5,0.5-0.5h2c0.28,0,0.5,0.22,0.5,0.5v2.88L12,8.38l-1.5-1.5V4z M7.5,9H4c-1.1,0-2,0.9-2,2v2c0,1.1,0.9,2,2,2h3.5 l3-3L7.5,9z M6.88,13.5H4c-0.28,0-0.5-0.22-0.5-0.5v-2c0-0.28,0.22-0.5,0.5-0.5h2.88l1.5,1.5L6.88,13.5z M20,9h-3.5l-3,3l3,3H20 c1.1,0,2-0.9,2-2v-2C22,9.9,21.1,9,20,9z M20.5,13c0,0.28-0.22,0.5-0.5,0.5h-2.88l-1.5-1.5l1.5-1.5H20c0.28,0,0.5,0.22,0.5,0.5V13z" />
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_file_copy.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_file_copy.xml
index dc6ab95e23b1..b8e9845d5039 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_file_copy.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_file_copy.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="#FF737373"
+ android:tint="@*android:color/material_grey_600"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_lock.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_lock.xml
index 1e3400b40e79..5a67f95788ee 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_lock.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_lock.xml
@@ -16,7 +16,6 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="32dp"
- android:tint="?android:attr/textColor"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="32dp" >
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_lock_open.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_lock_open.xml
index f4606a2a9d3e..21abd6e2d3ba 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_lock_open.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_lock_open.xml
@@ -16,7 +16,6 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="32dp"
- android:tint="?android:attr/textColor"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="32dp" >
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_lockscreen_ime.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_lockscreen_ime.xml
index 4344e32a75aa..455bdd50ceba 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_lockscreen_ime.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_lockscreen_ime.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_mode_edit.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_mode_edit.xml
index f0d782e03d11..aca3d52c1a24 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_mode_edit.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_mode_edit.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_delete_accent.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_notifications_alerted.xml
index b4d88271284c..86863b3b6c98 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_delete_accent.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_notifications_alerted.xml
@@ -16,17 +16,19 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="?android:attr/colorAccent"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M9,20h6c1.66,0,3-1.34,3-3V6h0.5c0.41,0,0.75-0.34,0.75-0.75S18.91,4.5,18.5,4.5H18h-3l-1-1h-4l-1,1H6H5.5 c-0.41,0-0.75,0.34-0.75,0.75S5.09,6,5.5,6H6v11C6,18.66,7.34,20,9,20z M16.5,6v11c0,0.83-0.67,1.5-1.5,1.5H9 c-0.83,0-1.5-0.67-1.5-1.5V6H16.5z" />
+ android:pathData="M5.85,3.01C3.72,4.82,2.5,7.46,2.5,10.25C2.5,10.66,2.84,11,3.25,11S4,10.66,4,10.25c0-2.35,1.03-4.57,2.82-6.1 C7.14,3.88,7.17,3.41,6.91,3.1C6.64,2.78,6.17,2.74,5.85,3.01z" />
<path
android:fillColor="@android:color/white"
- android:pathData="M13.97,16c0.41,0,0.75-0.34,0.75-0.75v-6.5c0-0.41-0.34-0.75-0.75-0.75s-0.75,0.34-0.75,0.75v6.5 C13.22,15.66,13.55,16,13.97,16z" />
+ android:pathData="M21.5,10.25c0-2.79-1.22-5.43-3.35-7.24c-0.32-0.27-0.79-0.23-1.06,0.08c-0.27,0.32-0.23,0.79,0.08,1.06 C18.97,5.68,20,7.9,20,10.25c0,0.41,0.34,0.75,0.75,0.75S21.5,10.66,21.5,10.25z" />
<path
android:fillColor="@android:color/white"
- android:pathData="M10,16c0.41,0,0.75-0.34,0.75-0.75v-6.5C10.75,8.34,10.41,8,10,8S9.25,8.34,9.25,8.75v6.5C9.25,15.66,9.59,16,10,16z" />
+ android:pathData="M12,2.5c-0.83,0-1.5,0.67-1.5,1.5v0.7C7.91,5.36,6,7.71,6,10.5V15c0,0.55-0.45,1-1,1s-1,0.45-1,1v2h16v-2 c0-0.55-0.45-1-1-1s-1-0.45-1-1v-4.5c0-2.79-1.91-5.14-4.5-5.8V4C13.5,3.17,12.83,2.5,12,2.5z M16.5,10.5V15 c0,1.21,0.86,2.22,2,2.45v0.05h-13v-0.05c1.14-0.23,2-1.24,2-2.45v-4.5C7.5,8.02,9.52,6,12,6S16.5,8.02,16.5,10.5z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M14,20h-4c0,1.1,0.9,2,2,2S14,21.1,14,20z" />
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_phone.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_phone.xml
index 28733c1890cb..85c184b9f9a8 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_phone.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_phone.xml
@@ -15,7 +15,9 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_qs_battery_saver.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_qs_battery_saver.xml
index a558337902c4..73310b03f625 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_qs_battery_saver.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_qs_battery_saver.xml
@@ -15,7 +15,9 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_qs_bluetooth.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_qs_bluetooth.xml
index 452a032c49e9..19731249bfc7 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_qs_bluetooth.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_qs_bluetooth.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_0_4_bar.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_0_4_bar.xml
index e09aeb7f1d2f..d9dfa54697e4 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_0_4_bar.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_0_4_bar.xml
@@ -19,28 +19,32 @@
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
- <path
- android:fillAlpha="0.3"
- android:fillColor="@android:color/white"
- android:pathData="M20,22H18.5V4.75A0.76 0.76 ,0,0,1,19.25,4h0a0.76 0.76 ,0,0,1,0.75 0.75 Z"
- android:strokeAlpha="0.3"
- android:strokeWidth="1" />
- <path
- android:fillAlpha="0.3"
- android:fillColor="@android:color/white"
- android:pathData="M15.33,22h-1.5V9.75A0.76 0.76 ,0,0,1,14.58,9h0a0.75 0.75 ,0,0,1,0.75 0.75 Z"
- android:strokeAlpha="0.3"
- android:strokeWidth="1" />
- <path
- android:fillAlpha="0.3"
- android:fillColor="@android:color/white"
- android:pathData="M10.67,22H9.17V14.75A0.75 0.75 ,0,0,1,9.92,14h0a0.76 0.76 ,0,0,1,0.75 0.75 Z"
- android:strokeAlpha="0.3"
- android:strokeWidth="1" />
- <path
- android:fillAlpha="0.3"
- android:fillColor="@android:color/white"
- android:pathData="M6,22H4.5V19.75A0.76 0.76 ,0,0,1,5.25,19h0a0.76 0.76 ,0,0,1,0.75 0.75 Z"
- android:strokeAlpha="0.3"
- android:strokeWidth="1" />
+ <group
+ android:translateX="4.000000"
+ android:translateY="3.000000" >
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M16,18 L14.5,18 L14.5,0.75 C14.5053858,0.338037936 14.8380379,0.00538581231 15.25,0 L15.25,0 C15.6619621,0.00538581231 15.9946142,0.338037936 16,0.75 L16,18 Z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M11.33,18 L9.83,18 L9.83,5.75 C9.83538581,5.33803794 10.1680379,5.00538581 10.58,5 L10.58,5 C10.9942136,5 11.33,5.33578644 11.33,5.75 L11.33,18 Z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M6.67,18 L5.17,18 L5.17,10.75 C5.17,10.3357864 5.50578644,10 5.92,10 L5.92,10 C6.33196206,10.0053858 6.66461419,10.3380379 6.67,10.75 L6.67,18 Z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M2,18 L0.5,18 L0.5,15.75 C0.505385812,15.3380379 0.838037936,15.0053858 1.25,15 L1.25,15 C1.66196206,15.0053858 1.99461419,15.3380379 2,15.75 L2,18 Z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ </group>
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_1_4_bar.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_1_4_bar.xml
index 26e96ab4c5c8..70f91afab7d5 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_1_4_bar.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_1_4_bar.xml
@@ -19,25 +19,30 @@
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
- <path
- android:fillAlpha="0.3"
- android:fillColor="@android:color/white"
- android:pathData="M20,22H18.5V4.75A0.76 0.76 ,0,0,1,19.25,4h0a0.76 0.76 ,0,0,1,0.75 0.75 Z"
- android:strokeAlpha="0.3"
- android:strokeWidth="1" />
- <path
- android:fillAlpha="0.3"
- android:fillColor="@android:color/white"
- android:pathData="M15.33,22h-1.5V9.75A0.76 0.76 ,0,0,1,14.58,9h0a0.75 0.75 ,0,0,1,0.75 0.75 Z"
- android:strokeAlpha="0.3"
- android:strokeWidth="1" />
- <path
- android:fillAlpha="0.3"
- android:fillColor="@android:color/white"
- android:pathData="M10.67,22H9.17V14.75A0.75 0.75 ,0,0,1,9.92,14h0a0.76 0.76 ,0,0,1,0.75 0.75 Z"
- android:strokeAlpha="0.3"
- android:strokeWidth="1" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M6,22H4.5V19.75A0.76 0.76 ,0,0,1,5.25,19h0a0.76 0.76 ,0,0,1,0.75 0.75 Z" />
+ <group
+ android:translateX="4.000000"
+ android:translateY="3.000000" >
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M16,18 L14.5,18 L14.5,0.75 C14.5053858,0.338037936 14.8380379,0.00538581231 15.25,0 L15.25,0 C15.6619621,0.00538581231 15.9946142,0.338037936 16,0.75 L16,18 Z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M11.33,18 L9.83,18 L9.83,5.75 C9.83538581,5.33803794 10.1680379,5.00538581 10.58,5 L10.58,5 C10.9942136,5 11.33,5.33578644 11.33,5.75 L11.33,18 Z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M6.67,18 L5.17,18 L5.17,10.75 C5.17,10.3357864 5.50578644,10 5.92,10 L5.92,10 C6.33196206,10.0053858 6.66461419,10.3380379 6.67,10.75 L6.67,18 Z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M2,18 L0.5,18 L0.5,15.75 C0.505385812,15.3380379 0.838037936,15.0053858 1.25,15 L1.25,15 C1.66196206,15.0053858 1.99461419,15.3380379 2,15.75 L2,18 Z"
+ android:strokeWidth="1" />
+ </group>
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_2_4_bar.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_2_4_bar.xml
index 53be899d5a8d..f014eea9354f 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_2_4_bar.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_2_4_bar.xml
@@ -19,22 +19,28 @@
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
- <path
- android:fillAlpha="0.3"
- android:fillColor="@android:color/white"
- android:pathData="M20,22H18.5V4.75A0.76 0.76 ,0,0,1,19.25,4h0a0.76 0.76 ,0,0,1,0.75 0.75 Z"
- android:strokeAlpha="0.3"
- android:strokeWidth="1" />
- <path
- android:fillAlpha="0.3"
- android:fillColor="@android:color/white"
- android:pathData="M15.33,22h-1.5V9.75A0.76 0.76 ,0,0,1,14.58,9h0a0.75 0.75 ,0,0,1,0.75 0.75 Z"
- android:strokeAlpha="0.3"
- android:strokeWidth="1" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M10.67,22H9.17V14.75A0.75 0.75 ,0,0,1,9.92,14h0a0.76 0.76 ,0,0,1,0.75 0.75 Z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M6,22H4.5V19.75A0.76 0.76 ,0,0,1,5.25,19h0a0.76 0.76 ,0,0,1,0.75 0.75 Z" />
+ <group
+ android:translateX="4.000000"
+ android:translateY="3.000000" >
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M16,18 L14.5,18 L14.5,0.75 C14.5053858,0.338037936 14.8380379,0.00538581231 15.25,0 L15.25,0 C15.6619621,0.00538581231 15.9946142,0.338037936 16,0.75 L16,18 Z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M11.33,18 L9.83,18 L9.83,5.75 C9.83538581,5.33803794 10.1680379,5.00538581 10.58,5 L10.58,5 C10.9942136,5 11.33,5.33578644 11.33,5.75 L11.33,18 Z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M6.67,18 L5.17,18 L5.17,10.75 C5.17,10.3357864 5.50578644,10 5.92,10 L5.92,10 C6.33196206,10.0053858 6.66461419,10.3380379 6.67,10.75 L6.67,18 Z"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M2,18 L0.5,18 L0.5,15.75 C0.505385812,15.3380379 0.838037936,15.0053858 1.25,15 L1.25,15 C1.66196206,15.0053858 1.99461419,15.3380379 2,15.75 L2,18 Z"
+ android:strokeWidth="1" />
+ </group>
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_3_4_bar.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_3_4_bar.xml
index 9139bb449509..9b83fab35144 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_3_4_bar.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_3_4_bar.xml
@@ -19,19 +19,26 @@
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
- <path
- android:fillAlpha="0.3"
- android:fillColor="@android:color/white"
- android:pathData="M20,22H18.5V4.75A0.76 0.76 ,0,0,1,19.25,4h0a0.76 0.76 ,0,0,1,0.75 0.75 Z"
- android:strokeAlpha="0.3"
- android:strokeWidth="1" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M15.33,22h-1.5V9.75A0.76 0.76 ,0,0,1,14.58,9h0a0.75 0.75 ,0,0,1,0.75 0.75 Z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M10.67,22H9.17V14.75A0.75 0.75 ,0,0,1,9.92,14h0a0.76 0.76 ,0,0,1,0.75 0.75 Z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M6,22H4.5V19.75A0.76 0.76 ,0,0,1,5.25,19h0a0.76 0.76 ,0,0,1,0.75 0.75 Z" />
+ <group
+ android:translateX="4.000000"
+ android:translateY="3.000000" >
+ <path
+ android:fillAlpha="0.3"
+ android:fillColor="@android:color/white"
+ android:pathData="M16,18 L14.5,18 L14.5,0.75 C14.5053858,0.338037936 14.8380379,0.00538581231 15.25,0 L15.25,0 C15.6619621,0.00538581231 15.9946142,0.338037936 16,0.75 L16,18 Z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M11.33,18 L9.83,18 L9.83,5.75 C9.83538581,5.33803794 10.1680379,5.00538581 10.58,5 L10.58,5 C10.9942136,5 11.33,5.33578644 11.33,5.75 L11.33,18 Z"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M6.67,18 L5.17,18 L5.17,10.75 C5.17,10.3357864 5.50578644,10 5.92,10 L5.92,10 C6.33196206,10.0053858 6.66461419,10.3380379 6.67,10.75 L6.67,18 Z"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M2,18 L0.5,18 L0.5,15.75 C0.505385812,15.3380379 0.838037936,15.0053858 1.25,15 L1.25,15 C1.66196206,15.0053858 1.99461419,15.3380379 2,15.75 L2,18 Z"
+ android:strokeWidth="1" />
+ </group>
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_4_4_bar.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_4_4_bar.xml
index 2c8d70123f60..6f7f48d1ea96 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_4_4_bar.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/ic_signal_cellular_4_4_bar.xml
@@ -19,16 +19,24 @@
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
- <path
- android:fillColor="@android:color/white"
- android:pathData="M20,22H18.5V4.75A0.76 0.76 ,0,0,1,19.25,4h0a0.76 0.76 ,0,0,1,0.75 0.75 Z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M15.33,22h-1.5V9.75A0.76 0.76 ,0,0,1,14.58,9h0a0.75 0.75 ,0,0,1,0.75 0.75 Z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M10.67,22H9.17V14.75A0.75 0.75 ,0,0,1,9.92,14h0a0.76 0.76 ,0,0,1,0.75 0.75 Z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M6,22H4.5V19.75A0.76 0.76 ,0,0,1,5.25,19h0a0.76 0.76 ,0,0,1,0.75 0.75 Z" />
+ <group
+ android:translateX="4.000000"
+ android:translateY="3.000000" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M16,18 L14.5,18 L14.5,0.75 C14.5053858,0.338037936 14.8380379,0.00538581231 15.25,0 L15.25,0 C15.6619621,0.00538581231 15.9946142,0.338037936 16,0.75 L16,18 Z"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M11.33,18 L9.83,18 L9.83,5.75 C9.83538581,5.33803794 10.1680379,5.00538581 10.58,5 L10.58,5 C10.9942136,5 11.33,5.33578644 11.33,5.75 L11.33,18 Z"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M6.67,18 L5.17,18 L5.17,10.75 C5.17,10.3357864 5.50578644,10 5.92,10 L5.92,10 C6.33196206,10.0053858 6.66461419,10.3380379 6.67,10.75 L6.67,18 Z"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M2,18 L0.5,18 L0.5,15.75 C0.505385812,15.3380379 0.838037936,15.0053858 1.25,15 L1.25,15 C1.66196206,15.0053858 1.99461419,15.3380379 2,15.75 L2,18 Z"
+ android:strokeWidth="1" />
+ </group>
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_activity_recognition.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_activity_recognition.xml
index 5ad146eb21ac..cbd60d880fb2 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_activity_recognition.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_activity_recognition.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_calendar.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_calendar.xml
index 781c0f8e8ea5..397050fd88f4 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_calendar.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_calendar.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_call_log.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_call_log.xml
index 126b70cff251..b56eec39334c 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_call_log.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_call_log.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_camera.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_camera.xml
index 70d4fcc945df..c8cb2e2cfc1f 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_camera.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_camera.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_contacts.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_contacts.xml
index 6da4b269d312..6124df86e931 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_contacts.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_contacts.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_location.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_location.xml
index d443a7484e5a..77ff42ad3e25 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_location.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_location.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_microphone.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_microphone.xml
index cdac2d8cadaa..06aa0cd3f238 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_microphone.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_microphone.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_phone_calls.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_phone_calls.xml
index 991f320add6c..3aea5f44902b 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_phone_calls.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_phone_calls.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_sensors.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_sensors.xml
index e4dee2adc467..4d70fc90850e 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_sensors.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_sensors.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_sms.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_sms.xml
index d15cfa3b1e3a..30ed8c92a198 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_sms.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_sms.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_storage.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_storage.xml
index 29d26736135b..52cd4c1c7153 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_storage.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_storage.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_visual.xml b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_visual.xml
index 519136a28725..1c461791c868 100644
--- a/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_visual.xml
+++ b/packages/overlays/IconPackCircularAndroidOverlay/res/drawable/perm_group_visual.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_setting.xml b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_setting.xml
index 4c9b5d7b1c48..f1f0f507d4b9 100644
--- a/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_setting.xml
+++ b/packages/overlays/IconPackCircularLauncherOverlay/res/drawable/ic_setting.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/textColorPrimary"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_arrow_back.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_arrow_back.xml
index 920ecb5deb70..a9e1ffe6d69e 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_arrow_back.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_arrow_back.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_battery_saver_accent_24dp.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_battery_saver_accent_24dp.xml
deleted file mode 100644
index 01d87ce25a2f..000000000000
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_battery_saver_accent_24dp.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2019 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="24dp"
- android:tint="?android:attr/colorAccent"
- android:viewportHeight="24"
- android:viewportWidth="24"
- android:width="24dp" >
- <path
- android:fillColor="@android:color/white"
- android:pathData="M9.75,13.75h1.5v1.5c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75v-1.5h1.5c0.41,0,0.75-0.34,0.75-0.75 s-0.34-0.75-0.75-0.75h-1.5v-1.5c0-0.41-0.34-0.75-0.75-0.75s-0.75,0.34-0.75,0.75v1.5h-1.5C9.34,12.25,9,12.59,9,13 S9.34,13.75,9.75,13.75z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M6,19c0,1.66,1.34,3,3,3h6c1.66,0,3-1.34,3-3V7c0-1.66-1.34-3-3-3h-1c0-0.55-0.45-1-1-1h-2c-0.55,0-1,0.45-1,1H9 C7.34,4,6,5.34,6,7V19z M7.5,7c0-0.83,0.67-1.5,1.5-1.5h6c0.83,0,1.5,0.67,1.5,1.5v12c0,0.83-0.67,1.5-1.5,1.5H9 c-0.83,0-1.5-0.67-1.5-1.5V7z" />
-</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_battery_status_bad_24dp.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_battery_status_bad_24dp.xml
deleted file mode 100644
index a558337902c4..000000000000
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_battery_status_bad_24dp.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2019 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="24dp"
- android:viewportHeight="24"
- android:viewportWidth="24"
- android:width="24dp" >
- <path
- android:fillColor="@android:color/white"
- android:pathData="M9.75,13.75h1.5v1.5c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75v-1.5h1.5c0.41,0,0.75-0.34,0.75-0.75 s-0.34-0.75-0.75-0.75h-1.5v-1.5c0-0.41-0.34-0.75-0.75-0.75s-0.75,0.34-0.75,0.75v1.5h-1.5C9.34,12.25,9,12.59,9,13 S9.34,13.75,9.75,13.75z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M6,19c0,1.66,1.34,3,3,3h6c1.66,0,3-1.34,3-3V7c0-1.66-1.34-3-3-3h-1c0-0.55-0.45-1-1-1h-2c-0.55,0-1,0.45-1,1H9 C7.34,4,6,5.34,6,7V19z M7.5,7c0-0.83,0.67-1.5,1.5-1.5h6c0.83,0,1.5,0.67,1.5,1.5v12c0,0.83-0.67,1.5-1.5,1.5H9 c-0.83,0-1.5-0.67-1.5-1.5V7z" />
-</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_cellular_off.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_cellular_off.xml
index 57fcebc91d2e..6df47564407e 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_cellular_off.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_cellular_off.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:tint="?android:attr/colorAccent"
android:viewportHeight="24"
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_chevron_right_24dp.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_chevron_right_24dp.xml
index 9569e68be613..82df1de6211c 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_chevron_right_24dp.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_chevron_right_24dp.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_content_copy_grey600_24dp.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_content_copy_grey600_24dp.xml
index 9dea4ca2ea28..b8e9845d5039 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_content_copy_grey600_24dp.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_content_copy_grey600_24dp.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="#757575"
+ android:tint="@*android:color/material_grey_600"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_data_saver.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_data_saver.xml
index 77c0a158ebdd..ba3c5808d26c 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_data_saver.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_data_saver.xml
@@ -15,18 +15,19 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
- <path
- android:fillColor="@android:color/white"
- android:pathData="M12,7a0.76 0.76 ,0,0,0-0.75 0.75 v3.5H7.75a0.75 0.75 ,0,0,0,0,1.5h3.5v3.5a0.75 0.75 ,0,0,0,1.5,0v-3.5h3.5a0.75 0.75 ,0,0,0,0-1.5h-3.5V7.75A0.76 0.76 ,0,0,0,12,7Z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M3.36,7A10,10,0,0,0,20.27,17.64L18.1,16.39A7.5,7.5,0,1,1,11.25,4.56V2.05A10,10,0,0,0,3.36,7Z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M21,16.35a10,10,0,0,0-8.27-14.3V4.56a7.48,7.48,0,0,1,6.1,10.54Z" />
+ <group
+ android:translateX="2.000000"
+ android:translateY="2.000000" >
+ <path
+ android:fillColor="@android:color/white"
+ android:fillType="evenOdd"
+ android:pathData="M17.5000671,10 C17.5000671,6.198 14.6680671,3.064 11.0000671,2.574 L11.0000671,0.05 C16.0500671,0.55 20.0000671,4.82 20.0000671,10 C20.0000671,11.45 19.6800671,12.83 19.1200671,14.07 L16.9560671,12.796 C17.3040671,11.932 17.5000671,10.989 17.5000671,10 Z M10.0000671,17.5 C12.3900671,17.5 14.5140671,16.378 15.8870671,14.637 C16.6270671,15.073 18.0500671,15.91 18.0500671,15.91 C15.9790671,18.732 12.4710671,20.427 8.60106711,19.906 C4.22106711,19.316 0.68406711,15.774 0.0940671101,11.394 C-0.68693289,5.591 3.49306711,0.594 9.00006711,0.05 L9.00006711,2.574 C5.33206711,3.064 2.50006711,6.198 2.50006711,10 C2.50006711,14.142 5.85806711,17.5 10.0000671,17.5 Z M6,10 C6.00538581,9.58803794 6.33803794,9.25538581 6.75,9.25 L9.25,9.25 L9.25,6.75 C9.25,6.33578644 9.58578644,6 10,6 C10.4142136,6 10.75,6.33578644 10.75,6.75 L10.75,9.25 L13.25,9.25 C13.6642136,9.25 14,9.58578644 14,10 C14,10.4142136 13.6642136,10.75 13.25,10.75 L10.75,10.75 L10.75,13.25 C10.75,13.6642136 10.4142136,14 10,14 C9.58578644,14 9.25,13.6642136 9.25,13.25 L9.25,10.75 L6.75,10.75 C6.33803794,10.7446142 6.00538581,10.4119621 6,10 Z"
+ android:strokeWidth="1" />
+ </group>
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_devices_other.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_devices_other.xml
index 17a191e2ad07..14898c465a31 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_devices_other.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_devices_other.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_eject_24dp.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_eject_24dp.xml
index 1c1fa4b7a5ee..abbab51e90e1 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_eject_24dp.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_eject_24dp.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_find_in_page_24px.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_find_in_page_24px.xml
new file mode 100644
index 000000000000..fd1a00dc738b
--- /dev/null
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_find_in_page_24px.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <group
+ android:translateX="4.000100"
+ android:translateY="2.000100" >
+ <path
+ android:fillColor="@android:color/white"
+ android:fillType="evenOdd"
+ android:pathData="M7.9999,15.2499 C6.2079,15.2499 4.7499,13.7919 4.7499,11.9999 C4.7499,10.2079 6.2079,8.7499 7.9999,8.7499 C9.7919,8.7499 11.2499,10.2079 11.2499,11.9999 C11.2499,13.7919 9.7919,15.2499 7.9999,15.2499 L7.9999,15.2499 Z M1.4999,17.7779 L1.4999,2.2219 C1.4999,1.8239 1.8529,1.4999 2.2859,1.4999 L9.6769,1.4999 L14.4999,6.1889 L14.4999,17.5799 L11.8269,14.7879 C12.3999,14.0029 12.7499,13.0439 12.7499,11.9999 C12.7499,9.3809 10.6189,7.2499 7.9999,7.2499 C5.3809,7.2499 3.2499,9.3809 3.2499,11.9999 C3.2499,14.6189 5.3809,16.7499 7.9999,16.7499 C9.0329,16.7499 9.9829,16.4089 10.7649,15.8469 L13.3039,18.4999 L2.2859,18.4999 C1.8529,18.4999 1.4999,18.1759 1.4999,17.7779 L1.4999,17.7779 Z M10.2859,-0.0001 L2.2859,-0.0001 C1.0229,-0.0001 -0.0001,0.9949 -0.0001,2.2219 L-0.0001,17.7779 C-0.0001,19.0049 1.0229,19.9999 2.2859,19.9999 L13.7139,19.9999 C14.9769,19.9999 15.9999,19.0049 15.9999,17.7779 L15.9999,5.5559 L10.2859,-0.0001 Z"
+ android:strokeWidth="1" />
+ </group>
+</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_help_actionbar.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_help_actionbar.xml
index 8b388f2d8761..b980a2cce710 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_help_actionbar.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_help_actionbar.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_network_cell.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_network_cell.xml
index b6fa9fcf8294..1d72e5fa284f 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_network_cell.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_network_cell.xml
@@ -15,21 +15,30 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
- <path
- android:fillColor="@android:color/white"
- android:pathData="M20,22H18.5V4.75A0.76 0.76 ,0,0,1,19.25,4h0a0.76 0.76 ,0,0,1,0.75 0.75 Z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M15.33,22h-1.5V9.75A0.76 0.76 ,0,0,1,14.58,9h0a0.75 0.75 ,0,0,1,0.75 0.75 Z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M10.67,22H9.17V14.75A0.75 0.75 ,0,0,1,9.92,14h0a0.76 0.76 ,0,0,1,0.75 0.75 Z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M6,22H4.5V19.75A0.76 0.76 ,0,0,1,5.25,19h0a0.76 0.76 ,0,0,1,0.75 0.75 Z" />
+ <group
+ android:translateX="4.000000"
+ android:translateY="3.000000" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M16,18 L14.5,18 L14.5,0.75 C14.5053858,0.338037936 14.8380379,0.00538581231 15.25,0 L15.25,0 C15.6619621,0.00538581231 15.9946142,0.338037936 16,0.75 L16,18 Z"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M11.33,18 L9.83,18 L9.83,5.75 C9.83538581,5.33803794 10.1680379,5.00538581 10.58,5 L10.58,5 C10.9942136,5 11.33,5.33578644 11.33,5.75 L11.33,18 Z"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M6.67,18 L5.17,18 L5.17,10.75 C5.17,10.3357864 5.50578644,10 5.92,10 L5.92,10 C6.33196206,10.0053858 6.66461419,10.3380379 6.67,10.75 L6.67,18 Z"
+ android:strokeWidth="1" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M2,18 L0.5,18 L0.5,15.75 C0.505385812,15.3380379 0.838037936,15.0053858 1.25,15 L1.25,15 C1.66196206,15.0053858 1.99461419,15.3380379 2,15.75 L2,18 Z"
+ android:strokeWidth="1" />
+ </group>
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_notifications_off_24dp.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_notifications_off_24dp.xml
index 2dc6545c0fe3..2a21776232b4 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_notifications_off_24dp.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_notifications_off_24dp.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_data_usage.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_data_usage.xml
index e48cc146a515..855e4bb2a39d 100644
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_data_usage.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_data_usage.xml
@@ -22,8 +22,7 @@
android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M12,19.52a7.5,7.5,0,0,1-0.77-15V2.06A10,10,0,1,0,22,12.77h-2.5A7.52,7.52,0,0,1,12,19.52Z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M19.48,11.27H22a10,10,0,0,0-9.23-9.22v2.5A7.51,7.51,0,0,1,19.48,11.27Z" />
+ android:fillType="evenOdd"
+ android:pathData="M19.5000671,12 C19.5000671,8.198 16.6680671,5.064 13.0000671,4.574 L13.0000671,2.05 C18.0500671,2.55 22.0000671,6.82 22.0000671,12 C22.0000671,13.45 21.6800671,14.83 21.1200671,16.07 L18.9560671,14.796 C19.3040671,13.932 19.5000671,12.989 19.5000671,12 Z M12.0000671,19.5 C14.3900671,19.5 16.5140671,18.378 17.8870671,16.637 C18.6270671,17.073 20.0500671,17.91 20.0500671,17.91 C17.9790671,20.732 14.4710671,22.427 10.6010671,21.906 C6.22106711,21.316 2.68406711,17.774 2.09406711,13.394 C1.31306711,7.591 5.49306711,2.594 11.0000671,2.05 L11.0000671,4.574 C7.33206711,5.064 4.50006711,8.198 4.50006711,12 C4.50006711,16.142 7.85806711,19.5 12.0000671,19.5 Z"
+ android:strokeWidth="1" />
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_language.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_language.xml
new file mode 100644
index 000000000000..2c83c3481ba4
--- /dev/null
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_language.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,2C6.48,2,2,6.48,2,12c0,5.15,3.89,9.38,8.89,9.93c0.01,0.01,0.01,0.01,0.01,0.02l0.02-0.02C11.28,21.98,11.64,22,12,22 s0.72-0.02,1.08-0.06l0.02,0.02c0.01-0.01,0.01-0.01,0.01-0.02c5-0.55,8.89-4.79,8.89-9.93C22,6.48,17.52,2,12,2z M19.35,7.75 h-3.39c-0.39-1.35-0.97-2.67-1.73-3.94C16.41,4.4,18.24,5.84,19.35,7.75z M20.5,12c0,0.96-0.17,1.89-0.47,2.75h-3.69 c0.33-1.82,0.32-3.67-0.02-5.5h3.71C20.33,10.11,20.5,11.04,20.5,12z M12,20.5c-0.1,0-0.2-0.01-0.3-0.02 c-0.96-1.36-1.68-2.78-2.14-4.23h4.89c-0.47,1.45-1.18,2.87-2.14,4.23C12.2,20.49,12.1,20.5,12,20.5z M9.16,14.75 c-0.37-1.82-0.36-3.67,0.02-5.5h5.64c0.38,1.83,0.39,3.68,0.02,5.5H9.16z M3.5,12c0-0.96,0.17-1.89,0.47-2.75h3.71 c-0.34,1.83-0.35,3.68-0.02,5.5H3.97C3.67,13.89,3.5,12.96,3.5,12z M12,3.5c0.09,0,0.17,0.01,0.26,0.01 c0.96,1.37,1.68,2.79,2.16,4.24H9.58c0.48-1.45,1.2-2.87,2.16-4.24C11.83,3.51,11.91,3.5,12,3.5z M9.77,3.81 C9.01,5.08,8.43,6.4,8.04,7.75H4.65C5.76,5.84,7.59,4.4,9.77,3.81z M4.65,16.25h3.36c0.38,1.34,0.95,2.66,1.71,3.93 C7.56,19.58,5.75,18.15,4.65,16.25z M14.28,20.18c0.75-1.27,1.32-2.59,1.71-3.93h3.36C18.25,18.15,16.44,19.58,14.28,20.18z" />
+</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_battery_status_bad_24dp.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_multiuser.xml
index db4d302eb240..d6d655871b74 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_battery_status_bad_24dp.xml
+++ b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_multiuser.xml
@@ -16,13 +16,14 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M9.74,13.75h1.5v1.5c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75v-1.5h1.5c0.41,0,0.75-0.34,0.75-0.75 s-0.34-0.75-0.75-0.75h-1.5v-1.5c0-0.41-0.34-0.75-0.75-0.75s-0.75,0.34-0.75,0.75v1.5h-1.5c-0.41,0-0.75,0.34-0.75,0.75 S9.33,13.75,9.74,13.75z" />
+ android:pathData="M8,8c0,2.21,1.79,4,4,4s4-1.79,4-4c0-2.21-1.79-4-4-4S8,5.79,8,8z M12,5.5c1.38,0,2.5,1.12,2.5,2.5 c0,1.38-1.12,2.5-2.5,2.5S9.5,9.38,9.5,8C9.5,6.62,10.62,5.5,12,5.5z" />
<path
android:fillColor="@android:color/white"
- android:pathData="M17,4h-3V3.49c0-0.55-0.45-1-1-1h-2c-0.55,0-1,0.45-1,1V4H7C6.45,4,6,4.45,6,5v16c0,0.55,0.45,1,1,1h10c0.55,0,1-0.45,1-1 V5C18,4.45,17.55,4,17,4z M16.5,20.5h-9v-15h9V20.5z" />
+ android:pathData="M20,20c0-3.99-4-6-8-6s-8,2.01-8,6H20z M12,15.5c2.57,0,5.3,0.95,6.2,3H5.8C6.7,16.45,9.43,15.5,12,15.5z" />
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_wireless_white.xml b/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_wireless_white.xml
deleted file mode 100644
index fde996584f57..000000000000
--- a/packages/overlays/IconPackCircularSettingsOverlay/res/drawable/ic_settings_wireless_white.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2019 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="24dp"
- android:viewportHeight="24"
- android:viewportWidth="24"
- android:width="24dp" >
- <path
- android:fillColor="@android:color/white"
- android:pathData="M 12 17 C 12.8284271247 17 13.5 17.6715728753 13.5 18.5 C 13.5 19.3284271247 12.8284271247 20 12 20 C 11.1715728753 20 10.5 19.3284271247 10.5 18.5 C 10.5 17.6715728753 11.1715728753 17 12 17 Z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M19.42,11.84c-0.19,0-0.38-0.07-0.53-0.22C17.05,9.77,14.6,8.75,12,8.75s-5.05,1.02-6.89,2.86 c-0.29,0.29-0.77,0.29-1.06,0c-0.29-0.29-0.29-0.77,0-1.06C6.17,8.43,9,7.25,12,7.25s5.83,1.17,7.95,3.3 c0.29,0.29,0.29,0.77,0,1.06C19.8,11.76,19.61,11.84,19.42,11.84z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M22.61,8.65c-0.19,0-0.38-0.07-0.53-0.22C19.38,5.74,15.81,4.25,12,4.25S4.62,5.74,1.92,8.43c-0.29,0.29-0.77,0.29-1.06,0 s-0.29-0.77,0-1.06C3.84,4.39,7.79,2.75,12,2.75s8.16,1.64,11.14,4.61c0.29,0.29,0.29,0.77,0,1.06 C22.99,8.57,22.8,8.65,22.61,8.65z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M16.25,15c-0.19,0-0.38-0.07-0.53-0.22c-1-0.99-2.32-1.53-3.73-1.53s-2.73,0.54-3.73,1.53c-0.29,0.29-0.77,0.29-1.06-0.01 s-0.29-0.77,0.01-1.06c1.28-1.27,2.98-1.96,4.78-1.96s3.5,0.7,4.78,1.96c0.29,0.29,0.3,0.77,0.01,1.06 C16.64,14.93,16.45,15,16.25,15z" />
-</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_arrow_back.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_arrow_back.xml
index 920ecb5deb70..a9e1ffe6d69e 100644
--- a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_arrow_back.xml
+++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_arrow_back.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_brightness_thumb.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_brightness_thumb.xml
index dbd9b8e6d494..fae73a4c0e09 100644
--- a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_brightness_thumb.xml
+++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_brightness_thumb.xml
@@ -20,7 +20,7 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="?android:attr/colorPrimary"
+ android:fillColor="?android:attr/colorBackgroundFloating"
android:pathData="M18.94,9.75L18.5,9.31V8.69V6c0-0.28-0.22-0.5-0.5-0.5h-2.69h-0.62l-0.44-0.44l-1.9-1.9 C12.23,3.04,12.08,3.02,12,3.02c-0.08,0-0.23,0.02-0.35,0.15l-1.9,1.9L9.31,5.5H8.69H6C5.72,5.5,5.5,5.72,5.5,6v2.69v0.62 L5.06,9.75l-1.9,1.9C3.04,11.77,3.02,11.92,3.02,12s0.02,0.23,0.15,0.35l1.9,1.9l0.44,0.44v0.62V18c0,0.28,0.22,0.5,0.5,0.5h2.69 h0.62l0.44,0.44l1.9,1.9c0.13,0.13,0.28,0.15,0.35,0.15c0.08,0,0.23-0.02,0.35-0.15l1.9-1.9l0.44-0.44h0.62H18 c0.28,0,0.5-0.22,0.5-0.5v-2.69v-0.62l0.44-0.44l1.9-1.9c0.13-0.13,0.15-0.28,0.15-0.35s-0.02-0.23-0.15-0.35L18.94,9.75z M12,17 c-2.76,0-5-2.24-5-5s2.24-5,5-5s5,2.24,5,5S14.76,17,12,17z" />
<path
android:fillColor="?android:attr/colorControlActivated"
diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_camera.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_camera.xml
index c4728eb3f389..77197a58a04a 100644
--- a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_camera.xml
+++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_camera.xml
@@ -15,10 +15,10 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="24dp"
+ android:height="17dp"
android:viewportHeight="24"
android:viewportWidth="24"
- android:width="24dp" >
+ android:width="17dp" >
<path
android:fillColor="@android:color/white"
android:pathData="M22,8c0-1.66-1.34-3-3-3h-2l-2-2H9L7,5H5C3.34,5,2,6.34,2,8v13h20V8z M20.5,19.5h-17V8c0-0.83,0.67-1.5,1.5-1.5h14 c0.83,0,1.5,0.67,1.5,1.5V19.5z" />
diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_data_saver.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_data_saver.xml
index 938d2412bef8..cdc3bfbd3d5f 100644
--- a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_data_saver.xml
+++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_data_saver.xml
@@ -15,17 +15,17 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="18dp "
+ android:height="18dp"
android:viewportHeight="24"
android:viewportWidth="24"
- android:width="18dp " >
- <path
- android:fillColor="@android:color/white"
- android:pathData="M12,7a0.76 0.76 ,0,0,0-0.75 0.75 v3.5H7.75a0.75 0.75 ,0,0,0,0,1.5h3.5v3.5a0.75 0.75 ,0,0,0,1.5,0v-3.5h3.5a0.75 0.75 ,0,0,0,0-1.5h-3.5V7.75A0.76 0.76 ,0,0,0,12,7Z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M3.36,7A10,10,0,0,0,20.27,17.64L18.1,16.39A7.5,7.5,0,1,1,11.25,4.56V2.05A10,10,0,0,0,3.36,7Z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M21,16.35a10,10,0,0,0-8.27-14.3V4.56a7.48,7.48,0,0,1,6.1,10.54Z" />
+ android:width="18dp" >
+ <group
+ android:translateX="2.000000"
+ android:translateY="2.000000" >
+ <path
+ android:fillColor="@android:color/white"
+ android:fillType="evenOdd"
+ android:pathData="M17.5000671,10 C17.5000671,6.198 14.6680671,3.064 11.0000671,2.574 L11.0000671,0.05 C16.0500671,0.55 20.0000671,4.82 20.0000671,10 C20.0000671,11.45 19.6800671,12.83 19.1200671,14.07 L16.9560671,12.796 C17.3040671,11.932 17.5000671,10.989 17.5000671,10 Z M10.0000671,17.5 C12.3900671,17.5 14.5140671,16.378 15.8870671,14.637 C16.6270671,15.073 18.0500671,15.91 18.0500671,15.91 C15.9790671,18.732 12.4710671,20.427 8.60106711,19.906 C4.22106711,19.316 0.68406711,15.774 0.0940671101,11.394 C-0.68693289,5.591 3.49306711,0.594 9.00006711,0.05 L9.00006711,2.574 C5.33206711,3.064 2.50006711,6.198 2.50006711,10 C2.50006711,14.142 5.85806711,17.5 10.0000671,17.5 Z M6,10 C6.00538581,9.58803794 6.33803794,9.25538581 6.75,9.25 L9.25,9.25 L9.25,6.75 C9.25,6.33578644 9.58578644,6 10,6 C10.4142136,6 10.75,6.33578644 10.75,6.75 L10.75,9.25 L13.25,9.25 C13.6642136,9.25 14,9.58578644 14,10 C14,10.4142136 13.6642136,10.75 13.25,10.75 L10.75,10.75 L10.75,13.25 C10.75,13.6642136 10.4142136,14 10,14 C9.58578644,14 9.25,13.6642136 9.25,13.25 L9.25,10.75 L6.75,10.75 C6.33803794,10.7446142 6.00538581,10.4119621 6,10 Z"
+ android:strokeWidth="1" />
+ </group>
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_data_saver_off.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_data_saver_off.xml
index 3d620a18bb1a..7dab949f9da5 100644
--- a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_data_saver_off.xml
+++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_data_saver_off.xml
@@ -21,8 +21,7 @@
android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M3.36,7A10,10,0,0,0,20.27,17.64L18.1,16.39A7.5,7.5,0,1,1,11.25,4.56V2.05A10,10,0,0,0,3.36,7Z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M21,16.35a10,10,0,0,0-8.27-14.3V4.56a7.48,7.48,0,0,1,6.1,10.54Z" />
+ android:fillType="evenOdd"
+ android:pathData="M19.5000671,12 C19.5000671,8.198 16.6680671,5.064 13.0000671,4.574 L13.0000671,2.05 C18.0500671,2.55 22.0000671,6.82 22.0000671,12 C22.0000671,13.45 21.6800671,14.83 21.1200671,16.07 L18.9560671,14.796 C19.3040671,13.932 19.5000671,12.989 19.5000671,12 Z M12.0000671,19.5 C14.3900671,19.5 16.5140671,18.378 17.8870671,16.637 C18.6270671,17.073 20.0500671,17.91 20.0500671,17.91 C17.9790671,20.732 14.4710671,22.427 10.6010671,21.906 C6.22106711,21.316 2.68406711,17.774 2.09406711,13.394 C1.31306711,7.591 5.49306711,2.594 11.0000671,2.05 L11.0000671,4.574 C7.33206711,5.064 4.50006711,8.198 4.50006711,12 C4.50006711,16.142 7.85806711,19.5 12.0000671,19.5 Z"
+ android:strokeWidth="1" />
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_bluetooth_connecting.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_bluetooth_connecting.xml
index fc38ed431759..c7a0266cbfca 100644
--- a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_bluetooth_connecting.xml
+++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_qs_bluetooth_connecting.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_volume_alarm_mute.xml b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_volume_alarm_mute.xml
index 659b4e164415..9bdc79a23008 100644
--- a/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_volume_alarm_mute.xml
+++ b/packages/overlays/IconPackCircularSystemUIOverlay/res/drawable/ic_volume_alarm_mute.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_delete_accent.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_battery_80_24dp.xml
index e65987e1d5f6..eb8550fb9f44 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_delete_accent.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_battery_80_24dp.xml
@@ -16,14 +16,16 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="?android:attr/colorAccent"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
+ android:fillAlpha="0.3"
android:fillColor="@android:color/white"
- android:pathData="M18,4h-2.5l-0.71-0.71C14.61,3.11,14.35,3,14.09,3H9.9C9.64,3,9.38,3.11,9.2,3.29L8.49,4h-2.5c-0.55,0-1,0.45-1,1 s0.45,1,1,1h12c0.55,0,1-0.45,1-1C19,4.45,18.55,4,18,4z" />
+ android:pathData="M17,5.33C17,4.6,16.4,4,15.67,4H14V2h-4v2H8.33C7.6,4,7,4.6,7,5.33V9h10V5.33z"
+ android:strokeAlpha="0.3"
+ android:strokeWidth="1" />
<path
android:fillColor="@android:color/white"
- android:pathData="M6,19c0,1.1,0.9,2,2,2h8c1.1,0,2-0.9,2-2V7H6V19z" />
+ android:pathData="M7,9v11.67C7,21.4,7.6,22,8.33,22h7.33C16.4,22,17,21.4,17,20.67V9H7z" />
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bt_misc_hid.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bt_misc_hid.xml
index b86d9ba1849b..6b9735c1acfb 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bt_misc_hid.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_bt_misc_hid.xml
@@ -20,7 +20,6 @@
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
- <path android:pathData="M0,0h24v24H0V0z" />
<path
android:fillColor="@android:color/white"
android:pathData="M15,7.09V3c0-0.55-0.45-1-1-1h-4C9.45,2,9,2.45,9,3v4.09c0,0.27,0.11,0.52,0.29,0.71l2,2c0.39,0.39,1.02,0.39,1.41,0l2-2 C14.89,7.61,15,7.35,15,7.09z M7.09,9H3c-0.55,0-1,0.45-1,1v4c0,0.55,0.45,1,1,1h4.09c0.27,0,0.52-0.11,0.71-0.29l2-2 c0.39-0.39,0.39-1.02,0-1.41l-2-2C7.61,9.11,7.35,9,7.09,9z M9,16.91V21c0,0.55,0.45,1,1,1h4c0.55,0,1-0.45,1-1v-4.09 c0-0.27-0.11-0.52-0.29-0.71l-2-2c-0.39-0.39-1.02-0.39-1.41,0l-2,2C9.11,16.39,9,16.65,9,16.91z M16.21,9.29l-2,2 c-0.39,0.39-0.39,1.02,0,1.41l2,2c0.19,0.19,0.44,0.29,0.71,0.29H21c0.55,0,1-0.45,1-1v-4c0-0.55-0.45-1-1-1h-4.09 C16.65,9,16.39,9.11,16.21,9.29z" />
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_file_copy.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_file_copy.xml
index 6245147c538b..e479f506bac5 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_file_copy.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_file_copy.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="#FF737373"
+ android:tint="@*android:color/material_grey_600"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_lock.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_lock.xml
index 07c81ddf563c..b2fa85f9fd16 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_lock.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_lock.xml
@@ -16,7 +16,6 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="32dp"
- android:tint="?android:attr/textColor"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="32dp" >
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_lock_open.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_lock_open.xml
index 698ce668c1e9..13bfbf901adb 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_lock_open.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_lock_open.xml
@@ -16,7 +16,6 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="32dp"
- android:tint="?android:attr/textColor"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="32dp" >
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_lockscreen_ime.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_lockscreen_ime.xml
index 4cd05f3374c9..16541e614965 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_lockscreen_ime.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_lockscreen_ime.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_mode_edit.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_mode_edit.xml
index bf8df45826ec..bb3c043f68f5 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_mode_edit.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_mode_edit.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_wireless_white.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_notifications_alerted.xml
index 03e142e2be35..0847a3564998 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_wireless_white.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_notifications_alerted.xml
@@ -21,11 +21,14 @@
android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M11.29,19.29c0.39,0.39,1.03,0.4,1.42,0L14,18c0.47-0.47,0.38-1.28-0.22-1.58C13.25,16.15,12.64,16,12,16 c-0.64,0-1.24,0.15-1.77,0.41c-0.59,0.29-0.69,1.11-0.22,1.58L11.29,19.29z" />
+ android:pathData="M4.12,9.67C4.42,7.73,5.38,6,6.77,4.73C7.19,4.35,7.2,3.7,6.8,3.3c-0.39-0.39-1-0.39-1.4-0.03 C3.7,4.84,2.52,6.96,2.15,9.34c-0.1,0.61,0.37,1.16,0.99,1.16C3.63,10.5,4.04,10.15,4.12,9.67z" />
<path
android:fillColor="@android:color/white"
- android:pathData="M17.6,14.39l0.71-0.71c0.42-0.42,0.39-1.12-0.08-1.5C16.52,10.82,14.35,10,12,10c-2.34,0-4.5,0.81-6.21,2.17 c-0.47,0.37-0.51,1.07-0.09,1.49l0.71,0.71c0.35,0.36,0.92,0.39,1.32,0.08C8.91,13.54,10.39,13,12,13c1.61,0,3.1,0.55,4.29,1.47 C16.69,14.78,17.25,14.75,17.6,14.39z" />
+ android:pathData="M18.6,3.28c-0.4-0.37-1.02-0.36-1.4,0.02c-0.4,0.4-0.38,1.04,0.03,1.42c1.38,1.27,2.35,3,2.65,4.94 c0.08,0.49,0.5,0.84,0.98,0.84c0.61,0,1.09-0.55,0.99-1.16C21.47,6.96,20.29,4.84,18.6,3.28z" />
<path
android:fillColor="@android:color/white"
- android:pathData="M21.83,10.16l0.71-0.71c0.42-0.42,0.38-1.09-0.06-1.48C19.68,5.5,16.01,4,12,4C8.01,4,4.36,5.49,1.56,7.94 C1.12,8.33,1.08,9,1.49,9.41l0.71,0.71c0.37,0.37,0.96,0.4,1.35,0.06C5.81,8.2,8.77,7,12,7c3.25,0,6.22,1.22,8.49,3.22 C20.88,10.56,21.47,10.53,21.83,10.16z" />
+ android:pathData="M12,22c1.1,0,2-0.9,2-2h-4C10,21.1,10.9,22,12,22z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M18,16v-5c0-3.07-1.64-5.64-4.5-6.32V4c0-0.83-0.67-1.5-1.5-1.5S10.5,3.17,10.5,4v0.68C7.63,5.36,6,7.92,6,11v5 l-2.15,2.15c-0.19,0.2-0.19,0.51,0.01,0.71C3.95,18.95,4.07,19,4.2,19h15.6c0.45,0,0.67-0.54,0.35-0.85L18,16z" />
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_phone.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_phone.xml
index de348159cc6c..adf521c853ae 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_phone.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_phone.xml
@@ -15,7 +15,9 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_qs_battery_saver.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_qs_battery_saver.xml
index 22e183c694d5..4f7d96381e6e 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_qs_battery_saver.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_qs_battery_saver.xml
@@ -15,7 +15,9 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_qs_bluetooth.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_qs_bluetooth.xml
index 012fdb6f5b8b..18a60d82faed 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_qs_bluetooth.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/ic_qs_bluetooth.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_activity_recognition.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_activity_recognition.xml
index e1849bbee061..67d28c60b7a0 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_activity_recognition.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_activity_recognition.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_calendar.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_calendar.xml
index 16359b04178d..0144ba2fbf36 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_calendar.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_calendar.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_call_log.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_call_log.xml
index 8d70f484e731..590ced09e4af 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_call_log.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_call_log.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_camera.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_camera.xml
index 03075a688846..b063e2bb6985 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_camera.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_camera.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_contacts.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_contacts.xml
index 50cd6331e42a..54cfeec0355e 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_contacts.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_contacts.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_location.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_location.xml
index ebd9e61d8efe..3815921846b7 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_location.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_location.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_microphone.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_microphone.xml
index 39acc9ca82a1..e6493bc95ff2 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_microphone.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_microphone.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_phone_calls.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_phone_calls.xml
index 2b6e32a59cab..ae84541e0801 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_phone_calls.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_phone_calls.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_sensors.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_sensors.xml
index 2128e79b350a..88f0c541caf5 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_sensors.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_sensors.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_sms.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_sms.xml
index eef9e62f15b0..7a320e0c81e2 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_sms.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_sms.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_storage.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_storage.xml
index 3a863a342354..0ad7e6d3484b 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_storage.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_storage.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_visual.xml b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_visual.xml
index 57c7ae9f6efa..d5bdb872825e 100644
--- a/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_visual.xml
+++ b/packages/overlays/IconPackFilledAndroidOverlay/res/drawable/perm_group_visual.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_setting.xml b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_setting.xml
index 30e866095675..b3625ac9cf15 100644
--- a/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_setting.xml
+++ b/packages/overlays/IconPackFilledLauncherOverlay/res/drawable/ic_setting.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/textColorPrimary"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_arrow_back.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_arrow_back.xml
index b4f2a9de63a6..deb77c820ecb 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_arrow_back.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_arrow_back.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_cellular_off.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_cellular_off.xml
index 32ce0f5ea249..466ae50cb46a 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_cellular_off.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_cellular_off.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:tint="?android:attr/colorAccent"
android:viewportHeight="24"
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_chevron_right_24dp.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_chevron_right_24dp.xml
index e1a8b1feb22b..b5b514a57e9d 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_chevron_right_24dp.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_chevron_right_24dp.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_content_copy_grey600_24dp.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_content_copy_grey600_24dp.xml
index be607a3c4d33..e479f506bac5 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_content_copy_grey600_24dp.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_content_copy_grey600_24dp.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="#757575"
+ android:tint="@*android:color/material_grey_600"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_data_saver.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_data_saver.xml
index 2718efadfe59..5c85eb36b41c 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_data_saver.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_data_saver.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_devices_other.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_devices_other.xml
index 21368fe5782b..a451ef831e78 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_devices_other.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_devices_other.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_eject_24dp.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_eject_24dp.xml
index 5a9511a5cfbe..7af92461d3f9 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_eject_24dp.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_eject_24dp.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_find_in_page_24px.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_find_in_page_24px.xml
new file mode 100644
index 000000000000..dd35dae227b0
--- /dev/null
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_find_in_page_24px.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path android:pathData="M0 0h24v24H0z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M20 19.59V8l-6-6H6c-1.1 0-1.99 0.9 -1.99 2L4 20c0 1.1 0.89 2 1.99 2H18c0.45 0 0.85-0.15 1.19-0.4l-4.43-4.43c-0.8 0.52 -1.74 0.83 -2.76 0.83 -2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5c0 1.02-0.31 1.96-0.83 2.75L20 19.59zM9 13c0 1.66 1.34 3 3 3s3-1.34 3-3-1.34-3-3-3-3 1.34-3 3z" />
+</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_help_actionbar.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_help_actionbar.xml
index ed6d553f5f37..4d6d9dd0a9e5 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_help_actionbar.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_help_actionbar.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_network_cell.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_network_cell.xml
index 2e9433b08220..d62758e51976 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_network_cell.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_network_cell.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_notifications_off_24dp.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_notifications_off_24dp.xml
index 9944bb5b4f69..c6cd0159854e 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_notifications_off_24dp.xml
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_notifications_off_24dp.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_language.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_language.xml
new file mode 100644
index 000000000000..e23b9b6ebf58
--- /dev/null
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_language.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M11.99,2C6.47,2,2,6.48,2,12c0,5.52,4.47,10,9.99,10C17.52,22,22,17.52,22,12C22,6.48,17.52,2,11.99,2z M18.92,8h-2.95 c-0.31-1.24-0.78-2.43-1.38-3.56C16.41,5.07,17.95,6.33,18.92,8z M12,4.04c0.83,1.2,1.48,2.53,1.91,3.96h-3.82 C10.52,6.57,11.17,5.24,12,4.04z M4.26,14C4.1,13.36,4,12.69,4,12s0.1-1.36,0.26-2h3.38c-0.08,0.66-0.14,1.32-0.14,2 s0.06,1.34,0.14,2H4.26z M5.08,16h2.95c0.32,1.25,0.78,2.45,1.38,3.56C7.58,18.94,6.05,17.67,5.08,16z M8.03,8H5.08 c0.97-1.67,2.5-2.94,4.33-3.56C8.81,5.57,8.34,6.76,8.03,8z M12,19.96c-0.83-1.2-1.48-2.53-1.91-3.96h3.82 C13.48,17.43,12.83,18.76,12,19.96z M14.34,14H9.66c-0.09-0.66-0.16-1.32-0.16-2s0.07-1.35,0.16-2h4.68c0.09,0.65,0.16,1.32,0.16,2 S14.43,13.34,14.34,14z M14.59,19.56c0.6-1.11,1.06-2.31,1.38-3.56h2.95C17.95,17.67,16.41,18.93,14.59,19.56z M16.36,14 c0.08-0.66,0.14-1.32,0.14-2s-0.06-1.34-0.14-2h3.38C19.9,10.64,20,11.31,20,12s-0.1,1.36-0.26,2H16.36z" />
+</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_multiuser.xml b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_multiuser.xml
new file mode 100644
index 000000000000..accc694238d9
--- /dev/null
+++ b/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_settings_multiuser.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M 12 4 C 14.2091389993 4 16 5.79086100068 16 8 C 16 10.2091389993 14.2091389993 12 12 12 C 9.79086100068 12 8 10.2091389993 8 8 C 8 5.79086100068 9.79086100068 4 12 4 Z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,13.5c-2.67,0-8,1.34-8,4v2C4,19.77,4.22,20,4.5,20h15c0.27,0,0.5-0.23,0.5-0.5v-2C20,14.84,14.67,13.5,12,13.5z" />
+</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_arrow_back.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_arrow_back.xml
index b4f2a9de63a6..deb77c820ecb 100644
--- a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_arrow_back.xml
+++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_arrow_back.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_brightness_thumb.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_brightness_thumb.xml
index e82e9a3ee185..1b881eac9fc2 100644
--- a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_brightness_thumb.xml
+++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_brightness_thumb.xml
@@ -23,6 +23,6 @@
android:fillColor="?android:attr/colorControlActivated"
android:pathData="M4,15.3V19c0,0.55,0.45,1,1,1h3.69l2.6,2.6c0.39,0.39,1.02,0.39,1.41,0l2.6-2.6H19c0.55,0,1-0.45,1-1v-3.69l2.6-2.6 c0.39-0.39,0.39-1.02,0-1.41L20,8.69V5c0-0.55-0.45-1-1-1h-3.69l-2.6-2.6c-0.39-0.39-1.02-0.39-1.41,0L8.69,4H5C4.45,4,4,4.45,4,5 v3.69l-2.6,2.6c-0.39,0.39-0.39,1.02,0,1.41L4,15.3z M12,7c2.76,0,5,2.24,5,5s-2.24,5-5,5s-5-2.24-5-5S9.24,7,12,7z" />
<path
- android:fillColor="?android:attr/colorPrimary"
+ android:fillColor="?android:attr/colorBackgroundFloating"
android:pathData="M 12 7 C 14.7614237492 7 17 9.23857625085 17 12 C 17 14.7614237492 14.7614237492 17 12 17 C 9.23857625085 17 7 14.7614237492 7 12 C 7 9.23857625085 9.23857625085 7 12 7 Z" />
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_camera.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_camera.xml
index ae3e7e2d60c6..fac551cf4a63 100644
--- a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_camera.xml
+++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_camera.xml
@@ -15,10 +15,10 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="24dp"
+ android:height="17dp"
android:viewportHeight="24"
android:viewportWidth="24"
- android:width="24dp" >
+ android:width="17dp" >
<path
android:fillColor="@android:color/white"
android:pathData="M 12 8.8 C 13.7673111995 8.8 15.2 10.2326888005 15.2 12 C 15.2 13.7673111995 13.7673111995 15.2 12 15.2 C 10.2326888005 15.2 8.8 13.7673111995 8.8 12 C 8.8 10.2326888005 10.2326888005 8.8 12 8.8 Z" />
diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_cast_connected.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_cast_connected.xml
index f5056f2a1f12..bbe2cff62720 100644
--- a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_cast_connected.xml
+++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_cast_connected.xml
@@ -15,10 +15,10 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="17dp"
+ android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
- android:width="17dp" >
+ android:width="24dp" >
<path
android:fillColor="@android:color/white"
android:pathData="M2.07,10.05C1.5,10,1.02,10.45,1,11.03c-0.01,0.52,0.34,0.96,0.85,1.01c4.26,0.43,7.68,3.82,8.1,8.08 C10,20.62,10.43,21,10.94,21c0.59,0,1.06-0.51,1-1.1C11.42,14.69,7.28,10.56,2.07,10.05z" />
diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_data_saver.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_data_saver.xml
index 3d4cf5e88f07..28b8ba1bccfc 100644
--- a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_data_saver.xml
+++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_data_saver.xml
@@ -15,10 +15,10 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="18dp "
+ android:height="18dp"
android:viewportHeight="24"
android:viewportWidth="24"
- android:width="18dp " >
+ android:width="18dp" >
<path
android:fillColor="@android:color/white"
android:pathData="M11,11H9c-0.55,0-1,0.45-1,1s0.45,1,1,1h2v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2h2c0.55,0,1-0.45,1-1s-0.45-1-1-1h-2V9 c0-0.55-0.45-1-1-1s-1,0.45-1,1V11z" />
diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_bluetooth_connecting.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_bluetooth_connecting.xml
index f661673e1fea..59a18bad6c66 100644
--- a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_bluetooth_connecting.xml
+++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_qs_bluetooth_connecting.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_volume_alarm_mute.xml b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_volume_alarm_mute.xml
index 8640a7950672..e498f803f687 100644
--- a/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_volume_alarm_mute.xml
+++ b/packages/overlays/IconPackFilledSystemUIOverlay/res/drawable/ic_volume_alarm_mute.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_battery_saver_accent_24dp.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_battery_80_24dp.xml
index 4ddeae66401c..c19ca31d41b2 100644
--- a/packages/overlays/IconPackFilledSettingsOverlay/res/drawable/ic_battery_saver_accent_24dp.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_battery_80_24dp.xml
@@ -16,11 +16,10 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="?android:attr/colorAccent"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M10,2v2H8.33C7.6,4,7,4.6,7,5.33v15.33C7,21.4,7.6,22,8.33,22h7.33C16.4,22,17,21.4,17,20.67V5.33C17,4.6,16.4,4,15.67,4 H14V2H10z M15,13c0,0.55-0.45,1-1,1h-1v1c0,0.55-0.45,1-1,1s-1-0.45-1-1v-1h-1c-0.55,0-1-0.45-1-1s0.45-1,1-1h1v-1 c0-0.55,0.45-1,1-1s1,0.45,1,1v1h1C14.55,12,15,12.45,15,13z" />
+ android:pathData="M13,2.49h-2c-0.55,0-1,0.45-1,1V4H7C6.45,4,6,4.45,6,5v16c0,0.55,0.45,1,1,1h10c0.55,0,1-0.45,1-1V5c0-0.55-0.45-1-1-1h-3 V3.49C14,2.94,13.55,2.49,13,2.49z M16.5,9.01h-9V5.5h9V9.01z" />
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_file_copy.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_file_copy.xml
index 97945f00395e..1feaab1663c1 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_file_copy.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_file_copy.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="#FF737373"
+ android:tint="@*android:color/material_grey_600"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_lock.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_lock.xml
index ac8e4781b904..d0b85e70920d 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_lock.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_lock.xml
@@ -16,7 +16,6 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="32dp"
- android:tint="?android:attr/textColor"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="32dp" >
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_lock_open.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_lock_open.xml
index 345d6b181b92..6f19afe7c484 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_lock_open.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_lock_open.xml
@@ -16,7 +16,6 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="32dp"
- android:tint="?android:attr/textColor"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="32dp" >
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_lockscreen_ime.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_lockscreen_ime.xml
index 16f0868987fb..fae8445a0a42 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_lockscreen_ime.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_lockscreen_ime.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_mode_edit.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_mode_edit.xml
index 5db3b12ac1dd..c44a8d6fb9c5 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_mode_edit.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_mode_edit.xml
@@ -16,10 +16,17 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
- <path
- android:fillColor="@android:color/white"
- android:pathData="M20.08,5.08l-1.17-1.17c-0.39-0.39-0.9-0.58-1.41-0.58c-0.51,0-1.02,0.2-1.41,0.59L3.29,16.71C3.11,16.89,3,17.15,3,17.41 l0,2.59c0,0.55,0.45,1,1,1c0,0,0,0,0,0L6.59,21c0.26,0,0.52-0.11,0.71-0.29l10.68-10.68l0,0l1.06-1.06l0,0l1.05-1.06 C20.87,7.13,20.87,5.86,20.08,5.08z M6.38,19.5l-1.88,0l0-1.88L15.03,7.09l1.88,1.88L6.38,19.5z M19.02,6.85l-1.06,1.06l-1.88-1.88 l1.05-1.05c0.13-0.13,0.28-0.15,0.35-0.15c0.08,0,0.23,0.02,0.35,0.15l1.17,1.17c0.13,0.13,0.15,0.28,0.15,0.35 C19.17,6.57,19.15,6.72,19.02,6.85z" />
+ <group
+ android:translateX="3.000000"
+ android:translateY="3.000000" >
+ <path
+ android:fillColor="@android:color/white"
+ android:fillType="evenOdd"
+ android:pathData="M14.971,4.992 L13.092,3.115 L14.499,1.707 L16.38,3.583 L14.971,4.992 Z M3.38,16.588 L1.501,16.592 L1.502,14.708 L12.031,4.176 L13.91,6.054 L3.38,16.588 Z M17.794,2.874 L15.205,0.292 C15.01,0.097 14.755,0 14.499,0 C14.243,0 13.987,0.098 13.792,0.293 L0.295,13.794 C0.108,13.981 0.002,14.236 0.002,14.5 L-1.42108547e-14,17.594 C-1.42108547e-14,17.87 0.224,18.094 0.5,18.094 L0.501,18.094 L3.589,18.088 C3.854,18.087 4.107,17.982 4.294,17.795 L17.795,4.289 C18.185,3.898 18.185,3.264 17.794,2.874 L17.794,2.874 Z"
+ android:strokeWidth="1" />
+ </group>
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_delete_accent.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_notifications_alerted.xml
index d30eb7c0f098..752dab5082a4 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_delete_accent.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_notifications_alerted.xml
@@ -16,17 +16,19 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="?android:attr/colorAccent"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M20,4h-1h-4c0-0.55-0.45-1-1-1h-4C9.45,3,9,3.45,9,4H5H4C3.59,4,3.25,4.34,3.25,4.75S3.59,5.5,4,5.5h1V18 c0,1.66,1.34,3,3,3h8c1.66,0,3-1.34,3-3V5.5h1c0.41,0,0.75-0.34,0.75-0.75S20.41,4,20,4z M17.5,18c0,0.83-0.67,1.5-1.5,1.5H8 c-0.83,0-1.5-0.67-1.5-1.5V5.5h11V18z" />
+ android:pathData="M14,20h-4c0,1.1,0.9,2,2,2S14,21.1,14,20z" />
<path
android:fillColor="@android:color/white"
- android:pathData="M14.25,8c-0.41,0-0.75,0.34-0.75,0.75v7.5c0,0.41,0.34,0.75,0.75,0.75S15,16.66,15,16.25v-7.5C15,8.34,14.66,8,14.25,8z" />
+ android:pathData="M12,2.5c-0.69,0-1.25,0.56-1.25,1.25v0.77C8.04,5.11,6,7.51,6,10.4V17H4.75C4.34,17,4,17.34,4,17.75s0.34,0.75,0.75,0.75 h14.5c0.41,0,0.75-0.34,0.75-0.75S19.66,17,19.25,17H18v-6.6c0-2.88-2.04-5.29-4.75-5.87V3.75C13.25,3.06,12.69,2.5,12,2.5z M16.5,10.4V17h-9v-6.6c0-2.48,2.02-4.5,4.5-4.5S16.5,7.91,16.5,10.4z" />
<path
android:fillColor="@android:color/white"
- android:pathData="M9.75,8C9.34,8,9,8.34,9,8.75v7.5C9,16.66,9.34,17,9.75,17s0.75-0.34,0.75-0.75v-7.5C10.5,8.34,10.16,8,9.75,8z" />
+ android:pathData="M5.85,3.01C3.72,4.82,2.5,7.46,2.5,10.25C2.5,10.66,2.84,11,3.25,11S4,10.66,4,10.25c0-2.35,1.03-4.57,2.82-6.1 C7.14,3.88,7.17,3.41,6.91,3.1C6.64,2.78,6.17,2.74,5.85,3.01z" />
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M18.15,3.01c-0.32-0.27-0.79-0.23-1.06,0.08c-0.27,0.32-0.23,0.79,0.08,1.06C18.97,5.68,20,7.9,20,10.25 c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75C21.5,7.46,20.28,4.82,18.15,3.01z" />
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_phone.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_phone.xml
index 21153928240f..c6e8f57f5ec1 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_phone.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_phone.xml
@@ -15,7 +15,9 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_qs_battery_saver.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_qs_battery_saver.xml
index db4d302eb240..ca37d581332b 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_qs_battery_saver.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_qs_battery_saver.xml
@@ -15,7 +15,9 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_qs_bluetooth.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_qs_bluetooth.xml
index 3d270b3fce42..5e1a5f20c6d6 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_qs_bluetooth.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/ic_qs_bluetooth.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_activity_recognition.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_activity_recognition.xml
index b470603cddd0..669704775311 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_activity_recognition.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_activity_recognition.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_calendar.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_calendar.xml
index e9dddd071481..4e61af0dbf34 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_calendar.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_calendar.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_call_log.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_call_log.xml
index 2d6a6b916789..8d3c43c3d216 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_call_log.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_call_log.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_camera.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_camera.xml
index e3498c380d11..7d42ff758b8c 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_camera.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_camera.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_contacts.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_contacts.xml
index 987ed184a826..5d68581757ba 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_contacts.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_contacts.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_location.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_location.xml
index 2da48d857617..5dce9cb985b3 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_location.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_location.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_microphone.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_microphone.xml
index ddf14df872f2..b45e8322628d 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_microphone.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_microphone.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_phone_calls.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_phone_calls.xml
index 516ee36d7f48..fe45a97a3287 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_phone_calls.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_phone_calls.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_sensors.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_sensors.xml
index 65a193d98b32..c84cb0e99bde 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_sensors.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_sensors.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_sms.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_sms.xml
index b5509d12a059..96b70f7fbfbd 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_sms.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_sms.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_storage.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_storage.xml
index 9b17e55f0be1..9240bb48b35e 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_storage.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_storage.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_visual.xml b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_visual.xml
index 350bb4b80c85..2cd1bc0f17b0 100644
--- a/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_visual.xml
+++ b/packages/overlays/IconPackRoundedAndroidOverlay/res/drawable/perm_group_visual.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="@android:color/black"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_setting.xml b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_setting.xml
index 86cb525e203a..70621ae19749 100644
--- a/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_setting.xml
+++ b/packages/overlays/IconPackRoundedLauncherOverlay/res/drawable/ic_setting.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/textColorPrimary"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_arrow_back.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_arrow_back.xml
index 03f06e997e26..34f79b4478c9 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_arrow_back.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_arrow_back.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_cellular_off.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_cellular_off.xml
index 710387ca88d5..34d40ec813e4 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_cellular_off.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_cellular_off.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:tint="?android:attr/colorAccent"
android:viewportHeight="24"
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_chevron_right_24dp.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_chevron_right_24dp.xml
index 7df03ad48705..1e86983cd551 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_chevron_right_24dp.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_chevron_right_24dp.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_content_copy_grey600_24dp.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_content_copy_grey600_24dp.xml
index b3f642191ca3..1feaab1663c1 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_content_copy_grey600_24dp.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_content_copy_grey600_24dp.xml
@@ -16,7 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="#757575"
+ android:tint="@*android:color/material_grey_600"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_data_saver.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_data_saver.xml
index 9acb62da7d43..ba3c5808d26c 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_data_saver.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_data_saver.xml
@@ -15,18 +15,19 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
- <path
- android:fillColor="@android:color/white"
- android:pathData="M3.36,7A10,10,0,0,0,20.27,17.64L18.1,16.39A7.5,7.5,0,1,1,11.25,4.56V2.05A10,10,0,0,0,3.36,7Z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M21,16.35a10,10,0,0,0-8.27-14.3V4.56a7.48,7.48,0,0,1,6.1,10.54Z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M8,12a0.76 0.76 ,0,0,0,0.75 0.75 h2.5v2.5a0.75 0.75 ,0,0,0,1.5,0v-2.5h2.5a0.75 0.75 ,0,0,0,0-1.5h-2.5V8.75a0.75 0.75 ,0,0,0-1.5,0v2.5H8.75A0.76 0.76 ,0,0,0,8,12Z" />
+ <group
+ android:translateX="2.000000"
+ android:translateY="2.000000" >
+ <path
+ android:fillColor="@android:color/white"
+ android:fillType="evenOdd"
+ android:pathData="M17.5000671,10 C17.5000671,6.198 14.6680671,3.064 11.0000671,2.574 L11.0000671,0.05 C16.0500671,0.55 20.0000671,4.82 20.0000671,10 C20.0000671,11.45 19.6800671,12.83 19.1200671,14.07 L16.9560671,12.796 C17.3040671,11.932 17.5000671,10.989 17.5000671,10 Z M10.0000671,17.5 C12.3900671,17.5 14.5140671,16.378 15.8870671,14.637 C16.6270671,15.073 18.0500671,15.91 18.0500671,15.91 C15.9790671,18.732 12.4710671,20.427 8.60106711,19.906 C4.22106711,19.316 0.68406711,15.774 0.0940671101,11.394 C-0.68693289,5.591 3.49306711,0.594 9.00006711,0.05 L9.00006711,2.574 C5.33206711,3.064 2.50006711,6.198 2.50006711,10 C2.50006711,14.142 5.85806711,17.5 10.0000671,17.5 Z M6,10 C6.00538581,9.58803794 6.33803794,9.25538581 6.75,9.25 L9.25,9.25 L9.25,6.75 C9.25,6.33578644 9.58578644,6 10,6 C10.4142136,6 10.75,6.33578644 10.75,6.75 L10.75,9.25 L13.25,9.25 C13.6642136,9.25 14,9.58578644 14,10 C14,10.4142136 13.6642136,10.75 13.25,10.75 L10.75,10.75 L10.75,13.25 C10.75,13.6642136 10.4142136,14 10,14 C9.58578644,14 9.25,13.6642136 9.25,13.25 L9.25,10.75 L6.75,10.75 C6.33803794,10.7446142 6.00538581,10.4119621 6,10 Z"
+ android:strokeWidth="1" />
+ </group>
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_devices_other.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_devices_other.xml
index 9283216b1a2f..463525d4bf26 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_devices_other.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_devices_other.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_eject_24dp.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_eject_24dp.xml
index 4e37a8866dfb..0d4bd9bc48d0 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_eject_24dp.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_eject_24dp.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_find_in_page_24px.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_find_in_page_24px.xml
new file mode 100644
index 000000000000..a54c0f080b5e
--- /dev/null
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_find_in_page_24px.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <group
+ android:translateX="4.000000"
+ android:translateY="2.000000" >
+ <path
+ android:fillColor="@android:color/white"
+ android:fillType="evenOdd"
+ android:pathData="M8,15.25 C6.208,15.25 4.75,13.792 4.75,12 C4.75,10.208 6.208,8.75 8,8.75 C9.792,8.75 11.25,10.208 11.25,12 C11.25,13.792 9.792,15.25 8,15.25 L8,15.25 Z M1.5,18 L1.5,2 C1.5,1.725 1.725,1.5 2,1.5 L9.379,1.5 L14.5,6.621 L14.5,17.439 L11.837,14.776 C12.405,13.993 12.75,13.039 12.75,12 C12.75,9.381 10.619,7.25 8,7.25 C5.381,7.25 3.25,9.381 3.25,12 C3.25,14.619 5.381,16.75 8,16.75 C9.039,16.75 9.993,16.405 10.776,15.837 L13.439,18.5 L2,18.5 C1.725,18.5 1.5,18.275 1.5,18 L1.5,18 Z M10,0 L2,0 C0.896,0 0,0.896 0,2 L0,18 C0,19.104 0.896,20 2,20 L14,20 C15.104,20 16,19.104 16,18 L16,6 L10,0 Z"
+ android:strokeWidth="1" />
+ </group>
+</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_help_actionbar.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_help_actionbar.xml
index e0a6f9553b15..c7d672efa574 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_help_actionbar.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_help_actionbar.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_network_cell.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_network_cell.xml
index 10e0f2fd1fca..fbe5ef03ad80 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_network_cell.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_network_cell.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_notifications_off_24dp.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_notifications_off_24dp.xml
index 81f18fb4b383..56a67c912176 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_notifications_off_24dp.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_notifications_off_24dp.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_data_usage.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_data_usage.xml
index b9c131b80ab6..855e4bb2a39d 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_data_usage.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_data_usage.xml
@@ -22,8 +22,7 @@
android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M12,20c-4.4,0-8-3.6-8-8c0-4.2,3.2-7.6,7.2-8V2C5.7,2.4,1.6,7.3,2,12.8c0.4,5.5,5.3,9.6,10.8,9.2c4.9-0.4,8.8-4.3,9.2-9.2 h-2C19.6,16.8,16.2,20,12,20z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M20,11.2h2c-0.4-4.9-4.3-8.9-9.2-9.2v2C16.6,4.4,19.6,7.4,20,11.2z" />
+ android:fillType="evenOdd"
+ android:pathData="M19.5000671,12 C19.5000671,8.198 16.6680671,5.064 13.0000671,4.574 L13.0000671,2.05 C18.0500671,2.55 22.0000671,6.82 22.0000671,12 C22.0000671,13.45 21.6800671,14.83 21.1200671,16.07 L18.9560671,14.796 C19.3040671,13.932 19.5000671,12.989 19.5000671,12 Z M12.0000671,19.5 C14.3900671,19.5 16.5140671,18.378 17.8870671,16.637 C18.6270671,17.073 20.0500671,17.91 20.0500671,17.91 C17.9790671,20.732 14.4710671,22.427 10.6010671,21.906 C6.22106711,21.316 2.68406711,17.774 2.09406711,13.394 C1.31306711,7.591 5.49306711,2.594 11.0000671,2.05 L11.0000671,4.574 C7.33206711,5.064 4.50006711,8.198 4.50006711,12 C4.50006711,16.142 7.85806711,19.5 12.0000671,19.5 Z"
+ android:strokeWidth="1" />
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_language.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_language.xml
new file mode 100644
index 000000000000..730942bda59c
--- /dev/null
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_language.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
+ android:viewportHeight="24"
+ android:viewportWidth="24"
+ android:width="24dp" >
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M12,22c5.52,0,10-4.48,10-10c0-5.52-4.48-10-10-10C6.48,2,2,6.48,2,12C2,17.52,6.48,22,12,22z M4.5,16h3.14 c0.4,1.41,1.01,2.8,1.84,4.12C7.34,19.45,5.55,17.95,4.5,16z M3.5,12c0-0.87,0.13-1.71,0.38-2.5H7.3c-0.29,1.66-0.3,3.34-0.01,5 H3.88C3.63,13.71,3.5,12.87,3.5,12z M20.5,12c0,0.87-0.13,1.71-0.38,2.5h-3.42c0.29-1.66,0.28-3.34-0.01-5h3.43 C20.37,10.29,20.5,11.13,20.5,12z M15.2,14.5H8.8c-0.33-1.66-0.32-3.34,0.01-5h6.39C15.53,11.16,15.53,12.84,15.2,14.5z M11.55,20.48c-1.08-1.43-1.86-2.94-2.36-4.48h5.62c-0.5,1.54-1.28,3.05-2.36,4.48c-0.15,0.01-0.3,0.02-0.45,0.02 S11.7,20.49,11.55,20.48z M14.51,20.12c0.83-1.32,1.44-2.71,1.84-4.12h3.14C18.45,17.95,16.66,19.45,14.51,20.12z M19.5,8h-3.15 c-0.4-1.41-1.01-2.79-1.84-4.12C16.66,4.54,18.45,6.04,19.5,8z M12.45,3.52C13.52,4.96,14.3,6.46,14.8,8H9.2 c0.5-1.54,1.28-3.04,2.35-4.48C11.7,3.51,11.85,3.5,12,3.5S12.3,3.51,12.45,3.52z M9.49,3.88C8.67,5.21,8.06,6.59,7.65,8H4.5 C5.55,6.04,7.34,4.54,9.49,3.88z" />
+</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_battery_saver_accent_24dp.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_multiuser.xml
index 9b39a9406dc8..83d9d2a9311e 100644
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_battery_saver_accent_24dp.xml
+++ b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_multiuser.xml
@@ -16,14 +16,14 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
- android:tint="?android:attr/colorAccent"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M9.74,13.75h1.5v1.5c0,0.41,0.34,0.75,0.75,0.75s0.75-0.34,0.75-0.75v-1.5h1.5c0.41,0,0.75-0.34,0.75-0.75 s-0.34-0.75-0.75-0.75h-1.5v-1.5c0-0.41-0.34-0.75-0.75-0.75s-0.75,0.34-0.75,0.75v1.5h-1.5c-0.41,0-0.75,0.34-0.75,0.75 S9.33,13.75,9.74,13.75z" />
+ android:pathData="M4,19c0,0.55,0.45,1,1,1h14c0.55,0,1-0.45,1-1v-3c0-1.66-1.34-3-3-3H7c-1.66,0-3,1.34-3,3V19z M5.5,16 c0-0.83,0.67-1.5,1.5-1.5h10c0.83,0,1.5,0.67,1.5,1.5v2.5h-13V16z" />
<path
android:fillColor="@android:color/white"
- android:pathData="M17,4h-3V3.49c0-0.55-0.45-1-1-1h-2c-0.55,0-1,0.45-1,1V4H7C6.45,4,6,4.45,6,5v16c0,0.55,0.45,1,1,1h10c0.55,0,1-0.45,1-1 V5C18,4.45,17.55,4,17,4z M16.5,20.5h-9v-15h9V20.5z" />
+ android:pathData="M8,8c0,2.21,1.79,4,4,4s4-1.79,4-4c0-2.21-1.79-4-4-4S8,5.79,8,8z M12,5.5c1.38,0,2.5,1.12,2.5,2.5 c0,1.38-1.12,2.5-2.5,2.5S9.5,9.38,9.5,8C9.5,6.62,10.62,5.5,12,5.5z" />
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_wireless_white.xml b/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_wireless_white.xml
deleted file mode 100644
index 0a1c3055870d..000000000000
--- a/packages/overlays/IconPackRoundedSettingsOverlay/res/drawable/ic_settings_wireless_white.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2019 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="24dp"
- android:viewportHeight="24"
- android:viewportWidth="24"
- android:width="24dp" >
- <path
- android:fillColor="@android:color/white"
- android:pathData="M12,2.75C7.95,2.69,4.05,4.3,1.22,7.2C0.96,7.5,0.97,7.95,1.24,8.23C1.53,8.53,2,8.54,2.3,8.25c2.55-2.61,6.05-4.06,9.7-4 c3.65-0.06,7.17,1.4,9.72,4.02c0.28,0.27,0.73,0.28,1.03,0.01c0.31-0.28,0.33-0.75,0.05-1.06C19.96,4.32,16.06,2.69,12,2.75z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M15.78,14.82c0.05,0.06,0.1,0.11,0.17,0.15c0.34,0.23,0.81,0.14,1.04-0.21s0.14-0.81-0.21-1.04 c-2.64-2.64-6.91-2.64-9.55,0c-0.27,0.29-0.27,0.73,0,1.02c0.28,0.3,0.76,0.32,1.06,0.04h0.03c0,0,0,0,0.01-0.01 c2.05-2.05,5.37-2.04,7.42,0.01C15.75,14.8,15.76,14.81,15.78,14.82z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M 12 17 C 12.8284271247 17 13.5 17.6715728753 13.5 18.5 C 13.5 19.3284271247 12.8284271247 20 12 20 C 11.1715728753 20 10.5 19.3284271247 10.5 18.5 C 10.5 17.6715728753 11.1715728753 17 12 17 Z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M20.03,11.79c0.3-0.29,0.3-0.77,0.01-1.06h-0.01c-2.12-2.18-5.01-3.44-8.04-3.5c-3.04,0.06-5.93,1.32-8.05,3.5 c-0.29,0.3-0.28,0.77,0.01,1.06c0.3,0.29,0.77,0.28,1.06-0.01c1.85-1.88,4.36-2.96,7-3c2.62,0.05,5.11,1.13,6.95,3 C19.25,12.07,19.73,12.08,20.03,11.79z" />
-</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_arrow_back.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_arrow_back.xml
index 03f06e997e26..34f79b4478c9 100644
--- a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_arrow_back.xml
+++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_arrow_back.xml
@@ -15,6 +15,7 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:autoMirrored="true"
android:height="24dp"
android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_brightness_thumb.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_brightness_thumb.xml
index 697d1c29eac7..62fcd4c3a33a 100644
--- a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_brightness_thumb.xml
+++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_brightness_thumb.xml
@@ -20,7 +20,7 @@
android:viewportWidth="24"
android:width="24dp" >
<path
- android:fillColor="?android:attr/colorPrimary"
+ android:fillColor="?android:attr/colorBackgroundFloating"
android:pathData="M 12 0 L 12 0 Q 24 0 24 12 L 24 12 Q 24 24 12 24 L 12 24 Q 0 24 0 12 L 0 12 Q 0 0 12 0 Z" />
<path
android:fillColor="?android:attr/colorControlActivated"
diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_camera.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_camera.xml
index 294e181faef8..142e078bdfd9 100644
--- a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_camera.xml
+++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_camera.xml
@@ -15,10 +15,10 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="24dp"
+ android:height="17dp"
android:viewportHeight="24"
android:viewportWidth="24"
- android:width="24dp" >
+ android:width="17dp" >
<path
android:fillColor="@android:color/white"
android:pathData="M22,7c0-1.1-0.9-2-2-2h-3l-1.41-1.41C15.21,3.21,14.7,3,14.17,3H9.83C9.3,3,8.79,3.21,8.41,3.59L7,5H4C2.9,5,2,5.9,2,7v12 c0,1.1,0.9,2,2,2h16c1.1,0,2-0.9,2-2V7z M20.5,19c0,0.28-0.22,0.5-0.5,0.5H4c-0.28,0-0.5-0.22-0.5-0.5V7c0-0.28,0.22-0.5,0.5-0.5 h3.62l1.85-1.85C9.57,4.55,9.69,4.5,9.83,4.5h4.34c0.13,0,0.26,0.05,0.35,0.15l1.85,1.85H20c0.28,0,0.5,0.22,0.5,0.5V19z" />
diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_cast_connected.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_cast_connected.xml
index 14d88e76bb91..f2821668c870 100644
--- a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_cast_connected.xml
+++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_cast_connected.xml
@@ -15,10 +15,10 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="17dp"
+ android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24"
- android:width="17dp" >
+ android:width="24dp" >
<path
android:fillColor="@android:color/white"
android:pathData="M20.5,4h-17C3.49,4,3.48,4,3.47,4C2.64,4.02,1.98,4.7,2,5.53v3.18c0,0.41,0.34,0.75,0.75,0.75S3.5,9.12,3.5,8.71 c0-1.96,0-3.21,0-3.21l17,0.03V18.5h-7.35c-0.41,0-0.75,0.34-0.75,0.75S12.74,20,13.15,20h7.35c0.01,0,0.02,0,0.03,0 c0.83-0.02,1.49-0.7,1.47-1.53V5.53c0-0.01,0-0.02,0-0.03C22,4.67,21.33,4,20.5,4z" />
diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_data_saver.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_data_saver.xml
index ee11b84b28ba..cdc3bfbd3d5f 100644
--- a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_data_saver.xml
+++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_data_saver.xml
@@ -15,17 +15,17 @@
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:height="18dp "
+ android:height="18dp"
android:viewportHeight="24"
android:viewportWidth="24"
- android:width="18dp " >
- <path
- android:fillColor="@android:color/white"
- android:pathData="M3.36,7A10,10,0,0,0,20.27,17.64L18.1,16.39A7.5,7.5,0,1,1,11.25,4.56V2.05A10,10,0,0,0,3.36,7Z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M21,16.35a10,10,0,0,0-8.27-14.3V4.56a7.48,7.48,0,0,1,6.1,10.54Z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M8,12a0.76 0.76 ,0,0,0,0.75 0.75 h2.5v2.5a0.75 0.75 ,0,0,0,1.5,0v-2.5h2.5a0.75 0.75 ,0,0,0,0-1.5h-2.5V8.75a0.75 0.75 ,0,0,0-1.5,0v2.5H8.75A0.76 0.76 ,0,0,0,8,12Z" />
+ android:width="18dp" >
+ <group
+ android:translateX="2.000000"
+ android:translateY="2.000000" >
+ <path
+ android:fillColor="@android:color/white"
+ android:fillType="evenOdd"
+ android:pathData="M17.5000671,10 C17.5000671,6.198 14.6680671,3.064 11.0000671,2.574 L11.0000671,0.05 C16.0500671,0.55 20.0000671,4.82 20.0000671,10 C20.0000671,11.45 19.6800671,12.83 19.1200671,14.07 L16.9560671,12.796 C17.3040671,11.932 17.5000671,10.989 17.5000671,10 Z M10.0000671,17.5 C12.3900671,17.5 14.5140671,16.378 15.8870671,14.637 C16.6270671,15.073 18.0500671,15.91 18.0500671,15.91 C15.9790671,18.732 12.4710671,20.427 8.60106711,19.906 C4.22106711,19.316 0.68406711,15.774 0.0940671101,11.394 C-0.68693289,5.591 3.49306711,0.594 9.00006711,0.05 L9.00006711,2.574 C5.33206711,3.064 2.50006711,6.198 2.50006711,10 C2.50006711,14.142 5.85806711,17.5 10.0000671,17.5 Z M6,10 C6.00538581,9.58803794 6.33803794,9.25538581 6.75,9.25 L9.25,9.25 L9.25,6.75 C9.25,6.33578644 9.58578644,6 10,6 C10.4142136,6 10.75,6.33578644 10.75,6.75 L10.75,9.25 L13.25,9.25 C13.6642136,9.25 14,9.58578644 14,10 C14,10.4142136 13.6642136,10.75 13.25,10.75 L10.75,10.75 L10.75,13.25 C10.75,13.6642136 10.4142136,14 10,14 C9.58578644,14 9.25,13.6642136 9.25,13.25 L9.25,10.75 L6.75,10.75 C6.33803794,10.7446142 6.00538581,10.4119621 6,10 Z"
+ android:strokeWidth="1" />
+ </group>
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_data_saver_off.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_data_saver_off.xml
index 3d620a18bb1a..7dab949f9da5 100644
--- a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_data_saver_off.xml
+++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_data_saver_off.xml
@@ -21,8 +21,7 @@
android:width="24dp" >
<path
android:fillColor="@android:color/white"
- android:pathData="M3.36,7A10,10,0,0,0,20.27,17.64L18.1,16.39A7.5,7.5,0,1,1,11.25,4.56V2.05A10,10,0,0,0,3.36,7Z" />
- <path
- android:fillColor="@android:color/white"
- android:pathData="M21,16.35a10,10,0,0,0-8.27-14.3V4.56a7.48,7.48,0,0,1,6.1,10.54Z" />
+ android:fillType="evenOdd"
+ android:pathData="M19.5000671,12 C19.5000671,8.198 16.6680671,5.064 13.0000671,4.574 L13.0000671,2.05 C18.0500671,2.55 22.0000671,6.82 22.0000671,12 C22.0000671,13.45 21.6800671,14.83 21.1200671,16.07 L18.9560671,14.796 C19.3040671,13.932 19.5000671,12.989 19.5000671,12 Z M12.0000671,19.5 C14.3900671,19.5 16.5140671,18.378 17.8870671,16.637 C18.6270671,17.073 20.0500671,17.91 20.0500671,17.91 C17.9790671,20.732 14.4710671,22.427 10.6010671,21.906 C6.22106711,21.316 2.68406711,17.774 2.09406711,13.394 C1.31306711,7.591 5.49306711,2.594 11.0000671,2.05 L11.0000671,4.574 C7.33206711,5.064 4.50006711,8.198 4.50006711,12 C4.50006711,16.142 7.85806711,19.5 12.0000671,19.5 Z"
+ android:strokeWidth="1" />
</vector> \ No newline at end of file
diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_bluetooth_connecting.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_bluetooth_connecting.xml
index f2284bc37287..85c2bcdbdce0 100644
--- a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_bluetooth_connecting.xml
+++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_qs_bluetooth_connecting.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_volume_alarm_mute.xml b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_volume_alarm_mute.xml
index 15201e924933..3a26cbaf7238 100644
--- a/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_volume_alarm_mute.xml
+++ b/packages/overlays/IconPackRoundedSystemUIOverlay/res/drawable/ic_volume_alarm_mute.xml
@@ -16,6 +16,7 @@
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
+ android:tint="?android:attr/colorControlNormal"
android:viewportHeight="24"
android:viewportWidth="24"
android:width="24dp" >
diff --git a/packages/overlays/NavigationBarModeGesturalOverlay/res/values/dimens.xml b/packages/overlays/NavigationBarModeGesturalOverlay/res/values/dimens.xml
index 987d20375e5e..1232201de862 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlay/res/values/dimens.xml
+++ b/packages/overlays/NavigationBarModeGesturalOverlay/res/values/dimens.xml
@@ -25,4 +25,6 @@
<dimen name="navigation_bar_width">16dp</dimen>
<!-- Height of the bottom navigation / system bar. -->
<dimen name="navigation_bar_frame_height">48dp</dimen>
+ <!-- The height of the bottom navigation gesture area. -->
+ <dimen name="navigation_bar_gesture_height">32dp</dimen>
</resources> \ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/Android.mk b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/Android.mk
new file mode 100644
index 000000000000..9a38efa2f95d
--- /dev/null
+++ b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/Android.mk
@@ -0,0 +1,30 @@
+#
+# Copyright 2019, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_RRO_THEME := NavigationBarModeGesturalExtraWideBack
+
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := NavigationBarModeGesturalOverlayExtraWideBack
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_RRO_PACKAGE) \ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/AndroidManifest.xml b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/AndroidManifest.xml
new file mode 100644
index 000000000000..ba7bebac16a4
--- /dev/null
+++ b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<!--
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.internal.systemui.navbar.gestural_extra_wide_back"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <overlay android:targetPackage="android"
+ android:category="com.android.internal.navigation_bar_mode"
+ android:priority="1"/>
+
+ <application android:label="@string/navigation_bar_mode_title" android:hasCode="false"/>
+</manifest> \ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/config.xml b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/config.xml
new file mode 100644
index 000000000000..c8f994c982e5
--- /dev/null
+++ b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/config.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources>
+ <!-- Controls the navigation bar interaction mode:
+ 0: 3 button mode (back, home, overview buttons)
+ 1: 2 button mode (back, home buttons + swipe up for overview)
+ 2: gestures only for back, home and overview -->
+ <integer name="config_navBarInteractionMode">2</integer>
+
+ <!-- Controls whether the nav bar can move from the bottom to the side in landscape.
+ Only applies if the device display is not square. -->
+ <bool name="config_navBarCanMove">false</bool>
+
+ <!-- Controls whether the navigation bar lets through taps. -->
+ <bool name="config_navBarTapThrough">true</bool>
+
+ <!-- Controls the size of the back gesture inset. -->
+ <dimen name="config_backGestureInset">40dp</dimen>
+
+ <!-- Controls whether the navbar needs a scrim with
+ {@link Window#setEnsuringNavigationBarContrastWhenTransparent}. -->
+ <bool name="config_navBarNeedsScrim">false</bool>
+
+ <!-- Controls whether seamless rotation should be allowed even though the navbar can move
+ (which normally prevents seamless rotation). -->
+ <bool name="config_allowSeamlessRotationDespiteNavBarMoving">true</bool>
+
+ <!-- Controls whether the side edge gestures can always trigger the transient nav bar to
+ show. -->
+ <bool name="config_navBarAlwaysShowOnSideEdgeGesture">true</bool>
+
+</resources>
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/dimens.xml b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/dimens.xml
new file mode 100644
index 000000000000..987d20375e5e
--- /dev/null
+++ b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/dimens.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources>
+ <!-- Height of the bottom navigation / system bar. -->
+ <dimen name="navigation_bar_height">16dp</dimen>
+ <!-- Height of the bottom navigation bar in portrait; often the same as @dimen/navigation_bar_height -->
+ <dimen name="navigation_bar_height_landscape">16dp</dimen>
+ <!-- Width of the navigation bar when it is placed vertically on the screen -->
+ <dimen name="navigation_bar_width">16dp</dimen>
+ <!-- Height of the bottom navigation / system bar. -->
+ <dimen name="navigation_bar_frame_height">48dp</dimen>
+</resources> \ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/strings.xml b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/strings.xml
new file mode 100644
index 000000000000..bbab5e0477f7
--- /dev/null
+++ b/packages/overlays/NavigationBarModeGesturalOverlayExtraWideBack/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Name of overlay [CHAR LIMIT=64] -->
+ <string name="navigation_bar_mode_title" translatable="false">Gestural Navigation Bar</string>
+</resources> \ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/Android.mk b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/Android.mk
new file mode 100644
index 000000000000..1d004c83faef
--- /dev/null
+++ b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/Android.mk
@@ -0,0 +1,30 @@
+#
+# Copyright 2019, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_RRO_THEME := NavigationBarModeGesturalNarrowBack
+
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := NavigationBarModeGesturalOverlayNarrowBack
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_RRO_PACKAGE) \ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/AndroidManifest.xml b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/AndroidManifest.xml
new file mode 100644
index 000000000000..8de91c0cf8ab
--- /dev/null
+++ b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<!--
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.internal.systemui.navbar.gestural_narrow_back"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <overlay android:targetPackage="android"
+ android:category="com.android.internal.navigation_bar_mode"
+ android:priority="1"/>
+
+ <application android:label="@string/navigation_bar_mode_title" android:hasCode="false"/>
+</manifest> \ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/config.xml b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/config.xml
new file mode 100644
index 000000000000..693110adb312
--- /dev/null
+++ b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/config.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources>
+ <!-- Controls the navigation bar interaction mode:
+ 0: 3 button mode (back, home, overview buttons)
+ 1: 2 button mode (back, home buttons + swipe up for overview)
+ 2: gestures only for back, home and overview -->
+ <integer name="config_navBarInteractionMode">2</integer>
+
+ <!-- Controls whether the nav bar can move from the bottom to the side in landscape.
+ Only applies if the device display is not square. -->
+ <bool name="config_navBarCanMove">false</bool>
+
+ <!-- Controls whether the navigation bar lets through taps. -->
+ <bool name="config_navBarTapThrough">true</bool>
+
+ <!-- Controls the size of the back gesture inset. -->
+ <dimen name="config_backGestureInset">18dp</dimen>
+
+ <!-- Controls whether the navbar needs a scrim with
+ {@link Window#setEnsuringNavigationBarContrastWhenTransparent}. -->
+ <bool name="config_navBarNeedsScrim">false</bool>
+
+ <!-- Controls whether seamless rotation should be allowed even though the navbar can move
+ (which normally prevents seamless rotation). -->
+ <bool name="config_allowSeamlessRotationDespiteNavBarMoving">true</bool>
+
+ <!-- Controls whether the side edge gestures can always trigger the transient nav bar to
+ show. -->
+ <bool name="config_navBarAlwaysShowOnSideEdgeGesture">true</bool>
+
+</resources>
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/dimens.xml b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/dimens.xml
new file mode 100644
index 000000000000..987d20375e5e
--- /dev/null
+++ b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/dimens.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources>
+ <!-- Height of the bottom navigation / system bar. -->
+ <dimen name="navigation_bar_height">16dp</dimen>
+ <!-- Height of the bottom navigation bar in portrait; often the same as @dimen/navigation_bar_height -->
+ <dimen name="navigation_bar_height_landscape">16dp</dimen>
+ <!-- Width of the navigation bar when it is placed vertically on the screen -->
+ <dimen name="navigation_bar_width">16dp</dimen>
+ <!-- Height of the bottom navigation / system bar. -->
+ <dimen name="navigation_bar_frame_height">48dp</dimen>
+</resources> \ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/strings.xml b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/strings.xml
new file mode 100644
index 000000000000..bbab5e0477f7
--- /dev/null
+++ b/packages/overlays/NavigationBarModeGesturalOverlayNarrowBack/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Name of overlay [CHAR LIMIT=64] -->
+ <string name="navigation_bar_mode_title" translatable="false">Gestural Navigation Bar</string>
+</resources> \ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/Android.mk b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/Android.mk
new file mode 100644
index 000000000000..0ab463f8e49f
--- /dev/null
+++ b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/Android.mk
@@ -0,0 +1,30 @@
+#
+# Copyright 2019, The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_RRO_THEME := NavigationBarModeGesturalWideBack
+
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := NavigationBarModeGesturalOverlayWideBack
+LOCAL_SDK_VERSION := current
+
+include $(BUILD_RRO_PACKAGE) \ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/AndroidManifest.xml b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/AndroidManifest.xml
new file mode 100644
index 000000000000..daf461382b28
--- /dev/null
+++ b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/AndroidManifest.xml
@@ -0,0 +1,27 @@
+<!--
+/**
+ * Copyright (c) 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.internal.systemui.navbar.gestural_wide_back"
+ android:versionCode="1"
+ android:versionName="1.0">
+ <overlay android:targetPackage="android"
+ android:category="com.android.internal.navigation_bar_mode"
+ android:priority="1"/>
+
+ <application android:label="@string/navigation_bar_mode_title" android:hasCode="false"/>
+</manifest> \ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/config.xml b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/config.xml
new file mode 100644
index 000000000000..5cd6ce3d7d50
--- /dev/null
+++ b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/config.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources>
+ <!-- Controls the navigation bar interaction mode:
+ 0: 3 button mode (back, home, overview buttons)
+ 1: 2 button mode (back, home buttons + swipe up for overview)
+ 2: gestures only for back, home and overview -->
+ <integer name="config_navBarInteractionMode">2</integer>
+
+ <!-- Controls whether the nav bar can move from the bottom to the side in landscape.
+ Only applies if the device display is not square. -->
+ <bool name="config_navBarCanMove">false</bool>
+
+ <!-- Controls whether the navigation bar lets through taps. -->
+ <bool name="config_navBarTapThrough">true</bool>
+
+ <!-- Controls the size of the back gesture inset. -->
+ <dimen name="config_backGestureInset">32dp</dimen>
+
+ <!-- Controls whether the navbar needs a scrim with
+ {@link Window#setEnsuringNavigationBarContrastWhenTransparent}. -->
+ <bool name="config_navBarNeedsScrim">false</bool>
+
+ <!-- Controls whether seamless rotation should be allowed even though the navbar can move
+ (which normally prevents seamless rotation). -->
+ <bool name="config_allowSeamlessRotationDespiteNavBarMoving">true</bool>
+
+ <!-- Controls whether the side edge gestures can always trigger the transient nav bar to
+ show. -->
+ <bool name="config_navBarAlwaysShowOnSideEdgeGesture">true</bool>
+
+</resources>
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/dimens.xml b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/dimens.xml
new file mode 100644
index 000000000000..987d20375e5e
--- /dev/null
+++ b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/dimens.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources>
+ <!-- Height of the bottom navigation / system bar. -->
+ <dimen name="navigation_bar_height">16dp</dimen>
+ <!-- Height of the bottom navigation bar in portrait; often the same as @dimen/navigation_bar_height -->
+ <dimen name="navigation_bar_height_landscape">16dp</dimen>
+ <!-- Width of the navigation bar when it is placed vertically on the screen -->
+ <dimen name="navigation_bar_width">16dp</dimen>
+ <!-- Height of the bottom navigation / system bar. -->
+ <dimen name="navigation_bar_frame_height">48dp</dimen>
+</resources> \ No newline at end of file
diff --git a/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/strings.xml b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/strings.xml
new file mode 100644
index 000000000000..bbab5e0477f7
--- /dev/null
+++ b/packages/overlays/NavigationBarModeGesturalOverlayWideBack/res/values/strings.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Name of overlay [CHAR LIMIT=64] -->
+ <string name="navigation_bar_mode_title" translatable="false">Gestural Navigation Bar</string>
+</resources> \ No newline at end of file
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 71d03a86300d..0f0e6f9fb446 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -7376,6 +7376,18 @@ message MetricsEvent {
// OS: Q
FIELD_BIOMETRIC_AUTH_ERROR = 1741;
+ // Custom tag for NotificationItem. Hash of the NAS that made adjustments.
+ FIELD_NOTIFICATION_ASSISTANT_SERVICE_HASH = 1742;
+
+ // Report interactions with seekbar on media notifications
+ // OPEN: Seekbar is visible
+ // CLOSE: Seekbar is not visible
+ // DETAIL: Seekbar scrubber enabled / disabled
+ // Subtype: 0 disabled, cannot seek; 1 enabled, can seek
+ // UPDATE: Scrubber was moved by user
+ // CATEGORY: NOTIFICATION
+ MEDIA_NOTIFICATION_SEEKBAR = 1743;
+
// ---- End Q Constants, all Q constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
index 430abf5c479d..10ba9a5e98d9 100644
--- a/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
+++ b/services/appprediction/java/com/android/server/appprediction/AppPredictionPerUserService.java
@@ -28,13 +28,17 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ParceledListSlice;
import android.content.pm.ServiceInfo;
+import android.os.IBinder;
import android.os.RemoteException;
import android.service.appprediction.AppPredictionService;
+import android.util.ArrayMap;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.server.infra.AbstractPerUserSystemService;
+import java.util.ArrayList;
+
/**
* Per-user instance of {@link AppPredictionManagerService}.
*/
@@ -48,6 +52,17 @@ public class AppPredictionPerUserService extends
@GuardedBy("mLock")
private RemoteAppPredictionService mRemoteService;
+ /**
+ * When {@code true}, remote service died but service state is kept so it's restored after
+ * the system re-binds to it.
+ */
+ @GuardedBy("mLock")
+ private boolean mZombie;
+
+ @GuardedBy("mLock")
+ private final ArrayMap<AppPredictionSessionId, AppPredictionSessionInfo> mSessionInfos =
+ new ArrayMap<>();
+
protected AppPredictionPerUserService(AppPredictionManagerService master,
Object lock, int userId) {
super(master, lock, userId);
@@ -92,6 +107,16 @@ public class AppPredictionPerUserService extends
final RemoteAppPredictionService service = getRemoteServiceLocked();
if (service != null) {
service.onCreatePredictionSession(context, sessionId);
+
+ mSessionInfos.put(sessionId, new AppPredictionSessionInfo(sessionId, context, () -> {
+ synchronized (mLock) {
+ AppPredictionSessionInfo sessionInfo = mSessionInfos.get(sessionId);
+ if (sessionInfo != null) {
+ sessionInfo.removeAllCallbacksLocked();
+ mSessionInfos.remove(sessionId);
+ }
+ }
+ }));
}
}
@@ -140,6 +165,11 @@ public class AppPredictionPerUserService extends
final RemoteAppPredictionService service = getRemoteServiceLocked();
if (service != null) {
service.registerPredictionUpdates(sessionId, callback);
+
+ AppPredictionSessionInfo sessionInfo = mSessionInfos.get(sessionId);
+ if (sessionInfo != null) {
+ sessionInfo.addCallbackLocked(callback);
+ }
}
}
@@ -152,6 +182,11 @@ public class AppPredictionPerUserService extends
final RemoteAppPredictionService service = getRemoteServiceLocked();
if (service != null) {
service.unregisterPredictionUpdates(sessionId, callback);
+
+ AppPredictionSessionInfo sessionInfo = mSessionInfos.get(sessionId);
+ if (sessionInfo != null) {
+ sessionInfo.removeCallbackLocked(callback);
+ }
}
}
@@ -174,6 +209,12 @@ public class AppPredictionPerUserService extends
final RemoteAppPredictionService service = getRemoteServiceLocked();
if (service != null) {
service.onDestroyPredictionSession(sessionId);
+
+ AppPredictionSessionInfo sessionInfo = mSessionInfos.get(sessionId);
+ if (sessionInfo != null) {
+ sessionInfo.removeAllCallbacksLocked();
+ mSessionInfos.remove(sessionId);
+ }
}
}
@@ -182,17 +223,54 @@ public class AppPredictionPerUserService extends
if (isDebug()) {
Slog.d(TAG, "onFailureOrTimeout(): timed out=" + timedOut);
}
-
// Do nothing, we are just proxying to the prediction service
}
@Override
+ public void onConnectedStateChanged(boolean connected) {
+ if (isDebug()) {
+ Slog.d(TAG, "onConnectedStateChanged(): connected=" + connected);
+ }
+ if (connected) {
+ synchronized (mLock) {
+ if (mZombie) {
+ // Sanity check - shouldn't happen
+ if (mRemoteService == null) {
+ Slog.w(TAG, "Cannot resurrect sessions because remote service is null");
+ return;
+ }
+ mZombie = false;
+ resurrectSessionsLocked();
+ }
+ }
+ }
+ }
+
+ @Override
public void onServiceDied(RemoteAppPredictionService service) {
if (isDebug()) {
- Slog.d(TAG, "onServiceDied():");
+ Slog.w(TAG, "onServiceDied(): service=" + service);
+ }
+ synchronized (mLock) {
+ mZombie = true;
+ }
+ // Do nothing, eventually the system will bind to the remote service again...
+ }
+
+ /**
+ * Called after the remote service connected, it's used to restore state from a 'zombie'
+ * service (i.e., after it died).
+ */
+ private void resurrectSessionsLocked() {
+ final int numSessions = mSessionInfos.size();
+ if (isDebug()) {
+ Slog.d(TAG, "Resurrecting remote service (" + mRemoteService + ") on "
+ + numSessions + " sessions.");
}
- // Do nothing, we are just proxying to the prediction service
+ for (AppPredictionSessionInfo sessionInfo : mSessionInfos.values()) {
+ sessionInfo.resurrectSessionLocked(this);
+ }
}
@GuardedBy("mLock")
@@ -215,4 +293,57 @@ public class AppPredictionPerUserService extends
return mRemoteService;
}
+
+ private static final class AppPredictionSessionInfo {
+ private final AppPredictionSessionId mSessionId;
+ private final AppPredictionContext mContext;
+ private final ArrayList<IPredictionCallback> mCallbacks = new ArrayList<>();
+ private final IBinder.DeathRecipient mBinderDeathHandler;
+
+ AppPredictionSessionInfo(AppPredictionSessionId id, AppPredictionContext context,
+ IBinder.DeathRecipient binderDeathHandler) {
+ mSessionId = id;
+ mContext = context;
+ mBinderDeathHandler = binderDeathHandler;
+ }
+
+ void addCallbackLocked(IPredictionCallback callback) {
+ if (mBinderDeathHandler != null) {
+ try {
+ callback.asBinder().linkToDeath(mBinderDeathHandler, 0);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to link to death: " + e);
+ }
+ }
+ mCallbacks.add(callback);
+ }
+
+ void removeCallbackLocked(IPredictionCallback callback) {
+ if (mBinderDeathHandler != null) {
+ callback.asBinder().unlinkToDeath(mBinderDeathHandler, 0);
+ }
+ mCallbacks.remove(callback);
+ }
+
+ void removeAllCallbacksLocked() {
+ if (mBinderDeathHandler != null) {
+ for (IPredictionCallback callback : mCallbacks) {
+ callback.asBinder().unlinkToDeath(mBinderDeathHandler, 0);
+ }
+ }
+ mCallbacks.clear();
+ }
+
+ void resurrectSessionLocked(AppPredictionPerUserService service) {
+ if (service.isDebug()) {
+ Slog.d(TAG, "Resurrecting remote service (" + service.getRemoteServiceLocked()
+ + ") for session Id=" + mSessionId + " and "
+ + mCallbacks.size() + " callbacks.");
+ }
+ service.onCreatePredictionSessionLocked(mContext, mSessionId);
+ for (IPredictionCallback callback : mCallbacks) {
+ service.registerPredictionUpdatesLocked(mSessionId, callback);
+ }
+ }
+ }
}
diff --git a/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java b/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java
index 19226be2e1ca..c82e7a012fff 100644
--- a/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java
+++ b/services/appprediction/java/com/android/server/appprediction/RemoteAppPredictionService.java
@@ -42,6 +42,8 @@ public class RemoteAppPredictionService extends
private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 2 * DateUtils.SECOND_IN_MILLIS;
+ private final RemoteAppPredictionServiceCallbacks mCallback;
+
public RemoteAppPredictionService(Context context, String serviceInterface,
ComponentName componentName, int userId,
RemoteAppPredictionServiceCallbacks callback, boolean bindInstantServiceAllowed,
@@ -50,6 +52,7 @@ public class RemoteAppPredictionService extends
context.getMainThreadHandler(),
bindInstantServiceAllowed ? Context.BIND_ALLOW_INSTANT : 0,
verbose, /* initialCapacity= */ 1);
+ mCallback = callback;
}
@Override
@@ -141,5 +144,17 @@ public class RemoteAppPredictionService extends
* Notifies a the failure or timeout of a remote call.
*/
void onFailureOrTimeout(boolean timedOut);
+
+ /**
+ * Notifies change in connected state of the remote service.
+ */
+ void onConnectedStateChanged(boolean connected);
+ }
+
+ @Override // from AbstractRemoteService
+ protected void handleOnConnectedStateChanged(boolean connected) {
+ if (mCallback != null) {
+ mCallback.onConnectedStateChanged(connected);
+ }
}
}
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 66b5437f0a7d..af9b0e2aa7b1 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -2178,6 +2178,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
private void requestNewFillResponseOnViewEnteredIfNecessaryLocked(@NonNull AutofillId id,
@NonNull ViewState viewState, int flags) {
if ((flags & FLAG_MANUAL_REQUEST) != 0) {
+ mForAugmentedAutofillOnly = false;
if (sDebug) Slog.d(TAG, "Re-starting session on view " + id + " and flags " + flags);
requestNewFillResponseLocked(viewState, ViewState.STATE_RESTARTED_SESSION, flags);
return;
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index dfbb55a02ec7..d0edaaaf7619 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -1763,7 +1763,7 @@ class AlarmManagerService extends SystemService {
+ ", callingPackage: " + callingPackage;
// STOPSHIP (b/128866264): Just to catch breakages. Remove before final release.
Slog.wtf(TAG, errorMsg);
- throw new UnsupportedOperationException(errorMsg);
+ throw new IllegalStateException(errorMsg);
}
setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, maxElapsed,
interval, operation, directReceiver, listenerTag, flags, true, workSource,
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 0a1dbff38bf3..d6b4043af4fe 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -91,6 +91,7 @@ import android.net.NetworkFactory;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
import android.net.NetworkMisc;
+import android.net.NetworkMonitorManager;
import android.net.NetworkPolicyManager;
import android.net.NetworkQuotaInfo;
import android.net.NetworkRequest;
@@ -169,6 +170,7 @@ import com.android.internal.util.MessageUtils;
import com.android.internal.util.WakeupMessage;
import com.android.internal.util.XmlUtils;
import com.android.server.am.BatteryStatsService;
+import com.android.server.connectivity.AutodestructReference;
import com.android.server.connectivity.DataConnectionStats;
import com.android.server.connectivity.DnsManager;
import com.android.server.connectivity.DnsManager.PrivateDnsValidationUpdate;
@@ -1785,8 +1787,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// caller type. Need to re-factor NetdEventListenerService to allow multiple
// NetworkMonitor registrants.
if (nai != null && nai.satisfies(mDefaultRequest)) {
- Binder.withCleanCallingIdentity(() ->
- nai.networkMonitor().notifyDnsResponse(returnCode));
+ nai.networkMonitor().notifyDnsResponse(returnCode);
}
}
@@ -2763,29 +2764,31 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
private class NetworkMonitorCallbacks extends INetworkMonitorCallbacks.Stub {
- private final NetworkAgentInfo mNai;
+ private final int mNetId;
+ private final AutodestructReference<NetworkAgentInfo> mNai;
private NetworkMonitorCallbacks(NetworkAgentInfo nai) {
- mNai = nai;
+ mNetId = nai.network.netId;
+ mNai = new AutodestructReference(nai);
}
@Override
public void onNetworkMonitorCreated(INetworkMonitor networkMonitor) {
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT,
- new Pair<>(mNai, networkMonitor)));
+ new Pair<>(mNai.getAndDestroy(), networkMonitor)));
}
@Override
public void notifyNetworkTested(int testResult, @Nullable String redirectUrl) {
mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(EVENT_NETWORK_TESTED,
- testResult, mNai.network.netId, redirectUrl));
+ testResult, mNetId, redirectUrl));
}
@Override
public void notifyPrivateDnsConfigResolved(PrivateDnsConfigParcel config) {
mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(
EVENT_PRIVATE_DNS_CONFIG_RESOLVED,
- 0, mNai.network.netId, PrivateDnsConfig.fromParcel(config)));
+ 0, mNetId, PrivateDnsConfig.fromParcel(config)));
}
@Override
@@ -2803,15 +2806,13 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(
EVENT_PROVISIONING_NOTIFICATION, PROVISIONING_NOTIFICATION_SHOW,
- mNai.network.netId,
- pendingIntent));
+ mNetId, pendingIntent));
}
@Override
public void hideProvisioningNotification() {
mTrackerHandler.sendMessage(mTrackerHandler.obtainMessage(
- EVENT_PROVISIONING_NOTIFICATION, PROVISIONING_NOTIFICATION_HIDE,
- mNai.network.netId));
+ EVENT_PROVISIONING_NOTIFICATION, PROVISIONING_NOTIFICATION_HIDE, mNetId));
}
@Override
@@ -2853,11 +2854,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// Notify the NetworkAgentInfo/NetworkMonitor in case NetworkMonitor needs to cancel or
// schedule DNS resolutions. If a DNS resolution is required the
// result will be sent back to us.
- try {
- nai.networkMonitor().notifyPrivateDnsChanged(cfg.toParcel());
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
+ nai.networkMonitor().notifyPrivateDnsChanged(cfg.toParcel());
// With Private DNS bypass support, we can proceed to update the
// Private DNS config immediately, even if we're in strict mode
@@ -3023,11 +3020,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// Disable wakeup packet monitoring for each interface.
wakeupModifyInterface(iface, nai.networkCapabilities, false);
}
- try {
- nai.networkMonitor().notifyNetworkDisconnected();
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
+ nai.networkMonitor().notifyNetworkDisconnected();
mNetworkAgentInfos.remove(nai.messenger);
nai.clatd.update();
synchronized (mNetworkForNetId) {
@@ -3440,11 +3433,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
//
// TODO: NetworkMonitor does not refer to the "never ask again" bit. The bit is stored
// per network. Therefore, NetworkMonitor may still do https probe.
- try {
- nai.networkMonitor().setAcceptPartialConnectivity();
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
+ nai.networkMonitor().setAcceptPartialConnectivity();
}
}
@@ -3476,11 +3465,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
if (nai == null) return;
if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_CAPTIVE_PORTAL)) return;
- try {
- nai.networkMonitor().launchCaptivePortalApp();
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
+ nai.networkMonitor().launchCaptivePortalApp();
});
}
@@ -3515,7 +3500,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
@Override
- public void appResponse(final int response) throws RemoteException {
+ public void appResponse(final int response) {
if (response == CaptivePortal.APP_RETURN_WANTED_AS_IS) {
enforceSettingsPermission();
}
@@ -3525,16 +3510,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (nai == null) return;
// nai.networkMonitor() is thread-safe
- final INetworkMonitor nm = nai.networkMonitor();
+ final NetworkMonitorManager nm = nai.networkMonitor();
if (nm == null) return;
-
- final long token = Binder.clearCallingIdentity();
- try {
- nm.notifyCaptivePortalAppFinished(response);
- } finally {
- // Not using Binder.withCleanCallingIdentity() to keep the checked RemoteException
- Binder.restoreCallingIdentity(token);
- }
+ nm.notifyCaptivePortalAppFinished(response);
}
@Override
@@ -4105,11 +4083,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (isNetworkWithLinkPropertiesBlocked(lp, uid, false)) {
return;
}
- try {
- nai.networkMonitor().forceReevaluation(uid);
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
+ nai.networkMonitor().forceReevaluation(uid);
}
/**
@@ -4363,7 +4337,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
/**
* @return VPN information for accounting, or null if we can't retrieve all required
- * information, e.g primary underlying iface.
+ * information, e.g underlying ifaces.
*/
@Nullable
private VpnInfo createVpnInfo(Vpn vpn) {
@@ -4375,17 +4349,24 @@ public class ConnectivityService extends IConnectivityManager.Stub
// see VpnService.setUnderlyingNetworks()'s javadoc about how to interpret
// the underlyingNetworks list.
if (underlyingNetworks == null) {
- NetworkAgentInfo defaultNetwork = getDefaultNetwork();
- if (defaultNetwork != null && defaultNetwork.linkProperties != null) {
- info.primaryUnderlyingIface = getDefaultNetwork().linkProperties.getInterfaceName();
+ NetworkAgentInfo defaultNai = getDefaultNetwork();
+ if (defaultNai != null) {
+ underlyingNetworks = new Network[] { defaultNai.network };
+ }
+ }
+ if (underlyingNetworks != null && underlyingNetworks.length > 0) {
+ List<String> interfaces = new ArrayList<>();
+ for (Network network : underlyingNetworks) {
+ LinkProperties lp = getLinkProperties(network);
+ if (lp != null && !TextUtils.isEmpty(lp.getInterfaceName())) {
+ interfaces.add(lp.getInterfaceName());
+ }
}
- } else if (underlyingNetworks.length > 0) {
- LinkProperties linkProperties = getLinkProperties(underlyingNetworks[0]);
- if (linkProperties != null) {
- info.primaryUnderlyingIface = linkProperties.getInterfaceName();
+ if (!interfaces.isEmpty()) {
+ info.underlyingIfaces = interfaces.toArray(new String[interfaces.size()]);
}
}
- return info.primaryUnderlyingIface == null ? null : info;
+ return info.underlyingIfaces == null ? null : info;
}
/**
@@ -5535,11 +5516,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// Start or stop DNS64 detection and 464xlat according to network state.
networkAgent.clatd.update();
notifyIfacesChangedForNetworkStats();
- try {
- networkAgent.networkMonitor().notifyLinkPropertiesChanged(newLp);
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
- }
+ networkAgent.networkMonitor().notifyLinkPropertiesChanged(newLp);
if (networkAgent.everConnected) {
notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_IP_CHANGED);
}
@@ -6523,15 +6500,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
// command must be sent after updating LinkProperties to maximize chances of
// NetworkMonitor seeing the correct LinkProperties when starting.
// TODO: pass LinkProperties to the NetworkMonitor in the notifyNetworkConnected call.
- try {
- if (networkAgent.networkMisc.acceptPartialConnectivity) {
- networkAgent.networkMonitor().setAcceptPartialConnectivity();
- }
- networkAgent.networkMonitor().notifyNetworkConnected(
- networkAgent.linkProperties, networkAgent.networkCapabilities);
- } catch (RemoteException e) {
- e.rethrowAsRuntimeException();
+ if (networkAgent.networkMisc.acceptPartialConnectivity) {
+ networkAgent.networkMonitor().setAcceptPartialConnectivity();
}
+ networkAgent.networkMonitor().notifyNetworkConnected(
+ networkAgent.linkProperties, networkAgent.networkCapabilities);
scheduleUnvalidatedPrompt(networkAgent);
// Whether a particular NetworkRequest listen should cause signal strength thresholds to
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index d52fe8170358..ae04f76b95b4 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -82,6 +82,7 @@ import android.os.UserManager;
import android.os.WorkSource;
import android.os.WorkSource.WorkChain;
import android.provider.Settings;
+import android.stats.location.LocationStatsEnums;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
@@ -269,10 +270,14 @@ public class LocationManagerService extends ILocationManager.Stub {
@PowerManager.LocationPowerSaveMode
private int mBatterySaverMode;
+ @GuardedBy("mLock")
+ private final LocationUsageLogger mLocationUsageLogger;
+
public LocationManagerService(Context context) {
super();
mContext = context;
mHandler = FgThread.getHandler();
+ mLocationUsageLogger = new LocationUsageLogger();
// Let the package manager query which are the default location
// providers as they get certain permissions granted by default.
@@ -2346,7 +2351,18 @@ public class LocationManagerService extends ILocationManager.Stub {
* Method to be called when a record will no longer be used.
*/
private void disposeLocked(boolean removeReceiver) {
- mRequestStatistics.stopRequesting(mReceiver.mCallerIdentity.mPackageName, mProvider);
+ String packageName = mReceiver.mCallerIdentity.mPackageName;
+ mRequestStatistics.stopRequesting(packageName, mProvider);
+
+ mLocationUsageLogger.logLocationApiUsage(
+ LocationStatsEnums.USAGE_ENDED,
+ LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
+ packageName,
+ mRealRequest,
+ mReceiver.isListener(),
+ mReceiver.isPendingIntent(),
+ /* radius= */ 0,
+ mActivityManager.getPackageImportance(packageName));
// remove from mRecordsByProvider
ArrayList<UpdateRecord> globalRecords = mRecordsByProvider.get(this.mProvider);
@@ -2521,6 +2537,13 @@ public class LocationManagerService extends ILocationManager.Stub {
"cannot register both listener and intent");
}
+ mLocationUsageLogger.logLocationApiUsage(
+ LocationStatsEnums.USAGE_STARTED,
+ LocationStatsEnums.API_REQUEST_LOCATION_UPDATES,
+ packageName, request, listener != null, intent != null,
+ /* radius= */ 0,
+ mActivityManager.getPackageImportance(packageName));
+
Receiver receiver;
if (intent != null) {
receiver = getReceiverLocked(intent, pid, uid, packageName, workSource,
@@ -2813,6 +2836,18 @@ public class LocationManagerService extends ILocationManager.Stub {
}
long identity = Binder.clearCallingIdentity();
try {
+ synchronized (mLock) {
+ mLocationUsageLogger.logLocationApiUsage(
+ LocationStatsEnums.USAGE_STARTED,
+ LocationStatsEnums.API_REQUEST_GEOFENCE,
+ packageName,
+ request,
+ /* hasListener= */ false,
+ intent != null,
+ geofence.getRadius(),
+ mActivityManager.getPackageImportance(packageName));
+ }
+
mGeofenceManager.addFence(sanitizedRequest, geofence, intent,
allowedResolutionLevel,
uid, packageName);
@@ -2833,6 +2868,17 @@ public class LocationManagerService extends ILocationManager.Stub {
// geo-fence manager uses the public location API, need to clear identity
long identity = Binder.clearCallingIdentity();
try {
+ synchronized (mLock) {
+ mLocationUsageLogger.logLocationApiUsage(
+ LocationStatsEnums.USAGE_ENDED,
+ LocationStatsEnums.API_REQUEST_GEOFENCE,
+ packageName,
+ /* LocationRequest= */ null,
+ /* hasListener= */ false,
+ intent != null,
+ geofence.getRadius(),
+ mActivityManager.getPackageImportance(packageName));
+ }
mGeofenceManager.removeFence(geofence, intent);
} finally {
Binder.restoreCallingIdentity(identity);
@@ -2916,6 +2962,20 @@ public class LocationManagerService extends ILocationManager.Stub {
gnssDataListeners.put(binder, linkedListener);
long identity = Binder.clearCallingIdentity();
try {
+ if (gnssDataProvider == mGnssNavigationMessageProvider
+ || gnssDataProvider == mGnssStatusProvider) {
+ mLocationUsageLogger.logLocationApiUsage(
+ LocationStatsEnums.USAGE_STARTED,
+ gnssDataProvider == mGnssNavigationMessageProvider
+ ? LocationStatsEnums.API_ADD_GNSS_MEASUREMENTS_LISTENER
+ : LocationStatsEnums.API_REGISTER_GNSS_STATUS_CALLBACK,
+ packageName,
+ /* LocationRequest= */ null,
+ /* hasListener= */ true,
+ /* hasIntent= */ false,
+ /* radius */ 0,
+ mActivityManager.getPackageImportance(packageName));
+ }
if (isThrottlingExemptLocked(callerIdentity)
|| isImportanceForeground(
mActivityManager.getPackageImportance(packageName))) {
@@ -2941,6 +3001,26 @@ public class LocationManagerService extends ILocationManager.Stub {
if (linkedListener == null) {
return;
}
+ long identity = Binder.clearCallingIdentity();
+ try {
+ if (gnssDataProvider == mGnssNavigationMessageProvider
+ || gnssDataProvider == mGnssStatusProvider) {
+ mLocationUsageLogger.logLocationApiUsage(
+ LocationStatsEnums.USAGE_ENDED,
+ gnssDataProvider == mGnssNavigationMessageProvider
+ ? LocationStatsEnums.API_ADD_GNSS_MEASUREMENTS_LISTENER
+ : LocationStatsEnums.API_REGISTER_GNSS_STATUS_CALLBACK,
+ linkedListener.mCallerIdentity.mPackageName,
+ /* LocationRequest= */ null,
+ /* hasListener= */ true,
+ /* hasIntent= */ false,
+ /* radius= */ 0,
+ mActivityManager.getPackageImportance(
+ linkedListener.mCallerIdentity.mPackageName));
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
unlinkFromListenerDeathNotificationLocked(binder, linkedListener);
gnssDataProvider.removeListener(listener);
}
@@ -3026,6 +3106,11 @@ public class LocationManagerService extends ILocationManager.Stub {
checkResolutionLevelIsSufficientForProviderUseLocked(getCallerAllowedResolutionLevel(),
providerName);
+ mLocationUsageLogger.logLocationApiUsage(
+ LocationStatsEnums.USAGE_STARTED,
+ LocationStatsEnums.API_SEND_EXTRA_COMMAND,
+ providerName);
+
// and check for ACCESS_LOCATION_EXTRA_COMMANDS
if ((mContext.checkCallingOrSelfPermission(ACCESS_LOCATION_EXTRA_COMMANDS)
!= PERMISSION_GRANTED)) {
@@ -3037,6 +3122,11 @@ public class LocationManagerService extends ILocationManager.Stub {
provider.sendExtraCommandLocked(command, extras);
}
+ mLocationUsageLogger.logLocationApiUsage(
+ LocationStatsEnums.USAGE_ENDED,
+ LocationStatsEnums.API_SEND_EXTRA_COMMAND,
+ providerName);
+
return true;
}
}
diff --git a/services/core/java/com/android/server/LocationUsageLogger.java b/services/core/java/com/android/server/LocationUsageLogger.java
new file mode 100644
index 000000000000..c5030351f69d
--- /dev/null
+++ b/services/core/java/com/android/server/LocationUsageLogger.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import android.app.ActivityManager;
+import android.location.LocationManager;
+import android.location.LocationRequest;
+import android.os.SystemClock;
+import android.stats.location.LocationStatsEnums;
+import android.util.Log;
+import android.util.StatsLog;
+
+import java.time.Instant;
+
+/**
+ * Logger for Location API usage logging.
+ */
+class LocationUsageLogger {
+ private static final String TAG = "LocationUsageLogger";
+ private static final boolean D = Log.isLoggable(TAG, Log.DEBUG);
+
+ private static final int ONE_SEC_IN_MILLIS = 1000;
+ private static final int ONE_MINUTE_IN_MILLIS = 60000;
+ private static final int ONE_HOUR_IN_MILLIS = 3600000;
+
+ private long mLastApiUsageLogHour = 0;
+
+ private int mApiUsageLogHourlyCount = 0;
+
+ private static final int API_USAGE_LOG_HOURLY_CAP = 60;
+
+ private static int providerNameToStatsdEnum(String provider) {
+ if (LocationManager.NETWORK_PROVIDER.equals(provider)) {
+ return LocationStatsEnums.PROVIDER_NETWORK;
+ } else if (LocationManager.GPS_PROVIDER.equals(provider)) {
+ return LocationStatsEnums.PROVIDER_GPS;
+ } else if (LocationManager.PASSIVE_PROVIDER.equals(provider)) {
+ return LocationStatsEnums.PROVIDER_PASSIVE;
+ } else if (LocationManager.FUSED_PROVIDER.equals(provider)) {
+ return LocationStatsEnums.PROVIDER_FUSED;
+ } else {
+ return LocationStatsEnums.PROVIDER_UNKNOWN;
+ }
+ }
+
+ private static int bucketizeIntervalToStatsdEnum(long interval) {
+ // LocationManager already converts negative values to 0.
+ if (interval < ONE_SEC_IN_MILLIS) {
+ return LocationStatsEnums.INTERVAL_BETWEEN_0_SEC_AND_1_SEC;
+ } else if (interval < ONE_SEC_IN_MILLIS * 5) {
+ return LocationStatsEnums.INTERVAL_BETWEEN_1_SEC_AND_5_SEC;
+ } else if (interval < ONE_MINUTE_IN_MILLIS) {
+ return LocationStatsEnums.INTERVAL_BETWEEN_5_SEC_AND_1_MIN;
+ } else if (interval < ONE_MINUTE_IN_MILLIS * 10) {
+ return LocationStatsEnums.INTERVAL_BETWEEN_1_MIN_AND_10_MIN;
+ } else if (interval < ONE_HOUR_IN_MILLIS) {
+ return LocationStatsEnums.INTERVAL_BETWEEN_10_MIN_AND_1_HOUR;
+ } else {
+ return LocationStatsEnums.INTERVAL_LARGER_THAN_1_HOUR;
+ }
+ }
+
+ private static int bucketizeSmallestDisplacementToStatsdEnum(float smallestDisplacement) {
+ // LocationManager already converts negative values to 0.
+ if (smallestDisplacement == 0) {
+ return LocationStatsEnums.DISTANCE_ZERO;
+ } else if (smallestDisplacement > 0 && smallestDisplacement <= 100) {
+ return LocationStatsEnums.DISTANCE_BETWEEN_0_AND_100;
+ } else {
+ return LocationStatsEnums.DISTANCE_LARGER_THAN_100;
+ }
+ }
+
+ private static int bucketizeRadiusToStatsdEnum(float radius) {
+ if (radius < 0) {
+ return LocationStatsEnums.RADIUS_NEGATIVE;
+ } else if (radius < 100) {
+ return LocationStatsEnums.RADIUS_BETWEEN_0_AND_100;
+ } else if (radius < 200) {
+ return LocationStatsEnums.RADIUS_BETWEEN_100_AND_200;
+ } else if (radius < 300) {
+ return LocationStatsEnums.RADIUS_BETWEEN_200_AND_300;
+ } else if (radius < 1000) {
+ return LocationStatsEnums.RADIUS_BETWEEN_300_AND_1000;
+ } else if (radius < 10000) {
+ return LocationStatsEnums.RADIUS_BETWEEN_1000_AND_10000;
+ } else {
+ return LocationStatsEnums.RADIUS_LARGER_THAN_100000;
+ }
+ }
+
+ private static int getBucketizedExpireIn(long expireAt) {
+ if (expireAt == Long.MAX_VALUE) {
+ return LocationStatsEnums.EXPIRATION_NO_EXPIRY;
+ }
+
+ long elapsedRealtime = SystemClock.elapsedRealtime();
+ long expireIn = Math.max(0, expireAt - elapsedRealtime);
+
+ if (expireIn < 20 * ONE_SEC_IN_MILLIS) {
+ return LocationStatsEnums.EXPIRATION_BETWEEN_0_AND_20_SEC;
+ } else if (expireIn < ONE_MINUTE_IN_MILLIS) {
+ return LocationStatsEnums.EXPIRATION_BETWEEN_20_SEC_AND_1_MIN;
+ } else if (expireIn < ONE_MINUTE_IN_MILLIS * 10) {
+ return LocationStatsEnums.EXPIRATION_BETWEEN_1_MIN_AND_10_MIN;
+ } else if (expireIn < ONE_HOUR_IN_MILLIS) {
+ return LocationStatsEnums.EXPIRATION_BETWEEN_10_MIN_AND_1_HOUR;
+ } else {
+ return LocationStatsEnums.EXPIRATION_LARGER_THAN_1_HOUR;
+ }
+ }
+
+ private static int categorizeActivityImportance(int importance) {
+ if (importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
+ return LocationStatsEnums.IMPORTANCE_TOP;
+ } else if (importance == ActivityManager
+ .RunningAppProcessInfo
+ .IMPORTANCE_FOREGROUND_SERVICE) {
+ return LocationStatsEnums.IMPORTANCE_FORGROUND_SERVICE;
+ } else {
+ return LocationStatsEnums.IMPORTANCE_BACKGROUND;
+ }
+ }
+
+ private static int getCallbackType(
+ int apiType, boolean hasListener, boolean hasIntent) {
+ if (apiType == LocationStatsEnums.API_SEND_EXTRA_COMMAND) {
+ return LocationStatsEnums.CALLBACK_NOT_APPLICABLE;
+ }
+
+ // Listener and PendingIntent will not be set at
+ // the same time.
+ if (hasIntent) {
+ return LocationStatsEnums.CALLBACK_PENDING_INTENT;
+ } else if (hasListener) {
+ return LocationStatsEnums.CALLBACK_LISTENER;
+ } else {
+ return LocationStatsEnums.CALLBACK_UNKNOWN;
+ }
+ }
+
+ // Update the hourly count of APIUsage log event.
+ // Returns false if hit the hourly log cap.
+ private boolean checkApiUsageLogCap() {
+ if (D) {
+ Log.d(TAG, "checking APIUsage log cap.");
+ }
+
+ long currentHour = Instant.now().toEpochMilli() / ONE_HOUR_IN_MILLIS;
+ if (currentHour > mLastApiUsageLogHour) {
+ mLastApiUsageLogHour = currentHour;
+ mApiUsageLogHourlyCount = 0;
+ return true;
+ } else {
+ mApiUsageLogHourlyCount = Math.min(
+ mApiUsageLogHourlyCount + 1, API_USAGE_LOG_HOURLY_CAP);
+ return mApiUsageLogHourlyCount < API_USAGE_LOG_HOURLY_CAP;
+ }
+ }
+
+ /**
+ * Log a Location API usage event to Statsd.
+ * Logging event is capped at 60 per hour. Usage events exceeding
+ * the cap will be dropped by LocationUsageLogger.
+ */
+ public void logLocationApiUsage(int usageType, int apiInUse,
+ String packageName, LocationRequest locationRequest,
+ boolean hasListener, boolean hasIntent,
+ float radius, int activityImportance) {
+ try {
+ if (!checkApiUsageLogCap()) {
+ return;
+ }
+
+ boolean isLocationRequestNull = locationRequest == null;
+ if (D) {
+ Log.d(TAG, "log API Usage to statsd. usageType: " + usageType + ", apiInUse: "
+ + apiInUse + ", packageName: " + (packageName == null ? "" : packageName)
+ + ", locationRequest: "
+ + (isLocationRequestNull ? "" : locationRequest.toString())
+ + ", hasListener: " + hasListener
+ + ", hasIntent: " + hasIntent
+ + ", radius: " + radius
+ + ", importance: " + activityImportance);
+ }
+
+ StatsLog.write(StatsLog.LOCATION_MANAGER_API_USAGE_REPORTED, usageType,
+ apiInUse, packageName,
+ isLocationRequestNull
+ ? LocationStatsEnums.PROVIDER_UNKNOWN
+ : providerNameToStatsdEnum(locationRequest.getProvider()),
+ isLocationRequestNull
+ ? LocationStatsEnums.QUALITY_UNKNOWN
+ : locationRequest.getQuality(),
+ isLocationRequestNull
+ ? LocationStatsEnums.INTERVAL_UNKNOWN
+ : bucketizeIntervalToStatsdEnum(locationRequest.getInterval()),
+ isLocationRequestNull
+ ? LocationStatsEnums.DISTANCE_UNKNOWN
+ : bucketizeSmallestDisplacementToStatsdEnum(
+ locationRequest.getSmallestDisplacement()),
+ isLocationRequestNull ? 0 : locationRequest.getNumUpdates(),
+ // only log expireIn for USAGE_STARTED
+ isLocationRequestNull || usageType == LocationStatsEnums.USAGE_ENDED
+ ? LocationStatsEnums.EXPIRATION_UNKNOWN
+ : getBucketizedExpireIn(locationRequest.getExpireAt()),
+ getCallbackType(apiInUse, hasListener, hasIntent),
+ bucketizeRadiusToStatsdEnum(radius),
+ categorizeActivityImportance(activityImportance));
+ } catch (Exception e) {
+ // Swallow exceptions to avoid crashing LMS.
+ Log.w(TAG, "Failed to log API usage to statsd.", e);
+ }
+ }
+
+ /**
+ * Log a Location API usage event to Statsd.
+ * Logging event is capped at 60 per hour. Usage events exceeding
+ * the cap will be dropped by LocationUsageLogger.
+ */
+ public void logLocationApiUsage(int usageType, int apiInUse, String providerName) {
+ try {
+ if (!checkApiUsageLogCap()) {
+ return;
+ }
+
+ if (D) {
+ Log.d(TAG, "log API Usage to statsd. usageType: " + usageType + ", apiInUse: "
+ + apiInUse + ", providerName: " + providerName);
+ }
+
+ StatsLog.write(StatsLog.LOCATION_MANAGER_API_USAGE_REPORTED, usageType, apiInUse,
+ /* package_name= */ null,
+ providerNameToStatsdEnum(providerName),
+ LocationStatsEnums.QUALITY_UNKNOWN,
+ LocationStatsEnums.INTERVAL_UNKNOWN,
+ LocationStatsEnums.DISTANCE_UNKNOWN,
+ /* numUpdates= */ 0,
+ LocationStatsEnums.EXPIRATION_UNKNOWN,
+ getCallbackType(
+ apiInUse,
+ /* isListenerNull= */ true,
+ /* isIntentNull= */ true),
+ /* bucketizedRadius= */ 0,
+ LocationStatsEnums.IMPORTANCE_UNKNOWN);
+ } catch (Exception e) {
+ // Swallow exceptions to avoid crashing LMS.
+ Log.w(TAG, "Failed to log API usage to statsd.", e);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 32671144aee3..dee89e5d5c4d 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -25,6 +25,7 @@ import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
+import android.net.NetworkStackClient;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
@@ -115,6 +116,7 @@ public class PackageWatchdog {
// File containing the XML data of monitored packages /data/system/package-watchdog.xml
private final AtomicFile mPolicyFile;
private final ExplicitHealthCheckController mHealthCheckController;
+ private final NetworkStackClient mNetworkStackClient;
@GuardedBy("mLock")
private boolean mIsPackagesReady;
// Flag to control whether explicit health checks are supported or not
@@ -135,7 +137,8 @@ public class PackageWatchdog {
new File(new File(Environment.getDataDirectory(), "system"),
"package-watchdog.xml")),
new Handler(Looper.myLooper()), BackgroundThread.getHandler(),
- new ExplicitHealthCheckController(context));
+ new ExplicitHealthCheckController(context),
+ NetworkStackClient.getInstance());
}
/**
@@ -143,12 +146,14 @@ public class PackageWatchdog {
*/
@VisibleForTesting
PackageWatchdog(Context context, AtomicFile policyFile, Handler shortTaskHandler,
- Handler longTaskHandler, ExplicitHealthCheckController controller) {
+ Handler longTaskHandler, ExplicitHealthCheckController controller,
+ NetworkStackClient networkStackClient) {
mContext = context;
mPolicyFile = policyFile;
mShortTaskHandler = shortTaskHandler;
mLongTaskHandler = longTaskHandler;
mHealthCheckController = controller;
+ mNetworkStackClient = networkStackClient;
loadFromFile();
}
@@ -174,6 +179,7 @@ public class PackageWatchdog {
() -> syncRequestsAsync());
setPropertyChangedListenerLocked();
updateConfigs();
+ registerNetworkStackHealthListener();
}
}
@@ -630,29 +636,40 @@ public class PackageWatchdog {
synchronized (mLock) {
PackageHealthObserver registeredObserver = observer.mRegisteredObserver;
if (registeredObserver != null) {
- PackageManager pm = mContext.getPackageManager();
Iterator<MonitoredPackage> it = failedPackages.iterator();
while (it.hasNext()) {
String failedPackage = it.next().getName();
- long versionCode = 0;
Slog.i(TAG, "Explicit health check failed for package " + failedPackage);
- try {
- versionCode = pm.getPackageInfo(
- failedPackage, 0 /* flags */).getLongVersionCode();
- } catch (PackageManager.NameNotFoundException e) {
+ VersionedPackage versionedPkg = getVersionedPackage(failedPackage);
+ if (versionedPkg == null) {
Slog.w(TAG, "Explicit health check failed but could not find package "
+ failedPackage);
// TODO(b/120598832): Skip. We only continue to pass tests for now since
// the tests don't install any packages
+ versionedPkg = new VersionedPackage(failedPackage, 0L);
}
- registeredObserver.execute(
- new VersionedPackage(failedPackage, versionCode));
+ registeredObserver.execute(versionedPkg);
}
}
}
});
}
+ @Nullable
+ private VersionedPackage getVersionedPackage(String packageName) {
+ final PackageManager pm = mContext.getPackageManager();
+ if (pm == null) {
+ return null;
+ }
+ try {
+ final long versionCode = pm.getPackageInfo(
+ packageName, 0 /* flags */).getLongVersionCode();
+ return new VersionedPackage(packageName, versionCode);
+ } catch (PackageManager.NameNotFoundException e) {
+ return null;
+ }
+ }
+
/**
* Loads mAllObservers from file.
*
@@ -726,6 +743,27 @@ public class PackageWatchdog {
}
}
+ private void registerNetworkStackHealthListener() {
+ // TODO: have an internal method to trigger a rollback by reporting high severity errors,
+ // and rely on ActivityManager to inform the watchdog of severe network stack crashes
+ // instead of having this listener in parallel.
+ mNetworkStackClient.registerHealthListener(
+ packageName -> {
+ final VersionedPackage pkg = getVersionedPackage(packageName);
+ if (pkg == null) {
+ Slog.wtf(TAG, "NetworkStack failed but could not find its package");
+ return;
+ }
+ // This is a severe failure and recovery should be attempted immediately.
+ // TODO: have a better way to handle such failures.
+ final List<VersionedPackage> pkgList = Collections.singletonList(pkg);
+ final long failureCount = getTriggerFailureCount();
+ for (int i = 0; i < failureCount; i++) {
+ onPackageFailure(pkgList);
+ }
+ });
+ }
+
/**
* Persists mAllObservers to file. Threshold information is ignored.
*/
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index bbbec665020b..d2b992bad462 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -2842,8 +2842,9 @@ class StorageManagerService extends IStorageManager.Stub
}
}
+ /** Not thread safe */
class AppFuseMountScope extends AppFuseBridge.MountScope {
- boolean opened = false;
+ private boolean mMounted = false;
public AppFuseMountScope(int uid, int mountId) {
super(uid, mountId);
@@ -2852,8 +2853,9 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public ParcelFileDescriptor open() throws NativeDaemonConnectorException {
try {
- return new ParcelFileDescriptor(
- mVold.mountAppFuse(uid, mountId));
+ final FileDescriptor fd = mVold.mountAppFuse(uid, mountId);
+ mMounted = true;
+ return new ParcelFileDescriptor(fd);
} catch (Exception e) {
throw new NativeDaemonConnectorException("Failed to mount", e);
}
@@ -2872,9 +2874,9 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public void close() throws Exception {
- if (opened) {
+ if (mMounted) {
mVold.unmountAppFuse(uid, mountId);
- opened = false;
+ mMounted = false;
}
}
}
@@ -3582,6 +3584,10 @@ class StorageManagerService extends IStorageManager.Stub
}
final String[] packagesForUid = mIPackageManager.getPackagesForUid(uid);
+ if (ArrayUtils.isEmpty(packagesForUid)) {
+ // It's possible the package got uninstalled already, so just ignore.
+ return Zygote.MOUNT_EXTERNAL_NONE;
+ }
if (packageName == null) {
packageName = packagesForUid[0];
}
diff --git a/services/core/java/com/android/server/adb/AdbDebuggingManager.java b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
index bdbff3db943d..4b48ef917744 100644
--- a/services/core/java/com/android/server/adb/AdbDebuggingManager.java
+++ b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
@@ -661,12 +661,6 @@ public class AdbDebuggingManager {
return mTestUserKeyFile == null ? getAdbFile(ADB_KEYS_FILE) : mTestUserKeyFile;
}
- private void createKeyFile(File keyFile) throws IOException {
- keyFile.createNewFile();
- FileUtils.setPermissions(keyFile.toString(),
- FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP, -1, -1);
- }
-
private void writeKey(String key) {
try {
File keyFile = getUserKeyFile();
@@ -675,14 +669,13 @@ public class AdbDebuggingManager {
return;
}
- if (!keyFile.exists()) {
- createKeyFile(keyFile);
- }
-
FileOutputStream fo = new FileOutputStream(keyFile, true);
fo.write(key.getBytes());
fo.write('\n');
fo.close();
+
+ FileUtils.setPermissions(keyFile.toString(),
+ FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP, -1, -1);
} catch (IOException ex) {
Slog.e(TAG, "Error writing key:" + ex);
}
@@ -698,10 +691,6 @@ public class AdbDebuggingManager {
return;
}
- if (!keyFile.exists()) {
- createKeyFile(keyFile);
- }
-
atomicKeyFile = new AtomicFile(keyFile);
fo = atomicKeyFile.startWrite();
for (String key : keys) {
@@ -709,6 +698,9 @@ public class AdbDebuggingManager {
fo.write('\n');
}
atomicKeyFile.finishWrite(fo);
+
+ FileUtils.setPermissions(keyFile.toString(),
+ FileUtils.S_IRUSR | FileUtils.S_IWUSR | FileUtils.S_IRGRP, -1, -1);
} catch (IOException ex) {
Slog.e(TAG, "Error writing keys: " + ex);
if (atomicKeyFile != null) {
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 90266f12a5dd..fae853c52c01 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -3250,6 +3250,7 @@ public final class ActiveServices {
int memFactor = mAm.mProcessStats.getMemFactorLocked();
long now = SystemClock.uptimeMillis();
r.tracker.setExecuting(false, memFactor, now);
+ r.tracker.setForeground(false, memFactor, now);
r.tracker.setBound(false, memFactor, now);
r.tracker.setStarted(false, memFactor, now);
}
@@ -3293,8 +3294,10 @@ public final class ActiveServices {
}
r.executeFg = false;
if (r.tracker != null) {
- r.tracker.setExecuting(false, mAm.mProcessStats.getMemFactorLocked(),
- SystemClock.uptimeMillis());
+ final int memFactor = mAm.mProcessStats.getMemFactorLocked();
+ final long now = SystemClock.uptimeMillis();
+ r.tracker.setExecuting(false, memFactor, now);
+ r.tracker.setForeground(false, memFactor, now);
if (finishing) {
r.tracker.clearCurrentOwner(r, false);
r.tracker = null;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 0619eb95dec7..2321031e30d8 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -18156,13 +18156,20 @@ public class ActivityManagerService extends IActivityManager.Stub
}
}
+ // The arguments here are untyped because the base ActivityManagerInternal class
+ // doesn't have compile-time visiblity into ActivityServiceConnectionHolder or
+ // ConnectionRecord.
@Override
- public void disconnectActivityFromServices(Object connectionHolder) {
+ public void disconnectActivityFromServices(Object connectionHolder, Object conns) {
+ // 'connectionHolder' is an untyped ActivityServiceConnectionsHolder
+ // 'conns' is an untyped HashSet<ConnectionRecord>
+ final ActivityServiceConnectionsHolder holder =
+ (ActivityServiceConnectionsHolder) connectionHolder;
+ final HashSet<ConnectionRecord> toDisconnect = (HashSet<ConnectionRecord>) conns;
synchronized(ActivityManagerService.this) {
- final ActivityServiceConnectionsHolder c =
- (ActivityServiceConnectionsHolder) connectionHolder;
- c.forEachConnection(cr -> mServices.removeConnectionLocked(
- (ConnectionRecord) cr, null, c));
+ for (ConnectionRecord cr : toDisconnect) {
+ mServices.removeConnectionLocked(cr, null, holder);
+ }
}
}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index a0522e3971e7..884ecbaac058 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -241,15 +241,6 @@ import com.android.internal.annotations.GuardedBy;
sendLMsgNoDelay(MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT, SENDMSG_QUEUE, info);
}
- /*package*/ void postBluetoothA2dpDeviceConfigChangeExt(
- @NonNull BluetoothDevice device,
- @AudioService.BtProfileConnectionState int state, int profile,
- boolean suppressNoisyIntent, int a2dpVolume) {
- final BtDeviceConnectionInfo info = new BtDeviceConnectionInfo(device, state, profile,
- suppressNoisyIntent, a2dpVolume);
- sendLMsgNoDelay(MSG_L_A2DP_ACTIVE_DEVICE_CHANGE_EXT, SENDMSG_QUEUE, info);
- }
-
private static final class HearingAidDeviceConnectionInfo {
final @NonNull BluetoothDevice mDevice;
final @AudioService.BtProfileConnectionState int mState;
@@ -578,9 +569,8 @@ import com.android.internal.annotations.GuardedBy;
return mBrokerHandler.hasMessages(MSG_IL_BTA2DP_DOCK_TIMEOUT);
}
- //###
// must be called synchronized on mConnectedDevices
- /*package*/ boolean hasScheduledA2dpSinkConnectionState(BluetoothDevice btDevice) {
+ /*package*/ boolean hasScheduledA2dpSinkConnectionState(BluetoothDevice btDevice) {
return mBrokerHandler.hasMessages(MSG_IL_SET_A2DP_SINK_CONNECTION_STATE,
new BtHelper.BluetoothA2dpDeviceInfo(btDevice));
}
@@ -862,22 +852,6 @@ import com.android.internal.annotations.GuardedBy;
info.mDevice, info.mState, info.mSupprNoisy, info.mMusicDevice);
}
} break;
- case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE_EXT: {
- final BtDeviceConnectionInfo info = (BtDeviceConnectionInfo) msg.obj;
- AudioService.sDeviceLogger.log((new AudioEventLogger.StringEvent(
- "handleBluetoothA2dpActiveDeviceChangeExt "
- + " state=" + info.mState
- // only querying address as this is the only readily available
- // field on the device
- + " addr=" + info.mDevice.getAddress()
- + " prof=" + info.mProfile + " supprNoisy=" + info.mSupprNoisy
- + " vol=" + info.mVolume)).printLog(TAG));
- synchronized (mDeviceStateLock) {
- mDeviceInventory.handleBluetoothA2dpActiveDeviceChangeExt(
- info.mDevice, info.mState, info.mProfile,
- info.mSupprNoisy, info.mVolume);
- }
- } break;
default:
Log.wtf(TAG, "Invalid message " + msg.what);
}
@@ -925,10 +899,8 @@ import com.android.internal.annotations.GuardedBy;
private static final int MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT = 27;
// process external command to (dis)connect a hearing aid device
private static final int MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT = 28;
- // process external command to (dis)connect or change active A2DP device
- private static final int MSG_L_A2DP_ACTIVE_DEVICE_CHANGE_EXT = 29;
// a ScoClient died in BtHelper
- private static final int MSG_L_SCOCLIENT_DIED = 30;
+ private static final int MSG_L_SCOCLIENT_DIED = 29;
private static boolean isMessageHandledUnderWakelock(int msgId) {
@@ -943,7 +915,6 @@ import com.android.internal.annotations.GuardedBy;
case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE:
case MSG_L_A2DP_DEVICE_CONNECTION_CHANGE_EXT:
case MSG_L_HEARING_AID_DEVICE_CONNECTION_CHANGE_EXT:
- case MSG_L_A2DP_ACTIVE_DEVICE_CHANGE_EXT:
return true;
default:
return false;
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 887c90873bdd..a9a8ef2f7e12 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -146,6 +146,7 @@ public final class AudioDeviceInventory {
}
}
+ @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ void onSetA2dpSinkConnectionState(@NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo,
@AudioService.BtProfileConnectionState int state) {
final BluetoothDevice btDevice = btInfo.getBtDevice();
@@ -259,6 +260,7 @@ public final class AudioDeviceInventory {
}
}
+ @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ void onBluetoothA2dpActiveDeviceChange(
@NonNull BtHelper.BluetoothA2dpDeviceInfo btInfo, int event) {
final BluetoothDevice btDevice = btInfo.getBtDevice();
@@ -532,6 +534,7 @@ public final class AudioDeviceInventory {
return mCurAudioRoutes;
}
+ @GuardedBy("AudioDeviceBroker.mDeviceStateLock")
/*package*/ void setBluetoothA2dpDeviceConnectionState(
@NonNull BluetoothDevice device, @AudioService.BtProfileConnectionState int state,
int profile, boolean suppressNoisyIntent, int musicDevice, int a2dpVolume) {
@@ -559,9 +562,13 @@ public final class AudioDeviceInventory {
final BtHelper.BluetoothA2dpDeviceInfo a2dpDeviceInfo =
new BtHelper.BluetoothA2dpDeviceInfo(device, a2dpVolume, a2dpCodec);
if (profile == BluetoothProfile.A2DP) {
- mDeviceBroker.postA2dpSinkConnection(state,
- a2dpDeviceInfo,
- delay);
+ if (delay == 0) {
+ onSetA2dpSinkConnectionState(a2dpDeviceInfo, state);
+ } else {
+ mDeviceBroker.postA2dpSinkConnection(state,
+ a2dpDeviceInfo,
+ delay);
+ }
} else { //profile == BluetoothProfile.A2DP_SINK
mDeviceBroker.postA2dpSourceConnection(state,
a2dpDeviceInfo,
@@ -570,49 +577,6 @@ public final class AudioDeviceInventory {
}
}
- /*package*/ void handleBluetoothA2dpActiveDeviceChangeExt(
- @NonNull BluetoothDevice device,
- @AudioService.BtProfileConnectionState int state, int profile,
- boolean suppressNoisyIntent, int a2dpVolume) {
- if (state == BluetoothProfile.STATE_DISCONNECTED) {
- mDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
- device, state, profile, suppressNoisyIntent, a2dpVolume);
- return;
- }
- // state == BluetoothProfile.STATE_CONNECTED
- synchronized (mConnectedDevices) {
- final String address = device.getAddress();
- final int a2dpCodec = mDeviceBroker.getA2dpCodec(device);
- final String deviceKey = DeviceInfo.makeDeviceListKey(
- AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address);
- DeviceInfo deviceInfo = mConnectedDevices.get(deviceKey);
- if (deviceInfo != null) {
- // Device config change for matching A2DP device
- mDeviceBroker.postBluetoothA2dpDeviceConfigChange(device);
- return;
- }
- for (int i = 0; i < mConnectedDevices.size(); i++) {
- deviceInfo = mConnectedDevices.valueAt(i);
- if (deviceInfo.mDeviceType != AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP) {
- continue;
- }
- // A2DP device exists, handle active device change
- final String existingDevicekey = mConnectedDevices.keyAt(i);
- mConnectedDevices.remove(existingDevicekey);
- mConnectedDevices.put(deviceKey, new DeviceInfo(
- AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, BtHelper.getName(device),
- address, a2dpCodec));
- mDeviceBroker.postA2dpActiveDeviceChange(
- new BtHelper.BluetoothA2dpDeviceInfo(
- device, a2dpVolume, a2dpCodec));
- return;
- }
- }
- // New A2DP device connection
- mDeviceBroker.postBluetoothA2dpDeviceConnectionStateSuppressNoisyIntent(
- device, state, profile, suppressNoisyIntent, a2dpVolume);
- }
-
/*package*/ int setWiredDeviceConnectionState(int type, @AudioService.ConnectionState int state,
String address, String name, String caller) {
synchronized (mConnectedDevices) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 15e8851a6a2b..376e9b58d493 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -1275,8 +1275,6 @@ public class AudioService extends IAudioService.Stub
System.VOLUME_SETTINGS_INT[a11yStreamAlias];
mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].setAllIndexes(
mStreamStates[a11yStreamAlias], caller);
- mStreamStates[AudioSystem.STREAM_ACCESSIBILITY].refreshRange(
- mStreamVolumeAlias[AudioSystem.STREAM_ACCESSIBILITY]);
}
}
if (sIndependentA11yVolume) {
@@ -1577,20 +1575,19 @@ public class AudioService extends IAudioService.Stub
}
private int rescaleIndex(int index, int srcStream, int dstStream) {
- int max = mStreamStates[srcStream].getMaxIndex();
- if (max == 0) {
- Log.e(TAG, "rescaleIndex : Max index should not be zero");
- return mStreamStates[srcStream].getMinIndex();
- }
- final int rescaled =
- (index * mStreamStates[dstStream].getMaxIndex()
- + mStreamStates[srcStream].getMaxIndex() / 2)
- / mStreamStates[srcStream].getMaxIndex();
- if (rescaled < mStreamStates[dstStream].getMinIndex()) {
+ int srcRange =
+ mStreamStates[srcStream].getMaxIndex() - mStreamStates[srcStream].getMinIndex();
+ int dstRange =
+ mStreamStates[dstStream].getMaxIndex() - mStreamStates[dstStream].getMinIndex();
+
+ if (srcRange == 0) {
+ Log.e(TAG, "rescaleIndex : index range should not be zero");
return mStreamStates[dstStream].getMinIndex();
- } else {
- return rescaled;
}
+
+ return mStreamStates[dstStream].getMinIndex()
+ + ((index - mStreamStates[srcStream].getMinIndex()) * dstRange + srcRange / 2)
+ / srcRange;
}
///////////////////////////////////////////////////////////////////////////
@@ -4382,27 +4379,6 @@ public class AudioService extends IAudioService.Stub
mDeviceBroker.postBluetoothA2dpDeviceConfigChange(device);
}
- /**
- * @see AudioManager#handleBluetoothA2dpActiveDeviceChange(BluetoothDevice, int, int,
- * boolean, int)
- */
- public void handleBluetoothA2dpActiveDeviceChange(
- BluetoothDevice device, int state, int profile, boolean suppressNoisyIntent,
- int a2dpVolume) {
- if (device == null) {
- throw new IllegalArgumentException("Illegal null device");
- }
- if (profile != BluetoothProfile.A2DP && profile != BluetoothProfile.A2DP_SINK) {
- throw new IllegalArgumentException("invalid profile " + profile);
- }
- if (state != BluetoothProfile.STATE_CONNECTED
- && state != BluetoothProfile.STATE_DISCONNECTED) {
- throw new IllegalArgumentException("Invalid state " + state);
- }
- mDeviceBroker.postBluetoothA2dpDeviceConfigChangeExt(device, state, profile,
- suppressNoisyIntent, a2dpVolume);
- }
-
private static final int DEVICE_MEDIA_UNMUTED_ON_PLUG =
AudioSystem.DEVICE_OUT_WIRED_HEADSET | AudioSystem.DEVICE_OUT_WIRED_HEADPHONE |
AudioSystem.DEVICE_OUT_LINE |
@@ -4751,24 +4727,6 @@ public class AudioService extends IAudioService.Stub
}
/**
- * Updates the min/max index values from another stream. Use this when changing the alias
- * for the current stream type.
- * @param sourceStreamType
- */
- // must be sync'd on mSettingsLock before VolumeStreamState.class
- @GuardedBy("VolumeStreamState.class")
- public void refreshRange(int sourceStreamType) {
- mIndexMin = MIN_STREAM_VOLUME[sourceStreamType] * 10;
- mIndexMax = MAX_STREAM_VOLUME[sourceStreamType] * 10;
- // verify all current volumes are within bounds
- for (int i = 0 ; i < mIndexMap.size(); i++) {
- final int device = mIndexMap.keyAt(i);
- final int index = mIndexMap.valueAt(i);
- mIndexMap.put(device, getValidIndex(index));
- }
- }
-
- /**
* Copies all device/index pairs from the given VolumeStreamState after initializing
* them with the volume for DEVICE_OUT_DEFAULT. No-op if the source VolumeStreamState
* has the same stream type as this instance.
@@ -5529,6 +5487,8 @@ public class AudioService extends IAudioService.Stub
public void avrcpSupportsAbsoluteVolume(String address, boolean support) {
// address is not used for now, but may be used when multiple a2dp devices are supported
+ sVolumeLogger.log(new AudioEventLogger.StringEvent("avrcpSupportsAbsoluteVolume addr="
+ + address + " support=" + support));
mDeviceBroker.setAvrcpAbsoluteVolumeSupported(support);
sendMsg(mAudioHandler, MSG_SET_DEVICE_VOLUME, SENDMSG_QUEUE,
AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, 0,
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 934c7bfe3392..1a63f8f51ee3 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -200,16 +200,20 @@ public class BtHelper {
/*package*/ synchronized void setAvrcpAbsoluteVolumeSupported(boolean supported) {
mAvrcpAbsVolSupported = supported;
+ Log.i(TAG, "setAvrcpAbsoluteVolumeSupported supported=" + supported);
}
/*package*/ synchronized void setAvrcpAbsoluteVolumeIndex(int index) {
if (mA2dp == null) {
if (AudioService.DEBUG_VOL) {
- Log.d(TAG, "setAvrcpAbsoluteVolumeIndex: bailing due to null mA2dp");
+ AudioService.sVolumeLogger.log(new AudioEventLogger.StringEvent(
+ "setAvrcpAbsoluteVolumeIndex: bailing due to null mA2dp").printLog(TAG));
return;
}
}
if (!mAvrcpAbsVolSupported) {
+ AudioService.sVolumeLogger.log(new AudioEventLogger.StringEvent(
+ "setAvrcpAbsoluteVolumeIndex: abs vol not supported ").printLog(TAG));
return;
}
if (AudioService.DEBUG_VOL) {
diff --git a/services/core/java/com/android/server/clipboard/ClipboardService.java b/services/core/java/com/android/server/clipboard/ClipboardService.java
index af25ad56a2a7..b279b370c611 100644
--- a/services/core/java/com/android/server/clipboard/ClipboardService.java
+++ b/services/core/java/com/android/server/clipboard/ClipboardService.java
@@ -775,8 +775,7 @@ public class ClipboardService extends SystemService {
// if the application has the permission, let it to access user's clipboard.
// To passed synthesized uid user#10_app#systemui may not tell the real uid.
// userId must pass intending userId. i.e. user#10.
- allowed = mContentCaptureInternal.isContentCaptureServiceForUser(
- Binder.getCallingUid(), userId);
+ allowed = mContentCaptureInternal.isContentCaptureServiceForUser(uid, userId);
}
if (!allowed && mAutofillInternal != null) {
// ...or the Augmented Autofill Service
@@ -785,8 +784,7 @@ public class ClipboardService extends SystemService {
// if the application has the permission, let it to access user's clipboard.
// To passed synthesized uid user#10_app#systemui may not tell the real uid.
// userId must pass intending userId. i.e. user#10.
- allowed = mAutofillInternal.isAugmentedAutofillServiceForUser(
- Binder.getCallingUid(), userId);
+ allowed = mAutofillInternal.isAugmentedAutofillServiceForUser(uid, userId);
}
if (!allowed) {
Slog.e(TAG, "Denying clipboard access to " + callingPackage
diff --git a/services/core/java/com/android/server/connectivity/AutodestructReference.java b/services/core/java/com/android/server/connectivity/AutodestructReference.java
new file mode 100644
index 000000000000..009a43e58285
--- /dev/null
+++ b/services/core/java/com/android/server/connectivity/AutodestructReference.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.connectivity;
+
+import android.annotation.NonNull;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * A ref that autodestructs at the first usage of it.
+ * @param <T> The type of the held object
+ * @hide
+ */
+public class AutodestructReference<T> {
+ private final AtomicReference<T> mHeld;
+ public AutodestructReference(@NonNull T obj) {
+ if (null == obj) throw new NullPointerException("Autodestruct reference to null");
+ mHeld = new AtomicReference<>(obj);
+ }
+
+ /** Get the ref and destruct it. NPE if already destructed. */
+ @NonNull
+ public T getAndDestroy() {
+ final T obj = mHeld.getAndSet(null);
+ if (null == obj) throw new NullPointerException("Already autodestructed");
+ return obj;
+ }
+}
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 34772d062fd2..864a793b8f40 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -25,12 +25,12 @@ import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.NetworkMisc;
+import android.net.NetworkMonitorManager;
import android.net.NetworkRequest;
import android.net.NetworkState;
import android.os.Handler;
import android.os.INetworkManagementService;
import android.os.Messenger;
-import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;
import android.util.SparseArray;
@@ -247,7 +247,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
public final Nat464Xlat clatd;
// Set after asynchronous creation of the NetworkMonitor.
- private volatile INetworkMonitor mNetworkMonitor;
+ private volatile NetworkMonitorManager mNetworkMonitor;
private static final String TAG = ConnectivityService.class.getSimpleName();
private static final boolean VDBG = false;
@@ -278,7 +278,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
* Inform NetworkAgentInfo that a new NetworkMonitor was created.
*/
public void onNetworkMonitorCreated(INetworkMonitor networkMonitor) {
- mNetworkMonitor = networkMonitor;
+ mNetworkMonitor = new NetworkMonitorManager(networkMonitor);
}
/**
@@ -290,13 +290,9 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
*/
public void setNetworkCapabilities(NetworkCapabilities nc) {
networkCapabilities = nc;
- final INetworkMonitor nm = mNetworkMonitor;
+ final NetworkMonitorManager nm = mNetworkMonitor;
if (nm != null) {
- try {
- nm.notifyNetworkCapabilitiesChanged(nc);
- } catch (RemoteException e) {
- Log.e(TAG, "Error notifying NetworkMonitor of updated NetworkCapabilities", e);
- }
+ nm.notifyNetworkCapabilitiesChanged(nc);
}
}
@@ -317,11 +313,11 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
}
/**
- * Get the INetworkMonitor in this NetworkAgentInfo.
+ * Get the NetworkMonitorManager in this NetworkAgentInfo.
*
* <p>This will be null before {@link #onNetworkMonitorCreated(INetworkMonitor)} is called.
*/
- public INetworkMonitor networkMonitor() {
+ public NetworkMonitorManager networkMonitor() {
return mNetworkMonitor;
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
index 0910dac27337..f6735d983466 100644
--- a/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
+++ b/services/core/java/com/android/server/connectivity/NetworkNotificationManager.java
@@ -237,9 +237,15 @@ public class NetworkNotificationManager {
+ getTransportName(transportType));
return;
}
-
- final String channelId = highPriority ? SystemNotificationChannels.NETWORK_ALERTS :
- SystemNotificationChannels.NETWORK_STATUS;
+ // When replacing an existing notification for a given network, don't alert, just silently
+ // update the existing notification. Note that setOnlyAlertOnce() will only work for the
+ // same id, and the id used here is the NotificationType which is different in every type of
+ // notification. This is required because the notification metrics only track the ID but not
+ // the tag.
+ final boolean hasPreviousNotification = previousNotifyType != null;
+ final String channelId = (highPriority && !hasPreviousNotification)
+ ? SystemNotificationChannels.NETWORK_ALERTS
+ : SystemNotificationChannels.NETWORK_STATUS;
Notification.Builder builder = new Notification.Builder(mContext, channelId)
.setWhen(System.currentTimeMillis())
.setShowWhen(notifyType == NotificationType.NETWORK_SWITCH)
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 0271d3bcb57c..40a4820355ad 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -953,30 +953,21 @@ public class Vpn {
return false;
}
- LinkProperties lp = makeLinkProperties();
- final boolean hadInternetCapability = mNetworkCapabilities.hasCapability(
- NetworkCapabilities.NET_CAPABILITY_INTERNET);
- final boolean willHaveInternetCapability = providesRoutesToMostDestinations(lp);
- if (hadInternetCapability != willHaveInternetCapability) {
- // A seamless handover would have led to a change to INTERNET capability, which
- // is supposed to be immutable for a given network. In this case bail out and do not
- // perform handover.
- Log.i(TAG, "Handover not possible due to changes to INTERNET capability");
- return false;
- }
-
- agent.sendLinkProperties(lp);
+ agent.sendLinkProperties(makeLinkProperties());
return true;
}
private void agentConnect() {
LinkProperties lp = makeLinkProperties();
- if (providesRoutesToMostDestinations(lp)) {
- mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
- } else {
- mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
- }
+ // VPN either provide a default route (IPv4 or IPv6 or both), or they are a split tunnel
+ // that falls back to the default network, which by definition provides INTERNET (unless
+ // there is no default network, in which case none of this matters in any sense).
+ // Also, it guarantees that when a VPN applies to an app, the VPN will always be reported
+ // as the network by getDefaultNetwork and registerDefaultNetworkCallback. This in turn
+ // protects the invariant that apps calling CM#bindProcessToNetwork(getDefaultNetwork())
+ // the same as if they use the default network.
+ mNetworkCapabilities.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
mNetworkInfo.setDetailedState(DetailedState.CONNECTING, null, null);
@@ -1846,10 +1837,11 @@ public class Vpn {
if (!profile.searchDomains.isEmpty()) {
config.searchDomains = Arrays.asList(profile.searchDomains.split(" +"));
}
- startLegacyVpn(config, racoon, mtpd);
+ startLegacyVpn(config, racoon, mtpd, profile);
}
- private synchronized void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd) {
+ private synchronized void startLegacyVpn(VpnConfig config, String[] racoon, String[] mtpd,
+ VpnProfile profile) {
stopLegacyVpnPrivileged();
// Prepare for the new request.
@@ -1857,7 +1849,7 @@ public class Vpn {
updateState(DetailedState.CONNECTING, "startLegacyVpn");
// Start a new LegacyVpnRunner and we are done!
- mLegacyVpnRunner = new LegacyVpnRunner(config, racoon, mtpd);
+ mLegacyVpnRunner = new LegacyVpnRunner(config, racoon, mtpd, profile);
mLegacyVpnRunner.start();
}
@@ -1923,6 +1915,7 @@ public class Vpn {
private final String mOuterInterface;
private final AtomicInteger mOuterConnection =
new AtomicInteger(ConnectivityManager.TYPE_NONE);
+ private final VpnProfile mProfile;
private long mBringupStartTime = -1;
@@ -1949,7 +1942,7 @@ public class Vpn {
}
};
- public LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd) {
+ LegacyVpnRunner(VpnConfig config, String[] racoon, String[] mtpd, VpnProfile profile) {
super(TAG);
mConfig = config;
mDaemons = new String[] {"racoon", "mtpd"};
@@ -1965,6 +1958,8 @@ public class Vpn {
// registering
mOuterInterface = mConfig.interfaze;
+ mProfile = profile;
+
if (!TextUtils.isEmpty(mOuterInterface)) {
final ConnectivityManager cm = ConnectivityManager.from(mContext);
for (Network network : cm.getAllNetworks()) {
@@ -2177,7 +2172,7 @@ public class Vpn {
}
// Add a throw route for the VPN server endpoint, if one was specified.
- String endpoint = parameters[5];
+ String endpoint = parameters[5].isEmpty() ? mProfile.server : parameters[5];
if (!endpoint.isEmpty()) {
try {
InetAddress addr = InetAddress.parseNumericAddress(endpoint);
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 5fb67ddc1266..5804fc8ba72f 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -309,6 +309,13 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
private boolean mAppliedTemporaryAutoBrightnessAdjustment;
private boolean mAppliedBrightnessBoost;
+ // Reason for which the brightness was last changed. See {@link BrightnessReason} for more
+ // information.
+ // At the time of this writing, this value is changed within updatePowerState() only, which is
+ // limited to the thread used by DisplayControllerHandler.
+ private BrightnessReason mBrightnessReason = new BrightnessReason();
+ private BrightnessReason mBrightnessReasonTemp = new BrightnessReason();
+
// Brightness animation ramp rates in brightness units per second
private final int mBrightnessRampRateFast;
private final int mBrightnessRampRateSlow;
@@ -733,6 +740,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
final boolean mustNotify;
final int previousPolicy;
boolean mustInitialize = false;
+ int brightnessAdjustmentFlags = 0;
+ mBrightnessReasonTemp.set(null);
synchronized (mLock) {
mPendingUpdatePowerStateLocked = false;
@@ -786,6 +795,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
if (!mAllowAutoBrightnessWhileDozingConfig) {
brightness = mPowerRequest.dozeScreenBrightness;
+ mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE);
}
break;
case DisplayPowerRequest.POLICY_VR:
@@ -839,15 +849,18 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// Use zero brightness when screen is off.
if (state == Display.STATE_OFF) {
brightness = PowerManager.BRIGHTNESS_OFF;
+ mBrightnessReasonTemp.setReason(BrightnessReason.REASON_SCREEN_OFF);
}
// Always use the VR brightness when in the VR state.
if (state == Display.STATE_VR) {
brightness = mScreenBrightnessForVr;
+ mBrightnessReasonTemp.setReason(BrightnessReason.REASON_VR);
}
if (brightness < 0 && mPowerRequest.screenBrightnessOverride > 0) {
brightness = mPowerRequest.screenBrightnessOverride;
+ mBrightnessReasonTemp.setReason(BrightnessReason.REASON_OVERRIDE);
mAppliedScreenBrightnessOverride = true;
} else {
mAppliedScreenBrightnessOverride = false;
@@ -867,6 +880,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
if (mTemporaryScreenBrightness > 0) {
brightness = mTemporaryScreenBrightness;
mAppliedTemporaryBrightness = true;
+ mBrightnessReasonTemp.setReason(BrightnessReason.REASON_TEMPORARY);
} else {
mAppliedTemporaryBrightness = false;
}
@@ -880,9 +894,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
final float autoBrightnessAdjustment;
if (!Float.isNaN(mTemporaryAutoBrightnessAdjustment)) {
autoBrightnessAdjustment = mTemporaryAutoBrightnessAdjustment;
+ brightnessAdjustmentFlags = BrightnessReason.ADJUSTMENT_AUTO_TEMP;
mAppliedTemporaryAutoBrightnessAdjustment = true;
} else {
autoBrightnessAdjustment = mAutoBrightnessAdjustment;
+ brightnessAdjustmentFlags = BrightnessReason.ADJUSTMENT_AUTO;
mAppliedTemporaryAutoBrightnessAdjustment = false;
}
@@ -893,6 +909,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
if (mPowerRequest.boostScreenBrightness
&& brightness != PowerManager.BRIGHTNESS_OFF) {
brightness = PowerManager.BRIGHTNESS_ON;
+ mBrightnessReasonTemp.setReason(BrightnessReason.REASON_BOOST);
mAppliedBrightnessBoost = true;
} else {
mAppliedBrightnessBoost = false;
@@ -936,6 +953,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// it means in absolute terms.
putScreenBrightnessSetting(brightness);
mAppliedAutoBrightness = true;
+ mBrightnessReasonTemp.setReason(BrightnessReason.REASON_AUTOMATIC);
} else {
mAppliedAutoBrightness = false;
}
@@ -943,19 +961,25 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
// If the autobrightness controller has decided to change the adjustment value
// used, make sure that's reflected in settings.
putAutoBrightnessAdjustmentSetting(newAutoBrightnessAdjustment);
+ } else {
+ // Adjustment values resulted in no change
+ brightnessAdjustmentFlags = 0;
}
} else {
mAppliedAutoBrightness = false;
+ brightnessAdjustmentFlags = 0;
}
// Use default brightness when dozing unless overridden.
if (brightness < 0 && Display.isDozeState(state)) {
brightness = mScreenBrightnessDozeConfig;
+ mBrightnessReasonTemp.setReason(BrightnessReason.REASON_DOZE_DEFAULT);
}
// Apply manual brightness.
if (brightness < 0) {
brightness = clampScreenBrightness(mCurrentScreenBrightnessSetting);
+ mBrightnessReasonTemp.setReason(BrightnessReason.REASON_MANUAL);
}
// Apply dimming by at least some minimum amount when user activity
@@ -964,6 +988,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
if (brightness > mScreenBrightnessRangeMinimum) {
brightness = Math.max(Math.min(brightness - SCREEN_DIM_MINIMUM_REDUCTION,
mScreenBrightnessDimConfig), mScreenBrightnessRangeMinimum);
+ mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_DIMMED);
}
if (!mAppliedDimming) {
slowChange = false;
@@ -982,6 +1007,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
Math.min(mPowerRequest.screenLowPowerBrightnessFactor, 1);
final int lowPowerBrightness = (int) (brightness * brightnessFactor);
brightness = Math.max(lowPowerBrightness, mScreenBrightnessRangeMinimum);
+ mBrightnessReasonTemp.addModifier(BrightnessReason.MODIFIER_LOW_POWER);
}
if (!mAppliedLowPower) {
slowChange = false;
@@ -1047,6 +1073,14 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
+ // Log any changes to what is currently driving the brightness setting.
+ if (!mBrightnessReasonTemp.equals(mBrightnessReason) || brightnessAdjustmentFlags != 0) {
+ Slog.v(TAG, "Brightness [" + brightness + "] reason changing to: '"
+ + mBrightnessReasonTemp.toString(brightnessAdjustmentFlags)
+ + "', previous reason: '" + mBrightnessReason + "'.");
+ mBrightnessReason.set(mBrightnessReasonTemp);
+ }
+
// Update display white-balance.
if (mDisplayWhiteBalanceController != null) {
if (state == Display.STATE_ON && mDisplayWhiteBalanceSettings.isEnabled()) {
@@ -1737,6 +1771,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
pw.println(" mPendingScreenBrightnessSetting=" + mPendingScreenBrightnessSetting);
pw.println(" mTemporaryScreenBrightness=" + mTemporaryScreenBrightness);
pw.println(" mAutoBrightnessAdjustment=" + mAutoBrightnessAdjustment);
+ pw.println(" mBrightnessReason=" + mBrightnessReason);
pw.println(" mTemporaryAutoBrightnessAdjustment=" + mTemporaryAutoBrightnessAdjustment);
pw.println(" mPendingAutoBrightnessAdjustment=" + mPendingAutoBrightnessAdjustment);
pw.println(" mScreenBrightnessForVr=" + mScreenBrightnessForVr);
@@ -1956,4 +1991,121 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
sendUpdatePowerState();
}
}
+
+ /**
+ * Stores data about why the brightness was changed. Made up of one main
+ * {@code BrightnessReason.REASON_*} reason and various {@code BrightnessReason.MODIFIER_*}
+ * modifiers.
+ */
+ private final class BrightnessReason {
+ static final int REASON_UNKNOWN = 0;
+ static final int REASON_MANUAL = 1;
+ static final int REASON_DOZE = 2;
+ static final int REASON_DOZE_DEFAULT = 3;
+ static final int REASON_AUTOMATIC = 4;
+ static final int REASON_SCREEN_OFF = 5;
+ static final int REASON_VR = 6;
+ static final int REASON_OVERRIDE = 7;
+ static final int REASON_TEMPORARY = 8;
+ static final int REASON_BOOST = 9;
+ static final int REASON_MAX = REASON_BOOST;
+
+ static final int MODIFIER_DIMMED = 0x1;
+ static final int MODIFIER_LOW_POWER = 0x2;
+ static final int MODIFIER_MASK = 0x3;
+
+ // ADJUSTMENT_*
+ // These things can happen at any point, even if the main brightness reason doesn't
+ // fundamentally change, so they're not stored.
+
+ // Auto-brightness adjustment factor changed
+ static final int ADJUSTMENT_AUTO_TEMP = 0x1;
+ // Temporary adjustment to the auto-brightness adjustment factor.
+ static final int ADJUSTMENT_AUTO = 0x2;
+
+ // One of REASON_*
+ public int reason;
+ // Any number of MODIFIER_*
+ public int modifier;
+
+ public void set(BrightnessReason other) {
+ setReason(other == null ? REASON_UNKNOWN : other.reason);
+ setModifier(other == null ? 0 : other.modifier);
+ }
+
+ public void setReason(int reason) {
+ if (reason < REASON_UNKNOWN || reason > REASON_MAX) {
+ Slog.w(TAG, "brightness reason out of bounds: " + reason);
+ } else {
+ this.reason = reason;
+ }
+ }
+
+ public void setModifier(int modifier) {
+ if ((modifier & ~MODIFIER_MASK) != 0) {
+ Slog.w(TAG, "brightness modifier out of bounds: 0x"
+ + Integer.toHexString(modifier));
+ } else {
+ this.modifier = modifier;
+ }
+ }
+
+ public void addModifier(int modifier) {
+ setModifier(modifier | this.modifier);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || !(obj instanceof BrightnessReason)) {
+ return false;
+ }
+ BrightnessReason other = (BrightnessReason) obj;
+ return other.reason == reason && other.modifier == modifier;
+ }
+
+ @Override
+ public String toString() {
+ return toString(0);
+ }
+
+ public String toString(int adjustments) {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(reasonToString(reason));
+ sb.append(" [");
+ if ((adjustments & ADJUSTMENT_AUTO_TEMP) != 0) {
+ sb.append(" temp_adj");
+ }
+ if ((adjustments & ADJUSTMENT_AUTO) != 0) {
+ sb.append(" auto_adj");
+ }
+ if ((modifier & MODIFIER_LOW_POWER) != 0) {
+ sb.append(" low_pwr");
+ }
+ if ((modifier & MODIFIER_DIMMED) != 0) {
+ sb.append(" dim");
+ }
+ int strlen = sb.length();
+ if (sb.charAt(strlen - 1) == '[') {
+ sb.setLength(strlen - 2);
+ } else {
+ sb.append(" ]");
+ }
+ return sb.toString();
+ }
+
+ private String reasonToString(int reason) {
+ switch (reason) {
+ case REASON_MANUAL: return "manual";
+ case REASON_DOZE: return "doze";
+ case REASON_DOZE_DEFAULT: return "doze_default";
+ case REASON_AUTOMATIC: return "automatic";
+ case REASON_SCREEN_OFF: return "screen_off";
+ case REASON_VR: return "vr";
+ case REASON_OVERRIDE: return "override";
+ case REASON_TEMPORARY: return "temporary";
+ case REASON_BOOST: return "boost";
+ default: return Integer.toString(reason);
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java
index b2420b5b320e..64a9e0074cb1 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -394,7 +394,9 @@ public final class ColorDisplayService extends SystemService {
private void tearDown() {
Slog.d(TAG, "tearDown: currentUser=" + mCurrentUser);
- getContext().getContentResolver().unregisterContentObserver(mContentObserver);
+ if (mContentObserver != null) {
+ getContext().getContentResolver().unregisterContentObserver(mContentObserver);
+ }
if (mNightDisplayTintController.isAvailable(getContext())) {
if (mNightDisplayAutoMode != null) {
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index ea1c49daefb9..ab4ae9d521bd 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -1635,6 +1635,9 @@ public class JobSchedulerService extends com.android.server.SystemService
*/
private static final long PERIODIC_JOB_WINDOW_BUFFER = 30 * MINUTE_IN_MILLIS;
+ /** The maximum period a periodic job can have. Anything higher will be clamped down to this. */
+ public static final long MAX_ALLOWED_PERIOD_MS = 365 * 24 * 60 * 60 * 1000L;
+
/**
* Called after a periodic has executed so we can reschedule it. We take the last execution
* time of the job to be the time of completion (i.e. the time at which this function is
@@ -1652,11 +1655,21 @@ public class JobSchedulerService extends com.android.server.SystemService
JobStatus getRescheduleJobForPeriodic(JobStatus periodicToReschedule) {
final long elapsedNow = sElapsedRealtimeClock.millis();
final long newLatestRuntimeElapsed;
- final long period = periodicToReschedule.getJob().getIntervalMillis();
- final long latestRunTimeElapsed = periodicToReschedule.getOriginalLatestRunTimeElapsed();
- final long flex = periodicToReschedule.getJob().getFlexMillis();
+ // Make sure period is in the interval [min_possible_period, max_possible_period].
+ final long period = Math.max(JobInfo.getMinPeriodMillis(),
+ Math.min(MAX_ALLOWED_PERIOD_MS, periodicToReschedule.getJob().getIntervalMillis()));
+ // Make sure flex is in the interval [min_possible_flex, period].
+ final long flex = Math.max(JobInfo.getMinFlexMillis(),
+ Math.min(period, periodicToReschedule.getJob().getFlexMillis()));
long rescheduleBuffer = 0;
+ long olrte = periodicToReschedule.getOriginalLatestRunTimeElapsed();
+ if (olrte < 0 || olrte == JobStatus.NO_LATEST_RUNTIME) {
+ Slog.wtf(TAG, "Invalid periodic job original latest run time: " + olrte);
+ olrte = elapsedNow;
+ }
+ final long latestRunTimeElapsed = olrte;
+
final long diffMs = Math.abs(elapsedNow - latestRunTimeElapsed);
if (elapsedNow > latestRunTimeElapsed) {
// The job ran past its expected run window. Have it count towards the current window
@@ -1664,7 +1677,7 @@ public class JobSchedulerService extends com.android.server.SystemService
if (DEBUG) {
Slog.i(TAG, "Periodic job ran after its intended window.");
}
- int numSkippedWindows = (int) (diffMs / period) + 1; // +1 to include original window
+ long numSkippedWindows = (diffMs / period) + 1; // +1 to include original window
if (period != flex && diffMs > Math.min(PERIODIC_JOB_WINDOW_BUFFER,
(period - flex) / 2)) {
if (DEBUG) {
@@ -1684,6 +1697,16 @@ public class JobSchedulerService extends com.android.server.SystemService
}
}
+ if (newLatestRuntimeElapsed < elapsedNow) {
+ Slog.wtf(TAG, "Rescheduling calculated latest runtime in the past: "
+ + newLatestRuntimeElapsed);
+ return new JobStatus(periodicToReschedule, getCurrentHeartbeat(),
+ elapsedNow + period - flex, elapsedNow + period,
+ 0 /* backoffAttempt */,
+ sSystemClock.millis() /* lastSuccessfulRunTime */,
+ periodicToReschedule.getLastFailedRunTime());
+ }
+
final long newEarliestRunTimeElapsed = newLatestRuntimeElapsed
- Math.min(flex, period - rescheduleBuffer);
@@ -2280,8 +2303,6 @@ public class JobSchedulerService extends com.android.server.SystemService
if (bucket >= mConstants.STANDBY_BEATS.length
|| (mHeartbeat > appLastRan
&& mHeartbeat < appLastRan + mConstants.STANDBY_BEATS[bucket])) {
- // TODO: log/trace that we're deferring the job due to bucketing if we
- // hit this
if (job.getWhenStandbyDeferred() == 0) {
if (DEBUG_STANDBY) {
Slog.v(TAG, "Bucket deferral: " + mHeartbeat + " < "
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index fd20e116d82a..eb5d472f7fbc 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -511,8 +511,13 @@ public final class JobStatus {
final long elapsedNow = sElapsedRealtimeClock.millis();
final long earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis;
if (job.isPeriodic()) {
- latestRunTimeElapsedMillis = elapsedNow + job.getIntervalMillis();
- earliestRunTimeElapsedMillis = latestRunTimeElapsedMillis - job.getFlexMillis();
+ // Make sure period is in the interval [min_possible_period, max_possible_period].
+ final long period = Math.max(JobInfo.getMinPeriodMillis(),
+ Math.min(JobSchedulerService.MAX_ALLOWED_PERIOD_MS, job.getIntervalMillis()));
+ latestRunTimeElapsedMillis = elapsedNow + period;
+ earliestRunTimeElapsedMillis = latestRunTimeElapsedMillis
+ // Make sure flex is in the interval [min_possible_flex, period].
+ - Math.max(JobInfo.getMinFlexMillis(), Math.min(period, job.getFlexMillis()));
} else {
earliestRunTimeElapsedMillis = job.hasEarlyConstraint() ?
elapsedNow + job.getMinLatencyMillis() : NO_EARLIEST_RUNTIME;
@@ -1631,6 +1636,9 @@ public final class JobStatus {
formatRunTime(pw, earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME, elapsedRealtimeMillis);
pw.print(", latest=");
formatRunTime(pw, latestRunTimeElapsedMillis, NO_LATEST_RUNTIME, elapsedRealtimeMillis);
+ pw.print(", original latest=");
+ formatRunTime(pw, mOriginalLatestRunTimeElapsedMillis,
+ NO_LATEST_RUNTIME, elapsedRealtimeMillis);
pw.println();
if (numFailures != 0) {
pw.print(prefix); pw.print("Num failures: "); pw.println(numFailures);
diff --git a/services/core/java/com/android/server/job/controllers/QuotaController.java b/services/core/java/com/android/server/job/controllers/QuotaController.java
index f560d69310a3..18d193ac68ec 100644
--- a/services/core/java/com/android/server/job/controllers/QuotaController.java
+++ b/services/core/java/com/android/server/job/controllers/QuotaController.java
@@ -16,6 +16,10 @@
package com.android.server.job.controllers;
+import static android.text.format.DateUtils.HOUR_IN_MILLIS;
+import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
+import static android.text.format.DateUtils.SECOND_IN_MILLIS;
+
import static com.android.server.job.JobSchedulerService.ACTIVE_INDEX;
import static com.android.server.job.JobSchedulerService.FREQUENT_INDEX;
import static com.android.server.job.JobSchedulerService.NEVER_INDEX;
@@ -75,17 +79,28 @@ import java.util.function.Predicate;
/**
* Controller that tracks whether an app has exceeded its standby bucket quota.
*
- * Each job in each bucket is given 10 minutes to run within its respective time window. Active
- * jobs can run indefinitely, working set jobs can run for 10 minutes within a 2 hour window,
- * frequent jobs get to run 10 minutes in an 8 hour window, and rare jobs get to run 10 minutes in
- * a 24 hour window. The windows are rolling, so as soon as a job would have some quota based on its
- * bucket, it will be eligible to run. When a job's bucket changes, its new quota is immediately
- * applied to it.
+ * With initial defaults, each app in each bucket is given 10 minutes to run within its respective
+ * time window. Active jobs can run indefinitely, working set jobs can run for 10 minutes within a
+ * 2 hour window, frequent jobs get to run 10 minutes in an 8 hour window, and rare jobs get to run
+ * 10 minutes in a 24 hour window. The windows are rolling, so as soon as a job would have some
+ * quota based on its bucket, it will be eligible to run. When a job's bucket changes, its new
+ * quota is immediately applied to it.
+ *
+ * Job and session count limits are included to prevent abuse/spam. Each bucket has its own limit on
+ * the number of jobs or sessions that can run within the window. Regardless of bucket, apps will
+ * not be allowed to run more than 20 jobs within the past 10 minutes.
*
* Jobs are throttled while an app is not in a foreground state. All jobs are allowed to run
* freely when an app enters the foreground state and are restricted when the app leaves the
- * foreground state. However, jobs that are started while the app is in the TOP state are not
- * restricted regardless of the app's state change.
+ * foreground state. However, jobs that are started while the app is in the TOP state do not count
+ * towards any quota and are not restricted regardless of the app's state change.
+ *
+ * Jobs will not be throttled when the device is charging. The device is considered to be charging
+ * once the {@link BatteryManager#ACTION_CHARGING} intent has been broadcast.
+ *
+ * Note: all limits are enforced per bucket window unless explicitly stated otherwise.
+ * All stated values are configurable and subject to change. See {@link QcConstants} for current
+ * defaults.
*
* Test: atest com.android.server.job.controllers.QuotaControllerTest
*/
@@ -94,8 +109,6 @@ public final class QuotaController extends StateController {
private static final boolean DEBUG = JobSchedulerService.DEBUG
|| Log.isLoggable(TAG, Log.DEBUG);
- private static final long MINUTE_IN_MILLIS = 60 * 1000L;
-
private static final String ALARM_TAG_CLEANUP = "*job.cleanup*";
private static final String ALARM_TAG_QUOTA_CHECK = "*job.quota_check*";
@@ -244,6 +257,8 @@ public final class QuotaController extends StateController {
public long expirationTimeElapsed;
public long windowSizeMs;
+ public int jobCountLimit;
+ public int sessionCountLimit;
/** The total amount of time the app ran in its respective bucket window size. */
public long executionTimeInWindowMs;
@@ -260,54 +275,58 @@ public final class QuotaController extends StateController {
public int sessionCountInWindow;
/**
- * The time after which the sum of all the app's sessions plus {@link #mQuotaBufferMs}
- * equals the quota. This is only valid if
- * executionTimeInWindowMs >= {@link #mAllowedTimePerPeriodMs} or
- * executionTimeInMaxPeriodMs >= {@link #mMaxExecutionTimeMs}.
+ * The time after which the app will be under the bucket quota and can start running jobs
+ * again. This is only valid if
+ * {@link #executionTimeInWindowMs} >= {@link #mAllowedTimePerPeriodMs},
+ * {@link #executionTimeInMaxPeriodMs} >= {@link #mMaxExecutionTimeMs},
+ * {@link #bgJobCountInWindow} >= {@link #jobCountLimit}, or
+ * {@link #sessionCountInWindow} >= {@link #sessionCountLimit}.
*/
- public long quotaCutoffTimeElapsed;
+ public long inQuotaTimeElapsed;
/**
- * The time after which {@link #jobCountInAllowedTime} should be considered invalid, in the
- * elapsed realtime timebase.
+ * The time after which {@link #jobCountInRateLimitingWindow} should be considered invalid,
+ * in the elapsed realtime timebase.
*/
- public long jobCountExpirationTimeElapsed;
+ public long jobRateLimitExpirationTimeElapsed;
/**
- * The number of jobs that ran in at least the last {@link #mAllowedTimePerPeriodMs}.
+ * The number of jobs that ran in at least the last {@link #mRateLimitingWindowMs}.
* It may contain a few stale entries since cleanup won't happen exactly every
- * {@link #mAllowedTimePerPeriodMs}.
+ * {@link #mRateLimitingWindowMs}.
*/
- public int jobCountInAllowedTime;
+ public int jobCountInRateLimitingWindow;
/**
- * The time after which {@link #sessionCountInAllowedTime} should be considered
+ * The time after which {@link #sessionCountInRateLimitingWindow} should be considered
* invalid, in the elapsed realtime timebase.
*/
- public long sessionCountExpirationTimeElapsed;
+ public long sessionRateLimitExpirationTimeElapsed;
/**
* The number of {@link TimingSession}s that ran in at least the last
- * {@link #mAllowedTimePerPeriodMs}. It may contain a few stale entries since cleanup won't
- * happen exactly every {@link #mAllowedTimePerPeriodMs}. This should only be considered
- * valid before elapsed realtime has reached {@link #sessionCountExpirationTimeElapsed}.
+ * {@link #mRateLimitingWindowMs}. It may contain a few stale entries since cleanup won't
+ * happen exactly every {@link #mRateLimitingWindowMs}. This should only be considered
+ * valid before elapsed realtime has reached {@link #sessionRateLimitExpirationTimeElapsed}.
*/
- public int sessionCountInAllowedTime;
+ public int sessionCountInRateLimitingWindow;
@Override
public String toString() {
return "expirationTime=" + expirationTimeElapsed + ", "
- + "windowSize=" + windowSizeMs + ", "
+ + "windowSizeMs=" + windowSizeMs + ", "
+ + "jobCountLimit=" + jobCountLimit + ", "
+ + "sessionCountLimit=" + sessionCountLimit + ", "
+ "executionTimeInWindow=" + executionTimeInWindowMs + ", "
+ "bgJobCountInWindow=" + bgJobCountInWindow + ", "
+ "executionTimeInMaxPeriod=" + executionTimeInMaxPeriodMs + ", "
+ "bgJobCountInMaxPeriod=" + bgJobCountInMaxPeriod + ", "
+ "sessionCountInWindow=" + sessionCountInWindow + ", "
- + "quotaCutoffTime=" + quotaCutoffTimeElapsed + ", "
- + "jobCountExpirationTime=" + jobCountExpirationTimeElapsed + ", "
- + "jobCountInAllowedTime=" + jobCountInAllowedTime + ", "
- + "sessionCountExpirationTime=" + sessionCountExpirationTimeElapsed + ", "
- + "sessionCountInAllowedTime=" + sessionCountInAllowedTime;
+ + "inQuotaTime=" + inQuotaTimeElapsed + ", "
+ + "jobCountExpirationTime=" + jobRateLimitExpirationTimeElapsed + ", "
+ + "jobCountInRateLimitingWindow=" + jobCountInRateLimitingWindow + ", "
+ + "sessionCountExpirationTime=" + sessionRateLimitExpirationTimeElapsed + ", "
+ + "sessionCountInRateLimitingWindow=" + sessionCountInRateLimitingWindow;
}
@Override
@@ -316,18 +335,21 @@ public final class QuotaController extends StateController {
ExecutionStats other = (ExecutionStats) obj;
return this.expirationTimeElapsed == other.expirationTimeElapsed
&& this.windowSizeMs == other.windowSizeMs
+ && this.jobCountLimit == other.jobCountLimit
+ && this.sessionCountLimit == other.sessionCountLimit
&& this.executionTimeInWindowMs == other.executionTimeInWindowMs
&& this.bgJobCountInWindow == other.bgJobCountInWindow
&& this.executionTimeInMaxPeriodMs == other.executionTimeInMaxPeriodMs
&& this.sessionCountInWindow == other.sessionCountInWindow
&& this.bgJobCountInMaxPeriod == other.bgJobCountInMaxPeriod
- && this.quotaCutoffTimeElapsed == other.quotaCutoffTimeElapsed
- && this.jobCountExpirationTimeElapsed == other.jobCountExpirationTimeElapsed
- && this.jobCountInAllowedTime == other.jobCountInAllowedTime
- && this.sessionCountExpirationTimeElapsed
- == other.sessionCountExpirationTimeElapsed
- && this.sessionCountInAllowedTime
- == other.sessionCountInAllowedTime;
+ && this.inQuotaTimeElapsed == other.inQuotaTimeElapsed
+ && this.jobRateLimitExpirationTimeElapsed
+ == other.jobRateLimitExpirationTimeElapsed
+ && this.jobCountInRateLimitingWindow == other.jobCountInRateLimitingWindow
+ && this.sessionRateLimitExpirationTimeElapsed
+ == other.sessionRateLimitExpirationTimeElapsed
+ && this.sessionCountInRateLimitingWindow
+ == other.sessionCountInRateLimitingWindow;
} else {
return false;
}
@@ -338,16 +360,18 @@ public final class QuotaController extends StateController {
int result = 0;
result = 31 * result + hashLong(expirationTimeElapsed);
result = 31 * result + hashLong(windowSizeMs);
+ result = 31 * result + hashLong(jobCountLimit);
+ result = 31 * result + hashLong(sessionCountLimit);
result = 31 * result + hashLong(executionTimeInWindowMs);
result = 31 * result + bgJobCountInWindow;
result = 31 * result + hashLong(executionTimeInMaxPeriodMs);
result = 31 * result + bgJobCountInMaxPeriod;
result = 31 * result + sessionCountInWindow;
- result = 31 * result + hashLong(quotaCutoffTimeElapsed);
- result = 31 * result + hashLong(jobCountExpirationTimeElapsed);
- result = 31 * result + jobCountInAllowedTime;
- result = 31 * result + hashLong(sessionCountExpirationTimeElapsed);
- result = 31 * result + sessionCountInAllowedTime;
+ result = 31 * result + hashLong(inQuotaTimeElapsed);
+ result = 31 * result + hashLong(jobRateLimitExpirationTimeElapsed);
+ result = 31 * result + jobCountInRateLimitingWindow;
+ result = 31 * result + hashLong(sessionRateLimitExpirationTimeElapsed);
+ result = 31 * result + sessionCountInRateLimitingWindow;
return result;
}
}
@@ -399,19 +423,19 @@ public final class QuotaController extends StateController {
private boolean mShouldThrottle;
/** How much time each app will have to run jobs within their standby bucket window. */
- private long mAllowedTimePerPeriodMs = 10 * MINUTE_IN_MILLIS;
+ private long mAllowedTimePerPeriodMs = QcConstants.DEFAULT_ALLOWED_TIME_PER_PERIOD_MS;
/**
* The maximum amount of time an app can have its jobs running within a {@link #MAX_PERIOD_MS}
* window.
*/
- private long mMaxExecutionTimeMs = 4 * 60 * MINUTE_IN_MILLIS;
+ private long mMaxExecutionTimeMs = QcConstants.DEFAULT_MAX_EXECUTION_TIME_MS;
/**
* How much time the app should have before transitioning from out-of-quota to in-quota.
* This should not affect processing if the app is already in-quota.
*/
- private long mQuotaBufferMs = 30 * 1000L; // 30 seconds
+ private long mQuotaBufferMs = QcConstants.DEFAULT_IN_QUOTA_BUFFER_MS;
/**
* {@link #mAllowedTimePerPeriodMs} - {@link #mQuotaBufferMs}. This can be used to determine
@@ -425,14 +449,19 @@ public final class QuotaController extends StateController {
*/
private long mMaxExecutionTimeIntoQuotaMs = mMaxExecutionTimeMs - mQuotaBufferMs;
- /** The maximum number of jobs that can run within the past {@link #mAllowedTimePerPeriodMs}. */
- private int mMaxJobCountPerAllowedTime = 20;
+ /** The period of time used to rate limit recently run jobs. */
+ private long mRateLimitingWindowMs = QcConstants.DEFAULT_RATE_LIMITING_WINDOW_MS;
+
+ /** The maximum number of jobs that can run within the past {@link #mRateLimitingWindowMs}. */
+ private int mMaxJobCountPerRateLimitingWindow =
+ QcConstants.DEFAULT_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW;
/**
* The maximum number of {@link TimingSession}s that can run within the past {@link
- * #mAllowedTimePerPeriodMs}.
+ * #mRateLimitingWindowMs}.
*/
- private int mMaxSessionCountPerAllowedTime = 20;
+ private int mMaxSessionCountPerRateLimitingWindow =
+ QcConstants.DEFAULT_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW;
private long mNextCleanupTimeElapsed = 0;
private final AlarmManager.OnAlarmListener mSessionCleanupAlarmListener =
@@ -486,11 +515,11 @@ public final class QuotaController extends StateController {
* The rolling window size for each standby bucket. Within each window, an app will have 10
* minutes to run its jobs.
*/
- private final long[] mBucketPeriodsMs = new long[] {
- 10 * MINUTE_IN_MILLIS, // 10 minutes for ACTIVE -- ACTIVE apps can run jobs at any time
- 2 * 60 * MINUTE_IN_MILLIS, // 2 hours for WORKING
- 8 * 60 * MINUTE_IN_MILLIS, // 8 hours for FREQUENT
- 24 * 60 * MINUTE_IN_MILLIS // 24 hours for RARE
+ private final long[] mBucketPeriodsMs = new long[]{
+ QcConstants.DEFAULT_WINDOW_SIZE_ACTIVE_MS,
+ QcConstants.DEFAULT_WINDOW_SIZE_WORKING_MS,
+ QcConstants.DEFAULT_WINDOW_SIZE_FREQUENT_MS,
+ QcConstants.DEFAULT_WINDOW_SIZE_RARE_MS
};
/** The maximum period any bucket can have. */
@@ -503,16 +532,13 @@ public final class QuotaController extends StateController {
*
* @see #mBucketPeriodsMs
*/
- private final int[] mMaxBucketJobCounts = new int[] {
- 200, // ACTIVE -- 1200/hr
- 1200, // WORKING -- 600/hr
- 1800, // FREQUENT -- 225/hr
- 2400 // RARE -- 100/hr
+ private final int[] mMaxBucketJobCounts = new int[]{
+ QcConstants.DEFAULT_MAX_JOB_COUNT_ACTIVE,
+ QcConstants.DEFAULT_MAX_JOB_COUNT_WORKING,
+ QcConstants.DEFAULT_MAX_JOB_COUNT_FREQUENT,
+ QcConstants.DEFAULT_MAX_JOB_COUNT_RARE
};
- /** The minimum number of jobs that any bucket will be allowed to run. */
- private static final int MIN_BUCKET_JOB_COUNT = 100;
-
/**
* The maximum number of {@link TimingSession}s based on its standby bucket. For each max value
* count in the array, the app will not be allowed to have more than that many number of
@@ -527,14 +553,12 @@ public final class QuotaController extends StateController {
QcConstants.DEFAULT_MAX_SESSION_COUNT_RARE
};
- /** The minimum number of {@link TimingSession}s that any bucket will be allowed to run. */
- private static final int MIN_BUCKET_SESSION_COUNT = 3;
-
/**
* Treat two distinct {@link TimingSession}s as the same if they start and end within this
* amount of time of each other.
*/
- private long mTimingSessionCoalescingDurationMs = 0;
+ private long mTimingSessionCoalescingDurationMs =
+ QcConstants.DEFAULT_TIMING_SESSION_COALESCING_DURATION_MS;
/** An app has reached its quota. The message should contain a {@link Package} object. */
private static final int MSG_REACHED_QUOTA = 0;
@@ -593,7 +617,7 @@ public final class QuotaController extends StateController {
jobStatus.setTrackingController(JobStatus.TRACKING_QUOTA);
if (mShouldThrottle) {
final boolean isWithinQuota = isWithinQuotaLocked(jobStatus);
- jobStatus.setQuotaConstraintSatisfied(isWithinQuota);
+ setConstraintSatisfied(jobStatus, isWithinQuota);
if (!isWithinQuota) {
maybeScheduleStartAlarmLocked(userId, pkgName,
getEffectiveStandbyBucket(jobStatus));
@@ -761,8 +785,8 @@ public final class QuotaController extends StateController {
final int standbyBucket) {
final long now = sElapsedRealtimeClock.millis();
final boolean isUnderAllowedTimeQuota =
- (stats.jobCountExpirationTimeElapsed <= now
- || stats.jobCountInAllowedTime < mMaxJobCountPerAllowedTime);
+ (stats.jobRateLimitExpirationTimeElapsed <= now
+ || stats.jobCountInRateLimitingWindow < mMaxJobCountPerRateLimitingWindow);
return isUnderAllowedTimeQuota
&& (stats.bgJobCountInWindow < mMaxBucketJobCounts[standbyBucket]);
}
@@ -770,10 +794,8 @@ public final class QuotaController extends StateController {
private boolean isUnderSessionCountQuotaLocked(@NonNull ExecutionStats stats,
final int standbyBucket) {
final long now = sElapsedRealtimeClock.millis();
- final boolean isUnderAllowedTimeQuota =
- (stats.sessionCountExpirationTimeElapsed <= now
- || stats.sessionCountInAllowedTime
- < mMaxSessionCountPerAllowedTime);
+ final boolean isUnderAllowedTimeQuota = (stats.sessionRateLimitExpirationTimeElapsed <= now
+ || stats.sessionCountInRateLimitingWindow < mMaxSessionCountPerRateLimitingWindow);
return isUnderAllowedTimeQuota
&& stats.sessionCountInWindow < mMaxBucketSessionCounts[standbyBucket];
}
@@ -924,12 +946,18 @@ public final class QuotaController extends StateController {
}
if (refreshStatsIfOld) {
final long bucketWindowSizeMs = mBucketPeriodsMs[standbyBucket];
+ final int jobCountLimit = mMaxBucketJobCounts[standbyBucket];
+ final int sessionCountLimit = mMaxBucketSessionCounts[standbyBucket];
Timer timer = mPkgTimers.get(userId, packageName);
if ((timer != null && timer.isActive())
|| stats.expirationTimeElapsed <= sElapsedRealtimeClock.millis()
- || stats.windowSizeMs != bucketWindowSizeMs) {
+ || stats.windowSizeMs != bucketWindowSizeMs
+ || stats.jobCountLimit != jobCountLimit
+ || stats.sessionCountLimit != sessionCountLimit) {
// The stats are no longer valid.
stats.windowSizeMs = bucketWindowSizeMs;
+ stats.jobCountLimit = jobCountLimit;
+ stats.sessionCountLimit = sessionCountLimit;
updateExecutionStatsLocked(userId, packageName, stats);
}
}
@@ -945,7 +973,7 @@ public final class QuotaController extends StateController {
stats.executionTimeInMaxPeriodMs = 0;
stats.bgJobCountInMaxPeriod = 0;
stats.sessionCountInWindow = 0;
- stats.quotaCutoffTimeElapsed = 0;
+ stats.inQuotaTimeElapsed = 0;
Timer timer = mPkgTimers.get(userId, packageName);
final long nowElapsed = sElapsedRealtimeClock.millis();
@@ -958,12 +986,12 @@ public final class QuotaController extends StateController {
// invalidate now.
stats.expirationTimeElapsed = nowElapsed;
if (stats.executionTimeInWindowMs >= mAllowedTimeIntoQuotaMs) {
- stats.quotaCutoffTimeElapsed = Math.max(stats.quotaCutoffTimeElapsed,
- nowElapsed - mAllowedTimeIntoQuotaMs);
+ stats.inQuotaTimeElapsed = Math.max(stats.inQuotaTimeElapsed,
+ nowElapsed - mAllowedTimeIntoQuotaMs + stats.windowSizeMs);
}
if (stats.executionTimeInMaxPeriodMs >= mMaxExecutionTimeIntoQuotaMs) {
- stats.quotaCutoffTimeElapsed = Math.max(stats.quotaCutoffTimeElapsed,
- nowElapsed - mMaxExecutionTimeIntoQuotaMs);
+ stats.inQuotaTimeElapsed = Math.max(stats.inQuotaTimeElapsed,
+ nowElapsed - mMaxExecutionTimeIntoQuotaMs + MAX_PERIOD_MS);
}
}
@@ -985,36 +1013,40 @@ public final class QuotaController extends StateController {
TimingSession session = sessions.get(i);
// Window management.
- if (startWindowElapsed < session.startTimeElapsed) {
- stats.executionTimeInWindowMs += session.endTimeElapsed - session.startTimeElapsed;
- stats.bgJobCountInWindow += session.bgJobCount;
- emptyTimeMs = Math.min(emptyTimeMs, session.startTimeElapsed - startWindowElapsed);
- if (stats.executionTimeInWindowMs >= mAllowedTimeIntoQuotaMs) {
- stats.quotaCutoffTimeElapsed = Math.max(stats.quotaCutoffTimeElapsed,
- session.startTimeElapsed + stats.executionTimeInWindowMs
- - mAllowedTimeIntoQuotaMs);
- }
- if (i == loopStart
- || (sessions.get(i + 1).startTimeElapsed - session.endTimeElapsed)
- > mTimingSessionCoalescingDurationMs) {
- // Coalesce sessions if they are very close to each other in time
- sessionCountInWindow++;
+ if (startWindowElapsed < session.endTimeElapsed) {
+ final long start;
+ if (startWindowElapsed < session.startTimeElapsed) {
+ start = session.startTimeElapsed;
+ emptyTimeMs =
+ Math.min(emptyTimeMs, session.startTimeElapsed - startWindowElapsed);
+ } else {
+ // The session started before the window but ended within the window. Only
+ // include the portion that was within the window.
+ start = startWindowElapsed;
+ emptyTimeMs = 0;
}
- } else if (startWindowElapsed < session.endTimeElapsed) {
- // The session started before the window but ended within the window. Only include
- // the portion that was within the window.
- stats.executionTimeInWindowMs += session.endTimeElapsed - startWindowElapsed;
+
+ stats.executionTimeInWindowMs += session.endTimeElapsed - start;
stats.bgJobCountInWindow += session.bgJobCount;
- emptyTimeMs = 0;
if (stats.executionTimeInWindowMs >= mAllowedTimeIntoQuotaMs) {
- stats.quotaCutoffTimeElapsed = Math.max(stats.quotaCutoffTimeElapsed,
- startWindowElapsed + stats.executionTimeInWindowMs
- - mAllowedTimeIntoQuotaMs);
+ stats.inQuotaTimeElapsed = Math.max(stats.inQuotaTimeElapsed,
+ start + stats.executionTimeInWindowMs - mAllowedTimeIntoQuotaMs
+ + stats.windowSizeMs);
+ }
+ if (stats.bgJobCountInWindow >= stats.jobCountLimit) {
+ stats.inQuotaTimeElapsed = Math.max(stats.inQuotaTimeElapsed,
+ session.endTimeElapsed + stats.windowSizeMs);
}
if (i == loopStart
|| (sessions.get(i + 1).startTimeElapsed - session.endTimeElapsed)
> mTimingSessionCoalescingDurationMs) {
+ // Coalesce sessions if they are very close to each other in time
sessionCountInWindow++;
+
+ if (sessionCountInWindow >= stats.sessionCountLimit) {
+ stats.inQuotaTimeElapsed = Math.max(stats.inQuotaTimeElapsed,
+ session.endTimeElapsed + stats.windowSizeMs);
+ }
}
}
@@ -1025,9 +1057,9 @@ public final class QuotaController extends StateController {
stats.bgJobCountInMaxPeriod += session.bgJobCount;
emptyTimeMs = Math.min(emptyTimeMs, session.startTimeElapsed - startMaxElapsed);
if (stats.executionTimeInMaxPeriodMs >= mMaxExecutionTimeIntoQuotaMs) {
- stats.quotaCutoffTimeElapsed = Math.max(stats.quotaCutoffTimeElapsed,
+ stats.inQuotaTimeElapsed = Math.max(stats.inQuotaTimeElapsed,
session.startTimeElapsed + stats.executionTimeInMaxPeriodMs
- - mMaxExecutionTimeIntoQuotaMs);
+ - mMaxExecutionTimeIntoQuotaMs + MAX_PERIOD_MS);
}
} else if (startMaxElapsed < session.endTimeElapsed) {
// The session started before the window but ended within the window. Only include
@@ -1036,9 +1068,9 @@ public final class QuotaController extends StateController {
stats.bgJobCountInMaxPeriod += session.bgJobCount;
emptyTimeMs = 0;
if (stats.executionTimeInMaxPeriodMs >= mMaxExecutionTimeIntoQuotaMs) {
- stats.quotaCutoffTimeElapsed = Math.max(stats.quotaCutoffTimeElapsed,
+ stats.inQuotaTimeElapsed = Math.max(stats.inQuotaTimeElapsed,
startMaxElapsed + stats.executionTimeInMaxPeriodMs
- - mMaxExecutionTimeIntoQuotaMs);
+ - mMaxExecutionTimeIntoQuotaMs + MAX_PERIOD_MS);
}
} else {
// This session ended before the window. No point in going any further.
@@ -1094,11 +1126,11 @@ public final class QuotaController extends StateController {
stats = new ExecutionStats();
appStats[i] = stats;
}
- if (stats.jobCountExpirationTimeElapsed <= now) {
- stats.jobCountExpirationTimeElapsed = now + mAllowedTimePerPeriodMs;
- stats.jobCountInAllowedTime = 0;
+ if (stats.jobRateLimitExpirationTimeElapsed <= now) {
+ stats.jobRateLimitExpirationTimeElapsed = now + mRateLimitingWindowMs;
+ stats.jobCountInRateLimitingWindow = 0;
}
- stats.jobCountInAllowedTime += count;
+ stats.jobCountInRateLimitingWindow += count;
}
}
@@ -1115,11 +1147,11 @@ public final class QuotaController extends StateController {
stats = new ExecutionStats();
appStats[i] = stats;
}
- if (stats.sessionCountExpirationTimeElapsed <= now) {
- stats.sessionCountExpirationTimeElapsed = now + mAllowedTimePerPeriodMs;
- stats.sessionCountInAllowedTime = 0;
+ if (stats.sessionRateLimitExpirationTimeElapsed <= now) {
+ stats.sessionRateLimitExpirationTimeElapsed = now + mRateLimitingWindowMs;
+ stats.sessionCountInRateLimitingWindow = 0;
}
- stats.sessionCountInAllowedTime++;
+ stats.sessionCountInRateLimitingWindow++;
}
}
@@ -1250,10 +1282,10 @@ public final class QuotaController extends StateController {
// An app in the ACTIVE bucket may be out of quota while the job could be in quota
// for some reason. Therefore, avoid setting the real value here and check each job
// individually.
- changed |= js.setQuotaConstraintSatisfied(realInQuota);
+ changed |= setConstraintSatisfied(js, realInQuota);
} else {
// This job is somehow exempted. Need to determine its own quota status.
- changed |= js.setQuotaConstraintSatisfied(isWithinQuotaLocked(js));
+ changed |= setConstraintSatisfied(js, isWithinQuotaLocked(js));
}
}
if (!realInQuota) {
@@ -1278,7 +1310,7 @@ public final class QuotaController extends StateController {
@Override
public void accept(JobStatus jobStatus) {
- wasJobChanged |= jobStatus.setQuotaConstraintSatisfied(isWithinQuotaLocked(jobStatus));
+ wasJobChanged |= setConstraintSatisfied(jobStatus, isWithinQuotaLocked(jobStatus));
final int userId = jobStatus.getSourceUserId();
final String packageName = jobStatus.getSourcePackageName();
final int realStandbyBucket = jobStatus.getStandbyBucket();
@@ -1367,18 +1399,17 @@ public final class QuotaController extends StateController {
}
// The time this app will have quota again.
- long inQuotaTimeElapsed = stats.quotaCutoffTimeElapsed + stats.windowSizeMs;
- if (stats.executionTimeInMaxPeriodMs >= mMaxExecutionTimeMs) {
+ long inQuotaTimeElapsed = stats.inQuotaTimeElapsed;
+ if (!isUnderJobCountQuota && stats.bgJobCountInWindow < stats.jobCountLimit) {
+ // App hit the rate limit.
inQuotaTimeElapsed = Math.max(inQuotaTimeElapsed,
- stats.quotaCutoffTimeElapsed + MAX_PERIOD_MS);
+ stats.jobRateLimitExpirationTimeElapsed);
}
- if (!isUnderJobCountQuota) {
+ if (!isUnderTimingSessionCountQuota
+ && stats.sessionCountInWindow < stats.sessionCountLimit) {
+ // App hit the rate limit.
inQuotaTimeElapsed = Math.max(inQuotaTimeElapsed,
- stats.jobCountExpirationTimeElapsed + mAllowedTimePerPeriodMs);
- }
- if (!isUnderTimingSessionCountQuota) {
- inQuotaTimeElapsed = Math.max(inQuotaTimeElapsed,
- stats.sessionCountExpirationTimeElapsed + mAllowedTimePerPeriodMs);
+ stats.sessionRateLimitExpirationTimeElapsed);
}
// Only schedule the alarm if:
// 1. There isn't one currently scheduled
@@ -1399,8 +1430,16 @@ public final class QuotaController extends StateController {
ALARM_TAG_QUOTA_CHECK, alarmListener, mHandler);
alarmListener.setTriggerTime(inQuotaTimeElapsed);
} else if (DEBUG) {
- Slog.d(TAG, "No need to scheduling start alarm for " + pkgString);
+ Slog.d(TAG, "No need to schedule start alarm for " + pkgString);
+ }
+ }
+
+ private boolean setConstraintSatisfied(@NonNull JobStatus jobStatus, boolean isWithinQuota) {
+ if (!isWithinQuota && jobStatus.getWhenStandbyDeferred() == 0) {
+ // Mark that the job is being deferred due to buckets.
+ jobStatus.setWhenStandbyDeferred(sElapsedRealtimeClock.millis());
}
+ return jobStatus.setQuotaConstraintSatisfied(isWithinQuota);
}
private final class ChargingTracker extends BroadcastReceiver {
@@ -1968,14 +2007,15 @@ public final class QuotaController extends StateController {
private static final String KEY_MAX_JOB_COUNT_WORKING = "max_job_count_working";
private static final String KEY_MAX_JOB_COUNT_FREQUENT = "max_job_count_frequent";
private static final String KEY_MAX_JOB_COUNT_RARE = "max_job_count_rare";
- private static final String KEY_MAX_JOB_COUNT_PER_ALLOWED_TIME =
- "max_count_per_allowed_time";
+ private static final String KEY_RATE_LIMITING_WINDOW_MS = "rate_limiting_window_ms";
+ private static final String KEY_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW =
+ "max_job_count_per_rate_limiting_window";
private static final String KEY_MAX_SESSION_COUNT_ACTIVE = "max_session_count_active";
private static final String KEY_MAX_SESSION_COUNT_WORKING = "max_session_count_working";
private static final String KEY_MAX_SESSION_COUNT_FREQUENT = "max_session_count_frequent";
private static final String KEY_MAX_SESSION_COUNT_RARE = "max_session_count_rare";
- private static final String KEY_MAX_SESSION_COUNT_PER_ALLOWED_TIME =
- "max_session_count_per_allowed_time";
+ private static final String KEY_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW =
+ "max_session_count_per_rate_limiting_window";
private static final String KEY_TIMING_SESSION_COALESCING_DURATION_MS =
"timing_session_coalescing_duration_ms";
@@ -1984,7 +2024,7 @@ public final class QuotaController extends StateController {
private static final long DEFAULT_IN_QUOTA_BUFFER_MS =
30 * 1000L; // 30 seconds
private static final long DEFAULT_WINDOW_SIZE_ACTIVE_MS =
- 10 * 60 * 1000L; // 10 minutes for ACTIVE -- ACTIVE apps can run jobs at any time
+ DEFAULT_ALLOWED_TIME_PER_PERIOD_MS; // ACTIVE apps can run jobs at any time
private static final long DEFAULT_WINDOW_SIZE_WORKING_MS =
2 * 60 * 60 * 1000L; // 2 hours
private static final long DEFAULT_WINDOW_SIZE_FREQUENT_MS =
@@ -1992,16 +2032,18 @@ public final class QuotaController extends StateController {
private static final long DEFAULT_WINDOW_SIZE_RARE_MS =
24 * 60 * 60 * 1000L; // 24 hours
private static final long DEFAULT_MAX_EXECUTION_TIME_MS =
- 4 * 60 * 60 * 1000L; // 4 hours
- private static final int DEFAULT_MAX_JOB_COUNT_ACTIVE =
- 200; // 1200/hr
- private static final int DEFAULT_MAX_JOB_COUNT_WORKING =
- 1200; // 600/hr
- private static final int DEFAULT_MAX_JOB_COUNT_FREQUENT =
- 1800; // 225/hr
- private static final int DEFAULT_MAX_JOB_COUNT_RARE =
- 2400; // 100/hr
- private static final int DEFAULT_MAX_JOB_COUNT_PER_ALLOWED_TIME = 20;
+ 4 * HOUR_IN_MILLIS;
+ private static final long DEFAULT_RATE_LIMITING_WINDOW_MS =
+ 10 * MINUTE_IN_MILLIS;
+ private static final int DEFAULT_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW = 20;
+ private static final int DEFAULT_MAX_JOB_COUNT_ACTIVE = // 20/window = 120/hr = 1/session
+ DEFAULT_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW;
+ private static final int DEFAULT_MAX_JOB_COUNT_WORKING = // 120/window = 60/hr = 12/session
+ (int) (60.0 * DEFAULT_WINDOW_SIZE_WORKING_MS / HOUR_IN_MILLIS);
+ private static final int DEFAULT_MAX_JOB_COUNT_FREQUENT = // 200/window = 25/hr = 25/session
+ (int) (25.0 * DEFAULT_WINDOW_SIZE_FREQUENT_MS / HOUR_IN_MILLIS);
+ private static final int DEFAULT_MAX_JOB_COUNT_RARE = // 48/window = 2/hr = 16/session
+ (int) (2.0 * DEFAULT_WINDOW_SIZE_RARE_MS / HOUR_IN_MILLIS);
private static final int DEFAULT_MAX_SESSION_COUNT_ACTIVE =
20; // 120/hr
private static final int DEFAULT_MAX_SESSION_COUNT_WORKING =
@@ -2010,8 +2052,8 @@ public final class QuotaController extends StateController {
8; // 1/hr
private static final int DEFAULT_MAX_SESSION_COUNT_RARE =
3; // .125/hr
- private static final int DEFAULT_MAX_SESSION_COUNT_PER_ALLOWED_TIME = 20;
- private static final long DEFAULT_TIMING_SESSION_COALESCING_DURATION_MS = 0;
+ private static final int DEFAULT_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW = 20;
+ private static final long DEFAULT_TIMING_SESSION_COALESCING_DURATION_MS = 5000; // 5 seconds
/** How much time each app will have to run jobs within their standby bucket window. */
public long ALLOWED_TIME_PER_PERIOD_MS = DEFAULT_ALLOWED_TIME_PER_PERIOD_MS;
@@ -2079,11 +2121,14 @@ public final class QuotaController extends StateController {
*/
public int MAX_JOB_COUNT_RARE = DEFAULT_MAX_JOB_COUNT_RARE;
+ /** The period of time used to rate limit recently run jobs. */
+ public long RATE_LIMITING_WINDOW_MS = DEFAULT_RATE_LIMITING_WINDOW_MS;
+
/**
- * The maximum number of jobs that can run within the past
- * {@link #ALLOWED_TIME_PER_PERIOD_MS}.
+ * The maximum number of jobs that can run within the past {@link #RATE_LIMITING_WINDOW_MS}.
*/
- public int MAX_JOB_COUNT_PER_ALLOWED_TIME = DEFAULT_MAX_JOB_COUNT_PER_ALLOWED_TIME;
+ public int MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW =
+ DEFAULT_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW;
/**
* The maximum number of {@link TimingSession}s an app can run within this particular
@@ -2113,7 +2158,8 @@ public final class QuotaController extends StateController {
* The maximum number of {@link TimingSession}s that can run within the past
* {@link #ALLOWED_TIME_PER_PERIOD_MS}.
*/
- public int MAX_SESSION_COUNT_PER_ALLOWED_TIME = DEFAULT_MAX_SESSION_COUNT_PER_ALLOWED_TIME;
+ public int MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW =
+ DEFAULT_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW;
/**
* Treat two distinct {@link TimingSession}s as the same if they start and end within this
@@ -2122,6 +2168,29 @@ public final class QuotaController extends StateController {
public long TIMING_SESSION_COALESCING_DURATION_MS =
DEFAULT_TIMING_SESSION_COALESCING_DURATION_MS;
+ // Safeguards
+
+ /** The minimum number of jobs that any bucket will be allowed to run within its window. */
+ private static final int MIN_BUCKET_JOB_COUNT = 10;
+
+ /**
+ * The minimum number of {@link TimingSession}s that any bucket will be allowed to run
+ * within its window.
+ */
+ private static final int MIN_BUCKET_SESSION_COUNT = 1;
+
+ /** The minimum value that {@link #MAX_EXECUTION_TIME_MS} can have. */
+ private static final long MIN_MAX_EXECUTION_TIME_MS = 60 * MINUTE_IN_MILLIS;
+
+ /** The minimum value that {@link #MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW} can have. */
+ private static final int MIN_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW = 10;
+
+ /** The minimum value that {@link #MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW} can have. */
+ private static final int MIN_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW = 10;
+
+ /** The minimum value that {@link #RATE_LIMITING_WINDOW_MS} can have. */
+ private static final long MIN_RATE_LIMITING_WINDOW_MS = 30 * SECOND_IN_MILLIS;
+
QcConstants(Handler handler) {
super(handler);
}
@@ -2167,8 +2236,11 @@ public final class QuotaController extends StateController {
KEY_MAX_JOB_COUNT_FREQUENT, DEFAULT_MAX_JOB_COUNT_FREQUENT);
MAX_JOB_COUNT_RARE = mParser.getInt(
KEY_MAX_JOB_COUNT_RARE, DEFAULT_MAX_JOB_COUNT_RARE);
- MAX_JOB_COUNT_PER_ALLOWED_TIME = mParser.getInt(
- KEY_MAX_JOB_COUNT_PER_ALLOWED_TIME, DEFAULT_MAX_JOB_COUNT_PER_ALLOWED_TIME);
+ RATE_LIMITING_WINDOW_MS = mParser.getLong(
+ KEY_RATE_LIMITING_WINDOW_MS, DEFAULT_RATE_LIMITING_WINDOW_MS);
+ MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW = mParser.getInt(
+ KEY_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW,
+ DEFAULT_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW);
MAX_SESSION_COUNT_ACTIVE = mParser.getInt(
KEY_MAX_SESSION_COUNT_ACTIVE, DEFAULT_MAX_SESSION_COUNT_ACTIVE);
MAX_SESSION_COUNT_WORKING = mParser.getInt(
@@ -2177,9 +2249,9 @@ public final class QuotaController extends StateController {
KEY_MAX_SESSION_COUNT_FREQUENT, DEFAULT_MAX_SESSION_COUNT_FREQUENT);
MAX_SESSION_COUNT_RARE = mParser.getInt(
KEY_MAX_SESSION_COUNT_RARE, DEFAULT_MAX_SESSION_COUNT_RARE);
- MAX_SESSION_COUNT_PER_ALLOWED_TIME = mParser.getInt(
- KEY_MAX_SESSION_COUNT_PER_ALLOWED_TIME,
- DEFAULT_MAX_SESSION_COUNT_PER_ALLOWED_TIME);
+ MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW = mParser.getInt(
+ KEY_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW,
+ DEFAULT_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW);
TIMING_SESSION_COALESCING_DURATION_MS = mParser.getLong(
KEY_TIMING_SESSION_COALESCING_DURATION_MS,
DEFAULT_TIMING_SESSION_COALESCING_DURATION_MS);
@@ -2192,7 +2264,14 @@ public final class QuotaController extends StateController {
synchronized (mLock) {
boolean changed = false;
- long newAllowedTimeMs = Math.min(MAX_PERIOD_MS,
+ long newMaxExecutionTimeMs = Math.max(MIN_MAX_EXECUTION_TIME_MS,
+ Math.min(MAX_PERIOD_MS, MAX_EXECUTION_TIME_MS));
+ if (mMaxExecutionTimeMs != newMaxExecutionTimeMs) {
+ mMaxExecutionTimeMs = newMaxExecutionTimeMs;
+ mMaxExecutionTimeIntoQuotaMs = mMaxExecutionTimeMs - mQuotaBufferMs;
+ changed = true;
+ }
+ long newAllowedTimeMs = Math.min(mMaxExecutionTimeMs,
Math.max(MINUTE_IN_MILLIS, ALLOWED_TIME_PER_PERIOD_MS));
if (mAllowedTimePerPeriodMs != newAllowedTimeMs) {
mAllowedTimePerPeriodMs = newAllowedTimeMs;
@@ -2231,47 +2310,44 @@ public final class QuotaController extends StateController {
mBucketPeriodsMs[RARE_INDEX] = newRarePeriodMs;
changed = true;
}
- long newMaxExecutionTimeMs = Math.max(60 * MINUTE_IN_MILLIS,
- Math.min(MAX_PERIOD_MS, MAX_EXECUTION_TIME_MS));
- if (mMaxExecutionTimeMs != newMaxExecutionTimeMs) {
- mMaxExecutionTimeMs = newMaxExecutionTimeMs;
- mMaxExecutionTimeIntoQuotaMs = mMaxExecutionTimeMs - mQuotaBufferMs;
+ long newRateLimitingWindowMs = Math.min(MAX_PERIOD_MS,
+ Math.max(MIN_RATE_LIMITING_WINDOW_MS, RATE_LIMITING_WINDOW_MS));
+ if (mRateLimitingWindowMs != newRateLimitingWindowMs) {
+ mRateLimitingWindowMs = newRateLimitingWindowMs;
changed = true;
}
- int newMaxCountPerAllowedPeriod = Math.max(10,
- MAX_JOB_COUNT_PER_ALLOWED_TIME);
- if (mMaxJobCountPerAllowedTime != newMaxCountPerAllowedPeriod) {
- mMaxJobCountPerAllowedTime = newMaxCountPerAllowedPeriod;
+ int newMaxJobCountPerRateLimitingWindow = Math.max(
+ MIN_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW,
+ MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW);
+ if (mMaxJobCountPerRateLimitingWindow != newMaxJobCountPerRateLimitingWindow) {
+ mMaxJobCountPerRateLimitingWindow = newMaxJobCountPerRateLimitingWindow;
changed = true;
}
- int newActiveMaxJobCount = Math.max(mMaxJobCountPerAllowedTime,
- Math.max(MIN_BUCKET_JOB_COUNT, MAX_JOB_COUNT_ACTIVE));
+ int newActiveMaxJobCount = Math.max(MIN_BUCKET_JOB_COUNT, MAX_JOB_COUNT_ACTIVE);
if (mMaxBucketJobCounts[ACTIVE_INDEX] != newActiveMaxJobCount) {
mMaxBucketJobCounts[ACTIVE_INDEX] = newActiveMaxJobCount;
changed = true;
}
- int newWorkingMaxJobCount = Math.max(mMaxJobCountPerAllowedTime,
- Math.max(MIN_BUCKET_JOB_COUNT, MAX_JOB_COUNT_WORKING));
+ int newWorkingMaxJobCount = Math.max(MIN_BUCKET_JOB_COUNT, MAX_JOB_COUNT_WORKING);
if (mMaxBucketJobCounts[WORKING_INDEX] != newWorkingMaxJobCount) {
mMaxBucketJobCounts[WORKING_INDEX] = newWorkingMaxJobCount;
changed = true;
}
- int newFrequentMaxJobCount = Math.max(mMaxJobCountPerAllowedTime,
- Math.max(MIN_BUCKET_JOB_COUNT, MAX_JOB_COUNT_FREQUENT));
+ int newFrequentMaxJobCount = Math.max(MIN_BUCKET_JOB_COUNT, MAX_JOB_COUNT_FREQUENT);
if (mMaxBucketJobCounts[FREQUENT_INDEX] != newFrequentMaxJobCount) {
mMaxBucketJobCounts[FREQUENT_INDEX] = newFrequentMaxJobCount;
changed = true;
}
- int newRareMaxJobCount = Math.max(mMaxJobCountPerAllowedTime,
- Math.max(MIN_BUCKET_JOB_COUNT, MAX_JOB_COUNT_RARE));
+ int newRareMaxJobCount = Math.max(MIN_BUCKET_JOB_COUNT, MAX_JOB_COUNT_RARE);
if (mMaxBucketJobCounts[RARE_INDEX] != newRareMaxJobCount) {
mMaxBucketJobCounts[RARE_INDEX] = newRareMaxJobCount;
changed = true;
}
- int newMaxSessionCountPerAllowedPeriod = Math.max(10,
- MAX_SESSION_COUNT_PER_ALLOWED_TIME);
- if (mMaxSessionCountPerAllowedTime != newMaxSessionCountPerAllowedPeriod) {
- mMaxSessionCountPerAllowedTime = newMaxSessionCountPerAllowedPeriod;
+ int newMaxSessionCountPerRateLimitPeriod = Math.max(
+ MIN_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW,
+ MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW);
+ if (mMaxSessionCountPerRateLimitingWindow != newMaxSessionCountPerRateLimitPeriod) {
+ mMaxSessionCountPerRateLimitingWindow = newMaxSessionCountPerRateLimitPeriod;
changed = true;
}
int newActiveMaxSessionCount =
@@ -2332,14 +2408,15 @@ public final class QuotaController extends StateController {
pw.printPair(KEY_MAX_JOB_COUNT_WORKING, MAX_JOB_COUNT_WORKING).println();
pw.printPair(KEY_MAX_JOB_COUNT_FREQUENT, MAX_JOB_COUNT_FREQUENT).println();
pw.printPair(KEY_MAX_JOB_COUNT_RARE, MAX_JOB_COUNT_RARE).println();
- pw.printPair(KEY_MAX_JOB_COUNT_PER_ALLOWED_TIME, MAX_JOB_COUNT_PER_ALLOWED_TIME)
- .println();
+ pw.printPair(KEY_RATE_LIMITING_WINDOW_MS, RATE_LIMITING_WINDOW_MS).println();
+ pw.printPair(KEY_MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW,
+ MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW).println();
pw.printPair(KEY_MAX_SESSION_COUNT_ACTIVE, MAX_SESSION_COUNT_ACTIVE).println();
pw.printPair(KEY_MAX_SESSION_COUNT_WORKING, MAX_SESSION_COUNT_WORKING).println();
pw.printPair(KEY_MAX_SESSION_COUNT_FREQUENT, MAX_SESSION_COUNT_FREQUENT).println();
pw.printPair(KEY_MAX_SESSION_COUNT_RARE, MAX_SESSION_COUNT_RARE).println();
- pw.printPair(KEY_MAX_SESSION_COUNT_PER_ALLOWED_TIME, MAX_SESSION_COUNT_PER_ALLOWED_TIME)
- .println();
+ pw.printPair(KEY_MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW,
+ MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW).println();
pw.printPair(KEY_TIMING_SESSION_COALESCING_DURATION_MS,
TIMING_SESSION_COALESCING_DURATION_MS).println();
pw.decreaseIndent();
@@ -2365,8 +2442,10 @@ public final class QuotaController extends StateController {
proto.write(ConstantsProto.QuotaController.MAX_JOB_COUNT_FREQUENT,
MAX_JOB_COUNT_FREQUENT);
proto.write(ConstantsProto.QuotaController.MAX_JOB_COUNT_RARE, MAX_JOB_COUNT_RARE);
- proto.write(ConstantsProto.QuotaController.MAX_JOB_COUNT_PER_ALLOWED_TIME,
- MAX_JOB_COUNT_PER_ALLOWED_TIME);
+ proto.write(ConstantsProto.QuotaController.RATE_LIMITING_WINDOW_MS,
+ RATE_LIMITING_WINDOW_MS);
+ proto.write(ConstantsProto.QuotaController.MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW,
+ MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW);
proto.write(ConstantsProto.QuotaController.MAX_SESSION_COUNT_ACTIVE,
MAX_SESSION_COUNT_ACTIVE);
proto.write(ConstantsProto.QuotaController.MAX_SESSION_COUNT_WORKING,
@@ -2375,8 +2454,8 @@ public final class QuotaController extends StateController {
MAX_SESSION_COUNT_FREQUENT);
proto.write(ConstantsProto.QuotaController.MAX_SESSION_COUNT_RARE,
MAX_SESSION_COUNT_RARE);
- proto.write(ConstantsProto.QuotaController.MAX_SESSION_COUNT_PER_ALLOWED_TIME,
- MAX_SESSION_COUNT_PER_ALLOWED_TIME);
+ proto.write(ConstantsProto.QuotaController.MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW,
+ MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW);
proto.write(ConstantsProto.QuotaController.TIMING_SESSION_COALESCING_DURATION_MS,
TIMING_SESSION_COALESCING_DURATION_MS);
proto.end(qcToken);
@@ -2431,18 +2510,23 @@ public final class QuotaController extends StateController {
}
@VisibleForTesting
- int getMaxJobCountPerAllowedTime() {
- return mMaxJobCountPerAllowedTime;
+ int getMaxJobCountPerRateLimitingWindow() {
+ return mMaxJobCountPerRateLimitingWindow;
}
@VisibleForTesting
- long getTimingSessionCoalescingDurationMs() {
- return mTimingSessionCoalescingDurationMs;
+ int getMaxSessionCountPerRateLimitingWindow() {
+ return mMaxSessionCountPerRateLimitingWindow;
}
@VisibleForTesting
- int getMaxSessionCountPerAllowedTime() {
- return mMaxSessionCountPerAllowedTime;
+ long getRateLimitingWindowMs() {
+ return mRateLimitingWindowMs;
+ }
+
+ @VisibleForTesting
+ long getTimingSessionCoalescingDurationMs() {
+ return mTimingSessionCoalescingDurationMs;
}
@VisibleForTesting
@@ -2659,6 +2743,12 @@ public final class QuotaController extends StateController {
StateControllerProto.QuotaController.ExecutionStats.WINDOW_SIZE_MS,
es.windowSizeMs);
proto.write(
+ StateControllerProto.QuotaController.ExecutionStats.JOB_COUNT_LIMIT,
+ es.jobCountLimit);
+ proto.write(
+ StateControllerProto.QuotaController.ExecutionStats.SESSION_COUNT_LIMIT,
+ es.sessionCountLimit);
+ proto.write(
StateControllerProto.QuotaController.ExecutionStats.EXECUTION_TIME_IN_WINDOW_MS,
es.executionTimeInWindowMs);
proto.write(
@@ -2674,20 +2764,20 @@ public final class QuotaController extends StateController {
StateControllerProto.QuotaController.ExecutionStats.SESSION_COUNT_IN_WINDOW,
es.sessionCountInWindow);
proto.write(
- StateControllerProto.QuotaController.ExecutionStats.QUOTA_CUTOFF_TIME_ELAPSED,
- es.quotaCutoffTimeElapsed);
+ StateControllerProto.QuotaController.ExecutionStats.IN_QUOTA_TIME_ELAPSED,
+ es.inQuotaTimeElapsed);
proto.write(
StateControllerProto.QuotaController.ExecutionStats.JOB_COUNT_EXPIRATION_TIME_ELAPSED,
- es.jobCountExpirationTimeElapsed);
+ es.jobRateLimitExpirationTimeElapsed);
proto.write(
- StateControllerProto.QuotaController.ExecutionStats.JOB_COUNT_IN_ALLOWED_TIME,
- es.jobCountInAllowedTime);
+ StateControllerProto.QuotaController.ExecutionStats.JOB_COUNT_IN_RATE_LIMITING_WINDOW,
+ es.jobCountInRateLimitingWindow);
proto.write(
StateControllerProto.QuotaController.ExecutionStats.SESSION_COUNT_EXPIRATION_TIME_ELAPSED,
- es.sessionCountExpirationTimeElapsed);
+ es.sessionRateLimitExpirationTimeElapsed);
proto.write(
- StateControllerProto.QuotaController.ExecutionStats.SESSION_COUNT_IN_ALLOWED_TIME,
- es.sessionCountInAllowedTime);
+ StateControllerProto.QuotaController.ExecutionStats.SESSION_COUNT_IN_RATE_LIMITING_WINDOW,
+ es.sessionCountInRateLimitingWindow);
proto.end(esToken);
}
}
diff --git a/services/core/java/com/android/server/location/GnssVisibilityControl.java b/services/core/java/com/android/server/location/GnssVisibilityControl.java
index 8d4ad7f30821..65bd5c6a14da 100644
--- a/services/core/java/com/android/server/location/GnssVisibilityControl.java
+++ b/services/core/java/com/android/server/location/GnssVisibilityControl.java
@@ -456,9 +456,8 @@ class GnssVisibilityControl {
final String proxyAppPkgName = nfwNotification.mProxyAppPackageName;
final ProxyAppState proxyAppState = mProxyAppsState.get(proxyAppPkgName);
final boolean isLocationRequestAccepted = nfwNotification.isRequestAccepted();
- final boolean isPermissionMismatched =
- (proxyAppState == null) ? isLocationRequestAccepted
- : (proxyAppState.mHasLocationPermission != isLocationRequestAccepted);
+ final boolean isPermissionMismatched = isPermissionMismatched(proxyAppState,
+ nfwNotification);
logEvent(nfwNotification, isPermissionMismatched);
if (!nfwNotification.isRequestAttributedToProxyApp()) {
@@ -506,14 +505,24 @@ class GnssVisibilityControl {
// Log proxy app permission mismatch between framework and GNSS HAL.
if (isPermissionMismatched) {
- Log.w(TAG, "Permission mismatch. Framework proxy app " + proxyAppPkgName
+ Log.w(TAG, "Permission mismatch. Proxy app " + proxyAppPkgName
+ " location permission is set to " + proxyAppState.mHasLocationPermission
+ + " and GNSS HAL enabled is set to " + mIsGpsEnabled
+ " but GNSS non-framework location access response type is "
+ nfwNotification.getResponseTypeAsString() + " for notification: "
+ nfwNotification);
}
}
+ private boolean isPermissionMismatched(ProxyAppState proxyAppState,
+ NfwNotification nfwNotification) {
+ // Non-framework non-emergency location requests must be accepted only when IGnss.hal
+ // is enabled and the proxy app has location permission.
+ final boolean isLocationRequestAccepted = nfwNotification.isRequestAccepted();
+ return (proxyAppState == null || !mIsGpsEnabled) ? isLocationRequestAccepted
+ : (proxyAppState.mHasLocationPermission != isLocationRequestAccepted);
+ }
+
private void showLocationIcon(ProxyAppState proxyAppState, NfwNotification nfwNotification,
int uid, String proxyAppPkgName) {
// If we receive a new NfwNotification before the location icon is turned off for the
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 19ff2c11d14c..6c34e1313f73 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -217,6 +217,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.internal.notification.SystemNotificationChannels;
+import com.android.internal.os.RoSystemProperties;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ConcurrentUtils;
@@ -1353,9 +1354,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mContext, 0, snoozeIntent, PendingIntent.FLAG_UPDATE_CURRENT));
final Intent viewIntent = buildViewDataUsageIntent(res, policy.template);
- builder.setContentIntent(PendingIntent.getActivity(
- mContext, 0, viewIntent, PendingIntent.FLAG_UPDATE_CURRENT));
-
+ // TODO: Resolve to single code path.
+ if (isHeadlessSystemUserBuild()) {
+ builder.setContentIntent(PendingIntent.getActivityAsUser(
+ mContext, 0, viewIntent, PendingIntent.FLAG_UPDATE_CURRENT,
+ /* options= */ null, UserHandle.CURRENT));
+ } else {
+ builder.setContentIntent(PendingIntent.getActivity(
+ mContext, 0, viewIntent, PendingIntent.FLAG_UPDATE_CURRENT));
+ }
break;
}
case TYPE_LIMIT: {
@@ -1375,8 +1382,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
builder.setSmallIcon(R.drawable.stat_notify_disabled_data);
final Intent intent = buildNetworkOverLimitIntent(res, policy.template);
- builder.setContentIntent(PendingIntent.getActivity(
- mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
+ // TODO: Resolve to single code path.
+ if (isHeadlessSystemUserBuild()) {
+ builder.setContentIntent(PendingIntent.getActivityAsUser(
+ mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT,
+ /* options= */ null, UserHandle.CURRENT));
+ } else {
+ builder.setContentIntent(PendingIntent.getActivity(
+ mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
+ }
break;
}
case TYPE_LIMIT_SNOOZED: {
@@ -1399,8 +1413,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
builder.setChannelId(SystemNotificationChannels.NETWORK_STATUS);
final Intent intent = buildViewDataUsageIntent(res, policy.template);
- builder.setContentIntent(PendingIntent.getActivity(
- mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
+ // TODO: Resolve to single code path.
+ if (isHeadlessSystemUserBuild()) {
+ builder.setContentIntent(PendingIntent.getActivityAsUser(
+ mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT,
+ /* options= */ null, UserHandle.CURRENT));
+ } else {
+ builder.setContentIntent(PendingIntent.getActivity(
+ mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
+ }
break;
}
case TYPE_RAPID: {
@@ -1419,8 +1440,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mContext, 0, snoozeIntent, PendingIntent.FLAG_UPDATE_CURRENT));
final Intent viewIntent = buildViewDataUsageIntent(res, policy.template);
- builder.setContentIntent(PendingIntent.getActivity(
- mContext, 0, viewIntent, PendingIntent.FLAG_UPDATE_CURRENT));
+ // TODO: Resolve to single code path.
+ if (isHeadlessSystemUserBuild()) {
+ builder.setContentIntent(PendingIntent.getActivityAsUser(
+ mContext, 0, viewIntent, PendingIntent.FLAG_UPDATE_CURRENT,
+ /* options= */ null, UserHandle.CURRENT));
+ } else {
+ builder.setContentIntent(PendingIntent.getActivity(
+ mContext, 0, viewIntent, PendingIntent.FLAG_UPDATE_CURRENT));
+ }
break;
}
default: {
@@ -5264,6 +5292,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
return (bundle != null) ? bundle.getBoolean(key, defaultValue) : defaultValue;
}
+ private static boolean isHeadlessSystemUserBuild() {
+ return RoSystemProperties.MULTIUSER_HEADLESS_SYSTEM_USER;
+ }
+
private class NotificationId {
private final String mTag;
private final int mId;
diff --git a/services/core/java/com/android/server/net/NetworkStatsAccess.java b/services/core/java/com/android/server/net/NetworkStatsAccess.java
index cebc47217831..7c1c1c7ce403 100644
--- a/services/core/java/com/android/server/net/NetworkStatsAccess.java
+++ b/services/core/java/com/android/server/net/NetworkStatsAccess.java
@@ -109,7 +109,7 @@ public final class NetworkStatsAccess {
final TelephonyManager tm = (TelephonyManager)
context.getSystemService(Context.TELEPHONY_SERVICE);
boolean hasCarrierPrivileges = tm != null &&
- tm.checkCarrierPrivilegesForPackage(callingPackage) ==
+ tm.checkCarrierPrivilegesForPackageAnyPhone(callingPackage) ==
TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
boolean isDeviceOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid,
DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
diff --git a/services/core/java/com/android/server/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java
index 69efd02dea9c..473cc97b7edc 100644
--- a/services/core/java/com/android/server/net/NetworkStatsFactory.java
+++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java
@@ -263,6 +263,10 @@ public class NetworkStatsFactory {
return stats;
}
+ /**
+ * @deprecated Use NetworkStatsService#getDetailedUidStats which also accounts for
+ * VPN traffic
+ */
public NetworkStats readNetworkStatsDetail() throws IOException {
return readNetworkStatsDetail(UID_ALL, null, TAG_ALL, null);
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsRecorder.java b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
index a2e7e0cae96b..bdff50053fae 100644
--- a/services/core/java/com/android/server/net/NetworkStatsRecorder.java
+++ b/services/core/java/com/android/server/net/NetworkStatsRecorder.java
@@ -41,10 +41,10 @@ import com.android.internal.net.VpnInfo;
import com.android.internal.util.FileRotator;
import com.android.internal.util.IndentingPrintWriter;
-import libcore.io.IoUtils;
-
import com.google.android.collect.Sets;
+import libcore.io.IoUtils;
+
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
@@ -234,7 +234,7 @@ public class NetworkStatsRecorder {
if (vpnArray != null) {
for (VpnInfo info : vpnArray) {
- delta.migrateTun(info.ownerUid, info.vpnIface, info.primaryUnderlyingIface);
+ delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces);
}
}
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index f34ace55a72e..a13368ff9de4 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -293,6 +293,22 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
/** Data layer operation counters for splicing into other structures. */
private NetworkStats mUidOperations = new NetworkStats(0L, 10);
+ /**
+ * Snapshot containing most recent network stats for all UIDs across all interfaces and tags
+ * since boot.
+ *
+ * <p>Maintains migrated VPN stats which are result of performing TUN migration on {@link
+ * #mLastUidDetailSnapshot}.
+ */
+ @GuardedBy("mStatsLock")
+ private NetworkStats mTunAdjustedStats;
+ /**
+ * Used by {@link #mTunAdjustedStats} to migrate VPN traffic over delta between this snapshot
+ * and latest snapshot.
+ */
+ @GuardedBy("mStatsLock")
+ private NetworkStats mLastUidDetailSnapshot;
+
/** Must be set in factory by calling #setHandler. */
private Handler mHandler;
private Handler.Callback mHandlerCallback;
@@ -812,15 +828,39 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
@Override
public NetworkStats getDetailedUidStats(String[] requiredIfaces) {
try {
+ // Get the latest snapshot from NetworkStatsFactory.
+ // TODO: Querying for INTERFACES_ALL may incur performance penalty. Consider restricting
+ // this to limited set of ifaces.
+ NetworkStats uidDetailStats = getNetworkStatsUidDetail(INTERFACES_ALL);
+
+ // Migrate traffic from VPN UID over delta and update mTunAdjustedStats.
+ NetworkStats result;
+ synchronized (mStatsLock) {
+ migrateTunTraffic(uidDetailStats, mVpnInfos);
+ result = mTunAdjustedStats.clone();
+ }
+
+ // Apply filter based on ifacesToQuery.
final String[] ifacesToQuery =
NetworkStatsFactory.augmentWithStackedInterfaces(requiredIfaces);
- return getNetworkStatsUidDetail(ifacesToQuery);
+ result.filter(UID_ALL, ifacesToQuery, TAG_ALL);
+ return result;
} catch (RemoteException e) {
Log.wtf(TAG, "Error compiling UID stats", e);
return new NetworkStats(0L, 0);
}
}
+ @VisibleForTesting
+ NetworkStats getTunAdjustedStats() {
+ synchronized (mStatsLock) {
+ if (mTunAdjustedStats == null) {
+ return null;
+ }
+ return mTunAdjustedStats.clone();
+ }
+ }
+
@Override
public String[] getMobileIfaces() {
return mMobileIfaces;
@@ -1295,6 +1335,34 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
// a race condition between the service handler thread and the observer's
mStatsObservers.updateStats(xtSnapshot, uidSnapshot, new ArrayMap<>(mActiveIfaces),
new ArrayMap<>(mActiveUidIfaces), vpnArray, currentTime);
+
+ migrateTunTraffic(uidSnapshot, vpnArray);
+ }
+
+ /**
+ * Updates {@link #mTunAdjustedStats} with the delta containing traffic migrated off of VPNs.
+ */
+ @GuardedBy("mStatsLock")
+ private void migrateTunTraffic(NetworkStats uidDetailStats, VpnInfo[] vpnInfoArray) {
+ if (mTunAdjustedStats == null) {
+ // Either device booted or system server restarted, hence traffic cannot be migrated
+ // correctly without knowing the past state of VPN's underlying networks.
+ mTunAdjustedStats = uidDetailStats;
+ mLastUidDetailSnapshot = uidDetailStats;
+ return;
+ }
+ // Migrate delta traffic from VPN to other apps.
+ NetworkStats delta = uidDetailStats.subtract(mLastUidDetailSnapshot);
+ for (VpnInfo info : vpnInfoArray) {
+ delta.migrateTun(info.ownerUid, info.vpnIface, info.underlyingIfaces);
+ }
+ // Filter out debug entries as that may lead to over counting.
+ delta.filterDebugEntries();
+ // Update #mTunAdjustedStats with migrated delta.
+ mTunAdjustedStats.combineAllValues(delta);
+ mTunAdjustedStats.setElapsedRealtime(uidDetailStats.getElapsedRealtime());
+ // Update last snapshot.
+ mLastUidDetailSnapshot = uidDetailStats;
}
/**
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 1160e33aca25..8485f46aefd4 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -283,7 +283,7 @@ public class NotificationManagerService extends SystemService {
static final boolean DEBUG_INTERRUPTIVENESS = SystemProperties.getBoolean(
"debug.notification.interruptiveness", false);
- static final int MAX_PACKAGE_NOTIFICATIONS = 50;
+ static final int MAX_PACKAGE_NOTIFICATIONS = 25;
static final float DEFAULT_MAX_NOTIFICATION_ENQUEUE_RATE = 5f;
// message codes
@@ -1036,19 +1036,12 @@ public class NotificationManagerService extends SystemService {
final StatusBarNotification n = r.sbn;
final int callingUid = n.getUid();
final String pkg = n.getPackageName();
- final boolean wasBubble = r.getNotification().isBubbleNotification();
if (isBubble && isNotificationAppropriateToBubble(r, pkg, callingUid,
null /* oldEntry */)) {
r.getNotification().flags |= FLAG_BUBBLE;
} else {
r.getNotification().flags &= ~FLAG_BUBBLE;
}
- if (wasBubble != r.getNotification().isBubbleNotification()) {
- // Add the "alert only once" flag so that the notification won't HUN
- // unnecessarily just because the bubble flag was changed.
- r.getNotification().flags |= FLAG_ONLY_ALERT_ONCE;
- mListeners.notifyPostedLocked(r, r);
- }
}
}
}
@@ -2643,18 +2636,25 @@ public class NotificationManagerService extends SystemService {
ParceledListSlice channelsList) {
List<NotificationChannel> channels = channelsList.getList();
final int channelsSize = channels.size();
+ boolean needsPolicyFileChange = false;
for (int i = 0; i < channelsSize; i++) {
final NotificationChannel channel = channels.get(i);
Preconditions.checkNotNull(channel, "channel in list is null");
- mPreferencesHelper.createNotificationChannel(pkg, uid, channel,
- true /* fromTargetApp */, mConditionProviders.isPackageOrComponentAllowed(
+ needsPolicyFileChange = mPreferencesHelper.createNotificationChannel(pkg, uid,
+ channel, true /* fromTargetApp */,
+ mConditionProviders.isPackageOrComponentAllowed(
pkg, UserHandle.getUserId(uid)));
- mListeners.notifyNotificationChannelChanged(pkg,
- UserHandle.getUserHandleForUid(uid),
- mPreferencesHelper.getNotificationChannel(pkg, uid, channel.getId(), false),
- NOTIFICATION_CHANNEL_OR_GROUP_ADDED);
+ if (needsPolicyFileChange) {
+ mListeners.notifyNotificationChannelChanged(pkg,
+ UserHandle.getUserHandleForUid(uid),
+ mPreferencesHelper.getNotificationChannel(pkg, uid, channel.getId(),
+ false),
+ NOTIFICATION_CHANNEL_OR_GROUP_ADDED);
+ }
+ }
+ if (needsPolicyFileChange) {
+ handleSavePolicyFile();
}
- handleSavePolicyFile();
}
@Override
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 4ed24ec7971b..c2e559a8a96b 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -174,6 +174,7 @@ public final class NotificationRecord {
private ArrayList<CharSequence> mSmartReplies;
private final List<Adjustment> mAdjustments;
+ private String mAdjustmentIssuer;
private final NotificationStats mStats;
private int mUserSentiment;
private boolean mIsInterruptive;
@@ -684,6 +685,9 @@ public final class NotificationRecord {
importance = Math.min(IMPORTANCE_HIGH, importance);
setAssistantImportance(importance);
}
+ if (!signals.isEmpty() && adjustment.getIssuer() != null) {
+ mAdjustmentIssuer = adjustment.getIssuer();
+ }
}
// We have now gotten all the information out of the adjustments and can forget them.
mAdjustments.clear();
@@ -1297,6 +1301,13 @@ public final class NotificationRecord {
lm.addTaggedData(MetricsEvent.FIELD_NOTIFICATION_IMPORTANCE_ASST,
mAssistantImportance);
}
+ // Log the issuer of any adjustments that may have affected this notification. We only log
+ // the hash here as NotificationItem events are frequent, and the number of NAS
+ // implementations (and hence the chance of collisions) is low.
+ if (mAdjustmentIssuer != null) {
+ lm.addTaggedData(MetricsEvent.FIELD_NOTIFICATION_ASSISTANT_SERVICE_HASH,
+ mAdjustmentIssuer.hashCode());
+ }
return lm;
}
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 5956c65defef..1c0ac167c26b 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -615,12 +615,13 @@ public class PreferencesHelper implements RankingConfig {
}
@Override
- public void createNotificationChannel(String pkg, int uid, NotificationChannel channel,
+ public boolean createNotificationChannel(String pkg, int uid, NotificationChannel channel,
boolean fromTargetApp, boolean hasDndAccess) {
Preconditions.checkNotNull(pkg);
Preconditions.checkNotNull(channel);
Preconditions.checkNotNull(channel.getId());
Preconditions.checkArgument(!TextUtils.isEmpty(channel.getName()));
+ boolean needsPolicyFileChange = false;
synchronized (mPackagePreferences) {
PackagePreferences r = getOrCreatePackagePreferencesLocked(pkg, uid);
if (r == null) {
@@ -637,17 +638,28 @@ public class PreferencesHelper implements RankingConfig {
if (existing != null && fromTargetApp) {
if (existing.isDeleted()) {
existing.setDeleted(false);
+ needsPolicyFileChange = true;
// log a resurrected channel as if it's new again
MetricsLogger.action(getChannelLog(channel, pkg).setType(
com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_OPEN));
}
- existing.setName(channel.getName().toString());
- existing.setDescription(channel.getDescription());
- existing.setBlockableSystem(channel.isBlockableSystem());
- if (existing.getGroup() == null) {
+ if (!Objects.equals(channel.getName().toString(), existing.getName().toString())) {
+ existing.setName(channel.getName().toString());
+ needsPolicyFileChange = true;
+ }
+ if (!Objects.equals(channel.getDescription(), existing.getDescription())) {
+ existing.setDescription(channel.getDescription());
+ needsPolicyFileChange = true;
+ }
+ if (channel.isBlockableSystem() != existing.isBlockableSystem()) {
+ existing.setBlockableSystem(channel.isBlockableSystem());
+ needsPolicyFileChange = true;
+ }
+ if (channel.getGroup() != null && existing.getGroup() == null) {
existing.setGroup(channel.getGroup());
+ needsPolicyFileChange = true;
}
// Apps are allowed to downgrade channel importance if the user has not changed any
@@ -656,23 +668,30 @@ public class PreferencesHelper implements RankingConfig {
if (existing.getUserLockedFields() == 0 &&
channel.getImportance() < existing.getImportance()) {
existing.setImportance(channel.getImportance());
+ needsPolicyFileChange = true;
}
// system apps and dnd access apps can bypass dnd if the user hasn't changed any
// fields on the channel yet
if (existing.getUserLockedFields() == 0 && hasDndAccess) {
boolean bypassDnd = channel.canBypassDnd();
- existing.setBypassDnd(bypassDnd);
+ if (bypassDnd != existing.canBypassDnd()) {
+ existing.setBypassDnd(bypassDnd);
+ needsPolicyFileChange = true;
- if (bypassDnd != mAreChannelsBypassingDnd
- || previousExistingImportance != existing.getImportance()) {
- updateChannelsBypassingDnd(mContext.getUserId());
+ if (bypassDnd != mAreChannelsBypassingDnd
+ || previousExistingImportance != existing.getImportance()) {
+ updateChannelsBypassingDnd(mContext.getUserId());
+ }
}
}
updateConfig();
- return;
+ return needsPolicyFileChange;
}
+
+ needsPolicyFileChange = true;
+
if (channel.getImportance() < IMPORTANCE_NONE
|| channel.getImportance() > NotificationManager.IMPORTANCE_MAX) {
throw new IllegalArgumentException("Invalid importance level");
@@ -708,6 +727,8 @@ public class PreferencesHelper implements RankingConfig {
MetricsLogger.action(getChannelLog(channel, pkg).setType(
com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_OPEN));
}
+
+ return needsPolicyFileChange;
}
void clearLockedFieldsLocked(NotificationChannel channel) {
diff --git a/services/core/java/com/android/server/notification/RankingConfig.java b/services/core/java/com/android/server/notification/RankingConfig.java
index 72502acd6560..5de00e43a05d 100644
--- a/services/core/java/com/android/server/notification/RankingConfig.java
+++ b/services/core/java/com/android/server/notification/RankingConfig.java
@@ -39,7 +39,7 @@ public interface RankingConfig {
boolean fromTargetApp);
ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroups(String pkg,
int uid, boolean includeDeleted, boolean includeNonGrouped, boolean includeEmpty);
- void createNotificationChannel(String pkg, int uid, NotificationChannel channel,
+ boolean createNotificationChannel(String pkg, int uid, NotificationChannel channel,
boolean fromTargetApp, boolean hasDndAccess);
void updateNotificationChannel(String pkg, int uid, NotificationChannel channel, boolean fromUser);
NotificationChannel getNotificationChannel(String pkg, int uid, String channelId, boolean includeDeleted);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 2a61feea6349..a1162373c16f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -14757,7 +14757,7 @@ public class PackageManagerService extends IPackageManager.Stub
if (ps != null) {
try {
- rm.restoreUserData(packageName, installedUsers, appId, ceDataInode,
+ rm.snapshotAndRestoreUserData(packageName, installedUsers, appId, ceDataInode,
seInfo, token);
} catch (RemoteException re) {
// Cannot happen, the RollbackManager is hosted in the same process.
@@ -15032,24 +15032,26 @@ public class PackageManagerService extends IPackageManager.Stub
void tryProcessInstallRequest(InstallArgs args, int currentStatus) {
mCurrentState.put(args, currentStatus);
- boolean success = true;
if (mCurrentState.size() != mChildParams.size()) {
return;
}
+ int completeStatus = PackageManager.INSTALL_SUCCEEDED;
for (Integer status : mCurrentState.values()) {
if (status == PackageManager.INSTALL_UNKNOWN) {
return;
} else if (status != PackageManager.INSTALL_SUCCEEDED) {
- success = false;
+ completeStatus = status;
break;
}
}
final List<InstallRequest> installRequests = new ArrayList<>(mCurrentState.size());
for (Map.Entry<InstallArgs, Integer> entry : mCurrentState.entrySet()) {
installRequests.add(new InstallRequest(entry.getKey(),
- createPackageInstalledInfo(entry.getValue())));
+ createPackageInstalledInfo(completeStatus)));
}
- processInstallRequestsAsync(success, installRequests);
+ processInstallRequestsAsync(
+ completeStatus == PackageManager.INSTALL_SUCCEEDED,
+ installRequests);
}
}
@@ -17080,6 +17082,13 @@ public class PackageManagerService extends IPackageManager.Stub
cleanUpAppIdCreation(result);
}
}
+ // TODO(patb): create a more descriptive reason than unknown in future release
+ // mark all non-failure installs as UNKNOWN so we do not treat them as success
+ for (InstallRequest request : requests) {
+ if (request.installResult.returnCode == PackageManager.INSTALL_SUCCEEDED) {
+ request.installResult.returnCode = PackageManager.INSTALL_UNKNOWN;
+ }
+ }
}
for (PrepareResult result : prepareResults.values()) {
if (result.freezer != null) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index f5c8049dcb25..81de8e263299 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -2496,9 +2496,9 @@ class PackageManagerShellCommand extends ShellCommand {
default:
throw new IllegalArgumentException("Unknown option " + opt);
}
- if (replaceExisting) {
- sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
- }
+ }
+ if (replaceExisting) {
+ sessionParams.installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;
}
return params;
}
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index eec4b70880a5..d6e87aab35fe 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -674,9 +674,10 @@ class ShortcutPackage extends ShortcutPackageItem {
return new ArrayList<>();
}
- // Get the list of all dynamic shortcuts in this package
+ // Get the list of all dynamic shortcuts in this package.
final ArrayList<ShortcutInfo> shortcuts = new ArrayList<>();
- findAll(shortcuts, ShortcutInfo::isDynamicVisible, ShortcutInfo.CLONE_REMOVE_FOR_LAUNCHER);
+ findAll(shortcuts, ShortcutInfo::isDynamicVisible,
+ ShortcutInfo.CLONE_REMOVE_FOR_APP_PREDICTION);
final List<ShortcutManager.ShareShortcutInfo> result = new ArrayList<>();
for (int i = 0; i < shortcuts.size(); i++) {
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 24bf18de13c8..950450cdbeb5 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -36,7 +36,6 @@ import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
import android.content.pm.ParceledListSlice;
import android.content.pm.Signature;
import android.content.rollback.IRollbackManager;
-import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
@@ -116,12 +115,9 @@ public class StagingManager {
final PackageInfo packageInfo = mApexManager.getPackageInfoForApexName(packageName);
if (packageInfo == null) {
- // Only allow installing new apexes if on a debuggable build.
- if (!Build.IS_DEBUGGABLE) {
- Slog.w(TAG, "Attempted to install new apex " + packageName + " on user build");
- return false;
- }
- return true;
+ // Don't allow installation of new APEX.
+ Slog.e(TAG, "Attempted to install a new apex " + packageName + ". Rejecting");
+ return false;
}
final SigningDetails existingSigningDetails;
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 267fbf030619..beb72686d6ce 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1173,6 +1173,14 @@ public class PermissionManagerService {
}
}
+ if (hardRestricted && !restrictionExempt
+ && (flags & FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
+ // Applying a hard restriction implies revoking it. This might
+ // lead to a system-fixed, revoked permission.
+ flags &= ~FLAG_PERMISSION_SYSTEM_FIXED;
+ wasChanged = true;
+ }
+
if (wasChanged) {
updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
}
diff --git a/services/core/java/com/android/server/power/AttentionDetector.java b/services/core/java/com/android/server/power/AttentionDetector.java
index 14f1196ab3a2..ed11fd45ec39 100644
--- a/services/core/java/com/android/server/power/AttentionDetector.java
+++ b/services/core/java/com/android/server/power/AttentionDetector.java
@@ -19,6 +19,8 @@ package com.android.server.power;
import static android.provider.Settings.System.ADAPTIVE_SLEEP;
import android.Manifest;
+import android.app.ActivityManager;
+import android.app.SynchronousUserSwitchObserver;
import android.attention.AttentionManagerInternal;
import android.attention.AttentionManagerInternal.AttentionCallbackInternal;
import android.content.ContentResolver;
@@ -28,6 +30,7 @@ import android.database.ContentObserver;
import android.os.Handler;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
+import android.os.RemoteException;
import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
@@ -54,6 +57,8 @@ public class AttentionDetector {
private static final String TAG = "AttentionDetector";
private static final boolean DEBUG = false;
+ private Context mContext;
+
private boolean mIsSettingEnabled;
/**
@@ -132,6 +137,7 @@ public class AttentionDetector {
}
public void systemReady(Context context) {
+ mContext = context;
updateEnabledFromSettings(context);
mPackageManager = context.getPackageManager();
mContentResolver = context.getContentResolver();
@@ -141,6 +147,13 @@ public class AttentionDetector {
mMaxAttentionApiTimeoutMillis = context.getResources().getInteger(
com.android.internal.R.integer.config_attentionApiTimeout);
+ try {
+ final UserSwitchObserver observer = new UserSwitchObserver();
+ ActivityManager.getService().registerUserSwitchObserver(observer, TAG);
+ } catch (RemoteException e) {
+ // Shouldn't happen since in-process.
+ }
+
context.getContentResolver().registerContentObserver(Settings.System.getUriFor(
Settings.System.ADAPTIVE_SLEEP),
false, new ContentObserver(new Handler()) {
@@ -326,4 +339,11 @@ public class AttentionDetector {
mRequested.set(false);
}
}
+
+ private final class UserSwitchObserver extends SynchronousUserSwitchObserver {
+ @Override
+ public void onUserSwitching(int newUserId) throws RemoteException {
+ updateEnabledFromSettings(mContext);
+ }
+ }
}
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index e2bbb2dc2dc5..cfd3ae6ef594 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -2085,7 +2085,8 @@ public final class PowerManagerService extends SystemService
nextTimeout = -1;
}
- if ((mUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0) {
+ if ((mUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0
+ && (mWakeLockSummary & WAKE_LOCK_STAY_AWAKE) == 0) {
nextTimeout = mAttentionDetector.updateUserActivity(nextTimeout);
}
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 9a2778dbf535..301f65061045 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -923,8 +923,8 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
}
if (rd != null) {
- // This is the apk session for a staged session. We have already
- // backed up the apks, we just need to do user data backup.
+ // This is the apk session for a staged session. We do not need to create a new rollback
+ // for this session.
PackageParser.PackageLite newPackage = null;
try {
newPackage = PackageParser.parsePackageLite(
@@ -937,8 +937,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
for (PackageRollbackInfo info : rd.info.getPackages()) {
if (info.getPackageName().equals(packageName)) {
info.getInstalledUsers().addAll(IntArray.wrap(installedUsers));
- mAppDataRollbackHelper.snapshotAppData(rd.info.getRollbackId(), info);
- saveRollbackData(rd);
return true;
}
}
@@ -959,8 +957,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
}
newRollback.addToken(token);
- return enableRollbackForPackageSession(newRollback.data, packageSession,
- installedUsers, /* snapshotUserData*/ true);
+ return enableRollbackForPackageSession(newRollback.data, packageSession, installedUsers);
}
/**
@@ -971,8 +968,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
* @return true on success, false on failure.
*/
private boolean enableRollbackForPackageSession(RollbackData data,
- PackageInstaller.SessionInfo session, @NonNull int[] installedUsers,
- boolean snapshotUserData) {
+ PackageInstaller.SessionInfo session, @NonNull int[] installedUsers) {
// TODO: Don't attempt to enable rollback for split installs.
final int installFlags = session.installFlags;
if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) {
@@ -1033,10 +1029,6 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
isApex, IntArray.wrap(installedUsers),
new SparseLongArray() /* ceSnapshotInodes */);
- if (snapshotUserData && !isApex) {
- mAppDataRollbackHelper.snapshotAppData(data.info.getRollbackId(), packageRollbackInfo);
- }
-
try {
ApplicationInfo appInfo = pkgInfo.applicationInfo;
RollbackStore.backupPackageCodePath(data, packageName, appInfo.sourceDir);
@@ -1057,13 +1049,15 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
}
@Override
- public void restoreUserData(String packageName, int[] userIds, int appId, long ceDataInode,
- String seInfo, int token) {
+ public void snapshotAndRestoreUserData(String packageName, int[] userIds, int appId,
+ long ceDataInode, String seInfo, int token) {
if (Binder.getCallingUid() != Process.SYSTEM_UID) {
- throw new SecurityException("restoreUserData may only be called by the system.");
+ throw new SecurityException(
+ "snapshotAndRestoreUserData may only be called by the system.");
}
getHandler().post(() -> {
+ snapshotUserDataInternal(packageName);
restoreUserDataInternal(packageName, userIds, appId, ceDataInode, seInfo, token);
final PackageManagerInternal pmi = LocalServices.getService(
PackageManagerInternal.class);
@@ -1071,6 +1065,38 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
});
}
+ private void snapshotUserDataInternal(String packageName) {
+ synchronized (mLock) {
+ // staged installs
+ ensureRollbackDataLoadedLocked();
+ for (int i = 0; i < mRollbacks.size(); i++) {
+ RollbackData data = mRollbacks.get(i);
+ if (data.state != RollbackData.ROLLBACK_STATE_ENABLING) {
+ continue;
+ }
+
+ for (PackageRollbackInfo info : data.info.getPackages()) {
+ if (info.getPackageName().equals(packageName)) {
+ mAppDataRollbackHelper.snapshotAppData(data.info.getRollbackId(), info);
+ saveRollbackData(data);
+ return;
+ }
+ }
+ }
+ // non-staged installs
+ PackageRollbackInfo info;
+ for (NewRollback rollback : mNewRollbacks) {
+ info = getPackageRollbackInfo(rollback.data, packageName);
+ if (info != null) {
+ mAppDataRollbackHelper.snapshotAppData(rollback.data.info.getRollbackId(),
+ info);
+ saveRollbackData(rollback.data);
+ return;
+ }
+ }
+ }
+ }
+
private void restoreUserDataInternal(String packageName, int[] userIds, int appId,
long ceDataInode, String seInfo, int token) {
PackageRollbackInfo info = null;
@@ -1130,7 +1156,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
if (!session.isMultiPackage()) {
if (!enableRollbackForPackageSession(newRollback.data, session,
- new int[0], /* snapshotUserData */ false)) {
+ new int[0])) {
Log.e(TAG, "Unable to enable rollback for session: " + sessionId);
result.offer(false);
return;
@@ -1145,7 +1171,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
return;
}
if (!enableRollbackForPackageSession(newRollback.data, childSession,
- new int[0], /* snapshotUserData */ false)) {
+ new int[0])) {
Log.e(TAG, "Unable to enable rollback for session: " + sessionId);
result.offer(false);
return;
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 112104d073b0..828f79007b95 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -719,21 +719,6 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
// Ensure state for the current user is applied, even if passed a non-current user.
final int net1 = gatherDisableActionsLocked(mCurrentUserId, 1);
final int net2 = gatherDisableActionsLocked(mCurrentUserId, 2);
-
- // TODO(b/113914868): investigation log for disappearing home button
- if (whichFlag == 1 && pkg != null && pkg.contains("systemui")) {
- String disabledData = "{ ";
- for (int i = 0; i < mDisableRecords.size(); i++) {
- DisableRecord tok = mDisableRecords.get(i);
- disabledData += " ([" + i + "] " + tok + "), ";
- }
- disabledData += " }";
- final UiState state = getUiState(displayId);
-
- Log.d(TAG, "disabledlocked (b/113914868): displayId=" + displayId + ", net1=" + net1
- + ", mDisabled1=" + state.mDisabled1 + ", token=" + token
- + ", mDisableRecords=" + mDisableRecords.size() + " => " + disabledData);
- }
final UiState state = getUiState(displayId);
if (!state.disableEquals(net1, net2)) {
state.setDisabled(net1, net2);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarShellCommand.java b/services/core/java/com/android/server/statusbar/StatusBarShellCommand.java
index b12129835ca1..d7f86cd65ae9 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarShellCommand.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarShellCommand.java
@@ -161,7 +161,15 @@ public class StatusBarShellCommand extends ShellCommand {
case "statusbar-expansion":
info.setStatusBarExpansionDisabled(true);
break;
-
+ case "system-icons":
+ info.setSystemIconsDisabled(true);
+ break;
+ case "clock":
+ info.setClockDisabled(true);
+ break;
+ case "notification-icons":
+ info.setNotificationIconsDisabled(true);
+ break;
default:
break;
}
@@ -221,6 +229,9 @@ public class StatusBarShellCommand extends ShellCommand {
pw.println(" recents - disable recents/overview");
pw.println(" notification-peek - disable notification peeking");
pw.println(" statusbar-expansion - disable status bar expansion");
+ pw.println(" system-icons - disable system icons appearing in status bar");
+ pw.println(" clock - disable clock appearing in status bar");
+ pw.println(" notification-icons - disable notification icons from status bar");
pw.println("");
}
diff --git a/services/core/java/com/android/server/telecom/TelecomLoaderService.java b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
index e65eae0ab156..54369ca5c367 100644
--- a/services/core/java/com/android/server/telecom/TelecomLoaderService.java
+++ b/services/core/java/com/android/server/telecom/TelecomLoaderService.java
@@ -16,21 +16,17 @@
package com.android.server.telecom;
+import android.app.role.RoleManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.Handler;
import android.os.IBinder;
-import android.os.Looper;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
-import android.provider.Settings;
import android.telecom.DefaultDialerManager;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
@@ -221,19 +217,10 @@ public class TelecomLoaderService extends SystemService {
private void registerDefaultAppNotifier() {
final DefaultPermissionGrantPolicy permissionPolicy = getDefaultPermissionGrantPolicy();
// Notify the package manager on default app changes
- final Uri defaultDialerAppUri = Settings.Secure.getUriFor(
- Settings.Secure.DIALER_DEFAULT_APPLICATION);
- ContentObserver contentObserver = new ContentObserver(
- new Handler(Looper.getMainLooper())) {
- @Override
- public void onChange(boolean selfChange, Uri uri, int userId) {
- if (defaultDialerAppUri.equals(uri)) {
- updateSimCallManagerPermissions(permissionPolicy, userId);
- }
- }
- };
- mContext.getContentResolver().registerContentObserver(defaultDialerAppUri,
- false, contentObserver, UserHandle.USER_ALL);
+ final RoleManager roleManager = mContext.getSystemService(RoleManager.class);
+ roleManager.addOnRoleHoldersChangedListenerAsUser(mContext.getMainExecutor(),
+ (roleName, user) -> updateSimCallManagerPermissions(permissionPolicy,
+ user.getIdentifier()), UserHandle.ALL);
}
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 3a390536b438..a2eb40b0c6fa 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -518,8 +518,11 @@ public class TrustManagerService extends SystemService {
agentInfo = mActiveAgents.valueAt(index);
}
- boolean directUnlock = resolveInfo.serviceInfo.directBootAware
- && agentInfo.settings.canUnlockProfile;
+ boolean directUnlock = false;
+ if (agentInfo.settings != null) {
+ directUnlock = resolveInfo.serviceInfo.directBootAware
+ && agentInfo.settings.canUnlockProfile;
+ }
if (directUnlock) {
if (DEBUG) Slog.d(TAG, "refreshAgentList: trustagent " + name
diff --git a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
index 476a27309f7e..165055ac828c 100644
--- a/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
+++ b/services/core/java/com/android/server/webkit/WebViewUpdateServiceImpl.java
@@ -19,6 +19,7 @@ import android.content.Context;
import android.content.pm.PackageInfo;
import android.os.AsyncTask;
import android.os.UserHandle;
+import android.util.Slog;
import android.webkit.WebViewProviderInfo;
import android.webkit.WebViewProviderResponse;
@@ -154,7 +155,10 @@ public class WebViewUpdateServiceImpl {
WebViewProviderInfo[] webviewProviders = mSystemInterface.getWebViewPackages();
WebViewProviderInfo fallbackProvider = getFallbackProvider(webviewProviders);
if (fallbackProvider != null) {
+ Slog.i(TAG, "One-time migration: enabling " + fallbackProvider.packageName);
mSystemInterface.enablePackageForAllUsers(mContext, fallbackProvider.packageName, true);
+ } else {
+ Slog.i(TAG, "Skipping one-time migration: no fallback provider");
}
mSystemInterface.enableFallbackLogic(false);
}
diff --git a/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java b/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java
index ad4624875d06..c56a9e2ac560 100644
--- a/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java
+++ b/services/core/java/com/android/server/wm/ActivityServiceConnectionsHolder.java
@@ -101,7 +101,13 @@ public class ActivityServiceConnectionsHolder<T> {
if (mConnections == null || mConnections.isEmpty()) {
return;
}
- mService.mH.post(() -> mService.mAmInternal.disconnectActivityFromServices(this));
+ // Capture and null out mConnections, to guarantee that we process
+ // disconnect of these specific connections exactly once even if
+ // we're racing with rapid activity lifecycle churn and this
+ // method is invoked more than once on this object.
+ final Object disc = mConnections;
+ mConnections = null;
+ mService.mH.post(() -> mService.mAmInternal.disconnectActivityFromServices(this, disc));
}
public void dump(PrintWriter pw, String prefix) {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 2e5b9fd55fc0..444e2190aba4 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -5867,8 +5867,10 @@ public class ActivityTaskManagerService extends IActivityTaskManager.Stub {
*/
Intent getSecondaryHomeIntent(String preferredPackage) {
final Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
- if (preferredPackage == null) {
- // Using the component stored in config if no package name.
+ final boolean useSystemProvidedLauncher = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_useSystemProvidedLauncherForSecondary);
+ if (preferredPackage == null || useSystemProvidedLauncher) {
+ // Using the component stored in config if no package name or forced.
final String secondaryHomeComponent = mContext.getResources().getString(
com.android.internal.R.string.config_secondaryHomeComponent);
intent.setComponent(ComponentName.unflattenFromString(secondaryHomeComponent));
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 3d7e50d91b08..cae7612e0fcc 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1733,17 +1733,13 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
return;
}
- if (mThumbnail == null && getTask() != null) {
- final TaskSnapshotController snapshotCtrl = mWmService.mTaskSnapshotController;
- final ArraySet<Task> tasks = new ArraySet<>();
- tasks.add(getTask());
- snapshotCtrl.snapshotTasks(tasks);
- snapshotCtrl.addSkipClosingAppSnapshotTasks(tasks);
- final ActivityManager.TaskSnapshot snapshot = snapshotCtrl.getSnapshot(
- getTask().mTaskId, getTask().mUserId, false /* restoreFromDisk */,
- false /* reducedResolution */);
+ Task task = getTask();
+ if (mThumbnail == null && task != null && !hasCommittedReparentToAnimationLeash()) {
+ SurfaceControl.ScreenshotGraphicBuffer snapshot =
+ mWmService.mTaskSnapshotController.createTaskSnapshot(
+ task, 1 /* scaleFraction */);
if (snapshot != null) {
- mThumbnail = new AppWindowThumbnail(t, this, snapshot.getSnapshot(),
+ mThumbnail = new AppWindowThumbnail(t, this, snapshot.getGraphicBuffer(),
true /* relative */);
}
}
@@ -2858,7 +2854,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
}
}
t.hide(mTransitChangeLeash);
- t.reparent(mTransitChangeLeash, null);
+ t.remove(mTransitChangeLeash);
mTransitChangeLeash = null;
if (cancel) {
onAnimationLeashLost(t);
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index e1dd3522a808..21f01ff38a0e 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -2720,9 +2720,9 @@ public class DisplayPolicy {
res.getBoolean(R.bool.config_navBarAlwaysShowOnSideEdgeGesture);
// This should calculate how much above the frame we accept gestures.
- mBottomGestureAdditionalInset = Math.max(0,
+ mBottomGestureAdditionalInset =
res.getDimensionPixelSize(R.dimen.navigation_bar_gesture_height)
- - getNavigationBarFrameHeight(portraitRotation, uiMode));
+ - getNavigationBarFrameHeight(portraitRotation, uiMode);
updateConfigurationAndScreenSizeDependentBehaviors();
mWindowOutsetBottom = ScreenShapeHelper.getWindowOutsetBottomPx(mContext.getResources());
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index c5b25664f762..434239f6ecf7 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -231,6 +231,11 @@ class RecentsAnimation implements RecentsAnimationCallbacks,
mService.mRootActivityContainer.sendPowerHintForLaunchEndIfNeeded();
}
+ // Once the target is shown, prevent spurious background app switches
+ if (reorderMode == REORDER_MOVE_TO_TOP) {
+ mService.stopAppSwitches();
+ }
+
mService.mH.post(
() -> mService.mAmInternal.setRunningRemoteAnimation(mCallingPid, false));
diff --git a/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java b/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java
index 854537b4618f..fb781b06f05f 100644
--- a/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java
+++ b/services/core/java/com/android/server/wm/SystemGesturesPointerEventListener.java
@@ -113,7 +113,12 @@ class SystemGesturesPointerEventListener implements PointerEventListener {
// statistics because it passes every touch event though a GestureDetector. By creating an
// anonymous subclass of GestureDetector, these statistics will be recorded with a unique
// source name that can be filtered.
- mGestureDetector = new GestureDetector(mContext, new FlingGestureDetector(), mHandler) {};
+
+ // GestureDetector would get a ViewConfiguration instance by context, that may also
+ // create a new WindowManagerImpl for the new display, and lock WindowManagerGlobal
+ // temporarily in the constructor that would make a deadlock.
+ mHandler.post(() -> mGestureDetector =
+ new GestureDetector(mContext, new FlingGestureDetector(), mHandler) {});
}
@Override
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 432ca3387ce7..181521850369 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -21,6 +21,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_SCREENSHOT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManager.TaskSnapshot;
@@ -241,16 +242,32 @@ class TaskSnapshotController {
return null;
}
- @Nullable private TaskSnapshot snapshotTask(Task task) {
- if (!mService.mPolicy.isScreenOn()) {
+ @Nullable
+ SurfaceControl.ScreenshotGraphicBuffer createTaskSnapshot(@NonNull Task task,
+ float scaleFraction) {
+ if (task.getSurfaceControl() == null) {
if (DEBUG_SCREENSHOT) {
- Slog.i(TAG_WM, "Attempted to take screenshot while display was off.");
+ Slog.w(TAG_WM, "Failed to take screenshot. No surface control for " + task);
}
return null;
}
- if (task.getSurfaceControl() == null) {
+ task.getBounds(mTmpRect);
+ mTmpRect.offsetTo(0, 0);
+ final SurfaceControl.ScreenshotGraphicBuffer screenshotBuffer =
+ SurfaceControl.captureLayers(
+ task.getSurfaceControl().getHandle(), mTmpRect, scaleFraction);
+ final GraphicBuffer buffer = screenshotBuffer != null ? screenshotBuffer.getGraphicBuffer()
+ : null;
+ if (buffer == null || buffer.getWidth() <= 1 || buffer.getHeight() <= 1) {
+ return null;
+ }
+ return screenshotBuffer;
+ }
+
+ @Nullable private TaskSnapshot snapshotTask(Task task) {
+ if (!mService.mPolicy.isScreenOn()) {
if (DEBUG_SCREENSHOT) {
- Slog.w(TAG_WM, "Failed to take screenshot. No surface control for " + task);
+ Slog.i(TAG_WM, "Attempted to take screenshot while display was off.");
}
return null;
}
@@ -271,8 +288,6 @@ class TaskSnapshotController {
final boolean isLowRamDevice = ActivityManager.isLowRamDeviceStatic();
final float scaleFraction = isLowRamDevice ? mPersister.getReducedScale() : 1f;
- task.getBounds(mTmpRect);
- mTmpRect.offsetTo(0, 0);
final WindowState mainWindow = appWindowToken.findMainWindow();
if (mainWindow == null) {
@@ -280,18 +295,17 @@ class TaskSnapshotController {
return null;
}
final SurfaceControl.ScreenshotGraphicBuffer screenshotBuffer =
- SurfaceControl.captureLayers(
- task.getSurfaceControl().getHandle(), mTmpRect, scaleFraction);
- final GraphicBuffer buffer = screenshotBuffer != null ? screenshotBuffer.getGraphicBuffer()
- : null;
- if (buffer == null || buffer.getWidth() <= 1 || buffer.getHeight() <= 1) {
+ createTaskSnapshot(task, scaleFraction);
+
+ if (screenshotBuffer == null) {
if (DEBUG_SCREENSHOT) {
Slog.w(TAG_WM, "Failed to take screenshot for " + task);
}
return null;
}
final boolean isWindowTranslucent = mainWindow.getAttrs().format != PixelFormat.OPAQUE;
- return new TaskSnapshot(appWindowToken.mActivityComponent, buffer,
+ return new TaskSnapshot(
+ appWindowToken.mActivityComponent, screenshotBuffer.getGraphicBuffer(),
screenshotBuffer.getColorSpace(), appWindowToken.getConfiguration().orientation,
getInsets(mainWindow), isLowRamDevice /* reduced */, scaleFraction /* scale */,
true /* isRealSnapshot */, task.getWindowingMode(), getSystemUiVisibility(task),
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 4e1cac905178..203704bf7224 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -749,10 +749,12 @@ public final class SystemServer {
if (!disableOtaDexopt) {
traceBeginAndSlog("StartOtaDexOptService");
try {
+ Watchdog.getInstance().pauseWatchingCurrentThread("moveab");
OtaDexoptService.main(mSystemContext, mPackageManagerService);
} catch (Throwable e) {
reportWtf("starting OtaDexOptService", e);
} finally {
+ Watchdog.getInstance().resumeWatchingCurrentThread("moveab");
traceEnd();
}
}
diff --git a/services/net/java/android/net/NetworkMonitorManager.java b/services/net/java/android/net/NetworkMonitorManager.java
new file mode 100644
index 000000000000..0f41302c0b15
--- /dev/null
+++ b/services/net/java/android/net/NetworkMonitorManager.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.annotation.NonNull;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * A convenience wrapper for INetworkMonitor.
+ *
+ * Wraps INetworkMonitor calls, making them a bit more friendly to use. Currently handles:
+ * - Clearing calling identity
+ * - Ignoring RemoteExceptions
+ * - Converting to stable parcelables
+ *
+ * By design, all methods on INetworkMonitor are asynchronous oneway IPCs and are thus void. All the
+ * wrapper methods in this class return a boolean that callers can use to determine whether
+ * RemoteException was thrown.
+ */
+public class NetworkMonitorManager {
+
+ @NonNull private final INetworkMonitor mNetworkMonitor;
+ @NonNull private final String mTag;
+
+ public NetworkMonitorManager(@NonNull INetworkMonitor networkMonitorManager,
+ @NonNull String tag) {
+ mNetworkMonitor = networkMonitorManager;
+ mTag = tag;
+ }
+
+ public NetworkMonitorManager(@NonNull INetworkMonitor networkMonitorManager) {
+ this(networkMonitorManager, NetworkMonitorManager.class.getSimpleName());
+ }
+
+ private void log(String s, Throwable e) {
+ Log.e(mTag, s, e);
+ }
+
+ // CHECKSTYLE:OFF Generated code
+
+ public boolean start() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.start();
+ return true;
+ } catch (RemoteException e) {
+ log("Error in start", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean launchCaptivePortalApp() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.launchCaptivePortalApp();
+ return true;
+ } catch (RemoteException e) {
+ log("Error in launchCaptivePortalApp", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean notifyCaptivePortalAppFinished(int response) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.notifyCaptivePortalAppFinished(response);
+ return true;
+ } catch (RemoteException e) {
+ log("Error in notifyCaptivePortalAppFinished", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean setAcceptPartialConnectivity() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.setAcceptPartialConnectivity();
+ return true;
+ } catch (RemoteException e) {
+ log("Error in setAcceptPartialConnectivity", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean forceReevaluation(int uid) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.forceReevaluation(uid);
+ return true;
+ } catch (RemoteException e) {
+ log("Error in forceReevaluation", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean notifyPrivateDnsChanged(PrivateDnsConfigParcel config) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.notifyPrivateDnsChanged(config);
+ return true;
+ } catch (RemoteException e) {
+ log("Error in notifyPrivateDnsChanged", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean notifyDnsResponse(int returnCode) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.notifyDnsResponse(returnCode);
+ return true;
+ } catch (RemoteException e) {
+ log("Error in notifyDnsResponse", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean notifyNetworkConnected(LinkProperties lp, NetworkCapabilities nc) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.notifyNetworkConnected(lp, nc);
+ return true;
+ } catch (RemoteException e) {
+ log("Error in notifyNetworkConnected", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean notifyNetworkDisconnected() {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.notifyNetworkDisconnected();
+ return true;
+ } catch (RemoteException e) {
+ log("Error in notifyNetworkDisconnected", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean notifyLinkPropertiesChanged(LinkProperties lp) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.notifyLinkPropertiesChanged(lp);
+ return true;
+ } catch (RemoteException e) {
+ log("Error in notifyLinkPropertiesChanged", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ public boolean notifyNetworkCapabilitiesChanged(NetworkCapabilities nc) {
+ final long token = Binder.clearCallingIdentity();
+ try {
+ mNetworkMonitor.notifyNetworkCapabilitiesChanged(nc);
+ return true;
+ } catch (RemoteException e) {
+ log("Error in notifyNetworkCapabilitiesChanged", e);
+ return false;
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ // CHECKSTYLE:ON Generated code
+}
diff --git a/services/net/java/android/net/NetworkStackClient.java b/services/net/java/android/net/NetworkStackClient.java
index 6b5842ff9065..99da637416c3 100644
--- a/services/net/java/android/net/NetworkStackClient.java
+++ b/services/net/java/android/net/NetworkStackClient.java
@@ -26,6 +26,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
+import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.dhcp.DhcpServingParamsParcel;
import android.net.dhcp.IDhcpServerCallbacks;
@@ -33,15 +34,21 @@ import android.net.ip.IIpClientCallbacks;
import android.net.util.SharedLog;
import android.os.Binder;
import android.os.Build;
+import android.os.Environment;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.SystemClock;
import android.os.UserHandle;
+import android.provider.DeviceConfig;
+import android.text.format.DateUtils;
+import android.util.ArraySet;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
+import java.io.File;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -54,6 +61,23 @@ public class NetworkStackClient {
private static final int NETWORKSTACK_TIMEOUT_MS = 10_000;
private static final String IN_PROCESS_SUFFIX = ".InProcess";
+ private static final String PREFS_FILE = "NetworkStackClientPrefs.xml";
+ private static final String PREF_KEY_LAST_CRASH_TIME = "lastcrash_time";
+ private static final String CONFIG_MIN_CRASH_INTERVAL_MS = "min_crash_interval";
+ private static final String CONFIG_MIN_UPTIME_BEFORE_CRASH_MS = "min_uptime_before_crash";
+ private static final String CONFIG_ALWAYS_RATELIMIT_NETWORKSTACK_CRASH =
+ "always_ratelimit_networkstack_crash";
+
+ // Even if the network stack is lost, do not crash the system more often than this.
+ // Connectivity would be broken, but if the user needs the device for something urgent
+ // (like calling emergency services) we should not bootloop the device.
+ // This is the default value: the actual value can be adjusted via device config.
+ private static final long DEFAULT_MIN_CRASH_INTERVAL_MS = 6 * DateUtils.HOUR_IN_MILLIS;
+
+ // Even if the network stack is lost, do not crash the system server if it was less than
+ // this much after boot. This avoids bootlooping the device, and crashes should address very
+ // infrequent failures, not failures on boot.
+ private static final long DEFAULT_MIN_UPTIME_BEFORE_CRASH_MS = 30 * DateUtils.MINUTE_IN_MILLIS;
private static NetworkStackClient sInstance;
@@ -67,12 +91,28 @@ public class NetworkStackClient {
@GuardedBy("mLog")
private final SharedLog mLog = new SharedLog(TAG);
- private volatile boolean mNetworkStackStartRequested = false;
+ private volatile boolean mWasSystemServerInitialized = false;
+
+ @GuardedBy("mHealthListeners")
+ private final ArraySet<NetworkStackHealthListener> mHealthListeners = new ArraySet<>();
private interface NetworkStackCallback {
void onNetworkStackConnected(INetworkStackConnector connector);
}
+ /**
+ * Callback interface for severe failures of the NetworkStack.
+ *
+ * <p>Useful for health monitors such as PackageWatchdog.
+ */
+ public interface NetworkStackHealthListener {
+ /**
+ * Called when there is a severe failure of the network stack.
+ * @param packageName Package name of the network stack.
+ */
+ void onNetworkStackFailure(@NonNull String packageName);
+ }
+
private NetworkStackClient() { }
/**
@@ -86,6 +126,15 @@ public class NetworkStackClient {
}
/**
+ * Add a {@link NetworkStackHealthListener} to listen to network stack health events.
+ */
+ public void registerHealthListener(@NonNull NetworkStackHealthListener listener) {
+ synchronized (mHealthListeners) {
+ mHealthListeners.add(listener);
+ }
+ }
+
+ /**
* Create a DHCP server according to the specified parameters.
*
* <p>The server will be returned asynchronously through the provided callbacks.
@@ -147,6 +196,16 @@ public class NetworkStackClient {
}
private class NetworkStackConnection implements ServiceConnection {
+ @NonNull
+ private final Context mContext;
+ @NonNull
+ private final String mPackageName;
+
+ private NetworkStackConnection(@NonNull Context context, @NonNull String packageName) {
+ mContext = context;
+ mPackageName = packageName;
+ }
+
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
logi("Network stack service connected");
@@ -155,14 +214,14 @@ public class NetworkStackClient {
@Override
public void onServiceDisconnected(ComponentName name) {
- // The system has lost its network stack (probably due to a crash in the
- // network stack process): better crash rather than stay in a bad state where all
- // networking is broken.
// onServiceDisconnected is not being called on device shutdown, so this method being
// called always indicates a bad state for the system server.
- maybeCrashWithTerribleFailure("Lost network stack");
+ // This code path is only run by the system server: only the system server binds
+ // to the NetworkStack as a service. Other processes get the NetworkStack from
+ // the ServiceManager.
+ maybeCrashWithTerribleFailure("Lost network stack", mContext, mPackageName);
}
- };
+ }
private void registerNetworkStackService(@NonNull IBinder service) {
final INetworkStackConnector connector = INetworkStackConnector.Stub.asInterface(service);
@@ -189,7 +248,7 @@ public class NetworkStackClient {
*/
public void init() {
log("Network stack init");
- mNetworkStackStartRequested = true;
+ mWasSystemServerInitialized = true;
}
/**
@@ -202,6 +261,7 @@ public class NetworkStackClient {
*/
public void start(Context context) {
log("Starting network stack");
+
final PackageManager pm = context.getPackageManager();
// Try to bind in-process if the device was shipped with an in-process version
@@ -216,16 +276,19 @@ public class NetworkStackClient {
}
if (intent == null) {
- maybeCrashWithTerribleFailure("Could not resolve the network stack");
+ maybeCrashWithTerribleFailure("Could not resolve the network stack", context, null);
return;
}
+ final String packageName = intent.getComponent().getPackageName();
+
// Start the network stack. The service will be added to the service manager in
// NetworkStackConnection.onServiceConnected().
- if (!context.bindServiceAsUser(intent, new NetworkStackConnection(),
+ if (!context.bindServiceAsUser(intent, new NetworkStackConnection(context, packageName),
Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.SYSTEM)) {
maybeCrashWithTerribleFailure(
- "Could not bind to network stack in-process, or in app with " + intent);
+ "Could not bind to network stack in-process, or in app with " + intent,
+ context, packageName);
return;
}
@@ -274,11 +337,91 @@ public class NetworkStackClient {
}
}
- private void maybeCrashWithTerribleFailure(@NonNull String message) {
+ private void maybeCrashWithTerribleFailure(@NonNull String message,
+ @NonNull Context context, @Nullable String packageName) {
logWtf(message, null);
- if (Build.IS_DEBUGGABLE) {
+ // uptime is monotonic even after a framework restart
+ final long uptime = SystemClock.elapsedRealtime();
+ final long now = System.currentTimeMillis();
+ final long minCrashIntervalMs = DeviceConfig.getLong(DeviceConfig.NAMESPACE_CONNECTIVITY,
+ CONFIG_MIN_CRASH_INTERVAL_MS, DEFAULT_MIN_CRASH_INTERVAL_MS);
+ final long minUptimeBeforeCrash = DeviceConfig.getLong(DeviceConfig.NAMESPACE_CONNECTIVITY,
+ CONFIG_MIN_UPTIME_BEFORE_CRASH_MS, DEFAULT_MIN_UPTIME_BEFORE_CRASH_MS);
+ final boolean alwaysRatelimit = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_CONNECTIVITY,
+ CONFIG_ALWAYS_RATELIMIT_NETWORKSTACK_CRASH, false);
+
+ final SharedPreferences prefs = getSharedPreferences(context);
+ final long lastCrashTime = tryGetLastCrashTime(prefs);
+
+ // Only crash if there was enough time since boot, and (if known) enough time passed since
+ // the last crash.
+ // time and lastCrashTime may be unreliable if devices have incorrect clock time, but they
+ // are only used to limit the number of crashes compared to only using the time since boot,
+ // which would also be OK behavior by itself.
+ // - If lastCrashTime is incorrectly more than the current time, only look at uptime
+ // - If it is much less than current time, only look at uptime
+ // - If current time is during the next few hours after last crash time, don't crash.
+ // Considering that this only matters if last boot was some time ago, it's likely that
+ // time will be set correctly. Otherwise, not crashing is not a big problem anyway. Being
+ // in this last state would also not last for long since the window is only a few hours.
+ final boolean alwaysCrash = Build.IS_DEBUGGABLE && !alwaysRatelimit;
+ final boolean justBooted = uptime < minUptimeBeforeCrash;
+ final boolean haveLastCrashTime = (lastCrashTime != 0) && (lastCrashTime < now);
+ final boolean haveKnownRecentCrash =
+ haveLastCrashTime && (now < lastCrashTime + minCrashIntervalMs);
+ if (alwaysCrash || (!justBooted && !haveKnownRecentCrash)) {
+ // The system is not bound to its network stack (for example due to a crash in the
+ // network stack process): better crash rather than stay in a bad state where all
+ // networking is broken.
+ // Using device-encrypted SharedPreferences as DeviceConfig does not have a synchronous
+ // API to persist settings before a crash.
+ tryWriteLastCrashTime(prefs, now);
throw new IllegalStateException(message);
}
+
+ // Here the system crashed recently already. Inform listeners that something is
+ // definitely wrong.
+ if (packageName != null) {
+ final ArraySet<NetworkStackHealthListener> listeners;
+ synchronized (mHealthListeners) {
+ listeners = new ArraySet<>(mHealthListeners);
+ }
+ for (NetworkStackHealthListener listener : listeners) {
+ listener.onNetworkStackFailure(packageName);
+ }
+ }
+ }
+
+ @Nullable
+ private SharedPreferences getSharedPreferences(@NonNull Context context) {
+ try {
+ final File prefsFile = new File(
+ Environment.getDataSystemDeDirectory(UserHandle.USER_SYSTEM), PREFS_FILE);
+ return context.createDeviceProtectedStorageContext()
+ .getSharedPreferences(prefsFile, Context.MODE_PRIVATE);
+ } catch (Throwable e) {
+ logWtf("Error loading shared preferences", e);
+ return null;
+ }
+ }
+
+ private long tryGetLastCrashTime(@Nullable SharedPreferences prefs) {
+ if (prefs == null) return 0L;
+ try {
+ return prefs.getLong(PREF_KEY_LAST_CRASH_TIME, 0L);
+ } catch (Throwable e) {
+ logWtf("Error getting last crash time", e);
+ return 0L;
+ }
+ }
+
+ private void tryWriteLastCrashTime(@Nullable SharedPreferences prefs, long value) {
+ if (prefs == null) return;
+ try {
+ prefs.edit().putLong(PREF_KEY_LAST_CRASH_TIME, value).commit();
+ } catch (Throwable e) {
+ logWtf("Error writing last crash time", e);
+ }
}
/**
@@ -350,7 +493,7 @@ public class NetworkStackClient {
"Only the system server should try to bind to the network stack.");
}
- if (!mNetworkStackStartRequested) {
+ if (!mWasSystemServerInitialized) {
// The network stack is not being started in this process, e.g. this process is not
// the system server. Get a remote connector registered by the system server.
final INetworkStackConnector connector = getRemoteConnector();
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 18c524ad7a94..748c23a24f6d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
@@ -16,6 +16,7 @@
package com.android.server.job;
+import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
@@ -162,6 +163,56 @@ public class JobSchedulerServiceTest {
/**
* Confirm that {@link JobSchedulerService#getRescheduleJobForPeriodic(JobStatus)} returns a job
+ * with the correct delay and deadline constraints if the periodic job is scheduled with the
+ * minimum possible period.
+ */
+ @Test
+ public void testGetRescheduleJobForPeriodic_minPeriod() {
+ final long now = sElapsedRealtimeClock.millis();
+ JobStatus job = createJobStatus("testGetRescheduleJobForPeriodic_insideWindow",
+ createJobInfo().setPeriodic(15 * MINUTE_IN_MILLIS));
+ final long nextWindowStartTime = now + 15 * MINUTE_IN_MILLIS;
+ final long nextWindowEndTime = now + 30 * MINUTE_IN_MILLIS;
+
+ for (int i = 0; i < 25; i++) {
+ JobStatus rescheduledJob = mService.getRescheduleJobForPeriodic(job);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+ advanceElapsedClock(30_000); // 30 seconds
+ }
+
+ for (int i = 0; i < 5; i++) {
+ // Window buffering in last 1/6 of window.
+ JobStatus rescheduledJob = mService.getRescheduleJobForPeriodic(job);
+ assertEquals(nextWindowStartTime + i * 30_000, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+ advanceElapsedClock(30_000); // 30 seconds
+ }
+ }
+
+ /**
+ * Confirm that {@link JobSchedulerService#getRescheduleJobForPeriodic(JobStatus)} returns a job
+ * with the correct delay and deadline constraints if the periodic job is scheduled with a
+ * period that's too large.
+ */
+ @Test
+ public void testGetRescheduleJobForPeriodic_largePeriod() {
+ final long now = sElapsedRealtimeClock.millis();
+ JobStatus job = createJobStatus("testGetRescheduleJobForPeriodic_insideWindow",
+ createJobInfo().setPeriodic(2 * 365 * DAY_IN_MILLIS));
+ assertEquals(now, job.getEarliestRunTime());
+ // Periods are capped at 365 days (1 year).
+ assertEquals(now + 365 * DAY_IN_MILLIS, job.getLatestRunTimeElapsed());
+ final long nextWindowStartTime = now + 365 * DAY_IN_MILLIS;
+ final long nextWindowEndTime = nextWindowStartTime + 365 * DAY_IN_MILLIS;
+
+ JobStatus rescheduledJob = mService.getRescheduleJobForPeriodic(job);
+ assertEquals(nextWindowStartTime, rescheduledJob.getEarliestRunTime());
+ assertEquals(nextWindowEndTime, rescheduledJob.getLatestRunTimeElapsed());
+ }
+
+ /**
+ * Confirm that {@link JobSchedulerService#getRescheduleJobForPeriodic(JobStatus)} returns a job
* with the correct delay and deadline constraints if the periodic job is completed and
* rescheduled while run in its expected running window.
*/
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
index 4e893575e9d4..f07a5b554d37 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
@@ -386,6 +386,8 @@ public class QuotaControllerTest {
ExecutionStats expectedStats = new ExecutionStats();
expectedStats.expirationTimeElapsed = now + 24 * HOUR_IN_MILLIS;
expectedStats.windowSizeMs = 24 * HOUR_IN_MILLIS;
+ expectedStats.jobCountLimit = mQcConstants.MAX_JOB_COUNT_RARE;
+ expectedStats.sessionCountLimit = mQcConstants.MAX_SESSION_COUNT_RARE;
final int uid = 10001;
mQuotaController.onAppRemovedLocked("com.android.test.remove", uid);
@@ -424,6 +426,8 @@ public class QuotaControllerTest {
ExecutionStats expectedStats = new ExecutionStats();
expectedStats.expirationTimeElapsed = now + 24 * HOUR_IN_MILLIS;
expectedStats.windowSizeMs = 24 * HOUR_IN_MILLIS;
+ expectedStats.jobCountLimit = mQcConstants.MAX_JOB_COUNT_RARE;
+ expectedStats.sessionCountLimit = mQcConstants.MAX_SESSION_COUNT_RARE;
mQuotaController.onUserRemovedLocked(0);
assertNull(mQuotaController.getTimingSessions(0, "com.android.test"));
@@ -456,6 +460,8 @@ public class QuotaControllerTest {
ExecutionStats inputStats = new ExecutionStats();
inputStats.windowSizeMs = expectedStats.windowSizeMs = 12 * HOUR_IN_MILLIS;
+ inputStats.jobCountLimit = expectedStats.jobCountLimit = 100;
+ inputStats.sessionCountLimit = expectedStats.sessionCountLimit = 100;
// Invalid time is now +24 hours since there are no sessions at all for the app.
expectedStats.expirationTimeElapsed = now + 24 * HOUR_IN_MILLIS;
mQuotaController.updateExecutionStatsLocked(0, "com.android.test.not.run", inputStats);
@@ -520,6 +526,7 @@ public class QuotaControllerTest {
assertEquals(expectedStats, inputStats);
inputStats.windowSizeMs = expectedStats.windowSizeMs = HOUR_IN_MILLIS;
+ inputStats.sessionCountLimit = expectedStats.sessionCountLimit = 2;
// Invalid time is now since the start of the session is at the very edge of the window
// cutoff time.
expectedStats.expirationTimeElapsed = now;
@@ -528,10 +535,13 @@ public class QuotaControllerTest {
expectedStats.executionTimeInMaxPeriodMs = 22 * MINUTE_IN_MILLIS;
expectedStats.bgJobCountInMaxPeriod = 15;
expectedStats.sessionCountInWindow = 3;
+ expectedStats.inQuotaTimeElapsed = now + 11 * MINUTE_IN_MILLIS;
mQuotaController.updateExecutionStatsLocked(0, "com.android.test", inputStats);
assertEquals(expectedStats, inputStats);
inputStats.windowSizeMs = expectedStats.windowSizeMs = 2 * HOUR_IN_MILLIS;
+ inputStats.jobCountLimit = expectedStats.jobCountLimit = 6;
+ inputStats.sessionCountLimit = expectedStats.sessionCountLimit = 100;
// Invalid time is now since the session straddles the window cutoff time.
expectedStats.expirationTimeElapsed = now;
expectedStats.executionTimeInWindowMs = 11 * MINUTE_IN_MILLIS;
@@ -539,8 +549,7 @@ public class QuotaControllerTest {
expectedStats.executionTimeInMaxPeriodMs = 22 * MINUTE_IN_MILLIS;
expectedStats.bgJobCountInMaxPeriod = 15;
expectedStats.sessionCountInWindow = 4;
- expectedStats.quotaCutoffTimeElapsed = now - (2 * HOUR_IN_MILLIS - MINUTE_IN_MILLIS)
- + mQcConstants.IN_QUOTA_BUFFER_MS;
+ expectedStats.inQuotaTimeElapsed = now + 5 * MINUTE_IN_MILLIS;
mQuotaController.updateExecutionStatsLocked(0, "com.android.test", inputStats);
assertEquals(expectedStats, inputStats);
@@ -553,8 +562,9 @@ public class QuotaControllerTest {
expectedStats.executionTimeInMaxPeriodMs = 22 * MINUTE_IN_MILLIS;
expectedStats.bgJobCountInMaxPeriod = 15;
expectedStats.sessionCountInWindow = 4;
- expectedStats.quotaCutoffTimeElapsed = now - (2 * HOUR_IN_MILLIS - MINUTE_IN_MILLIS)
- + mQcConstants.IN_QUOTA_BUFFER_MS;
+ // App goes under job execution time limit in ~61 minutes, but will be under job count limit
+ // in 65 minutes.
+ expectedStats.inQuotaTimeElapsed = now + 65 * MINUTE_IN_MILLIS;
mQuotaController.updateExecutionStatsLocked(0, "com.android.test", inputStats);
assertEquals(expectedStats, inputStats);
@@ -567,8 +577,7 @@ public class QuotaControllerTest {
expectedStats.executionTimeInMaxPeriodMs = 22 * MINUTE_IN_MILLIS;
expectedStats.bgJobCountInMaxPeriod = 15;
expectedStats.sessionCountInWindow = 5;
- expectedStats.quotaCutoffTimeElapsed = now - (2 * HOUR_IN_MILLIS - MINUTE_IN_MILLIS)
- + mQcConstants.IN_QUOTA_BUFFER_MS;
+ expectedStats.inQuotaTimeElapsed = now + 4 * HOUR_IN_MILLIS + 5 * MINUTE_IN_MILLIS;
mQuotaController.updateExecutionStatsLocked(0, "com.android.test", inputStats);
assertEquals(expectedStats, inputStats);
@@ -577,6 +586,7 @@ public class QuotaControllerTest {
.add(0,
createTimingSession(now - (23 * HOUR_IN_MILLIS), MINUTE_IN_MILLIS, 3));
inputStats.windowSizeMs = expectedStats.windowSizeMs = 8 * HOUR_IN_MILLIS;
+ inputStats.jobCountLimit = expectedStats.jobCountLimit = 100;
// Invalid time is now +1 hour since the earliest session in the max period is 1 hour
// before the end of the max period cutoff time.
expectedStats.expirationTimeElapsed = now + HOUR_IN_MILLIS;
@@ -585,7 +595,7 @@ public class QuotaControllerTest {
expectedStats.executionTimeInMaxPeriodMs = 23 * MINUTE_IN_MILLIS;
expectedStats.bgJobCountInMaxPeriod = 18;
expectedStats.sessionCountInWindow = 5;
- expectedStats.quotaCutoffTimeElapsed = now - (2 * HOUR_IN_MILLIS - MINUTE_IN_MILLIS)
+ expectedStats.inQuotaTimeElapsed = now + 6 * HOUR_IN_MILLIS + MINUTE_IN_MILLIS
+ mQcConstants.IN_QUOTA_BUFFER_MS;
mQuotaController.updateExecutionStatsLocked(0, "com.android.test", inputStats);
assertEquals(expectedStats, inputStats);
@@ -602,7 +612,7 @@ public class QuotaControllerTest {
expectedStats.executionTimeInMaxPeriodMs = 24 * MINUTE_IN_MILLIS;
expectedStats.bgJobCountInMaxPeriod = 20;
expectedStats.sessionCountInWindow = 5;
- expectedStats.quotaCutoffTimeElapsed = now - (2 * HOUR_IN_MILLIS - MINUTE_IN_MILLIS)
+ expectedStats.inQuotaTimeElapsed = now + 6 * HOUR_IN_MILLIS + MINUTE_IN_MILLIS
+ mQcConstants.IN_QUOTA_BUFFER_MS;
mQuotaController.updateExecutionStatsLocked(0, "com.android.test", inputStats);
assertEquals(expectedStats, inputStats);
@@ -627,6 +637,8 @@ public class QuotaControllerTest {
// Active
expectedStats.windowSizeMs = 10 * MINUTE_IN_MILLIS;
+ expectedStats.jobCountLimit = mQcConstants.MAX_JOB_COUNT_ACTIVE;
+ expectedStats.sessionCountLimit = mQcConstants.MAX_SESSION_COUNT_ACTIVE;
expectedStats.expirationTimeElapsed = now + 4 * MINUTE_IN_MILLIS;
expectedStats.executionTimeInWindowMs = 3 * MINUTE_IN_MILLIS;
expectedStats.bgJobCountInWindow = 5;
@@ -638,45 +650,103 @@ public class QuotaControllerTest {
// Working
expectedStats.windowSizeMs = 2 * HOUR_IN_MILLIS;
+ expectedStats.jobCountLimit = mQcConstants.MAX_JOB_COUNT_WORKING;
+ expectedStats.sessionCountLimit = mQcConstants.MAX_SESSION_COUNT_WORKING;
expectedStats.expirationTimeElapsed = now;
expectedStats.executionTimeInWindowMs = 13 * MINUTE_IN_MILLIS;
expectedStats.bgJobCountInWindow = 10;
expectedStats.executionTimeInMaxPeriodMs = 33 * MINUTE_IN_MILLIS;
expectedStats.bgJobCountInMaxPeriod = 20;
expectedStats.sessionCountInWindow = 2;
- expectedStats.quotaCutoffTimeElapsed = now - (2 * HOUR_IN_MILLIS - 3 * MINUTE_IN_MILLIS)
+ expectedStats.inQuotaTimeElapsed = now + 3 * MINUTE_IN_MILLIS
+ mQcConstants.IN_QUOTA_BUFFER_MS;
assertEquals(expectedStats,
mQuotaController.getExecutionStatsLocked(0, "com.android.test", WORKING_INDEX));
// Frequent
expectedStats.windowSizeMs = 8 * HOUR_IN_MILLIS;
+ expectedStats.jobCountLimit = mQcConstants.MAX_JOB_COUNT_FREQUENT;
+ expectedStats.sessionCountLimit = mQcConstants.MAX_SESSION_COUNT_FREQUENT;
expectedStats.expirationTimeElapsed = now + HOUR_IN_MILLIS;
expectedStats.executionTimeInWindowMs = 23 * MINUTE_IN_MILLIS;
expectedStats.bgJobCountInWindow = 15;
expectedStats.executionTimeInMaxPeriodMs = 33 * MINUTE_IN_MILLIS;
expectedStats.bgJobCountInMaxPeriod = 20;
expectedStats.sessionCountInWindow = 3;
- expectedStats.quotaCutoffTimeElapsed = now - (2 * HOUR_IN_MILLIS - 3 * MINUTE_IN_MILLIS)
+ expectedStats.inQuotaTimeElapsed = now + 6 * HOUR_IN_MILLIS + 3 * MINUTE_IN_MILLIS
+ mQcConstants.IN_QUOTA_BUFFER_MS;
assertEquals(expectedStats,
mQuotaController.getExecutionStatsLocked(0, "com.android.test", FREQUENT_INDEX));
// Rare
expectedStats.windowSizeMs = 24 * HOUR_IN_MILLIS;
+ expectedStats.jobCountLimit = mQcConstants.MAX_JOB_COUNT_RARE;
+ expectedStats.sessionCountLimit = mQcConstants.MAX_SESSION_COUNT_RARE;
expectedStats.expirationTimeElapsed = now + HOUR_IN_MILLIS;
expectedStats.executionTimeInWindowMs = 33 * MINUTE_IN_MILLIS;
expectedStats.bgJobCountInWindow = 20;
expectedStats.executionTimeInMaxPeriodMs = 33 * MINUTE_IN_MILLIS;
expectedStats.bgJobCountInMaxPeriod = 20;
expectedStats.sessionCountInWindow = 4;
- expectedStats.quotaCutoffTimeElapsed = now - (2 * HOUR_IN_MILLIS - 3 * MINUTE_IN_MILLIS)
+ expectedStats.inQuotaTimeElapsed = now + 22 * HOUR_IN_MILLIS + 3 * MINUTE_IN_MILLIS
+ mQcConstants.IN_QUOTA_BUFFER_MS;
assertEquals(expectedStats,
mQuotaController.getExecutionStatsLocked(0, "com.android.test", RARE_INDEX));
}
/**
+ * Tests that getExecutionStatsLocked returns the correct stats soon after device startup.
+ */
+ @Test
+ public void testGetExecutionStatsLocked_Values_BeginningOfTime() {
+ // Set time to 3 minutes after boot.
+ advanceElapsedClock(-JobSchedulerService.sElapsedRealtimeClock.millis());
+ advanceElapsedClock(3 * MINUTE_IN_MILLIS);
+
+ mQuotaController.saveTimingSession(0, "com.android.test",
+ createTimingSession(MINUTE_IN_MILLIS, MINUTE_IN_MILLIS, 2));
+
+ ExecutionStats expectedStats = new ExecutionStats();
+
+ // Active
+ expectedStats.windowSizeMs = 10 * MINUTE_IN_MILLIS;
+ expectedStats.jobCountLimit = mQcConstants.MAX_JOB_COUNT_ACTIVE;
+ expectedStats.sessionCountLimit = mQcConstants.MAX_SESSION_COUNT_ACTIVE;
+ expectedStats.expirationTimeElapsed = 11 * MINUTE_IN_MILLIS;
+ expectedStats.executionTimeInWindowMs = MINUTE_IN_MILLIS;
+ expectedStats.bgJobCountInWindow = 2;
+ expectedStats.executionTimeInMaxPeriodMs = MINUTE_IN_MILLIS;
+ expectedStats.bgJobCountInMaxPeriod = 2;
+ expectedStats.sessionCountInWindow = 1;
+ assertEquals(expectedStats,
+ mQuotaController.getExecutionStatsLocked(0, "com.android.test", ACTIVE_INDEX));
+
+ // Working
+ expectedStats.windowSizeMs = 2 * HOUR_IN_MILLIS;
+ expectedStats.jobCountLimit = mQcConstants.MAX_JOB_COUNT_WORKING;
+ expectedStats.sessionCountLimit = mQcConstants.MAX_SESSION_COUNT_WORKING;
+ expectedStats.expirationTimeElapsed = 2 * HOUR_IN_MILLIS + MINUTE_IN_MILLIS;
+ assertEquals(expectedStats,
+ mQuotaController.getExecutionStatsLocked(0, "com.android.test", WORKING_INDEX));
+
+ // Frequent
+ expectedStats.windowSizeMs = 8 * HOUR_IN_MILLIS;
+ expectedStats.jobCountLimit = mQcConstants.MAX_JOB_COUNT_FREQUENT;
+ expectedStats.sessionCountLimit = mQcConstants.MAX_SESSION_COUNT_FREQUENT;
+ expectedStats.expirationTimeElapsed = 8 * HOUR_IN_MILLIS + MINUTE_IN_MILLIS;
+ assertEquals(expectedStats,
+ mQuotaController.getExecutionStatsLocked(0, "com.android.test", FREQUENT_INDEX));
+
+ // Rare
+ expectedStats.windowSizeMs = 24 * HOUR_IN_MILLIS;
+ expectedStats.jobCountLimit = mQcConstants.MAX_JOB_COUNT_RARE;
+ expectedStats.sessionCountLimit = mQcConstants.MAX_SESSION_COUNT_RARE;
+ expectedStats.expirationTimeElapsed = 24 * HOUR_IN_MILLIS + MINUTE_IN_MILLIS;
+ assertEquals(expectedStats,
+ mQuotaController.getExecutionStatsLocked(0, "com.android.test", RARE_INDEX));
+ }
+
+ /**
* Tests that getExecutionStatsLocked returns the correct timing session stats when coalescing.
*/
@Test
@@ -850,13 +920,15 @@ public class QuotaControllerTest {
ExecutionStats expectedStats = new ExecutionStats();
expectedStats.windowSizeMs = originalStatsActive.windowSizeMs;
+ expectedStats.jobCountLimit = originalStatsActive.jobCountLimit;
+ expectedStats.sessionCountLimit = originalStatsActive.sessionCountLimit;
expectedStats.expirationTimeElapsed = originalStatsActive.expirationTimeElapsed;
expectedStats.executionTimeInWindowMs = originalStatsActive.executionTimeInWindowMs;
expectedStats.bgJobCountInWindow = originalStatsActive.bgJobCountInWindow;
expectedStats.executionTimeInMaxPeriodMs = originalStatsActive.executionTimeInMaxPeriodMs;
expectedStats.bgJobCountInMaxPeriod = originalStatsActive.bgJobCountInMaxPeriod;
expectedStats.sessionCountInWindow = originalStatsActive.sessionCountInWindow;
- expectedStats.quotaCutoffTimeElapsed = originalStatsActive.quotaCutoffTimeElapsed;
+ expectedStats.inQuotaTimeElapsed = originalStatsActive.inQuotaTimeElapsed;
final ExecutionStats newStatsActive = mQuotaController.getExecutionStatsLocked(0,
"com.android.test", ACTIVE_INDEX);
// Stats for the same bucket should use the same object.
@@ -864,33 +936,39 @@ public class QuotaControllerTest {
assertEquals(expectedStats, newStatsActive);
expectedStats.windowSizeMs = originalStatsWorking.windowSizeMs;
+ expectedStats.jobCountLimit = originalStatsWorking.jobCountLimit;
+ expectedStats.sessionCountLimit = originalStatsWorking.sessionCountLimit;
expectedStats.expirationTimeElapsed = originalStatsWorking.expirationTimeElapsed;
expectedStats.executionTimeInWindowMs = originalStatsWorking.executionTimeInWindowMs;
expectedStats.bgJobCountInWindow = originalStatsWorking.bgJobCountInWindow;
expectedStats.sessionCountInWindow = originalStatsWorking.sessionCountInWindow;
- expectedStats.quotaCutoffTimeElapsed = originalStatsWorking.quotaCutoffTimeElapsed;
+ expectedStats.inQuotaTimeElapsed = originalStatsWorking.inQuotaTimeElapsed;
final ExecutionStats newStatsWorking = mQuotaController.getExecutionStatsLocked(0,
"com.android.test", WORKING_INDEX);
assertTrue(originalStatsWorking == newStatsWorking);
assertNotEquals(expectedStats, newStatsWorking);
expectedStats.windowSizeMs = originalStatsFrequent.windowSizeMs;
+ expectedStats.jobCountLimit = originalStatsFrequent.jobCountLimit;
+ expectedStats.sessionCountLimit = originalStatsFrequent.sessionCountLimit;
expectedStats.expirationTimeElapsed = originalStatsFrequent.expirationTimeElapsed;
expectedStats.executionTimeInWindowMs = originalStatsFrequent.executionTimeInWindowMs;
expectedStats.bgJobCountInWindow = originalStatsFrequent.bgJobCountInWindow;
expectedStats.sessionCountInWindow = originalStatsFrequent.sessionCountInWindow;
- expectedStats.quotaCutoffTimeElapsed = originalStatsFrequent.quotaCutoffTimeElapsed;
+ expectedStats.inQuotaTimeElapsed = originalStatsFrequent.inQuotaTimeElapsed;
final ExecutionStats newStatsFrequent = mQuotaController.getExecutionStatsLocked(0,
"com.android.test", FREQUENT_INDEX);
assertTrue(originalStatsFrequent == newStatsFrequent);
assertNotEquals(expectedStats, newStatsFrequent);
expectedStats.windowSizeMs = originalStatsRare.windowSizeMs;
+ expectedStats.jobCountLimit = originalStatsRare.jobCountLimit;
+ expectedStats.sessionCountLimit = originalStatsRare.sessionCountLimit;
expectedStats.expirationTimeElapsed = originalStatsRare.expirationTimeElapsed;
expectedStats.executionTimeInWindowMs = originalStatsRare.executionTimeInWindowMs;
expectedStats.bgJobCountInWindow = originalStatsRare.bgJobCountInWindow;
expectedStats.sessionCountInWindow = originalStatsRare.sessionCountInWindow;
- expectedStats.quotaCutoffTimeElapsed = originalStatsRare.quotaCutoffTimeElapsed;
+ expectedStats.inQuotaTimeElapsed = originalStatsRare.inQuotaTimeElapsed;
final ExecutionStats newStatsRare = mQuotaController.getExecutionStatsLocked(0,
"com.android.test", RARE_INDEX);
assertTrue(originalStatsRare == newStatsRare);
@@ -1065,7 +1143,7 @@ public class QuotaControllerTest {
public void testIsWithinQuotaLocked_UnderDuration_OverJobCount() {
setDischarging();
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
- final int jobCount = mQcConstants.MAX_JOB_COUNT_PER_ALLOWED_TIME;
+ final int jobCount = mQcConstants.MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW;
mQuotaController.saveTimingSession(0, "com.android.test.spam",
createTimingSession(now - (HOUR_IN_MILLIS), 15 * MINUTE_IN_MILLIS, 25));
mQuotaController.saveTimingSession(0, "com.android.test.spam",
@@ -1100,7 +1178,7 @@ public class QuotaControllerTest {
public void testIsWithinQuotaLocked_OverDuration_OverJobCount() {
setDischarging();
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
- final int jobCount = mQcConstants.MAX_JOB_COUNT_PER_ALLOWED_TIME;
+ final int jobCount = mQcConstants.MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW;
mQuotaController.saveTimingSession(0, "com.android.test",
createTimingSession(now - (HOUR_IN_MILLIS), 15 * MINUTE_IN_MILLIS, 25));
mQuotaController.saveTimingSession(0, "com.android.test",
@@ -1141,7 +1219,7 @@ public class QuotaControllerTest {
advanceElapsedClock(10 * MINUTE_IN_MILLIS + 30 * SECOND_IN_MILLIS);
assertEquals(2, mQuotaController.getExecutionStatsLocked(
- SOURCE_USER_ID, SOURCE_PACKAGE, ACTIVE_INDEX).jobCountInAllowedTime);
+ SOURCE_USER_ID, SOURCE_PACKAGE, ACTIVE_INDEX).jobCountInRateLimitingWindow);
assertTrue(mQuotaController.isWithinQuotaLocked(jobStatus));
}
@@ -1212,9 +1290,9 @@ public class QuotaControllerTest {
mQuotaController.getTimingSessions(SOURCE_USER_ID, fgChangerPkgName).size());
for (int i = ACTIVE_INDEX; i < RARE_INDEX; ++i) {
assertEquals(42, mQuotaController.getExecutionStatsLocked(
- SOURCE_USER_ID, fgChangerPkgName, i).jobCountInAllowedTime);
+ SOURCE_USER_ID, fgChangerPkgName, i).jobCountInRateLimitingWindow);
assertEquals(1, mQuotaController.getExecutionStatsLocked(
- SOURCE_USER_ID, unaffectedPkgName, i).jobCountInAllowedTime);
+ SOURCE_USER_ID, unaffectedPkgName, i).jobCountInRateLimitingWindow);
}
}
@@ -1555,26 +1633,29 @@ public class QuotaControllerTest {
}
@Test
- public void testMaybeScheduleStartAlarmLocked_JobCount_AllowedTime() {
+ public void testMaybeScheduleStartAlarmLocked_JobCount_RateLimitingWindow() {
+ // Set rate limiting period different from allowed time to confirm code sets based on
+ // the former.
+ mQcConstants.ALLOWED_TIME_PER_PERIOD_MS = 10 * MINUTE_IN_MILLIS;
+ mQcConstants.RATE_LIMITING_WINDOW_MS = 5 * MINUTE_IN_MILLIS;
+ mQcConstants.updateConstants();
+
final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
final int standbyBucket = WORKING_INDEX;
ExecutionStats stats = mQuotaController.getExecutionStatsLocked(SOURCE_USER_ID,
SOURCE_PACKAGE, standbyBucket);
- stats.jobCountInAllowedTime =
- mQcConstants.MAX_JOB_COUNT_PER_ALLOWED_TIME + 2;
+ stats.jobCountInRateLimitingWindow =
+ mQcConstants.MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW + 2;
// Invalid time in the past, so the count shouldn't be used.
- stats.jobCountExpirationTimeElapsed =
- now - mQuotaController.getAllowedTimePerPeriodMs() / 2;
+ stats.jobRateLimitExpirationTimeElapsed = now - 5 * MINUTE_IN_MILLIS / 2;
mQuotaController.maybeScheduleStartAlarmLocked(
SOURCE_USER_ID, SOURCE_PACKAGE, standbyBucket);
verify(mAlarmManager, never()).set(anyInt(), anyLong(), eq(TAG_QUOTA_CHECK), any(), any());
- // Invalid time in the future, so the count should be used.
- stats.jobCountExpirationTimeElapsed =
- now + mQuotaController.getAllowedTimePerPeriodMs() / 2;
- final long expectedWorkingAlarmTime =
- stats.jobCountExpirationTimeElapsed + mQuotaController.getAllowedTimePerPeriodMs();
+ // Valid time in the future, so the count should be used.
+ stats.jobRateLimitExpirationTimeElapsed = now + 5 * MINUTE_IN_MILLIS / 2;
+ final long expectedWorkingAlarmTime = stats.jobRateLimitExpirationTimeElapsed;
mQuotaController.maybeScheduleStartAlarmLocked(
SOURCE_USER_ID, SOURCE_PACKAGE, standbyBucket);
verify(mAlarmManager, times(1))
@@ -1732,12 +1813,13 @@ public class QuotaControllerTest {
mQcConstants.MAX_JOB_COUNT_WORKING = 4000;
mQcConstants.MAX_JOB_COUNT_FREQUENT = 3000;
mQcConstants.MAX_JOB_COUNT_RARE = 2000;
- mQcConstants.MAX_JOB_COUNT_PER_ALLOWED_TIME = 500;
+ mQcConstants.RATE_LIMITING_WINDOW_MS = 15 * MINUTE_IN_MILLIS;
+ mQcConstants.MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW = 500;
mQcConstants.MAX_SESSION_COUNT_ACTIVE = 500;
mQcConstants.MAX_SESSION_COUNT_WORKING = 400;
mQcConstants.MAX_SESSION_COUNT_FREQUENT = 300;
mQcConstants.MAX_SESSION_COUNT_RARE = 200;
- mQcConstants.MAX_SESSION_COUNT_PER_ALLOWED_TIME = 50;
+ mQcConstants.MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW = 50;
mQcConstants.TIMING_SESSION_COALESCING_DURATION_MS = 10 * SECOND_IN_MILLIS;
mQcConstants.updateConstants();
@@ -1750,12 +1832,13 @@ public class QuotaControllerTest {
mQuotaController.getBucketWindowSizes()[FREQUENT_INDEX]);
assertEquals(60 * MINUTE_IN_MILLIS, mQuotaController.getBucketWindowSizes()[RARE_INDEX]);
assertEquals(3 * HOUR_IN_MILLIS, mQuotaController.getMaxExecutionTimeMs());
- assertEquals(500, mQuotaController.getMaxJobCountPerAllowedTime());
+ assertEquals(15 * MINUTE_IN_MILLIS, mQuotaController.getRateLimitingWindowMs());
+ assertEquals(500, mQuotaController.getMaxJobCountPerRateLimitingWindow());
assertEquals(5000, mQuotaController.getBucketMaxJobCounts()[ACTIVE_INDEX]);
assertEquals(4000, mQuotaController.getBucketMaxJobCounts()[WORKING_INDEX]);
assertEquals(3000, mQuotaController.getBucketMaxJobCounts()[FREQUENT_INDEX]);
assertEquals(2000, mQuotaController.getBucketMaxJobCounts()[RARE_INDEX]);
- assertEquals(50, mQuotaController.getMaxSessionCountPerAllowedTime());
+ assertEquals(50, mQuotaController.getMaxSessionCountPerRateLimitingWindow());
assertEquals(500, mQuotaController.getBucketMaxSessionCounts()[ACTIVE_INDEX]);
assertEquals(400, mQuotaController.getBucketMaxSessionCounts()[WORKING_INDEX]);
assertEquals(300, mQuotaController.getBucketMaxSessionCounts()[FREQUENT_INDEX]);
@@ -1778,12 +1861,13 @@ public class QuotaControllerTest {
mQcConstants.MAX_JOB_COUNT_WORKING = 1;
mQcConstants.MAX_JOB_COUNT_FREQUENT = 1;
mQcConstants.MAX_JOB_COUNT_RARE = 1;
- mQcConstants.MAX_JOB_COUNT_PER_ALLOWED_TIME = 0;
+ mQcConstants.RATE_LIMITING_WINDOW_MS = 15 * SECOND_IN_MILLIS;
+ mQcConstants.MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW = 0;
mQcConstants.MAX_SESSION_COUNT_ACTIVE = -1;
- mQcConstants.MAX_SESSION_COUNT_WORKING = 1;
- mQcConstants.MAX_SESSION_COUNT_FREQUENT = 2;
- mQcConstants.MAX_SESSION_COUNT_RARE = 1;
- mQcConstants.MAX_SESSION_COUNT_PER_ALLOWED_TIME = 0;
+ mQcConstants.MAX_SESSION_COUNT_WORKING = 0;
+ mQcConstants.MAX_SESSION_COUNT_FREQUENT = -3;
+ mQcConstants.MAX_SESSION_COUNT_RARE = 0;
+ mQcConstants.MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW = 0;
mQcConstants.TIMING_SESSION_COALESCING_DURATION_MS = -1;
mQcConstants.updateConstants();
@@ -1795,16 +1879,17 @@ public class QuotaControllerTest {
assertEquals(MINUTE_IN_MILLIS, mQuotaController.getBucketWindowSizes()[FREQUENT_INDEX]);
assertEquals(MINUTE_IN_MILLIS, mQuotaController.getBucketWindowSizes()[RARE_INDEX]);
assertEquals(HOUR_IN_MILLIS, mQuotaController.getMaxExecutionTimeMs());
- assertEquals(10, mQuotaController.getMaxJobCountPerAllowedTime());
- assertEquals(100, mQuotaController.getBucketMaxJobCounts()[ACTIVE_INDEX]);
- assertEquals(100, mQuotaController.getBucketMaxJobCounts()[WORKING_INDEX]);
- assertEquals(100, mQuotaController.getBucketMaxJobCounts()[FREQUENT_INDEX]);
- assertEquals(100, mQuotaController.getBucketMaxJobCounts()[RARE_INDEX]);
- assertEquals(10, mQuotaController.getMaxSessionCountPerAllowedTime());
- assertEquals(3, mQuotaController.getBucketMaxSessionCounts()[ACTIVE_INDEX]);
- assertEquals(3, mQuotaController.getBucketMaxSessionCounts()[WORKING_INDEX]);
- assertEquals(3, mQuotaController.getBucketMaxSessionCounts()[FREQUENT_INDEX]);
- assertEquals(3, mQuotaController.getBucketMaxSessionCounts()[RARE_INDEX]);
+ assertEquals(30 * SECOND_IN_MILLIS, mQuotaController.getRateLimitingWindowMs());
+ assertEquals(10, mQuotaController.getMaxJobCountPerRateLimitingWindow());
+ assertEquals(10, mQuotaController.getBucketMaxJobCounts()[ACTIVE_INDEX]);
+ assertEquals(10, mQuotaController.getBucketMaxJobCounts()[WORKING_INDEX]);
+ assertEquals(10, mQuotaController.getBucketMaxJobCounts()[FREQUENT_INDEX]);
+ assertEquals(10, mQuotaController.getBucketMaxJobCounts()[RARE_INDEX]);
+ assertEquals(10, mQuotaController.getMaxSessionCountPerRateLimitingWindow());
+ assertEquals(1, mQuotaController.getBucketMaxSessionCounts()[ACTIVE_INDEX]);
+ assertEquals(1, mQuotaController.getBucketMaxSessionCounts()[WORKING_INDEX]);
+ assertEquals(1, mQuotaController.getBucketMaxSessionCounts()[FREQUENT_INDEX]);
+ assertEquals(1, mQuotaController.getBucketMaxSessionCounts()[RARE_INDEX]);
assertEquals(0, mQuotaController.getTimingSessionCoalescingDurationMs());
// Test larger than a day. Controller should cap at one day.
@@ -1815,6 +1900,7 @@ public class QuotaControllerTest {
mQcConstants.WINDOW_SIZE_FREQUENT_MS = 25 * HOUR_IN_MILLIS;
mQcConstants.WINDOW_SIZE_RARE_MS = 25 * HOUR_IN_MILLIS;
mQcConstants.MAX_EXECUTION_TIME_MS = 25 * HOUR_IN_MILLIS;
+ mQcConstants.RATE_LIMITING_WINDOW_MS = 25 * HOUR_IN_MILLIS;
mQcConstants.TIMING_SESSION_COALESCING_DURATION_MS = 25 * HOUR_IN_MILLIS;
mQcConstants.updateConstants();
@@ -1826,6 +1912,7 @@ public class QuotaControllerTest {
assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getBucketWindowSizes()[FREQUENT_INDEX]);
assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getBucketWindowSizes()[RARE_INDEX]);
assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getMaxExecutionTimeMs());
+ assertEquals(24 * HOUR_IN_MILLIS, mQuotaController.getRateLimitingWindowMs());
assertEquals(15 * MINUTE_IN_MILLIS,
mQuotaController.getTimingSessionCoalescingDurationMs());
}
@@ -2126,7 +2213,7 @@ public class QuotaControllerTest {
assertNull(mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
ExecutionStats stats = mQuotaController.getExecutionStatsLocked(SOURCE_USER_ID,
SOURCE_PACKAGE, standbyBucket);
- assertEquals(0, stats.jobCountInAllowedTime);
+ assertEquals(0, stats.jobCountInRateLimitingWindow);
setProcessState(ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
mQuotaController.prepareForExecutionLocked(jobFg1);
@@ -2138,7 +2225,7 @@ public class QuotaControllerTest {
mQuotaController.maybeStopTrackingJobLocked(jobFg2, null, false);
assertNull(mQuotaController.getTimingSessions(SOURCE_USER_ID, SOURCE_PACKAGE));
- assertEquals(0, stats.jobCountInAllowedTime);
+ assertEquals(0, stats.jobCountInRateLimitingWindow);
}
/**
@@ -2154,7 +2241,7 @@ public class QuotaControllerTest {
ExecutionStats stats = mQuotaController.getExecutionStatsLocked(SOURCE_USER_ID,
SOURCE_PACKAGE, standbyBucket);
- assertEquals(0, stats.jobCountInAllowedTime);
+ assertEquals(0, stats.jobCountInRateLimitingWindow);
setProcessState(ActivityManager.PROCESS_STATE_TOP_SLEEPING);
mQuotaController.prepareForExecutionLocked(jobBg1);
@@ -2165,7 +2252,7 @@ public class QuotaControllerTest {
advanceElapsedClock(10 * SECOND_IN_MILLIS);
mQuotaController.maybeStopTrackingJobLocked(jobBg2, null, false);
- assertEquals(2, stats.jobCountInAllowedTime);
+ assertEquals(2, stats.jobCountInRateLimitingWindow);
}
/**
@@ -2363,6 +2450,8 @@ public class QuotaControllerTest {
timeout(remainingTimeMs + 2 * SECOND_IN_MILLIS).times(1))
.onControllerStateChanged();
assertFalse(jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+ assertEquals(JobSchedulerService.sElapsedRealtimeClock.millis(),
+ jobStatus.getWhenStandbyDeferred());
}
/**
@@ -2421,10 +2510,10 @@ public class QuotaControllerTest {
/**
* Tests that the start alarm is properly scheduled when a job has been throttled due to the job
- * count quota.
+ * count rate limiting.
*/
@Test
- public void testStartAlarmScheduled_JobCount_AllowedTime() {
+ public void testStartAlarmScheduled_JobCount_RateLimitingWindow() {
// saveTimingSession calls maybeScheduleCleanupAlarmLocked which interferes with these tests
// because it schedules an alarm too. Prevent it from doing so.
spyOn(mQuotaController);
@@ -2432,7 +2521,7 @@ public class QuotaControllerTest {
// Essentially disable session throttling.
mQcConstants.MAX_SESSION_COUNT_WORKING =
- mQcConstants.MAX_SESSION_COUNT_PER_ALLOWED_TIME = Integer.MAX_VALUE;
+ mQcConstants.MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW = Integer.MAX_VALUE;
mQcConstants.updateConstants();
final int standbyBucket = WORKING_INDEX;
@@ -2444,7 +2533,7 @@ public class QuotaControllerTest {
verify(mAlarmManager, never()).set(anyInt(), anyLong(), eq(TAG_QUOTA_CHECK), any(), any());
// Ran jobs up to the job limit. All of them should be allowed to run.
- for (int i = 0; i < mQcConstants.MAX_JOB_COUNT_PER_ALLOWED_TIME; ++i) {
+ for (int i = 0; i < mQcConstants.MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW; ++i) {
JobStatus job = createJobStatus("testStartAlarmScheduled_JobCount_AllowedTime", i);
setStandbyBucket(WORKING_INDEX, job);
mQuotaController.maybeStartTrackingJobLocked(job, null);
@@ -2466,18 +2555,17 @@ public class QuotaControllerTest {
ExecutionStats stats = mQuotaController.getExecutionStatsLocked(SOURCE_USER_ID,
SOURCE_PACKAGE, standbyBucket);
- final long expectedWorkingAlarmTime =
- stats.jobCountExpirationTimeElapsed + mQcConstants.ALLOWED_TIME_PER_PERIOD_MS;
+ final long expectedWorkingAlarmTime = stats.jobRateLimitExpirationTimeElapsed;
verify(mAlarmManager, times(1))
.set(anyInt(), eq(expectedWorkingAlarmTime), eq(TAG_QUOTA_CHECK), any(), any());
}
/**
- * Tests that the start alarm is properly scheduled when a job has been throttled due to the job
- * count quota.
+ * Tests that the start alarm is properly scheduled when a job has been throttled due to the
+ * session count rate limiting.
*/
@Test
- public void testStartAlarmScheduled_TimingSessionCount_AllowedTime() {
+ public void testStartAlarmScheduled_TimingSessionCount_RateLimitingWindow() {
// saveTimingSession calls maybeScheduleCleanupAlarmLocked which interferes with these tests
// because it schedules an alarm too. Prevent it from doing so.
spyOn(mQuotaController);
@@ -2485,10 +2573,10 @@ public class QuotaControllerTest {
// Essentially disable job count throttling.
mQcConstants.MAX_JOB_COUNT_FREQUENT =
- mQcConstants.MAX_JOB_COUNT_PER_ALLOWED_TIME = Integer.MAX_VALUE;
- // Make sure throttling is because of COUNT_PER_ALLOWED_TIME.
+ mQcConstants.MAX_JOB_COUNT_PER_RATE_LIMITING_WINDOW = Integer.MAX_VALUE;
+ // Make sure throttling is because of COUNT_PER_RATE_LIMITING_WINDOW.
mQcConstants.MAX_SESSION_COUNT_FREQUENT =
- mQcConstants.MAX_SESSION_COUNT_PER_ALLOWED_TIME + 1;
+ mQcConstants.MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW + 1;
mQcConstants.updateConstants();
final int standbyBucket = FREQUENT_INDEX;
@@ -2500,7 +2588,7 @@ public class QuotaControllerTest {
verify(mAlarmManager, never()).set(anyInt(), anyLong(), eq(TAG_QUOTA_CHECK), any(), any());
// Ran jobs up to the job limit. All of them should be allowed to run.
- for (int i = 0; i < mQcConstants.MAX_SESSION_COUNT_PER_ALLOWED_TIME; ++i) {
+ for (int i = 0; i < mQcConstants.MAX_SESSION_COUNT_PER_RATE_LIMITING_WINDOW; ++i) {
JobStatus job = createJobStatus(
"testStartAlarmScheduled_TimingSessionCount_AllowedTime", i);
setStandbyBucket(FREQUENT_INDEX, job);
@@ -2515,16 +2603,17 @@ public class QuotaControllerTest {
// Start alarm shouldn't have been scheduled since the app was in quota up until this point.
verify(mAlarmManager, never()).set(anyInt(), anyLong(), eq(TAG_QUOTA_CHECK), any(), any());
- // The app is now out of job count quota
+ // The app is now out of session count quota
JobStatus throttledJob = createJobStatus(
"testStartAlarmScheduled_TimingSessionCount_AllowedTime", 42);
mQuotaController.maybeStartTrackingJobLocked(throttledJob, null);
assertFalse(throttledJob.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA));
+ assertEquals(JobSchedulerService.sElapsedRealtimeClock.millis(),
+ throttledJob.getWhenStandbyDeferred());
ExecutionStats stats = mQuotaController.getExecutionStatsLocked(SOURCE_USER_ID,
SOURCE_PACKAGE, standbyBucket);
- final long expectedWorkingAlarmTime =
- stats.sessionCountExpirationTimeElapsed + mQcConstants.ALLOWED_TIME_PER_PERIOD_MS;
+ final long expectedWorkingAlarmTime = stats.sessionRateLimitExpirationTimeElapsed;
verify(mAlarmManager, times(1))
.set(anyInt(), eq(expectedWorkingAlarmTime), eq(TAG_QUOTA_CHECK), any(), any());
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
index fa1bcaccd786..fd3678dae0c4 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java
@@ -423,9 +423,7 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
assertEquals(null, si.getIntent());
assertEquals(123, si.getRank());
- assertEquals("person", si.getPersons()[0].getName());
- assertEquals("personKey", si.getPersons()[0].getKey());
- assertEquals("personUri", si.getPersons()[0].getUri());
+ assertEquals(null, si.getPersons());
assertEquals(1, si.getExtras().getInt("k"));
assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_LONG_LIVED, si.getFlags());
@@ -455,6 +453,30 @@ public class ShortcutManagerTest2 extends BaseShortcutManagerTest {
assertEquals(456, si.getIconResourceId());
assertEquals(null, si.getIconResName());
+
+ si = sorig.clone(ShortcutInfo.CLONE_REMOVE_FOR_APP_PREDICTION);
+
+ assertEquals(mClientContext.getPackageName(), si.getPackage());
+ assertEquals("id", si.getId());
+ assertEquals(new ComponentName("a", "b"), si.getActivity());
+ assertEquals(null, si.getIcon());
+ assertEquals("title", si.getTitle());
+ assertEquals("text", si.getText());
+ assertEquals("dismes", si.getDisabledMessage());
+ assertEquals(set(ShortcutInfo.SHORTCUT_CATEGORY_CONVERSATION, "xyz"), si.getCategories());
+ assertEquals("action", si.getIntent().getAction());
+ assertEquals("val", si.getIntent().getStringExtra("key"));
+ assertEquals(123, si.getRank());
+ assertEquals("person", si.getPersons()[0].getName());
+ assertEquals("personKey", si.getPersons()[0].getKey());
+ assertEquals("personUri", si.getPersons()[0].getUri());
+ assertEquals(1, si.getExtras().getInt("k"));
+
+ assertEquals(ShortcutInfo.FLAG_PINNED | ShortcutInfo.FLAG_LONG_LIVED, si.getFlags());
+ assertEquals(null, si.getBitmapPath());
+
+ assertEquals(456, si.getIconResourceId());
+ assertEquals(null, si.getIconResName());
}
public void testShortcutInfoClone_resId() {
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 87f221a18161..e75a30b12f68 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -22,7 +22,6 @@ import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIB
import static android.app.Notification.CATEGORY_CALL;
import static android.app.Notification.FLAG_BUBBLE;
import static android.app.Notification.FLAG_FOREGROUND_SERVICE;
-import static android.app.Notification.FLAG_ONLY_ALERT_ONCE;
import static android.app.NotificationManager.EXTRA_BLOCKED_STATE;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.IMPORTANCE_HIGH;
@@ -1660,11 +1659,14 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
eq(channel2.getId()), anyBoolean()))
.thenReturn(channel2);
+ when(mPreferencesHelper.createNotificationChannel(eq(PKG), anyInt(),
+ eq(channel2), anyBoolean(), anyBoolean()))
+ .thenReturn(true);
reset(mListeners);
mBinderService.createNotificationChannels(PKG,
new ParceledListSlice(Arrays.asList(mTestNotificationChannel, channel2)));
- verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
+ verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
eq(Process.myUserHandle()), eq(mTestNotificationChannel),
eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_ADDED));
verify(mListeners, times(1)).notifyNotificationChannelChanged(eq(PKG),
@@ -4963,13 +4965,10 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), false);
waitForIdle();
- // Make sure we are not a bubble / reported as such to listeners
- ArgumentCaptor<NotificationRecord> captor =
- ArgumentCaptor.forClass(NotificationRecord.class);
- verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any());
-
- assertEquals((captor.getValue().getNotification().flags & FLAG_BUBBLE), 0);
- assertTrue((captor.getValue().getNotification().flags & FLAG_ONLY_ALERT_ONCE) != 0);
+ // Make sure we are not a bubble
+ StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
+ assertEquals(1, notifsAfter.length);
+ assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
}
@Test
@@ -5000,13 +4999,10 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mService.mNotificationDelegate.onNotificationBubbleChanged(nr.getKey(), true);
waitForIdle();
- // Make sure we are a bubble / reported as such to listeners
- ArgumentCaptor<NotificationRecord> captor =
- ArgumentCaptor.forClass(NotificationRecord.class);
- verify(mListeners, times(1)).notifyPostedLocked(captor.capture(), any());
-
- assertTrue((captor.getValue().getNotification().flags & FLAG_BUBBLE) != 0);
- assertTrue((captor.getValue().getNotification().flags & FLAG_ONLY_ALERT_ONCE) != 0);
+ // Make sure we are a bubble
+ StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
+ assertEquals(1, notifsAfter.length);
+ assertTrue((notifsAfter[0].getNotification().flags & FLAG_BUBBLE) != 0);
}
@Test
@@ -5037,7 +5033,6 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
StatusBarNotification[] notifsAfter = mBinderService.getActiveNotifications(PKG);
assertEquals(1, notifsAfter.length);
assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
- verify(mListeners, times(0)).notifyPostedLocked(any(), any());
}
@Test
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 a0660c493605..8f8b746b59d4 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -262,13 +262,13 @@ public class PreferencesHelperTest extends UiServiceTestCase {
int uid0 = 1001;
setUpPackageWithUid(package0, uid0);
NotificationChannel channel0 = new NotificationChannel("id0", "name0", IMPORTANCE_HIGH);
- mHelper.createNotificationChannel(package0, uid0, channel0, true, false);
+ assertTrue(mHelper.createNotificationChannel(package0, uid0, channel0, true, false));
String package10 = "test.package.user10";
int uid10 = 1001001;
setUpPackageWithUid(package10, uid10);
NotificationChannel channel10 = new NotificationChannel("id10", "name10", IMPORTANCE_HIGH);
- mHelper.createNotificationChannel(package10, uid10, channel10, true, false);
+ assertTrue(mHelper.createNotificationChannel(package10, uid10, channel10, true, false));
ByteArrayOutputStream baos = writeXmlAndPurge(package10, uid10, true, 10);
@@ -293,7 +293,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
int uid0 = 1001;
setUpPackageWithUid(package0, uid0);
NotificationChannel channel0 = new NotificationChannel("id0", "name0", IMPORTANCE_HIGH);
- mHelper.createNotificationChannel(package0, uid0, channel0, true, false);
+ assertTrue(mHelper.createNotificationChannel(package0, uid0, channel0, true, false));
ByteArrayOutputStream baos = writeXmlAndPurge(package0, uid0, true, 0);
@@ -334,8 +334,8 @@ public class PreferencesHelperTest extends UiServiceTestCase {
mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg, true);
mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, ncg2, true);
- mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false);
- mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, false, false);
+ assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false));
+ assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, false, false));
mHelper.setShowBadge(PKG_N_MR1, UID_N_MR1, true);
mHelper.setAppImportanceLocked(PKG_N_MR1, UID_N_MR1);
@@ -716,8 +716,8 @@ public class PreferencesHelperTest extends UiServiceTestCase {
public void testCreateChannel_blocked() throws Exception {
mHelper.setImportance(PKG_N_MR1, UID_N_MR1, IMPORTANCE_NONE);
- mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
- new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true, false);
+ assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_LOW), true, false));
}
@Test
@@ -746,10 +746,10 @@ public class PreferencesHelperTest extends UiServiceTestCase {
} catch (IllegalArgumentException e) {
// yay
}
- mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
- new NotificationChannel("bananas", "bananas", IMPORTANCE_NONE), true, false);
- mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
- new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX), true, false);
+ assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_NONE), true, false));
+ assertFalse(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1,
+ new NotificationChannel("bananas", "bananas", IMPORTANCE_MAX), true, false));
}
@@ -763,7 +763,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
channel.setBypassDnd(true);
channel.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
- mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, false, false);
+ assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, false, false));
// same id, try to update all fields
final NotificationChannel channel2 =
@@ -776,7 +776,8 @@ public class PreferencesHelperTest extends UiServiceTestCase {
mHelper.updateNotificationChannel(PKG_N_MR1, UID_N_MR1, channel2, true);
// all fields should be changed
- assertEquals(channel2, mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), false));
+ assertEquals(channel2,
+ mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), false));
verify(mHandler, times(1)).requestSort();
}
@@ -894,7 +895,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
}
channel.lockFields(lockMask);
- mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false);
+ assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false));
NotificationChannel savedChannel =
mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), false);
@@ -1469,13 +1470,18 @@ public class PreferencesHelperTest extends UiServiceTestCase {
new NotificationChannel("id2", "name2", IMPORTANCE_LOW);
channel.setVibrationPattern(vibration);
- mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false);
+ assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false));
NotificationChannel newChannel = new NotificationChannel(
channel.getId(), channel.getName(), NotificationManager.IMPORTANCE_HIGH);
newChannel.setVibrationPattern(new long[]{100});
+ newChannel.setAllowBubbles(!channel.canBubble());
+ newChannel.setLightColor(Color.BLUE);
+ newChannel.setSound(Uri.EMPTY, null);
+ newChannel.setShowBadge(!channel.canShowBadge());
- mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, newChannel, true, false);
+ assertFalse(mHelper.createNotificationChannel(
+ PKG_N_MR1, UID_N_MR1, newChannel, true, false));
// Old settings not overridden
compareChannels(channel,
@@ -1588,16 +1594,17 @@ public class PreferencesHelperTest extends UiServiceTestCase {
new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false);
- mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG_N_MR1}, new int[]{
- UID_N_MR1});
+ assertTrue(mHelper.onPackagesChanged(true, UserHandle.USER_SYSTEM, new String[]{PKG_N_MR1},
+ new int[]{UID_N_MR1}));
- assertEquals(0, mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, true).getList().size());
+ assertEquals(0, mHelper.getNotificationChannels(
+ PKG_N_MR1, UID_N_MR1, true).getList().size());
// Not deleted
mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel1, true, false);
- mHelper.onPackagesChanged(false, UserHandle.USER_SYSTEM, new String[]{PKG_N_MR1}, new int[]{
- UID_N_MR1});
+ assertFalse(mHelper.onPackagesChanged(false, UserHandle.USER_SYSTEM,
+ new String[]{PKG_N_MR1}, new int[]{UID_N_MR1}));
assertEquals(2, mHelper.getNotificationChannels(PKG_N_MR1, UID_N_MR1, false).getList().size());
}
@@ -1825,13 +1832,13 @@ public class PreferencesHelperTest extends UiServiceTestCase {
@Test
public void testCreateChannel_updateName() {
NotificationChannel nc = new NotificationChannel("id", "hello", IMPORTANCE_DEFAULT);
- mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false);
+ assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false));
NotificationChannel actual =
mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "id", false);
assertEquals("hello", actual.getName());
nc = new NotificationChannel("id", "goodbye", IMPORTANCE_HIGH);
- mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false);
+ assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false));
actual = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "id", false);
assertEquals("goodbye", actual.getName());
@@ -1845,14 +1852,14 @@ public class PreferencesHelperTest extends UiServiceTestCase {
NotificationChannelGroup group = new NotificationChannelGroup("group", "");
mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true);
NotificationChannel nc = new NotificationChannel("id", "hello", IMPORTANCE_DEFAULT);
- mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false);
+ assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false));
NotificationChannel actual =
mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "id", false);
assertNull(actual.getGroup());
nc = new NotificationChannel("id", "hello", IMPORTANCE_HIGH);
nc.setGroup(group.getId());
- mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false);
+ assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, nc, true, false));
actual = mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "id", false);
assertNotNull(actual.getGroup());
@@ -2109,7 +2116,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
NotificationChannel update = new NotificationChannel("A", "a", IMPORTANCE_LOW);
update.setBypassDnd(true);
- mHelper.createNotificationChannel(SYSTEM_PKG, SYSTEM_UID, update, true, false);
+ assertFalse(mHelper.createNotificationChannel(SYSTEM_PKG, SYSTEM_UID, update, true, false));
assertFalse(mHelper.getNotificationChannel(SYSTEM_PKG, SYSTEM_UID, "A", false)
.canBypassDnd());
@@ -2122,7 +2129,7 @@ public class PreferencesHelperTest extends UiServiceTestCase {
NotificationChannel update = new NotificationChannel("A", "a", IMPORTANCE_LOW);
update.setBypassDnd(true);
- mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, update, true, true);
+ assertTrue(mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, update, true, true));
assertTrue(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, "A", false).canBypassDnd());
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index 0f7b35c4975c..c77e25fabf19 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -30,6 +30,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.ActivityDisplay.POSITION_TOP;
@@ -54,6 +55,7 @@ import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.ResolveInfo;
+import android.content.res.Resources;
import android.graphics.Rect;
import android.platform.test.annotations.Presubmit;
import android.util.Pair;
@@ -601,6 +603,73 @@ public class RootActivityContainerTests extends ActivityTestsBase {
}
/**
+ * Tests that the default secondary home activity is always picked when it is in forced by
+ * config_useSystemProvidedLauncherForSecondary.
+ */
+ @Test
+ public void testResolveSecondaryHomeActivityForced() throws Exception {
+ Resources resources = mContext.getResources();
+ spyOn(resources);
+ try {
+ // setUp: set secondary launcher and force it.
+ final String defaultSecondaryHome =
+ "com.android.test/com.android.test.TestDefaultSecondaryHome";
+ final ComponentName secondaryComp = ComponentName.unflattenFromString(
+ defaultSecondaryHome);
+ doReturn(defaultSecondaryHome).when(resources).getString(
+ com.android.internal.R.string.config_secondaryHomeComponent);
+ doReturn(true).when(resources).getBoolean(
+ com.android.internal.R.bool.config_useSystemProvidedLauncherForSecondary);
+ final Intent secondaryHomeIntent = mService.getSecondaryHomeIntent(null);
+ assertEquals(secondaryComp, secondaryHomeIntent.getComponent());
+ final ActivityInfo aInfoSecondary = new ActivityInfo();
+ aInfoSecondary.name = secondaryComp.getClassName();
+ aInfoSecondary.applicationInfo = new ApplicationInfo();
+ aInfoSecondary.applicationInfo.packageName = secondaryComp.getPackageName();
+ doReturn(aInfoSecondary).when(mRootActivityContainer).resolveHomeActivity(anyInt(),
+ refEq(secondaryHomeIntent));
+ final Intent homeIntent = mService.getHomeIntent();
+ final ActivityInfo aInfoDefault = new ActivityInfo();
+ aInfoDefault.name = "fakeHomeActivity";
+ aInfoDefault.applicationInfo = new ApplicationInfo();
+ aInfoDefault.applicationInfo.packageName = "fakeHomePackage";
+ doReturn(aInfoDefault).when(mRootActivityContainer).resolveHomeActivity(anyInt(),
+ refEq(homeIntent));
+ // Let resolveActivities call to validate both main launcher and second launcher so that
+ // resolveActivities call does not work as enabler for secondary.
+ final List<ResolveInfo> resolutions1 = new ArrayList<>();
+ final ResolveInfo resolveInfo1 = new ResolveInfo();
+ resolveInfo1.activityInfo = new ActivityInfo();
+ resolveInfo1.activityInfo.name = aInfoDefault.name;
+ resolveInfo1.activityInfo.applicationInfo = aInfoDefault.applicationInfo;
+ resolutions1.add(resolveInfo1);
+ doReturn(resolutions1).when(mRootActivityContainer).resolveActivities(anyInt(),
+ refEq(homeIntent));
+ final List<ResolveInfo> resolutions2 = new ArrayList<>();
+ final ResolveInfo resolveInfo2 = new ResolveInfo();
+ resolveInfo2.activityInfo = new ActivityInfo();
+ resolveInfo2.activityInfo.name = aInfoSecondary.name;
+ resolveInfo2.activityInfo.applicationInfo = aInfoSecondary.applicationInfo;
+ resolutions2.add(resolveInfo2);
+ doReturn(resolutions2).when(mRootActivityContainer).resolveActivities(anyInt(),
+ refEq(secondaryHomeIntent));
+ doReturn(true).when(mRootActivityContainer).canStartHomeOnDisplay(
+ any(), anyInt(), anyBoolean());
+
+ // Run the test
+ final Pair<ActivityInfo, Intent> resolvedInfo = mRootActivityContainer
+ .resolveSecondaryHomeActivity(0 /* userId */, 1 /* displayId */);
+ assertEquals(secondaryComp.getClassName(), resolvedInfo.first.name);
+ assertEquals(secondaryComp.getPackageName(),
+ resolvedInfo.first.applicationInfo.packageName);
+ assertEquals(aInfoSecondary.name, resolvedInfo.first.name);
+ } finally {
+ // tearDown
+ reset(resources);
+ }
+ }
+
+ /**
* Tests that secondary home should be selected if default home not support secondary displays
* or there is no matched activity in the same package as selected default home.
*/
diff --git a/services/usb/java/com/android/server/usb/UsbSerialReader.java b/services/usb/java/com/android/server/usb/UsbSerialReader.java
index 32fc796e7e05..8ca77f0c63dc 100644
--- a/services/usb/java/com/android/server/usb/UsbSerialReader.java
+++ b/services/usb/java/com/android/server/usb/UsbSerialReader.java
@@ -85,22 +85,22 @@ class UsbSerialReader extends IUsbSerialReader.Stub {
throw new RemoteException("package " + packageName + " cannot be found");
}
packageTargetSdkVersion = pkg.applicationInfo.targetSdkVersion;
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- if (packageTargetSdkVersion >= Build.VERSION_CODES.Q) {
- if (mContext.checkPermission(android.Manifest.permission.MANAGE_USB, pid, uid)
- == PackageManager.PERMISSION_DENIED) {
- UsbUserSettingsManager settings = mSettingsManager.getSettingsForUser(
- UserHandle.getUserId(uid));
+ if (packageTargetSdkVersion >= Build.VERSION_CODES.Q) {
+ if (mContext.checkPermission(android.Manifest.permission.MANAGE_USB, pid, uid)
+ == PackageManager.PERMISSION_DENIED) {
+ UsbUserSettingsManager settings = mSettingsManager.getSettingsForUser(
+ UserHandle.getUserId(uid));
- if (mDevice instanceof UsbDevice) {
- settings.checkPermission((UsbDevice) mDevice, packageName, uid);
- } else {
- settings.checkPermission((UsbAccessory) mDevice, uid);
+ if (mDevice instanceof UsbDevice) {
+ settings.checkPermission((UsbDevice) mDevice, packageName, uid);
+ } else {
+ settings.checkPermission((UsbAccessory) mDevice, uid);
+ }
}
}
+ } finally {
+ Binder.restoreCallingIdentity(token);
}
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 5175c1daf3c0..a125e319d35f 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1973,26 +1973,6 @@ public class CarrierConfigManager {
public static final String KEY_CARRIER_WIFI_STRING_ARRAY = "carrier_wifi_string_array";
/**
- * Base64 Encoding method the carrier will use for encoding encrypted IMSI and SSID.
- * The value set as below:
- * 2045 - RFC2045 (default value)
- * 4648 - RFC4648
- *
- * @hide
- */
- public static final String KEY_IMSI_ENCODING_METHOD_INT = "imsi_encoding_method_int";
-
- /**
- * Defines the sequence of sending an encrypted IMSI identity for EAP-SIM/AKA authentication.
- * The value set as below:
- * 1 - encrypted IMSI as EAP-RESPONSE/IDENTITY (default one).
- * 2 - anonymous as EAP-RESPONSE/IDENTITY -> encrypted IMSI as EAP-RESPONSE/AKA|SIM-IDENTITY.
- *
- * @hide
- */
- public static final String KEY_EAP_IDENTITY_SEQUENCE_INT = "imsi_eap_identity_sequence_int";
-
- /**
* Time delay (in ms) after which we show the notification to switch the preferred
* network.
* @hide
@@ -3265,8 +3245,6 @@ public class CarrierConfigManager {
sDefaults.putBoolean(KEY_STK_DISABLE_LAUNCH_BROWSER_BOOL, false);
sDefaults.putBoolean(KEY_ALLOW_METERED_NETWORK_FOR_CERT_DOWNLOAD_BOOL, false);
sDefaults.putStringArray(KEY_CARRIER_WIFI_STRING_ARRAY, null);
- sDefaults.putInt(KEY_IMSI_ENCODING_METHOD_INT, 2045);
- sDefaults.putInt(KEY_EAP_IDENTITY_SEQUENCE_INT, 1);
sDefaults.putInt(KEY_PREF_NETWORK_NOTIFICATION_DELAY_INT, -1);
sDefaults.putInt(KEY_EMERGENCY_NOTIFICATION_DELAY_INT, -1);
sDefaults.putBoolean(KEY_ALLOW_USSD_REQUESTS_VIA_TELEPHONY_MANAGER_BOOL, true);
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index 984d8f705a65..5d39a2cc194a 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -341,6 +341,7 @@ public class ServiceState implements Parcelable {
private String mOperatorAlphaLongRaw;
private String mOperatorAlphaShortRaw;
+ private boolean mIsIwlanPreferred;
/**
* get String description of roaming type
@@ -427,6 +428,7 @@ public class ServiceState implements Parcelable {
mNrFrequencyRange = s.mNrFrequencyRange;
mOperatorAlphaLongRaw = s.mOperatorAlphaLongRaw;
mOperatorAlphaShortRaw = s.mOperatorAlphaShortRaw;
+ mIsIwlanPreferred = s.mIsIwlanPreferred;
}
/**
@@ -463,6 +465,7 @@ public class ServiceState implements Parcelable {
mNrFrequencyRange = in.readInt();
mOperatorAlphaLongRaw = in.readString();
mOperatorAlphaShortRaw = in.readString();
+ mIsIwlanPreferred = in.readBoolean();
}
public void writeToParcel(Parcel out, int flags) {
@@ -492,6 +495,7 @@ public class ServiceState implements Parcelable {
out.writeInt(mNrFrequencyRange);
out.writeString(mOperatorAlphaLongRaw);
out.writeString(mOperatorAlphaShortRaw);
+ out.writeBoolean(mIsIwlanPreferred);
}
public int describeContents() {
@@ -853,7 +857,8 @@ public class ServiceState implements Parcelable {
mNetworkRegistrationInfos,
mNrFrequencyRange,
mOperatorAlphaLongRaw,
- mOperatorAlphaShortRaw);
+ mOperatorAlphaShortRaw,
+ mIsIwlanPreferred);
}
}
@@ -885,7 +890,8 @@ public class ServiceState implements Parcelable {
&& equalsHandlesNulls(mOperatorAlphaShortRaw, s.mOperatorAlphaShortRaw)
&& mNetworkRegistrationInfos.size() == s.mNetworkRegistrationInfos.size()
&& mNetworkRegistrationInfos.containsAll(s.mNetworkRegistrationInfos)
- && mNrFrequencyRange == s.mNrFrequencyRange;
+ && mNrFrequencyRange == s.mNrFrequencyRange
+ && mIsIwlanPreferred == s.mIsIwlanPreferred;
}
}
@@ -1043,6 +1049,7 @@ public class ServiceState implements Parcelable {
.append(", mNrFrequencyRange=").append(mNrFrequencyRange)
.append(", mOperatorAlphaLongRaw=").append(mOperatorAlphaLongRaw)
.append(", mOperatorAlphaShortRaw=").append(mOperatorAlphaShortRaw)
+ .append(", mIsIwlanPreferred=").append(mIsIwlanPreferred)
.append("}").toString();
}
}
@@ -1085,6 +1092,7 @@ public class ServiceState implements Parcelable {
}
mOperatorAlphaLongRaw = null;
mOperatorAlphaShortRaw = null;
+ mIsIwlanPreferred = false;
}
public void setStateOutOfService() {
@@ -1459,20 +1467,9 @@ public class ServiceState implements Parcelable {
/** @hide */
@UnsupportedAppUsage
public int getRilDataRadioTechnology() {
- NetworkRegistrationInfo wwanRegInfo = getNetworkRegistrationInfo(
- NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
- NetworkRegistrationInfo wlanRegInfo = getNetworkRegistrationInfo(
- NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
- if (wlanRegInfo != null
- && wlanRegInfo.getAccessNetworkTechnology() == TelephonyManager.NETWORK_TYPE_IWLAN
- && wlanRegInfo.getRegistrationState()
- == NetworkRegistrationInfo.REGISTRATION_STATE_HOME) {
- return RIL_RADIO_TECHNOLOGY_IWLAN;
- } else if (wwanRegInfo != null) {
- return networkTypeToRilRadioTechnology(wwanRegInfo.getAccessNetworkTechnology());
- }
- return RIL_RADIO_TECHNOLOGY_UNKNOWN;
+ return networkTypeToRilRadioTechnology(getDataNetworkType());
}
+
/**
* @hide
* @Deprecated to be removed Q3 2013 use {@link #getRilDataRadioTechnology} or
@@ -1608,26 +1605,40 @@ public class ServiceState implements Parcelable {
}
}
- /** @hide */
+ /**
+ * Get current data network type.
+ *
+ * Note that for IWLAN AP-assisted mode device, which is reporting both camped access networks
+ * (cellular RAT and IWLAN)at the same time, this API is simulating the old legacy mode device
+ * behavior,
+ *
+ * @return Current data network type
+ * @hide
+ */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public @TelephonyManager.NetworkType int getDataNetworkType() {
- final NetworkRegistrationInfo iwlanRegState = getNetworkRegistrationInfo(
+ final NetworkRegistrationInfo iwlanRegInfo = getNetworkRegistrationInfo(
NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
- if (iwlanRegState != null && iwlanRegState.getRegistrationState()
- == NetworkRegistrationInfo.REGISTRATION_STATE_HOME) {
- // If the device is on IWLAN, return IWLAN as the network type. This is to simulate the
- // behavior of legacy mode device. In the future caller should use
- // requestNetworkRegistrationInfo() to retrieve the actual data network type on cellular
- // or on IWLAN.
- return iwlanRegState.getAccessNetworkTechnology();
+ final NetworkRegistrationInfo wwanRegInfo = getNetworkRegistrationInfo(
+ NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+
+ // For legacy mode device, or AP-assisted mode device but IWLAN is out of service, use
+ // the RAT from cellular.
+ if (iwlanRegInfo == null || !iwlanRegInfo.isInService()) {
+ return (wwanRegInfo != null) ? wwanRegInfo.getAccessNetworkTechnology()
+ : TelephonyManager.NETWORK_TYPE_UNKNOWN;
}
- final NetworkRegistrationInfo regState = getNetworkRegistrationInfo(
- NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
- if (regState != null) {
- return regState.getAccessNetworkTechnology();
+ // At this point, it must be an AP-assisted mode device and IWLAN is in service. We should
+ // use the RAT from IWLAN service is cellular is out of service, or when both are in service
+ // and any APN type of data is preferred on IWLAN.
+ if (!wwanRegInfo.isInService() || mIsIwlanPreferred) {
+ return iwlanRegInfo.getAccessNetworkTechnology();
}
- return TelephonyManager.NETWORK_TYPE_UNKNOWN;
+
+ // If both cellular and IWLAN are in service, but no APN is preferred on IWLAN, still use
+ // the RAT from cellular.
+ return wwanRegInfo.getAccessNetworkTechnology();
}
/** @hide */
@@ -1976,4 +1987,14 @@ public class ServiceState implements Parcelable {
public String getOperatorAlphaShortRaw() {
return mOperatorAlphaShortRaw;
}
+
+ /**
+ * Set to {@code true} if any data network is preferred on IWLAN.
+ *
+ * @param isIwlanPreferred {@code true} if IWLAN is preferred.
+ * @hide
+ */
+ public void setIwlanPreferred(boolean isIwlanPreferred) {
+ mIsIwlanPreferred = isIwlanPreferred;
+ }
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index d63c37accb37..2ba34c6c3453 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -5356,18 +5356,30 @@ public class TelephonyManager {
* Returns the MMS user agent.
*/
public String getMmsUserAgent() {
- if (mContext == null) return null;
- return SubscriptionManager.getResourcesForSubId(mContext, getSubId()).getString(
- com.android.internal.R.string.config_mms_user_agent);
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.getMmsUserAgent(getSubId());
+ }
+ } catch (RemoteException ex) {
+ } catch (NullPointerException ex) {
+ }
+ return null;
}
/**
* Returns the MMS user agent profile URL.
*/
public String getMmsUAProfUrl() {
- if (mContext == null) return null;
- return SubscriptionManager.getResourcesForSubId(mContext, getSubId()).getString(
- com.android.internal.R.string.config_mms_user_agent_profile_url);
+ try {
+ ITelephony telephony = getITelephony();
+ if (telephony != null) {
+ return telephony.getMmsUAProfUrl(getSubId());
+ }
+ } catch (RemoteException ex) {
+ } catch (NullPointerException ex) {
+ }
+ return null;
}
/**
diff --git a/telephony/java/android/telephony/emergency/EmergencyNumber.java b/telephony/java/android/telephony/emergency/EmergencyNumber.java
index 7b5145740b08..511adf6ad65b 100644
--- a/telephony/java/android/telephony/emergency/EmergencyNumber.java
+++ b/telephony/java/android/telephony/emergency/EmergencyNumber.java
@@ -299,7 +299,7 @@ public final class EmergencyNumber implements Parcelable, Comparable<EmergencyNu
* Get the dialing number of the emergency number.
*
* The character in the number string is only the dial pad
- * character('0'-'9', '*', or '#'). For example: 911.
+ * character('0'-'9', '*', '+', or '#'). For example: 911.
*
* @return the dialing number.
*/
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 63aded1c4b20..cf1323a328fe 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1986,4 +1986,14 @@ interface ITelephony {
* outgoing SmsManager operation.
*/
oneway void enqueueSmsPickResult(String callingPackage, IIntegerConsumer subIdResult);
+
+ /**
+ * Returns the MMS user agent.
+ */
+ String getMmsUserAgent(int subId);
+
+ /**
+ * Returns the MMS user agent profile URL.
+ */
+ String getMmsUAProfUrl(int subId);
}
diff --git a/tests/PackageWatchdog/Android.bp b/tests/PackageWatchdog/Android.bp
index b07996568839..88d92c4d94fe 100644
--- a/tests/PackageWatchdog/Android.bp
+++ b/tests/PackageWatchdog/Android.bp
@@ -18,11 +18,18 @@ android_test {
srcs: ["src/**/*.java"],
static_libs: [
"junit",
+ "mockito-target-extended-minus-junit4",
"frameworks-base-testutils",
"androidx.test.rules",
"services.core",
+ "services.net",
],
libs: ["android.test.runner"],
+ jni_libs: [
+ // mockito-target-extended dependencies
+ "libdexmakerjvmtiagent",
+ "libstaticjvmtiagent",
+ ],
platform_apis: true,
test_suites: ["device-tests"],
}
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index eb19361d86a3..232b5cb17023 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -23,10 +23,20 @@ import static org.junit.Assert.assertFalse;
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.anyString;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.Manifest;
import android.content.Context;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
+import android.net.NetworkStackClient;
+import android.net.NetworkStackClient.NetworkStackHealthListener;
import android.os.Handler;
import android.os.test.TestLooper;
import android.provider.DeviceConfig;
@@ -41,6 +51,10 @@ import com.android.server.PackageWatchdog.PackageHealthObserverImpact;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import java.io.File;
import java.util.ArrayList;
@@ -70,13 +84,29 @@ public class PackageWatchdogTest {
private static final long SHORT_DURATION = TimeUnit.SECONDS.toMillis(1);
private static final long LONG_DURATION = TimeUnit.SECONDS.toMillis(5);
private TestLooper mTestLooper;
+ private Context mSpyContext;
+ @Mock
+ private NetworkStackClient mMockNetworkStackClient;
+ @Mock
+ private PackageManager mMockPackageManager;
+ @Captor
+ private ArgumentCaptor<NetworkStackHealthListener> mNetworkStackCallbackCaptor;
@Before
public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
new File(InstrumentationRegistry.getContext().getFilesDir(),
"package-watchdog.xml").delete();
adoptShellPermissions(Manifest.permission.READ_DEVICE_CONFIG);
mTestLooper = new TestLooper();
+ mSpyContext = spy(InstrumentationRegistry.getContext());
+ when(mSpyContext.getPackageManager()).thenReturn(mMockPackageManager);
+ when(mMockPackageManager.getPackageInfo(anyString(), anyInt())).then(inv -> {
+ final PackageInfo res = new PackageInfo();
+ res.packageName = inv.getArgument(0);
+ res.setLongVersionCode(VERSION_CODE);
+ return res;
+ });
}
@After
@@ -696,6 +726,26 @@ public class PackageWatchdogTest {
assertEquals(MonitoredPackage.STATE_PASSED, m4.handleElapsedTimeLocked(LONG_DURATION));
}
+ @Test
+ public void testNetworkStackFailure() {
+ final PackageWatchdog wd = createWatchdog();
+
+ // Start observing with failure handling
+ TestObserver observer = new TestObserver(OBSERVER_NAME_1,
+ PackageHealthObserverImpact.USER_IMPACT_HIGH);
+ wd.startObservingHealth(observer, Collections.singletonList(APP_A), SHORT_DURATION);
+
+ // Notify of NetworkStack failure
+ mNetworkStackCallbackCaptor.getValue().onNetworkStackFailure(APP_A);
+
+ // Run handler so package failures are dispatched to observers
+ mTestLooper.dispatchAll();
+
+ // Verify the NetworkStack observer is notified
+ assertEquals(1, observer.mFailedPackages.size());
+ assertEquals(APP_A, observer.mFailedPackages.get(0));
+ }
+
private void adoptShellPermissions(String... permissions) {
InstrumentationRegistry
.getInstrumentation()
@@ -727,18 +777,23 @@ public class PackageWatchdogTest {
}
private PackageWatchdog createWatchdog(TestController controller, boolean withPackagesReady) {
- Context context = InstrumentationRegistry.getContext();
AtomicFile policyFile =
- new AtomicFile(new File(context.getFilesDir(), "package-watchdog.xml"));
+ new AtomicFile(new File(mSpyContext.getFilesDir(), "package-watchdog.xml"));
Handler handler = new Handler(mTestLooper.getLooper());
PackageWatchdog watchdog =
- new PackageWatchdog(context, policyFile, handler, handler, controller);
+ new PackageWatchdog(mSpyContext, policyFile, handler, handler, controller,
+ mMockNetworkStackClient);
// Verify controller is not automatically started
assertFalse(controller.mIsEnabled);
if (withPackagesReady) {
+ // Only capture the NetworkStack callback for the latest registered watchdog
+ reset(mMockNetworkStackClient);
watchdog.onPackagesReady();
// Verify controller by default is started when packages are ready
assertTrue(controller.mIsEnabled);
+
+ verify(mMockNetworkStackClient).registerHealthListener(
+ mNetworkStackCallbackCaptor.capture());
}
return watchdog;
}
diff --git a/tests/RollbackTest/Android.bp b/tests/RollbackTest/Android.bp
index 1cf3d364a8d5..aec40558ad51 100644
--- a/tests/RollbackTest/Android.bp
+++ b/tests/RollbackTest/Android.bp
@@ -95,7 +95,7 @@ android_test {
":RollbackTestAppASplitV2",
],
test_config: "RollbackTest.xml",
- sdk_version: "test_current",
+ // TODO: sdk_version: "test_current" when Intent#resolveSystemservice is TestApi
}
java_test_host {
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
index 81629aaaec76..a9e20cdb191b 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
@@ -28,6 +28,7 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
@@ -82,13 +83,31 @@ class RollbackTestUtils {
* Returns -1 if the package is not currently installed.
*/
static long getInstalledVersion(String packageName) {
+ PackageInfo pi = getPackageInfo(packageName);
+ if (pi == null) {
+ return -1;
+ } else {
+ return pi.getLongVersionCode();
+ }
+ }
+
+ private static boolean isSystemAppWithoutUpdate(String packageName) {
+ PackageInfo pi = getPackageInfo(packageName);
+ if (pi == null) {
+ return false;
+ } else {
+ return ((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0)
+ && ((pi.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) == 0);
+ }
+ }
+
+ private static PackageInfo getPackageInfo(String packageName) {
Context context = InstrumentationRegistry.getContext();
PackageManager pm = context.getPackageManager();
try {
- PackageInfo info = pm.getPackageInfo(packageName, PackageManager.MATCH_APEX);
- return info.getLongVersionCode();
+ return pm.getPackageInfo(packageName, PackageManager.MATCH_APEX);
} catch (PackageManager.NameNotFoundException e) {
- return -1;
+ return null;
}
}
@@ -109,8 +128,8 @@ class RollbackTestUtils {
* @throws AssertionError if package can't be uninstalled.
*/
static void uninstall(String packageName) throws InterruptedException, IOException {
- // No need to uninstall if the package isn't installed.
- if (getInstalledVersion(packageName) == -1) {
+ // No need to uninstall if the package isn't installed or is installed on /system.
+ if (getInstalledVersion(packageName) == -1 || isSystemAppWithoutUpdate(packageName)) {
return;
}
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
index 1ddfa6ee54ce..1a29c4c11457 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java
@@ -21,7 +21,9 @@ import static com.android.tests.rollback.RollbackTestUtils.getUniqueRollbackInfo
import android.Manifest;
import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.VersionedPackage;
import android.content.rollback.RollbackInfo;
import android.content.rollback.RollbackManager;
@@ -30,6 +32,8 @@ import androidx.test.InstrumentationRegistry;
import static org.junit.Assert.assertEquals;
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.junit.Assert.fail;
@@ -54,6 +58,8 @@ public class StagedRollbackTest {
private static final String TEST_APP_A = "com.android.tests.rollback.testapp.A";
private static final String TEST_APP_A_V1 = "RollbackTestAppAv1.apk";
private static final String TEST_APP_A_CRASHING_V2 = "RollbackTestAppACrashingV2.apk";
+ private static final String NETWORK_STACK_CONNECTOR_CLASS =
+ "android.net.INetworkStackConnector";
/**
* Adopts common shell permissions needed for rollback tests.
@@ -157,4 +163,44 @@ public class StagedRollbackTest {
assertTrue(rollback.isStaged());
assertNotEquals(-1, rollback.getCommittedSessionId());
}
+
+ @Test
+ public void resetNetworkStack() throws Exception {
+ RollbackManager rm = RollbackTestUtils.getRollbackManager();
+ String networkStack = getNetworkStackPackageName();
+
+ rm.expireRollbackForPackage(networkStack);
+ RollbackTestUtils.uninstall(networkStack);
+
+ assertNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
+ networkStack));
+ }
+
+ @Test
+ public void assertNetworkStackRollbackAvailable() throws Exception {
+ RollbackManager rm = RollbackTestUtils.getRollbackManager();
+ assertNotNull(getUniqueRollbackInfoForPackage(rm.getAvailableRollbacks(),
+ getNetworkStackPackageName()));
+ }
+
+ @Test
+ public void assertNetworkStackRollbackCommitted() throws Exception {
+ RollbackManager rm = RollbackTestUtils.getRollbackManager();
+ assertNotNull(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(),
+ getNetworkStackPackageName()));
+ }
+
+ @Test
+ public void assertNoNetworkStackRollbackCommitted() throws Exception {
+ RollbackManager rm = RollbackTestUtils.getRollbackManager();
+ assertNull(getUniqueRollbackInfoForPackage(rm.getRecentlyCommittedRollbacks(),
+ getNetworkStackPackageName()));
+ }
+
+ private String getNetworkStackPackageName() {
+ Intent intent = new Intent(NETWORK_STACK_CONNECTOR_CLASS);
+ ComponentName comp = intent.resolveSystemService(
+ InstrumentationRegistry.getContext().getPackageManager(), 0);
+ return comp.getPackageName();
+ }
}
diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
index 75a95adf460a..bad294794337 100644
--- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
+++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java
@@ -23,6 +23,8 @@ import com.android.tradefed.log.LogUtil.CLog;
import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import org.junit.After;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -43,6 +45,20 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
phase));
}
+ @Before
+ public void setUp() throws Exception {
+ // Disconnect internet so we can test network health triggered rollbacks
+ getDevice().executeShellCommand("svc wifi disable");
+ getDevice().executeShellCommand("svc data disable");
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ // Reconnect internet after testing network health triggered rollbacks
+ getDevice().executeShellCommand("svc wifi enable");
+ getDevice().executeShellCommand("svc data enable");
+ }
+
/**
* Tests watchdog triggered staged rollbacks involving only apks.
*/
@@ -63,6 +79,90 @@ public class StagedRollbackTest extends BaseHostJUnit4Test {
}
getDevice().waitForDeviceAvailable();
+
runPhase("testBadApkOnlyConfirmRollback");
}
+
+ /**
+ * Tests failed network health check triggers watchdog staged rollbacks.
+ */
+ @Test
+ public void testNetworkFailedRollback() throws Exception {
+ // Remove available rollbacks and uninstall NetworkStack on /data/
+ runPhase("resetNetworkStack");
+ // Reduce health check deadline
+ getDevice().executeShellCommand("device_config put rollback "
+ + "watchdog_request_timeout_millis 300000");
+ // Simulate re-installation of new NetworkStack with rollbacks enabled
+ getDevice().executeShellCommand("pm install -r --staged --enable-rollback "
+ + "/system/priv-app/NetworkStack/NetworkStack.apk");
+
+ // Sleep to allow writes to disk before reboot
+ Thread.sleep(5000);
+ // Reboot device to activate staged package
+ getDevice().reboot();
+ getDevice().waitForDeviceAvailable();
+
+ // Verify rollback was enabled
+ runPhase("assertNetworkStackRollbackAvailable");
+
+ // Sleep for < health check deadline
+ Thread.sleep(5000);
+ // Verify rollback was not executed before health check deadline
+ runPhase("assertNoNetworkStackRollbackCommitted");
+ try {
+ // This is expected to fail due to the device being rebooted out
+ // from underneath the test. If this fails for reasons other than
+ // the device reboot, those failures should result in failure of
+ // the assertNetworkStackExecutedRollback phase.
+ CLog.logAndDisplay(LogLevel.INFO, "Sleep and expect to fail while sleeping");
+ // Sleep for > health check deadline
+ Thread.sleep(260000);
+ } catch (AssertionError e) {
+ // AssertionError is expected.
+ }
+
+ getDevice().waitForDeviceAvailable();
+ // Verify rollback was executed after health check deadline
+ runPhase("assertNetworkStackRollbackCommitted");
+ }
+
+ /**
+ * Tests passed network health check does not trigger watchdog staged rollbacks.
+ */
+ @Test
+ public void testNetworkPassedDoesNotRollback() throws Exception {
+ // Remove available rollbacks and uninstall NetworkStack on /data/
+ runPhase("resetNetworkStack");
+ // Reduce health check deadline, here unlike the network failed case, we use
+ // a longer deadline because joining a network can take a much longer time for
+ // reasons external to the device than 'not joining'
+ getDevice().executeShellCommand("device_config put rollback "
+ + "watchdog_request_timeout_millis 300000");
+ // Simulate re-installation of new NetworkStack with rollbacks enabled
+ getDevice().executeShellCommand("pm install -r --staged --enable-rollback "
+ + "/system/priv-app/NetworkStack/NetworkStack.apk");
+
+ // Sleep to allow writes to disk before reboot
+ Thread.sleep(5000);
+ // Reboot device to activate staged package
+ getDevice().reboot();
+ getDevice().waitForDeviceAvailable();
+
+ // Verify rollback was enabled
+ runPhase("assertNetworkStackRollbackAvailable");
+
+ // Connect to internet so network health check passes
+ getDevice().executeShellCommand("svc wifi enable");
+ getDevice().executeShellCommand("svc data enable");
+
+ // Wait for device available because emulator device may restart after turning
+ // on mobile data
+ getDevice().waitForDeviceAvailable();
+
+ // Sleep for > health check deadline
+ Thread.sleep(310000);
+ // Verify rollback was not executed after health check deadline
+ runPhase("assertNoNetworkStackRollbackCommitted");
+ }
}
diff --git a/tests/net/java/android/net/NetworkStatsTest.java b/tests/net/java/android/net/NetworkStatsTest.java
index b5b0384ca599..c16a0f446651 100644
--- a/tests/net/java/android/net/NetworkStatsTest.java
+++ b/tests/net/java/android/net/NetworkStatsTest.java
@@ -569,7 +569,7 @@ public class NetworkStatsTest {
.addValues(underlyingIface, tunUid, SET_FOREGROUND, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 0L, 0L, 0L, 0L, 0L);
- assertTrue(delta.toString(), delta.migrateTun(tunUid, tunIface, underlyingIface));
+ delta.migrateTun(tunUid, tunIface, new String[] {underlyingIface});
assertEquals(20, delta.size());
// tunIface and TEST_IFACE entries are not changed.
@@ -650,7 +650,7 @@ public class NetworkStatsTest {
.addValues(underlyingIface, tunUid, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
DEFAULT_NETWORK_NO, 75500L, 37L, 130000L, 70L, 0L);
- assertTrue(delta.migrateTun(tunUid, tunIface, underlyingIface));
+ delta.migrateTun(tunUid, tunIface, new String[]{underlyingIface});
assertEquals(9, delta.size());
// tunIface entries should not be changed.
@@ -813,6 +813,37 @@ public class NetworkStatsTest {
}
@Test
+ public void testFilterDebugEntries() {
+ NetworkStats.Entry entry1 = new NetworkStats.Entry(
+ "test1", 10100, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry2 = new NetworkStats.Entry(
+ "test2", 10101, SET_DBG_VPN_IN, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry3 = new NetworkStats.Entry(
+ "test2", 10101, SET_DEFAULT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats.Entry entry4 = new NetworkStats.Entry(
+ "test2", 10101, SET_DBG_VPN_OUT, TAG_NONE, METERED_NO, ROAMING_NO,
+ DEFAULT_NETWORK_NO, 50000L, 25L, 100000L, 50L, 0L);
+
+ NetworkStats stats = new NetworkStats(TEST_START, 4)
+ .addValues(entry1)
+ .addValues(entry2)
+ .addValues(entry3)
+ .addValues(entry4);
+
+ stats.filterDebugEntries();
+
+ assertEquals(2, stats.size());
+ assertEquals(entry1, stats.getValues(0, null));
+ assertEquals(entry3, stats.getValues(1, null));
+ }
+
+ @Test
public void testApply464xlatAdjustments() {
final String v4Iface = "v4-wlan0";
final String baseIface = "wlan0";
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index 2cae2509026c..ce50bef53d75 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -727,94 +727,4 @@ public class VpnTest {
"::/1", "8000::/2", "c000::/3", "e000::/4", "f000::/5", "f800::/6",
"fe00::/8", "2605:ef80:e:af1d::/64");
}
-
- @Test
- public void testProvidesRoutesToMostDestinations() {
- final LinkProperties lp = new LinkProperties();
-
- // Default route provides routes to all IPv4 destinations.
- lp.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0")));
- assertTrue(Vpn.providesRoutesToMostDestinations(lp));
-
- // Empty LP provides routes to no destination
- lp.clear();
- assertFalse(Vpn.providesRoutesToMostDestinations(lp));
-
- // All IPv4 routes except for local networks. This is the case most relevant
- // to this function. It provides routes to almost the entire space.
- // (clone the stream so that we can reuse it later)
- publicIpV4Routes().forEach(s -> lp.addRoute(new RouteInfo(new IpPrefix(s))));
- assertTrue(Vpn.providesRoutesToMostDestinations(lp));
-
- // Removing a 16-bit prefix, which is 65536 addresses. This is still enough to
- // provide routes to "most" destinations.
- lp.removeRoute(new RouteInfo(new IpPrefix("192.169.0.0/16")));
- assertTrue(Vpn.providesRoutesToMostDestinations(lp));
-
- // Remove the /2 route, which represent a quarter of the available routing space.
- // This LP does not provides routes to "most" destinations any more.
- lp.removeRoute(new RouteInfo(new IpPrefix("64.0.0.0/2")));
- assertFalse(Vpn.providesRoutesToMostDestinations(lp));
-
- lp.clear();
- publicIpV6Routes().forEach(s -> lp.addRoute(new RouteInfo(new IpPrefix(s))));
- assertTrue(Vpn.providesRoutesToMostDestinations(lp));
-
- lp.removeRoute(new RouteInfo(new IpPrefix("::/1")));
- assertFalse(Vpn.providesRoutesToMostDestinations(lp));
-
- // V6 does not provide sufficient coverage but v4 does
- publicIpV4Routes().forEach(s -> lp.addRoute(new RouteInfo(new IpPrefix(s))));
- assertTrue(Vpn.providesRoutesToMostDestinations(lp));
-
- // V4 still does
- lp.removeRoute(new RouteInfo(new IpPrefix("192.169.0.0/16")));
- assertTrue(Vpn.providesRoutesToMostDestinations(lp));
-
- // V4 does not any more
- lp.removeRoute(new RouteInfo(new IpPrefix("64.0.0.0/2")));
- assertFalse(Vpn.providesRoutesToMostDestinations(lp));
-
- // V4 does not, but V6 has sufficient coverage again
- lp.addRoute(new RouteInfo(new IpPrefix("::/1")));
- assertTrue(Vpn.providesRoutesToMostDestinations(lp));
-
- lp.clear();
- // V4-unreachable route should not be treated as sufficient coverage
- lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), RTN_UNREACHABLE));
- assertFalse(Vpn.providesRoutesToMostDestinations(lp));
-
- lp.clear();
- // V6-unreachable route should not be treated as sufficient coverage
- lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
- assertFalse(Vpn.providesRoutesToMostDestinations(lp));
- }
-
- @Test
- public void testDoesNotLockUpWithTooManyRoutes() {
- final LinkProperties lp = new LinkProperties();
- final byte[] ad = new byte[4];
- // Actually evaluating this many routes under 1500ms is impossible on
- // current hardware and for some time, as the algorithm is O(n²).
- // Make sure the system has a safeguard against this and does not
- // lock up.
- final int MAX_ROUTES = 4000;
- final long MAX_ALLOWED_TIME_MS = 1500;
- for (int i = 0; i < MAX_ROUTES; ++i) {
- ad[0] = (byte)((i >> 24) & 0xFF);
- ad[1] = (byte)((i >> 16) & 0xFF);
- ad[2] = (byte)((i >> 8) & 0xFF);
- ad[3] = (byte)(i & 0xFF);
- try {
- lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.getByAddress(ad), 32)));
- } catch (UnknownHostException e) {
- // UnknownHostException is only thrown for an address of illegal length,
- // which can't happen in the case above.
- }
- }
- final long start = SystemClock.currentThreadTimeMillis();
- assertTrue(Vpn.providesRoutesToMostDestinations(lp));
- final long end = SystemClock.currentThreadTimeMillis();
- assertTrue(end - start < MAX_ALLOWED_TIME_MS);
- }
}
diff --git a/tests/net/java/com/android/server/net/NetworkStatsAccessTest.java b/tests/net/java/com/android/server/net/NetworkStatsAccessTest.java
index 6e725dd69cb7..858358c74f80 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsAccessTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsAccessTest.java
@@ -161,7 +161,7 @@ public class NetworkStatsAccessTest {
}
private void setHasCarrierPrivileges(boolean hasPrivileges) {
- when(mTm.checkCarrierPrivilegesForPackage(TEST_PKG)).thenReturn(
+ when(mTm.checkCarrierPrivilegesForPackageAnyPhone(TEST_PKG)).thenReturn(
hasPrivileges ? TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS
: TelephonyManager.CARRIER_PRIVILEGE_STATUS_NO_ACCESS);
}
diff --git a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
index bce526d3ae29..d9f2c201fe37 100644
--- a/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -57,11 +57,11 @@ import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_PO
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
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.times;
import static org.mockito.Mockito.verify;
@@ -216,11 +216,16 @@ public class NetworkStatsServiceTest {
expectNetworkStatsUidDetail(buildEmptyStats());
expectSystemReady();
+ assertNull(mService.getTunAdjustedStats());
mService.systemReady();
+ // Verify that system ready fetches realtime stats and initializes tun adjusted stats.
+ verify(mNetManager).getNetworkStatsUidDetail(UID_ALL, INTERFACES_ALL);
+ assertNotNull("failed to initialize TUN adjusted stats", mService.getTunAdjustedStats());
+ assertEquals(0, mService.getTunAdjustedStats().size());
+
mSession = mService.openSession();
assertNotNull("openSession() failed", mSession);
-
// catch INetworkManagementEventObserver during systemReady()
ArgumentCaptor<INetworkManagementEventObserver> networkObserver =
ArgumentCaptor.forClass(INetworkManagementEventObserver.class);
@@ -733,11 +738,13 @@ public class NetworkStatsServiceTest {
NetworkStats stats = mService.getDetailedUidStats(ifaceFilter);
- verify(mNetManager, times(1)).getNetworkStatsUidDetail(eq(UID_ALL), argThat(ifaces ->
- ifaces != null && ifaces.length == 2
- && ArrayUtils.contains(ifaces, TEST_IFACE)
- && ArrayUtils.contains(ifaces, stackedIface)));
-
+ // mNetManager#getNetworkStatsUidDetail(UID_ALL, INTERFACES_ALL) has following invocations:
+ // 1) NetworkStatsService#systemReady from #setUp.
+ // 2) mService#forceUpdateIfaces in the test above.
+ // 3) Finally, mService#getDetailedUidStats.
+ verify(mNetManager, times(3)).getNetworkStatsUidDetail(UID_ALL, INTERFACES_ALL);
+ assertTrue(ArrayUtils.contains(stats.getUniqueIfaces(), TEST_IFACE));
+ assertTrue(ArrayUtils.contains(stats.getUniqueIfaces(), stackedIface));
assertEquals(2, stats.size());
assertEquals(uidStats, stats.getValues(0, null));
assertEquals(tetheredStats1, stats.getValues(1, null));
@@ -923,11 +930,70 @@ public class NetworkStatsServiceTest {
}
@Test
+ public void vpnRewriteTrafficThroughItself() throws Exception {
+ // WiFi network is connected and VPN is using WiFi (which has TEST_IFACE).
+ expectDefaultSettings();
+ NetworkState[] networkStates = new NetworkState[] {buildWifiState(), buildVpnState()};
+ VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
+ expectNetworkStatsUidDetail(buildEmptyStats());
+ expectBandwidthControlCheck();
+
+ mService.forceUpdateIfaces(
+ new Network[] {WIFI_NETWORK, VPN_NETWORK},
+ vpnInfos,
+ networkStates,
+ getActiveIface(networkStates));
+ // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
+ // overhead per packet):
+ //
+ // 1000 bytes (100 packets) were sent, and 2000 bytes (200 packets) were received by UID_RED
+ // over VPN.
+ // 500 bytes (50 packets) were sent, and 1000 bytes (100 packets) were received by UID_BLUE
+ // over VPN.
+ //
+ // VPN UID rewrites packets read from TUN back to TUN, plus some of its own traffic
+ // (100 bytes).
+ incrementCurrentTime(HOUR_IN_MILLIS);
+ expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 5)
+ .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 2000L, 200L, 1000L, 100L, 1L)
+ .addValues(TUN_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1000L, 100L, 500L, 50L, 1L)
+ // VPN rewrites all the packets read from TUN + 100 additional bytes of VPN's
+ // own traffic.
+ .addValues(TUN_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 0L, 0L, 1600L, 160L, 2L)
+ // VPN sent 1760 bytes over WiFi in foreground (SET_FOREGROUND) i.e. 1600
+ // bytes (160 packets) + 1 byte/packet overhead (=160 bytes).
+ .addValues(TEST_IFACE, UID_VPN, SET_FOREGROUND, TAG_NONE, 0L, 0L, 1760L, 176L, 1L)
+ // VPN received 3300 bytes over WiFi in background (SET_DEFAULT) i.e. 3000 bytes
+ // (300 packets) + 1 byte/packet encryption overhead (=300 bytes).
+ .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 3300L, 300L, 0L, 0L, 1L));
+
+ forcePollAndWaitForIdle();
+
+ // Verify increased TUN usage by UID_VPN does not get attributed to other apps.
+ NetworkStats tunStats =
+ mService.getDetailedUidStats(new String[] {TUN_IFACE});
+ assertValues(
+ tunStats, TUN_IFACE, UID_RED, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, 2000L, 200L, 1000L, 100L, 1);
+ assertValues(
+ tunStats, TUN_IFACE, UID_BLUE, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, 1000L, 100L, 500L, 50L, 1);
+ assertValues(
+ tunStats, TUN_IFACE, UID_VPN, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, 0L, 0L, 1600L, 160L, 2);
+
+ // Verify correct attribution over WiFi.
+ assertUidTotal(sTemplateWifi, UID_RED, 2000L, 200L, 1000L, 100L, 1);
+ assertUidTotal(sTemplateWifi, UID_BLUE, 1000L, 100L, 500L, 50L, 1);
+ assertUidTotal(sTemplateWifi, UID_VPN, 300L, 0L, 260L, 26L, 2);
+ }
+
+ @Test
public void vpnWithOneUnderlyingIface() throws Exception {
// WiFi network is connected and VPN is using WiFi (which has TEST_IFACE).
expectDefaultSettings();
NetworkState[] networkStates = new NetworkState[] {buildWifiState(), buildVpnState()};
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(TEST_IFACE)};
+ VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
expectNetworkStatsUidDetail(buildEmptyStats());
expectBandwidthControlCheck();
@@ -938,23 +1004,74 @@ public class NetworkStatsServiceTest {
getActiveIface(networkStates));
// create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
// overhead per packet):
- // 1000 bytes (100 packets) were sent/received by UID_RED over VPN.
- // 500 bytes (50 packets) were sent/received by UID_BLUE over VPN.
- // VPN sent/received 1650 bytes (150 packets) over WiFi.
- // Of 1650 bytes over WiFi, expect 1000 bytes attributed to UID_RED, 500 bytes attributed to
- // UID_BLUE, and 150 bytes attributed to UID_VPN for both rx/tx traffic.
+ // 1000 bytes (100 packets) were sent, and 2000 bytes (200 packets) were received by UID_RED
+ // over VPN.
+ // 500 bytes (50 packets) were sent, and 1000 bytes (100 packets) were received by UID_BLUE
+ // over VPN.
+ // VPN sent 1650 bytes (150 packets), and received 3300 (300 packets) over WiFi.
+ // Of 1650 bytes sent over WiFi, expect 1000 bytes attributed to UID_RED, 500 bytes
+ // attributed to UID_BLUE, and 150 bytes attributed to UID_VPN.
+ // Of 3300 bytes received over WiFi, expect 2000 bytes attributed to UID_RED, 1000 bytes
+ // attributed to UID_BLUE, and 300 bytes attributed to UID_VPN.
incrementCurrentTime(HOUR_IN_MILLIS);
expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3)
- .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1000L, 100L, 1000L, 100L, 1L)
- .addValues(TUN_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 500L, 50L, 500L, 50L, 1L)
- .addValues(
- TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 1650L, 150L, 1650L, 150L, 2L));
+ .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 2000L, 200L, 1000L, 100L, 1L)
+ .addValues(TUN_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1000L, 100L, 500L, 50L, 1L)
+ // VPN received 3300 bytes over WiFi in background (SET_DEFAULT).
+ .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 3300L, 300L, 0L, 0L, 1L)
+ // VPN sent 1650 bytes over WiFi in foreground (SET_FOREGROUND).
+ .addValues(TEST_IFACE, UID_VPN, SET_FOREGROUND, TAG_NONE, 0L, 0L, 1650L, 150L, 1L));
forcePollAndWaitForIdle();
- assertUidTotal(sTemplateWifi, UID_RED, 1000L, 100L, 1000L, 100L, 1);
- assertUidTotal(sTemplateWifi, UID_BLUE, 500L, 50L, 500L, 50L, 1);
- assertUidTotal(sTemplateWifi, UID_VPN, 150L, 0L, 150L, 0L, 2);
+ assertUidTotal(sTemplateWifi, UID_RED, 2000L, 200L, 1000L, 100L, 1);
+ assertUidTotal(sTemplateWifi, UID_BLUE, 1000L, 100L, 500L, 50L, 1);
+ assertUidTotal(sTemplateWifi, UID_VPN, 300L, 0L, 150L, 0L, 2);
+ }
+
+ @Test
+ public void vpnWithOneUnderlyingIfaceAndOwnTraffic() throws Exception {
+ // WiFi network is connected and VPN is using WiFi (which has TEST_IFACE).
+ expectDefaultSettings();
+ NetworkState[] networkStates = new NetworkState[] {buildWifiState(), buildVpnState()};
+ VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
+ expectNetworkStatsUidDetail(buildEmptyStats());
+ expectBandwidthControlCheck();
+
+ mService.forceUpdateIfaces(
+ new Network[] {WIFI_NETWORK, VPN_NETWORK},
+ vpnInfos,
+ networkStates,
+ getActiveIface(networkStates));
+ // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
+ // overhead per packet):
+ // 1000 bytes (100 packets) were sent, and 2000 bytes (200 packets) were received by UID_RED
+ // over VPN.
+ // 500 bytes (50 packets) were sent, and 1000 bytes (100 packets) were received by UID_BLUE
+ // over VPN.
+ // Additionally, the VPN sends 6000 bytes (600 packets) of its own traffic into the tun
+ // interface (passing that traffic to the VPN endpoint), and receives 5000 bytes (500
+ // packets) from it. Including overhead that is 6600/5500 bytes.
+ // VPN sent 8250 bytes (750 packets), and received 8800 (800 packets) over WiFi.
+ // Of 8250 bytes sent over WiFi, expect 1000 bytes attributed to UID_RED, 500 bytes
+ // attributed to UID_BLUE, and 6750 bytes attributed to UID_VPN.
+ // Of 8800 bytes received over WiFi, expect 2000 bytes attributed to UID_RED, 1000 bytes
+ // attributed to UID_BLUE, and 5800 bytes attributed to UID_VPN.
+ incrementCurrentTime(HOUR_IN_MILLIS);
+ expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3)
+ .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 2000L, 200L, 1000L, 100L, 1L)
+ .addValues(TUN_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1000L, 100L, 500L, 50L, 1L)
+ .addValues(TUN_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 5000L, 500L, 6000L, 600L, 1L)
+ // VPN received 8800 bytes over WiFi in background (SET_DEFAULT).
+ .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 8800L, 800L, 0L, 0L, 1L)
+ // VPN sent 8250 bytes over WiFi in foreground (SET_FOREGROUND).
+ .addValues(TEST_IFACE, UID_VPN, SET_FOREGROUND, TAG_NONE, 0L, 0L, 8250L, 750L, 1L));
+
+ forcePollAndWaitForIdle();
+
+ assertUidTotal(sTemplateWifi, UID_RED, 2000L, 200L, 1000L, 100L, 1);
+ assertUidTotal(sTemplateWifi, UID_BLUE, 1000L, 100L, 500L, 50L, 1);
+ assertUidTotal(sTemplateWifi, UID_VPN, 5800L, 500L, 6750L, 600L, 2);
}
@Test
@@ -962,7 +1079,7 @@ public class NetworkStatsServiceTest {
// WiFi network is connected and VPN is using WiFi (which has TEST_IFACE).
expectDefaultSettings();
NetworkState[] networkStates = new NetworkState[] {buildWifiState(), buildVpnState()};
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(TEST_IFACE)};
+ VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
expectNetworkStatsUidDetail(buildEmptyStats());
expectBandwidthControlCheck();
@@ -993,6 +1110,136 @@ public class NetworkStatsServiceTest {
}
@Test
+ public void vpnWithTwoUnderlyingIfaces_packetDuplication() throws Exception {
+ // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and
+ // Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set.
+ // Additionally, VPN is duplicating traffic across both WiFi and Cell.
+ expectDefaultSettings();
+ NetworkState[] networkStates =
+ new NetworkState[] {
+ buildWifiState(), buildMobile4gState(TEST_IFACE2), buildVpnState()
+ };
+ VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})};
+ expectNetworkStatsUidDetail(buildEmptyStats());
+ expectBandwidthControlCheck();
+
+ mService.forceUpdateIfaces(
+ new Network[] {WIFI_NETWORK, VPN_NETWORK},
+ vpnInfos,
+ networkStates,
+ getActiveIface(networkStates));
+ // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
+ // overhead per packet):
+ // 1000 bytes (100 packets) were sent/received by UID_RED and UID_BLUE over VPN.
+ // VPN sent/received 4400 bytes (400 packets) over both WiFi and Cell (8800 bytes in total).
+ // Of 8800 bytes over WiFi/Cell, expect:
+ // - 500 bytes rx/tx each over WiFi/Cell attributed to both UID_RED and UID_BLUE.
+ // - 1200 bytes rx/tx each over WiFi/Cell for VPN_UID.
+ incrementCurrentTime(HOUR_IN_MILLIS);
+ expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 4)
+ .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1000L, 100L, 1000L, 100L, 2L)
+ .addValues(TUN_IFACE, UID_BLUE, SET_DEFAULT, TAG_NONE, 1000L, 100L, 1000L, 100L, 2L)
+ .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 2200L, 200L, 2200L, 200L, 2L)
+ .addValues(
+ TEST_IFACE2, UID_VPN, SET_DEFAULT, TAG_NONE, 2200L, 200L, 2200L, 200L, 2L));
+
+ forcePollAndWaitForIdle();
+
+ assertUidTotal(sTemplateWifi, UID_RED, 500L, 50L, 500L, 50L, 1);
+ assertUidTotal(sTemplateWifi, UID_BLUE, 500L, 50L, 500L, 50L, 1);
+ assertUidTotal(sTemplateWifi, UID_VPN, 1200L, 100L, 1200L, 100L, 2);
+
+ assertUidTotal(buildTemplateMobileWildcard(), UID_RED, 500L, 50L, 500L, 50L, 1);
+ assertUidTotal(buildTemplateMobileWildcard(), UID_BLUE, 500L, 50L, 500L, 50L, 1);
+ assertUidTotal(buildTemplateMobileWildcard(), UID_VPN, 1200L, 100L, 1200L, 100L, 2);
+ }
+
+ @Test
+ public void vpnWithTwoUnderlyingIfaces_splitTraffic() throws Exception {
+ // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and
+ // Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set.
+ // Additionally, VPN is arbitrarily splitting traffic across WiFi and Cell.
+ expectDefaultSettings();
+ NetworkState[] networkStates =
+ new NetworkState[] {
+ buildWifiState(), buildMobile4gState(TEST_IFACE2), buildVpnState()
+ };
+ VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})};
+ expectNetworkStatsUidDetail(buildEmptyStats());
+ expectBandwidthControlCheck();
+
+ mService.forceUpdateIfaces(
+ new Network[] {WIFI_NETWORK, VPN_NETWORK},
+ vpnInfos,
+ networkStates,
+ getActiveIface(networkStates));
+ // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
+ // overhead per packet):
+ // 1000 bytes (100 packets) were sent, and 500 bytes (50 packets) received by UID_RED over
+ // VPN.
+ // VPN sent 660 bytes (60 packets) over WiFi and 440 bytes (40 packets) over Cell.
+ // And, it received 330 bytes (30 packets) over WiFi and 220 bytes (20 packets) over Cell.
+ // For UID_RED, expect 600 bytes attributed over WiFi and 400 bytes over Cell for sent (tx)
+ // traffic. For received (rx) traffic, expect 300 bytes over WiFi and 200 bytes over Cell.
+ //
+ // For UID_VPN, expect 60 bytes attributed over WiFi and 40 bytes over Cell for tx traffic.
+ // And, 30 bytes over WiFi and 20 bytes over Cell for rx traffic.
+ incrementCurrentTime(HOUR_IN_MILLIS);
+ expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 3)
+ .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 500L, 50L, 1000L, 100L, 2L)
+ .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 330L, 30L, 660L, 60L, 1L)
+ .addValues(TEST_IFACE2, UID_VPN, SET_DEFAULT, TAG_NONE, 220L, 20L, 440L, 40L, 1L));
+
+ forcePollAndWaitForIdle();
+
+ assertUidTotal(sTemplateWifi, UID_RED, 300L, 30L, 600L, 60L, 1);
+ assertUidTotal(sTemplateWifi, UID_VPN, 30L, 0L, 60L, 0L, 1);
+
+ assertUidTotal(buildTemplateMobileWildcard(), UID_RED, 200L, 20L, 400L, 40L, 1);
+ assertUidTotal(buildTemplateMobileWildcard(), UID_VPN, 20L, 0L, 40L, 0L, 1);
+ }
+
+ @Test
+ public void vpnWithTwoUnderlyingIfaces_splitTrafficWithCompression() throws Exception {
+ // WiFi and Cell networks are connected and VPN is using WiFi (which has TEST_IFACE) and
+ // Cell (which has TEST_IFACE2) and has declared both of them in its underlying network set.
+ // Additionally, VPN is arbitrarily splitting compressed traffic across WiFi and Cell.
+ expectDefaultSettings();
+ NetworkState[] networkStates =
+ new NetworkState[] {
+ buildWifiState(), buildMobile4gState(TEST_IFACE2), buildVpnState()
+ };
+ VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE, TEST_IFACE2})};
+ expectNetworkStatsUidDetail(buildEmptyStats());
+ expectBandwidthControlCheck();
+
+ mService.forceUpdateIfaces(
+ new Network[] {WIFI_NETWORK, VPN_NETWORK},
+ vpnInfos,
+ networkStates,
+ getActiveIface(networkStates));
+ // create some traffic (assume 10 bytes of MTU for VPN interface:
+ // 1000 bytes (100 packets) were sent/received by UID_RED over VPN.
+ // VPN sent/received 600 bytes (60 packets) over WiFi and 200 bytes (20 packets) over Cell.
+ // For UID_RED, expect 600 bytes attributed over WiFi and 200 bytes over Cell for both
+ // rx/tx.
+ // UID_VPN gets nothing attributed to it (avoiding negative stats).
+ incrementCurrentTime(HOUR_IN_MILLIS);
+ expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 4)
+ .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1000L, 100L, 1000L, 100L, 1L)
+ .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 600L, 60L, 600L, 60L, 0L)
+ .addValues(TEST_IFACE2, UID_VPN, SET_DEFAULT, TAG_NONE, 200L, 20L, 200L, 20L, 0L));
+
+ forcePollAndWaitForIdle();
+
+ assertUidTotal(sTemplateWifi, UID_RED, 600L, 60L, 600L, 60L, 0);
+ assertUidTotal(sTemplateWifi, UID_VPN, 0L, 0L, 0L, 0L, 0);
+
+ assertUidTotal(buildTemplateMobileWildcard(), UID_RED, 200L, 20L, 200L, 20L, 0);
+ assertUidTotal(buildTemplateMobileWildcard(), UID_VPN, 0L, 0L, 0L, 0L, 0);
+ }
+
+ @Test
public void vpnWithIncorrectUnderlyingIface() throws Exception {
// WiFi and Cell networks are connected and VPN is using Cell (which has TEST_IFACE2),
// but has declared only WiFi (TEST_IFACE) in its underlying network set.
@@ -1001,7 +1248,7 @@ public class NetworkStatsServiceTest {
new NetworkState[] {
buildWifiState(), buildMobile4gState(TEST_IFACE2), buildVpnState()
};
- VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(TEST_IFACE)};
+ VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
expectNetworkStatsUidDetail(buildEmptyStats());
expectBandwidthControlCheck();
@@ -1030,6 +1277,134 @@ public class NetworkStatsServiceTest {
}
@Test
+ public void recordSnapshot_migratesTunTrafficAndUpdatesTunAdjustedStats() throws Exception {
+ assertEquals(0, mService.getTunAdjustedStats().size());
+ // VPN using WiFi (TEST_IFACE).
+ VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
+ expectBandwidthControlCheck();
+ // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
+ // overhead per packet):
+ // 1000 bytes (100 packets) were downloaded by UID_RED over VPN.
+ // VPN received 1100 bytes (100 packets) over WiFi.
+ incrementCurrentTime(HOUR_IN_MILLIS);
+ expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 2)
+ .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1000L, 100L, 0L, 0L, 0L)
+ .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 1100L, 100L, 0L, 0L, 0L));
+
+ // this should lead to NSS#recordSnapshotLocked
+ mService.forceUpdateIfaces(
+ new Network[0], vpnInfos, new NetworkState[0], null /* activeIface */);
+
+ // Verify TUN adjusted stats have traffic migrated correctly.
+ // Of 1100 bytes VPN received over WiFi, expect 1000 bytes attributed to UID_RED and 100
+ // bytes attributed to UID_VPN.
+ NetworkStats tunAdjStats = mService.getTunAdjustedStats();
+ assertValues(
+ tunAdjStats, TEST_IFACE, UID_RED, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, 1000L, 100L, 0L, 0L, 0);
+ assertValues(
+ tunAdjStats, TEST_IFACE, UID_VPN, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, 100L, 0L, 0L, 0L, 0);
+ }
+
+ @Test
+ public void getDetailedUidStats_migratesTunTrafficAndUpdatesTunAdjustedStats()
+ throws Exception {
+ assertEquals(0, mService.getTunAdjustedStats().size());
+ // VPN using WiFi (TEST_IFACE).
+ VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
+ expectBandwidthControlCheck();
+ mService.forceUpdateIfaces(
+ new Network[0], vpnInfos, new NetworkState[0], null /* activeIface */);
+ // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
+ // overhead per packet):
+ // 1000 bytes (100 packets) were downloaded by UID_RED over VPN.
+ // VPN received 1100 bytes (100 packets) over WiFi.
+ incrementCurrentTime(HOUR_IN_MILLIS);
+ expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 2)
+ .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1000L, 100L, 0L, 0L, 0L)
+ .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 1100L, 100L, 0L, 0L, 0L));
+
+ mService.getDetailedUidStats(INTERFACES_ALL);
+
+ // Verify internally maintained TUN adjusted stats
+ NetworkStats tunAdjStats = mService.getTunAdjustedStats();
+ // Verify stats for TEST_IFACE (WiFi):
+ // Of 1100 bytes VPN received over WiFi, expect 1000 bytes attributed to UID_RED and 100
+ // bytes attributed to UID_VPN.
+ assertValues(
+ tunAdjStats, TEST_IFACE, UID_RED, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, 1000L, 100L, 0L, 0L, 0);
+ assertValues(
+ tunAdjStats, TEST_IFACE, UID_VPN, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, 100L, 0L, 0L, 0L, 0);
+ // Verify stats for TUN_IFACE; only UID_RED should have usage on it.
+ assertValues(
+ tunAdjStats, TUN_IFACE, UID_RED, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, 1000L, 100L, 0L, 0L, 0);
+ assertValues(
+ tunAdjStats, TUN_IFACE, UID_VPN, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, 0L, 0L, 0L, 0L, 0);
+
+ // lets assume that since last time, VPN received another 1100 bytes (same assumptions as
+ // before i.e. UID_RED downloaded another 1000 bytes).
+ incrementCurrentTime(HOUR_IN_MILLIS);
+ // Note - NetworkStatsFactory returns counters that are monotonically increasing.
+ expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 2)
+ .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 2000L, 200L, 0L, 0L, 0L)
+ .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 2200L, 200L, 0L, 0L, 0L));
+
+ mService.getDetailedUidStats(INTERFACES_ALL);
+
+ tunAdjStats = mService.getTunAdjustedStats();
+ // verify TEST_IFACE stats:
+ assertValues(
+ tunAdjStats, TEST_IFACE, UID_RED, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, 2000L, 200L, 0L, 0L, 0);
+ assertValues(
+ tunAdjStats, TEST_IFACE, UID_VPN, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, 200L, 0L, 0L, 0L, 0);
+ // verify TUN_IFACE stats:
+ assertValues(
+ tunAdjStats, TUN_IFACE, UID_RED, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, 2000L, 200L, 0L, 0L, 0);
+ assertValues(
+ tunAdjStats, TUN_IFACE, UID_VPN, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, 0L, 0L, 0L, 0L, 0);
+ }
+
+ @Test
+ public void getDetailedUidStats_returnsCorrectStatsWithVpnRunning() throws Exception {
+ // VPN using WiFi (TEST_IFACE).
+ VpnInfo[] vpnInfos = new VpnInfo[] {createVpnInfo(new String[] {TEST_IFACE})};
+ expectBandwidthControlCheck();
+ mService.forceUpdateIfaces(
+ new Network[0], vpnInfos, new NetworkState[0], null /* activeIface */);
+ // create some traffic (assume 10 bytes of MTU for VPN interface and 1 byte encryption
+ // overhead per packet):
+ // 1000 bytes (100 packets) were downloaded by UID_RED over VPN.
+ // VPN received 1100 bytes (100 packets) over WiFi.
+ incrementCurrentTime(HOUR_IN_MILLIS);
+ expectNetworkStatsUidDetail(new NetworkStats(getElapsedRealtime(), 2)
+ .addValues(TUN_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 1000L, 100L, 0L, 0L, 0L)
+ .addValues(TEST_IFACE, UID_VPN, SET_DEFAULT, TAG_NONE, 1100L, 100L, 0L, 0L, 0L));
+
+ // Query realtime stats for TEST_IFACE.
+ NetworkStats queriedStats =
+ mService.getDetailedUidStats(new String[] {TEST_IFACE});
+
+ assertEquals(HOUR_IN_MILLIS, queriedStats.getElapsedRealtime());
+ // verify that returned stats are only for TEST_IFACE and VPN traffic is migrated correctly.
+ assertEquals(new String[] {TEST_IFACE}, queriedStats.getUniqueIfaces());
+ assertValues(
+ queriedStats, TEST_IFACE, UID_RED, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, 1000L, 100L, 0L, 0L, 0);
+ assertValues(
+ queriedStats, TEST_IFACE, UID_VPN, SET_ALL, TAG_NONE, METERED_ALL, ROAMING_ALL,
+ DEFAULT_NETWORK_ALL, 100L, 0L, 0L, 0L, 0);
+ }
+
+ @Test
public void testRegisterUsageCallback() throws Exception {
// pretend that wifi network comes online; service should ask about full
// network state, and poll any existing interfaces before updating.
@@ -1382,11 +1757,11 @@ public class NetworkStatsServiceTest {
return new NetworkState(info, prop, new NetworkCapabilities(), VPN_NETWORK, null, null);
}
- private static VpnInfo createVpnInfo(String underlyingIface) {
+ private static VpnInfo createVpnInfo(String[] underlyingIfaces) {
VpnInfo info = new VpnInfo();
info.ownerUid = UID_VPN;
info.vpnIface = TUN_IFACE;
- info.primaryUnderlyingIface = underlyingIface;
+ info.underlyingIfaces = underlyingIfaces;
return info;
}