summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp1
-rw-r--r--apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java7
-rw-r--r--apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java25
-rw-r--r--apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING4
-rw-r--r--apex/media/framework/lint-baseline.xml324
-rw-r--r--apex/media/service/Android.bp1
-rw-r--r--apex/media/service/java/com/android/server/media/MediaCommunicationService.java3
-rw-r--r--apex/media/service/java/com/android/server/media/SessionPriorityList.java6
-rw-r--r--apex/media/service/lint-baseline.xml35
-rw-r--r--api/Android.bp1
-rw-r--r--api/api.go14
-rw-r--r--boot/Android.bp4
-rw-r--r--cmds/incidentd/src/WorkDirectory.cpp2
-rw-r--r--core/api/current.txt19
-rw-r--r--core/api/module-lib-current.txt11
-rw-r--r--core/api/system-current.txt27
-rw-r--r--core/api/system-lint-baseline.txt1
-rw-r--r--core/api/test-current.txt26
-rw-r--r--core/java/android/app/ActivityThread.java3
-rw-r--r--core/java/android/app/ApplicationPackageManager.java70
-rw-r--r--core/java/android/app/AsyncNotedAppOp.java30
-rw-r--r--core/java/android/app/KeyguardManager.java4
-rw-r--r--core/java/android/app/LoadedApk.java4
-rw-r--r--core/java/android/app/Notification.java18
-rw-r--r--core/java/android/app/SyncNotedAppOp.java25
-rw-r--r--core/java/android/app/TaskInfo.java15
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java48
-rw-r--r--core/java/android/app/trust/ITrustManager.aidl2
-rw-r--r--core/java/android/app/trust/TrustManager.java73
-rw-r--r--core/java/android/companion/virtual/VirtualDeviceParams.java22
-rw-r--r--core/java/android/content/Context.java4
-rw-r--r--core/java/android/content/pm/SharedLibraryInfo.java20
-rw-r--r--core/java/android/content/pm/TEST_MAPPING63
-rw-r--r--core/java/android/database/CursorWindow.java5
-rw-r--r--core/java/android/database/CursorWindowAllocationException.java6
-rw-r--r--core/java/android/hardware/biometrics/IBiometricContextListener.aidl (renamed from startop/scripts/trace_analyzer/queries_pretty_print_block_launch.sql)25
-rw-r--r--core/java/android/hardware/devicestate/DeviceStateManager.java13
-rw-r--r--core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java39
-rw-r--r--core/java/android/hardware/devicestate/DeviceStateRequest.java3
-rw-r--r--core/java/android/hardware/devicestate/IDeviceStateManager.aidl16
-rw-r--r--core/java/android/hardware/devicestate/IDeviceStateManagerCallback.aidl10
-rw-r--r--core/java/android/hardware/input/IInputManager.aidl4
-rw-r--r--core/java/android/hardware/input/InputManager.java17
-rw-r--r--core/java/android/hardware/usb/UsbManager.java1
-rw-r--r--core/java/android/inputmethodservice/IInputMethodWrapper.java36
-rw-r--r--core/java/android/inputmethodservice/InputMethodService.java21
-rw-r--r--core/java/android/inputmethodservice/NavigationBarController.java76
-rw-r--r--core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java72
-rw-r--r--core/java/android/os/BatteryStats.java126
-rw-r--r--core/java/android/os/BatteryStatsManager.java38
-rw-r--r--core/java/android/os/VibrationAttributes.java30
-rw-r--r--core/java/android/os/VibrationEffect.java41
-rw-r--r--core/java/android/os/Vibrator.java59
-rw-r--r--core/java/android/service/autofill/AutofillService.java8
-rw-r--r--core/java/android/service/autofill/FillRequest.java55
-rw-r--r--core/java/android/service/autofill/FillResponse.java16
-rw-r--r--core/java/android/service/trust/TrustAgentService.java4
-rw-r--r--core/java/android/service/wallpaper/WallpaperService.java14
-rw-r--r--core/java/android/util/IconDrawableFactory.java29
-rw-r--r--core/java/android/util/LauncherIcons.java11
-rw-r--r--core/java/android/view/IDisplayWindowListener.aidl2
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureSession.java2
-rw-r--r--core/java/android/view/inputmethod/InputMethod.java20
-rw-r--r--core/java/android/widget/RemoteViews.java49
-rw-r--r--core/java/android/widget/TextView.java4
-rw-r--r--core/java/com/android/internal/app/IBatteryStats.aidl4
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java271
-rw-r--r--core/java/com/android/internal/os/BinderCallsStats.java11
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBar.aidl3
-rw-r--r--core/java/com/android/internal/statusbar/IStatusBarService.aidl3
-rw-r--r--core/java/com/android/internal/util/UserIcons.java24
-rw-r--r--core/java/com/android/internal/view/IInputMethod.aidl8
-rw-r--r--core/jni/Android.bp3
-rw-r--r--core/jni/AndroidRuntime.cpp2
-rw-r--r--core/jni/android/opengl/OWNERS1
-rw-r--r--core/jni/android/opengl/util.cpp6
-rw-r--r--core/jni/android_hardware_SensorManager.cpp15
-rw-r--r--core/jni/android_media_AudioSystem.cpp103
-rw-r--r--core/jni/android_server_NetworkManagementSocketTagger.cpp73
-rw-r--r--core/res/AndroidManifest.xml25
-rw-r--r--core/res/res/values/config.xml6
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/tests/coretests/res/layout/remote_view_relative_layout.xml24
-rw-r--r--core/tests/coretests/res/layout/remote_view_relative_layout_with_theme.xml25
-rw-r--r--core/tests/coretests/res/layout/remote_views_light_background_text.xml21
-rw-r--r--core/tests/coretests/res/layout/remote_views_list.xml21
-rw-r--r--core/tests/coretests/res/values/styles.xml10
-rw-r--r--core/tests/coretests/src/android/widget/RemoteViewsTest.java191
-rw-r--r--core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java212
-rw-r--r--core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java35
-rw-r--r--data/fonts/fonts.xml14
-rw-r--r--graphics/java/android/graphics/Bitmap.java48
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java14
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java38
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java19
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DropZoneView.java138
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java41
-rw-r--r--libs/hwui/HardwareBitmapUploader.cpp51
-rw-r--r--libs/hwui/HardwareBitmapUploader.h2
-rw-r--r--libs/hwui/apex/android_bitmap.cpp7
-rw-r--r--libs/hwui/hwui/ImageDecoder.cpp2
-rw-r--r--libs/hwui/jni/BitmapRegionDecoder.cpp11
-rw-r--r--libs/hwui/jni/Graphics.cpp32
-rw-r--r--libs/hwui/jni/GraphicsJNI.h21
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.h9
-rw-r--r--location/java/android/location/LastLocationRequest.java9
-rw-r--r--location/java/android/location/LocationManager.java4
-rw-r--r--location/java/android/location/LocationRequest.java12
-rw-r--r--media/java/android/media/AudioManager.java24
-rw-r--r--media/java/android/media/IMediaRouter2Manager.aidl4
-rw-r--r--media/java/android/media/MediaRoute2Info.java85
-rw-r--r--media/java/android/media/MediaRouter2.java51
-rw-r--r--media/java/android/media/MediaRouter2Manager.java168
-rw-r--r--media/java/android/media/RouteDiscoveryPreference.java128
-rw-r--r--media/native/midi/amidi.cpp6
-rw-r--r--native/android/libandroid.map.txt12
-rw-r--r--native/android/performance_hint.cpp7
-rw-r--r--native/android/tests/performance_hint/PerformanceHintNativeTest.cpp2
-rw-r--r--native/graphics/jni/imagedecoder.cpp8
-rw-r--r--packages/ConnectivityT/framework-t/Android.bp32
-rw-r--r--packages/ConnectivityT/framework-t/jni/android_net_TrafficStats.cpp46
-rw-r--r--packages/ConnectivityT/framework-t/jni/onload.cpp39
-rw-r--r--packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java12
-rw-r--r--packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java86
-rw-r--r--packages/ConnectivityT/framework-t/src/com/android/server/NetworkManagementSocketTagger.java13
-rw-r--r--packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java15
-rw-r--r--packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java6
-rw-r--r--packages/SettingsLib/Android.bp1
-rw-r--r--packages/SettingsLib/AndroidManifest.xml6
-rw-r--r--packages/SettingsLib/res/drawable/avatar_choose_photo_circled.xml30
-rw-r--r--packages/SettingsLib/res/drawable/avatar_selector.xml25
-rw-r--r--packages/SettingsLib/res/drawable/avatar_take_photo_circled.xml30
-rw-r--r--packages/SettingsLib/res/drawable/ic_account_circle_outline.xml25
-rw-r--r--packages/SettingsLib/res/drawable/ic_avatar_choose_photo.xml24
-rw-r--r--packages/SettingsLib/res/drawable/ic_avatar_take_photo.xml24
-rw-r--r--packages/SettingsLib/res/layout/avatar_item.xml24
-rw-r--r--packages/SettingsLib/res/layout/avatar_picker.xml38
-rw-r--r--packages/SettingsLib/res/values-w1280dp-land/dimens.xml21
-rw-r--r--packages/SettingsLib/res/values-w1440dp-land/dimens.xml21
-rw-r--r--packages/SettingsLib/res/values-w1600dp-land/dimens.xml21
-rw-r--r--packages/SettingsLib/res/values-w480dp-port/dimens.xml21
-rw-r--r--packages/SettingsLib/res/values-w600dp-port/dimens.xml21
-rw-r--r--packages/SettingsLib/res/values-w720dp-port/dimens.xml21
-rw-r--r--packages/SettingsLib/res/values-w840dp-port/dimens.xml21
-rw-r--r--packages/SettingsLib/res/values-w960dp-land/dimens.xml21
-rw-r--r--packages/SettingsLib/res/values/arrays.xml2
-rw-r--r--packages/SettingsLib/res/values/dimens.xml7
-rw-r--r--packages/SettingsLib/res/values/strings.xml14
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java39
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/users/AvatarPhotoController.java297
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/users/AvatarPickerActivity.java334
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/users/EditUserInfoController.java36
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java437
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/users/PhotoCapabilityUtils.java4
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java10
-rw-r--r--packages/SystemUI/res/layout/controls_fullscreen.xml3
-rw-r--r--packages/SystemUI/res/layout/dream_overlay_complications_layer.xml26
-rw-r--r--packages/SystemUI/res/values-land/config.xml3
-rw-r--r--packages/SystemUI/res/values-land/dimens.xml2
-rw-r--r--packages/SystemUI/res/values-sw600dp-land/config.xml3
-rw-r--r--packages/SystemUI/res/values-sw600dp-port/config.xml1
-rw-r--r--packages/SystemUI/res/values-sw600dp/config.xml3
-rw-r--r--packages/SystemUI/res/values-sw600dp/dimens.xml2
-rw-r--r--packages/SystemUI/res/values-sw720dp-land/config.xml3
-rw-r--r--packages/SystemUI/res/values-w500dp/config.xml20
-rw-r--r--packages/SystemUI/res/values-w500dp/dimens.xml21
-rw-r--r--packages/SystemUI/res/values-w850dp/config.xml20
-rw-r--r--packages/SystemUI/res/values-w850dp/dimens.xml21
-rw-r--r--packages/SystemUI/res/values/dimens.xml34
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/communal/ICommunalHost.aidl33
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/communal/ICommunalSource.aidl34
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/communal/ICommunalSurfaceCallback.aidl30
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java111
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/SmartSpaceComplication.java113
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/complication/Complication.java32
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationCollectionLiveData.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutEngine.java35
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutParams.java54
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationUtils.java53
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java273
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/BouncerSwipeModule.java128
-rw-r--r--packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/DreamTouchModule.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java82
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt29
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dream/MediaComplicationViewController.java68
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamComplication.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamSentinel.java97
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dream/MediaViewHolder.java58
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/dream/dagger/MediaComplicationComponent.java100
-rw-r--r--packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java116
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java56
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java60
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java7
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java41
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java68
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/SmartSpaceComplicationTest.java77
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationCollectionLiveDataTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationLayoutEngineTest.java29
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationUtilsTest.java55
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java252
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaComplicationViewControllerTest.java68
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaDreamSentinelTest.java93
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt153
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java5
-rw-r--r--services/Android.bp3
-rw-r--r--services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java6
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java146
-rw-r--r--services/companion/java/com/android/server/companion/AssociationStoreImpl.java2
-rw-r--r--services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java2
-rw-r--r--services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java2
-rw-r--r--services/companion/java/com/android/server/companion/virtual/InputController.java102
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java30
-rw-r--r--services/core/java/com/android/server/am/DataConnectionStats.java2
-rw-r--r--services/core/java/com/android/server/audio/BtHelper.java4
-rw-r--r--services/core/java/com/android/server/biometrics/log/BiometricContext.java47
-rw-r--r--services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java105
-rw-r--r--services/core/java/com/android/server/biometrics/log/BiometricLogger.java11
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java9
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java11
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java31
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/EnrollClient.java9
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java9
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java29
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java22
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java11
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/InvalidationClient.java10
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/InvalidationRequesterClient.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/RemovalClient.java11
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/RevokeChallengeClient.java9
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/StartUserClient.java7
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/StopUserClient.java7
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/AidlSession.java4
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java35
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java29
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java15
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGenerateChallengeClient.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGetAuthenticatorIdClient.java7
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGetFeatureClient.java9
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java18
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalEnumerateClient.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInvalidationClient.java6
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java59
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceRemovalClient.java6
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceResetLockoutClient.java7
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceRevokeChallengeClient.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceSetFeatureClient.java11
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceStartUserClient.java5
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceStopUserClient.java5
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java11
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java55
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java10
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java9
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGenerateChallengeClient.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGetFeatureClient.java11
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalCleanupClient.java18
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalEnumerateClient.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceRemovalClient.java11
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceResetLockoutClient.java7
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceRevokeChallengeClient.java7
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceSetFeatureClient.java11
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceUpdateActiveUserClient.java9
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlSession.java4
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java26
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java14
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java12
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGenerateChallengeClient.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGetAuthenticatorIdClient.java12
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java23
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalEnumerateClient.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInvalidationClient.java6
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java52
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintRemovalClient.java6
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintResetLockoutClient.java7
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintRevokeChallengeClient.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintStartUserClient.java5
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintStopUserClient.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java13
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java55
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java13
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java11
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintGenerateChallengeClient.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalCleanupClient.java21
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalEnumerateClient.java8
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintRemovalClient.java6
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintResetLockoutClient.java10
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintRevokeChallengeClient.java7
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintUpdateActiveUserClient.java10
-rw-r--r--services/core/java/com/android/server/camera/CameraServiceProxy.java3
-rw-r--r--services/core/java/com/android/server/devicestate/DeviceStateManagerService.java69
-rw-r--r--services/core/java/com/android/server/devicestate/DeviceStateManagerShellCommand.java5
-rw-r--r--services/core/java/com/android/server/devicestate/OverrideRequestController.java215
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java23
-rw-r--r--services/core/java/com/android/server/display/HighBrightnessModeController.java4
-rw-r--r--services/core/java/com/android/server/dreams/DreamManagerService.java7
-rw-r--r--services/core/java/com/android/server/input/InputManagerService.java29
-rw-r--r--services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java21
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodManagerService.java32
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodMenuController.java2
-rw-r--r--services/core/java/com/android/server/location/LocationManagerService.java21
-rw-r--r--services/core/java/com/android/server/location/LocationPermissions.java25
-rw-r--r--services/core/java/com/android/server/location/LocationShellCommand.java30
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java11
-rw-r--r--services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java23
-rw-r--r--services/core/java/com/android/server/notification/NotificationComparator.java20
-rw-r--r--services/core/java/com/android/server/notification/PermissionHelper.java5
-rw-r--r--services/core/java/com/android/server/notification/ZenModeFiltering.java133
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java2
-rw-r--r--services/core/java/com/android/server/pm/UserRestrictionsUtils.java22
-rw-r--r--services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java2
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java16
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java11
-rw-r--r--services/core/java/com/android/server/statusbar/StatusBarManagerService.java12
-rw-r--r--services/core/java/com/android/server/trust/TrustManagerService.java32
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java33
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java30
-rw-r--r--services/core/java/com/android/server/wm/DisplayWindowListenerController.java5
-rw-r--r--services/core/java/com/android/server/wm/LetterboxConfiguration.java28
-rw-r--r--services/core/java/com/android/server/wm/Session.java5
-rw-r--r--services/core/java/com/android/server/wm/Task.java3
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerShellCommand.java36
-rw-r--r--services/core/jni/com_android_server_companion_virtual_InputController.cpp36
-rw-r--r--services/core/jni/com_android_server_location_GnssLocationProvider.cpp13
-rw-r--r--services/core/jni/gnss/AGnssRil.cpp2
-rw-r--r--services/core/jni/gnss/GnssMeasurementCallback.cpp13
-rw-r--r--services/core/jni/gnss/GnssMeasurementCallback.h4
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java529
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java28
-rw-r--r--services/java/com/android/server/SystemServer.java20
-rw-r--r--services/startop/Android.bp36
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java115
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java8
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/AcquisitionClientTest.java9
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/BaseClientMonitorTest.java5
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerOperationTest.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java19
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/CompositeCallbackTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java25
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java128
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceDetectClientTest.java116
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClientTest.java107
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java9
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/FaceGenerateChallengeClientTest.java8
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java265
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java116
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java224
-rw-r--r--services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/SensorTest.java9
-rw-r--r--services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java21
-rw-r--r--services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java38
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java302
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java17
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java22
-rw-r--r--services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java19
-rw-r--r--services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java93
-rw-r--r--services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java24
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ScanTests.java4
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationComparatorTest.java9
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java10
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java133
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java42
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java3
-rw-r--r--services/usage/java/com/android/server/usage/BroadcastResponseStatsTracker.java9
-rw-r--r--services/usage/java/com/android/server/usage/UsageStatsService.java2
-rw-r--r--startop/iorap/Android.bp44
-rw-r--r--startop/iorap/TEST_MAPPING12
-rw-r--r--startop/iorap/functional_tests/Android.bp50
-rw-r--r--startop/iorap/functional_tests/AndroidManifest.xml38
-rw-r--r--startop/iorap/functional_tests/AndroidTest.xml70
-rw-r--r--startop/iorap/functional_tests/src/com/google/android/startop/iorap/IorapWorkFlowTest.java416
-rw-r--r--startop/iorap/src/com/google/android/startop/iorap/ActivityHintEvent.java139
-rw-r--r--startop/iorap/src/com/google/android/startop/iorap/ActivityInfo.java104
-rw-r--r--startop/iorap/src/com/google/android/startop/iorap/AppIntentEvent.java138
-rw-r--r--startop/iorap/src/com/google/android/startop/iorap/AppLaunchEvent.java459
-rw-r--r--startop/iorap/src/com/google/android/startop/iorap/CheckHelpers.java46
-rw-r--r--startop/iorap/src/com/google/android/startop/iorap/DexOptEvent.java114
-rw-r--r--startop/iorap/src/com/google/android/startop/iorap/EventSequenceValidator.java267
-rw-r--r--startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java806
-rw-r--r--startop/iorap/src/com/google/android/startop/iorap/JobScheduledEvent.java174
-rw-r--r--startop/iorap/src/com/google/android/startop/iorap/PackageEvent.java131
-rw-r--r--startop/iorap/src/com/google/android/startop/iorap/RequestId.java125
-rw-r--r--startop/iorap/src/com/google/android/startop/iorap/SystemServiceEvent.java109
-rw-r--r--startop/iorap/src/com/google/android/startop/iorap/SystemServiceUserEvent.java127
-rw-r--r--startop/iorap/src/com/google/android/startop/iorap/TaskResult.java130
-rw-r--r--startop/iorap/stress/Android.bp42
-rw-r--r--startop/iorap/stress/main_memory.cc126
-rw-r--r--startop/iorap/tests/Android.bp72
-rw-r--r--startop/iorap/tests/AndroidManifest.xml37
-rw-r--r--startop/iorap/tests/AndroidTest.xml66
-rw-r--r--startop/iorap/tests/src/com/google/android/startop/iorap/AppLaunchEventTest.kt181
-rw-r--r--startop/iorap/tests/src/com/google/android/startop/iorap/IIorapIntegrationTest.kt137
-rw-r--r--startop/iorap/tests/src/com/google/android/startop/iorap/ParcelablesTest.kt140
-rwxr-xr-xstartop/scripts/app_startup/analyze_metrics.py457
-rwxr-xr-xstartop/scripts/app_startup/app_startup_runner.py393
-rwxr-xr-xstartop/scripts/app_startup/app_startup_runner_test.py176
-rwxr-xr-xstartop/scripts/app_startup/force_compiler_filter143
-rwxr-xr-xstartop/scripts/app_startup/launch_application52
-rw-r--r--startop/scripts/app_startup/lib/adb_utils.py126
-rw-r--r--startop/scripts/app_startup/lib/adb_utils_test.py16
-rw-r--r--startop/scripts/app_startup/lib/app_runner.py266
-rw-r--r--startop/scripts/app_startup/lib/app_runner_test.py104
-rw-r--r--startop/scripts/app_startup/lib/args_utils.py77
-rw-r--r--startop/scripts/app_startup/lib/args_utils_test.py58
-rwxr-xr-xstartop/scripts/app_startup/lib/common198
-rw-r--r--startop/scripts/app_startup/lib/data_frame.py201
-rw-r--r--startop/scripts/app_startup/lib/data_frame_test.py128
-rw-r--r--startop/scripts/app_startup/lib/perfetto_trace_collector.py166
-rw-r--r--startop/scripts/app_startup/lib/perfetto_trace_collector_test.py101
-rwxr-xr-xstartop/scripts/app_startup/parse_metrics215
-rwxr-xr-xstartop/scripts/app_startup/query_compiler_filter.py232
-rwxr-xr-xstartop/scripts/app_startup/query_compiler_filter_test.py116
-rwxr-xr-xstartop/scripts/app_startup/run_app_with_prefetch487
-rwxr-xr-xstartop/scripts/app_startup/run_app_with_prefetch.py230
-rw-r--r--startop/scripts/app_startup/run_app_with_prefetch_test.py286
-rwxr-xr-xstartop/scripts/app_startup/unlock_screen22
-rwxr-xr-xstartop/scripts/iorap/analyze_prefetch_file.py168
-rwxr-xr-xstartop/scripts/iorap/collector403
-rwxr-xr-xstartop/scripts/iorap/common253
-rwxr-xr-xstartop/scripts/iorap/compile_handcrafted_file.py297
-rw-r--r--startop/scripts/iorap/compiler.py73
-rw-r--r--startop/scripts/iorap/compiler_device.py68
-rwxr-xr-xstartop/scripts/iorap/compiler_ri.py325
-rw-r--r--startop/scripts/iorap/compiler_test.py78
-rwxr-xr-xstartop/scripts/iorap/dump_compiled_pb38
-rwxr-xr-xstartop/scripts/iorap/dump_trace_pb38
-rw-r--r--startop/scripts/iorap/generated/TraceFile_pb2.py259
-rwxr-xr-xstartop/scripts/iorap/generated/codegen_protos35
-rw-r--r--startop/scripts/iorap/lib/inode2filename.py94
-rwxr-xr-xstartop/scripts/iorap/lib/inode2filename_test.py83
-rw-r--r--startop/scripts/iorap/lib/iorapd_utils.py175
-rwxr-xr-xstartop/scripts/iorap/pull_textcache24
-rw-r--r--startop/scripts/iorap/test_fixtures/compiler/common_perfetto_trace.pbbin28375 -> 0 bytes
-rw-r--r--startop/scripts/iorap/test_fixtures/compiler/common_systrace5
-rw-r--r--startop/scripts/iorap/test_fixtures/compiler/common_textcache2
-rw-r--r--startop/scripts/iorap/test_fixtures/compiler/test_result_systrace748
-rw-r--r--startop/scripts/iorap/test_fixtures/compiler/test_result_with_duration.TraceFile.pbbin34 -> 0 bytes
-rw-r--r--startop/scripts/iorap/test_fixtures/compiler/test_result_without_duration.TraceFile.pbbin62 -> 0 bytes
-rw-r--r--startop/scripts/lib/cmd_utils.py184
-rw-r--r--startop/scripts/lib/logcat_utils.py104
-rw-r--r--startop/scripts/lib/logcat_utils_test.py88
-rw-r--r--startop/scripts/lib/print_utils.py67
-rw-r--r--startop/scripts/trace_analyzer/lib/trace2db.py355
-rwxr-xr-xstartop/scripts/trace_analyzer/lib/trace2db_test.py222
-rw-r--r--startop/scripts/trace_analyzer/queries_all.sql57
-rw-r--r--startop/scripts/trace_analyzer/queries_app_launch_spans_with_name.sql44
-rw-r--r--startop/scripts/trace_analyzer/queries_block_launch.sql52
-rw-r--r--startop/scripts/trace_analyzer/queries_find_sched_switch_unblocked.sql101
-rw-r--r--startop/scripts/trace_analyzer/queries_get_comm_and_pids.sql42
-rw-r--r--startop/scripts/trace_analyzer/queries_get_procs.sql30
-rw-r--r--startop/scripts/trace_analyzer/queries_get_ui_threads.sql88
-rw-r--r--startop/scripts/trace_analyzer/queries_mark_write_join.sql53
-rwxr-xr-xstartop/scripts/trace_analyzer/run-sql-queries79
-rw-r--r--startop/scripts/trace_analyzer/test_fixtures/common_systrace518
-rwxr-xr-xstartop/scripts/trace_analyzer/trace_analyzer42
-rwxr-xr-xstartop/scripts/trace_analyzer/trace_analyzer.py51
-rwxr-xr-xstartop/scripts/trace_analyzer/trace_analyzer_recursive78
-rw-r--r--startop/scripts/trace_analyzer/trace_analyzer_test.py66
-rwxr-xr-xtelecomm/java/android/telecom/ConnectionService.java25
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java2
-rw-r--r--tools/lint/README.md3
484 files changed, 10619 insertions, 16918 deletions
diff --git a/Android.bp b/Android.bp
index 838f304b2e8e..e03f8449891a 100644
--- a/Android.bp
+++ b/Android.bp
@@ -169,7 +169,6 @@ java_library_with_nonpublic_deps {
"framework-statsd.impl",
"framework-supplementalprocess.impl",
"framework-tethering.impl",
- "framework-nearby.impl",
"framework-uwb.impl",
"framework-wifi.impl",
"updatable-media",
diff --git a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
index 9b1f2d07d58a..ddcc74696d94 100644
--- a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
+++ b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
@@ -216,4 +216,11 @@ public interface AppStandbyInternal {
void dumpState(String[] args, PrintWriter pw);
boolean isAppIdleEnabled();
+
+ /**
+ * Returns the duration (in millis) for the window where events occurring will be
+ * considered as broadcast response, starting from the point when an app receives
+ * a broadcast.
+ */
+ long getBroadcastResponseWindowDurationMs();
}
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index 8b2639781181..050e3df5b5e1 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -347,6 +347,14 @@ public class AppStandbyController
*/
boolean mLinkCrossProfileApps =
ConstantsObserver.DEFAULT_CROSS_PROFILE_APPS_SHARE_STANDBY_BUCKETS;
+
+ /**
+ * Duration (in millis) for the window where events occurring will be considered as
+ * broadcast response, starting from the point when an app receives a broadcast.
+ */
+ volatile long mBroadcastResponseWindowDurationMillis =
+ ConstantsObserver.DEFAULT_BROADCAST_RESPONSE_WINDOW_DURATION_MS;
+
/**
* Whether we should allow apps into the
* {@link android.app.usage.UsageStatsManager#STANDBY_BUCKET_RESTRICTED} bucket or not.
@@ -1774,6 +1782,10 @@ public class AppStandbyController
}
}
+ @Override
+ public long getBroadcastResponseWindowDurationMs() {
+ return mBroadcastResponseWindowDurationMillis;
+ }
@Override
public void flushToDisk() {
@@ -2042,6 +2054,10 @@ public class AppStandbyController
TimeUtils.formatDuration(mSystemUpdateUsageTimeoutMillis, pw);
pw.println();
+ pw.print(" mBroadcastResponseWindowDurationMillis=");
+ TimeUtils.formatDuration(mBroadcastResponseWindowDurationMillis, pw);
+ pw.println();
+
pw.println();
pw.print("mAppIdleEnabled="); pw.print(mAppIdleEnabled);
pw.print(" mAllowRestrictedBucket=");
@@ -2473,6 +2489,8 @@ public class AppStandbyController
KEY_PREFIX_ELAPSED_TIME_THRESHOLD + "rare",
KEY_PREFIX_ELAPSED_TIME_THRESHOLD + "restricted"
};
+ private static final String KEY_BROADCAST_RESPONSE_WINDOW_DURATION_MS =
+ "broadcast_response_window_timeout_ms";
public static final long DEFAULT_CHECK_IDLE_INTERVAL_MS =
COMPRESS_TIME ? ONE_MINUTE : 4 * ONE_HOUR;
public static final long DEFAULT_STRONG_USAGE_TIMEOUT =
@@ -2502,6 +2520,8 @@ public class AppStandbyController
public static final long DEFAULT_AUTO_RESTRICTED_BUCKET_DELAY_MS =
COMPRESS_TIME ? ONE_MINUTE : ONE_DAY;
public static final boolean DEFAULT_CROSS_PROFILE_APPS_SHARE_STANDBY_BUCKETS = true;
+ public static final long DEFAULT_BROADCAST_RESPONSE_WINDOW_DURATION_MS =
+ 2 * ONE_MINUTE;
ConstantsObserver(Handler handler) {
super(handler);
@@ -2619,6 +2639,11 @@ public class AppStandbyController
KEY_UNEXEMPTED_SYNC_SCHEDULED_HOLD_DURATION,
DEFAULT_UNEXEMPTED_SYNC_SCHEDULED_TIMEOUT);
break;
+ case KEY_BROADCAST_RESPONSE_WINDOW_DURATION_MS:
+ mBroadcastResponseWindowDurationMillis = properties.getLong(
+ KEY_BROADCAST_RESPONSE_WINDOW_DURATION_MS,
+ DEFAULT_BROADCAST_RESPONSE_WINDOW_DURATION_MS);
+ break;
default:
if (!timeThresholdsUpdated
&& (name.startsWith(KEY_PREFIX_SCREEN_TIME_THRESHOLD)
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING b/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
index c5dc51cc9c24..e407e3126058 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
+++ b/apex/jobscheduler/service/java/com/android/server/usage/TEST_MAPPING
@@ -5,7 +5,9 @@
"options": [
{"include-filter": "android.app.usage.cts.UsageStatsTest"},
{"exclude-annotation": "android.platform.test.annotations.FlakyTest"},
- {"exclude-annotation": "androidx.test.filters.FlakyTest"}
+ {"exclude-annotation": "androidx.test.filters.FlakyTest"},
+ {"exclude-annotation": "androidx.test.filters.MediumTest"},
+ {"exclude-annotation": "androidx.test.filters.LargeTest"}
]
},
{
diff --git a/apex/media/framework/lint-baseline.xml b/apex/media/framework/lint-baseline.xml
index e1b145083f80..95eea45069ef 100644
--- a/apex/media/framework/lint-baseline.xml
+++ b/apex/media/framework/lint-baseline.xml
@@ -1,312 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.1.0" client="cli" variant="all" version="4.1.0">
+<issues format="6" by="lint 7.2.0-dev" type="baseline" client="" dependencies="true" name="" variant="all" version="7.2.0-dev">
<issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `new android.media.ApplicationMediaCapabilities.Builder`"
- errorLine1=" new ApplicationMediaCapabilities.Builder();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ id="DefaultLocale"
+ message="Implicitly using the default locale is a common source of bugs: Use `toLowerCase(Locale)` instead. For strings meant to be internal use `Locale.ROOT`, otherwise `Locale.getDefault()`."
+ errorLine1=" if (mSupportedVideoMimeTypes.contains(videoMime.toLowerCase())) {"
+ errorLine2=" ~~~~~~~~~~~">
<location
file="frameworks/base/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java"
- line="208"
- column="29"/>
+ line="121"
+ column="57"/>
</issue>
<issue
- id="NewApi"
- message="Call requires API level 31 (current min is 29): `new android.media.ApplicationMediaCapabilities.Builder`"
- errorLine1=" ApplicationMediaCapabilities.Builder builder = new ApplicationMediaCapabilities.Builder();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
+ id="DefaultLocale"
+ message="Implicitly using the default locale is a common source of bugs: Use `String.format(Locale, ...)` instead"
+ errorLine1=" return String.format(&quot; session: {id: %d, status: %s, result: %s, progress: %d}&quot;,"
+ errorLine2=" ^">
<location
- file="frameworks/base/apex/media/framework/java/android/media/ApplicationMediaCapabilities.java"
- line="314"
- column="56"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level R (current min is 29): `android.os.RemoteException#rethrowFromSystemServer`"
- errorLine1=" e.rethrowFromSystemServer();"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaCommunicationManager.java"
- line="110"
- column="15"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level R (current min is 29): `android.os.Parcel#writeParcelableCreator`"
- errorLine1=" dest.writeParcelableCreator((Parcelable) parcelable);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParceledListSlice.java"
- line="77"
- column="14"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level R (current min is 29): `android.os.Parcel#readParcelableCreator`"
- errorLine1=" return from.readParcelableCreator(loader);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParceledListSlice.java"
- line="82"
- column="21"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.TrackData#mediaFormat`"
- errorLine1=" this.mediaFormat = mediaFormat;"
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="273"
- column="13"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.TrackData#drmInitData`"
- errorLine1=" this.drmInitData = drmInitData;"
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="274"
- column="13"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#timeMicros`"
- errorLine1=" this.timeMicros = timeMicros;"
- errorLine2=" ~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="295"
- column="13"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#position`"
- errorLine1=" this.position = position;"
- errorLine2=" ~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="296"
- column="13"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#position`"
- errorLine1=" return &quot;[timeMicros=&quot; + timeMicros + &quot;, position=&quot; + position + &quot;]&quot;;"
- errorLine2=" ~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="302"
- column="66"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#timeMicros`"
- errorLine1=" return &quot;[timeMicros=&quot; + timeMicros + &quot;, position=&quot; + position + &quot;]&quot;;"
- errorLine2=" ~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="302"
- column="37"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Class requires API level R (current min is 29): `android.media.MediaParser.SeekPoint`"
- errorLine1=" SeekPoint other = (SeekPoint) obj;"
- errorLine2=" ~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="313"
- column="32"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#position`"
- errorLine1=" return timeMicros == other.timeMicros &amp;&amp; position == other.position;"
- errorLine2=" ~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="314"
- column="54"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#position`"
- errorLine1=" return timeMicros == other.timeMicros &amp;&amp; position == other.position;"
- errorLine2=" ~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="314"
- column="66"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#timeMicros`"
- errorLine1=" return timeMicros == other.timeMicros &amp;&amp; position == other.position;"
- errorLine2=" ~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="314"
+ file="frameworks/base/apex/media/framework/java/android/media/MediaTranscodingManager.java"
+ line="1651"
column="20"/>
</issue>
<issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#timeMicros`"
- errorLine1=" return timeMicros == other.timeMicros &amp;&amp; position == other.position;"
- errorLine2=" ~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="314"
- column="34"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#timeMicros`"
- errorLine1=" int result = (int) timeMicros;"
- errorLine2=" ~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="319"
- column="32"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#position`"
- errorLine1=" result = 31 * result + (int) position;"
- errorLine2=" ~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="320"
- column="42"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Class requires API level R (current min is 29): `android.media.MediaParser.InputReader`"
- errorLine1=" public interface SeekableInputReader extends InputReader {"
- errorLine2=" ~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="352"
- column="50"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level 31 (current min is 29): `android.media.metrics.LogSessionId#LOG_SESSION_ID_NONE`"
- errorLine1=" @NonNull private LogSessionId mLogSessionId = LogSessionId.LOG_SESSION_ID_NONE;"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="1071"
- column="51"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Cast from `SeekableInputReader` to `InputReader` requires API level 30 (current min is 29)"
- errorLine1=" mExoDataReader.mInputReader = seekableInputReader;"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="1201"
- column="39"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#position`"
- errorLine1=" mPendingSeekPosition = seekPoint.position;"
- errorLine2=" ~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="1287"
- column="36"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#timeMicros`"
- errorLine1=" mPendingSeekTimeMicros = seekPoint.timeMicros;"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="1288"
- column="38"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#position`"
- errorLine1=" mExtractor.seek(seekPoint.position, seekPoint.timeMicros);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="1290"
- column="29"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.MediaParser.SeekPoint#timeMicros`"
- errorLine1=" mExtractor.seek(seekPoint.position, seekPoint.timeMicros);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
+ id="ParcelClassLoader"
+ message="Passing null here (to use the default class loader) will not work if you are restoring your own classes. Consider using for example `getClass().getClassLoader()` instead."
+ errorLine1=" Bundle out = parcel.readBundle(null);"
+ errorLine2=" ~~~~~~~~~~~~~~~~">
<location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="1290"
- column="49"/>
+ file="frameworks/base/apex/media/framework/java/android/media/MediaSession2.java"
+ line="303"
+ column="33"/>
</issue>
<issue
- id="NewApi"
- message="Field requires API level R (current min is 29): `android.media.DrmInitData.SchemeInitData#uuid`"
- errorLine1=" if (schemeInitData.uuid.equals(schemeUuid)) {"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
+ id="ParcelClassLoader"
+ message="Using the default class loader will not work if you are restoring your own classes. Consider using for example `readBundle(getClass().getClassLoader())` instead."
+ errorLine1=" mCustomExtras = in.readBundle();"
+ errorLine2=" ~~~~~~~~~~~~">
<location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="1579"
- column="21"/>
+ file="frameworks/base/apex/media/framework/java/android/media/Session2Command.java"
+ line="104"
+ column="28"/>
</issue>
<issue
- id="NewApi"
- message="Class requires API level R (current min is 29): `android.media.MediaParser.InputReader`"
- errorLine1=" private static final class DataReaderAdapter implements InputReader {"
- errorLine2=" ~~~~~~~~~~~">
+ id="ParcelClassLoader"
+ message="Passing null here (to use the default class loader) will not work if you are restoring your own classes. Consider using for example `getClass().getClassLoader()` instead."
+ errorLine1=" mSessionLink = in.readParcelable(null);"
+ errorLine2=" ~~~~~~~~~~~~~~~~~~~~">
<location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="1872"
- column="61"/>
+ file="frameworks/base/apex/media/framework/java/android/media/Session2Token.java"
+ line="141"
+ column="27"/>
</issue>
<issue
- id="NewApi"
- message="Class requires API level R (current min is 29): `android.media.MediaParser.InputReader`"
- errorLine1=" private static final class ParsableByteArrayAdapter implements InputReader {"
- errorLine2=" ~~~~~~~~~~~">
+ id="ParcelClassLoader"
+ message="Using the default class loader will not work if you are restoring your own classes. Consider using for example `readBundle(getClass().getClassLoader())` instead."
+ errorLine1=" Bundle extras = in.readBundle();"
+ errorLine2=" ~~~~~~~~~~~~">
<location
- file="frameworks/base/apex/media/framework/java/android/media/MediaParser.java"
- line="1905"
- column="68"/>
+ file="frameworks/base/apex/media/framework/java/android/media/Session2Token.java"
+ line="144"
+ column="28"/>
</issue>
</issues>
diff --git a/apex/media/service/Android.bp b/apex/media/service/Android.bp
index cf384acccb12..2714809e0c3d 100644
--- a/apex/media/service/Android.bp
+++ b/apex/media/service/Android.bp
@@ -39,6 +39,7 @@ java_sdk_library {
":service-media-s-sources",
],
libs: [
+ "androidx.annotation_annotation",
"updatable-media",
"modules-annotation-minsdk",
"modules-utils-build",
diff --git a/apex/media/service/java/com/android/server/media/MediaCommunicationService.java b/apex/media/service/java/com/android/server/media/MediaCommunicationService.java
index 7d47e250f99d..4223fa65fd53 100644
--- a/apex/media/service/java/com/android/server/media/MediaCommunicationService.java
+++ b/apex/media/service/java/com/android/server/media/MediaCommunicationService.java
@@ -46,6 +46,8 @@ import android.util.SparseArray;
import android.util.SparseIntArray;
import android.view.KeyEvent;
+import androidx.annotation.RequiresApi;
+
import com.android.internal.annotations.GuardedBy;
import com.android.modules.annotation.MinSdk;
import com.android.server.SystemService;
@@ -63,6 +65,7 @@ import java.util.concurrent.Executors;
* @hide
*/
@MinSdk(Build.VERSION_CODES.S)
+@RequiresApi(Build.VERSION_CODES.S)
public class MediaCommunicationService extends SystemService {
private static final String TAG = "MediaCommunicationSrv";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
diff --git a/apex/media/service/java/com/android/server/media/SessionPriorityList.java b/apex/media/service/java/com/android/server/media/SessionPriorityList.java
index 47b14b63ddba..814586139123 100644
--- a/apex/media/service/java/com/android/server/media/SessionPriorityList.java
+++ b/apex/media/service/java/com/android/server/media/SessionPriorityList.java
@@ -18,9 +18,13 @@ package com.android.server.media;
import android.annotation.Nullable;
import android.media.Session2Token;
+import android.os.Build;
import android.util.Log;
+import androidx.annotation.RequiresApi;
+
import com.android.internal.annotations.GuardedBy;
+import com.android.modules.annotation.MinSdk;
import com.android.server.media.MediaCommunicationService.Session2Record;
import java.util.ArrayList;
@@ -33,6 +37,8 @@ import java.util.List;
* Higher priority session has more chance to be selected as media button session,
* which receives the media button events.
*/
+@MinSdk(Build.VERSION_CODES.S)
+@RequiresApi(Build.VERSION_CODES.S)
class SessionPriorityList {
private static final String TAG = "SessionPriorityList";
private final Object mLock = new Object();
diff --git a/apex/media/service/lint-baseline.xml b/apex/media/service/lint-baseline.xml
index 05ce17c26872..def6baf0ff4f 100644
--- a/apex/media/service/lint-baseline.xml
+++ b/apex/media/service/lint-baseline.xml
@@ -1,37 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
-<issues format="6" by="lint 7.1.0-dev" type="baseline" client="" dependencies="true" name="" variant="all" version="7.1.0-dev">
-
- <issue
- id="NewApi"
- message="Call requires API level S (current min is 29): `MediaParceledListSlice`"
- errorLine1=" new MediaParceledListSlice&lt;>(getSession2TokensLocked(ALL.getIdentifier()));"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/service/java/com/android/server/media/MediaCommunicationService.java"
- line="242"
- column="21"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level S (current min is 29): `MediaParceledListSlice`"
- errorLine1=" userSession2Tokens = new MediaParceledListSlice&lt;>(getSession2TokensLocked(userId));"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/service/java/com/android/server/media/MediaCommunicationService.java"
- line="243"
- column="34"/>
- </issue>
-
- <issue
- id="NewApi"
- message="Call requires API level S (current min is 29): `MediaParceledListSlice`"
- errorLine1=" MediaParceledListSlice parceledListSlice = new MediaParceledListSlice&lt;>(result);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="frameworks/base/apex/media/service/java/com/android/server/media/MediaCommunicationService.java"
- line="386"
- column="60"/>
- </issue>
+<issues format="6" by="lint 7.2.0-dev" type="baseline" client="" dependencies="true" name="" variant="all" version="7.2.0-dev">
</issues>
diff --git a/api/Android.bp b/api/Android.bp
index 3075d385f1ca..d57f5dbdf948 100644
--- a/api/Android.bp
+++ b/api/Android.bp
@@ -116,7 +116,6 @@ combined_apis {
"framework-graphics",
"framework-media",
"framework-mediaprovider",
- "framework-nearby",
"framework-permission",
"framework-permission-s",
"framework-scheduling",
diff --git a/api/api.go b/api/api.go
index aa9e399e7272..17649e80e81a 100644
--- a/api/api.go
+++ b/api/api.go
@@ -27,7 +27,6 @@ import (
const art = "art.module.public.api"
const conscrypt = "conscrypt.module.public.api"
const i18n = "i18n.module.public.api"
-var modules_with_only_public_scope = []string{i18n, conscrypt}
// The intention behind this soong plugin is to generate a number of "merged"
// API-related modules that would otherwise require a large amount of very
@@ -149,8 +148,6 @@ func createMergedStubsSrcjar(ctx android.LoadHookContext, modules []string) {
// This produces the same annotations.zip as framework-doc-stubs, but by using
// outputs from individual modules instead of all the source code.
func createMergedAnnotations(ctx android.LoadHookContext, modules []string) {
- // Conscrypt and i18n currently do not enable annotations
- modules = removeAll(modules, []string{conscrypt, i18n})
props := genruleProps{}
props.Name = proptools.StringPtr("sdk-annotations.zip")
props.Tools = []string{"merge_annotation_zips", "soong_zip"}
@@ -195,11 +192,8 @@ func createMergedPublicStubs(ctx android.LoadHookContext, modules []string) {
func createMergedSystemStubs(ctx android.LoadHookContext, modules []string) {
props := libraryProps{}
- modules_with_system_stubs := removeAll(modules, modules_with_only_public_scope)
props.Name = proptools.StringPtr("all-modules-system-stubs")
- props.Static_libs = append(
- transformArray(modules_with_only_public_scope, "", ".stubs"),
- transformArray(modules_with_system_stubs, "", ".stubs.system")...)
+ props.Static_libs = transformArray(modules, "", ".stubs.system")
props.Sdk_version = proptools.StringPtr("module_current")
props.Visibility = []string{"//frameworks/base"}
ctx.CreateModule(java.LibraryFactory, &props)
@@ -226,8 +220,6 @@ func createPublicStubsSourceFilegroup(ctx android.LoadHookContext, modules []str
func createMergedTxts(ctx android.LoadHookContext, bootclasspath, system_server_classpath []string) {
var textFiles []MergedTxtDefinition
- // Two module libraries currently do not support @SystemApi so only have the public scope.
- bcpWithSystemApi := removeAll(bootclasspath, modules_with_only_public_scope)
tagSuffix := []string{".api.txt}", ".removed-api.txt}"}
for i, f := range []string{"current.txt", "removed.txt"} {
@@ -241,14 +233,14 @@ func createMergedTxts(ctx android.LoadHookContext, bootclasspath, system_server_
textFiles = append(textFiles, MergedTxtDefinition{
TxtFilename: f,
BaseTxt: ":non-updatable-system-" + f,
- Modules: bcpWithSystemApi,
+ Modules: bootclasspath,
ModuleTag: "{.system" + tagSuffix[i],
Scope: "system",
})
textFiles = append(textFiles, MergedTxtDefinition{
TxtFilename: f,
BaseTxt: ":non-updatable-module-lib-" + f,
- Modules: bcpWithSystemApi,
+ Modules: bootclasspath,
ModuleTag: "{.module-lib" + tagSuffix[i],
Scope: "module-lib",
})
diff --git a/boot/Android.bp b/boot/Android.bp
index 8958d70f63cf..55ffe7c3dda3 100644
--- a/boot/Android.bp
+++ b/boot/Android.bp
@@ -80,10 +80,6 @@ platform_bootclasspath {
module: "com.android.mediaprovider-bootclasspath-fragment",
},
{
- apex: "com.android.nearby",
- module: "com.android.nearby-bootclasspath-fragment",
- },
- {
apex: "com.android.os.statsd",
module: "com.android.os.statsd-bootclasspath-fragment",
},
diff --git a/cmds/incidentd/src/WorkDirectory.cpp b/cmds/incidentd/src/WorkDirectory.cpp
index dd33fdfc28c3..c8d2e0ec4aca 100644
--- a/cmds/incidentd/src/WorkDirectory.cpp
+++ b/cmds/incidentd/src/WorkDirectory.cpp
@@ -280,7 +280,7 @@ void ReportFile::addReport(const IncidentReportArgs& args) {
// Lower privacy policy (less restrictive) wins.
report->set_privacy_policy(args.getPrivacyPolicy());
}
- report->set_all_sections(report->all_sections() | args.all());
+ report->set_all_sections(report->all_sections() || args.all());
for (int section: args.sections()) {
if (!has_section(*report, section)) {
report->add_section(section);
diff --git a/core/api/current.txt b/core/api/current.txt
index 922ad16c2a6e..dd0614648f8c 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -12225,7 +12225,7 @@ package android.content.pm {
field @NonNull public static final android.os.Parcelable.Creator<android.content.pm.SharedLibraryInfo> CREATOR;
field public static final int TYPE_BUILTIN = 0; // 0x0
field public static final int TYPE_DYNAMIC = 1; // 0x1
- field public static final int TYPE_SDK = 3; // 0x3
+ field public static final int TYPE_SDK_PACKAGE = 3; // 0x3
field public static final int TYPE_STATIC = 2; // 0x2
field public static final int VERSION_UNDEFINED = -1; // 0xffffffff
}
@@ -12953,6 +12953,10 @@ package android.database {
field @NonNull public static final android.os.Parcelable.Creator<android.database.CursorWindow> CREATOR;
}
+ public class CursorWindowAllocationException extends java.lang.RuntimeException {
+ ctor public CursorWindowAllocationException(@NonNull String);
+ }
+
public class CursorWrapper implements android.database.Cursor {
ctor public CursorWrapper(android.database.Cursor);
method public void close();
@@ -13984,6 +13988,7 @@ package android.graphics {
enum_constant @Deprecated public static final android.graphics.Bitmap.Config ARGB_4444;
enum_constant public static final android.graphics.Bitmap.Config ARGB_8888;
enum_constant public static final android.graphics.Bitmap.Config HARDWARE;
+ enum_constant public static final android.graphics.Bitmap.Config RGBA_1010102;
enum_constant public static final android.graphics.Bitmap.Config RGBA_F16;
enum_constant public static final android.graphics.Bitmap.Config RGB_565;
}
@@ -22723,6 +22728,7 @@ package android.media {
method public int describeContents();
method @Nullable public String getClientPackageName();
method public int getConnectionState();
+ method @NonNull public java.util.Set<java.lang.String> getDeduplicationIds();
method @Nullable public CharSequence getDescription();
method @Nullable public android.os.Bundle getExtras();
method @NonNull public java.util.List<java.lang.String> getFeatures();
@@ -22756,6 +22762,7 @@ package android.media {
method @NonNull public android.media.MediaRoute2Info.Builder clearFeatures();
method @NonNull public android.media.MediaRoute2Info.Builder setClientPackageName(@Nullable String);
method @NonNull public android.media.MediaRoute2Info.Builder setConnectionState(int);
+ method @NonNull public android.media.MediaRoute2Info.Builder setDeduplicationIds(@NonNull java.util.Set<java.lang.String>);
method @NonNull public android.media.MediaRoute2Info.Builder setDescription(@Nullable CharSequence);
method @NonNull public android.media.MediaRoute2Info.Builder setExtras(@Nullable android.os.Bundle);
method @NonNull public android.media.MediaRoute2Info.Builder setIconUri(@Nullable android.net.Uri);
@@ -23282,8 +23289,12 @@ package android.media {
public final class RouteDiscoveryPreference implements android.os.Parcelable {
method public int describeContents();
+ method @NonNull public java.util.List<java.lang.String> getAllowedPackages();
+ method @NonNull public java.util.List<java.lang.String> getDeduplicationPackageOrder();
method @NonNull public java.util.List<java.lang.String> getPreferredFeatures();
+ method @NonNull public java.util.List<java.lang.String> getRequiredFeatures();
method public boolean shouldPerformActiveScan();
+ method public boolean shouldRemoveDuplicates();
method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.media.RouteDiscoveryPreference> CREATOR;
}
@@ -23292,7 +23303,10 @@ package android.media {
ctor public RouteDiscoveryPreference.Builder(@NonNull java.util.List<java.lang.String>, boolean);
ctor public RouteDiscoveryPreference.Builder(@NonNull android.media.RouteDiscoveryPreference);
method @NonNull public android.media.RouteDiscoveryPreference build();
+ method @NonNull public android.media.RouteDiscoveryPreference.Builder setAllowedPackages(@NonNull java.util.List<java.lang.String>);
+ method @NonNull public android.media.RouteDiscoveryPreference.Builder setDeduplicationPackageOrder(@Nullable java.util.List<java.lang.String>);
method @NonNull public android.media.RouteDiscoveryPreference.Builder setPreferredFeatures(@NonNull java.util.List<java.lang.String>);
+ method @NonNull public android.media.RouteDiscoveryPreference.Builder setRequiredFeatures(@NonNull java.util.List<java.lang.String>);
method @NonNull public android.media.RouteDiscoveryPreference.Builder setShouldPerformActiveScan(boolean);
}
@@ -37882,6 +37896,7 @@ package android.service.autofill {
method public abstract void onFillRequest(@NonNull android.service.autofill.FillRequest, @NonNull android.os.CancellationSignal, @NonNull android.service.autofill.FillCallback);
method public abstract void onSaveRequest(@NonNull android.service.autofill.SaveRequest, @NonNull android.service.autofill.SaveCallback);
method public void onSavedDatasetsInfoRequest(@NonNull android.service.autofill.SavedDatasetsInfoCallback);
+ field public static final String EXTRA_FILL_RESPONSE = "android.service.autofill.extra.FILL_RESPONSE";
field public static final String SERVICE_INTERFACE = "android.service.autofill.AutofillService";
field public static final String SERVICE_META_DATA = "android.autofill";
}
@@ -38037,6 +38052,7 @@ package android.service.autofill {
public final class FillRequest implements android.os.Parcelable {
method public int describeContents();
method @Nullable public android.os.Bundle getClientState();
+ method @Nullable public android.content.IntentSender getDelayedFillIntentSender();
method @NonNull public java.util.List<android.service.autofill.FillContext> getFillContexts();
method public int getFlags();
method public int getId();
@@ -38051,6 +38067,7 @@ package android.service.autofill {
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.service.autofill.FillResponse> CREATOR;
+ field public static final int FLAG_DELAY_FILL = 4; // 0x4
field public static final int FLAG_DISABLE_ACTIVITY_ONLY = 2; // 0x2
field public static final int FLAG_TRACK_CONTEXT_COMMITED = 1; // 0x1
}
diff --git a/core/api/module-lib-current.txt b/core/api/module-lib-current.txt
index 8ea1abca7a3f..df61a968ffc0 100644
--- a/core/api/module-lib-current.txt
+++ b/core/api/module-lib-current.txt
@@ -446,6 +446,17 @@ package android.net {
}
+package android.net.netstats {
+
+ public class NetworkStatsDataMigrationUtils {
+ method @NonNull public static android.net.NetworkStatsCollection readPlatformCollection(@NonNull String, long) throws java.io.IOException;
+ field public static final String PREFIX_UID = "uid";
+ field public static final String PREFIX_UID_TAG = "uid_tag";
+ field public static final String PREFIX_XT = "xt";
+ }
+
+}
+
package android.os {
public final class BatteryStatsManager {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 171ee9a0a95b..c47c37b0bc7e 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -146,6 +146,7 @@ package android {
field public static final String KILL_UID = "android.permission.KILL_UID";
field public static final String LAUNCH_DEVICE_MANAGER_SETUP = "android.permission.LAUNCH_DEVICE_MANAGER_SETUP";
field public static final String LOCAL_MAC_ADDRESS = "android.permission.LOCAL_MAC_ADDRESS";
+ field public static final String LOCATION_BYPASS = "android.permission.LOCATION_BYPASS";
field public static final String LOCK_DEVICE = "android.permission.LOCK_DEVICE";
field public static final String LOOP_RADIO = "android.permission.LOOP_RADIO";
field public static final String MANAGE_ACCESSIBILITY = "android.permission.MANAGE_ACCESSIBILITY";
@@ -302,6 +303,7 @@ package android {
field public static final String SET_POINTER_SPEED = "android.permission.SET_POINTER_SPEED";
field public static final String SET_SCREEN_COMPATIBILITY = "android.permission.SET_SCREEN_COMPATIBILITY";
field public static final String SET_SYSTEM_AUDIO_CAPTION = "android.permission.SET_SYSTEM_AUDIO_CAPTION";
+ field public static final String SET_UNRESTRICTED_KEEP_CLEAR_AREAS = "android.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS";
field public static final String SET_VOLUME_KEY_LONG_PRESS_LISTENER = "android.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER";
field public static final String SET_WALLPAPER_COMPONENT = "android.permission.SET_WALLPAPER_COMPONENT";
field public static final String SET_WALLPAPER_DIM_AMOUNT = "android.permission.SET_WALLPAPER_DIM_AMOUNT";
@@ -2610,6 +2612,8 @@ package android.companion.virtual {
public final class VirtualDeviceParams implements android.os.Parcelable {
method public int describeContents();
+ method @Nullable public java.util.Set<android.content.ComponentName> getAllowedActivities();
+ method @Nullable public java.util.Set<android.content.ComponentName> getBlockedActivities();
method public int getLockState();
method @NonNull public java.util.Set<android.os.UserHandle> getUsersWithMatchingAccounts();
method public void writeToParcel(@NonNull android.os.Parcel, int);
@@ -2621,6 +2625,8 @@ package android.companion.virtual {
public static final class VirtualDeviceParams.Builder {
ctor public VirtualDeviceParams.Builder();
method @NonNull public android.companion.virtual.VirtualDeviceParams build();
+ method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setAllowedActivities(@Nullable java.util.Set<android.content.ComponentName>);
+ method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setBlockedActivities(@Nullable java.util.Set<android.content.ComponentName>);
method @NonNull @RequiresPermission(value=android.Manifest.permission.ADD_ALWAYS_UNLOCKED_DISPLAY, conditional=true) public android.companion.virtual.VirtualDeviceParams.Builder setLockState(int);
method @NonNull public android.companion.virtual.VirtualDeviceParams.Builder setUsersWithMatchingAccounts(@NonNull java.util.Set<android.os.UserHandle>);
}
@@ -2688,7 +2694,7 @@ package android.content {
field public static final String BATTERY_STATS_SERVICE = "batterystats";
field @Deprecated public static final int BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS = 1048576; // 0x100000
field public static final int BIND_ALLOW_FOREGROUND_SERVICE_STARTS_FROM_BACKGROUND = 262144; // 0x40000
- field public static final String CLOUDSEARCH_SERVICE = "cloudsearch_service";
+ field public static final String CLOUDSEARCH_SERVICE = "cloudsearch";
field public static final String CONTENT_SUGGESTIONS_SERVICE = "content_suggestions";
field public static final String CONTEXTHUB_SERVICE = "contexthub";
field public static final String ETHERNET_SERVICE = "ethernet";
@@ -5534,9 +5540,9 @@ package android.location {
ctor public LastLocationRequest.Builder();
ctor public LastLocationRequest.Builder(@NonNull android.location.LastLocationRequest);
method @NonNull public android.location.LastLocationRequest build();
- method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LastLocationRequest.Builder setAdasGnssBypass(boolean);
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.WRITE_SECURE_SETTINGS, android.Manifest.permission.LOCATION_BYPASS}) public android.location.LastLocationRequest.Builder setAdasGnssBypass(boolean);
method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LastLocationRequest.Builder setHiddenFromAppOps(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LastLocationRequest.Builder setLocationSettingsIgnored(boolean);
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.WRITE_SECURE_SETTINGS, android.Manifest.permission.LOCATION_BYPASS}) public android.location.LastLocationRequest.Builder setLocationSettingsIgnored(boolean);
}
public class Location implements android.os.Parcelable {
@@ -5565,7 +5571,7 @@ package android.location {
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.location.LocationListener, @Nullable android.os.Looper);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull java.util.concurrent.Executor, @NonNull android.location.LocationListener);
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void requestLocationUpdates(@Nullable android.location.LocationRequest, @NonNull android.app.PendingIntent);
- method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setAdasGnssLocationEnabled(boolean);
+ method @RequiresPermission(anyOf={android.Manifest.permission.WRITE_SECURE_SETTINGS, android.Manifest.permission.LOCATION_BYPASS}) public void setAdasGnssLocationEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setExtraLocationControllerPackage(@Nullable String);
method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public void setExtraLocationControllerPackageEnabled(boolean);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setLocationEnabledForUser(boolean, @NonNull android.os.UserHandle);
@@ -5598,7 +5604,7 @@ package android.location {
method @Deprecated @NonNull public android.location.LocationRequest setFastestInterval(long);
method @Deprecated public void setHideFromAppOps(boolean);
method @Deprecated @NonNull public android.location.LocationRequest setInterval(long);
- method @Deprecated @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LocationRequest setLocationSettingsIgnored(boolean);
+ method @Deprecated @NonNull @RequiresPermission(anyOf={android.Manifest.permission.WRITE_SECURE_SETTINGS, android.Manifest.permission.LOCATION_BYPASS}) public android.location.LocationRequest setLocationSettingsIgnored(boolean);
method @Deprecated @NonNull public android.location.LocationRequest setLowPowerMode(boolean);
method @Deprecated @NonNull public android.location.LocationRequest setNumUpdates(int);
method @Deprecated @NonNull public android.location.LocationRequest setProvider(@NonNull String);
@@ -5614,9 +5620,9 @@ package android.location {
}
public static final class LocationRequest.Builder {
- method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LocationRequest.Builder setAdasGnssBypass(boolean);
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.WRITE_SECURE_SETTINGS, android.Manifest.permission.LOCATION_BYPASS}) public android.location.LocationRequest.Builder setAdasGnssBypass(boolean);
method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS) public android.location.LocationRequest.Builder setHiddenFromAppOps(boolean);
- method @NonNull @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public android.location.LocationRequest.Builder setLocationSettingsIgnored(boolean);
+ method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.WRITE_SECURE_SETTINGS, android.Manifest.permission.LOCATION_BYPASS}) public android.location.LocationRequest.Builder setLocationSettingsIgnored(boolean);
method @NonNull @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public android.location.LocationRequest.Builder setLowPower(boolean);
method @NonNull @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public android.location.LocationRequest.Builder setWorkSource(@Nullable android.os.WorkSource);
}
@@ -5868,6 +5874,7 @@ package android.media {
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void unregisterAudioPolicyAsync(@NonNull android.media.audiopolicy.AudioPolicy);
method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void unregisterMuteAwaitConnectionCallback(@NonNull android.media.AudioManager.MuteAwaitConnectionCallback);
method public void unregisterVolumeGroupCallback(@NonNull android.media.AudioManager.VolumeGroupCallback);
+ field public static final String ACTION_VOLUME_CHANGED = "android.media.VOLUME_CHANGED_ACTION";
field public static final int AUDIOFOCUS_FLAG_DELAY_OK = 1; // 0x1
field public static final int AUDIOFOCUS_FLAG_LOCK = 4; // 0x4
field public static final int AUDIOFOCUS_FLAG_PAUSES_ON_DUCKABLE_LOSS = 2; // 0x2
@@ -5876,7 +5883,10 @@ package android.media {
field public static final int DEVICE_VOLUME_BEHAVIOR_FIXED = 2; // 0x2
field public static final int DEVICE_VOLUME_BEHAVIOR_FULL = 1; // 0x1
field public static final int DEVICE_VOLUME_BEHAVIOR_VARIABLE = 0; // 0x0
+ field public static final String EXTRA_VOLUME_STREAM_TYPE = "android.media.EXTRA_VOLUME_STREAM_TYPE";
+ field public static final String EXTRA_VOLUME_STREAM_VALUE = "android.media.EXTRA_VOLUME_STREAM_VALUE";
field @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static final int STREAM_ASSISTANT = 11; // 0xb
+ field public static final int STREAM_BLUETOOTH_SCO = 6; // 0x6
field public static final int SUCCESS = 0; // 0x0
}
@@ -8918,6 +8928,8 @@ package android.os {
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportBleScanResults(@NonNull android.os.WorkSource, int);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportBleScanStarted(@NonNull android.os.WorkSource, boolean);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportBleScanStopped(@NonNull android.os.WorkSource, boolean);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void reportBluetoothOff(int, int, @NonNull String);
+ method @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT) public void reportBluetoothOn(int, int, @NonNull String);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportFullWifiLockAcquiredFromSource(@NonNull android.os.WorkSource);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportFullWifiLockReleasedFromSource(@NonNull android.os.WorkSource);
method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void reportMobileRadioPowerState(boolean, int);
@@ -11843,6 +11855,7 @@ package android.telecom {
public abstract class ConnectionService extends android.app.Service {
method public final void addExistingConnection(@NonNull android.telecom.PhoneAccountHandle, @NonNull android.telecom.Connection, @NonNull android.telecom.Conference);
+ method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.telecom.Connection onCreateUnknownConnection(@NonNull android.telecom.PhoneAccountHandle, @NonNull android.telecom.ConnectionRequest);
}
public abstract class InCallService extends android.app.Service {
diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt
index dbb427467a68..e17a9bb1512c 100644
--- a/core/api/system-lint-baseline.txt
+++ b/core/api/system-lint-baseline.txt
@@ -294,7 +294,6 @@ SamShouldBeLast: android.webkit.WebChromeClient#onShowFileChooser(android.webkit
ServiceName: android.content.Context#CLOUDSEARCH_SERVICE:
- Inconsistent service value; expected `cloudsearch`, was `cloudsearch_service` (Note: Do not change the name of already released services, which will break tools using `adb shell dumpsys`. Instead add `@SuppressLint("ServiceName"))`
UserHandleName: android.app.search.SearchAction.Builder#setUserHandle(android.os.UserHandle):
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index 39e12f40a79d..15148a93cbe7 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -2,6 +2,7 @@
package android {
public static final class Manifest.permission {
+ field public static final String ACCESS_KEYGUARD_SECURE_STORAGE = "android.permission.ACCESS_KEYGUARD_SECURE_STORAGE";
field public static final String ACCESS_NOTIFICATIONS = "android.permission.ACCESS_NOTIFICATIONS";
field public static final String ACTIVITY_EMBEDDING = "android.permission.ACTIVITY_EMBEDDING";
field public static final String APPROVE_INCIDENT_REPORTS = "android.permission.APPROVE_INCIDENT_REPORTS";
@@ -287,8 +288,8 @@ package android.app {
}
public class KeyguardManager {
- method @RequiresPermission(anyOf={android.Manifest.permission.SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS, "android.permission.ACCESS_KEYGUARD_SECURE_STORAGE"}) public boolean checkLock(int, @Nullable byte[]);
- method @RequiresPermission(anyOf={android.Manifest.permission.SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS, "android.permission.ACCESS_KEYGUARD_SECURE_STORAGE"}) public boolean setLock(int, @Nullable byte[], int, @Nullable byte[]);
+ method @RequiresPermission(anyOf={android.Manifest.permission.SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS, android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE}) public boolean checkLock(int, @Nullable byte[]);
+ method @RequiresPermission(anyOf={android.Manifest.permission.SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS, android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE}) public boolean setLock(int, @Nullable byte[], int, @Nullable byte[]);
}
public class LocaleManager {
@@ -462,6 +463,7 @@ package android.app.admin {
method @RequiresPermission(android.Manifest.permission.FORCE_DEVICE_POLICY_MANAGER_LOGS) public long forceSecurityLogs();
method public void forceUpdateUserSetupComplete(int);
method @NonNull public java.util.Set<java.lang.String> getDefaultCrossProfilePackages();
+ method public int getDeviceOwnerType(@NonNull android.content.ComponentName);
method @NonNull public java.util.Set<java.lang.String> getDisallowedSystemApps(@NonNull android.content.ComponentName, int, @NonNull String);
method public long getLastBugReportRequestTime();
method public long getLastNetworkLogRetrievalTime();
@@ -477,6 +479,7 @@ package android.app.admin {
method @RequiresPermission(allOf={android.Manifest.permission.MANAGE_DEVICE_ADMINS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public void setActiveAdmin(@NonNull android.content.ComponentName, boolean, int);
method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public boolean setDeviceOwner(@NonNull android.content.ComponentName, @Nullable String, int);
method @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS) public boolean setDeviceOwnerOnly(@NonNull android.content.ComponentName, @Nullable String, int);
+ method public void setDeviceOwnerType(@NonNull android.content.ComponentName, int);
method @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS) public void setNextOperationSafety(int, int);
field public static final String ACTION_DATA_SHARING_RESTRICTION_APPLIED = "android.app.action.DATA_SHARING_RESTRICTION_APPLIED";
field public static final String ACTION_DEVICE_POLICY_CONSTANTS_CHANGED = "android.app.action.DEVICE_POLICY_CONSTANTS_CHANGED";
@@ -582,6 +585,15 @@ package android.app.prediction {
}
+package android.app.trust {
+
+ public class TrustManager {
+ method @RequiresPermission(android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE) public void enableTrustAgentForUserForTest(@NonNull android.content.ComponentName, int);
+ method @RequiresPermission(android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE) public void reportUserRequestedUnlock(int);
+ }
+
+}
+
package android.app.usage {
public class NetworkStatsManager {
@@ -1092,7 +1104,7 @@ package android.hardware.camera2 {
package android.hardware.devicestate {
public final class DeviceStateManager {
- method @RequiresPermission(value=android.Manifest.permission.CONTROL_DEVICE_STATE, conditional=true) public void cancelRequest(@NonNull android.hardware.devicestate.DeviceStateRequest);
+ method @RequiresPermission(value=android.Manifest.permission.CONTROL_DEVICE_STATE, conditional=true) public void cancelStateRequest();
method @NonNull public int[] getSupportedStates();
method public void registerCallback(@NonNull java.util.concurrent.Executor, @NonNull android.hardware.devicestate.DeviceStateManager.DeviceStateCallback);
method @RequiresPermission(value=android.Manifest.permission.CONTROL_DEVICE_STATE, conditional=true) public void requestState(@NonNull android.hardware.devicestate.DeviceStateRequest, @Nullable java.util.concurrent.Executor, @Nullable android.hardware.devicestate.DeviceStateRequest.Callback);
@@ -2362,6 +2374,14 @@ package android.service.quicksettings {
}
+package android.service.trust {
+
+ public class TrustAgentService extends android.app.Service {
+ method public void onUserRequestedUnlock();
+ }
+
+}
+
package android.service.voice {
public class AlwaysOnHotwordDetector implements android.service.voice.HotwordDetector {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3b2176ee10a2..876e4014ba45 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -200,6 +200,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IVoiceInteractor;
import com.android.internal.content.ReferrerIntent;
+import com.android.internal.os.BinderCallsStats;
import com.android.internal.os.BinderInternal;
import com.android.internal.os.RuntimeInit;
import com.android.internal.os.SomeArgs;
@@ -7812,6 +7813,8 @@ public final class ActivityThread extends ClientTransactionHandler
MediaFrameworkPlatformInitializer.setMediaServiceManager(new MediaServiceManager());
MediaFrameworkInitializer.setMediaServiceManager(new MediaServiceManager());
BluetoothFrameworkInitializer.setBluetoothServiceManager(new BluetoothServiceManager());
+ BluetoothFrameworkInitializer.setBinderCallsStatsInitializer(context -> {
+ BinderCallsStats.startForBluetooth(context); });
}
private void purgePendingResources() {
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 7b55b6c0e458..b1956effb093 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -16,6 +16,11 @@
package android.app;
+import static android.app.admin.DevicePolicyResources.Drawables.Style.SOLID_COLORED;
+import static android.app.admin.DevicePolicyResources.Drawables.Style.SOLID_NOT_COLORED;
+import static android.app.admin.DevicePolicyResources.Drawables.UNDEFINED;
+import static android.app.admin.DevicePolicyResources.Drawables.WORK_PROFILE_ICON;
+import static android.app.admin.DevicePolicyResources.Drawables.WORK_PROFILE_ICON_BADGE;
import static android.content.pm.Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA256;
import static android.content.pm.Checksum.TYPE_PARTIAL_MERKLE_ROOT_1M_SHA512;
import static android.content.pm.Checksum.TYPE_WHOLE_MD5;
@@ -31,6 +36,7 @@ import android.annotation.Nullable;
import android.annotation.StringRes;
import android.annotation.UserIdInt;
import android.annotation.XmlRes;
+import android.app.admin.DevicePolicyManager;
import android.app.role.RoleManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
@@ -62,7 +68,6 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
-import android.content.pm.PackageParser;
import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
@@ -74,7 +79,6 @@ import android.content.pm.SuspendDialogInfo;
import android.content.pm.VerifierDeviceIdentity;
import android.content.pm.VersionedPackage;
import android.content.pm.dex.ArtManager;
-import android.content.pm.pkg.FrameworkPackageUserState;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
@@ -122,7 +126,6 @@ import dalvik.system.VMRuntime;
import libcore.util.EmptyArray;
-import java.io.File;
import java.lang.ref.WeakReference;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
@@ -172,6 +175,8 @@ public class ApplicationPackageManager extends PackageManager {
private PackageInstaller mInstaller;
@GuardedBy("mLock")
private ArtManager mArtManager;
+ @GuardedBy("mLock")
+ private DevicePolicyManager mDevicePolicyManager;
@GuardedBy("mDelegates")
private final ArrayList<MoveCallbackDelegate> mDelegates = new ArrayList<>();
@@ -188,6 +193,15 @@ public class ApplicationPackageManager extends PackageManager {
}
}
+ DevicePolicyManager getDevicePolicyManager() {
+ synchronized (mLock) {
+ if (mDevicePolicyManager == null) {
+ mDevicePolicyManager = mContext.getSystemService(DevicePolicyManager.class);
+ }
+ return mDevicePolicyManager;
+ }
+ }
+
private PermissionManager getPermissionManager() {
synchronized (mLock) {
if (mPermissionManager == null) {
@@ -1876,12 +1890,27 @@ public class ApplicationPackageManager extends PackageManager {
if (!hasUserBadge(user.getIdentifier())) {
return icon;
}
+
+ final Drawable badgeForeground = getDevicePolicyManager().getDrawable(
+ getUpdatableUserIconBadgeId(user),
+ SOLID_COLORED,
+ () -> getDefaultUserIconBadge(user));
+
Drawable badge = new LauncherIcons(mContext).getBadgeDrawable(
- getUserManager().getUserIconBadgeResId(user.getIdentifier()),
+ badgeForeground,
getUserBadgeColor(user, false));
return getBadgedDrawable(icon, badge, null, true);
}
+ private String getUpdatableUserIconBadgeId(UserHandle user) {
+ return getUserManager().isManagedProfile(user.getIdentifier())
+ ? WORK_PROFILE_ICON_BADGE : UNDEFINED;
+ }
+
+ private Drawable getDefaultUserIconBadge(UserHandle user) {
+ return mContext.getDrawable(getUserManager().getUserIconBadgeResId(user.getIdentifier()));
+ }
+
@Override
public Drawable getUserBadgedDrawableForDensity(Drawable drawable, UserHandle user,
Rect badgeLocation, int badgeDensity) {
@@ -1913,13 +1942,28 @@ public class ApplicationPackageManager extends PackageManager {
if (badgeColor == null) {
return null;
}
- Drawable badgeForeground = getDrawableForDensity(
- getUserManager().getUserBadgeResId(user.getIdentifier()), density);
+
+ final Drawable badgeForeground = getDevicePolicyManager().getDrawableForDensity(
+ getUpdatableUserBadgeId(user),
+ SOLID_COLORED,
+ density,
+ () -> getDefaultUserBadgeForDensity(user, density));
+
badgeForeground.setTint(getUserBadgeColor(user, false));
Drawable badge = new LayerDrawable(new Drawable[] {badgeColor, badgeForeground });
return badge;
}
+ private String getUpdatableUserBadgeId(UserHandle user) {
+ return getUserManager().isManagedProfile(user.getIdentifier())
+ ? WORK_PROFILE_ICON : UNDEFINED;
+ }
+
+ private Drawable getDefaultUserBadgeForDensity(UserHandle user, int density) {
+ return getDrawableForDensity(
+ getUserManager().getUserBadgeResId(user.getIdentifier()), density);
+ }
+
/**
* Returns the badge color based on whether device has dark theme enabled or not.
*/
@@ -1928,14 +1972,24 @@ public class ApplicationPackageManager extends PackageManager {
if (!hasUserBadge(user.getIdentifier())) {
return null;
}
- Drawable badge = getDrawableForDensity(
- getUserManager().getUserBadgeNoBackgroundResId(user.getIdentifier()), density);
+
+ final Drawable badge = getDevicePolicyManager().getDrawableForDensity(
+ getUpdatableUserBadgeId(user),
+ SOLID_NOT_COLORED,
+ density,
+ () -> getDefaultUserBadgeNoBackgroundForDensity(user, density));
+
if (badge != null) {
badge.setTint(getUserBadgeColor(user, true));
}
return badge;
}
+ private Drawable getDefaultUserBadgeNoBackgroundForDensity(UserHandle user, int density) {
+ return getDrawableForDensity(
+ getUserManager().getUserBadgeNoBackgroundResId(user.getIdentifier()), density);
+ }
+
private Drawable getDrawableForDensity(int drawableId, int density) {
if (density <= 0) {
density = mContext.getResources().getDisplayMetrics().densityDpi;
diff --git a/core/java/android/app/AsyncNotedAppOp.java b/core/java/android/app/AsyncNotedAppOp.java
index db58c215ffe2..7845b6a6588e 100644
--- a/core/java/android/app/AsyncNotedAppOp.java
+++ b/core/java/android/app/AsyncNotedAppOp.java
@@ -37,7 +37,8 @@ import com.android.internal.util.Preconditions;
@Immutable
@DataClass(genEqualsHashCode = true,
genAidl = true,
- genHiddenConstructor = true)
+ genHiddenConstructor = true,
+ genToString = true)
// - We don't expose the opCode, but rather the public name of the op, hence use a non-standard
// getter
@DataClass.Suppress({"getOpCode"})
@@ -70,9 +71,13 @@ public final class AsyncNotedAppOp implements Parcelable {
Preconditions.checkArgumentInRange(mOpCode, 0, AppOpsManager._NUM_OP - 1, "opCode");
}
+ private String opCodeToString() {
+ return getOp();
+ }
+
- // Code below generated by codegen v1.0.20.
+ // Code below generated by codegen v1.0.23.
//
// DO NOT MODIFY!
// CHECKSTYLE:OFF Generated code
@@ -160,6 +165,21 @@ public final class AsyncNotedAppOp implements Parcelable {
@Override
@DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "AsyncNotedAppOp { " +
+ "opCode = " + opCodeToString() + ", " +
+ "notingUid = " + mNotingUid + ", " +
+ "attributionTag = " + mAttributionTag + ", " +
+ "message = " + mMessage + ", " +
+ "time = " + mTime +
+ " }";
+ }
+
+ @Override
+ @DataClass.Generated.Member
public boolean equals(@Nullable Object o) {
// You can override field equality logic by defining either of the methods like:
// boolean fieldNameEquals(AsyncNotedAppOp other) { ... }
@@ -261,10 +281,10 @@ public final class AsyncNotedAppOp implements Parcelable {
};
@DataClass.Generated(
- time = 1604456255752L,
- codegenVersion = "1.0.20",
+ time = 1643320606160L,
+ codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/app/AsyncNotedAppOp.java",
- inputSignatures = "private final @android.annotation.IntRange int mOpCode\nprivate final @android.annotation.IntRange int mNotingUid\nprivate final @android.annotation.Nullable java.lang.String mAttributionTag\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.annotation.CurrentTimeMillisLong long mTime\npublic @android.annotation.NonNull java.lang.String getOp()\nprivate void onConstructed()\nclass AsyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genHiddenConstructor=true)")
+ inputSignatures = "private final @android.annotation.IntRange int mOpCode\nprivate final @android.annotation.IntRange int mNotingUid\nprivate final @android.annotation.Nullable java.lang.String mAttributionTag\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.annotation.CurrentTimeMillisLong long mTime\npublic @android.annotation.NonNull java.lang.String getOp()\nprivate void onConstructed()\nprivate java.lang.String opCodeToString()\nclass AsyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genHiddenConstructor=true, genToString=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index 14afd0fcebf8..5d1f4df4359e 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -746,7 +746,7 @@ public class KeyguardManager {
if (!hasPermission(Manifest.permission.SET_INITIAL_LOCK)) {
throw new SecurityException("Requires SET_INITIAL_LOCK permission.");
}
- return mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE);
+ return true;
}
private boolean hasPermission(String permission) {
@@ -814,6 +814,8 @@ public class KeyguardManager {
/**
* Set the lockscreen password after validating against its expected complexity level.
*
+ * Below {@link android.os.Build.VERSION_CODES#S_V2}, this API will only work
+ * when {@link PackageManager.FEATURE_AUTOMOTIVE} is present.
* @param lockType - type of lock as specified in {@link LockTypes}
* @param password - password to validate; this has the same encoding
* as the output of String#getBytes
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 4e32e9a41869..56c725eb81f9 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -746,6 +746,10 @@ public final class LoadedApk {
// default linker namespace.
continue;
}
+ if (info.isSdk()) {
+ // SDKs are not loaded automatically.
+ continue;
+ }
if (libsToLoadAfter.contains(info.getName())) {
if (DEBUG) {
Slog.v(ActivityThread.TAG,
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index d57c288165d5..6a147720f8e9 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -17,6 +17,10 @@
package android.app;
import static android.annotation.Dimension.DP;
+import static android.app.admin.DevicePolicyResources.Drawables.Source.NOTIFICATION;
+import static android.app.admin.DevicePolicyResources.Drawables.Style.SOLID_COLORED;
+import static android.app.admin.DevicePolicyResources.Drawables.UNDEFINED;
+import static android.app.admin.DevicePolicyResources.Drawables.WORK_PROFILE_ICON;
import static android.graphics.drawable.Icon.TYPE_URI;
import static android.graphics.drawable.Icon.TYPE_URI_ADAPTIVE_BITMAP;
@@ -39,6 +43,7 @@ import android.annotation.StyleableRes;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.annotation.TestApi;
+import android.app.admin.DevicePolicyManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
@@ -71,6 +76,7 @@ import android.os.Parcelable;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
+import android.os.UserManager;
import android.provider.Settings;
import android.text.BidiFormatter;
import android.text.SpannableStringBuilder;
@@ -5046,6 +5052,18 @@ public class Notification implements Parcelable
}
// Note: This assumes that the current user can read the profile badge of the
// originating user.
+ DevicePolicyManager dpm = mContext.getSystemService(DevicePolicyManager.class);
+ return dpm.getDrawable(
+ getUpdatableProfileBadgeId(), SOLID_COLORED, NOTIFICATION,
+ this::getDefaultProfileBadgeDrawable);
+ }
+
+ private String getUpdatableProfileBadgeId() {
+ return mContext.getSystemService(UserManager.class).isManagedProfile()
+ ? WORK_PROFILE_ICON : UNDEFINED;
+ }
+
+ private Drawable getDefaultProfileBadgeDrawable() {
return mContext.getPackageManager().getUserBadgeForDensityNoBackground(
new UserHandle(mContext.getUserId()), 0);
}
diff --git a/core/java/android/app/SyncNotedAppOp.java b/core/java/android/app/SyncNotedAppOp.java
index 7c0c08a7fc35..f156b30d5050 100644
--- a/core/java/android/app/SyncNotedAppOp.java
+++ b/core/java/android/app/SyncNotedAppOp.java
@@ -40,7 +40,8 @@ import com.android.internal.util.DataClass;
@DataClass(
genEqualsHashCode = true,
genAidl = true,
- genConstructor = false
+ genConstructor = false,
+ genToString = true
)
@DataClass.Suppress({"getOpCode", "getOpMode"})
public final class SyncNotedAppOp implements Parcelable {
@@ -118,6 +119,10 @@ public final class SyncNotedAppOp implements Parcelable {
return mOpMode;
}
+ private String opCodeToString() {
+ return getOp();
+ }
+
// Code below generated by codegen v1.0.23.
@@ -153,6 +158,20 @@ public final class SyncNotedAppOp implements Parcelable {
@Override
@DataClass.Generated.Member
+ public String toString() {
+ // You can override field toString logic by defining methods like:
+ // String fieldNameToString() { ... }
+
+ return "SyncNotedAppOp { " +
+ "opMode = " + mOpMode + ", " +
+ "opCode = " + opCodeToString() + ", " +
+ "attributionTag = " + mAttributionTag + ", " +
+ "packageName = " + mPackageName +
+ " }";
+ }
+
+ @Override
+ @DataClass.Generated.Member
public boolean equals(@Nullable Object o) {
// You can override field equality logic by defining either of the methods like:
// boolean fieldNameEquals(SyncNotedAppOp other) { ... }
@@ -245,10 +264,10 @@ public final class SyncNotedAppOp implements Parcelable {
};
@DataClass.Generated(
- time = 1619711733947L,
+ time = 1643320427700L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/app/SyncNotedAppOp.java",
- inputSignatures = "private final int mOpMode\nprivate final @android.annotation.IntRange int mOpCode\nprivate final @android.annotation.Nullable java.lang.String mAttributionTag\nprivate final @android.annotation.NonNull java.lang.String mPackageName\npublic @android.annotation.NonNull java.lang.String getOp()\npublic int getOpMode()\nclass SyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genConstructor=false)")
+ inputSignatures = "private final int mOpMode\nprivate final @android.annotation.IntRange int mOpCode\nprivate final @android.annotation.Nullable java.lang.String mAttributionTag\nprivate final @android.annotation.NonNull java.lang.String mPackageName\npublic @android.annotation.NonNull java.lang.String getOp()\npublic int getOpMode()\nprivate java.lang.String opCodeToString()\nclass SyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genConstructor=false, genToString=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/app/TaskInfo.java b/core/java/android/app/TaskInfo.java
index 18f9379c4111..3d2c03dc4e24 100644
--- a/core/java/android/app/TaskInfo.java
+++ b/core/java/android/app/TaskInfo.java
@@ -214,6 +214,12 @@ public class TaskInfo {
public boolean topActivityInSizeCompat;
/**
+ * Whether the direct top activity is eligible for letterbox education.
+ * @hide
+ */
+ public boolean topActivityEligibleForLetterboxEducation;
+
+ /**
* Whether this task is resizable. Unlike {@link #resizeMode} (which is what the top activity
* supports), this is what the system actually uses for resizability based on other policy and
* developer options.
@@ -398,7 +404,8 @@ public class TaskInfo {
/** @hide */
public boolean hasCompatUI() {
- return hasCameraCompatControl() || topActivityInSizeCompat;
+ return hasCameraCompatControl() || topActivityInSizeCompat
+ || topActivityEligibleForLetterboxEducation;
}
/**
@@ -460,6 +467,8 @@ public class TaskInfo {
return displayId == that.displayId
&& taskId == that.taskId
&& topActivityInSizeCompat == that.topActivityInSizeCompat
+ && topActivityEligibleForLetterboxEducation
+ == that.topActivityEligibleForLetterboxEducation
&& cameraCompatControlState == that.cameraCompatControlState
// Bounds are important if top activity has compat controls.
&& (!hasCompatUI() || configuration.windowConfiguration.getBounds()
@@ -507,6 +516,7 @@ public class TaskInfo {
isVisible = source.readBoolean();
isSleeping = source.readBoolean();
topActivityInSizeCompat = source.readBoolean();
+ topActivityEligibleForLetterboxEducation = source.readBoolean();
mTopActivityLocusId = source.readTypedObject(LocusId.CREATOR);
displayAreaFeatureId = source.readInt();
cameraCompatControlState = source.readInt();
@@ -551,6 +561,7 @@ public class TaskInfo {
dest.writeBoolean(isVisible);
dest.writeBoolean(isSleeping);
dest.writeBoolean(topActivityInSizeCompat);
+ dest.writeBoolean(topActivityEligibleForLetterboxEducation);
dest.writeTypedObject(mTopActivityLocusId, flags);
dest.writeInt(displayAreaFeatureId);
dest.writeInt(cameraCompatControlState);
@@ -585,6 +596,8 @@ public class TaskInfo {
+ " isVisible=" + isVisible
+ " isSleeping=" + isSleeping
+ " topActivityInSizeCompat=" + topActivityInSizeCompat
+ + " topActivityEligibleForLetterboxEducation= "
+ + topActivityEligibleForLetterboxEducation
+ " locusId=" + mTopActivityLocusId
+ " displayAreaFeatureId=" + displayAreaFeatureId
+ " cameraCompatControlState="
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 3960f4e1518e..9ac4030c73a7 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -454,6 +454,52 @@ public class DevicePolicyManager {
* <li>{@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}, optional</li>
* </ul>
*
+ * <p>Once the device admin app is set as the device owner, the following APIs are available for
+ * managing polices on the device:
+ * <ul>
+ * <li>{@link #isDeviceManaged()}</li>
+ * <li>{@link #isUninstallBlocked(ComponentName, String)}</li>
+ * <li>{@link #setUninstallBlocked(ComponentName, String, boolean)}</li>
+ * <li>{@link #setUserControlDisabledPackages(ComponentName, List)}</li>
+ * <li>{@link #getUserControlDisabledPackages(ComponentName)}</li>
+ * <li>{@link #setOrganizationName(ComponentName, CharSequence)}</li>
+ * <li>{@link #setShortSupportMessage(ComponentName, CharSequence)}</li>
+ * <li>{@link #isBackupServiceEnabled(ComponentName)}</li>
+ * <li>{@link #setBackupServiceEnabled(ComponentName, boolean)}</li>
+ * <li>{@link #isLockTaskPermitted(String)}</li>
+ * <li>{@link #setLockTaskFeatures(ComponentName, int)}, where the following lock task features
+ * can be set (otherwise a {@link SecurityException} will be thrown):</li>
+ * <ul>
+ * <li>{@link #LOCK_TASK_FEATURE_SYSTEM_INFO}</li>
+ * <li>{@link #LOCK_TASK_FEATURE_KEYGUARD}</li>
+ * <li>{@link #LOCK_TASK_FEATURE_HOME}</li>
+ * <li>{@link #LOCK_TASK_FEATURE_GLOBAL_ACTIONS}</li>
+ * <li>{@link #LOCK_TASK_FEATURE_NOTIFICATIONS}</li>
+ * </ul>
+ * <li>{@link #setLockTaskPackages(ComponentName, String[])}</li>
+ * <li>{@link #addPersistentPreferredActivity(ComponentName, IntentFilter, ComponentName)}</li>
+ * <li>{@link #clearPackagePersistentPreferredActivities(ComponentName, String)} </li>
+ * <li>{@link #wipeData(int)}</li>
+ * <li>{@link #isDeviceOwnerApp(String)}</li>
+ * <li>{@link #clearDeviceOwnerApp(String)}</li>
+ * <li>{@link #setPermissionGrantState(ComponentName, String, String, int)}, where
+ * {@link permission#READ_PHONE_STATE} is the <b>only</b> permission that can be
+ * {@link #PERMISSION_GRANT_STATE_GRANTED}, {@link #PERMISSION_GRANT_STATE_DENIED}, or
+ * {@link #PERMISSION_GRANT_STATE_DEFAULT} and can <b>only</b> be applied to the device admin
+ * app (otherwise a {@link SecurityException} will be thrown)</li>
+ * <li>{@link #addUserRestriction(ComponentName, String)}, where the following user restrictions
+ * are permitted (otherwise a {@link SecurityException} will be thrown):</li>
+ * <ul>
+ * <li>{@link UserManager#DISALLOW_ADD_USER}</li>
+ * <li>{@link UserManager#DISALLOW_DEBUGGING_FEATURES}</li>
+ * <li>{@link UserManager#DISALLOW_INSTALL_UNKNOWN_SOURCES}</li>
+ * <li>{@link UserManager#DISALLOW_SAFE_BOOT}</li>
+ * <li>{@link UserManager#DISALLOW_CONFIG_DATE_TIME}</li>
+ * <li>{@link UserManager#DISALLOW_OUTGOING_CALLS}</li>
+ * </ul>
+ * <li>{@link #clearUserRestriction(ComponentName, String)}</li>
+ * </ul>
+ *
* @hide
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
@@ -14577,6 +14623,7 @@ public class DevicePolicyManager {
*
* @hide
*/
+ @TestApi
public void setDeviceOwnerType(@NonNull ComponentName admin,
@DeviceOwnerType int deviceOwnerType) {
throwIfParentInstance("setDeviceOwnerType");
@@ -14600,6 +14647,7 @@ public class DevicePolicyManager {
*
* @hide
*/
+ @TestApi
@DeviceOwnerType
public int getDeviceOwnerType(@NonNull ComponentName admin) {
throwIfParentInstance("getDeviceOwnerType");
diff --git a/core/java/android/app/trust/ITrustManager.aidl b/core/java/android/app/trust/ITrustManager.aidl
index edabccf23c2c..7956a35c7b3d 100644
--- a/core/java/android/app/trust/ITrustManager.aidl
+++ b/core/java/android/app/trust/ITrustManager.aidl
@@ -17,6 +17,7 @@
package android.app.trust;
import android.app.trust.ITrustListener;
+import android.content.ComponentName;
import android.hardware.biometrics.BiometricSourceType;
/**
@@ -29,6 +30,7 @@ interface ITrustManager {
void reportUserRequestedUnlock(int userId);
void reportUnlockLockout(int timeoutMs, int userId);
void reportEnabledTrustAgentsChanged(int userId);
+ void enableTrustAgentForUserForTest(in ComponentName componentName, int userId);
void registerTrustListener(in ITrustListener trustListener);
void unregisterTrustListener(in ITrustListener trustListener);
void reportKeyguardShowingChanged();
diff --git a/core/java/android/app/trust/TrustManager.java b/core/java/android/app/trust/TrustManager.java
index 70b7de0767e4..fba2d3e03769 100644
--- a/core/java/android/app/trust/TrustManager.java
+++ b/core/java/android/app/trust/TrustManager.java
@@ -16,10 +16,14 @@
package android.app.trust;
-import android.Manifest;
+import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE;
+
+import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
+import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
+import android.content.ComponentName;
import android.content.Context;
import android.hardware.biometrics.BiometricSourceType;
import android.os.Handler;
@@ -33,9 +37,17 @@ import java.util.ArrayList;
import java.util.List;
/**
- * See {@link com.android.server.trust.TrustManagerService}
+ * Interface to the system service managing trust.
+ *
+ * <p>This class is for internal use only. This class is marked {@code @TestApi} to
+ * enable testing the trust system including {@link android.service.trust.TrustAgentService}.
+ * Methods which are currently not used in tests are marked @hide.
+ *
+ * @see com.android.server.trust.TrustManagerService
+ *
* @hide
*/
+@TestApi
@SystemService(Context.TRUST_SERVICE)
public class TrustManager {
@@ -51,7 +63,8 @@ public class TrustManager {
private final ITrustManager mService;
private final ArrayMap<TrustListener, ITrustListener> mTrustListeners;
- public TrustManager(IBinder b) {
+ /** @hide */
+ public TrustManager(@NonNull IBinder b) {
mService = ITrustManager.Stub.asInterface(b);
mTrustListeners = new ArrayMap<TrustListener, ITrustListener>();
}
@@ -62,8 +75,10 @@ public class TrustManager {
*
* @param userId The id for the user to be locked/unlocked.
* @param locked The value for that user's locked state.
+ *
+ * @hide
*/
- @RequiresPermission(Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE)
+ @RequiresPermission(ACCESS_KEYGUARD_SECURE_STORAGE)
public void setDeviceLockedForUser(int userId, boolean locked) {
try {
mService.setDeviceLockedForUser(userId, locked);
@@ -78,8 +93,11 @@ public class TrustManager {
* @param successful if true, the unlock attempt was successful.
*
* Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
+ *
+ * @hide
*/
@UnsupportedAppUsage
+ @RequiresPermission(ACCESS_KEYGUARD_SECURE_STORAGE)
public void reportUnlockAttempt(boolean successful, int userId) {
try {
mService.reportUnlockAttempt(successful, userId);
@@ -93,6 +111,7 @@ public class TrustManager {
*
* Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
*/
+ @RequiresPermission(ACCESS_KEYGUARD_SECURE_STORAGE)
public void reportUserRequestedUnlock(int userId) {
try {
mService.reportUserRequestedUnlock(userId);
@@ -112,7 +131,10 @@ public class TrustManager {
* attempt to unlock the device again.
*
* Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
+ *
+ * @hide
*/
+ @RequiresPermission(ACCESS_KEYGUARD_SECURE_STORAGE)
public void reportUnlockLockout(int timeoutMs, int userId) {
try {
mService.reportUnlockLockout(timeoutMs, userId);
@@ -125,7 +147,10 @@ public class TrustManager {
* Reports that the list of enabled trust agents changed for user {@param userId}.
*
* Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
+ *
+ * @hide
*/
+ @RequiresPermission(ACCESS_KEYGUARD_SECURE_STORAGE)
public void reportEnabledTrustAgentsChanged(int userId) {
try {
mService.reportEnabledTrustAgentsChanged(userId);
@@ -135,10 +160,33 @@ public class TrustManager {
}
/**
+ * Enables a trust agent.
+ *
+ * <p>The agent is specified by {@code componentName} and must be a subclass of
+ * {@link android.service.trust.TrustAgentService} and otherwise meet the requirements
+ * to be a trust agent.
+ *
+ * <p>This method can only be used in tests.
+ *
+ * @param componentName the trust agent to enable
+ */
+ @RequiresPermission(ACCESS_KEYGUARD_SECURE_STORAGE)
+ public void enableTrustAgentForUserForTest(@NonNull ComponentName componentName, int userId) {
+ try {
+ mService.enableTrustAgentForUserForTest(componentName, userId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Reports that the visibility of the keyguard has changed.
*
* Requires the {@link android.Manifest.permission#ACCESS_KEYGUARD_SECURE_STORAGE} permission.
+ *
+ * @hide
*/
+ @RequiresPermission(ACCESS_KEYGUARD_SECURE_STORAGE)
public void reportKeyguardShowingChanged() {
try {
mService.reportKeyguardShowingChanged();
@@ -151,7 +199,10 @@ public class TrustManager {
* Registers a listener for trust events.
*
* Requires the {@link android.Manifest.permission#TRUST_LISTENER} permission.
+ *
+ * @hide
*/
+ @RequiresPermission(android.Manifest.permission.TRUST_LISTENER)
public void registerTrustListener(final TrustListener trustListener) {
try {
ITrustListener.Stub iTrustListener = new ITrustListener.Stub() {
@@ -192,7 +243,10 @@ public class TrustManager {
* Unregisters a listener for trust events.
*
* Requires the {@link android.Manifest.permission#TRUST_LISTENER} permission.
+ *
+ * @hide
*/
+ @RequiresPermission(android.Manifest.permission.TRUST_LISTENER)
public void unregisterTrustListener(final TrustListener trustListener) {
ITrustListener iTrustListener = mTrustListeners.remove(trustListener);
if (iTrustListener != null) {
@@ -207,6 +261,8 @@ public class TrustManager {
/**
* @return whether {@param userId} has enabled and configured trust agents. Ignores short-term
* unavailability of trust due to {@link LockPatternUtils.StrongAuthTracker}.
+ *
+ * @hide
*/
@RequiresPermission(android.Manifest.permission.TRUST_LISTENER)
public boolean isTrustUsuallyManaged(int userId) {
@@ -223,8 +279,10 @@ public class TrustManager {
* can be skipped.
*
* @param userId
+ *
+ * @hide
*/
- @RequiresPermission(Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE)
+ @RequiresPermission(ACCESS_KEYGUARD_SECURE_STORAGE)
public void unlockedByBiometricForUser(int userId, BiometricSourceType source) {
try {
mService.unlockedByBiometricForUser(userId, source);
@@ -235,8 +293,10 @@ public class TrustManager {
/**
* Clears authentication by the specified biometric type for all users.
+ *
+ * @hide
*/
- @RequiresPermission(Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE)
+ @RequiresPermission(ACCESS_KEYGUARD_SECURE_STORAGE)
public void clearAllBiometricRecognized(BiometricSourceType source, int unlockedUser) {
try {
mService.clearAllBiometricRecognized(source, unlockedUser);
@@ -264,6 +324,7 @@ public class TrustManager {
}
};
+ /** @hide */
public interface TrustListener {
/**
diff --git a/core/java/android/companion/virtual/VirtualDeviceParams.java b/core/java/android/companion/virtual/VirtualDeviceParams.java
index 2ddfeb4c8ab5..1d0f7c091807 100644
--- a/core/java/android/companion/virtual/VirtualDeviceParams.java
+++ b/core/java/android/companion/virtual/VirtualDeviceParams.java
@@ -22,6 +22,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.content.ComponentName;
import android.os.Parcel;
@@ -106,11 +107,13 @@ public final class VirtualDeviceParams implements Parcelable {
}
/**
- * Returns the set of activities allowed to be streamed, or {@code null} if this is not set.
+ * Returns the set of activities allowed to be streamed, or {@code null} if all activities are
+ * allowed, except the ones explicitly blocked.
*
* @see Builder#setAllowedActivities(Set)
- * @hide // TODO(b/194949534): Unhide this API
*/
+ // Null and empty have different semantics - Null allows all activities to be streamed
+ @SuppressLint("NullableCollection")
@Nullable
public Set<ComponentName> getAllowedActivities() {
if (mAllowedActivities == null) {
@@ -120,12 +123,13 @@ public final class VirtualDeviceParams implements Parcelable {
}
/**
- * Returns the set of activities that are blocked from streaming, or {@code null} if this is not
- * set.
+ * Returns the set of activities that are blocked from streaming, or {@code null} to indicate
+ * that all activities in {@link #getAllowedActivities} are allowed.
*
* @see Builder#setBlockedActivities(Set)
- * @hide // TODO(b/194949534): Unhide this API
*/
+ // Allowing null to enforce that at most one of allowed / blocked activities can be non-null
+ @SuppressLint("NullableCollection")
@Nullable
public Set<ComponentName> getBlockedActivities() {
if (mBlockedActivities == null) {
@@ -255,8 +259,10 @@ public final class VirtualDeviceParams implements Parcelable {
*
* @param allowedActivities A set of activity {@link ComponentName} allowed to be launched
* in the virtual device.
- * @hide // TODO(b/194949534): Unhide this API
*/
+ // Null and empty have different semantics - Null allows all activities to be streamed
+ @SuppressLint("NullableCollection")
+ @NonNull
public Builder setAllowedActivities(@Nullable Set<ComponentName> allowedActivities) {
if (mBlockedActivities != null && allowedActivities != null) {
throw new IllegalArgumentException(
@@ -279,8 +285,10 @@ public final class VirtualDeviceParams implements Parcelable {
*
* @param blockedActivities A set of {@link ComponentName} to be blocked launching from
* virtual device.
- * @hide // TODO(b/194949534): Unhide this API
*/
+ // Allowing null to enforce that at most one of allowed / blocked activities can be non-null
+ @SuppressLint("NullableCollection")
+ @NonNull
public Builder setBlockedActivities(@Nullable Set<ComponentName> blockedActivities) {
if (mAllowedActivities != null && blockedActivities != null) {
throw new IllegalArgumentException(
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 4b4e00855ac1..0b8a8a23aee4 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -4987,10 +4987,8 @@ public abstract class Context {
* @hide
* @see #getSystemService(String)
*/
- // TODO(216507592): Change cloudsearch_service to cloudsearch.
@SystemApi
- @SuppressLint("ServiceName")
- public static final String CLOUDSEARCH_SERVICE = "cloudsearch_service";
+ public static final String CLOUDSEARCH_SERVICE = "cloudsearch";
/**
* Use with {@link #getSystemService(String)} to access the
diff --git a/core/java/android/content/pm/SharedLibraryInfo.java b/core/java/android/content/pm/SharedLibraryInfo.java
index 43a4b17e5172..4c0e2e6b36ca 100644
--- a/core/java/android/content/pm/SharedLibraryInfo.java
+++ b/core/java/android/content/pm/SharedLibraryInfo.java
@@ -46,7 +46,7 @@ public final class SharedLibraryInfo implements Parcelable {
TYPE_BUILTIN,
TYPE_DYNAMIC,
TYPE_STATIC,
- TYPE_SDK,
+ TYPE_SDK_PACKAGE,
})
@Retention(RetentionPolicy.SOURCE)
@interface Type{}
@@ -68,15 +68,21 @@ public final class SharedLibraryInfo implements Parcelable {
* Shared library type: this library is <strong>not</strong> backwards
* -compatible, can be updated and updates can be uninstalled. Clients
* link against a specific version of the library.
+ *
+ * Static shared libraries simulate static linking while allowing for
+ * multiple clients to reuse the same instance of the library.
*/
public static final int TYPE_STATIC = 2;
/**
- * SDK library type: this library is <strong>not</strong> backwards
- * -compatible, can be updated and updates can be uninstalled. Clients
- * depend on a specific version of the library.
+ * SDK package shared library type: this library is <strong>not</strong>
+ * compatible between versions, can be updated and updates can be
+ * uninstalled. Clients depend on a specific version of the library.
+ *
+ * SDK packages are not loaded automatically by the OS and rely
+ * e.g. on 3P libraries to make them available for the clients.
*/
- public static final int TYPE_SDK = 3;
+ public static final int TYPE_SDK_PACKAGE = 3;
/**
* Constant for referring to an undefined version.
@@ -301,7 +307,7 @@ public final class SharedLibraryInfo implements Parcelable {
* @hide
*/
public boolean isSdk() {
- return mType == TYPE_SDK;
+ return mType == TYPE_SDK_PACKAGE;
}
/**
@@ -367,7 +373,7 @@ public final class SharedLibraryInfo implements Parcelable {
case TYPE_STATIC: {
return "static";
}
- case TYPE_SDK: {
+ case TYPE_SDK_PACKAGE: {
return "sdk";
}
default: {
diff --git a/core/java/android/content/pm/TEST_MAPPING b/core/java/android/content/pm/TEST_MAPPING
index a503d14b6de4..dea083422612 100644
--- a/core/java/android/content/pm/TEST_MAPPING
+++ b/core/java/android/content/pm/TEST_MAPPING
@@ -162,5 +162,68 @@
{
"name": "CtsInstallHostTestCases"
}
+ ],
+ "staged-platinum-postsubmit": [
+ {
+ "name": "CtsIncrementalInstallHostTestCases"
+ },
+ {
+ "name": "CtsInstallHostTestCases"
+ },
+ {
+ "name": "CtsStagedInstallHostTestCases"
+ },
+ {
+ "name": "CtsExtractNativeLibsHostTestCases"
+ },
+ {
+ "name": "CtsAppSecurityHostTestCases",
+ "options": [
+ {
+ "include-filter": "com.android.cts.splitapp.SplitAppTest"
+ },
+ {
+ "include-filter": "android.appsecurity.cts.EphemeralTest"
+ }
+ ]
+ },
+ {
+ "name": "FrameworksServicesTests",
+ "options": [
+ {
+ "include-filter": "com.android.server.pm.PackageParserTest"
+ }
+ ]
+ },
+ {
+ "name": "CtsRollbackManagerHostTestCases"
+ },
+ {
+ "name": "CtsOsHostTestCases",
+ "options": [
+ {
+ "include-filter": "com.android.server.pm.PackageParserTest"
+ }
+ ]
+ },
+ {
+ "name": "CtsContentTestCases",
+ "options": [
+ {
+ "include-filter": "android.content.cts.IntentFilterTest"
+ }
+ ]
+ },
+ {
+ "name": "CtsAppEnumerationTestCases"
+ },
+ {
+ "name": "PackageManagerServiceUnitTests",
+ "options": [
+ {
+ "include-filter": "com.android.server.pm.test.verify.domain"
+ }
+ ]
+ }
]
}
diff --git a/core/java/android/database/CursorWindow.java b/core/java/android/database/CursorWindow.java
index f13c79587a28..52bba1484f1a 100644
--- a/core/java/android/database/CursorWindow.java
+++ b/core/java/android/database/CursorWindow.java
@@ -131,11 +131,16 @@ public class CursorWindow extends SQLiteClosable implements Parcelable {
*
* @param name The name of the cursor window, or null if none.
* @param windowSizeBytes Size of cursor window in bytes.
+ * @throws IllegalArgumentException if {@code windowSizeBytes} is less than 0
+ * @throws AssertionError if created window pointer is 0
* <p><strong>Note:</strong> Memory is dynamically allocated as data rows are added to the
* window. Depending on the amount of data stored, the actual amount of memory allocated can be
* lower than specified size, but cannot exceed it.
*/
public CursorWindow(String name, @BytesLong long windowSizeBytes) {
+ if (windowSizeBytes < 0) {
+ throw new IllegalArgumentException("Window size cannot be less than 0");
+ }
mStartPos = 0;
mName = name != null && name.length() != 0 ? name : "<unnamed>";
mWindowPtr = nativeCreate(mName, (int) windowSizeBytes);
diff --git a/core/java/android/database/CursorWindowAllocationException.java b/core/java/android/database/CursorWindowAllocationException.java
index 2e3227dc6788..5315c8b591ab 100644
--- a/core/java/android/database/CursorWindowAllocationException.java
+++ b/core/java/android/database/CursorWindowAllocationException.java
@@ -16,14 +16,14 @@
package android.database;
+import android.annotation.NonNull;
+
/**
* This exception is thrown when a CursorWindow couldn't be allocated,
* most probably due to memory not being available.
- *
- * @hide
*/
public class CursorWindowAllocationException extends RuntimeException {
- public CursorWindowAllocationException(String description) {
+ public CursorWindowAllocationException(@NonNull String description) {
super(description);
}
}
diff --git a/startop/scripts/trace_analyzer/queries_pretty_print_block_launch.sql b/core/java/android/hardware/biometrics/IBiometricContextListener.aidl
index bf5e3ccb4ac7..55cab52fc4f7 100644
--- a/startop/scripts/trace_analyzer/queries_pretty_print_block_launch.sql
+++ b/core/java/android/hardware/biometrics/IBiometricContextListener.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -13,16 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package android.hardware.biometrics;
-.headers on
-.mode quote
-
-SELECT * FROM blocked_iowait_for_app_launches;
-
-/*
-Output as CSV example:
-
-'blocked_iowait_duration_ms','process_name','launching_duration_ms','launching_started_timestamp_ms','launching_finished_timestamp_ms'
-125.33199995596078224,'com.android.settings',1022.4840000009862706,17149896.822000000626,17150919.305999998003
-
-*/
+/**
+ * A secondary communication channel from AuthController back to BiometricService for
+ * events that are not associated with an autentication session. See
+ * {@link IBiometricSysuiReceiver} for events associated with a session.
+ *
+ * @hide
+ */
+oneway interface IBiometricContextListener {
+ void onDozeChanged(boolean isDozing);
+}
diff --git a/core/java/android/hardware/devicestate/DeviceStateManager.java b/core/java/android/hardware/devicestate/DeviceStateManager.java
index b06d076fe08e..30aa4db938da 100644
--- a/core/java/android/hardware/devicestate/DeviceStateManager.java
+++ b/core/java/android/hardware/devicestate/DeviceStateManager.java
@@ -79,9 +79,9 @@ public final class DeviceStateManager {
* <ul>
* <li>The system deems the request can no longer be honored, for example if the requested
* state becomes unsupported.
- * <li>A call to {@link #cancelRequest(DeviceStateRequest)}.
+ * <li>A call to {@link #cancelStateRequest}.
* <li>Another processes submits a request succeeding this request in which case the request
- * will be suspended until the interrupting request is canceled.
+ * will be canceled.
* </ul>
* However, this behavior can be changed by setting flags on the {@link DeviceStateRequest}.
*
@@ -100,19 +100,18 @@ public final class DeviceStateManager {
}
/**
- * Cancels a {@link DeviceStateRequest request} previously submitted with a call to
+ * Cancels the active {@link DeviceStateRequest} previously submitted with a call to
* {@link #requestState(DeviceStateRequest, Executor, DeviceStateRequest.Callback)}.
* <p>
- * This method is noop if the {@code request} has not been submitted with a call to
- * {@link #requestState(DeviceStateRequest, Executor, DeviceStateRequest.Callback)}.
+ * This method is noop if there is no request currently active.
*
* @throws SecurityException if the caller is neither the current top-focused activity nor if
* the {@link android.Manifest.permission#CONTROL_DEVICE_STATE} permission is held.
*/
@RequiresPermission(value = android.Manifest.permission.CONTROL_DEVICE_STATE,
conditional = true)
- public void cancelRequest(@NonNull DeviceStateRequest request) {
- mGlobal.cancelRequest(request);
+ public void cancelStateRequest() {
+ mGlobal.cancelStateRequest();
}
/**
diff --git a/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java b/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
index 85e70b0fb3e9..aba538f51043 100644
--- a/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
+++ b/core/java/android/hardware/devicestate/DeviceStateManagerGlobal.java
@@ -151,20 +151,14 @@ public final class DeviceStateManagerGlobal {
* Cancels a {@link DeviceStateRequest request} previously submitted with a call to
* {@link #requestState(DeviceStateRequest, Executor, DeviceStateRequest.Callback)}.
*
- * @see DeviceStateManager#cancelRequest(DeviceStateRequest)
+ * @see DeviceStateManager#cancelStateRequest
*/
- public void cancelRequest(@NonNull DeviceStateRequest request) {
+ public void cancelStateRequest() {
synchronized (mLock) {
registerCallbackIfNeededLocked();
- final IBinder token = findRequestTokenLocked(request);
- if (token == null) {
- // This request has not been submitted.
- return;
- }
-
try {
- mDeviceStateManager.cancelRequest(token);
+ mDeviceStateManager.cancelStateRequest();
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
@@ -299,20 +293,6 @@ public final class DeviceStateManagerGlobal {
/**
* Handles a call from the server that a request for the supplied {@code token} has become
- * suspended.
- */
- private void handleRequestSuspended(IBinder token) {
- DeviceStateRequestWrapper request;
- synchronized (mLock) {
- request = mRequests.get(token);
- }
- if (request != null) {
- request.notifyRequestSuspended();
- }
- }
-
- /**
- * Handles a call from the server that a request for the supplied {@code token} has become
* canceled.
*/
private void handleRequestCanceled(IBinder token) {
@@ -337,11 +317,6 @@ public final class DeviceStateManagerGlobal {
}
@Override
- public void onRequestSuspended(IBinder token) {
- handleRequestSuspended(token);
- }
-
- @Override
public void onRequestCanceled(IBinder token) {
handleRequestCanceled(token);
}
@@ -395,14 +370,6 @@ public final class DeviceStateManagerGlobal {
mExecutor.execute(() -> mCallback.onRequestActivated(mRequest));
}
- void notifyRequestSuspended() {
- if (mCallback == null) {
- return;
- }
-
- mExecutor.execute(() -> mCallback.onRequestSuspended(mRequest));
- }
-
void notifyRequestCanceled() {
if (mCallback == null) {
return;
diff --git a/core/java/android/hardware/devicestate/DeviceStateRequest.java b/core/java/android/hardware/devicestate/DeviceStateRequest.java
index df488d2f6df1..893d765e48da 100644
--- a/core/java/android/hardware/devicestate/DeviceStateRequest.java
+++ b/core/java/android/hardware/devicestate/DeviceStateRequest.java
@@ -32,8 +32,7 @@ import java.util.concurrent.Executor;
* DeviceStateRequest.Callback)}.
* <p>
* By default, the request is kept active until a call to
- * {@link DeviceStateManager#cancelRequest(DeviceStateRequest)} or until one of the following
- * occurs:
+ * {@link DeviceStateManager#cancelStateRequest} or until one of the following occurs:
* <ul>
* <li>Another processes submits a request succeeding this request in which case the request
* will be suspended until the interrupting request is canceled.
diff --git a/core/java/android/hardware/devicestate/IDeviceStateManager.aidl b/core/java/android/hardware/devicestate/IDeviceStateManager.aidl
index 14ed03d09fd0..e450e42497a0 100644
--- a/core/java/android/hardware/devicestate/IDeviceStateManager.aidl
+++ b/core/java/android/hardware/devicestate/IDeviceStateManager.aidl
@@ -41,8 +41,9 @@ interface IDeviceStateManager {
* previously registered with {@link #registerCallback(IDeviceStateManagerCallback)} before a
* call to this method.
*
- * @param token the request token previously registered with
- * {@link #requestState(IBinder, int, int)}
+ * @param token the request token provided
+ * @param state the state of device the request is asking for
+ * @param flags any flags that correspond to the request
*
* @throws IllegalStateException if a callback has not yet been registered for the calling
* process.
@@ -52,14 +53,11 @@ interface IDeviceStateManager {
void requestState(IBinder token, int state, int flags);
/**
- * Cancels a request previously submitted with a call to
+ * Cancels the active request previously submitted with a call to
* {@link #requestState(IBinder, int, int)}.
*
- * @param token the request token previously registered with
- * {@link #requestState(IBinder, int, int)}
- *
- * @throws IllegalStateException if the supplied {@code token} has not been previously
- * requested.
+ * @throws IllegalStateException if a callback has not yet been registered for the calling
+ * process.
*/
- void cancelRequest(IBinder token);
+ void cancelStateRequest();
}
diff --git a/core/java/android/hardware/devicestate/IDeviceStateManagerCallback.aidl b/core/java/android/hardware/devicestate/IDeviceStateManagerCallback.aidl
index efb9888fb6ba..348690f65e78 100644
--- a/core/java/android/hardware/devicestate/IDeviceStateManagerCallback.aidl
+++ b/core/java/android/hardware/devicestate/IDeviceStateManagerCallback.aidl
@@ -41,16 +41,6 @@ interface IDeviceStateManagerCallback {
oneway void onRequestActive(IBinder token);
/**
- * Called to notify the callback that a request has become suspended. Guaranteed to be called
- * before a subsequent call to {@link #onDeviceStateInfoChanged(DeviceStateInfo)} if the request
- * becoming suspended resulted in a change of device state info.
- *
- * @param token the request token previously registered with
- * {@link IDeviceStateManager#requestState(IBinder, int, int)}
- */
- oneway void onRequestSuspended(IBinder token);
-
- /**
* Called to notify the callback that a request has become canceled. No further callbacks will
* be triggered for this request. Guaranteed to be called before a subsequent call to
* {@link #onDeviceStateInfoChanged(DeviceStateInfo)} if the request becoming canceled resulted
diff --git a/core/java/android/hardware/input/IInputManager.aidl b/core/java/android/hardware/input/IInputManager.aidl
index 0304815ef8fe..27403ec4fe59 100644
--- a/core/java/android/hardware/input/IInputManager.aidl
+++ b/core/java/android/hardware/input/IInputManager.aidl
@@ -122,9 +122,9 @@ interface IInputManager {
void removePortAssociation(in String inputPort);
// Add a runtime association between the input device and display.
- void addUniqueIdAssociation(in String inputDeviceName, in String displayUniqueId);
+ void addUniqueIdAssociation(in String inputPort, in String displayUniqueId);
// Remove the runtime association between the input device and display.
- void removeUniqueIdAssociation(in String inputDeviceName);
+ void removeUniqueIdAssociation(in String inputPort);
InputSensorInfo[] getSensorList(int deviceId);
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index cbc837393b6b..979e9dd6a1f6 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -1359,19 +1359,18 @@ public final class InputManager {
}
/**
- * Add a runtime association between the input device name and display, by unique id. Input
- * device names are expected to be unique.
- * @param inputDeviceName The name of the input device.
+ * Add a runtime association between the input port and display, by unique id. Input ports are
+ * expected to be unique.
+ * @param inputPort The port of the input device.
* @param displayUniqueId The unique id of the associated display.
* <p>
* Requires {@link android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
* </p>
* @hide
*/
- public void addUniqueIdAssociation(@NonNull String inputDeviceName,
- @NonNull String displayUniqueId) {
+ public void addUniqueIdAssociation(@NonNull String inputPort, @NonNull String displayUniqueId) {
try {
- mIm.addUniqueIdAssociation(inputDeviceName, displayUniqueId);
+ mIm.addUniqueIdAssociation(inputPort, displayUniqueId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1379,15 +1378,15 @@ public final class InputManager {
/**
* Removes a runtime association between the input device and display.
- * @param inputDeviceName The name of the input device.
+ * @param inputPort The port of the input device.
* <p>
* Requires {@link android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY}.
* </p>
* @hide
*/
- public void removeUniqueIdAssociation(@NonNull String inputDeviceName) {
+ public void removeUniqueIdAssociation(@NonNull String inputPort) {
try {
- mIm.removeUniqueIdAssociation(inputDeviceName);
+ mIm.removeUniqueIdAssociation(inputPort);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 60f5135aed6c..7ff74c68fc53 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -1341,7 +1341,6 @@ public class UsbManager {
*
* @hide
*/
- @SystemApi
@RequiresPermission(Manifest.permission.MANAGE_USB)
boolean resetUsbPort(@NonNull UsbPort port, int operationId,
IUsbOperationInternal callback) {
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index 41642e7a9fce..af57f793bf73 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -70,6 +70,7 @@ class IInputMethodWrapper extends IInputMethod.Stub
private static final int DO_SET_INPUT_CONTEXT = 20;
private static final int DO_UNSET_INPUT_CONTEXT = 30;
private static final int DO_START_INPUT = 32;
+ private static final int DO_ON_SHOULD_SHOW_IME_SWITCHER_WHEN_IME_IS_SHOWN_CHANGED = 35;
private static final int DO_CREATE_SESSION = 40;
private static final int DO_SET_SESSION_ENABLED = 45;
private static final int DO_SHOW_SOFT_INPUT = 60;
@@ -175,7 +176,7 @@ class IInputMethodWrapper extends IInputMethod.Stub
try {
inputMethod.initializeInternal((IBinder) args.arg1,
(IInputMethodPrivilegedOperations) args.arg2, msg.arg1,
- (boolean) args.arg3);
+ (boolean) args.arg3, msg.arg2 != 0);
} finally {
args.recycle();
}
@@ -195,14 +196,22 @@ class IInputMethodWrapper extends IInputMethod.Stub
final EditorInfo info = (EditorInfo) args.arg3;
final CancellationGroup cancellationGroup = (CancellationGroup) args.arg4;
final boolean restarting = args.argi5 == 1;
+ final boolean shouldShowImeSwitcherWhenImeIsShown = args.argi6 != 0;
final InputConnection ic = inputContext != null
? new RemoteInputConnection(mTarget, inputContext, cancellationGroup)
: null;
info.makeCompatible(mTargetSdkVersion);
- inputMethod.dispatchStartInputWithToken(ic, info, restarting, startInputToken);
+ inputMethod.dispatchStartInputWithToken(ic, info, restarting, startInputToken,
+ shouldShowImeSwitcherWhenImeIsShown);
args.recycle();
return;
}
+ case DO_ON_SHOULD_SHOW_IME_SWITCHER_WHEN_IME_IS_SHOWN_CHANGED: {
+ final boolean shouldShowImeSwitcherWhenImeIsShown = msg.arg1 != 0;
+ inputMethod.onShouldShowImeSwitcherWhenImeIsShownChanged(
+ shouldShowImeSwitcherWhenImeIsShown);
+ return;
+ }
case DO_CREATE_SESSION: {
SomeArgs args = (SomeArgs)msg.obj;
inputMethod.createSession(new InputMethodSessionCallbackWrapper(
@@ -291,10 +300,11 @@ class IInputMethodWrapper extends IInputMethod.Stub
@BinderThread
@Override
public void initializeInternal(IBinder token, IInputMethodPrivilegedOperations privOps,
- int configChanges, boolean stylusHwSupported) {
- mCaller.executeOrSendMessage(
- mCaller.obtainMessageIOOO(
- DO_INITIALIZE_INTERNAL, configChanges, token, privOps, stylusHwSupported));
+ int configChanges, boolean stylusHwSupported,
+ boolean shouldShowImeSwitcherWhenImeIsShown) {
+ mCaller.executeOrSendMessage(mCaller.obtainMessageIIOOO(DO_INITIALIZE_INTERNAL,
+ configChanges, shouldShowImeSwitcherWhenImeIsShown ? 1 : 0, token, privOps,
+ stylusHwSupported));
}
@BinderThread
@@ -334,13 +344,23 @@ class IInputMethodWrapper extends IInputMethod.Stub
@BinderThread
@Override
public void startInput(IBinder startInputToken, IInputContext inputContext,
- EditorInfo attribute, boolean restarting) {
+ EditorInfo attribute, boolean restarting, boolean shouldShowImeSwitcherWhenImeIsShown) {
if (mCancellationGroup == null) {
Log.e(TAG, "startInput must be called after bindInput.");
mCancellationGroup = new CancellationGroup();
}
mCaller.executeOrSendMessage(mCaller.obtainMessageOOOOII(DO_START_INPUT, startInputToken,
- inputContext, attribute, mCancellationGroup, restarting ? 1 : 0, 0 /* unused */));
+ inputContext, attribute, mCancellationGroup, restarting ? 1 : 0,
+ shouldShowImeSwitcherWhenImeIsShown ? 1 : 0));
+ }
+
+ @BinderThread
+ @Override
+ public void onShouldShowImeSwitcherWhenImeIsShownChanged(
+ boolean shouldShowImeSwitcherWhenImeIsShown) {
+ mCaller.executeOrSendMessage(mCaller.obtainMessageI(
+ DO_ON_SHOULD_SHOW_IME_SWITCHER_WHEN_IME_IS_SHOWN_CHANGED,
+ shouldShowImeSwitcherWhenImeIsShown ? 1 : 0));
}
@BinderThread
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 14f92fbb4194..f55c41594389 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -658,7 +658,7 @@ public class InputMethodService extends AbstractInputMethodService {
@Override
public final void initializeInternal(@NonNull IBinder token,
IInputMethodPrivilegedOperations privilegedOperations, int configChanges,
- boolean stylusHwSupported) {
+ boolean stylusHwSupported, boolean shouldShowImeSwitcherWhenImeIsShown) {
if (mDestroyed) {
Log.i(TAG, "The InputMethodService has already onDestroyed()."
+ "Ignore the initialization.");
@@ -671,6 +671,8 @@ public class InputMethodService extends AbstractInputMethodService {
if (stylusHwSupported) {
mInkWindow = new InkWindow(mWindow.getContext());
}
+ mNavigationBarController.setShouldShowImeSwitcherWhenImeIsShown(
+ shouldShowImeSwitcherWhenImeIsShown);
attachToken(token);
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
@@ -780,9 +782,10 @@ public class InputMethodService extends AbstractInputMethodService {
@Override
public final void dispatchStartInputWithToken(@Nullable InputConnection inputConnection,
@NonNull EditorInfo editorInfo, boolean restarting,
- @NonNull IBinder startInputToken) {
+ @NonNull IBinder startInputToken, boolean shouldShowImeSwitcherWhenImeIsShown) {
mPrivOps.reportStartInputAsync(startInputToken);
-
+ mNavigationBarController.setShouldShowImeSwitcherWhenImeIsShown(
+ shouldShowImeSwitcherWhenImeIsShown);
if (restarting) {
restartInput(inputConnection, editorInfo);
} else {
@@ -796,6 +799,18 @@ public class InputMethodService extends AbstractInputMethodService {
*/
@MainThread
@Override
+ public void onShouldShowImeSwitcherWhenImeIsShownChanged(
+ boolean shouldShowImeSwitcherWhenImeIsShown) {
+ mNavigationBarController.setShouldShowImeSwitcherWhenImeIsShown(
+ shouldShowImeSwitcherWhenImeIsShown);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @hide
+ */
+ @MainThread
+ @Override
public void hideSoftInputWithToken(int flags, ResultReceiver resultReceiver,
IBinder hideInputToken) {
mSystemCallingHideSoftInput = true;
diff --git a/core/java/android/inputmethodservice/NavigationBarController.java b/core/java/android/inputmethodservice/NavigationBarController.java
index 2484cf079c56..508172d13aa3 100644
--- a/core/java/android/inputmethodservice/NavigationBarController.java
+++ b/core/java/android/inputmethodservice/NavigationBarController.java
@@ -19,6 +19,7 @@ package android.inputmethodservice;
import static android.content.Intent.ACTION_OVERLAY_CHANGED;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;
+import android.animation.ValueAnimator;
import android.annotation.FloatRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -44,6 +45,8 @@ import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowInsetsController.Appearance;
import android.view.WindowManagerPolicyConstants;
+import android.view.animation.Interpolator;
+import android.view.animation.PathInterpolator;
import android.widget.FrameLayout;
import java.util.Objects;
@@ -71,6 +74,10 @@ final class NavigationBarController {
default void onDestroy() {
}
+ default void setShouldShowImeSwitcherWhenImeIsShown(
+ boolean shouldShowImeSwitcherWhenImeIsShown) {
+ }
+
default void onSystemBarAppearanceChanged(@Appearance int appearance) {
}
@@ -106,6 +113,10 @@ final class NavigationBarController {
mImpl.onDestroy();
}
+ void setShouldShowImeSwitcherWhenImeIsShown(boolean shouldShowImeSwitcherWhenImeIsShown) {
+ mImpl.setShouldShowImeSwitcherWhenImeIsShown(shouldShowImeSwitcherWhenImeIsShown);
+ }
+
void onSystemBarAppearanceChanged(@Appearance int appearance) {
mImpl.onSystemBarAppearanceChanged(appearance);
}
@@ -115,6 +126,12 @@ final class NavigationBarController {
}
private static final class Impl implements Callback {
+ private static final int DEFAULT_COLOR_ADAPT_TRANSITION_TIME = 1700;
+
+ // Copied from com.android.systemui.animation.Interpolators#LEGACY_DECELERATE
+ private static final Interpolator LEGACY_DECELERATE =
+ new PathInterpolator(0f, 0f, 0.2f, 1f);
+
@NonNull
private final InputMethodService mService;
@@ -130,9 +147,17 @@ final class NavigationBarController {
@Nullable
private BroadcastReceiver mSystemOverlayChangedReceiver;
+ private boolean mShouldShowImeSwitcherWhenImeIsShown;
+
@Appearance
private int mAppearance;
+ @FloatRange(from = 0.0f, to = 1.0f)
+ private float mDarkIntensity;
+
+ @Nullable
+ private ValueAnimator mTintAnimator;
+
Impl(@NonNull InputMethodService inputMethodService) {
mService = inputMethodService;
}
@@ -190,7 +215,9 @@ final class NavigationBarController {
// TODO(b/213337792): Support InputMethodService#setBackDisposition().
// TODO(b/213337792): Set NAVIGATION_HINT_IME_SHOWN only when necessary.
final int hints = StatusBarManager.NAVIGATION_HINT_BACK_ALT
- | StatusBarManager.NAVIGATION_HINT_IME_SHOWN;
+ | (mShouldShowImeSwitcherWhenImeIsShown
+ ? StatusBarManager.NAVIGATION_HINT_IME_SHOWN
+ : 0);
navigationBarView.setNavigationIconHints(hints);
}
} else {
@@ -368,6 +395,10 @@ final class NavigationBarController {
if (mDestroyed) {
return;
}
+ if (mTintAnimator != null) {
+ mTintAnimator.cancel();
+ mTintAnimator = null;
+ }
if (mSystemOverlayChangedReceiver != null) {
mService.unregisterReceiver(mSystemOverlayChangedReceiver);
mSystemOverlayChangedReceiver = null;
@@ -404,6 +435,31 @@ final class NavigationBarController {
}
@Override
+ public void setShouldShowImeSwitcherWhenImeIsShown(
+ boolean shouldShowImeSwitcherWhenImeIsShown) {
+ if (mDestroyed) {
+ return;
+ }
+ if (mShouldShowImeSwitcherWhenImeIsShown == shouldShowImeSwitcherWhenImeIsShown) {
+ return;
+ }
+ mShouldShowImeSwitcherWhenImeIsShown = shouldShowImeSwitcherWhenImeIsShown;
+
+ if (mNavigationBarFrame == null) {
+ return;
+ }
+ final NavigationBarView navigationBarView =
+ mNavigationBarFrame.findViewByPredicate(NavigationBarView.class::isInstance);
+ if (navigationBarView == null) {
+ return;
+ }
+ final int hints = StatusBarManager.NAVIGATION_HINT_BACK_ALT
+ | (shouldShowImeSwitcherWhenImeIsShown
+ ? StatusBarManager.NAVIGATION_HINT_IME_SHOWN : 0);
+ navigationBarView.setNavigationIconHints(hints);
+ }
+
+ @Override
public void onSystemBarAppearanceChanged(@Appearance int appearance) {
if (mDestroyed) {
return;
@@ -416,10 +472,24 @@ final class NavigationBarController {
}
final float targetDarkIntensity = calculateTargetDarkIntensity(mAppearance);
- setIconTintInternal(targetDarkIntensity);
+
+ if (mTintAnimator != null) {
+ mTintAnimator.cancel();
+ }
+ mTintAnimator = ValueAnimator.ofFloat(mDarkIntensity, targetDarkIntensity);
+ mTintAnimator.addUpdateListener(
+ animation -> setIconTintInternal((Float) animation.getAnimatedValue()));
+ mTintAnimator.setDuration(DEFAULT_COLOR_ADAPT_TRANSITION_TIME);
+ mTintAnimator.setStartDelay(0);
+ mTintAnimator.setInterpolator(LEGACY_DECELERATE);
+ mTintAnimator.start();
}
private void setIconTintInternal(float darkIntensity) {
+ mDarkIntensity = darkIntensity;
+ if (mNavigationBarFrame == null) {
+ return;
+ }
final NavigationBarView navigationBarView =
mNavigationBarFrame.findViewByPredicate(NavigationBarView.class::isInstance);
if (navigationBarView == null) {
@@ -438,7 +508,9 @@ final class NavigationBarController {
public String toDebugString() {
return "{mRenderGesturalNavButtons=" + mRenderGesturalNavButtons
+ " mNavigationBarFrame=" + mNavigationBarFrame
+ + " mShouldShowImeSwitcherWhenImeIsShown" + mShouldShowImeSwitcherWhenImeIsShown
+ " mAppearance=0x" + Integer.toHexString(mAppearance)
+ + " mDarkIntensity=" + mDarkIntensity
+ "}";
}
}
diff --git a/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java b/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java
index 24c22a99b78d..9772bde94ac9 100644
--- a/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java
+++ b/core/java/android/net/netstats/NetworkStatsDataMigrationUtils.java
@@ -16,9 +16,7 @@
package android.net.netstats;
-import static android.app.usage.NetworkStatsManager.PREFIX_UID;
-import static android.app.usage.NetworkStatsManager.PREFIX_UID_TAG;
-import static android.app.usage.NetworkStatsManager.PREFIX_XT;
+import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.ConnectivityManager.TYPE_MOBILE_DUN;
import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI;
@@ -28,6 +26,7 @@ import static android.net.NetworkStats.SET_DEFAULT;
import static android.net.NetworkStats.TAG_NONE;
import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.net.NetworkIdentity;
import android.net.NetworkStatsCollection;
import android.net.NetworkStatsHistory;
@@ -54,12 +53,27 @@ import java.util.HashSet;
import java.util.Set;
/**
- * Helper class to read old version of persistent network statistics, the implementation is
- * intended to be modified by OEM partners to accommodate their custom changes.
+ * Helper class to read old version of persistent network statistics.
+ *
+ * The implementation is intended to be modified by OEM partners to
+ * accommodate their custom changes.
+ *
* @hide
*/
-// @SystemApi(client = MODULE_LIBRARIES)
+@SystemApi(client = MODULE_LIBRARIES)
public class NetworkStatsDataMigrationUtils {
+ /**
+ * Prefix of the files which are used to store per network interface statistics.
+ */
+ public static final String PREFIX_XT = "xt";
+ /**
+ * Prefix of the files which are used to store per uid statistics.
+ */
+ public static final String PREFIX_UID = "uid";
+ /**
+ * Prefix of the files which are used to store per uid tagged traffic statistics.
+ */
+ public static final String PREFIX_UID_TAG = "uid_tag";
private static final HashMap<String, String> sPrefixLegacyFileNameMap =
new HashMap<String, String>() {{
@@ -146,17 +160,51 @@ public class NetworkStatsDataMigrationUtils {
}
/**
- * Read legacy persisted network stats from disk. This function provides a default
- * implementation to read persisted network stats from two different locations.
- * And this is intended to be modified by OEM to read from custom file format or
- * locations if necessary.
+ * Read legacy persisted network stats from disk.
+ *
+ * This function provides the implementation to read legacy network stats
+ * from disk. It is used for migration of legacy network stats into the
+ * stats provided by the Connectivity module.
+ * This function needs to know about the previous format(s) of the network
+ * stats data that might be stored on this device so it can be read and
+ * conserved upon upgrade to Android 13 or above.
+ *
+ * This function will be called multiple times sequentially, all on the
+ * same thread, and will not be called multiple times concurrently. This
+ * function is expected to do a substantial amount of disk access, and
+ * doesn't need to return particularly fast, but the first boot after
+ * an upgrade to Android 13+ will be held until migration is done. As
+ * migration is only necessary once, after the first boot following the
+ * upgrade, this delay is not incurred.
+ *
+ * If this function fails in any way, it should throw an exception. If this
+ * happens, the system can't know about the data that was stored in the
+ * legacy files, but it will still count data usage happening on this
+ * session. On the next boot, the system will try migration again, and
+ * merge the returned data with the data used with the previous session.
+ * The system will only try the migration up to three (3) times. The remaining
+ * count is stored in the netstats_import_legacy_file_needed device config. The
+ * legacy data is never deleted by the mainline module to avoid any possible
+ * data loss.
+ *
+ * It is possible to set the netstats_import_legacy_file_needed device config
+ * to any positive integer to force the module to perform the migration. This
+ * can be achieved by calling the following command before rebooting :
+ * adb shell device_config put connectivity netstats_import_legacy_file_needed 1
+ *
+ * The AOSP implementation provides code to read persisted network stats as
+ * they were written by AOSP prior to Android 13.
+ * OEMs who have used the AOSP implementation of persisting network stats
+ * to disk don't need to change anything.
+ * OEM that had modifications to this format should modify this function
+ * to read from their custom file format or locations if necessary.
*
* @param prefix Type of data which is being read by the service.
* @param bucketDuration Duration of the buckets of the object, in milliseconds.
* @return {@link NetworkStatsCollection} instance.
*/
@NonNull
- public static NetworkStatsCollection readPlatformCollectionLocked(
+ public static NetworkStatsCollection readPlatformCollection(
@NonNull String prefix, long bucketDuration) throws IOException {
final NetworkStatsCollection.Builder builder =
new NetworkStatsCollection.Builder(bucketDuration);
@@ -397,7 +445,7 @@ public class NetworkStatsDataMigrationUtils {
if (version >= IdentitySetVersion.VERSION_ADD_OEM_MANAGED_NETWORK) {
oemNetCapabilities = in.readInt();
} else {
- oemNetCapabilities = NetworkIdentity.OEM_NONE;
+ oemNetCapabilities = NetworkTemplate.OEM_MANAGED_NO;
}
// Legacy files might contain TYPE_MOBILE_* types which were deprecated in later
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 2d338179186e..07a51324404c 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -34,6 +34,7 @@ import android.server.ServerProtoEnums;
import android.service.batterystats.BatteryStatsServiceDumpHistoryProto;
import android.service.batterystats.BatteryStatsServiceDumpProto;
import android.telephony.CellSignalStrength;
+import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
import android.text.format.DateFormat;
import android.util.ArrayMap;
@@ -2654,6 +2655,46 @@ public abstract class BatteryStats implements Parcelable {
*/
public abstract Timer getPhoneDataConnectionTimer(int dataType);
+ /** @hide */
+ public static final int RADIO_ACCESS_TECHNOLOGY_OTHER = 0;
+ /** @hide */
+ public static final int RADIO_ACCESS_TECHNOLOGY_LTE = 1;
+ /** @hide */
+ public static final int RADIO_ACCESS_TECHNOLOGY_NR = 2;
+ /** @hide */
+ public static final int RADIO_ACCESS_TECHNOLOGY_COUNT = 3;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "RADIO_ACCESS_TECHNOLOGY_",
+ value = {RADIO_ACCESS_TECHNOLOGY_OTHER, RADIO_ACCESS_TECHNOLOGY_LTE,
+ RADIO_ACCESS_TECHNOLOGY_NR})
+ public @interface RadioAccessTechnology {
+ }
+
+ /** @hide */
+ public static final String[] RADIO_ACCESS_TECHNOLOGY_NAMES = {"Other", "LTE", "NR"};
+
+ /**
+ * Returns the time in microseconds that the mobile radio has been active on a
+ * given Radio Access Technology (RAT), at a given frequency (NR RAT only), for a given
+ * transmission power level.
+ *
+ * @param rat Radio Access Technology {@see RadioAccessTechnology}
+ * @param frequencyRange frequency range {@see ServiceState.FrequencyRange}, only needed for
+ * RADIO_ACCESS_TECHNOLOGY_NR. Use
+ * {@link ServiceState.FREQUENCY_RANGE_UNKNOWN} for other Radio Access
+ * Technologies.
+ * @param signalStrength the cellular signal strength. {@see CellSignalStrength#getLevel()}
+ * @param elapsedRealtimeMs current elapsed realtime
+ * @return time (in milliseconds) the mobile radio spent active in the specified state,
+ * while on battery.
+ * @hide
+ */
+ public abstract long getActiveRadioDurationMs(@RadioAccessTechnology int rat,
+ @ServiceState.FrequencyRange int frequencyRange, int signalStrength,
+ long elapsedRealtimeMs);
+
static final String[] WIFI_SUPPL_STATE_NAMES = {
"invalid", "disconn", "disabled", "inactive", "scanning",
"authenticating", "associating", "associated", "4-way-handshake",
@@ -3997,6 +4038,89 @@ public abstract class BatteryStats implements Parcelable {
}
}
+ private void printCellularPerRatBreakdown(PrintWriter pw, StringBuilder sb, String prefix,
+ long rawRealtimeMs) {
+ final String allFrequenciesHeader =
+ " All frequencies:\n";
+ final String[] nrFrequencyRangeDescription = new String[]{
+ " Unknown frequency:\n",
+ " Low frequency (less than 1GHz):\n",
+ " Middle frequency (1GHz to 3GHz):\n",
+ " High frequency (3GHz to 6GHz):\n",
+ " Mmwave frequency (greater than 6GHz):\n"};
+ final String signalStrengthHeader =
+ " Signal Strength Time:\n";
+ final String[] signalStrengthDescription = new String[]{
+ " unknown: ",
+ " poor: ",
+ " moderate: ",
+ " good: ",
+ " great: "};
+
+ final long totalActiveTimesMs = getMobileRadioActiveTime(rawRealtimeMs * 1000,
+ STATS_SINCE_CHARGED) / 1000;
+
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append("Active Cellular Radio Access Technology Breakdown:");
+ pw.println(sb);
+
+ boolean hasData = false;
+ final int numSignalStrength = CellSignalStrength.getNumSignalStrengthLevels();
+ for (int rat = RADIO_ACCESS_TECHNOLOGY_COUNT - 1; rat >= 0; rat--) {
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" ");
+ sb.append(RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
+ sb.append(":\n");
+ sb.append(prefix);
+
+ final int numFreqLvl =
+ rat == RADIO_ACCESS_TECHNOLOGY_NR ? nrFrequencyRangeDescription.length : 1;
+ for (int freqLvl = numFreqLvl - 1; freqLvl >= 0; freqLvl--) {
+ final int freqDescriptionStart = sb.length();
+ boolean hasFreqData = false;
+ if (rat == RADIO_ACCESS_TECHNOLOGY_NR) {
+ sb.append(nrFrequencyRangeDescription[freqLvl]);
+ } else {
+ sb.append(allFrequenciesHeader);
+ }
+
+ sb.append(prefix);
+ sb.append(signalStrengthHeader);
+ for (int strength = 0; strength < numSignalStrength; strength++) {
+ final long timeMs = getActiveRadioDurationMs(rat, freqLvl, strength,
+ rawRealtimeMs);
+ if (timeMs <= 0) continue;
+ hasFreqData = true;
+ sb.append(prefix);
+ sb.append(signalStrengthDescription[strength]);
+ formatTimeMs(sb, timeMs);
+ sb.append("(");
+ sb.append(formatRatioLocked(timeMs, totalActiveTimesMs));
+ sb.append(")\n");
+ }
+
+ if (hasFreqData) {
+ hasData = true;
+ pw.print(sb);
+ sb.setLength(0);
+ sb.append(prefix);
+ } else {
+ // No useful data was printed, rewind sb to before the start of this frequency.
+ sb.setLength(freqDescriptionStart);
+ }
+ }
+ }
+
+ if (!hasData) {
+ sb.setLength(0);
+ sb.append(prefix);
+ sb.append(" (no activity)");
+ pw.println(sb);
+ }
+ }
+
/**
* Temporary for settings.
*/
@@ -5269,6 +5393,8 @@ public abstract class BatteryStats implements Parcelable {
printControllerActivity(pw, sb, prefix, CELLULAR_CONTROLLER_NAME,
getModemControllerActivity(), which);
+ printCellularPerRatBreakdown(pw, sb, prefix + " ", rawRealtimeMs);
+
pw.print(" Cellular data received: "); pw.println(formatBytesLocked(mobileRxTotalBytes));
pw.print(" Cellular data sent: "); pw.println(formatBytesLocked(mobileTxTotalBytes));
pw.print(" Cellular packets received: "); pw.println(mobileRxTotalPackets);
diff --git a/core/java/android/os/BatteryStatsManager.java b/core/java/android/os/BatteryStatsManager.java
index 2a609b8f6ae4..f16bbc66e6cd 100644
--- a/core/java/android/os/BatteryStatsManager.java
+++ b/core/java/android/os/BatteryStatsManager.java
@@ -24,6 +24,8 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
+import android.bluetooth.annotations.RequiresBluetoothConnectPermission;
+import android.bluetooth.annotations.RequiresLegacyBluetoothAdminPermission;
import android.content.Context;
import android.net.NetworkStack;
import android.os.connectivity.CellularBatteryStats;
@@ -515,6 +517,42 @@ public final class BatteryStatsManager {
}
/**
+ * Indicates that Bluetooth was toggled on.
+ *
+ * @param uid calling package uid
+ * @param reason why Bluetooth has been turned on
+ * @param packageName package responsible for this change
+ */
+ @RequiresLegacyBluetoothAdminPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
+ public void reportBluetoothOn(int uid, int reason, @NonNull String packageName) {
+ try {
+ mBatteryStats.noteBluetoothOn(uid, reason, packageName);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Indicates that Bluetooth was toggled off.
+ *
+ * @param uid calling package uid
+ * @param reason why Bluetooth has been turned on
+ * @param packageName package responsible for this change
+ */
+ @RequiresLegacyBluetoothAdminPermission
+ @RequiresBluetoothConnectPermission
+ @RequiresPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
+ public void reportBluetoothOff(int uid, int reason, @NonNull String packageName) {
+ try {
+ mBatteryStats.noteBluetoothOff(uid, reason, packageName);
+ } catch (RemoteException e) {
+ e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Indicates that a new Bluetooth LE scan has started.
*
* @param ws worksource (to be used for battery blaming).
diff --git a/core/java/android/os/VibrationAttributes.java b/core/java/android/os/VibrationAttributes.java
index 49c052097492..d223a19b4348 100644
--- a/core/java/android/os/VibrationAttributes.java
+++ b/core/java/android/os/VibrationAttributes.java
@@ -106,20 +106,28 @@ public final class VibrationAttributes implements Parcelable {
public static final int USAGE_NOTIFICATION = 0x30 | USAGE_CLASS_ALARM;
/**
* Usage value to use for vibrations which mean a request to enter/end a
- * communication, such as a VoIP communication or video-conference.
+ * communication with the user, such as a voice prompt.
*/
public static final int USAGE_COMMUNICATION_REQUEST = 0x40 | USAGE_CLASS_ALARM;
/**
* Usage value to use for touch vibrations.
+ *
+ * <p>Most typical haptic feedback should be classed as <em>touch</em> feedback. Examples
+ * include vibrations for tap, long press, drag and scroll.
*/
public static final int USAGE_TOUCH = 0x10 | USAGE_CLASS_FEEDBACK;
/**
- * Usage value to use for vibrations which emulate physical effects, such as edge squeeze.
+ * Usage value to use for vibrations which emulate physical hardware reactions,
+ * such as edge squeeze.
+ *
+ * <p>Note that normal screen-touch feedback "click" effects would typically be
+ * classed as {@link #USAGE_TOUCH}, and that on-screen "physical" animations
+ * like bouncing would be {@link #USAGE_MEDIA}.
*/
public static final int USAGE_PHYSICAL_EMULATION = 0x20 | USAGE_CLASS_FEEDBACK;
/**
- * Usage value to use for vibrations which provide a feedback for hardware interaction,
- * such as a fingerprint sensor.
+ * Usage value to use for vibrations which provide a feedback for hardware
+ * component interaction, such as a fingerprint sensor.
*/
public static final int USAGE_HARDWARE_FEEDBACK = 0x30 | USAGE_CLASS_FEEDBACK;
/**
@@ -183,7 +191,6 @@ public final class VibrationAttributes implements Parcelable {
/**
* Return the vibration usage class.
- * @return USAGE_CLASS_ALARM, USAGE_CLASS_FEEDBACK or USAGE_CLASS_UNKNOWN
*/
@UsageClass
public int getUsageClass() {
@@ -192,7 +199,6 @@ public final class VibrationAttributes implements Parcelable {
/**
* Return the vibration usage.
- * @return one of the values that can be set in {@link Builder#setUsage(int)}
*/
@Usage
public int getUsage() {
@@ -429,16 +435,8 @@ public final class VibrationAttributes implements Parcelable {
}
/**
- * Sets the attribute describing the type of corresponding vibration.
- * @param usage one of {@link VibrationAttributes#USAGE_ALARM},
- * {@link VibrationAttributes#USAGE_RINGTONE},
- * {@link VibrationAttributes#USAGE_NOTIFICATION},
- * {@link VibrationAttributes#USAGE_COMMUNICATION_REQUEST},
- * {@link VibrationAttributes#USAGE_TOUCH},
- * {@link VibrationAttributes#USAGE_PHYSICAL_EMULATION},
- * {@link VibrationAttributes#USAGE_HARDWARE_FEEDBACK}.
- * {@link VibrationAttributes#USAGE_ACCESSIBILITY}.
- * {@link VibrationAttributes#USAGE_MEDIA}.
+ * Sets the attribute describing the type of the corresponding vibration.
+ * @param usage The type of usage for the vibration
* @return the same Builder instance.
*/
public @NonNull Builder setUsage(@Usage int usage) {
diff --git a/core/java/android/os/VibrationEffect.java b/core/java/android/os/VibrationEffect.java
index f490587ae1e1..9598410d8f33 100644
--- a/core/java/android/os/VibrationEffect.java
+++ b/core/java/android/os/VibrationEffect.java
@@ -194,27 +194,27 @@ public abstract class VibrationEffect implements Parcelable {
}
/**
- * Create a waveform vibration.
+ * Create a waveform vibration, using only off/on transitions at the provided time intervals,
+ * and potentially repeating.
*
- * <p>Waveform vibrations are a potentially repeating series of timing and amplitude pairs. For
- * each pair, the value in the amplitude array determines the strength of the vibration and the
- * value in the timing array determines how long it vibrates for. An amplitude of 0 implies no
- * vibration (i.e. off), and any pairs with a timing value of 0 will be ignored.
+ * <p>In effect, the timings array represents the number of milliseconds <em>before</em> turning
+ * the vibrator on, followed by the number of milliseconds to keep the vibrator on, then
+ * the number of milliseconds turned off, and so on. Consequently, the first timing value will
+ * often be 0, so that the effect will start vibrating immediately.
*
- * <p>The amplitude array of the generated waveform will be the same size as the given
- * timing array with alternating values of 0 (i.e. off) and {@link #DEFAULT_AMPLITUDE},
- * starting with 0. Therefore the first timing value will be the period to wait before turning
- * the vibrator on, the second value will be how long to vibrate at {@link #DEFAULT_AMPLITUDE}
- * strength, etc.
+ * <p>This method is equivalent to calling {@link #createWaveform(long[], int[], int)} with
+ * corresponding amplitude values alternating between 0 and {@link #DEFAULT_AMPLITUDE},
+ * beginning with 0.
*
* <p>To cause the pattern to repeat, pass the index into the timings array at which to start
* the repetition, or -1 to disable repeating. Repeating effects will be played indefinitely
* and should be cancelled via {@link Vibrator#cancel()}.
*
- * @param timings The pattern of alternating on-off timings, starting with off. Timing values
- * of 0 will cause the timing / amplitude pair to be ignored.
- * @param repeat The index into the timings array at which to repeat, or -1 if you you don't
- * want to repeat.
+ * @param timings The pattern of alternating on-off timings, starting with an 'off' timing, and
+ * representing the length of time to sustain the individual item (not
+ * cumulative).
+ * @param repeat The index into the timings array at which to repeat, or -1 if you don't
+ * want to repeat indefinitely.
*
* @return The desired effect.
*/
@@ -229,11 +229,10 @@ public abstract class VibrationEffect implements Parcelable {
/**
* Create a waveform vibration.
*
- * <p>Waveform vibrations are a potentially repeating series of timing and amplitude pairs. For
- * each pair, the value in the amplitude array determines the strength of the vibration and the
- * value in the timing array determines how long it vibrates for, in milliseconds. Amplitude
- * values must be between 0 and 255, and an amplitude of 0 implies no vibration (i.e. off). Any
- * pairs with a timing value of 0 will be ignored.
+ * <p>Waveform vibrations are a potentially repeating series of timing and amplitude pairs,
+ * provided in separate arrays. For each pair, the value in the amplitude array determines
+ * the strength of the vibration and the value in the timing array determines how long it
+ * vibrates for, in milliseconds.
*
* <p>To cause the pattern to repeat, pass the index into the timings array at which to start
* the repetition, or -1 to disable repeating. Repeating effects will be played indefinitely
@@ -244,8 +243,8 @@ public abstract class VibrationEffect implements Parcelable {
* @param amplitudes The amplitude values of the timing / amplitude pairs. Amplitude values
* must be between 0 and 255, or equal to {@link #DEFAULT_AMPLITUDE}. An
* amplitude value of 0 implies the motor is off.
- * @param repeat The index into the timings array at which to repeat, or -1 if you you don't
- * want to repeat.
+ * @param repeat The index into the timings array at which to repeat, or -1 if you don't
+ * want to repeat indefinitely.
*
* @return The desired effect.
*/
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index 23baa5d70c66..8f5086021530 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -98,7 +98,8 @@ public abstract class Vibrator {
/**
* Vibration effect support: unsupported
*
- * This effect is <b>not</b> supported by the underlying hardware.
+ * This effect is <b>not</b> natively supported by the underlying hardware, although
+ * the system may still play a fallback vibration.
*/
public static final int VIBRATION_EFFECT_SUPPORT_NO = 2;
@@ -485,20 +486,25 @@ public abstract class Vibrator {
String reason, @NonNull VibrationAttributes attributes);
/**
- * Query whether the vibrator supports the given effects.
+ * Query whether the vibrator natively supports the given effects.
*
- * Not all hardware reports its effect capabilities, so the system may not necessarily know
- * whether an effect is supported or not.
+ * <p>If an effect is not supported, the system may still automatically fall back to playing
+ * a simpler vibration instead, which is not optimised for the specific device. This includes
+ * the unknown case, which can't be determined in advance, that will dynamically attempt to
+ * fall back if the optimised effect fails to play.
*
- * The returned array will be the same length as the query array and the value at a given index
- * will contain {@link #VIBRATION_EFFECT_SUPPORT_YES} if the effect at that same index in the
- * querying array is supported, {@link #VIBRATION_EFFECT_SUPPORT_NO} if it isn't supported, or
- * {@link #VIBRATION_EFFECT_SUPPORT_UNKNOWN} if the system can't determine whether it's
- * supported or not.
+ * <p>The returned array will be the same length as the query array and the value at a given
+ * index will contain {@link #VIBRATION_EFFECT_SUPPORT_YES} if the effect at that same index
+ * in the querying array is supported, {@link #VIBRATION_EFFECT_SUPPORT_NO} if it isn't
+ * supported, or {@link #VIBRATION_EFFECT_SUPPORT_UNKNOWN} if the system can't determine whether
+ * it's supported or not, as some hardware doesn't report its effect capabilities.
+ *
+ * <p>Use {@link #areAllEffectsSupported(int...)} to get a single combined result,
+ * or for convenience when querying exactly one effect.
*
* @param effectIds Which effects to query for.
* @return An array containing the systems current knowledge about whether the given effects
- * are supported or not.
+ * are natively supported by the device, or not.
*/
@NonNull
@VibrationEffectSupport
@@ -515,23 +521,27 @@ public abstract class Vibrator {
/**
* Query whether the vibrator supports all of the given effects.
*
- * Not all hardware reports its effect capabilities, so the system may not necessarily know
- * whether an effect is supported or not.
+ * <p>If an effect is not supported, the system may still automatically fall back to a simpler
+ * vibration instead, which is not optimised for the specific device, however vibration isn't
+ * guaranteed in this case.
*
- * If the result is {@link #VIBRATION_EFFECT_SUPPORT_YES}, all effects in the query are
+ * <p>If the result is {@link #VIBRATION_EFFECT_SUPPORT_YES}, all effects in the query are
* supported by the hardware.
*
- * If the result is {@link #VIBRATION_EFFECT_SUPPORT_NO}, at least one of the effects in the
- * query is not supported.
+ * <p>If the result is {@link #VIBRATION_EFFECT_SUPPORT_NO}, at least one of the effects in the
+ * query is not supported, and using them may fall back to an un-optimized vibration or no
+ * vibration.
*
- * If the result is {@link #VIBRATION_EFFECT_SUPPORT_UNKNOWN}, the system doesn't know whether
- * all of the effects are supported. It may support any or all of the queried effects,
+ * <p>If the result is {@link #VIBRATION_EFFECT_SUPPORT_UNKNOWN}, the system doesn't know
+ * whether all of the effects are supported. It may support any or all of the queried effects,
* but there's no way to programmatically know whether a {@link #vibrate} call will successfully
* cause a vibration. It's guaranteed, however, that none of the queried effects are
* definitively unsupported by the hardware.
*
+ * <p>Use {@link #areEffectsSupported(int...)} to get individual results for each effect.
+ *
* @param effectIds Which effects to query for.
- * @return Whether all of the effects are supported.
+ * @return Whether all of the effects are natively supported by the device.
*/
@VibrationEffectSupport
public final int areAllEffectsSupported(
@@ -555,6 +565,12 @@ public abstract class Vibrator {
* will contain whether the effect at that same index in the querying array is supported or
* not.
*
+ * <p>If a primitive is not supported by the device, then <em>no vibration</em> will occur if
+ * it is played.
+ *
+ * <p>Use {@link #areAllPrimitivesSupported(int...)} to get a single combined result,
+ * or for convenience when querying exactly one primitive.
+ *
* @param primitiveIds Which primitives to query for.
* @return Whether the primitives are supported.
*/
@@ -572,8 +588,13 @@ public abstract class Vibrator {
/**
* Query whether the vibrator supports all of the given primitives.
*
+ * <p>If a primitive is not supported by the device, then <em>no vibration</em> will occur if
+ * it is played.
+ *
+ * <p>Use {@link #arePrimitivesSupported(int...)} to get individual results for each primitive.
+ *
* @param primitiveIds Which primitives to query for.
- * @return Whether primitives effects are supported.
+ * @return Whether all specified primitives are supported.
*/
public final boolean areAllPrimitivesSupported(
@NonNull @VibrationEffect.Composition.PrimitiveType int... primitiveIds) {
diff --git a/core/java/android/service/autofill/AutofillService.java b/core/java/android/service/autofill/AutofillService.java
index 29c7796d8660..cb1b5d3d20b8 100644
--- a/core/java/android/service/autofill/AutofillService.java
+++ b/core/java/android/service/autofill/AutofillService.java
@@ -578,6 +578,14 @@ public abstract class AutofillService extends Service {
public static final String SERVICE_META_DATA = "android.autofill";
/**
+ * Name of the {@link FillResponse} extra used to return a delayed fill response.
+ *
+ * <p>Please see {@link FillRequest#getDelayedFillIntentSender()} on how to send a delayed
+ * fill response to framework.</p>
+ */
+ public static final String EXTRA_FILL_RESPONSE = "android.service.autofill.extra.FILL_RESPONSE";
+
+ /**
* Name of the {@link IResultReceiver} extra used to return the primary result of a request.
*
* @hide
diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java
index f820f0389f0d..e4d3732361ed 100644
--- a/core/java/android/service/autofill/FillRequest.java
+++ b/core/java/android/service/autofill/FillRequest.java
@@ -19,6 +19,7 @@ package android.service.autofill;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.IntentSender;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -160,6 +161,19 @@ public final class FillRequest implements Parcelable {
*/
private final @Nullable InlineSuggestionsRequest mInlineSuggestionsRequest;
+ /**
+ * Gets the {@link IntentSender} to send a delayed fill response.
+ *
+ * <p>The autofill service must first indicate that it wants to return a delayed
+ * {@link FillResponse} by setting {@link FillResponse#FLAG_DELAY_FILL} in a successful
+ * fill response. Then it can use this IntentSender to send an Intent with extra
+ * {@link AutofillService#EXTRA_FILL_RESPONSE} with the delayed response.</p>
+ *
+ * <p>Note that this may be null if a delayed fill response is not supported for
+ * this fill request.</p>
+ */
+ private final @Nullable IntentSender mDelayedFillIntentSender;
+
private void onConstructed() {
Preconditions.checkCollectionElementsNotNull(mFillContexts, "contexts");
}
@@ -252,6 +266,16 @@ public final class FillRequest implements Parcelable {
*
* <p>The Autofill Service must set supportsInlineSuggestions in its XML to enable support
* for inline suggestions.</p>
+ * @param delayedFillIntentSender
+ * Gets the {@link IntentSender} to send a delayed fill response.
+ *
+ * <p>The autofill service must first indicate that it wants to return a delayed
+ * {@link FillResponse} by setting {@link FillResponse#FLAG_DELAY_FILL} in a successful
+ * fill response. Then it can use this IntentSender to send an Intent with extra
+ * {@link AutofillService#EXTRA_FILL_RESPONSE} with the delayed response.</p>
+ *
+ * <p>Note that this may be null if a delayed fill response is not supported for
+ * this fill request.</p>
* @hide
*/
@DataClass.Generated.Member
@@ -260,7 +284,8 @@ public final class FillRequest implements Parcelable {
@NonNull List<FillContext> fillContexts,
@Nullable Bundle clientState,
@RequestFlags int flags,
- @Nullable InlineSuggestionsRequest inlineSuggestionsRequest) {
+ @Nullable InlineSuggestionsRequest inlineSuggestionsRequest,
+ @Nullable IntentSender delayedFillIntentSender) {
this.mId = id;
this.mFillContexts = fillContexts;
com.android.internal.util.AnnotationValidations.validate(
@@ -276,6 +301,7 @@ public final class FillRequest implements Parcelable {
| FLAG_VIEW_NOT_FOCUSED
| FLAG_ACTIVITY_START);
this.mInlineSuggestionsRequest = inlineSuggestionsRequest;
+ this.mDelayedFillIntentSender = delayedFillIntentSender;
onConstructed();
}
@@ -348,6 +374,22 @@ public final class FillRequest implements Parcelable {
return mInlineSuggestionsRequest;
}
+ /**
+ * Gets the {@link IntentSender} to send a delayed fill response.
+ *
+ * <p>The autofill service must first indicate that it wants to return a delayed
+ * {@link FillResponse} by setting {@link FillResponse#FLAG_DELAY_FILL} in a successful
+ * fill response. Then it can use this IntentSender to send an Intent with extra
+ * {@link AutofillService#EXTRA_FILL_RESPONSE} with the delayed response.</p>
+ *
+ * <p>Note that this may be null if a delayed fill response is not supported for
+ * this fill request.</p>
+ */
+ @DataClass.Generated.Member
+ public @Nullable IntentSender getDelayedFillIntentSender() {
+ return mDelayedFillIntentSender;
+ }
+
@Override
@DataClass.Generated.Member
public String toString() {
@@ -359,7 +401,8 @@ public final class FillRequest implements Parcelable {
"fillContexts = " + mFillContexts + ", " +
"clientState = " + mClientState + ", " +
"flags = " + requestFlagsToString(mFlags) + ", " +
- "inlineSuggestionsRequest = " + mInlineSuggestionsRequest +
+ "inlineSuggestionsRequest = " + mInlineSuggestionsRequest + ", " +
+ "delayedFillIntentSender = " + mDelayedFillIntentSender +
" }";
}
@@ -372,12 +415,14 @@ public final class FillRequest implements Parcelable {
byte flg = 0;
if (mClientState != null) flg |= 0x4;
if (mInlineSuggestionsRequest != null) flg |= 0x10;
+ if (mDelayedFillIntentSender != null) flg |= 0x20;
dest.writeByte(flg);
dest.writeInt(mId);
dest.writeParcelableList(mFillContexts, flags);
if (mClientState != null) dest.writeBundle(mClientState);
dest.writeInt(mFlags);
if (mInlineSuggestionsRequest != null) dest.writeTypedObject(mInlineSuggestionsRequest, flags);
+ if (mDelayedFillIntentSender != null) dest.writeTypedObject(mDelayedFillIntentSender, flags);
}
@Override
@@ -398,6 +443,7 @@ public final class FillRequest implements Parcelable {
Bundle clientState = (flg & 0x4) == 0 ? null : in.readBundle();
int flags = in.readInt();
InlineSuggestionsRequest inlineSuggestionsRequest = (flg & 0x10) == 0 ? null : (InlineSuggestionsRequest) in.readTypedObject(InlineSuggestionsRequest.CREATOR);
+ IntentSender delayedFillIntentSender = (flg & 0x20) == 0 ? null : (IntentSender) in.readTypedObject(IntentSender.CREATOR);
this.mId = id;
this.mFillContexts = fillContexts;
@@ -414,6 +460,7 @@ public final class FillRequest implements Parcelable {
| FLAG_VIEW_NOT_FOCUSED
| FLAG_ACTIVITY_START);
this.mInlineSuggestionsRequest = inlineSuggestionsRequest;
+ this.mDelayedFillIntentSender = delayedFillIntentSender;
onConstructed();
}
@@ -433,10 +480,10 @@ public final class FillRequest implements Parcelable {
};
@DataClass.Generated(
- time = 1643052544776L,
+ time = 1643386870464L,
codegenVersion = "1.0.23",
sourceFile = "frameworks/base/core/java/android/service/autofill/FillRequest.java",
- inputSignatures = "public static final @android.service.autofill.FillRequest.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_PASSWORD_INPUT_TYPE\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_VIEW_NOT_FOCUSED\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_ACTIVITY_START\npublic static final int INVALID_REQUEST_ID\nprivate final int mId\nprivate final @android.annotation.NonNull java.util.List<android.service.autofill.FillContext> mFillContexts\nprivate final @android.annotation.Nullable android.os.Bundle mClientState\nprivate final @android.service.autofill.FillRequest.RequestFlags int mFlags\nprivate final @android.annotation.Nullable android.view.inputmethod.InlineSuggestionsRequest mInlineSuggestionsRequest\nprivate void onConstructed()\nclass FillRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstructor=true, genHiddenConstDefs=true)")
+ inputSignatures = "public static final @android.service.autofill.FillRequest.RequestFlags int FLAG_MANUAL_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_COMPATIBILITY_MODE_REQUEST\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_PASSWORD_INPUT_TYPE\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_VIEW_NOT_FOCUSED\npublic static final @android.service.autofill.FillRequest.RequestFlags int FLAG_ACTIVITY_START\npublic static final int INVALID_REQUEST_ID\nprivate final int mId\nprivate final @android.annotation.NonNull java.util.List<android.service.autofill.FillContext> mFillContexts\nprivate final @android.annotation.Nullable android.os.Bundle mClientState\nprivate final @android.service.autofill.FillRequest.RequestFlags int mFlags\nprivate final @android.annotation.Nullable android.view.inputmethod.InlineSuggestionsRequest mInlineSuggestionsRequest\nprivate final @android.annotation.Nullable android.content.IntentSender mDelayedFillIntentSender\nprivate void onConstructed()\nclass FillRequest extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstructor=true, genHiddenConstDefs=true)")
@Deprecated
private void __metadata() {}
diff --git a/core/java/android/service/autofill/FillResponse.java b/core/java/android/service/autofill/FillResponse.java
index 903e77fcb3d7..296877a448ab 100644
--- a/core/java/android/service/autofill/FillResponse.java
+++ b/core/java/android/service/autofill/FillResponse.java
@@ -65,10 +65,22 @@ public final class FillResponse implements Parcelable {
*/
public static final int FLAG_DISABLE_ACTIVITY_ONLY = 0x2;
+ /**
+ * Flag used to request to wait for a delayed fill from the remote Autofill service if it's
+ * passed to {@link Builder#setFlags(int)}.
+ *
+ * <p>Some datasets (i.e. OTP) take time to produce. This flags allows remote service to send
+ * a {@link FillResponse} to the latest {@link FillRequest} via
+ * {@link FillRequest#getDelayedFillIntentSender()} even if the original {@link FillCallback}
+ * has timed out.
+ */
+ public static final int FLAG_DELAY_FILL = 0x4;
+
/** @hide */
@IntDef(flag = true, prefix = { "FLAG_" }, value = {
FLAG_TRACK_CONTEXT_COMMITED,
- FLAG_DISABLE_ACTIVITY_ONLY
+ FLAG_DISABLE_ACTIVITY_ONLY,
+ FLAG_DELAY_FILL
})
@Retention(RetentionPolicy.SOURCE)
@interface FillResponseFlags {}
@@ -657,7 +669,7 @@ public final class FillResponse implements Parcelable {
public Builder setFlags(@FillResponseFlags int flags) {
throwIfDestroyed();
mFlags = Preconditions.checkFlagsArgument(flags,
- FLAG_TRACK_CONTEXT_COMMITED | FLAG_DISABLE_ACTIVITY_ONLY);
+ FLAG_TRACK_CONTEXT_COMMITED | FLAG_DISABLE_ACTIVITY_ONLY | FLAG_DELAY_FILL);
return this;
}
diff --git a/core/java/android/service/trust/TrustAgentService.java b/core/java/android/service/trust/TrustAgentService.java
index fba61cfd801e..5bd423599f5d 100644
--- a/core/java/android/service/trust/TrustAgentService.java
+++ b/core/java/android/service/trust/TrustAgentService.java
@@ -21,6 +21,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.app.Service;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
@@ -310,9 +311,10 @@ public class TrustAgentService extends Service {
*
* @see #FLAG_GRANT_TRUST_TEMPORARY_AND_RENEWABLE
*
- * TODO(b/213631672): Add CTS tests
+ * TODO(b/213631672): Remove @hide and @TestApi
* @hide
*/
+ @TestApi
public void onUserRequestedUnlock() {
}
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index f2a03558663e..c91851a8896d 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -905,11 +905,12 @@ public abstract class WallpaperService extends Service {
if (!ENABLE_WALLPAPER_DIMMING || mBbqSurfaceControl == null) {
return;
}
+
+ SurfaceControl.Transaction surfaceControlTransaction = new SurfaceControl.Transaction();
// TODO: apply the dimming to preview as well once surface transparency works in
// preview mode.
if (!isPreview() && mShouldDim) {
Log.v(TAG, "Setting wallpaper dimming: " + mWallpaperDimAmount);
- SurfaceControl.Transaction surfaceControl = new SurfaceControl.Transaction();
// Animate dimming to gradually change the wallpaper alpha from the previous
// dim amount to the new amount only if the dim amount changed.
@@ -919,16 +920,15 @@ public abstract class WallpaperService extends Service {
? 0 : DIMMING_ANIMATION_DURATION_MS);
animator.addUpdateListener((ValueAnimator va) -> {
final float dimValue = (float) va.getAnimatedValue();
- surfaceControl
- .setAlpha(mBbqSurfaceControl, 1 - dimValue)
- .apply();
+ if (mBbqSurfaceControl != null) {
+ surfaceControlTransaction
+ .setAlpha(mBbqSurfaceControl, 1 - dimValue).apply();
+ }
});
animator.start();
} else {
Log.v(TAG, "Setting wallpaper dimming: " + 0);
- new SurfaceControl.Transaction()
- .setAlpha(mBbqSurfaceControl, 1.0f)
- .apply();
+ surfaceControlTransaction.setAlpha(mBbqSurfaceControl, 1.0f).apply();
}
}
diff --git a/core/java/android/util/IconDrawableFactory.java b/core/java/android/util/IconDrawableFactory.java
index b5e8dd7ed0af..5bb263a1f463 100644
--- a/core/java/android/util/IconDrawableFactory.java
+++ b/core/java/android/util/IconDrawableFactory.java
@@ -15,7 +15,12 @@
*/
package android.util;
+import static android.app.admin.DevicePolicyResources.Drawables.Style.SOLID_COLORED;
+import static android.app.admin.DevicePolicyResources.Drawables.UNDEFINED;
+import static android.app.admin.DevicePolicyResources.Drawables.WORK_PROFILE_ICON_BADGE;
+
import android.annotation.UserIdInt;
+import android.app.admin.DevicePolicyManager;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.pm.ApplicationInfo;
@@ -37,6 +42,7 @@ public class IconDrawableFactory {
protected final Context mContext;
protected final PackageManager mPm;
protected final UserManager mUm;
+ protected final DevicePolicyManager mDpm;
protected final LauncherIcons mLauncherIcons;
protected final boolean mEmbedShadow;
@@ -44,6 +50,7 @@ public class IconDrawableFactory {
mContext = context;
mPm = context.getPackageManager();
mUm = context.getSystemService(UserManager.class);
+ mDpm = context.getSystemService(DevicePolicyManager.class);
mLauncherIcons = new LauncherIcons(context);
mEmbedShadow = embedShadow;
}
@@ -73,18 +80,32 @@ public class IconDrawableFactory {
if (appInfo.isInstantApp()) {
int badgeColor = Resources.getSystem().getColor(
com.android.internal.R.color.instant_app_badge, null);
+ Drawable badge = mContext.getDrawable(
+ com.android.internal.R.drawable.ic_instant_icon_badge_bolt);
icon = mLauncherIcons.getBadgedDrawable(icon,
- com.android.internal.R.drawable.ic_instant_icon_badge_bolt,
+ badge,
badgeColor);
}
if (mUm.hasBadge(userId)) {
- icon = mLauncherIcons.getBadgedDrawable(icon,
- mUm.getUserIconBadgeResId(userId),
- mUm.getUserBadgeColor(userId));
+
+ Drawable badge = mDpm.getDrawable(
+ getUpdatableUserIconBadgeId(userId),
+ SOLID_COLORED,
+ () -> getDefaultUserIconBadge(userId));
+
+ icon = mLauncherIcons.getBadgedDrawable(icon, badge, mUm.getUserBadgeColor(userId));
}
return icon;
}
+ private String getUpdatableUserIconBadgeId(int userId) {
+ return mUm.isManagedProfile(userId) ? WORK_PROFILE_ICON_BADGE : UNDEFINED;
+ }
+
+ private Drawable getDefaultUserIconBadge(int userId) {
+ return mContext.getResources().getDrawable(mUm.getUserIconBadgeResId(userId));
+ }
+
/**
* Add shadow to the icon if {@link AdaptiveIconDrawable}
*/
diff --git a/core/java/android/util/LauncherIcons.java b/core/java/android/util/LauncherIcons.java
index e652e17bceb3..355b2e9934fd 100644
--- a/core/java/android/util/LauncherIcons.java
+++ b/core/java/android/util/LauncherIcons.java
@@ -45,10 +45,12 @@ public final class LauncherIcons {
private final SparseArray<Bitmap> mShadowCache = new SparseArray<>();
private final int mIconSize;
private final Resources mRes;
+ private final Context mContext;
public LauncherIcons(Context context) {
mRes = context.getResources();
mIconSize = mRes.getDimensionPixelSize(android.R.dimen.app_icon_size);
+ mContext = context;
}
public Drawable wrapIconDrawableWithShadow(Drawable drawable) {
@@ -98,14 +100,14 @@ public final class LauncherIcons {
return shadow;
}
- public Drawable getBadgeDrawable(int foregroundRes, int backgroundColor) {
- return getBadgedDrawable(null, foregroundRes, backgroundColor);
+ public Drawable getBadgeDrawable(Drawable badgeForeground, int backgroundColor) {
+ return getBadgedDrawable(null, badgeForeground, backgroundColor);
}
- public Drawable getBadgedDrawable(Drawable base, int foregroundRes, int backgroundColor) {
+ public Drawable getBadgedDrawable(
+ Drawable base, Drawable badgeForeground, int backgroundColor) {
Resources overlayableRes =
ActivityThread.currentActivityThread().getApplication().getResources();
-
// ic_corp_icon_badge_shadow is not work-profile-specific.
Drawable badgeShadow = overlayableRes.getDrawable(
com.android.internal.R.drawable.ic_corp_icon_badge_shadow);
@@ -115,7 +117,6 @@ public final class LauncherIcons {
com.android.internal.R.drawable.ic_corp_icon_badge_color)
.getConstantState().newDrawable().mutate();
- Drawable badgeForeground = overlayableRes.getDrawable(foregroundRes);
badgeForeground.setTint(backgroundColor);
Drawable[] drawables = base == null
diff --git a/core/java/android/view/IDisplayWindowListener.aidl b/core/java/android/view/IDisplayWindowListener.aidl
index 449e9b325904..67ae7430e0b7 100644
--- a/core/java/android/view/IDisplayWindowListener.aidl
+++ b/core/java/android/view/IDisplayWindowListener.aidl
@@ -63,5 +63,5 @@ oneway interface IDisplayWindowListener {
/**
* Called when the keep clear ares on a display have changed.
*/
- void onKeepClearAreasChanged(int displayId, in List<Rect> keepClearAreas);
+ void onKeepClearAreasChanged(int displayId, in List<Rect> restricted, in List<Rect> unrestricted);
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index 955269160e49..2134d819943e 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -291,6 +291,8 @@ public abstract class ContentCaptureSession implements AutoCloseable {
* <p>Typically used to change the context associated with the default session from an activity.
*/
public final void setContentCaptureContext(@Nullable ContentCaptureContext context) {
+ if (!isContentCaptureEnabled()) return;
+
mClientContext = context;
updateContentCaptureContext(context);
}
diff --git a/core/java/android/view/inputmethod/InputMethod.java b/core/java/android/view/inputmethod/InputMethod.java
index ff6903e814b7..08cc31c8534f 100644
--- a/core/java/android/view/inputmethod/InputMethod.java
+++ b/core/java/android/view/inputmethod/InputMethod.java
@@ -105,12 +105,14 @@ public interface InputMethod {
* current IME.
* @param configChanges {@link InputMethodInfo#getConfigChanges()} declared by IME.
* @param stylusHwSupported {@link InputMethodInfo#supportsStylusHandwriting()} declared by IME.
+ * @param shouldShowImeSwitcherWhenImeIsShown {@code true} If the IME switcher is expected to be
+ * shown while the IME is shown.
* @hide
*/
@MainThread
default void initializeInternal(IBinder token,
IInputMethodPrivilegedOperations privilegedOperations, int configChanges,
- boolean stylusHwSupported) {
+ boolean stylusHwSupported, boolean shouldShowImeSwitcherWhenImeIsShown) {
attachToken(token);
}
@@ -229,6 +231,8 @@ public interface InputMethod {
* the next {@link #startInput(InputConnection, EditorInfo, IBinder)} as
* long as your implementation of {@link InputMethod} relies on such
* IPCs
+ * @param shouldShowImeSwitcherWhenImeIsShown {@code true} If the IME switcher is expected to be
+ * shown while the IME is shown.
* @see #startInput(InputConnection, EditorInfo)
* @see #restartInput(InputConnection, EditorInfo)
* @see EditorInfo
@@ -237,7 +241,7 @@ public interface InputMethod {
@MainThread
default void dispatchStartInputWithToken(@Nullable InputConnection inputConnection,
@NonNull EditorInfo editorInfo, boolean restarting,
- @NonNull IBinder startInputToken) {
+ @NonNull IBinder startInputToken, boolean shouldShowImeSwitcherWhenImeIsShown) {
if (restarting) {
restartInput(inputConnection, editorInfo);
} else {
@@ -246,6 +250,18 @@ public interface InputMethod {
}
/**
+ * Notifies that whether the IME should show the IME switcher or not is being changed.
+ *
+ * @param shouldShowImeSwitcherWhenImeIsShown {@code true} If the IME switcher is expected to be
+ * shown while the IME is shown.
+ * @hide
+ */
+ @MainThread
+ default void onShouldShowImeSwitcherWhenImeIsShownChanged(
+ boolean shouldShowImeSwitcherWhenImeIsShown) {
+ }
+
+ /**
* Create a new {@link InputMethodSession} that can be handed to client
* applications for interacting with the input method. You can later
* use {@link #revokeSession(InputMethodSession)} to destroy the session
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index c6f64f4ad633..b00a3829f468 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -301,6 +301,13 @@ public class RemoteViews implements Parcelable, Filter {
public static final int FLAG_USE_LIGHT_BACKGROUND_LAYOUT = 4;
/**
+ * This mask determines which flags are propagated to nested RemoteViews (either added by
+ * addView, or set as portrait/landscape/sized RemoteViews).
+ */
+ static final int FLAG_MASK_TO_PROPAGATE =
+ FLAG_WIDGET_IS_COLLECTION_CHILD | FLAG_USE_LIGHT_BACKGROUND_LAYOUT;
+
+ /**
* A ReadWriteHelper which has the same behavior as ReadWriteHelper.DEFAULT, but which is
* intentionally a different instance in order to trick Bundle reader so that it doesn't allow
* lazy initialization.
@@ -467,6 +474,18 @@ public class RemoteViews implements Parcelable, Filter {
*/
public void addFlags(@ApplyFlags int flags) {
mApplyFlags = mApplyFlags | flags;
+
+ int flagsToPropagate = flags & FLAG_MASK_TO_PROPAGATE;
+ if (flagsToPropagate != 0) {
+ if (hasSizedRemoteViews()) {
+ for (RemoteViews remoteView : mSizedRemoteViews) {
+ remoteView.addFlags(flagsToPropagate);
+ }
+ } else if (hasLandscapeAndPortraitLayouts()) {
+ mLandscape.addFlags(flagsToPropagate);
+ mPortrait.addFlags(flagsToPropagate);
+ }
+ }
}
/**
@@ -2407,6 +2426,10 @@ public class RemoteViews implements Parcelable, Filter {
// will return -1.
final int nextChild = getNextRecyclableChild(target);
RemoteViews rvToApply = mNestedViews.getRemoteViewsToApply(context);
+
+ int flagsToPropagate = mApplyFlags & FLAG_MASK_TO_PROPAGATE;
+ if (flagsToPropagate != 0) rvToApply.addFlags(flagsToPropagate);
+
if (nextChild >= 0 && mStableId != NO_ID) {
// At that point, the views starting at index nextChild are the ones recyclable but
// not yet recycled. All views added on that round of application are placed before.
@@ -2419,8 +2442,8 @@ public class RemoteViews implements Parcelable, Filter {
target.removeViews(nextChild, recycledViewIndex - nextChild);
}
setNextRecyclableChild(target, nextChild + 1, target.getChildCount());
- rvToApply.reapply(context, child, handler, null /* size */, colorResources,
- false /* topLevel */);
+ rvToApply.reapplyNestedViews(context, child, rootParent, handler,
+ null /* size */, colorResources);
return;
}
// If we cannot recycle the views, we still remove all views in between to
@@ -2431,8 +2454,8 @@ public class RemoteViews implements Parcelable, Filter {
// If we cannot recycle, insert the new view before the next recyclable child.
// Inflate nested views and add as children
- View nestedView = rvToApply.apply(context, target, handler, null /* size */,
- colorResources);
+ View nestedView = rvToApply.applyNestedViews(context, target, rootParent, handler,
+ null /* size */, colorResources);
if (mStableId != NO_ID) {
setStableId(nestedView, mStableId);
}
@@ -3780,7 +3803,7 @@ public class RemoteViews implements Parcelable, Filter {
* @param parcel
*/
public RemoteViews(Parcel parcel) {
- this(parcel, /* rootParent= */ null, /* info= */ null, /* depth= */ 0);
+ this(parcel, /* rootData= */ null, /* info= */ null, /* depth= */ 0);
}
private RemoteViews(@NonNull Parcel parcel, @Nullable HierarchyRootData rootData,
@@ -5580,6 +5603,16 @@ public class RemoteViews implements Parcelable, Filter {
return result;
}
+ private View applyNestedViews(Context context, ViewGroup directParent,
+ ViewGroup rootParent, InteractionHandler handler, SizeF size,
+ ColorResources colorResources) {
+ RemoteViews rvToApply = getRemoteViewsToApply(context, size);
+
+ View result = inflateView(context, rvToApply, directParent, 0, colorResources);
+ rvToApply.performApply(result, rootParent, handler, colorResources);
+ return result;
+ }
+
private View inflateView(Context context, RemoteViews rv, ViewGroup parent) {
return inflateView(context, rv, parent, 0, null);
}
@@ -5895,6 +5928,12 @@ public class RemoteViews implements Parcelable, Filter {
}
}
+ private void reapplyNestedViews(Context context, View v, ViewGroup rootParent,
+ InteractionHandler handler, SizeF size, ColorResources colorResources) {
+ RemoteViews rvToApply = getRemoteViewsToReapply(context, v, size);
+ rvToApply.performApply(v, rootParent, handler, colorResources);
+ }
+
/**
* Applies all the actions to the provided view, moving as much of the task on the background
* thread as possible.
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 41c540116928..7c939aca09cf 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4461,7 +4461,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* pixel" units. This size is adjusted based on the current density and
* user font size preference.
*
- * <p>Note: if this TextView has the auto-size feature enabled than this function is no-op.
+ * <p>Note: if this TextView has the auto-size feature enabled, then this function is no-op.
*
* @param size The scaled pixel size.
*
@@ -4476,7 +4476,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
* Set the default text size to a given unit and value. See {@link
* TypedValue} for the possible dimension units.
*
- * <p>Note: if this TextView has the auto-size feature enabled than this function is no-op.
+ * <p>Note: if this TextView has the auto-size feature enabled, then this function is no-op.
*
* @param unit The desired dimension unit.
* @param size The desired size in the given units.
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 9648008274ef..629a1b36b9e6 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -113,7 +113,7 @@ interface IBatteryStats {
void notePhoneOn();
void notePhoneOff();
void notePhoneSignalStrength(in SignalStrength signalStrength);
- void notePhoneDataConnectionState(int dataType, boolean hasData, int serviceType);
+ void notePhoneDataConnectionState(int dataType, boolean hasData, int serviceType, int nrFrequency);
void notePhoneState(int phoneState);
void noteWifiOn();
void noteWifiOff();
@@ -145,6 +145,8 @@ interface IBatteryStats {
long getAwakeTimeBattery();
long getAwakeTimePlugged();
+ void noteBluetoothOn(int uid, int reason, String packageName);
+ void noteBluetoothOff(int uid, int reason, String packageName);
void noteBleScanStarted(in WorkSource ws, boolean isUnoptimized);
void noteBleScanStopped(in WorkSource ws, boolean isUnoptimized);
void noteBleScanReset();
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 25ee2d0fa019..cbd593207166 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -69,10 +69,14 @@ import android.os.connectivity.GpsBatteryStats;
import android.os.connectivity.WifiActivityEnergyInfo;
import android.os.connectivity.WifiBatteryStats;
import android.provider.Settings;
+import android.telephony.Annotation.NetworkType;
import android.telephony.CellSignalStrength;
+import android.telephony.CellSignalStrengthLte;
+import android.telephony.CellSignalStrengthNr;
import android.telephony.DataConnectionRealTimeInfo;
import android.telephony.ModemActivityInfo;
import android.telephony.ServiceState;
+import android.telephony.ServiceState.RegState;
import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
@@ -935,6 +939,119 @@ public class BatteryStatsImpl extends BatteryStats {
final StopwatchTimer[] mPhoneDataConnectionsTimer =
new StopwatchTimer[NUM_DATA_CONNECTION_TYPES];
+ @RadioAccessTechnology
+ int mActiveRat = RADIO_ACCESS_TECHNOLOGY_OTHER;
+
+ private static class RadioAccessTechnologyBatteryStats {
+ /**
+ * This RAT is currently being used.
+ */
+ private boolean mActive = false;
+ /**
+ * Current active frequency range for this RAT.
+ */
+ @ServiceState.FrequencyRange
+ private int mFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
+ /**
+ * Current signal strength for this RAT.
+ */
+ private int mSignalStrength = CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+ /**
+ * Timers for each combination of frequency range and signal strength.
+ */
+ public final StopwatchTimer[][] perStateTimers;
+
+ RadioAccessTechnologyBatteryStats(int freqCount, Clock clock, TimeBase timeBase) {
+ perStateTimers =
+ new StopwatchTimer[freqCount][CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS];
+ for (int i = 0; i < freqCount; i++) {
+ for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
+ perStateTimers[i][j] = new StopwatchTimer(clock, null, -1, null, timeBase);
+ }
+ }
+ }
+
+ /**
+ * Note this RAT is currently being used.
+ */
+ public void noteActive(boolean active, long elapsedRealtimeMs) {
+ if (mActive == active) return;
+ mActive = active;
+ if (mActive) {
+ perStateTimers[mFrequencyRange][mSignalStrength].startRunningLocked(
+ elapsedRealtimeMs);
+ } else {
+ perStateTimers[mFrequencyRange][mSignalStrength].stopRunningLocked(
+ elapsedRealtimeMs);
+ }
+ }
+
+ /**
+ * Note current frequency range has changed.
+ */
+ public void noteFrequencyRange(@ServiceState.FrequencyRange int frequencyRange,
+ long elapsedRealtimeMs) {
+ if (mFrequencyRange == frequencyRange) return;
+
+ if (!mActive) {
+ // RAT not in use, note the frequency change and move on.
+ mFrequencyRange = frequencyRange;
+ return;
+ }
+ perStateTimers[mFrequencyRange][mSignalStrength].stopRunningLocked(elapsedRealtimeMs);
+ perStateTimers[frequencyRange][mSignalStrength].startRunningLocked(elapsedRealtimeMs);
+ mFrequencyRange = frequencyRange;
+ }
+
+ /**
+ * Note current signal strength has changed.
+ */
+ public void noteSignalStrength(int signalStrength, long elapsedRealtimeMs) {
+ if (mSignalStrength == signalStrength) return;
+
+ if (!mActive) {
+ // RAT not in use, note the signal strength change and move on.
+ mSignalStrength = signalStrength;
+ return;
+ }
+ perStateTimers[mFrequencyRange][mSignalStrength].stopRunningLocked(elapsedRealtimeMs);
+ perStateTimers[mFrequencyRange][signalStrength].startRunningLocked(elapsedRealtimeMs);
+ mSignalStrength = signalStrength;
+ }
+
+ /**
+ * Reset display timers.
+ */
+ public void reset(long elapsedRealtimeUs) {
+ final int size = perStateTimers.length;
+ for (int i = 0; i < size; i++) {
+ for (int j = 0; j < CellSignalStrength.NUM_SIGNAL_STRENGTH_BINS; j++) {
+ perStateTimers[i][j].reset(false, elapsedRealtimeUs);
+ }
+ }
+ }
+ }
+
+ /**
+ * Number of frequency ranges, keep in sync with {@link ServiceState.FrequencyRange}
+ */
+ private static final int NR_FREQUENCY_COUNT = 5;
+
+ RadioAccessTechnologyBatteryStats[] mPerRatBatteryStats =
+ new RadioAccessTechnologyBatteryStats[RADIO_ACCESS_TECHNOLOGY_COUNT];
+
+ @GuardedBy("this")
+ private RadioAccessTechnologyBatteryStats getRatBatteryStatsLocked(
+ @RadioAccessTechnology int rat) {
+ RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
+ if (stats == null) {
+ final int freqCount = rat == RADIO_ACCESS_TECHNOLOGY_NR ? NR_FREQUENCY_COUNT : 1;
+ stats = new RadioAccessTechnologyBatteryStats(freqCount, mClock, mOnBatteryTimeBase);
+ mPerRatBatteryStats[rat] = stats;
+ }
+ return stats;
+ }
+
final LongSamplingCounter[] mNetworkByteActivityCounters =
new LongSamplingCounter[NUM_NETWORK_ACTIVITY_TYPES];
@@ -5886,6 +6003,10 @@ public class BatteryStatsImpl extends BatteryStats {
+ Integer.toHexString(mHistoryCur.states));
addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mMobileRadioPowerState = powerState;
+
+ // Inform current RatBatteryStats that the modem active state might have changed.
+ getRatBatteryStatsLocked(mActiveRat).noteActive(active, elapsedRealtimeMs);
+
if (active) {
mMobileRadioActiveTimer.startRunningLocked(elapsedRealtimeMs);
mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtimeMs);
@@ -6307,21 +6428,86 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
public void notePhoneSignalStrengthLocked(SignalStrength signalStrength,
long elapsedRealtimeMs, long uptimeMs) {
- // Bin the strength.
- int bin = signalStrength.getLevel();
- updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, bin,
+ final int overallSignalStrength = signalStrength.getLevel();
+ final SparseIntArray perRatSignalStrength = new SparseIntArray(
+ BatteryStats.RADIO_ACCESS_TECHNOLOGY_COUNT);
+
+ // Extract signal strength level for each RAT.
+ final List<CellSignalStrength> cellSignalStrengths =
+ signalStrength.getCellSignalStrengths();
+ final int size = cellSignalStrengths.size();
+ for (int i = 0; i < size; i++) {
+ CellSignalStrength cellSignalStrength = cellSignalStrengths.get(i);
+ // Map each CellSignalStrength to a BatteryStats.RadioAccessTechnology
+ final int ratType;
+ final int level;
+ if (cellSignalStrength instanceof CellSignalStrengthNr) {
+ ratType = RADIO_ACCESS_TECHNOLOGY_NR;
+ level = cellSignalStrength.getLevel();
+ } else if (cellSignalStrength instanceof CellSignalStrengthLte) {
+ ratType = RADIO_ACCESS_TECHNOLOGY_LTE;
+ level = cellSignalStrength.getLevel();
+ } else {
+ ratType = RADIO_ACCESS_TECHNOLOGY_OTHER;
+ level = cellSignalStrength.getLevel();
+ }
+
+ // According to SignalStrength#getCellSignalStrengths(), multiple of the same
+ // cellSignalStrength can be present. Just take the highest level one for each RAT.
+ if (perRatSignalStrength.get(ratType, -1) < level) {
+ perRatSignalStrength.put(ratType, level);
+ }
+ }
+
+ notePhoneSignalStrengthLocked(overallSignalStrength, perRatSignalStrength,
+ elapsedRealtimeMs, uptimeMs);
+ }
+
+ /**
+ * Note phone signal strength change, including per RAT signal strength.
+ *
+ * @param signalStrength overall signal strength {@see SignalStrength#getLevel()}
+ * @param perRatSignalStrength signal strength of available RATs
+ */
+ @GuardedBy("this")
+ public void notePhoneSignalStrengthLocked(int signalStrength,
+ SparseIntArray perRatSignalStrength) {
+ notePhoneSignalStrengthLocked(signalStrength, perRatSignalStrength,
+ mClock.elapsedRealtime(), mClock.uptimeMillis());
+ }
+
+ /**
+ * Note phone signal strength change, including per RAT signal strength.
+ *
+ * @param signalStrength overall signal strength {@see SignalStrength#getLevel()}
+ * @param perRatSignalStrength signal strength of available RATs
+ */
+ @GuardedBy("this")
+ public void notePhoneSignalStrengthLocked(int signalStrength,
+ SparseIntArray perRatSignalStrength,
+ long elapsedRealtimeMs, long uptimeMs) {
+ // Note each RAT's signal strength.
+ final int size = perRatSignalStrength.size();
+ for (int i = 0; i < size; i++) {
+ final int rat = perRatSignalStrength.keyAt(i);
+ final int ratSignalStrength = perRatSignalStrength.valueAt(i);
+ getRatBatteryStatsLocked(rat).noteSignalStrength(ratSignalStrength, elapsedRealtimeMs);
+ }
+ updateAllPhoneStateLocked(mPhoneServiceStateRaw, mPhoneSimStateRaw, signalStrength,
elapsedRealtimeMs, uptimeMs);
}
@UnsupportedAppUsage
@GuardedBy("this")
- public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType) {
- notePhoneDataConnectionStateLocked(dataType, hasData, serviceType,
+ public void notePhoneDataConnectionStateLocked(@NetworkType int dataType, boolean hasData,
+ @RegState int serviceType, @ServiceState.FrequencyRange int nrFrequency) {
+ notePhoneDataConnectionStateLocked(dataType, hasData, serviceType, nrFrequency,
mClock.elapsedRealtime(), mClock.uptimeMillis());
}
@GuardedBy("this")
- public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType,
+ public void notePhoneDataConnectionStateLocked(@NetworkType int dataType, boolean hasData,
+ @RegState int serviceType, @ServiceState.FrequencyRange int nrFrequency,
long elapsedRealtimeMs, long uptimeMs) {
// BatteryStats uses 0 to represent no network type.
// Telephony does not have a concept of no network type, and uses 0 to represent unknown.
@@ -6344,6 +6530,13 @@ public class BatteryStatsImpl extends BatteryStats {
}
}
}
+
+ final int newRat = mapNetworkTypeToRadioAccessTechnology(bin);
+ if (newRat == RADIO_ACCESS_TECHNOLOGY_NR) {
+ // Note possible frequency change for the NR RAT.
+ getRatBatteryStatsLocked(newRat).noteFrequencyRange(nrFrequency, elapsedRealtimeMs);
+ }
+
if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
if (mPhoneDataConnectionType != bin) {
mHistoryCur.states = (mHistoryCur.states&~HistoryItem.STATE_DATA_CONNECTION_MASK)
@@ -6357,6 +6550,45 @@ public class BatteryStatsImpl extends BatteryStats {
}
mPhoneDataConnectionType = bin;
mPhoneDataConnectionsTimer[bin].startRunningLocked(elapsedRealtimeMs);
+
+ if (mActiveRat != newRat) {
+ getRatBatteryStatsLocked(mActiveRat).noteActive(false, elapsedRealtimeMs);
+ mActiveRat = newRat;
+ }
+ final boolean modemActive = mMobileRadioActiveTimer.isRunningLocked();
+ getRatBatteryStatsLocked(newRat).noteActive(modemActive, elapsedRealtimeMs);
+ }
+ }
+
+ @RadioAccessTechnology
+ private static int mapNetworkTypeToRadioAccessTechnology(@NetworkType int dataType) {
+ switch (dataType) {
+ case TelephonyManager.NETWORK_TYPE_NR:
+ return RADIO_ACCESS_TECHNOLOGY_NR;
+ case TelephonyManager.NETWORK_TYPE_LTE:
+ return RADIO_ACCESS_TECHNOLOGY_LTE;
+ case TelephonyManager.NETWORK_TYPE_UNKNOWN: //fallthrough
+ case TelephonyManager.NETWORK_TYPE_GPRS: //fallthrough
+ case TelephonyManager.NETWORK_TYPE_EDGE: //fallthrough
+ case TelephonyManager.NETWORK_TYPE_UMTS: //fallthrough
+ case TelephonyManager.NETWORK_TYPE_CDMA: //fallthrough
+ case TelephonyManager.NETWORK_TYPE_EVDO_0: //fallthrough
+ case TelephonyManager.NETWORK_TYPE_EVDO_A: //fallthrough
+ case TelephonyManager.NETWORK_TYPE_1xRTT: //fallthrough
+ case TelephonyManager.NETWORK_TYPE_HSDPA: //fallthrough
+ case TelephonyManager.NETWORK_TYPE_HSUPA: //fallthrough
+ case TelephonyManager.NETWORK_TYPE_HSPA: //fallthrough
+ case TelephonyManager.NETWORK_TYPE_IDEN: //fallthrough
+ case TelephonyManager.NETWORK_TYPE_EVDO_B: //fallthrough
+ case TelephonyManager.NETWORK_TYPE_EHRPD: //fallthrough
+ case TelephonyManager.NETWORK_TYPE_HSPAP: //fallthrough
+ case TelephonyManager.NETWORK_TYPE_GSM: //fallthrough
+ case TelephonyManager.NETWORK_TYPE_TD_SCDMA: //fallthrough
+ case TelephonyManager.NETWORK_TYPE_IWLAN: //fallthrough
+ return RADIO_ACCESS_TECHNOLOGY_OTHER;
+ default:
+ Slog.w(TAG, "Unhandled NetworkType (" + dataType + "), mapping to OTHER");
+ return RADIO_ACCESS_TECHNOLOGY_OTHER;
}
}
@@ -7731,6 +7963,23 @@ public class BatteryStatsImpl extends BatteryStats {
return mPhoneDataConnectionsTimer[dataType];
}
+ @Override public long getActiveRadioDurationMs(@RadioAccessTechnology int rat,
+ @ServiceState.FrequencyRange int frequencyRange, int signalStrength,
+ long elapsedRealtimeMs) {
+ final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[rat];
+ if (stats == null) return 0L;
+
+ final int freqCount = stats.perStateTimers.length;
+ if (frequencyRange < 0 || frequencyRange >= freqCount) return 0L;
+
+ final StopwatchTimer[] strengthTimers = stats.perStateTimers[frequencyRange];
+ final int strengthCount = strengthTimers.length;
+ if (signalStrength < 0 || signalStrength >= strengthCount) return 0L;
+
+ return stats.perStateTimers[frequencyRange][signalStrength].getTotalTimeLocked(
+ elapsedRealtimeMs * 1000, STATS_SINCE_CHARGED) / 1000;
+ }
+
@UnsupportedAppUsage
@Override public long getMobileRadioActiveTime(long elapsedRealtimeUs, int which) {
return mMobileRadioActiveTimer.getTotalTimeLocked(elapsedRealtimeUs, which);
@@ -12553,6 +12802,11 @@ public class BatteryStatsImpl extends BatteryStats {
mNetworkByteActivityCounters[i].reset(false, elapsedRealtimeUs);
mNetworkPacketActivityCounters[i].reset(false, elapsedRealtimeUs);
}
+ for (int i = 0; i < RADIO_ACCESS_TECHNOLOGY_COUNT; i++) {
+ final RadioAccessTechnologyBatteryStats stats = mPerRatBatteryStats[i];
+ if (stats == null) continue;
+ stats.reset(elapsedRealtimeUs);
+ }
mMobileRadioActiveTimer.reset(false, elapsedRealtimeUs);
mMobileRadioActivePerAppTimer.reset(false, elapsedRealtimeUs);
mMobileRadioActiveAdjustedTime.reset(false, elapsedRealtimeUs);
@@ -16107,6 +16361,11 @@ public class BatteryStatsImpl extends BatteryStats {
BATTERY_CHARGED_DELAY_MS = delay >= 0 ? delay : mParser.getInt(
KEY_BATTERY_CHARGED_DELAY_MS,
DEFAULT_BATTERY_CHARGED_DELAY_MS);
+
+ if (mHandler.hasCallbacks(mDeferSetCharging)) {
+ mHandler.removeCallbacks(mDeferSetCharging);
+ mHandler.postDelayed(mDeferSetCharging, BATTERY_CHARGED_DELAY_MS);
+ }
}
private void updateKernelUidReadersThrottleTime(long oldTimeMs, long newTimeMs) {
diff --git a/core/java/com/android/internal/os/BinderCallsStats.java b/core/java/com/android/internal/os/BinderCallsStats.java
index be91aaca5d39..0a29fc5285a5 100644
--- a/core/java/com/android/internal/os/BinderCallsStats.java
+++ b/core/java/com/android/internal/os/BinderCallsStats.java
@@ -1159,6 +1159,17 @@ public class BinderCallsStats implements BinderInternal.Observer {
: Integer.compare(a.transactionCode, b.transactionCode);
}
+ /** @hide */
+ public static void startForBluetooth(Context context) {
+ new BinderCallsStats.SettingsObserver(
+ context,
+ new BinderCallsStats(
+ new BinderCallsStats.Injector(),
+ com.android.internal.os.BinderLatencyProto.Dims.BLUETOOTH));
+
+ }
+
+
/**
* Settings observer for other processes (not system_server).
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index a5cf7ce1d37c..23ebc9f94915 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -20,6 +20,7 @@ import android.app.ITransientNotificationCallback;
import android.content.ComponentName;
import android.graphics.drawable.Icon;
import android.graphics.Rect;
+import android.hardware.biometrics.IBiometricContextListener;
import android.hardware.biometrics.IBiometricSysuiReceiver;
import android.hardware.biometrics.PromptInfo;
import android.hardware.fingerprint.IUdfpsHbmListener;
@@ -166,6 +167,8 @@ oneway interface IStatusBar
* Used to hide the authentication dialog, e.g. when the application cancels authentication.
*/
void hideAuthenticationDialog();
+ /* Used to notify the biometric service of events that occur outside of an operation. */
+ void setBiometicContextListener(in IBiometricContextListener listener);
/**
* Sets an instance of IUdfpsHbmListener for UdfpsController.
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index accb98645599..f28325e3cc51 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -20,6 +20,7 @@ import android.app.Notification;
import android.content.ComponentName;
import android.graphics.drawable.Icon;
import android.graphics.Rect;
+import android.hardware.biometrics.IBiometricContextListener;
import android.hardware.biometrics.IBiometricSysuiReceiver;
import android.hardware.biometrics.PromptInfo;
import android.hardware.fingerprint.IUdfpsHbmListener;
@@ -125,6 +126,8 @@ interface IStatusBarService
void onBiometricError(int modality, int error, int vendorCode);
// Used to hide the authentication dialog, e.g. when the application cancels authentication
void hideAuthenticationDialog();
+ // Used to notify the biometric service of events that occur outside of an operation.
+ void setBiometicContextListener(in IBiometricContextListener listener);
/**
* Sets an instance of IUdfpsHbmListener for UdfpsController.
diff --git a/core/java/com/android/internal/util/UserIcons.java b/core/java/com/android/internal/util/UserIcons.java
index bfe43237da58..17b84ffc2f3f 100644
--- a/core/java/com/android/internal/util/UserIcons.java
+++ b/core/java/com/android/internal/util/UserIcons.java
@@ -16,6 +16,7 @@
package com.android.internal.util;
+import android.annotation.ColorInt;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
@@ -72,9 +73,30 @@ public class UserIcons {
// Return colored icon instead
colorResId = USER_ICON_COLORS[userId % USER_ICON_COLORS.length];
}
+ return getDefaultUserIconInColor(resources, resources.getColor(colorResId, null));
+ }
+
+ /**
+ * Returns a default user icon in a particular color.
+ *
+ * @param resources resources object to fetch the user icon
+ * @param color the color used for the icon
+ */
+ public static Drawable getDefaultUserIconInColor(Resources resources, @ColorInt int color) {
Drawable icon = resources.getDrawable(R.drawable.ic_account_circle, null).mutate();
- icon.setColorFilter(resources.getColor(colorResId, null), Mode.SRC_IN);
+ icon.setColorFilter(color, Mode.SRC_IN);
icon.setBounds(0, 0, icon.getIntrinsicWidth(), icon.getIntrinsicHeight());
return icon;
}
+
+ /**
+ * Returns an array containing colors to be used for default user icons.
+ */
+ public static int[] getUserIconColors(Resources resources) {
+ int[] result = new int[USER_ICON_COLORS.length];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = resources.getColor(USER_ICON_COLORS[i], null);
+ }
+ return result;
+ }
}
diff --git a/core/java/com/android/internal/view/IInputMethod.aidl b/core/java/com/android/internal/view/IInputMethod.aidl
index da24832f9d84..d2bc3442ed36 100644
--- a/core/java/com/android/internal/view/IInputMethod.aidl
+++ b/core/java/com/android/internal/view/IInputMethod.aidl
@@ -37,7 +37,8 @@ import com.android.internal.view.InlineSuggestionsRequestInfo;
*/
oneway interface IInputMethod {
void initializeInternal(IBinder token, IInputMethodPrivilegedOperations privOps,
- int configChanges, boolean stylusHwSupported);
+ int configChanges, boolean stylusHwSupported,
+ boolean shouldShowImeSwitcherWhenImeIsShown);
void onCreateInlineSuggestionsRequest(in InlineSuggestionsRequestInfo requestInfo,
in IInlineSuggestionsRequestCallback cb);
@@ -47,7 +48,10 @@ oneway interface IInputMethod {
void unbindInput();
void startInput(in IBinder startInputToken, in IInputContext inputContext,
- in EditorInfo attribute, boolean restarting);
+ in EditorInfo attribute, boolean restarting,
+ boolean shouldShowImeSwitcherWhenImeIsShown);
+
+ void onShouldShowImeSwitcherWhenImeIsShownChanged(boolean shouldShowImeSwitcherWhenImeIsShown);
void createSession(in InputChannel channel, IInputSessionCallback callback);
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 430d84ebb3e1..8bb9a0a0d6ff 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -195,7 +195,6 @@ cc_library_shared {
"android_util_FileObserver.cpp",
"android/opengl/poly_clip.cpp", // TODO: .arm
"android/opengl/util.cpp",
- "android_server_NetworkManagementSocketTagger.cpp",
"android_ddm_DdmHandleNativeHeap.cpp",
"android_backup_BackupDataInput.cpp",
"android_backup_BackupDataOutput.cpp",
@@ -310,6 +309,8 @@ cc_library_shared {
"libdl_android",
"libtimeinstate",
"server_configurable_flags",
+ // TODO: delete when ConnectivityT moves to APEX.
+ "libframework-connectivity-tiramisu-jni",
],
export_shared_lib_headers: [
// our headers include libnativewindow's public headers
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index f4296becf484..cde71cf6b30f 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -164,7 +164,6 @@ extern int register_android_text_AndroidCharacter(JNIEnv *env);
extern int register_android_text_Hyphenator(JNIEnv *env);
extern int register_android_opengl_classes(JNIEnv *env);
extern int register_android_ddm_DdmHandleNativeHeap(JNIEnv *env);
-extern int register_android_server_NetworkManagementSocketTagger(JNIEnv* env);
extern int register_android_backup_BackupDataInput(JNIEnv *env);
extern int register_android_backup_BackupDataOutput(JNIEnv *env);
extern int register_android_backup_FileBackupHelperBase(JNIEnv *env);
@@ -1623,7 +1622,6 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_media_midi),
REG_JNI(register_android_opengl_classes),
- REG_JNI(register_android_server_NetworkManagementSocketTagger),
REG_JNI(register_android_ddm_DdmHandleNativeHeap),
REG_JNI(register_android_backup_BackupDataInput),
REG_JNI(register_android_backup_BackupDataOutput),
diff --git a/core/jni/android/opengl/OWNERS b/core/jni/android/opengl/OWNERS
new file mode 100644
index 000000000000..ce4b9075d59c
--- /dev/null
+++ b/core/jni/android/opengl/OWNERS
@@ -0,0 +1 @@
+file:/graphics/java/android/graphics/OWNERS
diff --git a/core/jni/android/opengl/util.cpp b/core/jni/android/opengl/util.cpp
index 82601baee914..d8522658d747 100644
--- a/core/jni/android/opengl/util.cpp
+++ b/core/jni/android/opengl/util.cpp
@@ -643,6 +643,8 @@ static bool checkInternalFormat(int32_t bitmapFormat, int internalformat, int ty
return (type == GL_UNSIGNED_SHORT_5_6_5 && internalformat == GL_RGB);
case ANDROID_BITMAP_FORMAT_RGBA_F16:
return (type == GL_HALF_FLOAT && internalformat == GL_RGBA16F);
+ case ANDROID_BITMAP_FORMAT_RGBA_1010102:
+ return (type == GL_UNSIGNED_INT_2_10_10_10_REV && internalformat == GL_RGB10_A2);
default:
break;
}
@@ -676,6 +678,8 @@ static int getInternalFormat(int32_t bitmapFormat) {
return GL_RGB;
case ANDROID_BITMAP_FORMAT_RGBA_F16:
return GL_RGBA16F;
+ case ANDROID_BITMAP_FORMAT_RGBA_1010102:
+ return GL_RGB10_A2;
default:
return -1;
}
@@ -693,6 +697,8 @@ static int getType(int32_t bitmapFormat) {
return GL_UNSIGNED_SHORT_5_6_5;
case ANDROID_BITMAP_FORMAT_RGBA_F16:
return GL_HALF_FLOAT;
+ case ANDROID_BITMAP_FORMAT_RGBA_1010102:
+ return GL_UNSIGNED_INT_2_10_10_10_REV;
default:
return -1;
}
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index d039bcff3b26..78b403c39a17 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -133,6 +133,18 @@ nativeClassInit (JNIEnv *_env, jclass _this)
MakeGlobalRefOrDie(_env, _env->CallObjectMethod(empty.get(), stringOffsets.intern));
}
+uint64_t htonll(uint64_t ll) {
+ constexpr uint32_t kBytesToTest = 0x12345678;
+ constexpr uint8_t kFirstByte = (const uint8_t &)kBytesToTest;
+ constexpr bool kIsLittleEndian = kFirstByte == 0x78;
+
+ if constexpr (kIsLittleEndian) {
+ return static_cast<uint64_t>(htonl(ll & 0xffffffff)) << 32 | htonl(ll >> 32);
+ } else {
+ return ll;
+ }
+}
+
static jstring getJavaInternedString(JNIEnv *env, const String8 &string) {
if (string == "") {
return gStringOffsets.emptyString;
@@ -193,7 +205,8 @@ translateNativeSensorToJavaSensor(JNIEnv *env, jobject sensor, const Sensor& nat
int32_t id = nativeSensor.getId();
env->CallVoidMethod(sensor, sensorOffsets.setId, id);
Sensor::uuid_t uuid = nativeSensor.getUuid();
- env->CallVoidMethod(sensor, sensorOffsets.setUuid, id, uuid.i64[0], uuid.i64[1]);
+ env->CallVoidMethod(sensor, sensorOffsets.setUuid, htonll(uuid.i64[0]),
+ htonll(uuid.i64[1]));
}
return sensor;
}
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index e13b78868a2c..edc8c5b99ebe 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -204,6 +204,12 @@ jclass gClsAudioRecordRoutingProxy;
jclass gAudioProfileClass;
jmethodID gAudioProfileCstor;
+static struct {
+ jfieldID mSamplingRates;
+ jfieldID mChannelMasks;
+ jfieldID mChannelIndexMasks;
+ jfieldID mEncapsulationType;
+} gAudioProfileFields;
jclass gVibratorClass;
static struct {
@@ -1288,7 +1294,7 @@ static jint convertAudioProfileFromNative(JNIEnv *env, jobject *jAudioProfile,
audioFormatFromNative(nAudioProfile->format), jSamplingRates.get(),
jChannelMasks.get(), jChannelIndexMasks.get(), encapsulationType);
- if (jAudioProfile == nullptr) {
+ if (*jAudioProfile == nullptr) {
return AUDIO_JAVA_ERROR;
}
@@ -1340,81 +1346,50 @@ static jint convertAudioPortFromNative(JNIEnv *env, jobject *jAudioPort,
jStatus = (jint)AUDIO_JAVA_ERROR;
goto exit;
}
- for (size_t i = 0; i < nAudioPort->num_audio_profiles; ++i) {
- size_t numPositionMasks = 0;
- size_t numIndexMasks = 0;
- // count up how many masks are positional and indexed
- for (size_t index = 0; index < nAudioPort->audio_profiles[i].num_channel_masks; index++) {
- const audio_channel_mask_t mask = nAudioPort->audio_profiles[i].channel_masks[index];
- if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
- numIndexMasks++;
- } else {
- numPositionMasks++;
- }
- }
- ScopedLocalRef<jintArray> jSamplingRates(env,
- env->NewIntArray(nAudioPort->audio_profiles[i]
- .num_sample_rates));
- ScopedLocalRef<jintArray> jChannelMasks(env, env->NewIntArray(numPositionMasks));
- ScopedLocalRef<jintArray> jChannelIndexMasks(env, env->NewIntArray(numIndexMasks));
- if (!jSamplingRates.get() || !jChannelMasks.get() || !jChannelIndexMasks.get()) {
+ for (size_t i = 0; i < nAudioPort->num_audio_profiles; ++i) {
+ jobject jAudioProfile = nullptr;
+ jStatus = convertAudioProfileFromNative(env, &jAudioProfile, &nAudioPort->audio_profiles[i],
+ useInMask);
+ if (jStatus != NO_ERROR) {
jStatus = (jint)AUDIO_JAVA_ERROR;
goto exit;
}
+ env->CallBooleanMethod(jAudioProfiles, gArrayListMethods.add, jAudioProfile);
- if (nAudioPort->audio_profiles[i].num_sample_rates) {
- env->SetIntArrayRegion(jSamplingRates.get(), 0 /*start*/,
- nAudioPort->audio_profiles[i].num_sample_rates,
- (jint *)nAudioPort->audio_profiles[i].sample_rates);
- }
-
- // put the masks in the output arrays
- for (size_t maskIndex = 0, posMaskIndex = 0, indexedMaskIndex = 0;
- maskIndex < nAudioPort->audio_profiles[i].num_channel_masks; maskIndex++) {
- const audio_channel_mask_t mask =
- nAudioPort->audio_profiles[i].channel_masks[maskIndex];
- if (audio_channel_mask_get_representation(mask) == AUDIO_CHANNEL_REPRESENTATION_INDEX) {
- jint jMask = audio_channel_mask_get_bits(mask);
- env->SetIntArrayRegion(jChannelIndexMasks.get(), indexedMaskIndex++, 1, &jMask);
- } else {
- jint jMask =
- useInMask ? inChannelMaskFromNative(mask) : outChannelMaskFromNative(mask);
- env->SetIntArrayRegion(jChannelMasks.get(), posMaskIndex++, 1, &jMask);
- }
- }
-
- int encapsulationType;
- if (audioEncapsulationTypeFromNative(nAudioPort->audio_profiles[i].encapsulation_type,
- &encapsulationType) != NO_ERROR) {
- ALOGW("Unknown encapsualtion type for JAVA API: %u",
- nAudioPort->audio_profiles[i].encapsulation_type);
- continue;
- }
-
- ScopedLocalRef<jobject>
- jAudioProfile(env,
- env->NewObject(gAudioProfileClass, gAudioProfileCstor,
- audioFormatFromNative(
- nAudioPort->audio_profiles[i].format),
- jSamplingRates.get(), jChannelMasks.get(),
- jChannelIndexMasks.get(), encapsulationType));
- if (jAudioProfile == nullptr) {
- jStatus = (jint)AUDIO_JAVA_ERROR;
- goto exit;
- }
- env->CallBooleanMethod(jAudioProfiles, gArrayListMethods.add, jAudioProfile.get());
if (nAudioPort->audio_profiles[i].format == AUDIO_FORMAT_PCM_FLOAT) {
hasFloat = true;
} else if (jPcmFloatProfileFromExtendedInteger.get() == nullptr &&
audio_is_linear_pcm(nAudioPort->audio_profiles[i].format) &&
audio_bytes_per_sample(nAudioPort->audio_profiles[i].format) > 2) {
+ ScopedLocalRef<jintArray>
+ jSamplingRates(env,
+ (jintArray)
+ env->GetObjectField(jAudioProfile,
+ gAudioProfileFields.mSamplingRates));
+ ScopedLocalRef<jintArray>
+ jChannelMasks(env,
+ (jintArray)
+ env->GetObjectField(jAudioProfile,
+ gAudioProfileFields.mChannelMasks));
+ ScopedLocalRef<jintArray>
+ jChannelIndexMasks(env,
+ (jintArray)env->GetObjectField(jAudioProfile,
+ gAudioProfileFields
+ .mChannelIndexMasks));
+ int encapsulationType =
+ env->GetIntField(jAudioProfile, gAudioProfileFields.mEncapsulationType);
+
jPcmFloatProfileFromExtendedInteger.reset(
env->NewObject(gAudioProfileClass, gAudioProfileCstor,
audioFormatFromNative(AUDIO_FORMAT_PCM_FLOAT),
jSamplingRates.get(), jChannelMasks.get(),
jChannelIndexMasks.get(), encapsulationType));
}
+
+ if (jAudioProfile != nullptr) {
+ env->DeleteLocalRef(jAudioProfile);
+ }
}
if (!hasFloat && jPcmFloatProfileFromExtendedInteger.get() != nullptr) {
// R and earlier compatibility - add ENCODING_PCM_FLOAT to the end
@@ -3285,6 +3260,14 @@ int register_android_media_AudioSystem(JNIEnv *env)
jclass audioProfileClass = FindClassOrDie(env, "android/media/AudioProfile");
gAudioProfileClass = MakeGlobalRefOrDie(env, audioProfileClass);
gAudioProfileCstor = GetMethodIDOrDie(env, audioProfileClass, "<init>", "(I[I[I[II)V");
+ gAudioProfileFields.mSamplingRates =
+ GetFieldIDOrDie(env, audioProfileClass, "mSamplingRates", "[I");
+ gAudioProfileFields.mChannelMasks =
+ GetFieldIDOrDie(env, audioProfileClass, "mChannelMasks", "[I");
+ gAudioProfileFields.mChannelIndexMasks =
+ GetFieldIDOrDie(env, audioProfileClass, "mChannelIndexMasks", "[I");
+ gAudioProfileFields.mEncapsulationType =
+ GetFieldIDOrDie(env, audioProfileClass, "mEncapsulationType", "I");
jclass audioDescriptorClass = FindClassOrDie(env, "android/media/AudioDescriptor");
gAudioDescriptorClass = MakeGlobalRefOrDie(env, audioDescriptorClass);
diff --git a/core/jni/android_server_NetworkManagementSocketTagger.cpp b/core/jni/android_server_NetworkManagementSocketTagger.cpp
deleted file mode 100644
index 9734ab9b9e1d..000000000000
--- a/core/jni/android_server_NetworkManagementSocketTagger.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2011, 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.
- */
-
-#define LOG_TAG "NMST_QTagUidNative"
-
-#include <android/multinetwork.h>
-#include <cutils/qtaguid.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <nativehelper/JNIPlatformHelp.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <utils/Log.h>
-#include <utils/misc.h>
-
-#include "jni.h"
-
-namespace android {
-
-static jint tagSocketFd(JNIEnv* env, jclass, jobject fileDescriptor,
- jint tagNum, jint uid) {
- int userFd = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
- if (env->ExceptionCheck()) {
- ALOGE("Can't get FileDescriptor num");
- return (jint)-1;
- }
-
- int res = android_tag_socket_with_uid(userFd, tagNum, uid);
- if (res < 0) {
- return (jint)-errno;
- }
- return (jint)res;
-}
-
-static jint untagSocketFd(JNIEnv* env, jclass, jobject fileDescriptor) {
- int userFd = jniGetFDFromFileDescriptor(env, fileDescriptor);
-
- if (env->ExceptionCheck()) {
- ALOGE("Can't get FileDescriptor num");
- return (jint)-1;
- }
-
- int res = android_untag_socket(userFd);
- if (res < 0) {
- return (jint)-errno;
- }
- return (jint)res;
-}
-
-static const JNINativeMethod gQTagUidMethods[] = {
- { "native_tagSocketFd", "(Ljava/io/FileDescriptor;II)I", (void*)tagSocketFd},
- { "native_untagSocketFd", "(Ljava/io/FileDescriptor;)I", (void*)untagSocketFd},
-};
-
-int register_android_server_NetworkManagementSocketTagger(JNIEnv* env) {
- return jniRegisterNativeMethods(env, "com/android/server/NetworkManagementSocketTagger", gQTagUidMethods, NELEM(gQTagUidMethods));
-}
-
-};
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index c9bd22210a77..92f7f2921bee 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -719,6 +719,7 @@
<protected-broadcast android:name="android.safetycenter.action.REFRESH_SAFETY_SOURCES" />
<protected-broadcast android:name="android.app.action.DEVICE_POLICY_RESOURCE_UPDATED" />
<protected-broadcast android:name="android.intent.action.SHOW_FOREGROUND_SERVICE_MANAGER" />
+ <protected-broadcast android:name="android.service.autofill.action.DELAYED_FILL" />
<!-- ====================================================================== -->
<!-- RUNTIME PERMISSIONS -->
@@ -1144,6 +1145,15 @@
android:description="@string/permdesc_accessBackgroundLocation"
android:protectionLevel="dangerous|instant" />
+ <!-- Allows an application (emergency or advanced driver-assistance app) to bypass
+ location settings.
+ <p>Not for use by third-party applications.
+ @SystemApi
+ @hide
+ -->
+ <permission android:name="android.permission.LOCATION_BYPASS"
+ android:protectionLevel="signature|privileged"/>
+
<!-- ====================================================================== -->
<!-- Permissions for accessing the call log -->
<!-- ====================================================================== -->
@@ -5416,7 +5426,7 @@
android:protectionLevel="signature|setup|role" />
<!-- Allows access to keyguard secure storage. Only allowed for system processes.
- @hide -->
+ @hide @TestApi -->
<permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE"
android:protectionLevel="signature|setup" />
@@ -6290,6 +6300,15 @@
<permission android:name="android.permission.BIND_AMBIENT_CONTEXT_DETECTION_SERVICE"
android:protectionLevel="signature" />
+ <!-- @SystemApi Allows an app to set keep-clear areas without restrictions on the size or
+ number of keep-clear areas (see {@link android.view.View#setPreferKeepClearRects}).
+ When the system arranges floating windows onscreen, it might decide to ignore keep-clear
+ areas from windows, whose owner does not have this permission.
+ @hide
+ -->
+ <permission android:name="android.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS"
+ android:protectionLevel="signature|privileged" />
+
<!-- Attribution for Geofencing service. -->
<attribution android:tag="GeofencingService" android:label="@string/geofencing_service"/>
<!-- Attribution for Country Detector. -->
@@ -6784,10 +6803,6 @@
android:resource="@xml/autofill_compat_accessibility_service" />
</service>
- <service android:name="com.google.android.startop.iorap.IorapForwardingService$IorapdJobServiceProxy"
- android:permission="android.permission.BIND_JOB_SERVICE" >
- </service>
-
<service android:name="com.android.server.blob.BlobStoreIdleJobService"
android:permission="android.permission.BIND_JOB_SERVICE">
</service>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 48bdd2ada409..1997e91a579e 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2711,6 +2711,9 @@
Values are bandwidth_estimator, carrier_config and modem. -->
<string name="config_bandwidthEstimateSource">bandwidth_estimator</string>
+ <!-- Whether force to enable telephony new data stack or not -->
+ <bool name="config_force_enable_telephony_new_data_stack">false</bool>
+
<!-- Whether WiFi display is supported by this device.
There are many prerequisites for this feature to work correctly.
Here are a few of them:
@@ -5137,6 +5140,9 @@
If given value is outside of this range, the option 1 (center) is assummed. -->
<integer name="config_letterboxDefaultPositionForReachability">1</integer>
+ <!-- Whether displaying letterbox education is enabled for letterboxed fullscreen apps. -->
+ <bool name="config_letterboxIsEducationEnabled">false</bool>
+
<!-- Whether a camera compat controller is enabled to allow the user to apply or revert
treatment for stretched issues in camera viewfinder. -->
<bool name="config_isCameraCompatControlForStretchedIssuesEnabled">false</bool>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 136b98b5cb1e..1884467cdcac 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -473,6 +473,7 @@
<java-symbol type="integer" name="config_mobile_mtu" />
<java-symbol type="array" name="config_mobile_tcp_buffers" />
<java-symbol type="string" name="config_tcp_buffers" />
+ <java-symbol type="bool" name="config_force_enable_telephony_new_data_stack" />
<java-symbol type="integer" name="config_volte_replacement_rat"/>
<java-symbol type="integer" name="config_valid_wappush_index" />
<java-symbol type="integer" name="config_overrideHasPermanentMenuKey" />
@@ -4329,6 +4330,7 @@
<java-symbol type="dimen" name="config_letterboxHorizontalPositionMultiplier" />
<java-symbol type="bool" name="config_letterboxIsReachabilityEnabled" />
<java-symbol type="integer" name="config_letterboxDefaultPositionForReachability" />
+ <java-symbol type="bool" name="config_letterboxIsEducationEnabled" />
<java-symbol type="bool" name="config_isCameraCompatControlForStretchedIssuesEnabled" />
<java-symbol type="bool" name="config_hideDisplayCutoutWithDisplayArea" />
diff --git a/core/tests/coretests/res/layout/remote_view_relative_layout.xml b/core/tests/coretests/res/layout/remote_view_relative_layout.xml
new file mode 100644
index 000000000000..713a4c89ea4d
--- /dev/null
+++ b/core/tests/coretests/res/layout/remote_view_relative_layout.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2008, 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.
+*/
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
diff --git a/core/tests/coretests/res/layout/remote_view_relative_layout_with_theme.xml b/core/tests/coretests/res/layout/remote_view_relative_layout_with_theme.xml
new file mode 100644
index 000000000000..74c939b7eaa3
--- /dev/null
+++ b/core/tests/coretests/res/layout/remote_view_relative_layout_with_theme.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2008, 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.
+*/
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/themed_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:theme="@style/RelativeLayoutAlignTop25Alpha"/>
diff --git a/core/tests/coretests/res/layout/remote_views_light_background_text.xml b/core/tests/coretests/res/layout/remote_views_light_background_text.xml
new file mode 100644
index 000000000000..f300f0991a97
--- /dev/null
+++ b/core/tests/coretests/res/layout/remote_views_light_background_text.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2016 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
+ -->
+
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/light_background_text"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
diff --git a/core/tests/coretests/res/layout/remote_views_list.xml b/core/tests/coretests/res/layout/remote_views_list.xml
new file mode 100644
index 000000000000..ca43bc8986e7
--- /dev/null
+++ b/core/tests/coretests/res/layout/remote_views_list.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2016 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
+ -->
+<ListView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"/>
+
diff --git a/core/tests/coretests/res/values/styles.xml b/core/tests/coretests/res/values/styles.xml
index 352b4dceb3cc..32eebb35e0c3 100644
--- a/core/tests/coretests/res/values/styles.xml
+++ b/core/tests/coretests/res/values/styles.xml
@@ -34,6 +34,16 @@
<style name="LayoutInDisplayCutoutModeAlways">
<item name="android:windowLayoutInDisplayCutoutMode">always</item>
</style>
+ <style name="RelativeLayoutAlignBottom50Alpha">
+ <item name="android:layout_alignParentTop">false</item>
+ <item name="android:layout_alignParentBottom">true</item>
+ <item name="android:alpha">0.5</item>
+ </style>
+ <style name="RelativeLayoutAlignTop25Alpha">
+ <item name="android:layout_alignParentTop">true</item>
+ <item name="android:layout_alignParentBottom">false</item>
+ <item name="android:alpha">0.25</item>
+ </style>
<style name="WindowBackgroundColorLiteral">
<item name="android:windowBackground">#00FF00</item>
</style>
diff --git a/core/tests/coretests/src/android/widget/RemoteViewsTest.java b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
index 059c764213bc..00b3693c902b 100644
--- a/core/tests/coretests/src/android/widget/RemoteViewsTest.java
+++ b/core/tests/coretests/src/android/widget/RemoteViewsTest.java
@@ -16,8 +16,12 @@
package android.widget;
+import static com.android.internal.R.id.pending_intent_tag;
+
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
@@ -31,7 +35,10 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Binder;
+import android.os.Looper;
import android.os.Parcel;
+import android.util.SizeF;
+import android.view.ContextThemeWrapper;
import android.view.View;
import android.view.ViewGroup;
@@ -49,6 +56,7 @@ import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Map;
import java.util.concurrent.CountDownLatch;
/**
@@ -261,6 +269,148 @@ public class RemoteViewsTest {
verifyViewTree(syncView, asyncView, "row1-c1", "row1-c2", "row1-c3", "row2-c1", "row2-c2");
}
+ @Test
+ public void nestedViews_setRemoteAdapter_intent() {
+ Looper.prepare();
+
+ AppWidgetHostView widget = new AppWidgetHostView(mContext);
+ RemoteViews top = new RemoteViews(mPackage, R.layout.remote_view_host);
+ RemoteViews inner1 = new RemoteViews(mPackage, R.layout.remote_view_host);
+ RemoteViews inner2 = new RemoteViews(mPackage, R.layout.remote_views_list);
+ inner2.setRemoteAdapter(R.id.list, new Intent());
+ inner1.addView(R.id.container, inner2);
+ top.addView(R.id.container, inner1);
+
+ View view = top.apply(mContext, widget);
+ widget.addView(view);
+
+ ListView listView = (ListView) view.findViewById(R.id.list);
+ listView.onRemoteAdapterConnected();
+ assertNotNull(listView.getAdapter());
+
+ top.reapply(mContext, view);
+ listView = (ListView) view.findViewById(R.id.list);
+ assertNotNull(listView.getAdapter());
+ }
+
+ @Test
+ public void nestedViews_setRemoteAdapter_remoteCollectionItems() {
+ AppWidgetHostView widget = new AppWidgetHostView(mContext);
+ RemoteViews top = new RemoteViews(mPackage, R.layout.remote_view_host);
+ RemoteViews inner1 = new RemoteViews(mPackage, R.layout.remote_view_host);
+ RemoteViews inner2 = new RemoteViews(mPackage, R.layout.remote_views_list);
+ inner2.setRemoteAdapter(
+ R.id.list,
+ new RemoteViews.RemoteCollectionItems.Builder()
+ .addItem(0, new RemoteViews(mPackage, R.layout.remote_view_host))
+ .build());
+ inner1.addView(R.id.container, inner2);
+ top.addView(R.id.container, inner1);
+
+ View view = top.apply(mContext, widget);
+ widget.addView(view);
+
+ ListView listView = (ListView) view.findViewById(R.id.list);
+ assertNotNull(listView.getAdapter());
+
+ top.reapply(mContext, view);
+ listView = (ListView) view.findViewById(R.id.list);
+ assertNotNull(listView.getAdapter());
+ }
+
+ @Test
+ public void nestedViews_collectionChildFlag() throws Exception {
+ RemoteViews nested = new RemoteViews(mPackage, R.layout.remote_views_text);
+ nested.setOnClickPendingIntent(
+ R.id.text,
+ PendingIntent.getActivity(mContext, 0, new Intent(), PendingIntent.FLAG_MUTABLE)
+ );
+
+ RemoteViews listItem = new RemoteViews(mPackage, R.layout.remote_view_host);
+ listItem.addView(R.id.container, nested);
+ listItem.addFlags(RemoteViews.FLAG_WIDGET_IS_COLLECTION_CHILD);
+
+ View view = listItem.apply(mContext, mContainer);
+ TextView text = (TextView) view.findViewById(R.id.text);
+ assertNull(text.getTag(pending_intent_tag));
+ }
+
+ @Test
+ public void landscapePortraitViews_collectionChildFlag() throws Exception {
+ RemoteViews inner = new RemoteViews(mPackage, R.layout.remote_views_text);
+ inner.setOnClickPendingIntent(
+ R.id.text,
+ PendingIntent.getActivity(mContext, 0, new Intent(), PendingIntent.FLAG_MUTABLE)
+ );
+
+ RemoteViews listItem = new RemoteViews(inner, inner);
+ listItem.addFlags(RemoteViews.FLAG_WIDGET_IS_COLLECTION_CHILD);
+
+ View view = listItem.apply(mContext, mContainer);
+ TextView text = (TextView) view.findViewById(R.id.text);
+ assertNull(text.getTag(pending_intent_tag));
+ }
+
+ @Test
+ public void sizedViews_collectionChildFlag() throws Exception {
+ RemoteViews inner = new RemoteViews(mPackage, R.layout.remote_views_text);
+ inner.setOnClickPendingIntent(
+ R.id.text,
+ PendingIntent.getActivity(mContext, 0, new Intent(), PendingIntent.FLAG_MUTABLE)
+ );
+
+ RemoteViews listItem = new RemoteViews(
+ Map.of(new SizeF(0, 0), inner, new SizeF(100, 100), inner));
+ listItem.addFlags(RemoteViews.FLAG_WIDGET_IS_COLLECTION_CHILD);
+
+ View view = listItem.apply(mContext, mContainer);
+ TextView text = (TextView) view.findViewById(R.id.text);
+ assertNull(text.getTag(pending_intent_tag));
+ }
+
+ @Test
+ public void nestedViews_lightBackgroundLayoutFlag() {
+ RemoteViews nested = new RemoteViews(mPackage, R.layout.remote_views_text);
+ nested.setLightBackgroundLayoutId(R.layout.remote_views_light_background_text);
+
+ RemoteViews parent = new RemoteViews(mPackage, R.layout.remote_view_host);
+ parent.addView(R.id.container, nested);
+ parent.setLightBackgroundLayoutId(R.layout.remote_view_host);
+ parent.addFlags(RemoteViews.FLAG_USE_LIGHT_BACKGROUND_LAYOUT);
+
+ View view = parent.apply(mContext, mContainer);
+ assertNull(view.findViewById(R.id.text));
+ assertNotNull(view.findViewById(R.id.light_background_text));
+ }
+
+
+ @Test
+ public void landscapePortraitViews_lightBackgroundLayoutFlag() {
+ RemoteViews inner = new RemoteViews(mPackage, R.layout.remote_views_text);
+ inner.setLightBackgroundLayoutId(R.layout.remote_views_light_background_text);
+
+ RemoteViews parent = new RemoteViews(inner, inner);
+ parent.addFlags(RemoteViews.FLAG_USE_LIGHT_BACKGROUND_LAYOUT);
+
+ View view = parent.apply(mContext, mContainer);
+ assertNull(view.findViewById(R.id.text));
+ assertNotNull(view.findViewById(R.id.light_background_text));
+ }
+
+ @Test
+ public void sizedViews_lightBackgroundLayoutFlag() {
+ RemoteViews inner = new RemoteViews(mPackage, R.layout.remote_views_text);
+ inner.setLightBackgroundLayoutId(R.layout.remote_views_light_background_text);
+
+ RemoteViews parent = new RemoteViews(
+ Map.of(new SizeF(0, 0), inner, new SizeF(100, 100), inner));
+ parent.addFlags(RemoteViews.FLAG_USE_LIGHT_BACKGROUND_LAYOUT);
+
+ View view = parent.apply(mContext, mContainer);
+ assertNull(view.findViewById(R.id.text));
+ assertNotNull(view.findViewById(R.id.light_background_text));
+ }
+
private RemoteViews createViewChained(int depth, String... texts) {
RemoteViews result = new RemoteViews(mPackage, R.layout.remote_view_host);
@@ -483,6 +633,47 @@ public class RemoteViewsTest {
index, inflated.getTag(com.android.internal.R.id.notification_action_index_tag));
}
+ @Test
+ public void nestedViews_themesPropagateCorrectly() {
+ Context themedContext =
+ new ContextThemeWrapper(mContext, R.style.RelativeLayoutAlignBottom50Alpha);
+ RelativeLayout rootParent = new RelativeLayout(themedContext);
+
+ RemoteViews top = new RemoteViews(mPackage, R.layout.remote_view_relative_layout);
+ RemoteViews inner1 =
+ new RemoteViews(mPackage, R.layout.remote_view_relative_layout_with_theme);
+ RemoteViews inner2 =
+ new RemoteViews(mPackage, R.layout.remote_view_relative_layout);
+
+ inner1.addView(R.id.themed_layout, inner2);
+ top.addView(R.id.container, inner1);
+
+ RelativeLayout root = (RelativeLayout) top.apply(themedContext, rootParent);
+ assertEquals(0.5, root.getAlpha(), 0.);
+ RelativeLayout.LayoutParams rootParams =
+ (RelativeLayout.LayoutParams) root.getLayoutParams();
+ assertEquals(RelativeLayout.TRUE,
+ rootParams.getRule(RelativeLayout.ALIGN_PARENT_BOTTOM));
+
+ // The theme is set on inner1View and its descendants. However, inner1View does
+ // not get its layout params from its theme (though its descendants do), but other
+ // attributes such as alpha are set.
+ RelativeLayout inner1View = (RelativeLayout) root.getChildAt(0);
+ assertEquals(R.id.themed_layout, inner1View.getId());
+ assertEquals(0.25, inner1View.getAlpha(), 0.);
+ RelativeLayout.LayoutParams inner1Params =
+ (RelativeLayout.LayoutParams) inner1View.getLayoutParams();
+ assertEquals(RelativeLayout.TRUE,
+ inner1Params.getRule(RelativeLayout.ALIGN_PARENT_BOTTOM));
+
+ RelativeLayout inner2View = (RelativeLayout) inner1View.getChildAt(0);
+ assertEquals(0.25, inner2View.getAlpha(), 0.);
+ RelativeLayout.LayoutParams inner2Params =
+ (RelativeLayout.LayoutParams) inner2View.getLayoutParams();
+ assertEquals(RelativeLayout.TRUE,
+ inner2Params.getRule(RelativeLayout.ALIGN_PARENT_TOP));
+ }
+
private class WidgetContainer extends AppWidgetHostView {
int[] mSharedViewIds;
String[] mSharedViewNames;
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
index b655369d7e60..f5cbffb64bb5 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
@@ -17,6 +17,7 @@
package com.android.internal.os;
import static android.os.BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS;
+import static android.os.BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR;
import static android.os.BatteryStats.STATS_SINCE_CHARGED;
import static android.os.BatteryStats.WAKE_TYPE_PARTIAL;
@@ -30,6 +31,12 @@ import android.os.BatteryStats.Uid.Sensor;
import android.os.Process;
import android.os.UserHandle;
import android.os.WorkSource;
+import android.telephony.Annotation;
+import android.telephony.CellSignalStrength;
+import android.telephony.DataConnectionRealTimeInfo;
+import android.telephony.ServiceState;
+import android.telephony.TelephonyManager;
+import android.util.SparseIntArray;
import android.util.SparseLongArray;
import android.view.Display;
@@ -1165,6 +1172,185 @@ public class BatteryStatsNoteTest extends TestCase {
"D", totalBlameA, totalBlameB, uid1, blame1A, blame1B, uid2, blame2A, blame2B, bi);
}
+ @SmallTest
+ public void testGetPerStateActiveRadioDurationMs() {
+ final MockClock clock = new MockClock(); // holds realtime and uptime in ms
+ final MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clock);
+ final int ratCount = BatteryStats.RADIO_ACCESS_TECHNOLOGY_COUNT;
+ final int frequencyCount = ServiceState.FREQUENCY_RANGE_MMWAVE + 1;
+ final int txLevelCount = CellSignalStrength.getNumSignalStrengthLevels();
+
+ final long[][][] expectedDurationsMs = new long[ratCount][frequencyCount][txLevelCount];
+ for (int rat = 0; rat < ratCount; rat++) {
+ for (int freq = 0; freq < frequencyCount; freq++) {
+ for (int txLvl = 0; txLvl < txLevelCount; txLvl++) {
+ expectedDurationsMs[rat][freq][txLvl] = 0;
+ }
+ }
+ }
+
+ class ModemAndBatteryState {
+ public long currentTimeMs = 100;
+ public boolean onBattery = false;
+ public boolean modemActive = false;
+ @Annotation.NetworkType
+ public int currentNetworkDataType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+ @BatteryStats.RadioAccessTechnology
+ public int currentRat = BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER;
+ @ServiceState.FrequencyRange
+ public int currentFrequencyRange = ServiceState.FREQUENCY_RANGE_UNKNOWN;
+ public SparseIntArray currentSignalStrengths = new SparseIntArray();
+
+ void setOnBattery(boolean onBattery) {
+ this.onBattery = onBattery;
+ bi.updateTimeBasesLocked(onBattery, Display.STATE_OFF, currentTimeMs * 1000,
+ currentTimeMs * 1000);
+ }
+
+ void setModemActive(boolean active) {
+ modemActive = active;
+ final int state = active ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
+ : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
+ bi.noteMobileRadioPowerStateLocked(state, currentTimeMs * 1000_000L, UID);
+ }
+
+ void setRatType(@Annotation.NetworkType int dataType,
+ @BatteryStats.RadioAccessTechnology int rat) {
+ currentNetworkDataType = dataType;
+ currentRat = rat;
+ bi.notePhoneDataConnectionStateLocked(dataType, true, ServiceState.STATE_IN_SERVICE,
+ currentFrequencyRange);
+ }
+
+ void setFrequencyRange(@ServiceState.FrequencyRange int frequency) {
+ currentFrequencyRange = frequency;
+ bi.notePhoneDataConnectionStateLocked(currentNetworkDataType, true,
+ ServiceState.STATE_IN_SERVICE, frequency);
+ }
+
+ void setSignalStrength(@BatteryStats.RadioAccessTechnology int rat, int strength) {
+ currentSignalStrengths.put(rat, strength);
+ final int size = currentSignalStrengths.size();
+ final int newestGenSignalStrength = currentSignalStrengths.valueAt(size - 1);
+ bi.notePhoneSignalStrengthLocked(newestGenSignalStrength, currentSignalStrengths);
+ }
+ }
+ final ModemAndBatteryState state = new ModemAndBatteryState();
+
+ IntConsumer incrementTime = inc -> {
+ state.currentTimeMs += inc;
+ clock.realtime = clock.uptime = state.currentTimeMs;
+
+ // If the device is not on battery, no timers should increment.
+ if (!state.onBattery) return;
+ // If the modem is not active, no timers should increment.
+ if (!state.modemActive) return;
+
+ final int currentRat = state.currentRat;
+ final int currentFrequencyRange =
+ currentRat == RADIO_ACCESS_TECHNOLOGY_NR ? state.currentFrequencyRange : 0;
+ int currentSignalStrength = state.currentSignalStrengths.get(currentRat);
+ expectedDurationsMs[currentRat][currentFrequencyRange][currentSignalStrength] += inc;
+ };
+
+ state.setOnBattery(false);
+ state.setModemActive(false);
+ state.setRatType(TelephonyManager.NETWORK_TYPE_UNKNOWN,
+ BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER);
+ state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_UNKNOWN);
+ state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
+ CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+
+ // While not on battery, the timers should not increase.
+ state.setModemActive(true);
+ incrementTime.accept(100);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+
+ state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR);
+ incrementTime.accept(200);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+
+ state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR,
+ CellSignalStrength.SIGNAL_STRENGTH_GOOD);
+ incrementTime.accept(500);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+
+ state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_MMWAVE);
+ incrementTime.accept(300);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+
+ state.setRatType(TelephonyManager.NETWORK_TYPE_LTE,
+ BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE);
+ incrementTime.accept(400);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+
+ state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+ CellSignalStrength.SIGNAL_STRENGTH_MODERATE);
+ incrementTime.accept(500);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+
+ // When set on battery, currently active state (RAT:LTE, Signal Strength:Moderate) should
+ // start counting up.
+ state.setOnBattery(true);
+ incrementTime.accept(600);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+
+ // Changing LTE signal strength should be tracked.
+ state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+ CellSignalStrength.SIGNAL_STRENGTH_POOR);
+ incrementTime.accept(700);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+
+ state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+ CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
+ incrementTime.accept(800);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+
+ state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+ CellSignalStrength.SIGNAL_STRENGTH_GOOD);
+ incrementTime.accept(900);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+
+ state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_LTE,
+ CellSignalStrength.SIGNAL_STRENGTH_GREAT);
+ incrementTime.accept(1000);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+
+ // Change in the signal strength of nonactive RAT should not affect anything.
+ state.setSignalStrength(BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER,
+ CellSignalStrength.SIGNAL_STRENGTH_POOR);
+ incrementTime.accept(1100);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+
+ // Changing to OTHER Rat should start tracking the poor signal strength.
+ state.setRatType(TelephonyManager.NETWORK_TYPE_CDMA,
+ BatteryStats.RADIO_ACCESS_TECHNOLOGY_OTHER);
+ incrementTime.accept(1200);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+
+ // Noting frequency change should not affect non NR Rat.
+ state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_HIGH);
+ incrementTime.accept(1300);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+
+ // Now the NR Rat, HIGH frequency range, good signal strength should start counting.
+ state.setRatType(TelephonyManager.NETWORK_TYPE_NR, BatteryStats.RADIO_ACCESS_TECHNOLOGY_NR);
+ incrementTime.accept(1400);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+
+ // Noting frequency change should not affect non NR Rat.
+ state.setFrequencyRange(ServiceState.FREQUENCY_RANGE_LOW);
+ incrementTime.accept(1500);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+
+ // Modem no longer active, should not be tracking any more.
+ state.setModemActive(false);
+ incrementTime.accept(1500);
+ checkPerStateActiveRadioDurations(expectedDurationsMs, bi, state.currentTimeMs);
+
+ }
+
private void setFgState(int uid, boolean fgOn, MockBatteryStatsImpl bi) {
// Note that noteUidProcessStateLocked uses ActivityManager process states.
if (fgOn) {
@@ -1238,4 +1424,30 @@ public class BatteryStatsNoteTest extends TestCase {
bi.getScreenBrightnessTime(bin, currentTimeMs * 1000, STATS_SINCE_CHARGED));
}
}
+
+ private void checkPerStateActiveRadioDurations(long[][][] expectedDurationsMs,
+ BatteryStatsImpl bi, long currentTimeMs) {
+ for (int rat = 0; rat < expectedDurationsMs.length; rat++) {
+ final long[][] expectedRatDurationsMs = expectedDurationsMs[rat];
+ for (int freq = 0; freq < expectedRatDurationsMs.length; freq++) {
+ final long[] expectedFreqDurationsMs = expectedRatDurationsMs[freq];
+ for (int strength = 0; strength < expectedFreqDurationsMs.length; strength++) {
+ final long expectedSignalStrengthDurationMs = expectedFreqDurationsMs[strength];
+ final long actualDurationMs = bi.getActiveRadioDurationMs(rat, freq,
+ strength, currentTimeMs);
+
+ // Build a verbose fail message, just in case.
+ final StringBuilder sb = new StringBuilder();
+ sb.append("Wrong time in state for RAT:");
+ sb.append(BatteryStats.RADIO_ACCESS_TECHNOLOGY_NAMES[rat]);
+ sb.append(", frequency:");
+ sb.append(ServiceState.frequencyRangeToString(freq));
+ sb.append(", strength:");
+ sb.append(strength);
+
+ assertEquals(sb.toString(), expectedSignalStrengthDurationMs, actualDurationMs);
+ }
+ }
+ }
+ }
}
diff --git a/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java b/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java
index db63e6e0b187..4c247427ef8f 100644
--- a/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java
+++ b/core/tests/devicestatetests/src/android/hardware/devicestate/DeviceStateManagerGlobalTest.java
@@ -38,7 +38,6 @@ import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.Mockito;
-import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
@@ -155,7 +154,7 @@ public final class DeviceStateManagerGlobalTest {
verify(callback).onStateChanged(eq(OTHER_DEVICE_STATE));
Mockito.reset(callback);
- mDeviceStateManagerGlobal.cancelRequest(request);
+ mDeviceStateManagerGlobal.cancelStateRequest();
verify(callback).onStateChanged(eq(mService.getBaseState()));
}
@@ -172,7 +171,7 @@ public final class DeviceStateManagerGlobalTest {
verify(callback).onRequestActivated(eq(request));
Mockito.reset(callback);
- mDeviceStateManagerGlobal.cancelRequest(request);
+ mDeviceStateManagerGlobal.cancelStateRequest();
verify(callback).onRequestCanceled(eq(request));
}
@@ -203,13 +202,13 @@ public final class DeviceStateManagerGlobalTest {
private int[] mSupportedStates = new int[] { DEFAULT_DEVICE_STATE, OTHER_DEVICE_STATE };
private int mBaseState = DEFAULT_DEVICE_STATE;
- private ArrayList<Request> mRequests = new ArrayList<>();
+ private Request mRequest;
private Set<IDeviceStateManagerCallback> mCallbacks = new HashSet<>();
private DeviceStateInfo getInfo() {
- final int mergedState = mRequests.isEmpty()
- ? mBaseState : mRequests.get(mRequests.size() - 1).state;
+ final int mergedState = mRequest == null
+ ? mBaseState : mRequest.state;
return new DeviceStateInfo(mSupportedStates, mBaseState, mergedState);
}
@@ -245,11 +244,10 @@ public final class DeviceStateManagerGlobalTest {
@Override
public void requestState(IBinder token, int state, int flags) {
- if (!mRequests.isEmpty()) {
- final Request topRequest = mRequests.get(mRequests.size() - 1);
+ if (mRequest != null) {
for (IDeviceStateManagerCallback callback : mCallbacks) {
try {
- callback.onRequestSuspended(topRequest.token);
+ callback.onRequestCanceled(mRequest.token);
} catch (RemoteException e) {
// Do nothing. Should never happen.
}
@@ -257,7 +255,7 @@ public final class DeviceStateManagerGlobalTest {
}
final Request request = new Request(token, state, flags);
- mRequests.add(request);
+ mRequest = request;
notifyDeviceStateInfoChanged();
for (IDeviceStateManagerCallback callback : mCallbacks) {
@@ -270,20 +268,9 @@ public final class DeviceStateManagerGlobalTest {
}
@Override
- public void cancelRequest(IBinder token) {
- int index = -1;
- for (int i = 0; i < mRequests.size(); i++) {
- if (mRequests.get(i).token.equals(token)) {
- index = i;
- break;
- }
- }
-
- if (index == -1) {
- throw new IllegalArgumentException("Unknown request: " + token);
- }
-
- mRequests.remove(index);
+ public void cancelStateRequest() {
+ IBinder token = mRequest.token;
+ mRequest = null;
for (IDeviceStateManagerCallback callback : mCallbacks) {
try {
callback.onRequestCanceled(token);
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index 4ae0fc4ae6ed..5a3a033c1cc8 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -272,13 +272,13 @@
<!-- fallback fonts -->
<family lang="und-Arab" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoNaskhArabic">
+ <font weight="400" style="normal">
NotoNaskhArabic-Regular.ttf
</font>
<font weight="700" style="normal">NotoNaskhArabic-Bold.ttf</font>
</family>
<family lang="und-Arab" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoNaskhArabicUI">
+ <font weight="400" style="normal">
NotoNaskhArabicUI-Regular.ttf
</font>
<font weight="700" style="normal">NotoNaskhArabicUI-Bold.ttf</font>
@@ -329,7 +329,7 @@
<font weight="400" style="normal" postScriptName="NotoSansThai">NotoSansThai-Regular.ttf
</font>
<font weight="700" style="normal">NotoSansThai-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif" postScriptName="NotoSerifThai">
+ <font weight="400" style="normal" fallbackFor="serif">
NotoSerifThai-Regular.ttf
</font>
<font weight="700" style="normal" fallbackFor="serif">NotoSerifThai-Bold.ttf</font>
@@ -923,16 +923,16 @@
<font weight="700" style="normal">NotoSansKhmerUI-Bold.ttf</font>
</family>
<family lang="und-Laoo" variant="elegant">
- <font weight="400" style="normal" postScriptName="NotoSansLao">NotoSansLao-Regular.ttf
+ <font weight="400" style="normal">NotoSansLao-Regular.ttf
</font>
<font weight="700" style="normal">NotoSansLao-Bold.ttf</font>
- <font weight="400" style="normal" fallbackFor="serif" postScriptName="NotoSerifLao">
+ <font weight="400" style="normal" fallbackFor="serif">
NotoSerifLao-Regular.ttf
</font>
<font weight="700" style="normal" fallbackFor="serif">NotoSerifLao-Bold.ttf</font>
</family>
<family lang="und-Laoo" variant="compact">
- <font weight="400" style="normal" postScriptName="NotoSansLaoUI">NotoSansLaoUI-Regular.ttf
+ <font weight="400" style="normal">NotoSansLaoUI-Regular.ttf
</font>
<font weight="700" style="normal">NotoSansLaoUI-Bold.ttf</font>
</family>
@@ -1013,7 +1013,7 @@
</font>
</family>
<family lang="und-Cans">
- <font weight="400" style="normal" postScriptName="NotoSansCanadianAboriginal">
+ <font weight="400" style="normal">
NotoSansCanadianAboriginal-Regular.ttf
</font>
</family>
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 055e5ad17def..857af11e4ca3 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -458,7 +458,7 @@ public final class Bitmap implements Parcelable {
* No color information is stored.
* With this configuration, each pixel requires 1 byte of memory.
*/
- ALPHA_8 (1),
+ ALPHA_8(1),
/**
* Each pixel is stored on 2 bytes and only the RGB channels are
@@ -479,7 +479,7 @@ public final class Bitmap implements Parcelable {
* short color = (R & 0x1f) << 11 | (G & 0x3f) << 5 | (B & 0x1f);
* </pre>
*/
- RGB_565 (3),
+ RGB_565(3),
/**
* Each pixel is stored on 2 bytes. The three RGB color channels
@@ -501,7 +501,7 @@ public final class Bitmap implements Parcelable {
* it is advised to use {@link #ARGB_8888} instead.
*/
@Deprecated
- ARGB_4444 (4),
+ ARGB_4444(4),
/**
* Each pixel is stored on 4 bytes. Each channel (RGB and alpha
@@ -516,10 +516,10 @@ public final class Bitmap implements Parcelable {
* int color = (A & 0xff) << 24 | (B & 0xff) << 16 | (G & 0xff) << 8 | (R & 0xff);
* </pre>
*/
- ARGB_8888 (5),
+ ARGB_8888(5),
/**
- * Each pixels is stored on 8 bytes. Each channel (RGB and alpha
+ * Each pixel is stored on 8 bytes. Each channel (RGB and alpha
* for translucency) is stored as a
* {@link android.util.Half half-precision floating point value}.
*
@@ -531,7 +531,7 @@ public final class Bitmap implements Parcelable {
* long color = (A & 0xffff) << 48 | (B & 0xffff) << 32 | (G & 0xffff) << 16 | (R & 0xffff);
* </pre>
*/
- RGBA_F16 (6),
+ RGBA_F16(6),
/**
* Special configuration, when bitmap is stored only in graphic memory.
@@ -540,13 +540,29 @@ public final class Bitmap implements Parcelable {
* It is optimal for cases, when the only operation with the bitmap is to draw it on a
* screen.
*/
- HARDWARE (7);
+ HARDWARE(7),
+
+ /**
+ * Each pixel is stored on 4 bytes. Each RGB channel is stored with 10 bits of precision
+ * (1024 possible values). There is an additional alpha channel that is stored with 2 bits
+ * of precision (4 possible values).
+ *
+ * This configuration is suited for wide-gamut and HDR content which does not require alpha
+ * blending, such that the memory cost is the same as ARGB_8888 while enabling higher color
+ * precision.
+ *
+ * <p>Use this formula to pack into 32 bits:</p>
+ * <pre class="prettyprint">
+ * int color = (A & 0x3) << 30 | (B & 0x3ff) << 20 | (G & 0x3ff) << 10 | (R & 0x3ff);
+ * </pre>
+ */
+ RGBA_1010102(8);
@UnsupportedAppUsage
final int nativeInt;
private static Config sConfigs[] = {
- null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888, RGBA_F16, HARDWARE
+ null, ALPHA_8, null, RGB_565, ARGB_4444, ARGB_8888, RGBA_F16, HARDWARE, RGBA_1010102
};
Config(int ni) {
@@ -1000,8 +1016,8 @@ public final class Bitmap implements Parcelable {
* @param width The width of the bitmap
* @param height The height of the bitmap
* @param config The bitmap config to create.
- * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
- * mark the bitmap as opaque. Doing so will clear the bitmap in black
+ * @param hasAlpha If the bitmap is ARGB_8888, RGBA_16F, or RGBA_1010102 this flag can be
+ * used to mark the bitmap as opaque. Doing so will clear the bitmap in black
* instead of transparent.
*
* @throws IllegalArgumentException if the width or height are <= 0, or if
@@ -1019,8 +1035,8 @@ public final class Bitmap implements Parcelable {
* @param width The width of the bitmap
* @param height The height of the bitmap
* @param config The bitmap config to create.
- * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
- * mark the bitmap as opaque. Doing so will clear the bitmap in black
+ * @param hasAlpha If the bitmap is ARGB_8888, RGBA_16F, or RGBA_1010102 this flag can be
+ * used to mark the bitmap as opaque. Doing so will clear the bitmap in black
* instead of transparent.
* @param colorSpace The color space of the bitmap. If the config is {@link Config#RGBA_F16}
* and {@link ColorSpace.Named#SRGB sRGB} or
@@ -1050,8 +1066,8 @@ public final class Bitmap implements Parcelable {
* @param width The width of the bitmap
* @param height The height of the bitmap
* @param config The bitmap config to create.
- * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
- * mark the bitmap as opaque. Doing so will clear the bitmap in black
+ * @param hasAlpha If the bitmap is ARGB_8888, RGBA_16F, or RGBA_1010102 this flag can be
+ * used to mark the bitmap as opaque. Doing so will clear the bitmap in black
* instead of transparent.
*
* @throws IllegalArgumentException if the width or height are <= 0, or if
@@ -1074,8 +1090,8 @@ public final class Bitmap implements Parcelable {
* @param width The width of the bitmap
* @param height The height of the bitmap
* @param config The bitmap config to create.
- * @param hasAlpha If the bitmap is ARGB_8888 or RGBA_16F this flag can be used to
- * mark the bitmap as opaque. Doing so will clear the bitmap in black
+ * @param hasAlpha If the bitmap is ARGB_8888, RGBA_16F, or RGBA_1010102 this flag can be
+ * used to mark the bitmap as opaque. Doing so will clear the bitmap in black
* instead of transparent.
* @param colorSpace The color space of the bitmap. If the config is {@link Config#RGBA_F16}
* and {@link ColorSpace.Named#SRGB sRGB} or
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java
index e2bc36028405..9384e2b4dfdf 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayController.java
@@ -245,7 +245,8 @@ public class DisplayController {
}
}
- private void onKeepClearAreasChanged(int displayId, List<Rect> keepClearAreas) {
+ private void onKeepClearAreasChanged(int displayId, List<Rect> restricted,
+ List<Rect> unrestricted) {
synchronized (mDisplays) {
if (mDisplays.get(displayId) == null || getDisplay(displayId) == null) {
Slog.w(TAG, "Skipping onKeepClearAreasChanged on unknown"
@@ -253,7 +254,8 @@ public class DisplayController {
return;
}
for (int i = mDisplayChangedListeners.size() - 1; i >= 0; --i) {
- mDisplayChangedListeners.get(i).onKeepClearAreasChanged(displayId, keepClearAreas);
+ mDisplayChangedListeners.get(i)
+ .onKeepClearAreasChanged(displayId, restricted, unrestricted);
}
}
}
@@ -318,9 +320,10 @@ public class DisplayController {
}
@Override
- public void onKeepClearAreasChanged(int displayId, List<Rect> keepClearAreas) {
+ public void onKeepClearAreasChanged(int displayId, List<Rect> restricted,
+ List<Rect> unrestricted) {
mMainExecutor.execute(() -> {
- DisplayController.this.onKeepClearAreasChanged(displayId, keepClearAreas);
+ DisplayController.this.onKeepClearAreasChanged(displayId, restricted, unrestricted);
});
}
}
@@ -361,6 +364,7 @@ public class DisplayController {
/**
* Called when keep-clear areas on a display have changed.
*/
- default void onKeepClearAreasChanged(int displayId, List<Rect> keepClearAreas) {}
+ default void onKeepClearAreasChanged(int displayId, List<Rect> restricted,
+ List<Rect> unrestricted) {}
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
index eda09e3ce0b0..5ebdceba135b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropPolicy.java
@@ -150,43 +150,45 @@ public class DragAndDropPolicy {
if (inLandscape) {
final Rect leftHitRegion = new Rect();
- final Rect leftDrawRegion = topOrLeftBounds;
final Rect rightHitRegion = new Rect();
- final Rect rightDrawRegion = bottomOrRightBounds;
// If we have existing split regions use those bounds, otherwise split it 50/50
if (inSplitScreen) {
- // Add the divider bounds to each side since that counts for the hit region.
- leftHitRegion.set(topOrLeftBounds);
- leftHitRegion.right += dividerWidth / 2;
- rightHitRegion.set(bottomOrRightBounds);
- rightHitRegion.left -= dividerWidth / 2;
+ // The bounds of the existing split will have a divider bar, the hit region
+ // should include that space. Find the center of the divider bar:
+ float centerX = topOrLeftBounds.right + (dividerWidth / 2);
+ // Now set the hit regions using that center.
+ leftHitRegion.set(displayRegion);
+ leftHitRegion.right = (int) centerX;
+ rightHitRegion.set(displayRegion);
+ rightHitRegion.left = (int) centerX;
} else {
displayRegion.splitVertically(leftHitRegion, rightHitRegion);
}
- mTargets.add(new Target(TYPE_SPLIT_LEFT, leftHitRegion, leftDrawRegion));
- mTargets.add(new Target(TYPE_SPLIT_RIGHT, rightHitRegion, rightDrawRegion));
+ mTargets.add(new Target(TYPE_SPLIT_LEFT, leftHitRegion, topOrLeftBounds));
+ mTargets.add(new Target(TYPE_SPLIT_RIGHT, rightHitRegion, bottomOrRightBounds));
} else {
final Rect topHitRegion = new Rect();
- final Rect topDrawRegion = topOrLeftBounds;
final Rect bottomHitRegion = new Rect();
- final Rect bottomDrawRegion = bottomOrRightBounds;
// If we have existing split regions use those bounds, otherwise split it 50/50
if (inSplitScreen) {
- // Add the divider bounds to each side since that counts for the hit region.
- topHitRegion.set(topOrLeftBounds);
- topHitRegion.bottom += dividerWidth / 2;
- bottomHitRegion.set(bottomOrRightBounds);
- bottomHitRegion.top -= dividerWidth / 2;
+ // The bounds of the existing split will have a divider bar, the hit region
+ // should include that space. Find the center of the divider bar:
+ float centerX = topOrLeftBounds.bottom + (dividerWidth / 2);
+ // Now set the hit regions using that center.
+ topHitRegion.set(displayRegion);
+ topHitRegion.bottom = (int) centerX;
+ bottomHitRegion.set(displayRegion);
+ bottomHitRegion.top = (int) centerX;
} else {
displayRegion.splitHorizontally(topHitRegion, bottomHitRegion);
}
- mTargets.add(new Target(TYPE_SPLIT_TOP, topHitRegion, topDrawRegion));
- mTargets.add(new Target(TYPE_SPLIT_BOTTOM, bottomHitRegion, bottomDrawRegion));
+ mTargets.add(new Target(TYPE_SPLIT_TOP, topHitRegion, topOrLeftBounds));
+ mTargets.add(new Target(TYPE_SPLIT_BOTTOM, bottomHitRegion, bottomOrRightBounds));
}
} else {
// Split-screen not allowed, so only show the fullscreen target
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
index fd3be2b11c15..d44db498451e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragLayout.java
@@ -24,7 +24,6 @@ import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSIT
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
-import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
@@ -156,10 +155,6 @@ public class DragLayout extends LinearLayout {
}
}
- public boolean hasDropTarget() {
- return mCurrentTarget != null;
- }
-
public boolean hasDropped() {
return mHasDropped;
}
@@ -271,6 +266,9 @@ public class DragLayout extends LinearLayout {
* Updates the visible drop target as the user drags.
*/
public void update(DragEvent event) {
+ if (mHasDropped) {
+ return;
+ }
// Find containing region, if the same as mCurrentRegion, then skip, otherwise, animate the
// visibility of the current region
DragAndDropPolicy.Target target = mPolicy.getTargetAtLocation(
@@ -286,7 +284,8 @@ public class DragLayout extends LinearLayout {
animateHighlight(target);
} else {
// Switching between targets
- animateHighlight(target);
+ mDropZoneView1.animateSwitch();
+ mDropZoneView2.animateSwitch();
}
mCurrentTarget = target;
}
@@ -323,7 +322,7 @@ public class DragLayout extends LinearLayout {
: DISABLE_NONE);
mDropZoneView1.setShowingMargin(visible);
mDropZoneView2.setShowingMargin(visible);
- ObjectAnimator animator = mDropZoneView1.getAnimator();
+ Animator animator = mDropZoneView1.getAnimator();
if (animCompleteCallback != null) {
if (animator != null) {
animator.addListener(new AnimatorListenerAdapter() {
@@ -343,17 +342,11 @@ public class DragLayout extends LinearLayout {
if (target.type == DragAndDropPolicy.Target.TYPE_SPLIT_LEFT
|| target.type == DragAndDropPolicy.Target.TYPE_SPLIT_TOP) {
mDropZoneView1.setShowingHighlight(true);
- mDropZoneView1.setShowingSplash(false);
-
mDropZoneView2.setShowingHighlight(false);
- mDropZoneView2.setShowingSplash(true);
} else if (target.type == DragAndDropPolicy.Target.TYPE_SPLIT_RIGHT
|| target.type == DragAndDropPolicy.Target.TYPE_SPLIT_BOTTOM) {
mDropZoneView1.setShowingHighlight(false);
- mDropZoneView1.setShowingSplash(true);
-
mDropZoneView2.setShowingHighlight(true);
- mDropZoneView2.setShowingSplash(false);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DropZoneView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DropZoneView.java
index 2f47af57d496..a3ee8aed204d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DropZoneView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DropZoneView.java
@@ -18,6 +18,7 @@ package com.android.wm.shell.draganddrop;
import static com.android.wm.shell.animation.Interpolators.FAST_OUT_SLOW_IN;
+import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
@@ -27,7 +28,6 @@ import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.FloatProperty;
-import android.util.IntProperty;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
@@ -43,8 +43,8 @@ import com.android.wm.shell.R;
*/
public class DropZoneView extends FrameLayout {
- private static final int SPLASHSCREEN_ALPHA_INT = (int) (255 * 0.90f);
- private static final int HIGHLIGHT_ALPHA_INT = 255;
+ private static final float SPLASHSCREEN_ALPHA = 0.90f;
+ private static final float HIGHLIGHT_ALPHA = 1f;
private static final int MARGIN_ANIMATION_ENTER_DURATION = 400;
private static final int MARGIN_ANIMATION_EXIT_DURATION = 250;
@@ -61,54 +61,27 @@ public class DropZoneView extends FrameLayout {
}
};
- private static final IntProperty<ColorDrawable> SPLASHSCREEN_ALPHA =
- new IntProperty<ColorDrawable>("splashscreen") {
- @Override
- public void setValue(ColorDrawable d, int alpha) {
- d.setAlpha(alpha);
- }
-
- @Override
- public Integer get(ColorDrawable d) {
- return d.getAlpha();
- }
- };
-
- private static final IntProperty<ColorDrawable> HIGHLIGHT_ALPHA =
- new IntProperty<ColorDrawable>("highlight") {
- @Override
- public void setValue(ColorDrawable d, int alpha) {
- d.setAlpha(alpha);
- }
-
- @Override
- public Integer get(ColorDrawable d) {
- return d.getAlpha();
- }
- };
-
private final Path mPath = new Path();
private final float[] mContainerMargin = new float[4];
private float mCornerRadius;
private float mBottomInset;
private int mMarginColor; // i.e. color used for negative space like the container insets
- private int mHighlightColor;
private boolean mShowingHighlight;
private boolean mShowingSplash;
private boolean mShowingMargin;
- // TODO: might be more seamless to animate between splash/highlight color instead of 2 separate
- private ObjectAnimator mSplashAnimator;
- private ObjectAnimator mHighlightAnimator;
+ private int mSplashScreenColor;
+ private int mHighlightColor;
+
+ private ObjectAnimator mBackgroundAnimator;
private ObjectAnimator mMarginAnimator;
private float mMarginPercent;
// Renders a highlight or neutral transparent color
- private ColorDrawable mDropZoneDrawable;
+ private ColorDrawable mColorDrawable;
// Renders the translucent splashscreen with the app icon in the middle
private ImageView mSplashScreenView;
- private ColorDrawable mSplashBackgroundDrawable;
// Renders the margin / insets around the dropzone container
private MarginView mMarginView;
@@ -130,19 +103,14 @@ public class DropZoneView extends FrameLayout {
mCornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context);
mMarginColor = getResources().getColor(R.color.taskbar_background);
- mHighlightColor = getResources().getColor(android.R.color.system_accent1_500);
-
- mDropZoneDrawable = new ColorDrawable();
- mDropZoneDrawable.setColor(mHighlightColor);
- mDropZoneDrawable.setAlpha(0);
- setBackgroundDrawable(mDropZoneDrawable);
+ int c = getResources().getColor(android.R.color.system_accent1_500);
+ mHighlightColor = Color.argb(HIGHLIGHT_ALPHA, Color.red(c), Color.green(c), Color.blue(c));
+ mSplashScreenColor = Color.argb(SPLASHSCREEN_ALPHA, 0, 0, 0);
+ mColorDrawable = new ColorDrawable();
+ setBackgroundDrawable(mColorDrawable);
mSplashScreenView = new ImageView(context);
mSplashScreenView.setScaleType(ImageView.ScaleType.CENTER);
- mSplashBackgroundDrawable = new ColorDrawable();
- mSplashBackgroundDrawable.setColor(Color.WHITE);
- mSplashBackgroundDrawable.setAlpha(SPLASHSCREEN_ALPHA_INT);
- mSplashScreenView.setBackgroundDrawable(mSplashBackgroundDrawable);
addView(mSplashScreenView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
mSplashScreenView.setAlpha(0f);
@@ -157,10 +125,6 @@ public class DropZoneView extends FrameLayout {
mMarginColor = getResources().getColor(R.color.taskbar_background);
mHighlightColor = getResources().getColor(android.R.color.system_accent1_500);
- final int alpha = mDropZoneDrawable.getAlpha();
- mDropZoneDrawable.setColor(mHighlightColor);
- mDropZoneDrawable.setAlpha(alpha);
-
if (mMarginPercent > 0) {
mMarginView.invalidate();
}
@@ -187,38 +151,39 @@ public class DropZoneView extends FrameLayout {
}
/** Sets the color and icon to use for the splashscreen when shown. */
- public void setAppInfo(int splashScreenColor, Drawable appIcon) {
- mSplashBackgroundDrawable.setColor(splashScreenColor);
+ public void setAppInfo(int color, Drawable appIcon) {
+ Color c = Color.valueOf(color);
+ mSplashScreenColor = Color.argb(SPLASHSCREEN_ALPHA, c.red(), c.green(), c.blue());
mSplashScreenView.setImageDrawable(appIcon);
}
/** @return an active animator for this view if one exists. */
@Nullable
- public ObjectAnimator getAnimator() {
+ public Animator getAnimator() {
if (mMarginAnimator != null && mMarginAnimator.isRunning()) {
return mMarginAnimator;
- } else if (mHighlightAnimator != null && mHighlightAnimator.isRunning()) {
- return mHighlightAnimator;
- } else if (mSplashAnimator != null && mSplashAnimator.isRunning()) {
- return mSplashAnimator;
+ } else if (mBackgroundAnimator != null && mBackgroundAnimator.isRunning()) {
+ return mBackgroundAnimator;
}
return null;
}
- /** Animates the splashscreen to show or hide. */
- public void setShowingSplash(boolean showingSplash) {
- if (mShowingSplash != showingSplash) {
- mShowingSplash = showingSplash;
- animateSplashToState();
- }
+ /** Animates between highlight and splashscreen depending on current state. */
+ public void animateSwitch() {
+ mShowingHighlight = !mShowingHighlight;
+ mShowingSplash = !mShowingHighlight;
+ final int newColor = mShowingHighlight ? mHighlightColor : mSplashScreenColor;
+ animateBackground(mColorDrawable.getColor(), newColor);
+ animateSplashScreenIcon();
}
/** Animates the highlight indicating the zone is hovered on or not. */
public void setShowingHighlight(boolean showingHighlight) {
- if (mShowingHighlight != showingHighlight) {
- mShowingHighlight = showingHighlight;
- animateHighlightToState();
- }
+ mShowingHighlight = showingHighlight;
+ mShowingSplash = !mShowingHighlight;
+ final int newColor = mShowingHighlight ? mHighlightColor : mSplashScreenColor;
+ animateBackground(Color.TRANSPARENT, newColor);
+ animateSplashScreenIcon();
}
/** Animates the margins around the drop zone to show or hide. */
@@ -228,38 +193,29 @@ public class DropZoneView extends FrameLayout {
animateMarginToState();
}
if (!mShowingMargin) {
- setShowingHighlight(false);
- setShowingSplash(false);
+ mShowingHighlight = false;
+ mShowingSplash = false;
+ animateBackground(mColorDrawable.getColor(), Color.TRANSPARENT);
+ animateSplashScreenIcon();
}
}
- private void animateSplashToState() {
- if (mSplashAnimator != null) {
- mSplashAnimator.cancel();
+ private void animateBackground(int startColor, int endColor) {
+ if (mBackgroundAnimator != null) {
+ mBackgroundAnimator.cancel();
}
- mSplashAnimator = ObjectAnimator.ofInt(mSplashBackgroundDrawable,
- SPLASHSCREEN_ALPHA,
- mSplashBackgroundDrawable.getAlpha(),
- mShowingSplash ? SPLASHSCREEN_ALPHA_INT : 0);
- if (!mShowingSplash) {
- mSplashAnimator.setInterpolator(FAST_OUT_SLOW_IN);
+ mBackgroundAnimator = ObjectAnimator.ofArgb(mColorDrawable,
+ "color",
+ startColor,
+ endColor);
+ if (!mShowingSplash && !mShowingHighlight) {
+ mBackgroundAnimator.setInterpolator(FAST_OUT_SLOW_IN);
}
- mSplashAnimator.start();
- mSplashScreenView.animate().alpha(mShowingSplash ? 1f : 0f).start();
+ mBackgroundAnimator.start();
}
- private void animateHighlightToState() {
- if (mHighlightAnimator != null) {
- mHighlightAnimator.cancel();
- }
- mHighlightAnimator = ObjectAnimator.ofInt(mDropZoneDrawable,
- HIGHLIGHT_ALPHA,
- mDropZoneDrawable.getAlpha(),
- mShowingHighlight ? HIGHLIGHT_ALPHA_INT : 0);
- if (!mShowingHighlight) {
- mHighlightAnimator.setInterpolator(FAST_OUT_SLOW_IN);
- }
- mHighlightAnimator.start();
+ private void animateSplashScreenIcon() {
+ mSplashScreenView.animate().alpha(mShowingSplash ? 1f : 0f).start();
}
private void animateMarginToState() {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
index 825320b4e784..a6caefe6d3e7 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/ShellTaskOrganizerTests.java
@@ -363,6 +363,45 @@ public class ShellTaskOrganizerTests {
}
@Test
+ public void testOnEligibleForLetterboxEducationActivityChanged() {
+ final RunningTaskInfo taskInfo1 = createTaskInfo(12, WINDOWING_MODE_FULLSCREEN);
+ taskInfo1.displayId = DEFAULT_DISPLAY;
+ taskInfo1.topActivityEligibleForLetterboxEducation = false;
+ final TrackingTaskListener taskListener = new TrackingTaskListener();
+ mOrganizer.addListenerForType(taskListener, TASK_LISTENER_TYPE_FULLSCREEN);
+ mOrganizer.onTaskAppeared(taskInfo1, null);
+
+ // Task listener sent to compat UI is null if top activity isn't eligible for letterbox
+ // education.
+ verify(mCompatUI).onCompatInfoChanged(taskInfo1, null /* taskListener */);
+
+ // Task listener is non-null if top activity is eligible for letterbox education and task
+ // is visible.
+ clearInvocations(mCompatUI);
+ final RunningTaskInfo taskInfo2 =
+ createTaskInfo(taskInfo1.taskId, WINDOWING_MODE_FULLSCREEN);
+ taskInfo2.displayId = taskInfo1.displayId;
+ taskInfo2.topActivityEligibleForLetterboxEducation = true;
+ taskInfo2.isVisible = true;
+ mOrganizer.onTaskInfoChanged(taskInfo2);
+ verify(mCompatUI).onCompatInfoChanged(taskInfo2, taskListener);
+
+ // Task listener is null if task is invisible.
+ clearInvocations(mCompatUI);
+ final RunningTaskInfo taskInfo3 =
+ createTaskInfo(taskInfo1.taskId, WINDOWING_MODE_FULLSCREEN);
+ taskInfo3.displayId = taskInfo1.displayId;
+ taskInfo3.topActivityEligibleForLetterboxEducation = true;
+ taskInfo3.isVisible = false;
+ mOrganizer.onTaskInfoChanged(taskInfo3);
+ verify(mCompatUI).onCompatInfoChanged(taskInfo3, null /* taskListener */);
+
+ clearInvocations(mCompatUI);
+ mOrganizer.onTaskVanished(taskInfo1);
+ verify(mCompatUI).onCompatInfoChanged(taskInfo1, null /* taskListener */);
+ }
+
+ @Test
public void testOnCameraCompatActivityChanged() {
final RunningTaskInfo taskInfo1 = createTaskInfo(1, WINDOWING_MODE_FULLSCREEN);
taskInfo1.displayId = DEFAULT_DISPLAY;
@@ -375,7 +414,7 @@ public class ShellTaskOrganizerTests {
// compat control.
verify(mCompatUI).onCompatInfoChanged(taskInfo1, null /* taskListener */);
- // Task linster is non-null when request a camera compat control for a visible task.
+ // Task listener is non-null when request a camera compat control for a visible task.
clearInvocations(mCompatUI);
final RunningTaskInfo taskInfo2 =
createTaskInfo(taskInfo1.taskId, taskInfo1.getWindowingMode());
diff --git a/libs/hwui/HardwareBitmapUploader.cpp b/libs/hwui/HardwareBitmapUploader.cpp
index db3a1081e32c..dd272cd5ff7d 100644
--- a/libs/hwui/HardwareBitmapUploader.cpp
+++ b/libs/hwui/HardwareBitmapUploader.cpp
@@ -287,29 +287,29 @@ private:
std::mutex mVkLock;
};
-bool HardwareBitmapUploader::hasFP16Support() {
- static std::once_flag sOnce;
- static bool hasFP16Support = false;
-
- // Gralloc shouldn't let us create a USAGE_HW_TEXTURE if GLES is unable to consume it, so
- // we don't need to double-check the GLES version/extension.
- std::call_once(sOnce, []() {
- AHardwareBuffer_Desc desc = {
- .width = 1,
- .height = 1,
- .layers = 1,
- .format = AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT,
- .usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER |
- AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER |
- AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE,
- };
- UniqueAHardwareBuffer buffer = allocateAHardwareBuffer(desc);
- hasFP16Support = buffer != nullptr;
- });
+static bool checkSupport(AHardwareBuffer_Format format) {
+ AHardwareBuffer_Desc desc = {
+ .width = 1,
+ .height = 1,
+ .layers = 1,
+ .format = format,
+ .usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER | AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER |
+ AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE,
+ };
+ UniqueAHardwareBuffer buffer = allocateAHardwareBuffer(desc);
+ return buffer != nullptr;
+}
+bool HardwareBitmapUploader::hasFP16Support() {
+ static bool hasFP16Support = checkSupport(AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT);
return hasFP16Support;
}
+bool HardwareBitmapUploader::has1010102Support() {
+ static bool has101012Support = checkSupport(AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM);
+ return has101012Support;
+}
+
static FormatInfo determineFormat(const SkBitmap& skBitmap, bool usingGL) {
FormatInfo formatInfo;
switch (skBitmap.info().colorType()) {
@@ -350,6 +350,19 @@ static FormatInfo determineFormat(const SkBitmap& skBitmap, bool usingGL) {
formatInfo.type = GL_UNSIGNED_BYTE;
formatInfo.vkFormat = VK_FORMAT_R8G8B8A8_UNORM;
break;
+ case kRGBA_1010102_SkColorType:
+ formatInfo.isSupported = HardwareBitmapUploader::has1010102Support();
+ if (formatInfo.isSupported) {
+ formatInfo.type = GL_UNSIGNED_INT_2_10_10_10_REV;
+ formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM;
+ formatInfo.vkFormat = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
+ } else {
+ formatInfo.type = GL_UNSIGNED_BYTE;
+ formatInfo.bufferFormat = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
+ formatInfo.vkFormat = VK_FORMAT_R8G8B8A8_UNORM;
+ }
+ formatInfo.format = GL_RGBA;
+ break;
default:
ALOGW("unable to create hardware bitmap of colortype: %d", skBitmap.info().colorType());
formatInfo.valid = false;
diff --git a/libs/hwui/HardwareBitmapUploader.h b/libs/hwui/HardwareBitmapUploader.h
index ad7a95a4fa03..34f43cd8a198 100644
--- a/libs/hwui/HardwareBitmapUploader.h
+++ b/libs/hwui/HardwareBitmapUploader.h
@@ -29,10 +29,12 @@ public:
#ifdef __ANDROID__
static bool hasFP16Support();
+ static bool has1010102Support();
#else
static bool hasFP16Support() {
return true;
}
+ static bool has1010102Support() { return true; }
#endif
};
diff --git a/libs/hwui/apex/android_bitmap.cpp b/libs/hwui/apex/android_bitmap.cpp
index 3780ba072308..bc6bc456ba5a 100644
--- a/libs/hwui/apex/android_bitmap.cpp
+++ b/libs/hwui/apex/android_bitmap.cpp
@@ -57,6 +57,8 @@ static AndroidBitmapFormat getFormat(const SkImageInfo& info) {
return ANDROID_BITMAP_FORMAT_A_8;
case kRGBA_F16_SkColorType:
return ANDROID_BITMAP_FORMAT_RGBA_F16;
+ case kRGBA_1010102_SkColorType:
+ return ANDROID_BITMAP_FORMAT_RGBA_1010102;
default:
return ANDROID_BITMAP_FORMAT_NONE;
}
@@ -74,6 +76,8 @@ static SkColorType getColorType(AndroidBitmapFormat format) {
return kAlpha_8_SkColorType;
case ANDROID_BITMAP_FORMAT_RGBA_F16:
return kRGBA_F16_SkColorType;
+ case ANDROID_BITMAP_FORMAT_RGBA_1010102:
+ return kRGBA_1010102_SkColorType;
default:
return kUnknown_SkColorType;
}
@@ -249,6 +253,9 @@ int ABitmap_compress(const AndroidBitmapInfo* info, ADataSpace dataSpace, const
case ANDROID_BITMAP_FORMAT_RGBA_F16:
colorType = kRGBA_F16_SkColorType;
break;
+ case ANDROID_BITMAP_FORMAT_RGBA_1010102:
+ colorType = kRGBA_1010102_SkColorType;
+ break;
default:
return ANDROID_BITMAP_RESULT_BAD_PARAMETER;
}
diff --git a/libs/hwui/hwui/ImageDecoder.cpp b/libs/hwui/hwui/ImageDecoder.cpp
index fc542c81a597..dd68f825b61d 100644
--- a/libs/hwui/hwui/ImageDecoder.cpp
+++ b/libs/hwui/hwui/ImageDecoder.cpp
@@ -159,6 +159,8 @@ bool ImageDecoder::setOutColorType(SkColorType colorType) {
break;
case kRGBA_F16_SkColorType:
break;
+ case kRGBA_1010102_SkColorType:
+ break;
default:
return false;
}
diff --git a/libs/hwui/jni/BitmapRegionDecoder.cpp b/libs/hwui/jni/BitmapRegionDecoder.cpp
index 4cc05ef6f13b..1c20415dcc8f 100644
--- a/libs/hwui/jni/BitmapRegionDecoder.cpp
+++ b/libs/hwui/jni/BitmapRegionDecoder.cpp
@@ -137,9 +137,16 @@ static jobject nativeDecodeRegion(JNIEnv* env, jobject, jlong brdHandle, jint in
auto* brd = reinterpret_cast<skia::BitmapRegionDecoder*>(brdHandle);
SkColorType decodeColorType = brd->computeOutputColorType(colorType);
- if (decodeColorType == kRGBA_F16_SkColorType && isHardware &&
+
+ if (isHardware) {
+ if (decodeColorType == kRGBA_F16_SkColorType &&
!uirenderer::HardwareBitmapUploader::hasFP16Support()) {
- decodeColorType = kN32_SkColorType;
+ decodeColorType = kN32_SkColorType;
+ }
+ if (decodeColorType == kRGBA_1010102_SkColorType &&
+ !uirenderer::HardwareBitmapUploader::has1010102Support()) {
+ decodeColorType = kN32_SkColorType;
+ }
}
// Set up the pixel allocator
diff --git a/libs/hwui/jni/Graphics.cpp b/libs/hwui/jni/Graphics.cpp
index 77f46beb2100..33669ac0a34e 100644
--- a/libs/hwui/jni/Graphics.cpp
+++ b/libs/hwui/jni/Graphics.cpp
@@ -365,6 +365,8 @@ jint GraphicsJNI::colorTypeToLegacyBitmapConfig(SkColorType colorType) {
return kRGB_565_LegacyBitmapConfig;
case kAlpha_8_SkColorType:
return kA8_LegacyBitmapConfig;
+ case kRGBA_1010102_SkColorType:
+ return kRGBA_1010102_LegacyBitmapConfig;
case kUnknown_SkColorType:
default:
break;
@@ -374,14 +376,10 @@ jint GraphicsJNI::colorTypeToLegacyBitmapConfig(SkColorType colorType) {
SkColorType GraphicsJNI::legacyBitmapConfigToColorType(jint legacyConfig) {
const uint8_t gConfig2ColorType[] = {
- kUnknown_SkColorType,
- kAlpha_8_SkColorType,
- kUnknown_SkColorType, // Previously kIndex_8_SkColorType,
- kRGB_565_SkColorType,
- kARGB_4444_SkColorType,
- kN32_SkColorType,
- kRGBA_F16_SkColorType,
- kN32_SkColorType
+ kUnknown_SkColorType, kAlpha_8_SkColorType,
+ kUnknown_SkColorType, // Previously kIndex_8_SkColorType,
+ kRGB_565_SkColorType, kARGB_4444_SkColorType, kN32_SkColorType,
+ kRGBA_F16_SkColorType, kN32_SkColorType, kRGBA_1010102_SkColorType,
};
if (legacyConfig < 0 || legacyConfig > kLastEnum_LegacyBitmapConfig) {
@@ -399,15 +397,12 @@ AndroidBitmapFormat GraphicsJNI::getFormatFromConfig(JNIEnv* env, jobject jconfi
jint javaConfigId = env->GetIntField(jconfig, gBitmapConfig_nativeInstanceID);
const AndroidBitmapFormat config2BitmapFormat[] = {
- ANDROID_BITMAP_FORMAT_NONE,
- ANDROID_BITMAP_FORMAT_A_8,
- ANDROID_BITMAP_FORMAT_NONE, // Previously Config.Index_8
- ANDROID_BITMAP_FORMAT_RGB_565,
- ANDROID_BITMAP_FORMAT_RGBA_4444,
- ANDROID_BITMAP_FORMAT_RGBA_8888,
- ANDROID_BITMAP_FORMAT_RGBA_F16,
- ANDROID_BITMAP_FORMAT_NONE // Congfig.HARDWARE
- };
+ ANDROID_BITMAP_FORMAT_NONE, ANDROID_BITMAP_FORMAT_A_8,
+ ANDROID_BITMAP_FORMAT_NONE, // Previously Config.Index_8
+ ANDROID_BITMAP_FORMAT_RGB_565, ANDROID_BITMAP_FORMAT_RGBA_4444,
+ ANDROID_BITMAP_FORMAT_RGBA_8888, ANDROID_BITMAP_FORMAT_RGBA_F16,
+ ANDROID_BITMAP_FORMAT_NONE, // Congfig.HARDWARE
+ ANDROID_BITMAP_FORMAT_RGBA_1010102};
return config2BitmapFormat[javaConfigId];
}
@@ -430,6 +425,9 @@ jobject GraphicsJNI::getConfigFromFormat(JNIEnv* env, AndroidBitmapFormat format
case ANDROID_BITMAP_FORMAT_RGBA_F16:
configId = kRGBA_16F_LegacyBitmapConfig;
break;
+ case ANDROID_BITMAP_FORMAT_RGBA_1010102:
+ configId = kRGBA_1010102_LegacyBitmapConfig;
+ break;
default:
break;
}
diff --git a/libs/hwui/jni/GraphicsJNI.h b/libs/hwui/jni/GraphicsJNI.h
index ba407f2164de..085a905abaf8 100644
--- a/libs/hwui/jni/GraphicsJNI.h
+++ b/libs/hwui/jni/GraphicsJNI.h
@@ -34,16 +34,17 @@ public:
// This enum must keep these int values, to match the int values
// in the java Bitmap.Config enum.
enum LegacyBitmapConfig {
- kNo_LegacyBitmapConfig = 0,
- kA8_LegacyBitmapConfig = 1,
- kIndex8_LegacyBitmapConfig = 2,
- kRGB_565_LegacyBitmapConfig = 3,
- kARGB_4444_LegacyBitmapConfig = 4,
- kARGB_8888_LegacyBitmapConfig = 5,
- kRGBA_16F_LegacyBitmapConfig = 6,
- kHardware_LegacyBitmapConfig = 7,
-
- kLastEnum_LegacyBitmapConfig = kHardware_LegacyBitmapConfig
+ kNo_LegacyBitmapConfig = 0,
+ kA8_LegacyBitmapConfig = 1,
+ kIndex8_LegacyBitmapConfig = 2,
+ kRGB_565_LegacyBitmapConfig = 3,
+ kARGB_4444_LegacyBitmapConfig = 4,
+ kARGB_8888_LegacyBitmapConfig = 5,
+ kRGBA_16F_LegacyBitmapConfig = 6,
+ kHardware_LegacyBitmapConfig = 7,
+ kRGBA_1010102_LegacyBitmapConfig = 8,
+
+ kLastEnum_LegacyBitmapConfig = kRGBA_1010102_LegacyBitmapConfig
};
static void setJavaVM(JavaVM* javaVM);
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index 8ad8abcff2ed..25ed935b7a76 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -16,19 +16,18 @@
#ifndef DRAWFRAMETASK_H
#define DRAWFRAMETASK_H
-#include <optional>
-#include <vector>
-
-#include <performance_hint_private.h>
+#include <android/performance_hint.h>
#include <utils/Condition.h>
#include <utils/Mutex.h>
#include <utils/StrongPointer.h>
-#include "RenderTask.h"
+#include <optional>
+#include <vector>
#include "../FrameInfo.h"
#include "../Rect.h"
#include "../TreeInfo.h"
+#include "RenderTask.h"
namespace android {
namespace uirenderer {
diff --git a/location/java/android/location/LastLocationRequest.java b/location/java/android/location/LastLocationRequest.java
index 73c5c826584f..fe0a14f37cb6 100644
--- a/location/java/android/location/LastLocationRequest.java
+++ b/location/java/android/location/LastLocationRequest.java
@@ -16,6 +16,9 @@
package android.location;
+import static android.Manifest.permission.LOCATION_BYPASS;
+import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
+
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
@@ -220,8 +223,9 @@ public final class LastLocationRequest implements Parcelable {
*
* @hide
*/
+ // TODO: remove WRITE_SECURE_SETTINGS.
@SystemApi
- @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+ @RequiresPermission(anyOf = {WRITE_SECURE_SETTINGS, LOCATION_BYPASS})
public @NonNull LastLocationRequest.Builder setAdasGnssBypass(boolean adasGnssBypass) {
mAdasGnssBypass = adasGnssBypass;
return this;
@@ -238,8 +242,9 @@ public final class LastLocationRequest implements Parcelable {
*
* @hide
*/
+ // TODO: remove WRITE_SECURE_SETTINGS.
@SystemApi
- @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+ @RequiresPermission(anyOf = {WRITE_SECURE_SETTINGS, LOCATION_BYPASS})
public @NonNull Builder setLocationSettingsIgnored(boolean locationSettingsIgnored) {
mLocationSettingsIgnored = locationSettingsIgnored;
return this;
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index d275628f6e24..59c989b7f01e 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -18,6 +18,7 @@ package android.location;
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static android.Manifest.permission.LOCATION_BYPASS;
import static android.Manifest.permission.LOCATION_HARDWARE;
import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
import static android.location.LocationRequest.createFromDeprecatedCriteria;
@@ -678,8 +679,9 @@ public class LocationManager {
*
* @hide
*/
+ // TODO: remove WRITE_SECURE_SETTINGS.
@SystemApi
- @RequiresPermission(WRITE_SECURE_SETTINGS)
+ @RequiresPermission(anyOf = {WRITE_SECURE_SETTINGS, LOCATION_BYPASS})
public void setAdasGnssLocationEnabled(boolean enabled) {
try {
mService.setAdasGnssLocationEnabledForUser(enabled, mContext.getUser().getIdentifier());
diff --git a/location/java/android/location/LocationRequest.java b/location/java/android/location/LocationRequest.java
index 587222a4df43..59f4f5e8c19e 100644
--- a/location/java/android/location/LocationRequest.java
+++ b/location/java/android/location/LocationRequest.java
@@ -16,6 +16,9 @@
package android.location;
+import static android.Manifest.permission.LOCATION_BYPASS;
+import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
+
import static java.lang.Math.max;
import static java.lang.Math.min;
@@ -662,9 +665,10 @@ public final class LocationRequest implements Parcelable {
* @hide
* @deprecated LocationRequests should be treated as immutable.
*/
+ // TODO: remove WRITE_SECURE_SETTINGS.
@SystemApi
@Deprecated
- @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+ @RequiresPermission(anyOf = {WRITE_SECURE_SETTINGS, LOCATION_BYPASS})
public @NonNull LocationRequest setLocationSettingsIgnored(boolean locationSettingsIgnored) {
mBypass = locationSettingsIgnored;
return this;
@@ -1132,8 +1136,9 @@ public final class LocationRequest implements Parcelable {
*
* @hide
*/
+ // TODO: remove WRITE_SECURE_SETTINGS
@SystemApi
- @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+ @RequiresPermission(anyOf = {WRITE_SECURE_SETTINGS, LOCATION_BYPASS})
public @NonNull Builder setAdasGnssBypass(boolean adasGnssBypass) {
mAdasGnssBypass = adasGnssBypass;
return this;
@@ -1150,8 +1155,9 @@ public final class LocationRequest implements Parcelable {
*
* @hide
*/
+ // TODO: remove WRITE_SECURE_SETTINGS
@SystemApi
- @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
+ @RequiresPermission(anyOf = {WRITE_SECURE_SETTINGS, LOCATION_BYPASS})
public @NonNull Builder setLocationSettingsIgnored(boolean locationSettingsIgnored) {
mBypass = locationSettingsIgnored;
return this;
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index a2704f9a67fd..1b4c0bc64f78 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -181,6 +181,22 @@ public class AudioManager {
public static final String VOLUME_CHANGED_ACTION = "android.media.VOLUME_CHANGED_ACTION";
/**
+ * @hide Broadcast intent when the volume for a particular stream type changes.
+ * Includes the stream, the new volume and previous volumes.
+ * Notes:
+ * - for internal platform use only, do not make public,
+ * - never used for "remote" volume changes
+ *
+ * @see #EXTRA_VOLUME_STREAM_TYPE
+ * @see #EXTRA_VOLUME_STREAM_VALUE
+ * @see #EXTRA_PREV_VOLUME_STREAM_VALUE
+ */
+ @SystemApi
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ @SuppressLint("ActionValue")
+ public static final String ACTION_VOLUME_CHANGED = "android.media.VOLUME_CHANGED_ACTION";
+
+ /**
* @hide Broadcast intent when the devices for a particular stream type changes.
* Includes the stream, the new devices and previous devices.
* Notes:
@@ -244,7 +260,8 @@ public class AudioManager {
/**
* @hide The stream type for the volume changed intent.
*/
- @UnsupportedAppUsage
+ @SystemApi
+ @SuppressLint("ActionValue")
public static final String EXTRA_VOLUME_STREAM_TYPE = "android.media.EXTRA_VOLUME_STREAM_TYPE";
/**
@@ -261,7 +278,8 @@ public class AudioManager {
/**
* @hide The volume associated with the stream for the volume changed intent.
*/
- @UnsupportedAppUsage
+ @SystemApi
+ @SuppressLint("ActionValue")
public static final String EXTRA_VOLUME_STREAM_VALUE =
"android.media.EXTRA_VOLUME_STREAM_VALUE";
@@ -368,7 +386,7 @@ public class AudioManager {
public static final int STREAM_NOTIFICATION = AudioSystem.STREAM_NOTIFICATION;
/** @hide Used to identify the volume of audio streams for phone calls when connected
* to bluetooth */
- @UnsupportedAppUsage
+ @SystemApi
public static final int STREAM_BLUETOOTH_SCO = AudioSystem.STREAM_BLUETOOTH_SCO;
/** @hide Used to identify the volume of audio streams for enforced system sounds
* in certain countries (e.g camera in Japan) */
diff --git a/media/java/android/media/IMediaRouter2Manager.aidl b/media/java/android/media/IMediaRouter2Manager.aidl
index 5113dc2058e0..71dc2a781ba9 100644
--- a/media/java/android/media/IMediaRouter2Manager.aidl
+++ b/media/java/android/media/IMediaRouter2Manager.aidl
@@ -18,6 +18,7 @@ package android.media;
import android.media.MediaRoute2ProviderInfo;
import android.media.MediaRoute2Info;
+import android.media.RouteDiscoveryPreference;
import android.media.RoutingSessionInfo;
/**
@@ -27,7 +28,8 @@ oneway interface IMediaRouter2Manager {
void notifySessionCreated(int requestId, in RoutingSessionInfo session);
void notifySessionUpdated(in RoutingSessionInfo session);
void notifySessionReleased(in RoutingSessionInfo session);
- void notifyPreferredFeaturesChanged(String packageName, in List<String> preferredFeatures);
+ void notifyDiscoveryPreferenceChanged(String packageName,
+ in RouteDiscoveryPreference discoveryPreference);
void notifyRoutesAdded(in List<MediaRoute2Info> routes);
void notifyRoutesRemoved(in List<MediaRoute2Info> routes);
void notifyRoutesChanged(in List<MediaRoute2Info> routes);
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index 2427fa64562d..ee0293d629b1 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -34,6 +34,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
/**
* Describes the properties of a route.
@@ -340,10 +341,12 @@ public final class MediaRoute2Info implements Parcelable {
@ConnectionState
final int mConnectionState;
final String mClientPackageName;
+ final String mPackageName;
final int mVolumeHandling;
final int mVolumeMax;
final int mVolume;
final String mAddress;
+ final Set<String> mDeduplicationIds;
final Bundle mExtras;
final String mProviderId;
@@ -357,10 +360,12 @@ public final class MediaRoute2Info implements Parcelable {
mDescription = builder.mDescription;
mConnectionState = builder.mConnectionState;
mClientPackageName = builder.mClientPackageName;
+ mPackageName = builder.mPackageName;
mVolumeHandling = builder.mVolumeHandling;
mVolumeMax = builder.mVolumeMax;
mVolume = builder.mVolume;
mAddress = builder.mAddress;
+ mDeduplicationIds = builder.mDeduplicationIds;
mExtras = builder.mExtras;
mProviderId = builder.mProviderId;
}
@@ -375,10 +380,12 @@ public final class MediaRoute2Info implements Parcelable {
mDescription = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
mConnectionState = in.readInt();
mClientPackageName = in.readString();
+ mPackageName = in.readString();
mVolumeHandling = in.readInt();
mVolumeMax = in.readInt();
mVolume = in.readInt();
mAddress = in.readString();
+ mDeduplicationIds = Set.of(in.readStringArray());
mExtras = in.readBundle();
mProviderId = in.readString();
}
@@ -486,6 +493,17 @@ public final class MediaRoute2Info implements Parcelable {
}
/**
+ * Gets the package name of the provider that published the route.
+ * <p>
+ * It is set by the system service.
+ * @hide
+ */
+ @Nullable
+ public String getPackageName() {
+ return mPackageName;
+ }
+
+ /**
* Gets information about how volume is handled on the route.
*
* @return {@link #PLAYBACK_VOLUME_FIXED} or {@link #PLAYBACK_VOLUME_VARIABLE}
@@ -518,6 +536,18 @@ public final class MediaRoute2Info implements Parcelable {
return mAddress;
}
+ /**
+ * Gets the Deduplication ID of the route if available.
+ * @see RouteDiscoveryPreference#shouldRemoveDuplicates()
+ */
+ @NonNull
+ public Set<String> getDeduplicationIds() {
+ return mDeduplicationIds;
+ }
+
+ /**
+ * Gets an optional bundle with extra data.
+ */
@Nullable
public Bundle getExtras() {
return mExtras == null ? null : new Bundle(mExtras);
@@ -549,7 +579,7 @@ public final class MediaRoute2Info implements Parcelable {
* Returns if the route has at least one of the specified route features.
*
* @param features the list of route features to consider
- * @return true if the route has at least one feature in the list
+ * @return {@code true} if the route has at least one feature in the list
* @hide
*/
public boolean hasAnyFeatures(@NonNull Collection<String> features) {
@@ -563,6 +593,21 @@ public final class MediaRoute2Info implements Parcelable {
}
/**
+ * Returns if the route has all the specified route features.
+ *
+ * @hide
+ */
+ public boolean hasAllFeatures(@NonNull Collection<String> features) {
+ Objects.requireNonNull(features, "features must not be null");
+ for (String feature : features) {
+ if (!getFeatures().contains(feature)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
* Returns true if the route info has all of the required field.
* A route is valid if and only if it is obtained from
* {@link com.android.server.media.MediaRouterService}.
@@ -596,10 +641,12 @@ public final class MediaRoute2Info implements Parcelable {
&& Objects.equals(mDescription, other.mDescription)
&& (mConnectionState == other.mConnectionState)
&& Objects.equals(mClientPackageName, other.mClientPackageName)
+ && Objects.equals(mPackageName, other.mPackageName)
&& (mVolumeHandling == other.mVolumeHandling)
&& (mVolumeMax == other.mVolumeMax)
&& (mVolume == other.mVolume)
&& Objects.equals(mAddress, other.mAddress)
+ && Objects.equals(mDeduplicationIds, other.mDeduplicationIds)
&& Objects.equals(mProviderId, other.mProviderId);
}
@@ -607,8 +654,8 @@ public final class MediaRoute2Info implements Parcelable {
public int hashCode() {
// Note: mExtras is not included.
return Objects.hash(mId, mName, mFeatures, mType, mIsSystem, mIconUri, mDescription,
- mConnectionState, mClientPackageName, mVolumeHandling, mVolumeMax, mVolume,
- mAddress, mProviderId);
+ mConnectionState, mClientPackageName, mPackageName, mVolumeHandling, mVolumeMax,
+ mVolume, mAddress, mDeduplicationIds, mProviderId);
}
@Override
@@ -626,6 +673,7 @@ public final class MediaRoute2Info implements Parcelable {
.append(", volumeHandling=").append(getVolumeHandling())
.append(", volumeMax=").append(getVolumeMax())
.append(", volume=").append(getVolume())
+ .append(", deduplicationIds=").append(String.join(",", getDeduplicationIds()))
.append(", providerId=").append(getProviderId())
.append(" }");
return result.toString();
@@ -647,10 +695,12 @@ public final class MediaRoute2Info implements Parcelable {
TextUtils.writeToParcel(mDescription, dest, flags);
dest.writeInt(mConnectionState);
dest.writeString(mClientPackageName);
+ dest.writeString(mPackageName);
dest.writeInt(mVolumeHandling);
dest.writeInt(mVolumeMax);
dest.writeInt(mVolume);
dest.writeString(mAddress);
+ dest.writeStringArray(mDeduplicationIds.toArray(new String[mDeduplicationIds.size()]));
dest.writeBundle(mExtras);
dest.writeString(mProviderId);
}
@@ -671,10 +721,12 @@ public final class MediaRoute2Info implements Parcelable {
@ConnectionState
int mConnectionState;
String mClientPackageName;
+ String mPackageName;
int mVolumeHandling = PLAYBACK_VOLUME_FIXED;
int mVolumeMax;
int mVolume;
String mAddress;
+ Set<String> mDeduplicationIds;
Bundle mExtras;
String mProviderId;
@@ -698,6 +750,7 @@ public final class MediaRoute2Info implements Parcelable {
mId = id;
mName = name;
mFeatures = new ArrayList<>();
+ mDeduplicationIds = Set.of();
}
/**
@@ -733,10 +786,12 @@ public final class MediaRoute2Info implements Parcelable {
mDescription = routeInfo.mDescription;
mConnectionState = routeInfo.mConnectionState;
mClientPackageName = routeInfo.mClientPackageName;
+ mPackageName = routeInfo.mPackageName;
mVolumeHandling = routeInfo.mVolumeHandling;
mVolumeMax = routeInfo.mVolumeMax;
mVolume = routeInfo.mVolume;
mAddress = routeInfo.mAddress;
+ mDeduplicationIds = Set.copyOf(routeInfo.mDeduplicationIds);
if (routeInfo.mExtras != null) {
mExtras = new Bundle(routeInfo.mExtras);
}
@@ -860,6 +915,16 @@ public final class MediaRoute2Info implements Parcelable {
}
/**
+ * Sets the package name of the route.
+ * @hide
+ */
+ @NonNull
+ public Builder setPackageName(@NonNull String packageName) {
+ mPackageName = packageName;
+ return this;
+ }
+
+ /**
* Sets the route's volume handling.
*/
@NonNull
@@ -897,6 +962,20 @@ public final class MediaRoute2Info implements Parcelable {
}
/**
+ * Sets the deduplication ID of the route.
+ * Routes have the same ID could be removed even when
+ * they are from different providers.
+ * <p>
+ * If it's {@code null}, the route will not be removed.
+ * @see RouteDiscoveryPreference#shouldRemoveDuplicates()
+ */
+ @NonNull
+ public Builder setDeduplicationIds(@NonNull Set<String> id) {
+ mDeduplicationIds = Set.copyOf(id);
+ return this;
+ }
+
+ /**
* Sets a bundle of extras for the route.
* <p>
* Note: The extras will not affect the result of {@link MediaRoute2Info#equals(Object)}.
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 4b32dbfc42f5..b485eb51380d 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -34,15 +34,18 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.text.TextUtils;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
@@ -302,8 +305,7 @@ public final class MediaRouter2 {
mSystemController = new SystemRoutingController(
ensureClientPackageNameForSystemSession(
sManager.getSystemRoutingSession(clientPackageName)));
- mDiscoveryPreference = new RouteDiscoveryPreference.Builder(
- sManager.getPreferredFeatures(clientPackageName), true).build();
+ mDiscoveryPreference = sManager.getDiscoveryPreference(clientPackageName);
updateAllRoutesFromManager();
// Only used by non-system MediaRouter2.
@@ -1060,11 +1062,48 @@ public final class MediaRouter2 {
.build();
}
+ private List<MediaRoute2Info> getSortedRoutes(List<MediaRoute2Info> routes,
+ RouteDiscoveryPreference preference) {
+ if (!preference.shouldRemoveDuplicates()) {
+ return routes;
+ }
+ Map<String, Integer> packagePriority = new ArrayMap<>();
+ int count = preference.getDeduplicationPackageOrder().size();
+ for (int i = 0; i < count; i++) {
+ // the last package will have 1 as the priority
+ packagePriority.put(preference.getDeduplicationPackageOrder().get(i), count - i);
+ }
+ ArrayList<MediaRoute2Info> sortedRoutes = new ArrayList<>(routes);
+ // take the negative for descending order
+ sortedRoutes.sort(Comparator.comparingInt(
+ r -> -packagePriority.getOrDefault(r.getPackageName(), 0)));
+ return sortedRoutes;
+ }
+
private List<MediaRoute2Info> filterRoutes(List<MediaRoute2Info> routes,
- RouteDiscoveryPreference discoveryRequest) {
- return routes.stream()
- .filter(route -> route.hasAnyFeatures(discoveryRequest.getPreferredFeatures()))
- .collect(Collectors.toList());
+ RouteDiscoveryPreference discoveryPreference) {
+
+ Set<String> deduplicationIdSet = new ArraySet<>();
+
+ List<MediaRoute2Info> filteredRoutes = new ArrayList<>();
+ for (MediaRoute2Info route : getSortedRoutes(routes, discoveryPreference)) {
+ if (!route.hasAllFeatures(discoveryPreference.getRequiredFeatures())
+ || !route.hasAnyFeatures(discoveryPreference.getPreferredFeatures())) {
+ continue;
+ }
+ if (!discoveryPreference.getAllowedPackages().isEmpty()
+ && !discoveryPreference.getAllowedPackages().contains(route.getPackageName())) {
+ continue;
+ }
+ if (discoveryPreference.shouldRemoveDuplicates()) {
+ if (Collections.disjoint(deduplicationIdSet, route.getDeduplicationIds())) {
+ continue;
+ }
+ deduplicationIdSet.addAll(route.getDeduplicationIds());
+ }
+ filteredRoutes.add(route);
+ }
+ return filteredRoutes;
}
private void updateAllRoutesFromManager() {
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index 83fa7c255f9f..8635c0ea762c 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -29,6 +29,8 @@ import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Log;
import com.android.internal.annotations.GuardedBy;
@@ -36,15 +38,18 @@ import com.android.internal.annotations.VisibleForTesting;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
@@ -84,7 +89,8 @@ public final class MediaRouter2Manager {
@GuardedBy("mRoutesLock")
private final Map<String, MediaRoute2Info> mRoutes = new HashMap<>();
@NonNull
- final ConcurrentMap<String, List<String>> mPreferredFeaturesMap = new ConcurrentHashMap<>();
+ final ConcurrentMap<String, RouteDiscoveryPreference> mDiscoveryPreferenceMap =
+ new ConcurrentHashMap<>();
private final AtomicInteger mNextRequestId = new AtomicInteger(1);
private final CopyOnWriteArrayList<TransferRequest> mTransferRequests =
@@ -247,25 +253,8 @@ public final class MediaRouter2Manager {
*/
@NonNull
public List<MediaRoute2Info> getAvailableRoutes(@NonNull RoutingSessionInfo sessionInfo) {
- Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
-
- List<MediaRoute2Info> routes = new ArrayList<>();
-
- String packageName = sessionInfo.getClientPackageName();
- List<String> preferredFeatures = mPreferredFeaturesMap.get(packageName);
- if (preferredFeatures == null) {
- preferredFeatures = Collections.emptyList();
- }
- synchronized (mRoutesLock) {
- for (MediaRoute2Info route : mRoutes.values()) {
- if (route.hasAnyFeatures(preferredFeatures)
- || sessionInfo.getSelectedRoutes().contains(route.getId())
- || sessionInfo.getTransferableRoutes().contains(route.getId())) {
- routes.add(route);
- }
- }
- }
- return routes;
+ return getFilteredRoutes(sessionInfo, /*includeSelectedRoutes=*/true,
+ null);
}
/**
@@ -281,27 +270,70 @@ public final class MediaRouter2Manager {
*/
@NonNull
public List<MediaRoute2Info> getTransferableRoutes(@NonNull RoutingSessionInfo sessionInfo) {
+ return getFilteredRoutes(sessionInfo, /*includeSelectedRoutes=*/false,
+ (route) -> sessionInfo.isSystemSession() ^ route.isSystemRoute());
+ }
+
+ private List<MediaRoute2Info> getSortedRoutes(RouteDiscoveryPreference preference) {
+ if (!preference.shouldRemoveDuplicates()) {
+ synchronized (mRoutesLock) {
+ return List.copyOf(mRoutes.values());
+ }
+ }
+ Map<String, Integer> packagePriority = new ArrayMap<>();
+ int count = preference.getDeduplicationPackageOrder().size();
+ for (int i = 0; i < count; i++) {
+ // the last package will have 1 as the priority
+ packagePriority.put(preference.getDeduplicationPackageOrder().get(i), count - i);
+ }
+ ArrayList<MediaRoute2Info> routes;
+ synchronized (mRoutesLock) {
+ routes = new ArrayList<>(mRoutes.values());
+ }
+ // take the negative for descending order
+ routes.sort(Comparator.comparingInt(
+ r -> -packagePriority.getOrDefault(r.getPackageName(), 0)));
+ return routes;
+ }
+
+ private List<MediaRoute2Info> getFilteredRoutes(@NonNull RoutingSessionInfo sessionInfo,
+ boolean includeSelectedRoutes,
+ @Nullable Predicate<MediaRoute2Info> additionalFilter) {
Objects.requireNonNull(sessionInfo, "sessionInfo must not be null");
List<MediaRoute2Info> routes = new ArrayList<>();
+ Set<String> deduplicationIdSet = new ArraySet<>();
String packageName = sessionInfo.getClientPackageName();
- List<String> preferredFeatures = mPreferredFeaturesMap.get(packageName);
- if (preferredFeatures == null) {
- preferredFeatures = Collections.emptyList();
- }
- synchronized (mRoutesLock) {
- for (MediaRoute2Info route : mRoutes.values()) {
- if (sessionInfo.getTransferableRoutes().contains(route.getId())) {
- routes.add(route);
+ RouteDiscoveryPreference discoveryPreference =
+ mDiscoveryPreferenceMap.getOrDefault(packageName, RouteDiscoveryPreference.EMPTY);
+
+ for (MediaRoute2Info route : getSortedRoutes(discoveryPreference)) {
+ if (sessionInfo.getTransferableRoutes().contains(route.getId())
+ || (includeSelectedRoutes
+ && sessionInfo.getSelectedRoutes().contains(route.getId()))) {
+ routes.add(route);
+ continue;
+ }
+ if (!route.hasAllFeatures(discoveryPreference.getRequiredFeatures())
+ || !route.hasAnyFeatures(discoveryPreference.getPreferredFeatures())) {
+ continue;
+ }
+ if (!discoveryPreference.getAllowedPackages().isEmpty()
+ && !discoveryPreference.getAllowedPackages()
+ .contains(route.getPackageName())) {
+ continue;
+ }
+ if (additionalFilter != null && !additionalFilter.test(route)) {
+ continue;
+ }
+ if (discoveryPreference.shouldRemoveDuplicates()) {
+ if (Collections.disjoint(deduplicationIdSet, route.getDeduplicationIds())) {
continue;
}
- // Add Phone -> Cast and Cast -> Phone
- if (route.hasAnyFeatures(preferredFeatures)
- && (sessionInfo.isSystemSession() ^ route.isSystemRoute())) {
- routes.add(route);
- }
+ deduplicationIdSet.addAll(route.getDeduplicationIds());
}
+ routes.add(route);
}
return routes;
}
@@ -310,44 +342,10 @@ public final class MediaRouter2Manager {
* Returns the preferred features of the specified package name.
*/
@NonNull
- public List<String> getPreferredFeatures(@NonNull String packageName) {
- Objects.requireNonNull(packageName, "packageName must not be null");
-
- List<String> preferredFeatures = mPreferredFeaturesMap.get(packageName);
- if (preferredFeatures == null) {
- preferredFeatures = Collections.emptyList();
- }
- return preferredFeatures;
- }
-
- /**
- * Returns a list of routes which are related to the given package name in the given route list.
- */
- @NonNull
- public List<MediaRoute2Info> filterRoutesForPackage(@NonNull List<MediaRoute2Info> routes,
- @NonNull String packageName) {
- Objects.requireNonNull(routes, "routes must not be null");
+ public RouteDiscoveryPreference getDiscoveryPreference(@NonNull String packageName) {
Objects.requireNonNull(packageName, "packageName must not be null");
- List<RoutingSessionInfo> sessions = getRoutingSessions(packageName);
- RoutingSessionInfo sessionInfo = sessions.get(sessions.size() - 1);
-
- List<MediaRoute2Info> result = new ArrayList<>();
- List<String> preferredFeatures = mPreferredFeaturesMap.get(packageName);
- if (preferredFeatures == null) {
- preferredFeatures = Collections.emptyList();
- }
-
- synchronized (mRoutesLock) {
- for (MediaRoute2Info route : routes) {
- if (route.hasAnyFeatures(preferredFeatures)
- || sessionInfo.getSelectedRoutes().contains(route.getId())
- || sessionInfo.getTransferableRoutes().contains(route.getId())) {
- result.add(route);
- }
- }
- }
- return result;
+ return mDiscoveryPreferenceMap.getOrDefault(packageName, RouteDiscoveryPreference.EMPTY);
}
/**
@@ -713,19 +711,19 @@ public final class MediaRouter2Manager {
}
}
- void updatePreferredFeatures(String packageName, List<String> preferredFeatures) {
- if (preferredFeatures == null) {
- mPreferredFeaturesMap.remove(packageName);
+ void updateDiscoveryPreference(String packageName, RouteDiscoveryPreference preference) {
+ if (preference == null) {
+ mDiscoveryPreferenceMap.remove(packageName);
return;
}
- List<String> prevFeatures = mPreferredFeaturesMap.put(packageName, preferredFeatures);
- if ((prevFeatures == null && preferredFeatures.size() == 0)
- || Objects.equals(preferredFeatures, prevFeatures)) {
+ RouteDiscoveryPreference prevPreference =
+ mDiscoveryPreferenceMap.put(packageName, preference);
+ if (Objects.equals(preference, prevPreference)) {
return;
}
for (CallbackRecord record : mCallbackRecords) {
record.mExecutor.execute(() -> record.mCallback
- .onPreferredFeaturesChanged(packageName, preferredFeatures));
+ .onDiscoveryPreferenceChanged(packageName, preference));
}
}
@@ -1047,6 +1045,17 @@ public final class MediaRouter2Manager {
@NonNull List<String> preferredFeatures) {}
/**
+ * Called when the preferred route features of an app is changed.
+ *
+ * @param packageName the package name of the application
+ * @param discoveryPreference the new discovery preference set by the application.
+ */
+ default void onDiscoveryPreferenceChanged(@NonNull String packageName,
+ @NonNull RouteDiscoveryPreference discoveryPreference) {
+ onPreferredFeaturesChanged(packageName, discoveryPreference.getPreferredFeatures());
+ }
+
+ /**
* Called when a previous request has failed.
*
* @param reason the reason that the request has failed. Can be one of followings:
@@ -1125,9 +1134,10 @@ public final class MediaRouter2Manager {
}
@Override
- public void notifyPreferredFeaturesChanged(String packageName, List<String> features) {
- mHandler.sendMessage(obtainMessage(MediaRouter2Manager::updatePreferredFeatures,
- MediaRouter2Manager.this, packageName, features));
+ public void notifyDiscoveryPreferenceChanged(String packageName,
+ RouteDiscoveryPreference discoveryPreference) {
+ mHandler.sendMessage(obtainMessage(MediaRouter2Manager::updateDiscoveryPreference,
+ MediaRouter2Manager.this, packageName, discoveryPreference));
}
@Override
diff --git a/media/java/android/media/RouteDiscoveryPreference.java b/media/java/android/media/RouteDiscoveryPreference.java
index 37fee8466859..06dc498afe5e 100644
--- a/media/java/android/media/RouteDiscoveryPreference.java
+++ b/media/java/android/media/RouteDiscoveryPreference.java
@@ -64,6 +64,10 @@ public final class RouteDiscoveryPreference implements Parcelable {
@NonNull
private final List<String> mPreferredFeatures;
+ private final List<String> mRequiredFeatures;
+ private final List<String> mPackagesOrder;
+ private final List<String> mAllowedPackages;
+
private final boolean mShouldPerformActiveScan;
@Nullable
private final Bundle mExtras;
@@ -78,12 +82,18 @@ public final class RouteDiscoveryPreference implements Parcelable {
RouteDiscoveryPreference(@NonNull Builder builder) {
mPreferredFeatures = builder.mPreferredFeatures;
+ mRequiredFeatures = builder.mRequiredFeatures;
+ mPackagesOrder = builder.mPackageOrder;
+ mAllowedPackages = builder.mAllowedPackages;
mShouldPerformActiveScan = builder.mActiveScan;
mExtras = builder.mExtras;
}
RouteDiscoveryPreference(@NonNull Parcel in) {
mPreferredFeatures = in.createStringArrayList();
+ mRequiredFeatures = in.createStringArrayList();
+ mPackagesOrder = in.createStringArrayList();
+ mAllowedPackages = in.createStringArrayList();
mShouldPerformActiveScan = in.readBoolean();
mExtras = in.readBundle();
}
@@ -96,6 +106,8 @@ public final class RouteDiscoveryPreference implements Parcelable {
* {@link MediaRoute2Info#FEATURE_LIVE_AUDIO}, {@link MediaRoute2Info#FEATURE_LIVE_VIDEO},
* or {@link MediaRoute2Info#FEATURE_REMOTE_PLAYBACK} or custom features defined by a provider.
* </p>
+ *
+ * @see #getRequiredFeatures()
*/
@NonNull
public List<String> getPreferredFeatures() {
@@ -103,6 +115,44 @@ public final class RouteDiscoveryPreference implements Parcelable {
}
/**
+ * Gets the required features of routes that media router would like to discover.
+ * <p>
+ * Routes that have all the required features will be discovered.
+ * This precedes {@link #getPreferredFeatures()}.
+ * They may include predefined features such as
+ * {@link MediaRoute2Info#FEATURE_LIVE_AUDIO}, {@link MediaRoute2Info#FEATURE_LIVE_VIDEO},
+ * or {@link MediaRoute2Info#FEATURE_REMOTE_PLAYBACK} or custom features defined by a provider.
+ *
+ * @see #getPreferredFeatures()
+ */
+ @NonNull
+ public List<String> getRequiredFeatures() {
+ return mRequiredFeatures;
+ }
+
+ /**
+ * Gets the ordered list of package names used to remove duplicate routes.
+ * <p>
+ * When the app enables duplicate removal, all the routes that have the same deduplication ID
+ * except one from the provider whose package name appears first in the list will be removed.
+ */
+ @NonNull
+ public List<String> getDeduplicationPackageOrder() {
+ return mPackagesOrder == null ? List.of() : mPackagesOrder;
+ }
+
+ /**
+ * Gets the list of allowed packages.
+ * <p>
+ * If it's not empty, it will only discover routes from the provider whose package name
+ * belongs to the list.
+ */
+ @NonNull
+ public List<String> getAllowedPackages() {
+ return mAllowedPackages;
+ }
+
+ /**
* Gets whether active scanning should be performed.
* <p>
* If any of discovery preferences sets this as {@code true}, active scanning will
@@ -114,6 +164,16 @@ public final class RouteDiscoveryPreference implements Parcelable {
}
/**
+ * Gets whether duplicate routes should be removed.
+ * <p>
+ * If it is {@code true}, only one of routes that have
+ * the same deduplication ID will be obtained.
+ */
+ public boolean shouldRemoveDuplicates() {
+ return !mPackagesOrder.isEmpty();
+ }
+
+ /**
* @hide
*/
public Bundle getExtras() {
@@ -128,6 +188,9 @@ public final class RouteDiscoveryPreference implements Parcelable {
@Override
public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeStringList(mPreferredFeatures);
+ dest.writeStringList(mRequiredFeatures);
+ dest.writeStringList(mPackagesOrder);
+ dest.writeStringList(mAllowedPackages);
dest.writeBoolean(mShouldPerformActiveScan);
dest.writeBundle(mExtras);
}
@@ -155,14 +218,17 @@ public final class RouteDiscoveryPreference implements Parcelable {
return false;
}
RouteDiscoveryPreference other = (RouteDiscoveryPreference) o;
- //TODO: Make this order-free
return Objects.equals(mPreferredFeatures, other.mPreferredFeatures)
+ && Objects.equals(mRequiredFeatures, other.mRequiredFeatures)
+ && Objects.equals(mPackagesOrder, other.mPackagesOrder)
+ && Objects.equals(mAllowedPackages, other.mAllowedPackages)
&& mShouldPerformActiveScan == other.mShouldPerformActiveScan;
}
@Override
public int hashCode() {
- return Objects.hash(mPreferredFeatures, mShouldPerformActiveScan);
+ return Objects.hash(mPreferredFeatures, mRequiredFeatures, mPackagesOrder, mAllowedPackages,
+ mShouldPerformActiveScan);
}
/**
@@ -170,13 +236,21 @@ public final class RouteDiscoveryPreference implements Parcelable {
*/
public static final class Builder {
List<String> mPreferredFeatures;
+ List<String> mRequiredFeatures;
+ List<String> mPackageOrder;
+ List<String> mAllowedPackages;
+
boolean mActiveScan;
+
Bundle mExtras;
public Builder(@NonNull List<String> preferredFeatures, boolean activeScan) {
Objects.requireNonNull(preferredFeatures, "preferredFeatures must not be null");
mPreferredFeatures = preferredFeatures.stream().filter(str -> !TextUtils.isEmpty(str))
.collect(Collectors.toList());
+ mRequiredFeatures = List.of();
+ mPackageOrder = List.of();
+ mAllowedPackages = List.of();
mActiveScan = activeScan;
}
@@ -184,12 +258,15 @@ public final class RouteDiscoveryPreference implements Parcelable {
Objects.requireNonNull(preference, "preference must not be null");
mPreferredFeatures = preference.getPreferredFeatures();
+ mRequiredFeatures = preference.getRequiredFeatures();
+ mPackageOrder = preference.getDeduplicationPackageOrder();
+ mAllowedPackages = preference.getAllowedPackages();
mActiveScan = preference.shouldPerformActiveScan();
mExtras = preference.getExtras();
}
/**
- * A constructor to combine all of the preferences into a single preference.
+ * A constructor to combine all the preferences into a single preference.
* It ignores extras of preferences.
*
* @hide
@@ -224,6 +301,30 @@ public final class RouteDiscoveryPreference implements Parcelable {
}
/**
+ * Sets the required route features to discover.
+ */
+ @NonNull
+ public Builder setRequiredFeatures(@NonNull List<String> requiredFeatures) {
+ Objects.requireNonNull(requiredFeatures, "preferredFeatures must not be null");
+ mRequiredFeatures = requiredFeatures.stream().filter(str -> !TextUtils.isEmpty(str))
+ .collect(Collectors.toList());
+ return this;
+ }
+
+ /**
+ * Sets the list of package names of providers that media router would like to discover.
+ * <p>
+ * If it's non-empty, media router only discovers route from the provider in the list.
+ * The default value is empty, which discovers routes from all providers.
+ */
+ @NonNull
+ public Builder setAllowedPackages(@NonNull List<String> allowedPackages) {
+ Objects.requireNonNull(allowedPackages, "allowedPackages must not be null");
+ mAllowedPackages = List.copyOf(allowedPackages);
+ return this;
+ }
+
+ /**
* Sets if active scanning should be performed.
* <p>
* Since active scanning uses more system resources, set this as {@code true} only
@@ -237,6 +338,27 @@ public final class RouteDiscoveryPreference implements Parcelable {
}
/**
+ * Sets the order of packages when removing duplicate routes.
+ * <p>
+ * Routes are removed based on its
+ * {@link MediaRoute2Info#getDeduplicationIds() deduplication ID}.
+ * If two routes have the same ID, even if they are from different providers,
+ * one of them is removed from the list.
+ * <p>
+ * Routes from the provider whose package name appears first in the given package order
+ * will remain.
+ * If unspecified, any route can be selected.
+ *
+ * @param packageOrder list of package names for choosing routes to be removed or
+ * {@code null} not to remove duplicate routes.
+ */
+ @NonNull
+ public Builder setDeduplicationPackageOrder(@Nullable List<String> packageOrder) {
+ mPackageOrder = (packageOrder == null) ? null : List.copyOf(packageOrder);
+ return this;
+ }
+
+ /**
* Sets the extras of the route.
* @hide
*/
diff --git a/media/native/midi/amidi.cpp b/media/native/midi/amidi.cpp
index aa076e85e30d..fd8a06da5c6d 100644
--- a/media/native/midi/amidi.cpp
+++ b/media/native/midi/amidi.cpp
@@ -401,10 +401,14 @@ ssize_t AMIDI_API AMidiInputPort_send(const AMidiInputPort *inputPort, const uin
ssize_t AMIDI_API AMidiInputPort_sendWithTimestamp(const AMidiInputPort *inputPort,
const uint8_t *data, size_t numBytes, int64_t timestamp) {
- if (inputPort == nullptr || data == nullptr) {
+ if (inputPort == nullptr || data == nullptr || numBytes < 0 || timestamp < 0) {
return AMEDIA_ERROR_INVALID_PARAMETER;
}
+ if (numBytes == 0) {
+ return 0;
+ }
+
// AMIDI_logBuffer(data, numBytes);
uint8_t writeBuffer[AMIDI_BUFFER_SIZE + AMIDI_PACKET_OVERHEAD];
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index 35c794e82695..f9a17746892e 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -315,18 +315,18 @@ LIBANDROID {
AThermal_registerThermalStatusListener; # introduced=30
AThermal_unregisterThermalStatusListener; # introduced=30
AThermal_getThermalHeadroom; # introduced=31
+ APerformanceHint_getManager; # introduced=Tiramisu
+ APerformanceHint_createSession; # introduced=Tiramisu
+ APerformanceHint_getPreferredUpdateRateNanos; # introduced=Tiramisu
+ APerformanceHint_updateTargetWorkDuration; # introduced=Tiramisu
+ APerformanceHint_reportActualWorkDuration; # introduced=Tiramisu
+ APerformanceHint_closeSession; # introduced=Tiramisu
local:
*;
};
LIBANDROID_PLATFORM {
global:
- APerformanceHint_getManager;
- APerformanceHint_createSession;
- APerformanceHint_getPreferredUpdateRateNanos;
- APerformanceHint_updateTargetWorkDuration;
- APerformanceHint_reportActualWorkDuration;
- APerformanceHint_closeSession;
APerformanceHint_setIHintManagerForTesting;
extern "C++" {
ASurfaceControl_registerSurfaceStatsListener*;
diff --git a/native/android/performance_hint.cpp b/native/android/performance_hint.cpp
index 51a0c99af66e..0c360519ceb2 100644
--- a/native/android/performance_hint.cpp
+++ b/native/android/performance_hint.cpp
@@ -16,17 +16,18 @@
#define LOG_TAG "perf_hint"
-#include <utility>
-#include <vector>
-
#include <android/os/IHintManager.h>
#include <android/os/IHintSession.h>
+#include <android/performance_hint.h>
#include <binder/Binder.h>
#include <binder/IBinder.h>
#include <binder/IServiceManager.h>
#include <performance_hint_private.h>
#include <utils/SystemClock.h>
+#include <utility>
+#include <vector>
+
using namespace android;
using namespace android::os;
diff --git a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
index 284e9ee909ee..b17850e5d1e4 100644
--- a/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
+++ b/native/android/tests/performance_hint/PerformanceHintNativeTest.cpp
@@ -18,10 +18,12 @@
#include <android/os/IHintManager.h>
#include <android/os/IHintSession.h>
+#include <android/performance_hint.h>
#include <binder/IBinder.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <performance_hint_private.h>
+
#include <memory>
#include <vector>
diff --git a/native/graphics/jni/imagedecoder.cpp b/native/graphics/jni/imagedecoder.cpp
index a0f3098ad347..bb25274e3136 100644
--- a/native/graphics/jni/imagedecoder.cpp
+++ b/native/graphics/jni/imagedecoder.cpp
@@ -198,14 +198,16 @@ static SkColorType getColorType(AndroidBitmapFormat format) {
return kGray_8_SkColorType;
case ANDROID_BITMAP_FORMAT_RGBA_F16:
return kRGBA_F16_SkColorType;
+ case ANDROID_BITMAP_FORMAT_RGBA_1010102:
+ return kRGBA_1010102_SkColorType;
default:
return kUnknown_SkColorType;
}
}
int AImageDecoder_setAndroidBitmapFormat(AImageDecoder* decoder, int32_t format) {
- if (!decoder || format < ANDROID_BITMAP_FORMAT_NONE
- || format > ANDROID_BITMAP_FORMAT_RGBA_F16) {
+ if (!decoder || format < ANDROID_BITMAP_FORMAT_NONE ||
+ format > ANDROID_BITMAP_FORMAT_RGBA_1010102) {
return ANDROID_IMAGE_DECODER_BAD_PARAMETER;
}
@@ -290,6 +292,8 @@ static AndroidBitmapFormat getFormat(SkColorType colorType) {
return ANDROID_BITMAP_FORMAT_A_8;
case kRGBA_F16_SkColorType:
return ANDROID_BITMAP_FORMAT_RGBA_F16;
+ case kRGBA_1010102_SkColorType:
+ return ANDROID_BITMAP_FORMAT_RGBA_1010102;
default:
return ANDROID_BITMAP_FORMAT_NONE;
}
diff --git a/packages/ConnectivityT/framework-t/Android.bp b/packages/ConnectivityT/framework-t/Android.bp
index 223bdcdd9c95..327b1fb2f5d8 100644
--- a/packages/ConnectivityT/framework-t/Android.bp
+++ b/packages/ConnectivityT/framework-t/Android.bp
@@ -39,7 +39,6 @@ filegroup {
"src/android/net/TrafficStats.java",
"src/android/net/UnderlyingNetworkInfo.*",
"src/android/net/netstats/**/*.*",
- "src/com/android/server/NetworkManagementSocketTagger.java",
],
path: "src",
visibility: [
@@ -176,3 +175,34 @@ filegroup {
"//packages/modules/Connectivity:__subpackages__",
],
}
+
+cc_library_shared {
+ name: "libframework-connectivity-tiramisu-jni",
+ min_sdk_version: "30",
+ cflags: [
+ "-Wall",
+ "-Werror",
+ "-Wno-unused-parameter",
+ // Don't warn about S API usage even with
+ // min_sdk 30: the library is only loaded
+ // on S+ devices
+ "-Wno-unguarded-availability",
+ "-Wthread-safety",
+ ],
+ srcs: [
+ "jni/android_net_TrafficStats.cpp",
+ "jni/onload.cpp",
+ ],
+ shared_libs: [
+ "liblog",
+ ],
+ static_libs: [
+ "libnativehelper_compat_libc++",
+ ],
+ stl: "none",
+ apex_available: [
+ "com.android.tethering",
+ // TODO: remove when ConnectivityT moves to APEX.
+ "//apex_available:platform",
+ ],
+}
diff --git a/packages/ConnectivityT/framework-t/jni/android_net_TrafficStats.cpp b/packages/ConnectivityT/framework-t/jni/android_net_TrafficStats.cpp
new file mode 100644
index 000000000000..f3c58b112f0d
--- /dev/null
+++ b/packages/ConnectivityT/framework-t/jni/android_net_TrafficStats.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/file_descriptor_jni.h>
+#include <android/multinetwork.h>
+#include <nativehelper/JNIHelp.h>
+
+namespace android {
+
+static jint tagSocketFd(JNIEnv* env, jclass, jobject fileDescriptor, jint tag, jint uid) {
+ int fd = AFileDescriptor_getFd(env, fileDescriptor);
+ if (fd == -1) return -EBADF;
+ return android_tag_socket_with_uid(fd, tag, uid);
+}
+
+static jint untagSocketFd(JNIEnv* env, jclass, jobject fileDescriptor) {
+ int fd = AFileDescriptor_getFd(env, fileDescriptor);
+ if (fd == -1) return -EBADF;
+ return android_untag_socket(fd);
+}
+
+static const JNINativeMethod gMethods[] = {
+ /* name, signature, funcPtr */
+ { "native_tagSocketFd", "(Ljava/io/FileDescriptor;II)I", (void*) tagSocketFd },
+ { "native_untagSocketFd", "(Ljava/io/FileDescriptor;)I", (void*) untagSocketFd },
+};
+
+int register_android_net_TrafficStats(JNIEnv* env) {
+ return jniRegisterNativeMethods(env, "android/net/TrafficStats", gMethods, NELEM(gMethods));
+}
+
+}; // namespace android
+
diff --git a/packages/ConnectivityT/framework-t/jni/onload.cpp b/packages/ConnectivityT/framework-t/jni/onload.cpp
new file mode 100644
index 000000000000..1fb42c63477e
--- /dev/null
+++ b/packages/ConnectivityT/framework-t/jni/onload.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "FrameworkConnectivityJNI"
+
+#include <log/log.h>
+#include <nativehelper/JNIHelp.h>
+
+namespace android {
+
+int register_android_net_TrafficStats(JNIEnv* env);
+
+extern "C" jint JNI_OnLoad(JavaVM* vm, void*) {
+ JNIEnv *env;
+ if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+ __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "ERROR: GetEnv failed");
+ return JNI_ERR;
+ }
+
+ if (register_android_net_TrafficStats(env) < 0) return JNI_ERR;
+
+ return JNI_VERSION_1_6;
+}
+
+}; // namespace android
+
diff --git a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
index 84adef53e488..5ce7e59b38ff 100644
--- a/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
+++ b/packages/ConnectivityT/framework-t/src/android/app/usage/NetworkStatsManager.java
@@ -41,6 +41,7 @@ import android.net.NetworkStateSnapshot;
import android.net.NetworkTemplate;
import android.net.UnderlyingNetworkInfo;
import android.net.netstats.IUsageCallback;
+import android.net.netstats.NetworkStatsDataMigrationUtils;
import android.net.netstats.provider.INetworkStatsProviderCallback;
import android.net.netstats.provider.NetworkStatsProvider;
import android.os.Build;
@@ -126,17 +127,12 @@ public class NetworkStatsManager {
private final INetworkStatsService mService;
/**
- * Type constants for reading different types of Data Usage.
+ * @deprecated Use {@link NetworkStatsDataMigrationUtils#PREFIX_XT}
+ * instead.
* @hide
*/
- // @SystemApi(client = MODULE_LIBRARIES)
+ @Deprecated
public static final String PREFIX_DEV = "dev";
- /** @hide */
- public static final String PREFIX_XT = "xt";
- /** @hide */
- public static final String PREFIX_UID = "uid";
- /** @hide */
- public static final String PREFIX_UID_TAG = "uid_tag";
/** @hide */
public static final int FLAG_POLL_ON_OPEN = 1 << 0;
diff --git a/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java b/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java
index c2f0cdfb048c..bc836d857e3e 100644
--- a/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java
+++ b/packages/ConnectivityT/framework-t/src/android/net/TrafficStats.java
@@ -31,12 +31,9 @@ import android.media.MediaPlayer;
import android.os.Binder;
import android.os.Build;
import android.os.RemoteException;
+import android.os.StrictMode;
import android.util.Log;
-import com.android.server.NetworkManagementSocketTagger;
-
-import dalvik.system.SocketTagger;
-
import java.io.FileDescriptor;
import java.io.IOException;
import java.net.DatagramSocket;
@@ -56,6 +53,10 @@ import java.net.SocketException;
* use {@link NetworkStatsManager} instead.
*/
public class TrafficStats {
+ static {
+ System.loadLibrary("framework-connectivity-tiramisu-jni");
+ }
+
private static final String TAG = TrafficStats.class.getSimpleName();
/**
* The return value to indicate that the device does not support the statistic.
@@ -232,9 +233,68 @@ public class TrafficStats {
*/
@SystemApi(client = MODULE_LIBRARIES)
public static void attachSocketTagger() {
- NetworkManagementSocketTagger.install();
+ dalvik.system.SocketTagger.set(new SocketTagger());
+ }
+
+ private static class SocketTagger extends dalvik.system.SocketTagger {
+
+ // TODO: set to false
+ private static final boolean LOGD = true;
+
+ SocketTagger() {
+ }
+
+ @Override
+ public void tag(FileDescriptor fd) throws SocketException {
+ final UidTag tagInfo = sThreadUidTag.get();
+ if (LOGD) {
+ Log.d(TAG, "tagSocket(" + fd.getInt$() + ") with statsTag=0x"
+ + Integer.toHexString(tagInfo.tag) + ", statsUid=" + tagInfo.uid);
+ }
+ if (tagInfo.tag == -1) {
+ StrictMode.noteUntaggedSocket();
+ }
+
+ if (tagInfo.tag == -1 && tagInfo.uid == -1) return;
+ final int errno = native_tagSocketFd(fd, tagInfo.tag, tagInfo.uid);
+ if (errno < 0) {
+ Log.i(TAG, "tagSocketFd(" + fd.getInt$() + ", "
+ + tagInfo.tag + ", "
+ + tagInfo.uid + ") failed with errno" + errno);
+ }
+ }
+
+ @Override
+ public void untag(FileDescriptor fd) throws SocketException {
+ if (LOGD) {
+ Log.i(TAG, "untagSocket(" + fd.getInt$() + ")");
+ }
+
+ final UidTag tagInfo = sThreadUidTag.get();
+ if (tagInfo.tag == -1 && tagInfo.uid == -1) return;
+
+ final int errno = native_untagSocketFd(fd);
+ if (errno < 0) {
+ Log.w(TAG, "untagSocket(" + fd.getInt$() + ") failed with errno " + errno);
+ }
+ }
+ }
+
+ private static native int native_tagSocketFd(FileDescriptor fd, int tag, int uid);
+ private static native int native_untagSocketFd(FileDescriptor fd);
+
+ private static class UidTag {
+ public int tag = -1;
+ public int uid = -1;
}
+ private static ThreadLocal<UidTag> sThreadUidTag = new ThreadLocal<UidTag>() {
+ @Override
+ protected UidTag initialValue() {
+ return new UidTag();
+ }
+ };
+
/**
* Set active tag to use when accounting {@link Socket} traffic originating
* from the current thread. Only one active tag per thread is supported.
@@ -249,7 +309,7 @@ public class TrafficStats {
* @see #clearThreadStatsTag()
*/
public static void setThreadStatsTag(int tag) {
- NetworkManagementSocketTagger.setThreadSocketStatsTag(tag);
+ getAndSetThreadStatsTag(tag);
}
/**
@@ -267,7 +327,9 @@ public class TrafficStats {
* restore any existing values after a nested operation is finished
*/
public static int getAndSetThreadStatsTag(int tag) {
- return NetworkManagementSocketTagger.setThreadSocketStatsTag(tag);
+ final int old = sThreadUidTag.get().tag;
+ sThreadUidTag.get().tag = tag;
+ return old;
}
/**
@@ -327,7 +389,7 @@ public class TrafficStats {
* @see #setThreadStatsTag(int)
*/
public static int getThreadStatsTag() {
- return NetworkManagementSocketTagger.getThreadSocketStatsTag();
+ return sThreadUidTag.get().tag;
}
/**
@@ -337,7 +399,7 @@ public class TrafficStats {
* @see #setThreadStatsTag(int)
*/
public static void clearThreadStatsTag() {
- NetworkManagementSocketTagger.setThreadSocketStatsTag(-1);
+ sThreadUidTag.get().tag = -1;
}
/**
@@ -357,7 +419,7 @@ public class TrafficStats {
*/
@SuppressLint("RequiresPermission")
public static void setThreadStatsUid(int uid) {
- NetworkManagementSocketTagger.setThreadSocketStatsUid(uid);
+ sThreadUidTag.get().uid = uid;
}
/**
@@ -368,7 +430,7 @@ public class TrafficStats {
* @see #setThreadStatsUid(int)
*/
public static int getThreadStatsUid() {
- return NetworkManagementSocketTagger.getThreadSocketStatsUid();
+ return sThreadUidTag.get().uid;
}
/**
@@ -395,7 +457,7 @@ public class TrafficStats {
*/
@SuppressLint("RequiresPermission")
public static void clearThreadStatsUid() {
- NetworkManagementSocketTagger.setThreadSocketStatsUid(-1);
+ setThreadStatsUid(-1);
}
/**
diff --git a/packages/ConnectivityT/framework-t/src/com/android/server/NetworkManagementSocketTagger.java b/packages/ConnectivityT/framework-t/src/com/android/server/NetworkManagementSocketTagger.java
index 8bb12a6defe5..8aca1d67942f 100644
--- a/packages/ConnectivityT/framework-t/src/com/android/server/NetworkManagementSocketTagger.java
+++ b/packages/ConnectivityT/framework-t/src/com/android/server/NetworkManagementSocketTagger.java
@@ -111,19 +111,6 @@ public final class NetworkManagementSocketTagger extends SocketTagger {
public int statsUid = -1;
}
- /**
- * Convert {@code /proc/} tag format to {@link Integer}. Assumes incoming
- * format like {@code 0x7fffffff00000000}.
- */
- public static int kernelToTag(String string) {
- int length = string.length();
- if (length > 10) {
- return Long.decode(string.substring(0, length - 8)).intValue();
- } else {
- return 0;
- }
- }
-
private static native int native_tagSocketFd(FileDescriptor fd, int tag, int uid);
private static native int native_untagSocketFd(FileDescriptor fd);
}
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java
index 17f3455d20a2..668d1cba921b 100644
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsFactory.java
@@ -22,8 +22,6 @@ import static android.net.NetworkStats.TAG_ALL;
import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
-import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
@@ -470,6 +468,19 @@ public class NetworkStatsFactory {
}
/**
+ * Convert {@code /proc/} tag format to {@link Integer}. Assumes incoming
+ * format like {@code 0x7fffffff00000000}.
+ */
+ public static int kernelToTag(String string) {
+ int length = string.length();
+ if (length > 10) {
+ return Long.decode(string.substring(0, length - 8)).intValue();
+ } else {
+ return 0;
+ }
+ }
+
+ /**
* Parse statistics from file into given {@link NetworkStats} object. Values
* are expected to monotonically increase since device boot.
*/
diff --git a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
index 748b0ae02088..9f3371b724cf 100644
--- a/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
+++ b/packages/ConnectivityT/service/src/com/android/server/net/NetworkStatsService.java
@@ -20,9 +20,6 @@ import static android.Manifest.permission.NETWORK_STATS_PROVIDER;
import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
import static android.Manifest.permission.UPDATE_DEVICE_STATS;
import static android.app.usage.NetworkStatsManager.PREFIX_DEV;
-import static android.app.usage.NetworkStatsManager.PREFIX_UID;
-import static android.app.usage.NetworkStatsManager.PREFIX_UID_TAG;
-import static android.app.usage.NetworkStatsManager.PREFIX_XT;
import static android.content.Intent.ACTION_SHUTDOWN;
import static android.content.Intent.ACTION_UID_REMOVED;
import static android.content.Intent.ACTION_USER_REMOVED;
@@ -50,6 +47,9 @@ import static android.net.TrafficStats.KB_IN_BYTES;
import static android.net.TrafficStats.MB_IN_BYTES;
import static android.net.TrafficStats.UID_TETHERING;
import static android.net.TrafficStats.UNSUPPORTED;
+import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_UID;
+import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_UID_TAG;
+import static android.net.netstats.NetworkStatsDataMigrationUtils.PREFIX_XT;
import static android.os.Trace.TRACE_TAG_NETWORK;
import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
diff --git a/packages/SettingsLib/Android.bp b/packages/SettingsLib/Android.bp
index fcf2282160a7..684f4dee9ac2 100644
--- a/packages/SettingsLib/Android.bp
+++ b/packages/SettingsLib/Android.bp
@@ -50,6 +50,7 @@ android_library {
"SettingsLibSettingsTransition",
"SettingsLibActivityEmbedding",
"SettingsLibButtonPreference",
+ "setupdesign",
],
// ANDROIDMK TRANSLATION ERROR: unsupported assignment to LOCAL_SHARED_JAVA_LIBRARIES
diff --git a/packages/SettingsLib/AndroidManifest.xml b/packages/SettingsLib/AndroidManifest.xml
index a3473459948d..13f8a372c9b5 100644
--- a/packages/SettingsLib/AndroidManifest.xml
+++ b/packages/SettingsLib/AndroidManifest.xml
@@ -18,4 +18,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.android.settingslib">
+ <application>
+ <activity
+ android:name="com.android.settingslib.users.AvatarPickerActivity"
+ android:theme="@style/SudThemeGlifV2.DayNight"/>
+ </application>
+
</manifest>
diff --git a/packages/SettingsLib/res/drawable/avatar_choose_photo_circled.xml b/packages/SettingsLib/res/drawable/avatar_choose_photo_circled.xml
new file mode 100644
index 000000000000..97aec740ea43
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/avatar_choose_photo_circled.xml
@@ -0,0 +1,30 @@
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item>
+ <shape android:shape="oval">
+ <stroke
+ android:width="2dp"
+ android:color="?android:attr/colorPrimary"/>
+ </shape>
+ </item>
+ <item
+ android:left="@dimen/avatar_picker_icon_inset"
+ android:right="@dimen/avatar_picker_icon_inset"
+ android:top="@dimen/avatar_picker_icon_inset"
+ android:bottom="@dimen/avatar_picker_icon_inset"
+ android:drawable="@drawable/ic_avatar_choose_photo"/>
+</layer-list>
diff --git a/packages/SettingsLib/res/drawable/avatar_selector.xml b/packages/SettingsLib/res/drawable/avatar_selector.xml
new file mode 100644
index 000000000000..ccde59763a4a
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/avatar_selector.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+ <item android:state_selected="true">
+ <shape android:shape="oval">
+ <stroke
+ android:color="?android:attr/colorPrimary"
+ android:width="@dimen/avatar_picker_padding"/>
+ </shape>
+ </item>
+</selector> \ No newline at end of file
diff --git a/packages/SettingsLib/res/drawable/avatar_take_photo_circled.xml b/packages/SettingsLib/res/drawable/avatar_take_photo_circled.xml
new file mode 100644
index 000000000000..7033aaeec911
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/avatar_take_photo_circled.xml
@@ -0,0 +1,30 @@
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+ <item>
+ <shape android:shape="oval">
+ <stroke
+ android:width="2dp"
+ android:color="?android:attr/colorPrimary"/>
+ </shape>
+ </item>
+ <item
+ android:left="@dimen/avatar_picker_icon_inset"
+ android:right="@dimen/avatar_picker_icon_inset"
+ android:top="@dimen/avatar_picker_icon_inset"
+ android:bottom="@dimen/avatar_picker_icon_inset"
+ android:drawable="@drawable/ic_avatar_take_photo"/>
+</layer-list>
diff --git a/packages/SettingsLib/res/drawable/ic_account_circle_outline.xml b/packages/SettingsLib/res/drawable/ic_account_circle_outline.xml
new file mode 100644
index 000000000000..0cc54b6b4972
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_account_circle_outline.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="?android:attr/colorPrimary"
+ android:pathData="M5.85,17.1q1.275,-0.975 2.85,-1.538Q10.275,15 12,15q1.725,0 3.3,0.563 1.575,0.562 2.85,1.537 0.875,-1.025 1.363,-2.325Q20,13.475 20,12q0,-3.325 -2.337,-5.662Q15.325,4 12,4T6.338,6.338Q4,8.675 4,12q0,1.475 0.487,2.775 0.488,1.3 1.363,2.325zM12,13q-1.475,0 -2.488,-1.012Q8.5,10.975 8.5,9.5t1.012,-2.487Q10.525,6 12,6t2.488,1.013Q15.5,8.024 15.5,9.5t-1.012,2.488Q13.475,13 12,13zM12,22q-2.075,0 -3.9,-0.788 -1.825,-0.787 -3.175,-2.137 -1.35,-1.35 -2.137,-3.175Q2,14.075 2,12t0.788,-3.9q0.787,-1.825 2.137,-3.175 1.35,-1.35 3.175,-2.137Q9.925,2 12,2t3.9,0.788q1.825,0.787 3.175,2.137 1.35,1.35 2.137,3.175Q22,9.925 22,12t-0.788,3.9q-0.787,1.825 -2.137,3.175 -1.35,1.35 -3.175,2.137Q14.075,22 12,22zM12,20q1.325,0 2.5,-0.387 1.175,-0.388 2.15,-1.113 -0.975,-0.725 -2.15,-1.113Q13.325,17 12,17t-2.5,0.387q-1.175,0.388 -2.15,1.113 0.975,0.725 2.15,1.113Q10.675,20 12,20zM12,11q0.65,0 1.075,-0.425 0.425,-0.425 0.425,-1.075 0,-0.65 -0.425,-1.075Q12.65,8 12,8q-0.65,0 -1.075,0.425Q10.5,8.85 10.5,9.5q0,0.65 0.425,1.075Q11.35,11 12,11zM12,9.5zM12,18.5z"/>
+</vector>
+
diff --git a/packages/SettingsLib/res/drawable/ic_avatar_choose_photo.xml b/packages/SettingsLib/res/drawable/ic_avatar_choose_photo.xml
new file mode 100644
index 000000000000..b85fdc2de597
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_avatar_choose_photo.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="?android:attr/colorPrimary"
+ android:pathData="M9,14h10l-3.45,-4.5 -2.3,3 -1.55,-2zM8,18q-0.825,0 -1.412,-0.587Q6,16.825 6,16L6,4q0,-0.825 0.588,-1.413Q7.175,2 8,2h12q0.825,0 1.413,0.587Q22,3.175 22,4v12q0,0.825 -0.587,1.413Q20.825,18 20,18zM8,16h12L20,4L8,4v12zM4,22q-0.825,0 -1.413,-0.587Q2,20.825 2,20L2,6h2v14h14v2zM8,4v12L8,4z"/>
+</vector>
diff --git a/packages/SettingsLib/res/drawable/ic_avatar_take_photo.xml b/packages/SettingsLib/res/drawable/ic_avatar_take_photo.xml
new file mode 100644
index 000000000000..5c56276ec4f3
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_avatar_take_photo.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="?android:attr/colorPrimary"
+ android:pathData="M12,17.5q1.875,0 3.188,-1.313Q16.5,14.876 16.5,13q0,-1.875 -1.313,-3.188Q13.876,8.5 12,8.5q-1.875,0 -3.188,1.313Q7.5,11.124 7.5,13q0,1.875 1.313,3.188Q10.124,17.5 12,17.5zM4,21q-0.825,0 -1.413,-0.587Q2,19.825 2,19L2,7q0,-0.825 0.587,-1.412Q3.175,5 4,5h3.15L9,3h6l1.85,2L20,5q0.825,0 1.413,0.588Q22,6.175 22,7v12q0,0.825 -0.587,1.413Q20.825,21 20,21zM20,19L20,7L4,7v12zM4,19L4,7v12z"/>
+</vector>
diff --git a/packages/SettingsLib/res/layout/avatar_item.xml b/packages/SettingsLib/res/layout/avatar_item.xml
new file mode 100644
index 000000000000..c52f6648cb7e
--- /dev/null
+++ b/packages/SettingsLib/res/layout/avatar_item.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/avatar_image"
+ android:layout_height="@dimen/avatar_size_in_picker"
+ android:layout_width="@dimen/avatar_size_in_picker"
+ android:layout_margin="@dimen/avatar_picker_margin"
+ android:layout_gravity="center"
+ android:padding="@dimen/avatar_picker_padding"
+ android:background="@drawable/avatar_selector"/>
diff --git a/packages/SettingsLib/res/layout/avatar_picker.xml b/packages/SettingsLib/res/layout/avatar_picker.xml
new file mode 100644
index 000000000000..2d40bd0de7ea
--- /dev/null
+++ b/packages/SettingsLib/res/layout/avatar_picker.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<com.google.android.setupdesign.GlifLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/glif_layout"
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:icon="@drawable/ic_account_circle_outline"
+ app:sucUsePartnerResource="true"
+ app:sucHeaderText="@string/avatar_picker_title">
+
+ <LinearLayout
+ android:layout_height="match_parent"
+ android:layout_width="match_parent"
+ android:gravity="center_horizontal"
+ style="@style/SudContentFrame">
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/avatar_grid"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"/>
+ </LinearLayout>
+
+</com.google.android.setupdesign.GlifLayout> \ No newline at end of file
diff --git a/packages/SettingsLib/res/values-w1280dp-land/dimens.xml b/packages/SettingsLib/res/values-w1280dp-land/dimens.xml
new file mode 100644
index 000000000000..4097d0564251
--- /dev/null
+++ b/packages/SettingsLib/res/values-w1280dp-land/dimens.xml
@@ -0,0 +1,21 @@
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<resources>
+ <integer name="avatar_picker_columns">4</integer>
+ <dimen name="avatar_size_in_picker">104dp</dimen>
+ <dimen name="avatar_picker_padding">8dp</dimen>
+ <dimen name="avatar_picker_margin">3dp</dimen>
+</resources> \ No newline at end of file
diff --git a/packages/SettingsLib/res/values-w1440dp-land/dimens.xml b/packages/SettingsLib/res/values-w1440dp-land/dimens.xml
new file mode 100644
index 000000000000..764870efe222
--- /dev/null
+++ b/packages/SettingsLib/res/values-w1440dp-land/dimens.xml
@@ -0,0 +1,21 @@
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<resources>
+ <integer name="avatar_picker_columns">4</integer>
+ <dimen name="avatar_size_in_picker">128dp</dimen>
+ <dimen name="avatar_picker_padding">8dp</dimen>
+ <dimen name="avatar_picker_margin">4dp</dimen>
+</resources> \ No newline at end of file
diff --git a/packages/SettingsLib/res/values-w1600dp-land/dimens.xml b/packages/SettingsLib/res/values-w1600dp-land/dimens.xml
new file mode 100644
index 000000000000..872b88a3776d
--- /dev/null
+++ b/packages/SettingsLib/res/values-w1600dp-land/dimens.xml
@@ -0,0 +1,21 @@
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<resources>
+ <integer name="avatar_picker_columns">4</integer>
+ <dimen name="avatar_size_in_picker">148dp</dimen>
+ <dimen name="avatar_picker_padding">8dp</dimen>
+ <dimen name="avatar_picker_margin">6dp</dimen>
+</resources> \ No newline at end of file
diff --git a/packages/SettingsLib/res/values-w480dp-port/dimens.xml b/packages/SettingsLib/res/values-w480dp-port/dimens.xml
new file mode 100644
index 000000000000..cab78d64ce8d
--- /dev/null
+++ b/packages/SettingsLib/res/values-w480dp-port/dimens.xml
@@ -0,0 +1,21 @@
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<resources>
+ <integer name="avatar_picker_columns">3</integer>
+ <dimen name="avatar_size_in_picker">112dp</dimen>
+ <dimen name="avatar_picker_padding">8dp</dimen>
+ <dimen name="avatar_picker_margin">3dp</dimen>
+</resources>
diff --git a/packages/SettingsLib/res/values-w600dp-port/dimens.xml b/packages/SettingsLib/res/values-w600dp-port/dimens.xml
new file mode 100644
index 000000000000..4097d0564251
--- /dev/null
+++ b/packages/SettingsLib/res/values-w600dp-port/dimens.xml
@@ -0,0 +1,21 @@
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<resources>
+ <integer name="avatar_picker_columns">4</integer>
+ <dimen name="avatar_size_in_picker">104dp</dimen>
+ <dimen name="avatar_picker_padding">8dp</dimen>
+ <dimen name="avatar_picker_margin">3dp</dimen>
+</resources> \ No newline at end of file
diff --git a/packages/SettingsLib/res/values-w720dp-port/dimens.xml b/packages/SettingsLib/res/values-w720dp-port/dimens.xml
new file mode 100644
index 000000000000..764870efe222
--- /dev/null
+++ b/packages/SettingsLib/res/values-w720dp-port/dimens.xml
@@ -0,0 +1,21 @@
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<resources>
+ <integer name="avatar_picker_columns">4</integer>
+ <dimen name="avatar_size_in_picker">128dp</dimen>
+ <dimen name="avatar_picker_padding">8dp</dimen>
+ <dimen name="avatar_picker_margin">4dp</dimen>
+</resources> \ No newline at end of file
diff --git a/packages/SettingsLib/res/values-w840dp-port/dimens.xml b/packages/SettingsLib/res/values-w840dp-port/dimens.xml
new file mode 100644
index 000000000000..872b88a3776d
--- /dev/null
+++ b/packages/SettingsLib/res/values-w840dp-port/dimens.xml
@@ -0,0 +1,21 @@
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<resources>
+ <integer name="avatar_picker_columns">4</integer>
+ <dimen name="avatar_size_in_picker">148dp</dimen>
+ <dimen name="avatar_picker_padding">8dp</dimen>
+ <dimen name="avatar_picker_margin">6dp</dimen>
+</resources> \ No newline at end of file
diff --git a/packages/SettingsLib/res/values-w960dp-land/dimens.xml b/packages/SettingsLib/res/values-w960dp-land/dimens.xml
new file mode 100644
index 000000000000..8403dba54329
--- /dev/null
+++ b/packages/SettingsLib/res/values-w960dp-land/dimens.xml
@@ -0,0 +1,21 @@
+<!--
+ Copyright (C) 2022 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+<resources>
+ <integer name="avatar_picker_columns">4</integer>
+ <dimen name="avatar_size_in_picker">96dp</dimen>
+ <dimen name="avatar_picker_padding">6dp</dimen>
+ <dimen name="avatar_picker_margin">2dp</dimen>
+</resources>
diff --git a/packages/SettingsLib/res/values/arrays.xml b/packages/SettingsLib/res/values/arrays.xml
index 2b5e9cdc017d..93e3deef7aa5 100644
--- a/packages/SettingsLib/res/values/arrays.xml
+++ b/packages/SettingsLib/res/values/arrays.xml
@@ -647,4 +647,6 @@
<item>disabled</item>
</array>
+ <array name="avatar_images"/>
+
</resources>
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index 9ee42b648d3d..120df76218b3 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -102,4 +102,11 @@
<dimen name="user_photo_size_in_profile_info_dialog">112dp</dimen>
<dimen name="add_a_photo_icon_size_in_profile_info_dialog">32dp</dimen>
+ <integer name="avatar_picker_columns">3</integer>
+ <dimen name="avatar_size_in_picker">96dp</dimen>
+ <dimen name="avatar_picker_padding">6dp</dimen>
+ <dimen name="avatar_picker_margin">2dp</dimen>
+
+ <dimen name="avatar_picker_icon_inset">25dp</dimen>
+
</resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 5ada02825b31..af6a658f362a 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1548,4 +1548,18 @@
<!-- Content description of the no calling for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_no_calling">No calling.</string>
+
+ <!-- Screensaver overlay which displays the time. [CHAR LIMIT=20] -->
+ <string name="dream_complication_title_time">Time</string>
+ <!-- Screensaver overlay which displays the date. [CHAR LIMIT=20] -->
+ <string name="dream_complication_title_date">Date</string>
+ <!-- Screensaver overlay which displays the weather. [CHAR LIMIT=20] -->
+ <string name="dream_complication_title_weather">Weather</string>
+ <!-- Screensaver overlay which displays air quality. [CHAR LIMIT=20] -->
+ <string name="dream_complication_title_aqi">Air Quality</string>
+ <!-- Screensaver overlay which displays cast info. [CHAR LIMIT=20] -->
+ <string name="dream_complication_title_cast_info">Cast Info</string>
+
+ <!-- Title for a screen allowing the user to choose a profile picture. [CHAR LIMIT=NONE] -->
+ <string name="avatar_picker_title">Choose a profile picture</string>
</resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
index 46e31ceb7485..6bf43e528009 100644
--- a/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/dream/DreamBackend.java
@@ -34,6 +34,7 @@ import android.os.ServiceManager;
import android.provider.Settings;
import android.service.dreams.DreamService;
import android.service.dreams.IDreamManager;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Xml;
@@ -50,6 +51,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
@@ -292,6 +294,11 @@ public class DreamBackend {
}
}
+ /** Returns whether a particular complication is enabled */
+ public boolean isComplicationEnabled(@ComplicationType int complication) {
+ return getEnabledComplications().contains(complication);
+ }
+
/** Gets all complications which have been enabled by the user. */
public Set<Integer> getEnabledComplications() {
final String enabledComplications = Settings.Secure.getString(
@@ -331,6 +338,35 @@ public class DreamBackend {
convertToString(enabledComplications));
}
+ /**
+ * Gets the title of a particular complication type to be displayed to the user. If there
+ * is no title, null is returned.
+ */
+ @Nullable
+ public CharSequence getComplicationTitle(@ComplicationType int complicationType) {
+ int res = 0;
+ switch (complicationType) {
+ case COMPLICATION_TYPE_TIME:
+ res = R.string.dream_complication_title_time;
+ break;
+ case COMPLICATION_TYPE_DATE:
+ res = R.string.dream_complication_title_date;
+ break;
+ case COMPLICATION_TYPE_WEATHER:
+ res = R.string.dream_complication_title_weather;
+ break;
+ case COMPLICATION_TYPE_AIR_QUALITY:
+ res = R.string.dream_complication_title_aqi;
+ break;
+ case COMPLICATION_TYPE_CAST_INFO:
+ res = R.string.dream_complication_title_cast_info;
+ break;
+ default:
+ return null;
+ }
+ return mContext.getString(res);
+ }
+
private static String convertToString(Set<Integer> set) {
return set.stream()
.map(String::valueOf)
@@ -338,6 +374,9 @@ public class DreamBackend {
}
private static Set<Integer> parseFromString(String string) {
+ if (TextUtils.isEmpty(string)) {
+ return new HashSet<>();
+ }
return Arrays.stream(string.split(","))
.map(Integer::parseInt)
.collect(Collectors.toSet());
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/AvatarPhotoController.java b/packages/SettingsLib/src/com/android/settingslib/users/AvatarPhotoController.java
new file mode 100644
index 000000000000..61b8911acea4
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/users/AvatarPhotoController.java
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.users;
+
+import android.app.Activity;
+import android.content.ClipData;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.media.ExifInterface;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.StrictMode;
+import android.provider.ContactsContract;
+import android.provider.MediaStore;
+import android.util.EventLog;
+import android.util.Log;
+
+import androidx.core.content.FileProvider;
+
+import libcore.io.Streams;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+class AvatarPhotoController {
+ private static final String TAG = "AvatarPhotoController";
+
+ private static final int REQUEST_CODE_CHOOSE_PHOTO = 1001;
+ private static final int REQUEST_CODE_TAKE_PHOTO = 1002;
+ private static final int REQUEST_CODE_CROP_PHOTO = 1003;
+ // in rare cases we get a null Cursor when querying for DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI
+ // so we need a default photo size
+ private static final int DEFAULT_PHOTO_SIZE = 500;
+
+ private static final String IMAGES_DIR = "multi_user";
+ private static final String CROP_PICTURE_FILE_NAME = "CropEditUserPhoto.jpg";
+ private static final String TAKE_PICTURE_FILE_NAME = "TakeEditUserPhoto.jpg";
+
+ private final int mPhotoSize;
+
+ private final AvatarPickerActivity mActivity;
+ private final String mFileAuthority;
+
+ private final File mImagesDir;
+ private final Uri mCropPictureUri;
+ private final Uri mTakePictureUri;
+
+ AvatarPhotoController(AvatarPickerActivity activity, boolean waiting, String fileAuthority) {
+ mActivity = activity;
+ mFileAuthority = fileAuthority;
+
+ mImagesDir = new File(activity.getCacheDir(), IMAGES_DIR);
+ mImagesDir.mkdir();
+ mCropPictureUri = createTempImageUri(activity, CROP_PICTURE_FILE_NAME, !waiting);
+ mTakePictureUri = createTempImageUri(activity, TAKE_PICTURE_FILE_NAME, !waiting);
+ mPhotoSize = getPhotoSize(activity);
+ }
+
+ /**
+ * Handles activity result from containing activity/fragment after a take/choose/crop photo
+ * action result is received.
+ */
+ public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (resultCode != Activity.RESULT_OK) {
+ return false;
+ }
+ final Uri pictureUri = data != null && data.getData() != null
+ ? data.getData() : mTakePictureUri;
+
+ // Check if the result is a content uri
+ if (!ContentResolver.SCHEME_CONTENT.equals(pictureUri.getScheme())) {
+ Log.e(TAG, "Invalid pictureUri scheme: " + pictureUri.getScheme());
+ EventLog.writeEvent(0x534e4554, "172939189", -1, pictureUri.getPath());
+ return false;
+ }
+
+ switch (requestCode) {
+ case REQUEST_CODE_CROP_PHOTO:
+ mActivity.returnUriResult(pictureUri);
+ return true;
+ case REQUEST_CODE_TAKE_PHOTO:
+ case REQUEST_CODE_CHOOSE_PHOTO:
+ if (mTakePictureUri.equals(pictureUri)) {
+ if (PhotoCapabilityUtils.canCropPhoto(mActivity)) {
+ cropPhoto();
+ } else {
+ onPhotoNotCropped(pictureUri);
+ }
+ } else {
+ copyAndCropPhoto(pictureUri);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ void takePhoto() {
+ Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE_SECURE);
+ appendOutputExtra(intent, mTakePictureUri);
+ mActivity.startActivityForResult(intent, REQUEST_CODE_TAKE_PHOTO);
+ }
+
+ void choosePhoto() {
+ Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES, null);
+ intent.setType("image/*");
+ mActivity.startActivityForResult(intent, REQUEST_CODE_CHOOSE_PHOTO);
+ }
+
+ private void copyAndCropPhoto(final Uri pictureUri) {
+ // TODO: Replace AsyncTask
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ final ContentResolver cr = mActivity.getContentResolver();
+ try (InputStream in = cr.openInputStream(pictureUri);
+ OutputStream out = cr.openOutputStream(mTakePictureUri)) {
+ Streams.copy(in, out);
+ } catch (IOException e) {
+ Log.w(TAG, "Failed to copy photo", e);
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void result) {
+ if (!mActivity.isFinishing() && !mActivity.isDestroyed()) {
+ cropPhoto();
+ }
+ }
+ }.execute();
+ }
+
+ private void cropPhoto() {
+ // TODO: Use a public intent, when there is one.
+ Intent intent = new Intent("com.android.camera.action.CROP");
+ intent.setDataAndType(mTakePictureUri, "image/*");
+ appendOutputExtra(intent, mCropPictureUri);
+ appendCropExtras(intent);
+ if (intent.resolveActivity(mActivity.getPackageManager()) != null) {
+ try {
+ StrictMode.disableDeathOnFileUriExposure();
+ mActivity.startActivityForResult(intent, REQUEST_CODE_CROP_PHOTO);
+ } finally {
+ StrictMode.enableDeathOnFileUriExposure();
+ }
+ } else {
+ onPhotoNotCropped(mTakePictureUri);
+ }
+ }
+
+ private void appendOutputExtra(Intent intent, Uri pictureUri) {
+ intent.putExtra(MediaStore.EXTRA_OUTPUT, pictureUri);
+ intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+ | Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ intent.setClipData(ClipData.newRawUri(MediaStore.EXTRA_OUTPUT, pictureUri));
+ }
+
+ private void appendCropExtras(Intent intent) {
+ intent.putExtra("crop", "true");
+ intent.putExtra("scale", true);
+ intent.putExtra("scaleUpIfNeeded", true);
+ intent.putExtra("aspectX", 1);
+ intent.putExtra("aspectY", 1);
+ intent.putExtra("outputX", mPhotoSize);
+ intent.putExtra("outputY", mPhotoSize);
+ }
+
+ private void onPhotoNotCropped(final Uri data) {
+ // TODO: Replace AsyncTask to avoid possible memory leaks and handle configuration change
+ new AsyncTask<Void, Void, Bitmap>() {
+ @Override
+ protected Bitmap doInBackground(Void... params) {
+ // Scale and crop to a square aspect ratio
+ Bitmap croppedImage = Bitmap.createBitmap(mPhotoSize, mPhotoSize,
+ Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(croppedImage);
+ Bitmap fullImage;
+ try {
+ InputStream imageStream = mActivity.getContentResolver()
+ .openInputStream(data);
+ fullImage = BitmapFactory.decodeStream(imageStream);
+ } catch (FileNotFoundException fe) {
+ return null;
+ }
+ if (fullImage != null) {
+ int rotation = getRotation(mActivity, data);
+ final int squareSize = Math.min(fullImage.getWidth(),
+ fullImage.getHeight());
+ final int left = (fullImage.getWidth() - squareSize) / 2;
+ final int top = (fullImage.getHeight() - squareSize) / 2;
+
+ Matrix matrix = new Matrix();
+ RectF rectSource = new RectF(left, top,
+ left + squareSize, top + squareSize);
+ RectF rectDest = new RectF(0, 0, mPhotoSize, mPhotoSize);
+ matrix.setRectToRect(rectSource, rectDest, Matrix.ScaleToFit.CENTER);
+ matrix.postRotate(rotation, mPhotoSize / 2f, mPhotoSize / 2f);
+ canvas.drawBitmap(fullImage, matrix, new Paint());
+ return croppedImage;
+ } else {
+ // Bah! Got nothin.
+ return null;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Bitmap bitmap) {
+ saveBitmapToFile(bitmap, new File(mImagesDir, CROP_PICTURE_FILE_NAME));
+ mActivity.returnUriResult(mCropPictureUri);
+ }
+ }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
+ }
+
+ /**
+ * Reads the image's exif data and determines the rotation degree needed to display the image
+ * in portrait mode.
+ */
+ private int getRotation(Context context, Uri selectedImage) {
+ int rotation = -1;
+ try {
+ InputStream imageStream = context.getContentResolver().openInputStream(selectedImage);
+ ExifInterface exif = new ExifInterface(imageStream);
+ rotation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1);
+ } catch (IOException exception) {
+ Log.e(TAG, "Error while getting rotation", exception);
+ }
+
+ switch (rotation) {
+ case ExifInterface.ORIENTATION_ROTATE_90:
+ return 90;
+ case ExifInterface.ORIENTATION_ROTATE_180:
+ return 180;
+ case ExifInterface.ORIENTATION_ROTATE_270:
+ return 270;
+ default:
+ return 0;
+ }
+ }
+
+ private void saveBitmapToFile(Bitmap bitmap, File file) {
+ try {
+ OutputStream os = new FileOutputStream(file);
+ bitmap.compress(Bitmap.CompressFormat.PNG, 100, os);
+ os.flush();
+ os.close();
+ } catch (IOException e) {
+ Log.e(TAG, "Cannot create temp file", e);
+ }
+ }
+
+ private static int getPhotoSize(Context context) {
+ try (Cursor cursor = context.getContentResolver().query(
+ ContactsContract.DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI,
+ new String[]{ContactsContract.DisplayPhoto.DISPLAY_MAX_DIM}, null, null, null)) {
+ if (cursor != null) {
+ cursor.moveToFirst();
+ return cursor.getInt(0);
+ } else {
+ return DEFAULT_PHOTO_SIZE;
+ }
+ }
+ }
+
+ private Uri createTempImageUri(Context context, String fileName, boolean purge) {
+ final File fullPath = new File(mImagesDir, fileName);
+ if (purge) {
+ fullPath.delete();
+ }
+ return FileProvider.getUriForFile(context, mFileAuthority, fullPath);
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/AvatarPickerActivity.java b/packages/SettingsLib/src/com/android/settingslib/users/AvatarPickerActivity.java
new file mode 100644
index 000000000000..50015e653399
--- /dev/null
+++ b/packages/SettingsLib/src/com/android/settingslib/users/AvatarPickerActivity.java
@@ -0,0 +1,334 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settingslib.users;
+
+import android.app.Activity;
+import android.content.ContentResolver;
+import android.content.Intent;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+
+import androidx.annotation.NonNull;
+import androidx.core.graphics.drawable.RoundedBitmapDrawable;
+import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory;
+import androidx.recyclerview.widget.GridLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.internal.util.UserIcons;
+import com.android.settingslib.R;
+
+import com.google.android.setupcompat.template.FooterBarMixin;
+import com.google.android.setupcompat.template.FooterButton;
+import com.google.android.setupdesign.GlifLayout;
+import com.google.android.setupdesign.util.ThemeHelper;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Activity to allow the user to choose a user profile picture.
+ *
+ * <p>Options are provided to take a photo or choose a photo using the photo picker. In addition,
+ * preselected avatar images may be provided in the resource array {@code avatar_images}. If
+ * provided, every element of that array must be a bitmap drawable.
+ *
+ * <p>If preselected images are not provided, the default avatar will be shown instead, in a range
+ * of colors.
+ *
+ * <p>This activity should be started with startActivityForResult. If a photo or a preselected image
+ * is selected, a Uri will be returned in the data field of the result intent. If a colored default
+ * avatar is selected, the chosen color will be returned as {@code EXTRA_DEFAULT_ICON_TINT_COLOR}
+ * and the data field will be empty.
+ */
+public class AvatarPickerActivity extends Activity {
+
+ static final String EXTRA_FILE_AUTHORITY = "file_authority";
+ static final String EXTRA_DEFAULT_ICON_TINT_COLOR = "default_icon_tint_color";
+
+ private static final String KEY_AWAITING_RESULT = "awaiting_result";
+ private static final String KEY_SELECTED_POSITION = "selected_position";
+
+ private boolean mWaitingForActivityResult;
+
+ private FooterButton mDoneButton;
+ private AvatarAdapter mAdapter;
+
+ private AvatarPhotoController mAvatarPhotoController;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ ThemeHelper.trySetDynamicColor(this);
+ setContentView(R.layout.avatar_picker);
+ setUpButtons();
+
+ RecyclerView recyclerView = findViewById(R.id.avatar_grid);
+ mAdapter = new AvatarAdapter();
+ recyclerView.setAdapter(mAdapter);
+ recyclerView.setLayoutManager(new GridLayoutManager(this,
+ getResources().getInteger(R.integer.avatar_picker_columns)));
+
+ restoreState(savedInstanceState);
+
+ mAvatarPhotoController = new AvatarPhotoController(
+ this, mWaitingForActivityResult, getFileAuthority());
+ }
+
+ private void setUpButtons() {
+ GlifLayout glifLayout = findViewById(R.id.glif_layout);
+ FooterBarMixin mixin = glifLayout.getMixin(FooterBarMixin.class);
+
+ FooterButton secondaryButton =
+ new FooterButton.Builder(this)
+ .setText("Cancel")
+ .setListener(view -> cancel())
+ .build();
+
+ mDoneButton =
+ new FooterButton.Builder(this)
+ .setText("Done")
+ .setListener(view -> mAdapter.returnSelectionResult())
+ .build();
+ mDoneButton.setEnabled(false);
+
+ mixin.setSecondaryButton(secondaryButton);
+ mixin.setPrimaryButton(mDoneButton);
+ }
+
+ private String getFileAuthority() {
+ String authority = getIntent().getStringExtra(EXTRA_FILE_AUTHORITY);
+ if (authority == null) {
+ throw new IllegalStateException("File authority must be provided");
+ }
+ return authority;
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ mWaitingForActivityResult = false;
+ mAvatarPhotoController.onActivityResult(requestCode, resultCode, data);
+ }
+
+ @Override
+ protected void onSaveInstanceState(@NonNull Bundle outState) {
+ outState.putBoolean(KEY_AWAITING_RESULT, mWaitingForActivityResult);
+ outState.putInt(KEY_SELECTED_POSITION, mAdapter.mSelectedPosition);
+ super.onSaveInstanceState(outState);
+ }
+
+ private void restoreState(Bundle savedInstanceState) {
+ if (savedInstanceState != null) {
+ mWaitingForActivityResult = savedInstanceState.getBoolean(KEY_AWAITING_RESULT, false);
+ mAdapter.mSelectedPosition =
+ savedInstanceState.getInt(KEY_SELECTED_POSITION, AvatarAdapter.NONE);
+ }
+ }
+
+ @Override
+ public void startActivityForResult(Intent intent, int requestCode) {
+ mWaitingForActivityResult = true;
+ super.startActivityForResult(intent, requestCode);
+ }
+
+ void returnUriResult(Uri uri) {
+ Intent resultData = new Intent();
+ resultData.setData(uri);
+ setResult(RESULT_OK, resultData);
+ finish();
+ }
+
+ void returnColorResult(int color) {
+ Intent resultData = new Intent();
+ resultData.putExtra(EXTRA_DEFAULT_ICON_TINT_COLOR, color);
+ setResult(RESULT_OK, resultData);
+ finish();
+ }
+
+ private void cancel() {
+ setResult(RESULT_CANCELED);
+ finish();
+ }
+
+ private class AvatarAdapter extends RecyclerView.Adapter<AvatarViewHolder> {
+
+ private static final int NONE = -1;
+
+ private final int mTakePhotoPosition;
+ private final int mChoosePhotoPosition;
+ private final int mPreselectedImageStartPosition;
+
+ private final List<Drawable> mImageDrawables;
+ private final TypedArray mPreselectedImages;
+ private final int[] mUserIconColors;
+ private int mSelectedPosition = NONE;
+
+ AvatarAdapter() {
+ final boolean canTakePhoto =
+ PhotoCapabilityUtils.canTakePhoto(AvatarPickerActivity.this);
+ final boolean canChoosePhoto =
+ PhotoCapabilityUtils.canChoosePhoto(AvatarPickerActivity.this);
+ mTakePhotoPosition = (canTakePhoto ? 0 : NONE);
+ mChoosePhotoPosition = (canChoosePhoto ? (canTakePhoto ? 1 : 0) : NONE);
+ mPreselectedImageStartPosition = (canTakePhoto ? 1 : 0) + (canChoosePhoto ? 1 : 0);
+
+ mPreselectedImages = getResources().obtainTypedArray(R.array.avatar_images);
+ mUserIconColors = UserIcons.getUserIconColors(getResources());
+ mImageDrawables = buildDrawableList();
+ }
+
+ @NonNull
+ @Override
+ public AvatarViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int position) {
+ LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
+ View itemView = layoutInflater.inflate(R.layout.avatar_item, parent, false);
+ return new AvatarViewHolder(itemView);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull AvatarViewHolder viewHolder, int position) {
+ if (position == mTakePhotoPosition) {
+ viewHolder.setDrawable(getDrawable(R.drawable.avatar_take_photo_circled));
+ viewHolder.setClickListener(view -> mAvatarPhotoController.takePhoto());
+
+ } else if (position == mChoosePhotoPosition) {
+ viewHolder.setDrawable(getDrawable(R.drawable.avatar_choose_photo_circled));
+ viewHolder.setClickListener(view -> mAvatarPhotoController.choosePhoto());
+
+ } else if (position >= mPreselectedImageStartPosition) {
+ viewHolder.setSelected(position == mSelectedPosition);
+ viewHolder.setDrawable(mImageDrawables.get(indexFromPosition(position)));
+ viewHolder.setClickListener(view -> {
+ if (mSelectedPosition == position) {
+ deselect(position);
+ } else {
+ select(position);
+ }
+ });
+ }
+ }
+
+ @Override
+ public int getItemCount() {
+ return mPreselectedImageStartPosition + mImageDrawables.size();
+ }
+
+ private List<Drawable> buildDrawableList() {
+ List<Drawable> result = new ArrayList<>();
+
+ for (int i = 0; i < mPreselectedImages.length(); i++) {
+ Drawable drawable = mPreselectedImages.getDrawable(i);
+ if (drawable instanceof BitmapDrawable) {
+ result.add(circularDrawableFrom((BitmapDrawable) drawable));
+ } else {
+ throw new IllegalStateException("Avatar drawables must be bitmaps");
+ }
+ }
+ if (!result.isEmpty()) {
+ return result;
+ }
+
+ // No preselected images. Use tinted default icon.
+ for (int i = 0; i < mUserIconColors.length; i++) {
+ result.add(UserIcons.getDefaultUserIconInColor(getResources(), mUserIconColors[i]));
+ }
+ return result;
+ }
+
+ private Drawable circularDrawableFrom(BitmapDrawable drawable) {
+ Bitmap bitmap = drawable.getBitmap();
+
+ RoundedBitmapDrawable roundedBitmapDrawable =
+ RoundedBitmapDrawableFactory.create(getResources(), bitmap);
+ roundedBitmapDrawable.setCircular(true);
+
+ return roundedBitmapDrawable;
+ }
+
+ private int indexFromPosition(int position) {
+ return position - mPreselectedImageStartPosition;
+ }
+
+ private void select(int position) {
+ final int oldSelection = mSelectedPosition;
+ mSelectedPosition = position;
+ notifyItemChanged(position);
+ if (oldSelection != NONE) {
+ notifyItemChanged(oldSelection);
+ } else {
+ mDoneButton.setEnabled(true);
+ }
+ }
+
+ private void deselect(int position) {
+ mSelectedPosition = NONE;
+ notifyItemChanged(position);
+ mDoneButton.setEnabled(false);
+ }
+
+ private void returnSelectionResult() {
+ int index = indexFromPosition(mSelectedPosition);
+ if (mPreselectedImages.length() > 0) {
+ int resourceId = mPreselectedImages.getResourceId(index, -1);
+ if (resourceId == -1) {
+ throw new IllegalStateException("Preselected avatar images must be resources.");
+ }
+ returnUriResult(uriForResourceId(resourceId));
+ } else {
+ returnColorResult(
+ mUserIconColors[index]);
+ }
+ }
+
+ private Uri uriForResourceId(int resourceId) {
+ return new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE)
+ .authority(getResources().getResourcePackageName(resourceId))
+ .appendPath(getResources().getResourceTypeName(resourceId))
+ .appendPath(getResources().getResourceEntryName(resourceId))
+ .build();
+ }
+ }
+
+ private static class AvatarViewHolder extends RecyclerView.ViewHolder {
+ private final ImageView mImageView;
+
+ AvatarViewHolder(View view) {
+ super(view);
+ mImageView = view.findViewById(R.id.avatar_image);
+ }
+
+ public void setDrawable(Drawable drawable) {
+ mImageView.setImageDrawable(drawable);
+ }
+
+ public void setClickListener(View.OnClickListener listener) {
+ mImageView.setOnClickListener(listener);
+ }
+
+ public void setSelected(boolean selected) {
+ mImageView.setSelected(selected);
+ }
+ }
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/EditUserInfoController.java b/packages/SettingsLib/src/com/android/settingslib/users/EditUserInfoController.java
index 62043363d85f..80ee86f5e489 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/EditUserInfoController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/EditUserInfoController.java
@@ -25,6 +25,7 @@ import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.UserHandle;
+import android.os.UserManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
@@ -36,6 +37,8 @@ import androidx.annotation.VisibleForTesting;
import com.android.internal.util.UserIcons;
import com.android.settingslib.R;
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.drawable.CircleFramedDrawable;
import java.io.File;
@@ -139,12 +142,20 @@ public class EditUserInfoController {
Drawable userIcon = getUserIcon(activity, defaultUserIcon);
userPhotoView.setImageDrawable(userIcon);
- if (canChangePhoto(activity)) {
- mEditUserPhotoController = createEditUserPhotoController(activity, activityStarter,
- userPhotoView);
- } else {
- // some users can't change their photos, so we need to remove the suggestive icon
+ if (isChangePhotoRestrictedByBase(activity)) {
+ // some users can't change their photos so we need to remove the suggestive icon
content.findViewById(R.id.add_a_photo_icon).setVisibility(View.GONE);
+ } else {
+ RestrictedLockUtils.EnforcedAdmin adminRestriction =
+ getChangePhotoAdminRestriction(activity);
+ if (adminRestriction != null) {
+ userPhotoView.setOnClickListener(view ->
+ RestrictedLockUtils.sendShowAdminSupportDetailsIntent(
+ activity, adminRestriction));
+ } else {
+ mEditUserPhotoController = createEditUserPhotoController(activity, activityStarter,
+ userPhotoView);
+ }
}
mEditUserInfoDialog = buildDialog(activity, content, userNameView, oldUserIcon,
@@ -203,16 +214,21 @@ public class EditUserInfoController {
}
@VisibleForTesting
- boolean canChangePhoto(Context context) {
- return (PhotoCapabilityUtils.canCropPhoto(context)
- && PhotoCapabilityUtils.canChoosePhoto(context))
- || PhotoCapabilityUtils.canTakePhoto(context);
+ boolean isChangePhotoRestrictedByBase(Context context) {
+ return RestrictedLockUtilsInternal.hasBaseUserRestriction(
+ context, UserManager.DISALLOW_SET_USER_ICON, UserHandle.myUserId());
+ }
+
+ @VisibleForTesting
+ RestrictedLockUtils.EnforcedAdmin getChangePhotoAdminRestriction(Context context) {
+ return RestrictedLockUtilsInternal.checkIfRestrictionEnforced(
+ context, UserManager.DISALLOW_SET_USER_ICON, UserHandle.myUserId());
}
@VisibleForTesting
EditUserPhotoController createEditUserPhotoController(Activity activity,
ActivityStarter activityStarter, ImageView userPhotoView) {
return new EditUserPhotoController(activity, activityStarter, userPhotoView,
- mSavedPhoto, mWaitingForActivityResult, mFileAuthority);
+ mSavedPhoto, mFileAuthority);
}
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java b/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java
index f9584a3e15e9..f8bb38b5978e 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/EditUserPhotoController.java
@@ -16,46 +16,21 @@
package com.android.settingslib.users;
+import android.annotation.NonNull;
import android.app.Activity;
-import android.content.ClipData;
-import android.content.ContentResolver;
-import android.content.Context;
import android.content.Intent;
-import android.database.Cursor;
import android.graphics.Bitmap;
-import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.RectF;
import android.graphics.drawable.Drawable;
-import android.media.ExifInterface;
import android.net.Uri;
-import android.os.AsyncTask;
-import android.os.StrictMode;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.ContactsContract.DisplayPhoto;
-import android.provider.MediaStore;
-import android.util.EventLog;
import android.util.Log;
-import android.view.Gravity;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ArrayAdapter;
import android.widget.ImageView;
-import android.widget.ListPopupWindow;
-import android.widget.TextView;
-
-import androidx.core.content.FileProvider;
+import com.android.internal.util.UserIcons;
import com.android.settingslib.R;
-import com.android.settingslib.RestrictedLockUtils;
-import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.drawable.CircleFramedDrawable;
-
-import libcore.io.Streams;
+import com.android.settingslib.utils.ThreadUtils;
import java.io.File;
import java.io.FileNotFoundException;
@@ -63,8 +38,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.concurrent.ExecutionException;
/**
* This class contains logic for starting activities to take/choose/crop photo, reads and transforms
@@ -75,45 +49,30 @@ public class EditUserPhotoController {
// It seems that this class generates custom request codes and they may
// collide with ours, these values are very unlikely to have a conflict.
- private static final int REQUEST_CODE_CHOOSE_PHOTO = 1001;
- private static final int REQUEST_CODE_TAKE_PHOTO = 1002;
- private static final int REQUEST_CODE_CROP_PHOTO = 1003;
- // in rare cases we get a null Cursor when querying for DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI
- // so we need a default photo size
- private static final int DEFAULT_PHOTO_SIZE = 500;
+ private static final int REQUEST_CODE_PICK_AVATAR = 1004;
private static final String IMAGES_DIR = "multi_user";
- private static final String CROP_PICTURE_FILE_NAME = "CropEditUserPhoto.jpg";
- private static final String TAKE_PICTURE_FILE_NAME = "TakeEditUserPhoto.jpg";
private static final String NEW_USER_PHOTO_FILE_NAME = "NewUserPhoto.png";
- private final int mPhotoSize;
-
private final Activity mActivity;
private final ActivityStarter mActivityStarter;
private final ImageView mImageView;
private final String mFileAuthority;
private final File mImagesDir;
- private final Uri mCropPictureUri;
- private final Uri mTakePictureUri;
-
private Bitmap mNewUserPhotoBitmap;
private Drawable mNewUserPhotoDrawable;
public EditUserPhotoController(Activity activity, ActivityStarter activityStarter,
- ImageView view, Bitmap bitmap, boolean waiting, String fileAuthority) {
+ ImageView view, Bitmap bitmap, String fileAuthority) {
mActivity = activity;
mActivityStarter = activityStarter;
- mImageView = view;
mFileAuthority = fileAuthority;
mImagesDir = new File(activity.getCacheDir(), IMAGES_DIR);
mImagesDir.mkdir();
- mCropPictureUri = createTempImageUri(activity, CROP_PICTURE_FILE_NAME, !waiting);
- mTakePictureUri = createTempImageUri(activity, TAKE_PICTURE_FILE_NAME, !waiting);
- mPhotoSize = getPhotoSize(activity);
- mImageView.setOnClickListener(v -> showUpdatePhotoPopup());
+ mImageView = view;
+ mImageView.setOnClickListener(v -> showAvatarPicker());
mNewUserPhotoBitmap = bitmap;
}
@@ -125,32 +84,19 @@ public class EditUserPhotoController {
if (resultCode != Activity.RESULT_OK) {
return false;
}
- final Uri pictureUri = data != null && data.getData() != null
- ? data.getData() : mTakePictureUri;
- // Check if the result is a content uri
- if (!ContentResolver.SCHEME_CONTENT.equals(pictureUri.getScheme())) {
- Log.e(TAG, "Invalid pictureUri scheme: " + pictureUri.getScheme());
- EventLog.writeEvent(0x534e4554, "172939189", -1, pictureUri.getPath());
- return false;
- }
-
- switch (requestCode) {
- case REQUEST_CODE_CROP_PHOTO:
- onPhotoCropped(pictureUri);
+ if (requestCode == REQUEST_CODE_PICK_AVATAR) {
+ if (data.hasExtra(AvatarPickerActivity.EXTRA_DEFAULT_ICON_TINT_COLOR)) {
+ int tintColor =
+ data.getIntExtra(AvatarPickerActivity.EXTRA_DEFAULT_ICON_TINT_COLOR, -1);
+ onDefaultIconSelected(tintColor);
return true;
- case REQUEST_CODE_TAKE_PHOTO:
- case REQUEST_CODE_CHOOSE_PHOTO:
- if (mTakePictureUri.equals(pictureUri)) {
- if (PhotoCapabilityUtils.canCropPhoto(mActivity)) {
- cropPhoto();
- } else {
- onPhotoNotCropped(pictureUri);
- }
- } else {
- copyAndCropPhoto(pictureUri);
- }
+ }
+ if (data.getData() != null) {
+ onPhotoCropped(data.getData());
return true;
+ }
+
}
return false;
}
@@ -159,224 +105,60 @@ public class EditUserPhotoController {
return mNewUserPhotoDrawable;
}
- private void showUpdatePhotoPopup() {
- final Context context = mImageView.getContext();
- final boolean canTakePhoto = PhotoCapabilityUtils.canTakePhoto(context);
- final boolean canChoosePhoto = PhotoCapabilityUtils.canChoosePhoto(context);
-
- if (!canTakePhoto && !canChoosePhoto) {
- return;
- }
-
- final List<EditUserPhotoController.RestrictedMenuItem> items = new ArrayList<>();
-
- if (canTakePhoto) {
- final String title = context.getString(R.string.user_image_take_photo);
- items.add(new RestrictedMenuItem(context, title, UserManager.DISALLOW_SET_USER_ICON,
- this::takePhoto));
- }
-
- if (canChoosePhoto) {
- final String title = context.getString(R.string.user_image_choose_photo);
- items.add(new RestrictedMenuItem(context, title, UserManager.DISALLOW_SET_USER_ICON,
- this::choosePhoto));
- }
-
- final ListPopupWindow listPopupWindow = new ListPopupWindow(context);
-
- listPopupWindow.setAnchorView(mImageView);
- listPopupWindow.setModal(true);
- listPopupWindow.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
- listPopupWindow.setAdapter(new RestrictedPopupMenuAdapter(context, items));
-
- final int width = Math.max(mImageView.getWidth(), context.getResources()
- .getDimensionPixelSize(R.dimen.update_user_photo_popup_min_width));
- listPopupWindow.setWidth(width);
- listPopupWindow.setDropDownGravity(Gravity.START);
-
- listPopupWindow.setOnItemClickListener((parent, view, position, id) -> {
- listPopupWindow.dismiss();
- final RestrictedMenuItem item =
- (RestrictedMenuItem) parent.getAdapter().getItem(position);
- item.doAction();
- });
-
- listPopupWindow.show();
- }
-
- private void takePhoto() {
- Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE_SECURE);
- appendOutputExtra(intent, mTakePictureUri);
- mActivityStarter.startActivityForResult(intent, REQUEST_CODE_TAKE_PHOTO);
- }
-
- private void choosePhoto() {
- Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null);
- intent.setType("image/*");
- appendOutputExtra(intent, mTakePictureUri);
- mActivityStarter.startActivityForResult(intent, REQUEST_CODE_CHOOSE_PHOTO);
+ private void showAvatarPicker() {
+ Intent intent = new Intent(mImageView.getContext(), AvatarPickerActivity.class);
+ intent.putExtra(AvatarPickerActivity.EXTRA_FILE_AUTHORITY, mFileAuthority);
+ mActivityStarter.startActivityForResult(intent, REQUEST_CODE_PICK_AVATAR);
}
- private void copyAndCropPhoto(final Uri pictureUri) {
- // TODO: Replace AsyncTask
- new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... params) {
- final ContentResolver cr = mActivity.getContentResolver();
- try (InputStream in = cr.openInputStream(pictureUri);
- OutputStream out = cr.openOutputStream(mTakePictureUri)) {
- Streams.copy(in, out);
- } catch (IOException e) {
- Log.w(TAG, "Failed to copy photo", e);
- }
- return null;
- }
-
- @Override
- protected void onPostExecute(Void result) {
- if (!mActivity.isFinishing() && !mActivity.isDestroyed()) {
- cropPhoto();
- }
- }
- }.execute();
- }
+ private void onDefaultIconSelected(int tintColor) {
+ try {
+ ThreadUtils.postOnBackgroundThread(() -> {
+ Drawable drawable =
+ UserIcons.getDefaultUserIconInColor(mActivity.getResources(), tintColor);
+ Bitmap bitmap = convertToBitmap(drawable,
+ (int) mActivity.getResources().getDimension(R.dimen.circle_avatar_size));
- private void cropPhoto() {
- // TODO: Use a public intent, when there is one.
- Intent intent = new Intent("com.android.camera.action.CROP");
- intent.setDataAndType(mTakePictureUri, "image/*");
- appendOutputExtra(intent, mCropPictureUri);
- appendCropExtras(intent);
- if (intent.resolveActivity(mActivity.getPackageManager()) != null) {
- try {
- StrictMode.disableDeathOnFileUriExposure();
- mActivityStarter.startActivityForResult(intent, REQUEST_CODE_CROP_PHOTO);
- } finally {
- StrictMode.enableDeathOnFileUriExposure();
- }
- } else {
- onPhotoNotCropped(mTakePictureUri);
+ ThreadUtils.postOnMainThread(() -> onPhotoProcessed(bitmap));
+ }).get();
+ } catch (InterruptedException | ExecutionException e) {
+ Log.e(TAG, "Error processing default icon", e);
}
}
- private void appendOutputExtra(Intent intent, Uri pictureUri) {
- intent.putExtra(MediaStore.EXTRA_OUTPUT, pictureUri);
- intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION
- | Intent.FLAG_GRANT_READ_URI_PERMISSION);
- intent.setClipData(ClipData.newRawUri(MediaStore.EXTRA_OUTPUT, pictureUri));
- }
-
- private void appendCropExtras(Intent intent) {
- intent.putExtra("crop", "true");
- intent.putExtra("scale", true);
- intent.putExtra("scaleUpIfNeeded", true);
- intent.putExtra("aspectX", 1);
- intent.putExtra("aspectY", 1);
- intent.putExtra("outputX", mPhotoSize);
- intent.putExtra("outputY", mPhotoSize);
+ private static Bitmap convertToBitmap(@NonNull Drawable icon, int size) {
+ Bitmap bitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
+ Canvas canvas = new Canvas(bitmap);
+ icon.setBounds(0, 0, size, size);
+ icon.draw(canvas);
+ return bitmap;
}
private void onPhotoCropped(final Uri data) {
- // TODO: Replace AsyncTask to avoid possible memory leaks and handle configuration change
- new AsyncTask<Void, Void, Bitmap>() {
- @Override
- protected Bitmap doInBackground(Void... params) {
- InputStream imageStream = null;
- try {
- imageStream = mActivity.getContentResolver()
- .openInputStream(data);
- return BitmapFactory.decodeStream(imageStream);
- } catch (FileNotFoundException fe) {
- Log.w(TAG, "Cannot find image file", fe);
- return null;
- } finally {
- if (imageStream != null) {
- try {
- imageStream.close();
- } catch (IOException ioe) {
- Log.w(TAG, "Cannot close image stream", ioe);
- }
+ ThreadUtils.postOnBackgroundThread(() -> {
+ InputStream imageStream = null;
+ Bitmap bitmap = null;
+ try {
+ imageStream = mActivity.getContentResolver()
+ .openInputStream(data);
+ bitmap = BitmapFactory.decodeStream(imageStream);
+ } catch (FileNotFoundException fe) {
+ Log.w(TAG, "Cannot find image file", fe);
+ } finally {
+ if (imageStream != null) {
+ try {
+ imageStream.close();
+ } catch (IOException ioe) {
+ Log.w(TAG, "Cannot close image stream", ioe);
}
}
}
- @Override
- protected void onPostExecute(Bitmap bitmap) {
- onPhotoProcessed(bitmap);
-
- }
- }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
- }
-
- private void onPhotoNotCropped(final Uri data) {
- // TODO: Replace AsyncTask to avoid possible memory leaks and handle configuration change
- new AsyncTask<Void, Void, Bitmap>() {
- @Override
- protected Bitmap doInBackground(Void... params) {
- // Scale and crop to a square aspect ratio
- Bitmap croppedImage = Bitmap.createBitmap(mPhotoSize, mPhotoSize,
- Config.ARGB_8888);
- Canvas canvas = new Canvas(croppedImage);
- Bitmap fullImage;
- try {
- InputStream imageStream = mActivity.getContentResolver()
- .openInputStream(data);
- fullImage = BitmapFactory.decodeStream(imageStream);
- } catch (FileNotFoundException fe) {
- return null;
- }
- if (fullImage != null) {
- int rotation = getRotation(mActivity, data);
- final int squareSize = Math.min(fullImage.getWidth(),
- fullImage.getHeight());
- final int left = (fullImage.getWidth() - squareSize) / 2;
- final int top = (fullImage.getHeight() - squareSize) / 2;
-
- Matrix matrix = new Matrix();
- RectF rectSource = new RectF(left, top,
- left + squareSize, top + squareSize);
- RectF rectDest = new RectF(0, 0, mPhotoSize, mPhotoSize);
- matrix.setRectToRect(rectSource, rectDest, Matrix.ScaleToFit.CENTER);
- matrix.postRotate(rotation, mPhotoSize / 2f, mPhotoSize / 2f);
- canvas.drawBitmap(fullImage, matrix, new Paint());
- return croppedImage;
- } else {
- // Bah! Got nothin.
- return null;
- }
- }
-
- @Override
- protected void onPostExecute(Bitmap bitmap) {
- onPhotoProcessed(bitmap);
+ if (bitmap != null) {
+ Bitmap finalBitmap = bitmap;
+ ThreadUtils.postOnMainThread(() -> onPhotoProcessed(finalBitmap));
}
- }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
- }
-
- /**
- * Reads the image's exif data and determines the rotation degree needed to display the image
- * in portrait mode.
- */
- private int getRotation(Context context, Uri selectedImage) {
- int rotation = -1;
- try {
- InputStream imageStream = context.getContentResolver().openInputStream(selectedImage);
- ExifInterface exif = new ExifInterface(imageStream);
- rotation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1);
- } catch (IOException exception) {
- Log.e(TAG, "Error while getting rotation", exception);
- }
-
- switch (rotation) {
- case ExifInterface.ORIENTATION_ROTATE_90:
- return 90;
- case ExifInterface.ORIENTATION_ROTATE_180:
- return 180;
- case ExifInterface.ORIENTATION_ROTATE_270:
- return 270;
- default:
- return 0;
- }
+ });
}
private void onPhotoProcessed(Bitmap bitmap) {
@@ -386,29 +168,6 @@ public class EditUserPhotoController {
.getInstance(mImageView.getContext(), mNewUserPhotoBitmap);
mImageView.setImageDrawable(mNewUserPhotoDrawable);
}
- new File(mImagesDir, TAKE_PICTURE_FILE_NAME).delete();
- new File(mImagesDir, CROP_PICTURE_FILE_NAME).delete();
- }
-
- private static int getPhotoSize(Context context) {
- try (Cursor cursor = context.getContentResolver().query(
- DisplayPhoto.CONTENT_MAX_DIMENSIONS_URI,
- new String[]{DisplayPhoto.DISPLAY_MAX_DIM}, null, null, null)) {
- if (cursor != null) {
- cursor.moveToFirst();
- return cursor.getInt(0);
- } else {
- return DEFAULT_PHOTO_SIZE;
- }
- }
- }
-
- private Uri createTempImageUri(Context context, String fileName, boolean purge) {
- final File fullPath = new File(mImagesDir, fileName);
- if (purge) {
- fullPath.delete();
- }
- return FileProvider.getUriForFile(context, mFileAuthority, fullPath);
}
File saveNewUserPhotoBitmap() {
@@ -435,84 +194,4 @@ public class EditUserPhotoController {
void removeNewUserPhotoBitmapFile() {
new File(mImagesDir, NEW_USER_PHOTO_FILE_NAME).delete();
}
-
- private static final class RestrictedMenuItem {
- private final Context mContext;
- private final String mTitle;
- private final Runnable mAction;
- private final RestrictedLockUtils.EnforcedAdmin mAdmin;
- // Restriction may be set by system or something else via UserManager.setUserRestriction().
- private final boolean mIsRestrictedByBase;
-
- /**
- * The menu item, used for popup menu. Any element of such a menu can be disabled by admin.
- *
- * @param context A context.
- * @param title The title of the menu item.
- * @param restriction The restriction, that if is set, blocks the menu item.
- * @param action The action on menu item click.
- */
- RestrictedMenuItem(Context context, String title, String restriction,
- Runnable action) {
- mContext = context;
- mTitle = title;
- mAction = action;
-
- final int myUserId = UserHandle.myUserId();
- mAdmin = RestrictedLockUtilsInternal.checkIfRestrictionEnforced(context,
- restriction, myUserId);
- mIsRestrictedByBase = RestrictedLockUtilsInternal.hasBaseUserRestriction(mContext,
- restriction, myUserId);
- }
-
- @Override
- public String toString() {
- return mTitle;
- }
-
- void doAction() {
- if (isRestrictedByBase()) {
- return;
- }
-
- if (isRestrictedByAdmin()) {
- RestrictedLockUtils.sendShowAdminSupportDetailsIntent(mContext, mAdmin);
- return;
- }
-
- mAction.run();
- }
-
- boolean isRestrictedByAdmin() {
- return mAdmin != null;
- }
-
- boolean isRestrictedByBase() {
- return mIsRestrictedByBase;
- }
- }
-
- /**
- * Provide this adapter to ListPopupWindow.setAdapter() to have a popup window menu, where
- * any element can be restricted by admin (profile owner or device owner).
- */
- private static final class RestrictedPopupMenuAdapter extends ArrayAdapter<RestrictedMenuItem> {
- RestrictedPopupMenuAdapter(Context context, List<RestrictedMenuItem> items) {
- super(context, R.layout.restricted_popup_menu_item, R.id.text, items);
- }
-
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- final View view = super.getView(position, convertView, parent);
- final RestrictedMenuItem item = getItem(position);
- final TextView text = (TextView) view.findViewById(R.id.text);
- final ImageView image = (ImageView) view.findViewById(R.id.restricted_icon);
-
- text.setEnabled(!item.isRestrictedByAdmin() && !item.isRestrictedByBase());
- image.setVisibility(item.isRestrictedByAdmin() && !item.isRestrictedByBase()
- ? ImageView.VISIBLE : ImageView.GONE);
-
- return view;
- }
- }
}
diff --git a/packages/SettingsLib/src/com/android/settingslib/users/PhotoCapabilityUtils.java b/packages/SettingsLib/src/com/android/settingslib/users/PhotoCapabilityUtils.java
index 165c2808f16d..b8615a7e5aa9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/users/PhotoCapabilityUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/users/PhotoCapabilityUtils.java
@@ -40,12 +40,12 @@ public class PhotoCapabilityUtils {
/**
* Check if the current user can perform any activity for
- * android.intent.action.GET_CONTENT action for images.
+ * ACTION_PICK_IMAGES action for images.
* Returns false if the device is currently locked and
* requires a PIN, pattern or password to unlock.
*/
public static boolean canChoosePhoto(Context context) {
- Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+ Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
intent.setType("image/*");
boolean canPerformActivityForGetImage =
context.getPackageManager().queryIntentActivities(intent, 0).size() > 0;
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java
index d6c8816ecc58..a5ee4c35f724 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/users/EditUserInfoControllerTest.java
@@ -62,7 +62,7 @@ public class EditUserInfoControllerTest {
@Mock
private ActivityStarter mActivityStarter;
- private boolean mCanChangePhoto;
+ private boolean mPhotoRestrictedByBase;
private Activity mActivity;
private TestEditUserInfoController mController;
@@ -85,8 +85,8 @@ public class EditUserInfoControllerTest {
}
@Override
- boolean canChangePhoto(Context context) {
- return mCanChangePhoto;
+ boolean isChangePhotoRestrictedByBase(Context context) {
+ return mPhotoRestrictedByBase;
}
}
@@ -96,7 +96,7 @@ public class EditUserInfoControllerTest {
mActivity = spy(ActivityController.of(new FragmentActivity()).get());
mActivity.setTheme(R.style.Theme_AppCompat_DayNight);
mController = new TestEditUserInfoController();
- mCanChangePhoto = true;
+ mPhotoRestrictedByBase = true;
}
@Test
@@ -260,7 +260,7 @@ public class EditUserInfoControllerTest {
@Test
public void createDialog_canNotChangePhoto_nullPhotoController() {
- mCanChangePhoto = false;
+ mPhotoRestrictedByBase = false;
mController.createDialog(mActivity, mActivityStarter, mCurrentIcon,
"test", "title", null, null);
diff --git a/packages/SystemUI/res/layout/controls_fullscreen.xml b/packages/SystemUI/res/layout/controls_fullscreen.xml
index 7fd029cb2c1e..11a566588738 100644
--- a/packages/SystemUI/res/layout/controls_fullscreen.xml
+++ b/packages/SystemUI/res/layout/controls_fullscreen.xml
@@ -35,7 +35,8 @@
android:layout_height="wrap_content"
android:clipChildren="false"
android:orientation="vertical"
- android:clipToPadding="false" />
+ android:clipToPadding="false"
+ android:paddingHorizontal="@dimen/controls_padding_horizontal" />
</com.android.systemui.globalactions.MinHeightScrollView>
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/dream_overlay_complications_layer.xml b/packages/SystemUI/res/layout/dream_overlay_complications_layer.xml
index 51359471ff98..2d565a1a04fc 100644
--- a/packages/SystemUI/res/layout/dream_overlay_complications_layer.xml
+++ b/packages/SystemUI/res/layout/dream_overlay_complications_layer.xml
@@ -31,6 +31,7 @@
android:shadowRadius="2.0"
android:singleLine="true"
android:textSize="72sp"
+ android:textColor="@android:color/white"
app:layout_constraintBottom_toTopOf="@+id/date_view"
app:layout_constraintStart_toStartOf="parent" />
<TextClock
@@ -43,7 +44,32 @@
android:format24Hour="EEE, MMM d"
android:singleLine="true"
android:textSize="18sp"
+ android:textColor="@android:color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/time_view"
app:layout_constraintStart_toStartOf="@+id/time_view" />
+ <androidx.constraintlayout.widget.Guideline
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/complication_top_guide"
+ app:layout_constraintGuide_percent="@dimen/dream_overlay_complication_guide_top_percent"
+ android:orientation="horizontal"/>
+ <androidx.constraintlayout.widget.Guideline
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/complication_end_guide"
+ app:layout_constraintGuide_percent="@dimen/dream_overlay_complication_guide_end_percent"
+ android:orientation="vertical"/>
+ <androidx.constraintlayout.widget.Guideline
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/complication_bottom_guide"
+ app:layout_constraintGuide_percent="@dimen/dream_overlay_complication_guide_bottom_percent"
+ android:orientation="horizontal"/>
+ <androidx.constraintlayout.widget.Guideline
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/complication_start_guide"
+ app:layout_constraintGuide_percent="@dimen/dream_overlay_complication_guide_start_percent"
+ android:orientation="vertical"/>
</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res/values-land/config.xml b/packages/SystemUI/res/values-land/config.xml
index ac4dfd212bb8..8c5006de577e 100644
--- a/packages/SystemUI/res/values-land/config.xml
+++ b/packages/SystemUI/res/values-land/config.xml
@@ -31,9 +31,6 @@
<!-- orientation of the dead zone when touches have recently occurred elsewhere on screen -->
<integer name="navigation_bar_deadzone_orientation">1</integer>
- <!-- Max number of columns for quick controls area -->
- <integer name="controls_max_columns">4</integer>
-
<!-- Max number of columns for power menu -->
<integer name="power_menu_max_columns">4</integer>
</resources>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index fc5edf3ade8f..9d24e9b97da3 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -66,4 +66,6 @@
<dimen name="controls_management_favorites_top_margin">8dp</dimen>
<dimen name="wallet_card_carousel_container_top_margin">24dp</dimen>
+
+ <dimen name="large_dialog_width">348dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-sw600dp-land/config.xml b/packages/SystemUI/res/values-sw600dp-land/config.xml
index dabc3108458f..fe546f65bb13 100644
--- a/packages/SystemUI/res/values-sw600dp-land/config.xml
+++ b/packages/SystemUI/res/values-sw600dp-land/config.xml
@@ -15,9 +15,6 @@
~ limitations under the License
-->
<resources>
- <!-- Max number of columns for quick controls area -->
- <integer name="controls_max_columns">2</integer>
-
<!-- The maximum number of rows in the QSPanel -->
<integer name="quick_settings_max_rows">3</integer>
diff --git a/packages/SystemUI/res/values-sw600dp-port/config.xml b/packages/SystemUI/res/values-sw600dp-port/config.xml
index 02fd25bd077c..3c6a81e7c617 100644
--- a/packages/SystemUI/res/values-sw600dp-port/config.xml
+++ b/packages/SystemUI/res/values-sw600dp-port/config.xml
@@ -15,7 +15,6 @@
~ limitations under the License
-->
<resources>
-
<!-- The maximum number of tiles in the QuickQSPanel -->
<integer name="quick_qs_panel_max_tiles">6</integer>
diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml
index f5dc7e3e16da..1b8453ae824d 100644
--- a/packages/SystemUI/res/values-sw600dp/config.xml
+++ b/packages/SystemUI/res/values-sw600dp/config.xml
@@ -29,9 +29,6 @@
<!-- orientation of the dead zone when touches have recently occurred elsewhere on screen -->
<integer name="navigation_bar_deadzone_orientation">0</integer>
- <!-- Max number of columns for quick controls area -->
- <integer name="controls_max_columns">4</integer>
-
<!-- How many lines to show in the security footer -->
<integer name="qs_security_footer_maxLines">1</integer>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 7d033018c27f..a66ed15c9d84 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -69,5 +69,5 @@
<dimen name="qs_detail_margin_top">0dp</dimen>
<!-- The width of large/content heavy dialogs (e.g. Internet, Media output, etc) -->
- <dimen name="large_dialog_width">504dp</dimen>
+ <dimen name="large_dialog_width">472dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-sw720dp-land/config.xml b/packages/SystemUI/res/values-sw720dp-land/config.xml
index ae89ef4ccc86..be34a48d1cd6 100644
--- a/packages/SystemUI/res/values-sw720dp-land/config.xml
+++ b/packages/SystemUI/res/values-sw720dp-land/config.xml
@@ -15,9 +15,6 @@
~ limitations under the License
-->
<resources>
- <!-- Max number of columns for quick controls area -->
- <integer name="controls_max_columns">2</integer>
-
<!-- The maximum number of rows in the QSPanel -->
<integer name="quick_settings_max_rows">3</integer>
diff --git a/packages/SystemUI/res/values-w500dp/config.xml b/packages/SystemUI/res/values-w500dp/config.xml
new file mode 100644
index 000000000000..ef499ff5cdb7
--- /dev/null
+++ b/packages/SystemUI/res/values-w500dp/config.xml
@@ -0,0 +1,20 @@
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources>
+ <!-- Max number of columns for quick controls area -->
+ <integer name="controls_max_columns">3</integer>
+</resources> \ No newline at end of file
diff --git a/packages/SystemUI/res/values-w500dp/dimens.xml b/packages/SystemUI/res/values-w500dp/dimens.xml
new file mode 100644
index 000000000000..5ce5ceee6dc9
--- /dev/null
+++ b/packages/SystemUI/res/values-w500dp/dimens.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources>
+ <dimen name="controls_padding_horizontal">75dp</dimen>
+</resources>
diff --git a/packages/SystemUI/res/values-w850dp/config.xml b/packages/SystemUI/res/values-w850dp/config.xml
new file mode 100644
index 000000000000..337ebe19c748
--- /dev/null
+++ b/packages/SystemUI/res/values-w850dp/config.xml
@@ -0,0 +1,20 @@
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources>
+ <!-- Max number of columns for quick controls area -->
+ <integer name="controls_max_columns">4</integer>
+</resources> \ No newline at end of file
diff --git a/packages/SystemUI/res/values-w850dp/dimens.xml b/packages/SystemUI/res/values-w850dp/dimens.xml
new file mode 100644
index 000000000000..bb6ba8fb07b6
--- /dev/null
+++ b/packages/SystemUI/res/values-w850dp/dimens.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ ~ Copyright (C) 2022 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<resources>
+ <dimen name="controls_padding_horizontal">205dp</dimen>
+</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index b35571c17db7..800dd0a6d7a3 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1035,6 +1035,7 @@
<dimen name="controls_header_bottom_margin">24dp</dimen>
<dimen name="controls_header_app_icon_size">24dp</dimen>
<dimen name="controls_top_margin">48dp</dimen>
+ <dimen name="controls_padding_horizontal">0dp</dimen>
<dimen name="control_header_text_size">20sp</dimen>
<dimen name="control_item_text_size">16sp</dimen>
<dimen name="control_menu_item_text_size">16sp</dimen>
@@ -1343,4 +1344,37 @@
<!-- Height of the area at the top of the dream overlay to allow dragging down the notifications
shade. -->
<dimen name="dream_overlay_notifications_drag_area_height">100dp</dimen>
+
+ <!-- The position of the end guide, which dream overlay complications can align their start with
+ if their end is aligned with the parent end. Represented as the percentage over from the
+ start of the parent container. -->
+ <item name="dream_overlay_complication_guide_end_percent" format="float" type="dimen">
+ 0.75
+ </item>
+
+ <!-- The position of the start guide, which dream overlay complications can align their end to
+ if their start is aligned with the parent start. Represented as the percentage over from
+ the start of the parent container. -->
+ <item name="dream_overlay_complication_guide_start_percent" format="float" type="dimen">
+ 0.25
+ </item>
+
+ <!-- The position of the bottom guide, which dream overlay complications can align their top to
+ if their bottom is aligned with the parent bottom. Represented as the percentage over from
+ the top of the parent container. -->
+ <item name="dream_overlay_complication_guide_bottom_percent" format="float" type="dimen">
+ 0.90
+ </item>
+
+ <!-- The position of the top guide, which dream overlay complications can align their bottom to
+ if their top is aligned with the parent top. Represented as the percentage over from
+ the top of the parent container. -->
+ <item name="dream_overlay_complication_guide_top_percent" format="float" type="dimen">
+ 0.10
+ </item>
+
+ <!-- The percentage of the screen from which a swipe can start to reveal the bouncer. -->
+ <item name="dream_overlay_bouncer_start_region_screen_percentage" format="float" type="dimen">
+ .2
+ </item>
</resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/communal/ICommunalHost.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/communal/ICommunalHost.aidl
deleted file mode 100644
index b76be4fc719a..000000000000
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/communal/ICommunalHost.aidl
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2021 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.communal;
-
-import com.android.systemui.shared.communal.ICommunalSource;
-
-/**
-* An interface, implemented by SystemUI, for hosting a shared, communal surface on the lock
-* screen. Clients declare themselves sources (as defined by ICommunalSource). ICommunalHost is
-* meant only for the input of said sources. The lifetime scope and interactions that follow after
-* are bound to source.
-*/
-oneway interface ICommunalHost {
- /**
- * Invoked to specify the CommunalSource that should be consulted for communal surfaces to be
- * displayed.
- */
- void setSource(in ICommunalSource source) = 1;
-} \ No newline at end of file
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/communal/ICommunalSource.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/communal/ICommunalSource.aidl
deleted file mode 100644
index 7ef403b414be..000000000000
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/communal/ICommunalSource.aidl
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (C) 2021 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.communal;
-
-import com.android.systemui.shared.communal.ICommunalSurfaceCallback;
-
-/**
- * An interface, implemented by clients of CommunalHost, to provide communal surfaces for SystemUI.
- * The associated binder proxy will be retained by SystemUI and called on-demand when a communal
- * surface is needed (either new instantiation or update).
- */
-oneway interface ICommunalSource {
- /**
- * Called by the CommunalHost when a new communal surface is needed. The provided arguments
- * match the arguments necessary to construct a SurfaceControlViewHost for producing a
- * SurfacePackage to return.
- */
- void getCommunalSurface(in IBinder hostToken, in int width, in int height, in int displayId,
- in ICommunalSurfaceCallback callback) = 1;
-} \ No newline at end of file
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/communal/ICommunalSurfaceCallback.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/communal/ICommunalSurfaceCallback.aidl
deleted file mode 100644
index 3d5998bffcbf..000000000000
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/communal/ICommunalSurfaceCallback.aidl
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2021 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.communal;
-
-import android.view.SurfaceControlViewHost.SurfacePackage;
-
-/**
-* An interface for receiving the result of a surface request. ICommunalSurfaceCallback is
-* implemented by the CommunalHost (SystemUI) to process the results of a new communal surface.
-*/
-interface ICommunalSurfaceCallback {
- /**
- * Invoked when the CommunalSurface has generated the SurfacePackage to be displayed.
- */
- void onSurface(in SurfacePackage surfacePackage) = 1;
-} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index b0f7e55112af..fe5e36ef23e6 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -37,6 +37,7 @@ import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager.Authenticators;
import android.hardware.biometrics.BiometricManager.BiometricMultiSensorMode;
import android.hardware.biometrics.BiometricPrompt;
+import android.hardware.biometrics.IBiometricContextListener;
import android.hardware.biometrics.IBiometricSysuiReceiver;
import android.hardware.biometrics.PromptInfo;
import android.hardware.display.DisplayManager;
@@ -64,6 +65,7 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.DozeReceiver;
import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.util.concurrency.Execution;
@@ -96,6 +98,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
private final Handler mHandler;
private final Execution mExecution;
private final CommandQueue mCommandQueue;
+ private final StatusBarStateController mStatusBarStateController;
private final ActivityTaskManager mActivityTaskManager;
@Nullable
private final FingerprintManager mFingerprintManager;
@@ -118,6 +121,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
@Nullable private UdfpsController mUdfpsController;
@Nullable private IUdfpsHbmListener mUdfpsHbmListener;
@Nullable private SidefpsController mSidefpsController;
+ @Nullable private IBiometricContextListener mBiometricContextListener;
@VisibleForTesting
TaskStackListener mTaskStackListener;
@VisibleForTesting
@@ -130,7 +134,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
@Nullable private List<FingerprintSensorPropertiesInternal> mSidefpsProps;
@NonNull private final SparseBooleanArray mUdfpsEnrolledForUser;
- private SensorPrivacyManager mSensorPrivacyManager;
+ @NonNull private final SensorPrivacyManager mSensorPrivacyManager;
private final WakefulnessLifecycle mWakefulnessLifecycle;
private class BiometricTaskStackListener extends TaskStackListener {
@@ -491,6 +495,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
Provider<SidefpsController> sidefpsControllerFactory,
@NonNull DisplayManager displayManager,
WakefulnessLifecycle wakefulnessLifecycle,
+ @NonNull StatusBarStateController statusBarStateController,
@Main Handler handler) {
super(context);
mExecution = execution;
@@ -504,6 +509,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
mSidefpsControllerFactory = sidefpsControllerFactory;
mWindowManager = windowManager;
mUdfpsEnrolledForUser = new SparseBooleanArray();
+
mOrientationListener = new BiometricDisplayListener(
context,
displayManager,
@@ -514,6 +520,14 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
return Unit.INSTANCE;
});
+ mStatusBarStateController = statusBarStateController;
+ mStatusBarStateController.addCallback(new StatusBarStateController.StateListener() {
+ @Override
+ public void onDozingChanged(boolean isDozing) {
+ notifyDozeChanged(isDozing);
+ }
+ });
+
mFaceProps = mFaceManager != null ? mFaceManager.getSensorPropertiesInternal() : null;
int[] faceAuthLocation = context.getResources().getIntArray(
@@ -564,6 +578,22 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba
mActivityTaskManager.registerTaskStackListener(mTaskStackListener);
}
+ @Override
+ public void setBiometicContextListener(IBiometricContextListener listener) {
+ mBiometricContextListener = listener;
+ notifyDozeChanged(mStatusBarStateController.isDozing());
+ }
+
+ private void notifyDozeChanged(boolean isDozing) {
+ if (mBiometricContextListener != null) {
+ try {
+ mBiometricContextListener.onDozeChanged(isDozing);
+ } catch (RemoteException e) {
+ Log.w(TAG, "failed to notify initial doze state");
+ }
+ }
+ }
+
/**
* Stores the listener received from {@link com.android.server.display.DisplayModeDirector}.
*
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
index 96e2302f937c..41287b60fbf8 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIBinder.java
@@ -26,10 +26,12 @@ import com.android.systemui.accessibility.WindowMagnification;
import com.android.systemui.biometrics.AuthController;
import com.android.systemui.clipboardoverlay.ClipboardListener;
import com.android.systemui.dreams.DreamOverlayRegistrant;
+import com.android.systemui.dreams.SmartSpaceComplication;
import com.android.systemui.globalactions.GlobalActionsComponent;
import com.android.systemui.keyguard.KeyguardViewMediator;
import com.android.systemui.keyguard.dagger.KeyguardModule;
import com.android.systemui.log.SessionTracker;
+import com.android.systemui.media.dream.MediaDreamSentinel;
import com.android.systemui.media.systemsounds.HomeSoundEffectController;
import com.android.systemui.power.PowerUI;
import com.android.systemui.privacy.television.TvOngoingPrivacyChip;
@@ -218,4 +220,18 @@ public abstract class SystemUIBinder {
@ClassKey(DreamOverlayRegistrant.class)
public abstract CoreStartable bindDreamOverlayRegistrant(
DreamOverlayRegistrant dreamOverlayRegistrant);
+
+ /** Inject into SmartSpaceComplication.Registrant */
+ @Binds
+ @IntoMap
+ @ClassKey(SmartSpaceComplication.Registrant.class)
+ public abstract CoreStartable bindSmartSpaceComplicationRegistrant(
+ SmartSpaceComplication.Registrant registrant);
+
+ /** Inject into MediaDreamSentinel. */
+ @Binds
+ @IntoMap
+ @ClassKey(MediaDreamSentinel.class)
+ public abstract CoreStartable bindMediaDreamSentinel(
+ MediaDreamSentinel sentinel);
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
index 3ee0cad32097..2160744c6803 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayService.java
@@ -88,16 +88,20 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
}
};
+ private DreamOverlayStateController mStateController;
+
@Inject
public DreamOverlayService(
Context context,
@Main Executor executor,
DreamOverlayComponent.Factory dreamOverlayComponentFactory,
+ DreamOverlayStateController stateController,
KeyguardUpdateMonitor keyguardUpdateMonitor) {
mContext = context;
mExecutor = executor;
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
mKeyguardUpdateMonitor.registerCallback(mKeyguardCallback);
+ mStateController = stateController;
final DreamOverlayComponent component =
dreamOverlayComponentFactory.create(mViewModelStore, mHost);
@@ -118,6 +122,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
setCurrentState(Lifecycle.State.DESTROYED);
final WindowManager windowManager = mContext.getSystemService(WindowManager.class);
windowManager.removeView(mWindow.getDecorView());
+ mStateController.setOverlayActive(false);
super.onDestroy();
}
@@ -127,6 +132,7 @@ public class DreamOverlayService extends android.service.dreams.DreamOverlayServ
mExecutor.execute(() -> {
addOverlayWindowLocked(layoutParams);
setCurrentState(Lifecycle.State.RESUMED);
+ mStateController.setOverlayActive(true);
});
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java
index e83884819f70..ac7457d90e49 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/DreamOverlayStateController.java
@@ -16,6 +16,8 @@
package com.android.systemui.dreams;
+import android.util.Log;
+
import androidx.annotation.NonNull;
import com.android.internal.annotations.VisibleForTesting;
@@ -30,6 +32,8 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.concurrent.Executor;
+import java.util.function.Consumer;
+import java.util.stream.Collectors;
import javax.inject.Inject;
@@ -41,6 +45,16 @@ import javax.inject.Inject;
@SysUISingleton
public class DreamOverlayStateController implements
CallbackController<DreamOverlayStateController.Callback> {
+ private static final String TAG = "DreamOverlayStateCtlr";
+ private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
+
+ public static final int STATE_DREAM_OVERLAY_ACTIVE = 1 << 0;
+
+ private static final int OP_CLEAR_STATE = 1;
+ private static final int OP_SET_STATE = 2;
+
+ private int mState;
+
/**
* Callback for dream overlay events.
*/
@@ -50,11 +64,26 @@ public class DreamOverlayStateController implements
*/
default void onComplicationsChanged() {
}
+
+ /**
+ * Called when the dream overlay state changes.
+ */
+ default void onStateChanged() {
+ }
+
+ /**
+ * Called when the available complication types changes.
+ */
+ default void onAvailableComplicationTypesChanged() {
+ }
}
private final Executor mExecutor;
private final ArrayList<Callback> mCallbacks = new ArrayList<>();
+ @Complication.ComplicationType
+ private int mAvailableComplicationTypes = Complication.COMPLICATION_TYPE_NONE;
+
private final Collection<Complication> mComplications = new HashSet();
@VisibleForTesting
@@ -89,7 +118,33 @@ public class DreamOverlayStateController implements
* Returns collection of present {@link Complication}.
*/
public Collection<Complication> getComplications() {
- return Collections.unmodifiableCollection(mComplications);
+ return getComplications(true);
+ }
+
+ /**
+ * Returns collection of present {@link Complication}.
+ */
+ public Collection<Complication> getComplications(boolean filterByAvailability) {
+ return Collections.unmodifiableCollection(filterByAvailability
+ ? mComplications
+ .stream()
+ .filter(complication -> {
+ @Complication.ComplicationType
+ final int requiredTypes = complication.getRequiredTypeAvailability();
+
+ return requiredTypes == Complication.COMPLICATION_TYPE_NONE
+ || (requiredTypes & getAvailableComplicationTypes()) == requiredTypes;
+ })
+ .collect(Collectors.toCollection(HashSet::new))
+ : mComplications);
+ }
+
+ private void notifyCallbacks(Consumer<Callback> callbackConsumer) {
+ mExecutor.execute(() -> {
+ for (Callback callback : mCallbacks) {
+ callbackConsumer.accept(callback);
+ }
+ });
}
@Override
@@ -117,4 +172,58 @@ public class DreamOverlayStateController implements
mCallbacks.remove(callback);
});
}
+
+ /**
+ * Returns whether the overlay is active.
+ * @return {@code true} if overlay is active, {@code false} otherwise.
+ */
+ public boolean isOverlayActive() {
+ return containsState(STATE_DREAM_OVERLAY_ACTIVE);
+ }
+
+ private boolean containsState(int state) {
+ return (mState & state) != 0;
+ }
+
+ private void modifyState(int op, int state) {
+ final int existingState = mState;
+ switch (op) {
+ case OP_CLEAR_STATE:
+ mState &= ~state;
+ break;
+ case OP_SET_STATE:
+ mState |= state;
+ break;
+ }
+
+ if (existingState != mState) {
+ notifyCallbacks(callback -> callback.onStateChanged());
+ }
+ }
+
+ /**
+ * Sets whether the overlay is active.
+ * @param active {@code true} if overlay is active, {@code false} otherwise.
+ */
+ public void setOverlayActive(boolean active) {
+ modifyState(active ? OP_SET_STATE : OP_CLEAR_STATE, STATE_DREAM_OVERLAY_ACTIVE);
+ }
+
+ /**
+ * Returns the available complication types.
+ */
+ @Complication.ComplicationType
+ public int getAvailableComplicationTypes() {
+ return mAvailableComplicationTypes;
+ }
+
+ /**
+ * Sets the available complication types for the dream overlay.
+ */
+ public void setAvailableComplicationTypes(@Complication.ComplicationType int types) {
+ mExecutor.execute(() -> {
+ mAvailableComplicationTypes = types;
+ mCallbacks.forEach(callback -> callback.onAvailableComplicationTypesChanged());
+ });
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/SmartSpaceComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/SmartSpaceComplication.java
new file mode 100644
index 000000000000..09221b4f810a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dreams/SmartSpaceComplication.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dreams;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import com.android.systemui.CoreStartable;
+import com.android.systemui.dreams.complication.Complication;
+import com.android.systemui.dreams.complication.ComplicationLayoutParams;
+import com.android.systemui.dreams.complication.ComplicationViewModel;
+import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController;
+
+import javax.inject.Inject;
+
+/**
+ * {@link SmartSpaceComplication} embodies the SmartSpace view found on the lockscreen as a
+ * {@link Complication}
+ */
+public class SmartSpaceComplication implements Complication {
+ /**
+ * {@link CoreStartable} responsbile for registering {@link SmartSpaceComplication} with
+ * SystemUI.
+ */
+ public static class Registrant extends CoreStartable {
+ private final LockscreenSmartspaceController mSmartSpaceController;
+ private final DreamOverlayStateController mDreamOverlayStateController;
+ private final SmartSpaceComplication mComplication;
+
+ /**
+ * Default constructor for {@link SmartSpaceComplication}.
+ */
+ @Inject
+ public Registrant(Context context,
+ DreamOverlayStateController dreamOverlayStateController,
+ SmartSpaceComplication smartSpaceComplication,
+ LockscreenSmartspaceController smartSpaceController) {
+ super(context);
+ mDreamOverlayStateController = dreamOverlayStateController;
+ mComplication = smartSpaceComplication;
+ mSmartSpaceController = smartSpaceController;
+ }
+
+ @Override
+ public void start() {
+ if (mSmartSpaceController.isEnabled()) {
+ mDreamOverlayStateController.addComplication(mComplication);
+ }
+ }
+ }
+
+ private static class SmartSpaceComplicationViewHolder implements ViewHolder {
+ private final LockscreenSmartspaceController mSmartSpaceController;
+ private final Context mContext;
+
+ protected SmartSpaceComplicationViewHolder(
+ Context context,
+ LockscreenSmartspaceController smartSpaceController) {
+ mSmartSpaceController = smartSpaceController;
+ mContext = context;
+ }
+
+ @Override
+ public View getView() {
+ final FrameLayout smartSpaceContainer = new FrameLayout(mContext);
+ smartSpaceContainer.addView(
+ mSmartSpaceController.buildAndConnectView(smartSpaceContainer),
+ new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT));
+
+ return smartSpaceContainer;
+ }
+
+ @Override
+ public ComplicationLayoutParams getLayoutParams() {
+ return new ComplicationLayoutParams(0, ViewGroup.LayoutParams.WRAP_CONTENT,
+ ComplicationLayoutParams.POSITION_TOP | ComplicationLayoutParams.POSITION_START,
+ ComplicationLayoutParams.DIRECTION_DOWN,
+ 0, true);
+ }
+ }
+
+ private final LockscreenSmartspaceController mSmartSpaceController;
+ private final Context mContext;
+
+ @Inject
+ public SmartSpaceComplication(Context context,
+ LockscreenSmartspaceController smartSpaceController) {
+ mContext = context;
+ mSmartSpaceController = smartSpaceController;
+ }
+
+ @Override
+ public ViewHolder createView(ComplicationViewModel model) {
+ return new SmartSpaceComplicationViewHolder(mContext, mSmartSpaceController);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/Complication.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/Complication.java
index 96cf50d58d10..fe458f4c5318 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/Complication.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/Complication.java
@@ -154,6 +154,27 @@ public interface Complication {
int CATEGORY_SYSTEM = 1 << 1;
/**
+ * The type of dream complications which can be provided by a {@link Complication}.
+ */
+ @IntDef(prefix = {"COMPLICATION_TYPE_"}, flag = true, value = {
+ COMPLICATION_TYPE_NONE,
+ COMPLICATION_TYPE_TIME,
+ COMPLICATION_TYPE_DATE,
+ COMPLICATION_TYPE_WEATHER,
+ COMPLICATION_TYPE_AIR_QUALITY,
+ COMPLICATION_TYPE_CAST_INFO
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface ComplicationType {}
+
+ int COMPLICATION_TYPE_NONE = 0;
+ int COMPLICATION_TYPE_TIME = 1;
+ int COMPLICATION_TYPE_DATE = 1 << 1;
+ int COMPLICATION_TYPE_WEATHER = 1 << 2;
+ int COMPLICATION_TYPE_AIR_QUALITY = 1 << 3;
+ int COMPLICATION_TYPE_CAST_INFO = 1 << 4;
+
+ /**
* The {@link Host} interface specifies a way a {@link Complication} to communicate with its
* parent entity for information and actions.
*/
@@ -207,4 +228,15 @@ public interface Complication {
* @return a {@link ViewHolder} for this {@link Complication} instance.
*/
ViewHolder createView(ComplicationViewModel model);
+
+ /**
+ * Returns the types that must be present in order for this complication to participate on
+ * the dream overlay. By default, this method returns
+ * {@code Complication.COMPLICATION_TYPE_NONE} to indicate no types are required.
+ * @return
+ */
+ @Complication.ComplicationType
+ default int getRequiredTypeAvailability() {
+ return Complication.COMPLICATION_TYPE_NONE;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationCollectionLiveData.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationCollectionLiveData.java
index 76818fa0c42e..f6fe8d2e579c 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationCollectionLiveData.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationCollectionLiveData.java
@@ -42,6 +42,10 @@ public class ComplicationCollectionLiveData extends LiveData<Collection<Complica
setValue(mDreamOverlayStateController.getComplications());
}
+ @Override
+ public void onAvailableComplicationTypesChanged() {
+ setValue(mDreamOverlayStateController.getComplications());
+ }
};
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutEngine.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutEngine.java
index cb24ae609eeb..5223f379508f 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutEngine.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutEngine.java
@@ -25,10 +25,13 @@ import android.view.ViewGroup;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.constraintlayout.widget.Constraints;
+import com.android.systemui.R;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.function.Consumer;
import javax.inject.Inject;
import javax.inject.Named;
@@ -102,6 +105,8 @@ public class ComplicationLayoutEngine {
final int direction = getLayoutParams().getDirection();
+ final boolean snapsToGuide = getLayoutParams().snapsToGuide();
+
// If no parent, view is the anchor. In this case, it is given the highest priority for
// alignment. All alignment preferences are done in relation to the parent container.
final boolean isRoot = head == mView;
@@ -125,6 +130,11 @@ public class ComplicationLayoutEngine {
} else {
params.startToEnd = head.getId();
}
+ if (snapsToGuide
+ && (direction == ComplicationLayoutParams.DIRECTION_DOWN
+ || direction == ComplicationLayoutParams.DIRECTION_UP)) {
+ params.endToStart = R.id.complication_start_guide;
+ }
break;
case ComplicationLayoutParams.POSITION_TOP:
if (isRoot || direction != ComplicationLayoutParams.DIRECTION_DOWN) {
@@ -132,6 +142,11 @@ public class ComplicationLayoutEngine {
} else {
params.topToBottom = head.getId();
}
+ if (snapsToGuide
+ && (direction == ComplicationLayoutParams.DIRECTION_END
+ || direction == ComplicationLayoutParams.DIRECTION_START)) {
+ params.endToStart = R.id.complication_top_guide;
+ }
break;
case ComplicationLayoutParams.POSITION_BOTTOM:
if (isRoot || direction != ComplicationLayoutParams.DIRECTION_UP) {
@@ -139,6 +154,11 @@ public class ComplicationLayoutEngine {
} else {
params.bottomToTop = head.getId();
}
+ if (snapsToGuide
+ && (direction == ComplicationLayoutParams.DIRECTION_END
+ || direction == ComplicationLayoutParams.DIRECTION_START)) {
+ params.topToBottom = R.id.complication_bottom_guide;
+ }
break;
case ComplicationLayoutParams.POSITION_END:
if (isRoot || direction != ComplicationLayoutParams.DIRECTION_START) {
@@ -146,6 +166,11 @@ public class ComplicationLayoutEngine {
} else {
params.endToStart = head.getId();
}
+ if (snapsToGuide
+ && (direction == ComplicationLayoutParams.DIRECTION_UP
+ || direction == ComplicationLayoutParams.DIRECTION_DOWN)) {
+ params.startToEnd = R.id.complication_end_guide;
+ }
break;
}
});
@@ -153,6 +178,16 @@ public class ComplicationLayoutEngine {
mView.setLayoutParams(params);
}
+ private void setGuide(ConstraintLayout.LayoutParams lp, int validDirections,
+ Consumer<ConstraintLayout.LayoutParams> consumer) {
+ final ComplicationLayoutParams layoutParams = getLayoutParams();
+ if (!layoutParams.snapsToGuide()) {
+ return;
+ }
+
+ consumer.accept(lp);
+ }
+
/**
* Informs the {@link ViewEntry}'s parent entity to remove the {@link ViewEntry} from
* being shown further.
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutParams.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutParams.java
index f9a69fadfedc..8e8cb72d6ad0 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutParams.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationLayoutParams.java
@@ -40,13 +40,13 @@ public class ComplicationLayoutParams extends ViewGroup.LayoutParams {
@interface Position {}
/** Align view with the top of parent or bottom of preceding {@link Complication}. */
- static final int POSITION_TOP = 1 << 0;
+ public static final int POSITION_TOP = 1 << 0;
/** Align view with the bottom of parent or top of preceding {@link Complication}. */
- static final int POSITION_BOTTOM = 1 << 1;
+ public static final int POSITION_BOTTOM = 1 << 1;
/** Align view with the start of parent or end of preceding {@link Complication}. */
- static final int POSITION_START = 1 << 2;
+ public static final int POSITION_START = 1 << 2;
/** Align view with the end of parent or start of preceding {@link Complication}. */
- static final int POSITION_END = 1 << 3;
+ public static final int POSITION_END = 1 << 3;
private static final int FIRST_POSITION = POSITION_TOP;
private static final int LAST_POSITION = POSITION_END;
@@ -61,13 +61,13 @@ public class ComplicationLayoutParams extends ViewGroup.LayoutParams {
@interface Direction {}
/** Position view upward from position. */
- static final int DIRECTION_UP = 1 << 0;
+ public static final int DIRECTION_UP = 1 << 0;
/** Position view downward from position. */
- static final int DIRECTION_DOWN = 1 << 1;
+ public static final int DIRECTION_DOWN = 1 << 1;
/** Position view towards the start of the parent. */
- static final int DIRECTION_START = 1 << 2;
+ public static final int DIRECTION_START = 1 << 2;
/** Position view towards the end of parent. */
- static final int DIRECTION_END = 1 << 3;
+ public static final int DIRECTION_END = 1 << 3;
@Position
private final int mPosition;
@@ -77,6 +77,8 @@ public class ComplicationLayoutParams extends ViewGroup.LayoutParams {
private final int mWeight;
+ private final boolean mSnapToGuide;
+
// Do not allow specifying opposite positions
private static final int[] INVALID_POSITIONS =
{ POSITION_BOTTOM | POSITION_TOP, POSITION_END | POSITION_START };
@@ -104,6 +106,27 @@ public class ComplicationLayoutParams extends ViewGroup.LayoutParams {
*/
public ComplicationLayoutParams(int width, int height, @Position int position,
@Direction int direction, int weight) {
+ this(width, height, position, direction, weight, false);
+ }
+
+ /**
+ * Constructs a {@link ComplicationLayoutParams}.
+ * @param width The width {@link android.view.View.MeasureSpec} for the view.
+ * @param height The height {@link android.view.View.MeasureSpec} for the view.
+ * @param position The place within the parent container where the view should be positioned.
+ * @param direction The direction the view should be laid out from either the parent container
+ * or preceding view.
+ * @param weight The weight that should be considered for this view when compared to other
+ * views. This has an impact on the placement of the view but not the rendering of
+ * the view.
+ * @param snapToGuide When set to {@code true}, the dimension perpendicular to the direction
+ * will be automatically set to align with a predetermined guide for that
+ * side. For example, if the complication is aligned to the top end and
+ * direction is down, then the width of the complication will be set to span
+ * from the end of the parent to the guide.
+ */
+ public ComplicationLayoutParams(int width, int height, @Position int position,
+ @Direction int direction, int weight, boolean snapToGuide) {
super(width, height);
if (!validatePosition(position)) {
@@ -118,6 +141,8 @@ public class ComplicationLayoutParams extends ViewGroup.LayoutParams {
mDirection = direction;
mWeight = weight;
+
+ mSnapToGuide = snapToGuide;
}
/**
@@ -128,6 +153,7 @@ public class ComplicationLayoutParams extends ViewGroup.LayoutParams {
mPosition = source.mPosition;
mDirection = source.mDirection;
mWeight = source.mWeight;
+ mSnapToGuide = source.mSnapToGuide;
}
private static boolean validateDirection(@Position int position, @Direction int direction) {
@@ -180,7 +206,19 @@ public class ComplicationLayoutParams extends ViewGroup.LayoutParams {
return mPosition;
}
+ /**
+ * Returns the set weight for the complication. The weight determines ordering a complication
+ * given the same position/direction.
+ */
public int getWeight() {
return mWeight;
}
+
+ /**
+ * Returns whether the complication's dimension perpendicular to direction should be
+ * automatically set.
+ */
+ public boolean snapsToGuide() {
+ return mSnapToGuide;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationUtils.java b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationUtils.java
new file mode 100644
index 000000000000..3a2a6ef60f03
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dreams/complication/ComplicationUtils.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dreams.complication;
+
+import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_AIR_QUALITY;
+import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_CAST_INFO;
+import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_DATE;
+import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_NONE;
+import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_TIME;
+import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_WEATHER;
+
+import com.android.settingslib.dream.DreamBackend;
+
+/**
+ * A collection of utility methods for working with {@link Complication}.
+ */
+public class ComplicationUtils {
+ /**
+ * Converts a {@link com.android.settingslib.dream.DreamBackend.ComplicationType} to
+ * {@link ComplicationType}.
+ */
+ @Complication.ComplicationType
+ public static int convertComplicationType(@DreamBackend.ComplicationType int type) {
+ switch (type) {
+ case DreamBackend.COMPLICATION_TYPE_TIME:
+ return COMPLICATION_TYPE_TIME;
+ case DreamBackend.COMPLICATION_TYPE_DATE:
+ return COMPLICATION_TYPE_DATE;
+ case DreamBackend.COMPLICATION_TYPE_WEATHER:
+ return COMPLICATION_TYPE_WEATHER;
+ case DreamBackend.COMPLICATION_TYPE_AIR_QUALITY:
+ return COMPLICATION_TYPE_AIR_QUALITY;
+ case DreamBackend.COMPLICATION_TYPE_CAST_INFO:
+ return COMPLICATION_TYPE_CAST_INFO;
+ default:
+ return COMPLICATION_TYPE_NONE;
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java
index 503817a23f7f..4eb5cb97607a 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/dagger/DreamOverlayModule.java
@@ -34,7 +34,6 @@ import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dreams.DreamOverlayContainerView;
import com.android.systemui.dreams.DreamOverlayStatusBarView;
-import com.android.systemui.dreams.touch.DreamTouchHandler;
import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.tuner.TunerService;
@@ -44,7 +43,6 @@ import javax.inject.Named;
import dagger.Lazy;
import dagger.Module;
import dagger.Provides;
-import dagger.multibindings.IntoSet;
/** Dagger module for {@link DreamOverlayComponent}. */
@Module
@@ -149,12 +147,4 @@ public abstract class DreamOverlayModule {
static Lifecycle providesLifecycle(LifecycleOwner lifecycleOwner) {
return lifecycleOwner.getLifecycle();
}
-
- // TODO: This stub should be removed once there is a {@link DreamTouchHandler}
- // implementation present.
- @Provides
- @IntoSet
- static DreamTouchHandler provideDreamTouchHandler() {
- return session -> { };
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
new file mode 100644
index 000000000000..d16c8c8c59d6
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dreams.touch;
+
+import static com.android.systemui.dreams.touch.dagger.BouncerSwipeModule.SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_CLOSING;
+import static com.android.systemui.dreams.touch.dagger.BouncerSwipeModule.SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_OPENING;
+import static com.android.systemui.dreams.touch.dagger.BouncerSwipeModule.SWIPE_TO_BOUNCER_START_REGION;
+
+import android.animation.ValueAnimator;
+import android.util.Log;
+import android.view.GestureDetector;
+import android.view.InputEvent;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+
+import com.android.systemui.statusbar.NotificationShadeWindowController;
+import com.android.systemui.statusbar.phone.KeyguardBouncer;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.wm.shell.animation.FlingAnimationUtils;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+/**
+ * Monitor for tracking touches on the DreamOverlay to bring up the bouncer.
+ */
+public class BouncerSwipeTouchHandler implements DreamTouchHandler {
+ /**
+ * An interface for creating ValueAnimators.
+ */
+ public interface ValueAnimatorCreator {
+ /**
+ * Creates {@link ValueAnimator}.
+ */
+ ValueAnimator create(float start, float finish);
+ }
+
+ /**
+ * An interface for obtaining VelocityTrackers.
+ */
+ public interface VelocityTrackerFactory {
+ /**
+ * Obtains {@link VelocityTracker}.
+ */
+ VelocityTracker obtain();
+ }
+
+ public static final float FLING_PERCENTAGE_THRESHOLD = 0.5f;
+
+ private static final String TAG = "BouncerSwipeTouchHandler";
+ private final NotificationShadeWindowController mNotificationShadeWindowController;
+ private final float mBouncerZoneScreenPercentage;
+
+ private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+ private float mCurrentExpansion;
+ private final StatusBar mStatusBar;
+
+ private VelocityTracker mVelocityTracker;
+
+ private final FlingAnimationUtils mFlingAnimationUtils;
+ private final FlingAnimationUtils mFlingAnimationUtilsClosing;
+
+ private Boolean mCapture;
+
+ private TouchSession mTouchSession;
+
+ private ValueAnimatorCreator mValueAnimatorCreator;
+
+ private VelocityTrackerFactory mVelocityTrackerFactory;
+
+ private final GestureDetector.OnGestureListener mOnGestureListener =
+ new GestureDetector.SimpleOnGestureListener() {
+ boolean mTrack;
+ boolean mBouncerPresent;
+
+ @Override
+ public boolean onDown(MotionEvent e) {
+ // We only consider gestures that originate from the lower portion of the
+ // screen.
+ final float displayHeight = mStatusBar.getDisplayHeight();
+
+ mBouncerPresent = mStatusBar.isBouncerShowing();
+
+ // The target zone is either at the top or bottom of the screen, dependent on
+ // whether the bouncer is present.
+ final float zonePercentage =
+ Math.abs(e.getY() - (mBouncerPresent ? 0 : displayHeight))
+ / displayHeight;
+
+ mTrack = zonePercentage < mBouncerZoneScreenPercentage;
+
+ // Never capture onDown. While this might lead to some false positive touches
+ // being sent to other windows/layers, this is necessary to make sure the
+ // proper touch event sequence is received by others in the event we do not
+ // consume the sequence here.
+ return false;
+ }
+
+ @Override
+ public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
+ float distanceY) {
+ // Do not handle scroll gestures if not tracking touch events.
+ if (!mTrack) {
+ return false;
+ }
+
+ if (mCapture == null) {
+ // If the user scrolling favors a vertical direction, begin capturing
+ // scrolls.
+ mCapture = Math.abs(distanceY) > Math.abs(distanceX);
+
+ if (mCapture) {
+ // Since the user is dragging the bouncer up, set scrimmed to false.
+ mStatusBarKeyguardViewManager.showBouncer(false);
+ }
+ }
+
+ if (!mCapture) {
+ return false;
+ }
+
+ // For consistency, we adopt the expansion definition found in the
+ // PanelViewController. In this case, expansion refers to the view above the
+ // bouncer. As that view's expansion shrinks, the bouncer appears. The bouncer
+ // is fully hidden at full expansion (1) and fully visible when fully collapsed
+ // (0).
+ final float screenTravelPercentage =
+ Math.abs((e1.getY() - e2.getY()) / mStatusBar.getDisplayHeight());
+ setPanelExpansion(
+ mBouncerPresent ? screenTravelPercentage : 1 - screenTravelPercentage);
+
+ return true;
+ }
+ };
+
+ private void setPanelExpansion(float expansion) {
+ mCurrentExpansion = expansion;
+ mStatusBarKeyguardViewManager.onPanelExpansionChanged(mCurrentExpansion, false, true);
+ }
+
+ @Inject
+ public BouncerSwipeTouchHandler(
+ StatusBarKeyguardViewManager statusBarKeyguardViewManager,
+ StatusBar statusBar,
+ NotificationShadeWindowController notificationShadeWindowController,
+ ValueAnimatorCreator valueAnimatorCreator,
+ VelocityTrackerFactory velocityTrackerFactory,
+ @Named(SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_CLOSING)
+ FlingAnimationUtils flingAnimationUtils,
+ @Named(SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_OPENING)
+ FlingAnimationUtils flingAnimationUtilsClosing,
+ @Named(SWIPE_TO_BOUNCER_START_REGION) float swipeRegionPercentage) {
+ mStatusBar = statusBar;
+ mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
+ mNotificationShadeWindowController = notificationShadeWindowController;
+ mBouncerZoneScreenPercentage = swipeRegionPercentage;
+ mFlingAnimationUtils = flingAnimationUtils;
+ mFlingAnimationUtilsClosing = flingAnimationUtilsClosing;
+ mValueAnimatorCreator = valueAnimatorCreator;
+ mVelocityTrackerFactory = velocityTrackerFactory;
+ }
+
+ @Override
+ public void onSessionStart(TouchSession session) {
+ mVelocityTracker = mVelocityTrackerFactory.obtain();
+ mTouchSession = session;
+ mVelocityTracker.clear();
+ mNotificationShadeWindowController.setForcePluginOpen(true, this);
+ session.registerGestureListener(mOnGestureListener);
+ session.registerInputListener(ev -> onMotionEvent(ev));
+
+ }
+
+ @Override
+ public void onSessionEnd(TouchSession session) {
+ mVelocityTracker.recycle();
+ mCapture = null;
+ mNotificationShadeWindowController.setForcePluginOpen(false, this);
+ }
+
+ private void onMotionEvent(InputEvent event) {
+ if (!(event instanceof MotionEvent)) {
+ Log.e(TAG, "non MotionEvent received:" + event);
+ return;
+ }
+
+ final MotionEvent motionEvent = (MotionEvent) event;
+
+ switch(motionEvent.getAction()) {
+ case MotionEvent.ACTION_UP:
+ // If we are not capturing any input, there is no need to consider animating to
+ // finish transition.
+ if (mCapture == null || !mCapture) {
+ break;
+ }
+
+ // We must capture the resulting velocities as resetMonitor() will clear these
+ // values.
+ mVelocityTracker.computeCurrentVelocity(1000);
+ final float verticalVelocity = mVelocityTracker.getYVelocity();
+ final float horizontalVelocity = mVelocityTracker.getXVelocity();
+
+ final float velocityVector =
+ (float) Math.hypot(horizontalVelocity, verticalVelocity);
+
+
+ final float expansion = flingRevealsOverlay(verticalVelocity, velocityVector)
+ ? KeyguardBouncer.EXPANSION_HIDDEN : KeyguardBouncer.EXPANSION_VISIBLE;
+ flingToExpansion(verticalVelocity, expansion);
+
+ if (expansion == KeyguardBouncer.EXPANSION_HIDDEN) {
+ mStatusBarKeyguardViewManager.reset(false);
+ }
+ mTouchSession.pop();
+ break;
+ default:
+ mVelocityTracker.addMovement(motionEvent);
+ break;
+ }
+ }
+
+ private ValueAnimator createExpansionAnimator(float targetExpansion) {
+ final ValueAnimator animator =
+ mValueAnimatorCreator.create(mCurrentExpansion, targetExpansion);
+ animator.addUpdateListener(
+ animation -> {
+ setPanelExpansion((float) animation.getAnimatedValue());
+ });
+ return animator;
+ }
+
+ protected boolean flingRevealsOverlay(float velocity, float velocityVector) {
+ // Fully expand if the user has expanded the bouncer less than halfway or final velocity was
+ // positive, indicating an downward direction.
+ if (Math.abs(velocityVector) < mFlingAnimationUtils.getMinVelocityPxPerSecond()) {
+ return mCurrentExpansion > FLING_PERCENTAGE_THRESHOLD;
+ } else {
+ return velocity > 0;
+ }
+ }
+
+ protected void flingToExpansion(float velocity, float expansion) {
+ final float viewHeight = mStatusBar.getDisplayHeight();
+ final float currentHeight = viewHeight * mCurrentExpansion;
+ final float targetHeight = viewHeight * expansion;
+
+ final ValueAnimator animator = createExpansionAnimator(expansion);
+ if (expansion == KeyguardBouncer.EXPANSION_HIDDEN) {
+ // The animation utils deal in pixel units, rather than expansion height.
+ mFlingAnimationUtils.apply(animator, currentHeight, targetHeight, velocity, viewHeight);
+ } else {
+ mFlingAnimationUtilsClosing.apply(
+ animator, mCurrentExpansion, currentHeight, targetHeight, viewHeight);
+ }
+
+ animator.start();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/BouncerSwipeModule.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/BouncerSwipeModule.java
new file mode 100644
index 000000000000..b9436f96c74f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/BouncerSwipeModule.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dreams.touch.dagger;
+
+import android.animation.ValueAnimator;
+import android.content.res.Resources;
+import android.util.TypedValue;
+import android.view.VelocityTracker;
+
+import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dreams.touch.BouncerSwipeTouchHandler;
+import com.android.systemui.dreams.touch.DreamTouchHandler;
+import com.android.systemui.statusbar.phone.PanelViewController;
+import com.android.wm.shell.animation.FlingAnimationUtils;
+
+import javax.inject.Named;
+import javax.inject.Provider;
+
+import dagger.Module;
+import dagger.Provides;
+import dagger.multibindings.IntoSet;
+
+/**
+ * This module captures the components associated with {@link BouncerSwipeTouchHandler}.
+ */
+@Module
+public class BouncerSwipeModule {
+ /**
+ * The region, defined as the percentage of the screen, from which a touch gesture to start
+ * swiping up to the bouncer can occur.
+ */
+ public static final String SWIPE_TO_BOUNCER_START_REGION = "swipe_to_bouncer_start_region";
+
+ /**
+ * The {@link android.view.animation.AnimationUtils} for animating the bouncer closing.
+ */
+ public static final String SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_CLOSING =
+ "swipe_to_bouncer_fling_animation_utils_closing";
+
+ /**
+ * The {@link android.view.animation.AnimationUtils} for animating the bouncer opening.
+ */
+ public static final String SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_OPENING =
+ "swipe_to_bouncer_fling_animation_utils_opening";
+
+ /**
+ * Provides {@link BouncerSwipeTouchHandler} for inclusion in touch handling over the dream.
+ */
+ @Provides
+ @IntoSet
+ public static DreamTouchHandler providesBouncerSwipeTouchHandler(
+ BouncerSwipeTouchHandler touchHandler) {
+ return touchHandler;
+ }
+
+ /**
+ * Provides {@link android.view.animation.AnimationUtils} for closing.
+ */
+ @Provides
+ @Named(SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_CLOSING)
+ public static FlingAnimationUtils providesSwipeToBouncerFlingAnimationUtilsClosing(
+ Provider<FlingAnimationUtils.Builder> flingAnimationUtilsBuilderProvider) {
+ return flingAnimationUtilsBuilderProvider.get()
+ .reset()
+ .setMaxLengthSeconds(PanelViewController.FLING_CLOSING_MAX_LENGTH_SECONDS)
+ .setSpeedUpFactor(PanelViewController.FLING_SPEED_UP_FACTOR)
+ .build();
+ }
+
+ /**
+ * Provides {@link android.view.animation.AnimationUtils} for opening.
+ */
+ @Provides
+ @Named(SWIPE_TO_BOUNCER_FLING_ANIMATION_UTILS_OPENING)
+ public static FlingAnimationUtils providesSwipeToBouncerFlingAnimationUtilsOpening(
+ Provider<FlingAnimationUtils.Builder> flingAnimationUtilsBuilderProvider) {
+ return flingAnimationUtilsBuilderProvider.get()
+ .reset()
+ .setMaxLengthSeconds(PanelViewController.FLING_MAX_LENGTH_SECONDS)
+ .setSpeedUpFactor(PanelViewController.FLING_SPEED_UP_FACTOR)
+ .build();
+ }
+
+ /**
+ * Provides the region to start swipe gestures from.
+ */
+ @Provides
+ @Named(SWIPE_TO_BOUNCER_START_REGION)
+ public static float providesSwipeToBouncerStartRegion(@Main Resources resources) {
+ TypedValue typedValue = new TypedValue();
+ resources.getValue(R.dimen.dream_overlay_bouncer_start_region_screen_percentage,
+ typedValue, true);
+ return typedValue.getFloat();
+ }
+
+ /**
+ * Provides the default {@link BouncerSwipeTouchHandler.ValueAnimatorCreator}, which is simply
+ * a wrapper around {@link ValueAnimator}.
+ */
+ @Provides
+ public static BouncerSwipeTouchHandler.ValueAnimatorCreator providesValueAnimatorCreator() {
+ return (start, finish) -> ValueAnimator.ofFloat(start, finish);
+ }
+
+ /**
+ * Provides the default {@link BouncerSwipeTouchHandler.VelocityTrackerFactory}. which is a
+ * passthrough to {@link android.view.VelocityTracker}.
+ */
+ @Provides
+ public static BouncerSwipeTouchHandler.VelocityTrackerFactory providesVelocityTrackerFactory() {
+ return () -> VelocityTracker.obtain();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/DreamTouchModule.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/DreamTouchModule.java
index 7b77b593b330..dad0004613f6 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/DreamTouchModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/dagger/DreamTouchModule.java
@@ -21,8 +21,10 @@ import dagger.Module;
/**
* {@link DreamTouchModule} encapsulates dream touch-related components.
*/
-@Module(subcomponents = {
- InputSessionComponent.class,
+@Module(includes = {
+ BouncerSwipeModule.class,
+ }, subcomponents = {
+ InputSessionComponent.class,
})
public interface DreamTouchModule {
String INPUT_SESSION_NAME = "INPUT_SESSION_NAME";
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 701d1391d271..fd2c6dd3ca36 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -106,6 +106,7 @@ import com.android.systemui.animation.Interpolators;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.dagger.qualifiers.UiBackground;
+import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.dagger.KeyguardModule;
import com.android.systemui.navigationbar.NavigationModeController;
@@ -138,7 +139,7 @@ import dagger.Lazy;
* state of the keyguard, power management events that effect whether the keyguard
* should be shown or reset, callbacks to the phone window manager to notify
* it of when the keyguard is showing, and events from the keyguard view itself
- * stating that the keyguard was succesfully unlocked.
+ * stating that the keyguard was successfully unlocked.
*
* Note that the keyguard view is shown when the screen is off (as appropriate)
* so that once the screen comes on, it will be ready immediately.
@@ -152,15 +153,15 @@ import dagger.Lazy;
* - the keyguard is showing
*
* Example external events that translate to keyguard view changes:
- * - screen turned off -> reset the keyguard, and show it so it will be ready
+ * - screen turned off -> reset the keyguard, and show it, so it will be ready
* next time the screen turns on
* - keyboard is slid open -> if the keyguard is not secure, hide it
*
* Events from the keyguard view:
- * - user succesfully unlocked keyguard -> hide keyguard view, and no longer
+ * - user successfully unlocked keyguard -> hide keyguard view, and no longer
* restrict input events.
*
- * Note: in addition to normal power managment events that effect the state of
+ * Note: in addition to normal power management events that effect the state of
* whether the keyguard should be showing, external apps and services may request
* that the keyguard be disabled via {@link #setKeyguardEnabled(boolean)}. When
* false, this will override all other conditions for turning on the keyguard.
@@ -224,7 +225,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
/**
* How long we'll wait for the {@link ViewMediatorCallback#keyguardDoneDrawing()}
* callback before unblocking a call to {@link #setKeyguardEnabled(boolean)}
- * that is reenabling the keyguard.
+ * that is re-enabling the keyguard.
*/
private static final int KEYGUARD_DONE_DRAWING_TIMEOUT_MS = 2000;
@@ -233,6 +234,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
* keyguard to show even if it is disabled for the current user.
*/
public static final String OPTION_FORCE_SHOW = "force_show";
+ private final DreamOverlayStateController mDreamOverlayStateController;
/** The stream type that the lock sounds are tied to. */
private int mUiSoundsStreamType;
@@ -273,14 +275,14 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
// these are protected by synchronized (this)
/**
- * External apps (like the phone app) can tell us to disable the keygaurd.
+ * External apps (like the phone app) can tell us to disable the keyguard.
*/
private boolean mExternallyEnabled = true;
/**
* Remember if an external call to {@link #setKeyguardEnabled} with value
* false caused us to hide the keyguard, so that we need to reshow it once
- * the keygaurd is reenabled with another call with value true.
+ * the keyguard is re-enabled with another call with value true.
*/
private boolean mNeedToReshowWhenReenabled = false;
@@ -291,6 +293,9 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
// AOD is enabled and status bar is in AOD state.
private boolean mAodShowing;
+ // Dream overlay is visible.
+ private boolean mDreamOverlayShowing;
+
/** Cached value of #isInputRestricted */
private boolean mInputRestricted;
@@ -304,7 +309,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
private int mDelayedShowingSequence;
/**
- * Simiar to {@link #mDelayedProfileShowingSequence}, but it is for profile case.
+ * Similar to {@link #mDelayedProfileShowingSequence}, but it is for profile case.
*/
private int mDelayedProfileShowingSequence;
@@ -341,7 +346,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
private String mPhoneState = TelephonyManager.EXTRA_STATE_IDLE;
/**
- * Whether a hide is pending an we are just waiting for #startKeyguardExitAnimation to be
+ * Whether a hide is pending and we are just waiting for #startKeyguardExitAnimation to be
* called.
* */
private boolean mHiding;
@@ -355,7 +360,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
| Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
/**
- * {@link #setKeyguardEnabled} waits on this condition when it reenables
+ * {@link #setKeyguardEnabled} waits on this condition when it re-enables
* the keyguard.
*/
private boolean mWaitingUntilKeyguardVisible = false;
@@ -470,6 +475,14 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
}
};
+ private final DreamOverlayStateController.Callback mDreamOverlayStateCallback =
+ new DreamOverlayStateController.Callback() {
+ @Override
+ public void onStateChanged() {
+ mDreamOverlayShowing = mDreamOverlayStateController.isOverlayActive();
+ }
+ };
+
KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
@Override
@@ -494,7 +507,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
synchronized (KeyguardViewMediator.this) {
resetKeyguardDonePendingLocked();
if (mLockPatternUtils.isLockScreenDisabled(userId)) {
- // If we switching to a user that has keyguard disabled, dismiss keyguard.
+ // If we are switching to a user that has keyguard disabled, dismiss keyguard.
dismiss(null /* callback */, null /* message */);
} else {
resetStateLocked();
@@ -508,7 +521,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
if (DEBUG) Log.d(TAG, String.format("onUserSwitchComplete %d", userId));
if (userId != UserHandle.USER_SYSTEM) {
UserInfo info = UserManager.get(mContext).getUserInfo(userId);
- // Don't try to dismiss if the user has Pin/Patter/Password set
+ // Don't try to dismiss if the user has Pin/Pattern/Password set
if (info == null || mLockPatternUtils.isSecure(userId)) {
return;
} else if (info.isGuest() || info.isDemo()) {
@@ -836,6 +849,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
Lazy<NotificationShadeDepthController> notificationShadeDepthController,
ScreenOnCoordinator screenOnCoordinator,
InteractionJankMonitor interactionJankMonitor,
+ DreamOverlayStateController dreamOverlayStateController,
Lazy<NotificationShadeWindowController> notificationShadeWindowControllerLazy) {
super(context);
mFalsingCollector = falsingCollector;
@@ -875,6 +889,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
mKeyguardUnlockAnimationControllerLazy = keyguardUnlockAnimationControllerLazy;
mScreenOffAnimationController = screenOffAnimationController;
mInteractionJankMonitor = interactionJankMonitor;
+ mDreamOverlayStateController = dreamOverlayStateController;
}
public void userActivity() {
@@ -980,6 +995,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
mSystemReady = true;
doKeyguardLocked(null);
mUpdateMonitor.registerCallback(mUpdateCallback);
+ mDreamOverlayStateController.addCallback(mDreamOverlayStateCallback);
}
// Most services aren't available until the system reaches the ready state, so we
// send it here when the device first boots.
@@ -1041,7 +1057,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
mUpdateMonitor.dispatchStartedGoingToSleep(offReason);
- // Reset keyguard going away state so we can start listening for fingerprint. We
+ // Reset keyguard going away state, so we can start listening for fingerprint. We
// explicitly DO NOT want to call
// mKeyguardViewControllerLazy.get().setKeyguardGoingAwayState(false)
// here, since that will mess with the device lock state.
@@ -1121,9 +1137,9 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
}
private long getLockTimeout(int userId) {
- // if the screen turned off because of timeout or the user hit the power button
+ // if the screen turned off because of timeout or the user hit the power button,
// and we don't need to lock immediately, set an alarm
- // to enable it a little bit later (i.e, give the user a chance
+ // to enable it a bit later (i.e, give the user a chance
// to turn the screen back on within a certain window without
// having to unlock the screen)
final ContentResolver cr = mContext.getContentResolver();
@@ -1217,7 +1233,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
}
/**
- * Let's us know when the device is waking up.
+ * It will let us know when the device is waking up.
*/
public void onStartedWakingUp(boolean cameraGestureTriggered) {
Trace.beginSection("KeyguardViewMediator#onStartedWakingUp");
@@ -1299,7 +1315,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
if (mExitSecureCallback != null) {
if (DEBUG) Log.d(TAG, "in process of verifyUnlock request, ignoring");
// we're in the process of handling a request to verify the user
- // can get past the keyguard. ignore extraneous requests to disable / reenable
+ // can get past the keyguard. ignore extraneous requests to disable / re-enable
return;
}
@@ -1310,7 +1326,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
updateInputRestrictedLocked();
hideLocked();
} else if (enabled && mNeedToReshowWhenReenabled) {
- // reenabled after previously hidden, reshow
+ // re-enabled after previously hidden, reshow
if (DEBUG) Log.d(TAG, "previously hidden, reshowing, reenabling "
+ "status bar expansion");
mNeedToReshowWhenReenabled = false;
@@ -1328,8 +1344,8 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
} else {
showLocked(null);
- // block until we know the keygaurd is done drawing (and post a message
- // to unblock us after a timeout so we don't risk blocking too long
+ // block until we know the keyguard is done drawing (and post a message
+ // to unblock us after a timeout, so we don't risk blocking too long
// and causing an ANR).
mWaitingUntilKeyguardVisible = true;
mHandler.sendEmptyMessageDelayed(KEYGUARD_DONE_DRAWING, KEYGUARD_DONE_DRAWING_TIMEOUT_MS);
@@ -1917,7 +1933,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
mExitSecureCallback = null;
- // after succesfully exiting securely, no need to reshow
+ // after successfully exiting securely, no need to reshow
// the keyguard when they've released the lock
mExternallyEnabled = true;
mNeedToReshowWhenReenabled = false;
@@ -1992,7 +2008,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
if (mAudioManager.isStreamMute(mUiSoundsStreamType)) return;
int id = mLockSounds.play(soundId,
- mLockSoundVolume, mLockSoundVolume, 1/*priortiy*/, 0/*loop*/, 1.0f/*rate*/);
+ mLockSoundVolume, mLockSoundVolume, 1/*priority*/, 0/*loop*/, 1.0f/*rate*/);
synchronized (this) {
mLockSoundStreamId = id;
}
@@ -2078,7 +2094,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
|| mScreenOnCoordinator.getWakeAndUnlocking()
&& mWallpaperSupportsAmbientMode) {
// When the wallpaper supports ambient mode, the scrim isn't fully opaque during
- // wake and unlock and we should fade in the app on top of the wallpaper
+ // wake and unlock, and we should fade in the app on top of the wallpaper
flags |= WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
}
if (mKeyguardViewControllerLazy.get().isUnlockWithWallpaper()) {
@@ -2123,7 +2139,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
Trace.beginSection("KeyguardViewMediator#handleHide");
// It's possible that the device was unlocked in a dream state. It's time to wake up.
- if (mAodShowing) {
+ if (mAodShowing || mDreamOverlayShowing) {
PowerManager pm = mContext.getSystemService(PowerManager.class);
pm.wakeUp(SystemClock.uptimeMillis(), PowerManager.WAKE_REASON_GESTURE,
"com.android.systemui:BOUNCER_DOZING");
@@ -2167,15 +2183,15 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
synchronized (KeyguardViewMediator.this) {
// Tell ActivityManager that we canceled the keyguard animation if
- // handleStartKeyguardExitAnimation was called but we're not hiding the keyguard, unless
- // we're animating the surface behind the keyguard and will be hiding the keyguard
- // shortly.
+ // handleStartKeyguardExitAnimation was called, but we're not hiding the keyguard,
+ // unless we're animating the surface behind the keyguard and will be hiding the
+ // keyguard shortly.
if (!mHiding
&& !mSurfaceBehindRemoteAnimationRequested
&& !mKeyguardStateController.isFlingingToDismissKeyguardDuringSwipeGesture()) {
if (finishedCallback != null) {
// There will not execute animation, send a finish callback to ensure the remote
- // animation won't hanging there.
+ // animation won't hang there.
try {
finishedCallback.onAnimationFinished();
} catch (RemoteException e) {
@@ -2192,7 +2208,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
if (mScreenOnCoordinator.getWakeAndUnlocking()) {
// Hack level over 9000: To speed up wake-and-unlock sequence, force it to report
- // the next draw from here so we don't have to wait for window manager to signal
+ // the next draw from here, so we don't have to wait for window manager to signal
// this to our ViewRootImpl.
mKeyguardViewControllerLazy.get().getViewRootImpl().setReportNextDraw();
mScreenOnCoordinator.setWakeAndUnlocking(false);
@@ -2344,7 +2360,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
}
/**
- * Called if the keyguard exit animation has been cancelled and we should dismiss to the
+ * Called if the keyguard exit animation has been cancelled, and we should dismiss to the
* keyguard.
*
* This can happen due to the system cancelling the RemoteAnimation (due to a timeout, a new
@@ -2595,7 +2611,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
}
/**
- * Notifies to System UI that the activity behind has now been drawn and it's safe to remove
+ * Notifies to System UI that the activity behind has now been drawn, and it's safe to remove
* the wallpaper and keyguard flag, and WindowManager has started running keyguard exit
* animation.
*
@@ -2609,7 +2625,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
}
/**
- * Notifies to System UI that the activity behind has now been drawn and it's safe to remove
+ * Notifies to System UI that the activity behind has now been drawn, and it's safe to remove
* the wallpaper and keyguard flag, and System UI should start running keyguard exit animation.
*
* @param apps The list of apps to animate.
@@ -2625,7 +2641,7 @@ public class KeyguardViewMediator extends CoreStartable implements Dumpable,
}
/**
- * Notifies to System UI that the activity behind has now been drawn and it's safe to remove
+ * Notifies to System UI that the activity behind has now been drawn, and it's safe to remove
* the wallpaper and keyguard flag, and start running keyguard exit animation.
*
* @param startTime the start time of the animation in uptime milliseconds. Deprecated.
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index f14d13093620..b49b49cbbb6d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -37,6 +37,7 @@ import com.android.systemui.classifier.FalsingCollector;
import com.android.systemui.classifier.FalsingModule;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.UiBackground;
+import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.keyguard.DismissCallbackRegistry;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
@@ -100,6 +101,7 @@ public class KeyguardModule {
Lazy<NotificationShadeDepthController> notificationShadeDepthController,
ScreenOnCoordinator screenOnCoordinator,
InteractionJankMonitor interactionJankMonitor,
+ DreamOverlayStateController dreamOverlayStateController,
Lazy<NotificationShadeWindowController> notificationShadeWindowController) {
return new KeyguardViewMediator(
context,
@@ -125,6 +127,7 @@ public class KeyguardModule {
notificationShadeDepthController,
screenOnCoordinator,
interactionJankMonitor,
+ dreamOverlayStateController,
notificationShadeWindowController
);
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
index c8cd43287c99..64ebe568c790 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaHierarchyManager.kt
@@ -31,6 +31,7 @@ import androidx.annotation.VisibleForTesting
import com.android.systemui.R
import com.android.systemui.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dreams.DreamOverlayStateController
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.CrossFadeHelper
@@ -82,7 +83,8 @@ class MediaHierarchyManager @Inject constructor(
private val notifLockscreenUserManager: NotificationLockscreenUserManager,
configurationController: ConfigurationController,
wakefulnessLifecycle: WakefulnessLifecycle,
- private val statusBarKeyguardViewManager: StatusBarKeyguardViewManager
+ private val statusBarKeyguardViewManager: StatusBarKeyguardViewManager,
+ private val dreamOverlayStateController: DreamOverlayStateController
) {
/**
@@ -167,7 +169,7 @@ class MediaHierarchyManager @Inject constructor(
})
}
- private val mediaHosts = arrayOfNulls<MediaHost>(LOCATION_LOCKSCREEN + 1)
+ private val mediaHosts = arrayOfNulls<MediaHost>(LOCATION_DREAM_OVERLAY + 1)
/**
* The last location where this view was at before going to the desired location. This is
* useful for guided transitions.
@@ -349,6 +351,17 @@ class MediaHierarchyManager @Inject constructor(
}
/**
+ * Is the doze animation currently Running
+ */
+ private var dreamOverlayActive: Boolean = false
+ private set(value) {
+ if (field != value) {
+ field = value
+ updateDesiredLocation(forceNoAnimation = true)
+ }
+ }
+
+ /**
* The current cross fade progress. 0.5f means it's just switching
* between the start and the end location and the content is fully faded, while 0.75f means
* that we're halfway faded in again in the target state.
@@ -444,6 +457,12 @@ class MediaHierarchyManager @Inject constructor(
}
})
+ dreamOverlayStateController.addCallback(object : DreamOverlayStateController.Callback {
+ override fun onStateChanged() {
+ dreamOverlayStateController.isOverlayActive.also { dreamOverlayActive = it }
+ }
+ })
+
wakefulnessLifecycle.addObserver(object : WakefulnessLifecycle.Observer {
override fun onFinishedGoingToSleep() {
goingToSleep = false
@@ -940,6 +959,7 @@ class MediaHierarchyManager @Inject constructor(
statusbarState == StatusBarState.FULLSCREEN_USER_SWITCHER))
val allowedOnLockscreen = notifLockscreenUserManager.shouldShowLockscreenNotifications()
val location = when {
+ dreamOverlayActive -> LOCATION_DREAM_OVERLAY
(qsExpansion > 0.0f || inSplitShade) && !onLockscreen -> LOCATION_QS
qsExpansion > 0.4f && onLockscreen -> LOCATION_QS
!hasActiveMedia -> LOCATION_QS
@@ -1035,6 +1055,11 @@ class MediaHierarchyManager @Inject constructor(
const val LOCATION_LOCKSCREEN = 2
/**
+ * Attached on the dream overlay
+ */
+ const val LOCATION_DREAM_OVERLAY = 3
+
+ /**
* Attached at the root of the hierarchy in an overlay
*/
const val IN_OVERLAY = -1000
diff --git a/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java b/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java
index 4baef3aef309..2bc910e4a21a 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dagger/MediaModule.java
@@ -25,6 +25,7 @@ import com.android.systemui.media.MediaDataManager;
import com.android.systemui.media.MediaHierarchyManager;
import com.android.systemui.media.MediaHost;
import com.android.systemui.media.MediaHostStatesManager;
+import com.android.systemui.media.dream.dagger.MediaComplicationComponent;
import com.android.systemui.media.taptotransfer.MediaTttCommandLineHelper;
import com.android.systemui.media.taptotransfer.MediaTttFlags;
import com.android.systemui.media.taptotransfer.receiver.MediaTttChipControllerReceiver;
@@ -43,11 +44,14 @@ import dagger.multibindings.ClassKey;
import dagger.multibindings.IntoMap;
/** Dagger module for the media package. */
-@Module
+@Module(subcomponents = {
+ MediaComplicationComponent.class,
+})
public interface MediaModule {
String QS_PANEL = "media_qs_panel";
String QUICK_QS_PANEL = "media_quick_qs_panel";
String KEYGUARD = "media_keyguard";
+ String DREAM = "dream";
/** */
@Provides
@@ -82,6 +86,16 @@ public interface MediaModule {
/** */
@Provides
@SysUISingleton
+ @Named(DREAM)
+ static MediaHost providesDreamMediaHost(MediaHost.MediaHostStateHolder stateHolder,
+ MediaHierarchyManager hierarchyManager, MediaDataManager dataManager,
+ MediaHostStatesManager statesManager) {
+ return new MediaHost(stateHolder, hierarchyManager, dataManager, statesManager);
+ }
+
+ /** */
+ @Provides
+ @SysUISingleton
static Optional<MediaTttChipControllerSender> providesMediaTttChipControllerSender(
MediaTttFlags mediaTttFlags,
Context context,
diff --git a/packages/SystemUI/src/com/android/systemui/media/dream/MediaComplicationViewController.java b/packages/SystemUI/src/com/android/systemui/media/dream/MediaComplicationViewController.java
new file mode 100644
index 000000000000..65c5bc76f3c5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/dream/MediaComplicationViewController.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.dream;
+
+import static com.android.systemui.media.dagger.MediaModule.DREAM;
+import static com.android.systemui.media.dream.dagger.MediaComplicationComponent.MediaComplicationModule.MEDIA_COMPLICATION_CONTAINER;
+
+import android.widget.FrameLayout;
+
+import com.android.systemui.media.MediaHierarchyManager;
+import com.android.systemui.media.MediaHost;
+import com.android.systemui.media.MediaHostState;
+import com.android.systemui.util.ViewController;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+/**
+ * {@link MediaComplicationViewController} handles connecting the
+ * {@link com.android.systemui.dreams.complication.Complication} view to the {@link MediaHost}.
+ */
+public class MediaComplicationViewController extends ViewController<FrameLayout> {
+ private final MediaHost mMediaHost;
+
+ @Inject
+ public MediaComplicationViewController(
+ @Named(MEDIA_COMPLICATION_CONTAINER) FrameLayout view,
+ @Named(DREAM) MediaHost mediaHost) {
+ super(view);
+ mMediaHost = mediaHost;
+ }
+
+ @Override
+ protected void onInit() {
+ super.onInit();
+ mMediaHost.setExpansion(MediaHostState.COLLAPSED);
+ mMediaHost.setShowsOnlyActiveMedia(true);
+ mMediaHost.setFalsingProtectionNeeded(true);
+ mMediaHost.init(MediaHierarchyManager.LOCATION_DREAM_OVERLAY);
+ }
+
+ @Override
+ protected void onViewAttached() {
+ mMediaHost.hostView.setLayoutParams(new FrameLayout.LayoutParams(
+ FrameLayout.LayoutParams.MATCH_PARENT,
+ FrameLayout.LayoutParams.WRAP_CONTENT));
+ mView.addView(mMediaHost.hostView);
+ }
+
+ @Override
+ protected void onViewDetached() {
+ mView.removeView(mMediaHost.hostView);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamComplication.java b/packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamComplication.java
new file mode 100644
index 000000000000..2c35db337cda
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamComplication.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.dream;
+
+import com.android.systemui.dreams.complication.Complication;
+import com.android.systemui.dreams.complication.ComplicationViewModel;
+import com.android.systemui.media.dream.dagger.MediaComplicationComponent;
+
+import javax.inject.Inject;
+
+/**
+ * Media control complication for dream overlay.
+ */
+public class MediaDreamComplication implements Complication {
+ MediaComplicationComponent.Factory mComponentFactory;
+
+ /**
+ * Default constructor for {@link MediaDreamComplication}.
+ */
+ @Inject
+ public MediaDreamComplication(MediaComplicationComponent.Factory componentFactory) {
+ mComponentFactory = componentFactory;
+ }
+
+ @Override
+ public ViewHolder createView(ComplicationViewModel model) {
+ return mComponentFactory.create().getViewHolder();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamSentinel.java b/packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamSentinel.java
new file mode 100644
index 000000000000..8934cd1085b8
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/dream/MediaDreamSentinel.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.dream;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.systemui.CoreStartable;
+import com.android.systemui.dreams.DreamOverlayStateController;
+import com.android.systemui.media.MediaData;
+import com.android.systemui.media.MediaDataManager;
+import com.android.systemui.media.SmartspaceMediaData;
+
+import javax.inject.Inject;
+
+/**
+ * {@link MediaDreamSentinel} is responsible for tracking media state and registering/unregistering
+ * the media complication as appropriate
+ */
+public class MediaDreamSentinel extends CoreStartable {
+ private MediaDataManager.Listener mListener = new MediaDataManager.Listener() {
+ private boolean mAdded;
+ @Override
+ public void onSmartspaceMediaDataRemoved(@NonNull String key, boolean immediately) {
+ }
+
+ @Override
+ public void onMediaDataRemoved(@NonNull String key) {
+ if (!mAdded) {
+ return;
+ }
+
+ if (mMediaDataManager.hasActiveMedia()) {
+ return;
+ }
+
+ mAdded = false;
+ mDreamOverlayStateController.removeComplication(mComplication);
+ }
+
+ @Override
+ public void onSmartspaceMediaDataLoaded(@NonNull String key,
+ @NonNull SmartspaceMediaData data, boolean shouldPrioritize,
+ boolean isSsReactivated) {
+ }
+
+ @Override
+ public void onMediaDataLoaded(@NonNull String key, @Nullable String oldKey,
+ @NonNull MediaData data, boolean immediately, int receivedSmartspaceCardLatency) {
+ if (mAdded) {
+ return;
+ }
+
+ if (!mMediaDataManager.hasActiveMedia()) {
+ return;
+ }
+
+ mAdded = true;
+ mDreamOverlayStateController.addComplication(mComplication);
+ }
+ };
+
+ private final MediaDataManager mMediaDataManager;
+ private final DreamOverlayStateController mDreamOverlayStateController;
+ private final MediaDreamComplication mComplication;
+
+ @Inject
+ public MediaDreamSentinel(Context context, MediaDataManager mediaDataManager,
+ DreamOverlayStateController dreamOverlayStateController,
+ MediaDreamComplication complication) {
+ super(context);
+ mMediaDataManager = mediaDataManager;
+ mDreamOverlayStateController = dreamOverlayStateController;
+ mComplication = complication;
+ }
+
+ @Override
+ public void start() {
+ mMediaDataManager.addListener(mListener);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dream/MediaViewHolder.java b/packages/SystemUI/src/com/android/systemui/media/dream/MediaViewHolder.java
new file mode 100644
index 000000000000..128a38c639be
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/dream/MediaViewHolder.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.dream;
+
+import static com.android.systemui.media.dream.dagger.MediaComplicationComponent.MediaComplicationModule.MEDIA_COMPLICATION_CONTAINER;
+import static com.android.systemui.media.dream.dagger.MediaComplicationComponent.MediaComplicationModule.MEDIA_COMPLICATION_LAYOUT_PARAMS;
+
+import android.view.View;
+import android.widget.FrameLayout;
+
+import com.android.systemui.dreams.complication.Complication;
+import com.android.systemui.dreams.complication.ComplicationLayoutParams;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+/**
+ * {@link Complication.ViewHolder} implementation for media control.
+ */
+public class MediaViewHolder implements Complication.ViewHolder {
+ private final FrameLayout mContainer;
+ private final MediaComplicationViewController mViewController;
+ private final ComplicationLayoutParams mLayoutParams;
+
+ @Inject
+ MediaViewHolder(@Named(MEDIA_COMPLICATION_CONTAINER) FrameLayout container,
+ MediaComplicationViewController controller,
+ @Named(MEDIA_COMPLICATION_LAYOUT_PARAMS) ComplicationLayoutParams layoutParams) {
+ mContainer = container;
+ mViewController = controller;
+ mViewController.init();
+ mLayoutParams = layoutParams;
+ }
+
+ @Override
+ public View getView() {
+ return mContainer;
+ }
+
+ @Override
+ public ComplicationLayoutParams getLayoutParams() {
+ return mLayoutParams;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/media/dream/dagger/MediaComplicationComponent.java b/packages/SystemUI/src/com/android/systemui/media/dream/dagger/MediaComplicationComponent.java
new file mode 100644
index 000000000000..3372899b8fd7
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/media/dream/dagger/MediaComplicationComponent.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.dream.dagger;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import android.content.Context;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import com.android.systemui.dreams.complication.ComplicationLayoutParams;
+import com.android.systemui.media.dream.MediaViewHolder;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+
+import javax.inject.Named;
+import javax.inject.Scope;
+
+import dagger.Module;
+import dagger.Provides;
+import dagger.Subcomponent;
+
+/**
+ * {@link MediaComplicationComponent} is responsible for generating dependencies surrounding the
+ * media {@link com.android.systemui.dreams.complication.Complication}, such as view controllers
+ * and layout details.
+ */
+@Subcomponent(modules = {
+ MediaComplicationComponent.MediaComplicationModule.class,
+})
+@MediaComplicationComponent.MediaComplicationScope
+public interface MediaComplicationComponent {
+ @Documented
+ @Retention(RUNTIME)
+ @Scope
+ @interface MediaComplicationScope {}
+
+ /**
+ * Generates {@link MediaComplicationComponent}.
+ */
+ @Subcomponent.Factory
+ interface Factory {
+ MediaComplicationComponent create();
+ }
+
+ /**
+ * Creates {@link MediaViewHolder}.
+ */
+ MediaViewHolder getViewHolder();
+
+ /**
+ * Scoped values for {@link MediaComplicationComponent}.
+ */
+ @Module
+ interface MediaComplicationModule {
+ String MEDIA_COMPLICATION_CONTAINER = "media_complication_container";
+ String MEDIA_COMPLICATION_LAYOUT_PARAMS = "media_complication_layout_params";
+
+ /**
+ * Provides the complication view.
+ */
+ @Provides
+ @MediaComplicationScope
+ @Named(MEDIA_COMPLICATION_CONTAINER)
+ static FrameLayout provideComplicationContainer(Context context) {
+ return new FrameLayout(context);
+ }
+
+ /**
+ * Provides the layout parameters for the complication view.
+ */
+ @Provides
+ @MediaComplicationScope
+ @Named(MEDIA_COMPLICATION_LAYOUT_PARAMS)
+ static ComplicationLayoutParams provideLayoutParams() {
+ return new ComplicationLayoutParams(0,
+ ViewGroup.LayoutParams.WRAP_CONTENT,
+ ComplicationLayoutParams.POSITION_BOTTOM
+ | ComplicationLayoutParams.POSITION_END,
+ ComplicationLayoutParams.DIRECTION_UP,
+ 0,
+ true);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
index 4f4bd1e86e7c..90ed3c6fa5da 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/gestural/EdgeBackGestureHandler.java
@@ -318,7 +318,11 @@ public class EdgeBackGestureHandler extends CurrentUserTracker
String recentsPackageName = recentsComponentName.getPackageName();
PackageManager manager = context.getPackageManager();
try {
- Resources resources = manager.getResourcesForApplication(recentsPackageName);
+ Resources resources = manager.getResourcesForApplication(
+ manager.getApplicationInfo(recentsPackageName,
+ PackageManager.MATCH_UNINSTALLED_PACKAGES
+ | PackageManager.MATCH_DISABLED_COMPONENTS
+ | PackageManager.GET_SHARED_LIBRARY_FILES));
int resId = resources.getIdentifier(
"gesture_blocking_activities", "array", recentsPackageName);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 597e4242af66..9d43d303b834 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -37,6 +37,7 @@ import android.content.Context;
import android.graphics.drawable.Icon;
import android.hardware.biometrics.BiometricAuthenticator.Modality;
import android.hardware.biometrics.BiometricManager.BiometricMultiSensorMode;
+import android.hardware.biometrics.IBiometricContextListener;
import android.hardware.biometrics.IBiometricSysuiReceiver;
import android.hardware.biometrics.PromptInfo;
import android.hardware.display.DisplayManager;
@@ -154,6 +155,7 @@ public class CommandQueue extends IStatusBar.Stub implements
private static final int MSG_SET_UDFPS_HBM_LISTENER = 60 << MSG_SHIFT;
private static final int MSG_TILE_SERVICE_REQUEST_ADD = 61 << MSG_SHIFT;
private static final int MSG_TILE_SERVICE_REQUEST_CANCEL = 62 << MSG_SHIFT;
+ private static final int MSG_SET_BIOMETRICS_LISTENER = 63 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -317,6 +319,12 @@ public class CommandQueue extends IStatusBar.Stub implements
}
/**
+ * @see IStatusBar#setBiometicContextListener(IBiometricContextListener)
+ */
+ default void setBiometicContextListener(IBiometricContextListener listener) {
+ }
+
+ /**
* @see IStatusBar#setUdfpsHbmListener(IUdfpsHbmListener)
*/
default void setUdfpsHbmListener(IUdfpsHbmListener listener) {
@@ -958,6 +966,13 @@ public class CommandQueue extends IStatusBar.Stub implements
}
@Override
+ public void setBiometicContextListener(IBiometricContextListener listener) {
+ synchronized (mLock) {
+ mHandler.obtainMessage(MSG_SET_BIOMETRICS_LISTENER, listener).sendToTarget();
+ }
+ }
+
+ @Override
public void setUdfpsHbmListener(IUdfpsHbmListener listener) {
synchronized (mLock) {
mHandler.obtainMessage(MSG_SET_UDFPS_HBM_LISTENER, listener).sendToTarget();
@@ -1411,6 +1426,12 @@ public class CommandQueue extends IStatusBar.Stub implements
mCallbacks.get(i).hideAuthenticationDialog();
}
break;
+ case MSG_SET_BIOMETRICS_LISTENER:
+ for (int i = 0; i < mCallbacks.size(); i++) {
+ mCallbacks.get(i).setBiometicContextListener(
+ (IBiometricContextListener) msg.obj);
+ }
+ break;
case MSG_SET_UDFPS_HBM_LISTENER:
for (int i = 0; i < mCallbacks.size(); i++) {
mCallbacks.get(i).setUdfpsHbmListener((IUdfpsHbmListener) msg.obj);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
index c136d9cc7272..b312ce20b313 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/LockscreenShadeTransitionController.kt
@@ -337,11 +337,11 @@ class LockscreenShadeTransitionController @Inject constructor(
if (field != value || forceApplyAmount) {
field = value
if (!nsslController.isInLockedDownShade() || field == 0f || forceApplyAmount) {
- nsslController.setTransitionToFullShadeAmount(field)
- notificationPanelController.setTransitionToFullShadeAmount(field,
- false /* animate */, 0 /* delay */)
qSDragProgress = MathUtils.saturate(dragDownAmount / scrimTransitionDistance)
+ nsslController.setTransitionToFullShadeAmount(field, qSDragProgress)
qS.setTransitionToFullShadeAmount(field, qSDragProgress)
+ notificationPanelController.setTransitionToFullShadeAmount(field,
+ false /* animate */, 0 /* delay */)
// TODO: appear media also in split shade
val mediaAmount = if (useSplitShade) 0f else field
mediaHierarchyManager.setTransitionToFullShadeAmount(mediaAmount)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 51a66aad39fb..3411eab23d63 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar;
+import static com.android.systemui.statusbar.phone.NotificationIconContainer.MAX_ICONS_ON_LOCKSCREEN;
+
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
@@ -32,6 +34,7 @@ import android.view.animation.PathInterpolator;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.policy.SystemBarUtils;
import com.android.systemui.R;
+import com.android.systemui.animation.Interpolators;
import com.android.systemui.animation.ShadeInterpolation;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.statusbar.notification.NotificationUtils;
@@ -45,6 +48,7 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll
import com.android.systemui.statusbar.notification.stack.StackScrollAlgorithm;
import com.android.systemui.statusbar.notification.stack.ViewState;
import com.android.systemui.statusbar.phone.NotificationIconContainer;
+import com.android.systemui.util.Utils;
/**
* A notification shelf view that is placed inside the notification scroller. It manages the
@@ -81,6 +85,11 @@ public class NotificationShelf extends ActivatableNotificationView implements
private int mIndexOfFirstViewInShelf = -1;
private float mCornerAnimationDistance;
private NotificationShelfController mController;
+ private int mActualWidth = -1;
+ private boolean mUseSplitShade;
+
+ /** Fraction of lockscreen to shade animation (on lockscreen swipe down). */
+ private float mFractionToShade;
public NotificationShelf(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -122,13 +131,16 @@ public class NotificationShelf extends ActivatableNotificationView implements
layoutParams.height = res.getDimensionPixelOffset(R.dimen.notification_shelf_height);
setLayoutParams(layoutParams);
- int padding = res.getDimensionPixelOffset(R.dimen.shelf_icon_container_padding);
+ final int padding = res.getDimensionPixelOffset(R.dimen.shelf_icon_container_padding);
mShelfIcons.setPadding(padding, 0, padding, 0);
mScrollFastThreshold = res.getDimensionPixelOffset(R.dimen.scroll_fast_threshold);
mShowNotificationShelf = res.getBoolean(R.bool.config_showNotificationShelf);
mCornerAnimationDistance = res.getDimensionPixelSize(
R.dimen.notification_corner_animation_distance);
+ // TODO(b/213480466) enable short shelf on split shade
+ mUseSplitShade = Utils.shouldUseSplitNotificationShade(mContext.getResources());
+
mShelfIcons.setInNotificationIconShelf(true);
if (!mShowNotificationShelf) {
setVisibility(GONE);
@@ -203,6 +215,10 @@ public class NotificationShelf extends ActivatableNotificationView implements
final float stackEnd = ambientState.getStackY() + ambientState.getStackHeight();
viewState.yTranslation = stackEnd - viewState.height;
+
+ final int shortestWidth = mShelfIcons.calculateWidthFor(MAX_ICONS_ON_LOCKSCREEN);
+ final float fraction = Interpolators.STANDARD.getInterpolation(mFractionToShade);
+ updateStateWidth(viewState, fraction, shortestWidth);
} else {
viewState.hidden = true;
viewState.location = ExpandableViewState.LOCATION_GONE;
@@ -211,6 +227,77 @@ public class NotificationShelf extends ActivatableNotificationView implements
}
/**
+ * @param shelfState View state for NotificationShelf
+ * @param fraction Fraction of lockscreen to shade transition
+ * @param shortestWidth Shortest width to use for lockscreen shelf
+ */
+ @VisibleForTesting
+ public void updateStateWidth(ShelfState shelfState, float fraction, int shortestWidth) {
+ shelfState.actualWidth = !mUseSplitShade && mAmbientState.isOnKeyguard()
+ ? (int) MathUtils.lerp(shortestWidth, getWidth(), fraction)
+ : getWidth();
+ }
+
+ /**
+ * @param fractionToShade Fraction of lockscreen to shade transition
+ */
+ public void setFractionToShade(float fractionToShade) {
+ mFractionToShade = fractionToShade;
+ }
+
+ /**
+ * @return Actual width of shelf, accounting for possible ongoing width animation
+ */
+ public int getActualWidth() {
+ return mActualWidth > -1 ? mActualWidth : getWidth();
+ }
+
+ /**
+ * @param localX Click x from left of screen
+ * @param slop Margin of error within which we count x for valid click
+ * @param left Left of shelf, from left of screen
+ * @param right Right of shelf, from left of screen
+ * @return Whether click x was in view
+ */
+ @VisibleForTesting
+ public boolean isXInView(float localX, float slop, float left, float right) {
+ return (left - slop) <= localX && localX < (right + slop);
+ }
+
+ /**
+ * @param localY Click y from top of shelf
+ * @param slop Margin of error within which we count y for valid click
+ * @param top Top of shelf
+ * @param bottom Height of shelf
+ * @return Whether click y was in view
+ */
+ @VisibleForTesting
+ public boolean isYInView(float localY, float slop, float top, float bottom) {
+ return (top - slop) <= localY && localY < (bottom + slop);
+ }
+
+ /**
+ * @param localX Click x
+ * @param localY Click y
+ * @param slop Margin of error for valid click
+ * @return Whether this click was on the visible (non-clipped) part of the shelf
+ */
+ @Override
+ public boolean pointInView(float localX, float localY, float slop) {
+ final float containerWidth = getWidth();
+ final float shelfWidth = getActualWidth();
+
+ final float left = isLayoutRtl() ? containerWidth - shelfWidth : 0;
+ final float right = isLayoutRtl() ? containerWidth : shelfWidth;
+
+ final float top = mClipTopAmount;
+ final float bottom = getActualHeight();
+
+ return isXInView(localX, slop, left, right)
+ && isYInView(localY, slop, top, bottom);
+ }
+
+ /**
* Update the shelf appearance based on the other notifications around it. This transforms
* the icons from the notification area into the shelf.
*/
@@ -732,11 +819,15 @@ public class NotificationShelf extends ActivatableNotificationView implements
// we always want to clip to our sides, such that nothing can draw outside of these bounds
int height = getResources().getDisplayMetrics().heightPixels;
mClipRect.set(0, -height, getWidth(), height);
- mShelfIcons.setClipBounds(mClipRect);
+ if (mShelfIcons != null) {
+ mShelfIcons.setClipBounds(mClipRect);
+ }
}
private void updateRelativeOffset() {
- mCollapsedIcons.getLocationOnScreen(mTmp);
+ if (mCollapsedIcons != null) {
+ mCollapsedIcons.getLocationOnScreen(mTmp);
+ }
getLocationOnScreen(mTmp);
}
@@ -831,9 +922,20 @@ public class NotificationShelf extends ActivatableNotificationView implements
mIndexOfFirstViewInShelf = mHostLayoutController.indexOfChild(firstViewInShelf);
}
- private class ShelfState extends ExpandableViewState {
+ public class ShelfState extends ExpandableViewState {
private boolean hasItemsInStableShelf;
private ExpandableView firstViewInShelf;
+ public int actualWidth = -1;
+
+ private void updateShelfWidth(View view) {
+ if (actualWidth < 0) {
+ return;
+ }
+ mActualWidth = actualWidth;
+ ActivatableNotificationView anv = (ActivatableNotificationView) view;
+ anv.getBackgroundNormal().setActualWidth(actualWidth);
+ mShelfIcons.setActualLayoutWidth(actualWidth);
+ }
@Override
public void applyToView(View view) {
@@ -846,19 +948,21 @@ public class NotificationShelf extends ActivatableNotificationView implements
updateAppearance();
setHasItemsInStableShelf(hasItemsInStableShelf);
mShelfIcons.setAnimationsEnabled(mAnimationsEnabled);
+ updateShelfWidth(view);
}
@Override
- public void animateTo(View child, AnimationProperties properties) {
+ public void animateTo(View view, AnimationProperties properties) {
if (!mShowNotificationShelf) {
return;
}
- super.animateTo(child, properties);
+ super.animateTo(view, properties);
setIndexOfFirstViewInShelf(firstViewInShelf);
updateAppearance();
setHasItemsInStableShelf(hasItemsInStableShelf);
mShelfIcons.setAnimationsEnabled(mAnimationsEnabled);
+ updateShelfWidth(view);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
index bd948eceab9c..f56602ee2bcd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
@@ -518,6 +518,7 @@ public class StatusBarStateControllerImpl implements
}
private void recordHistoricalState(int newState, int lastState, boolean upcoming) {
+ Trace.traceCounter(Trace.TRACE_TAG_APP, "statusBarState", newState);
mHistoryIndex = (mHistoryIndex + 1) % HISTORY_SIZE;
HistoricalState state = mHistoricalRecords[mHistoryIndex];
state.mNewState = newState;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index 5d6d0f701f12..fca2aa167e37 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -162,6 +162,13 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
updateBackgroundTint();
}
+ /**
+ * @return The background of this view.
+ */
+ public NotificationBackgroundView getBackgroundNormal() {
+ return mBackgroundNormal;
+ }
+
@Override
protected void onFinishInflate() {
super.onFinishInflate();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
index 0f615aa9356f..c640ab6c3a90 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBackgroundView.java
@@ -29,6 +29,7 @@ import android.view.View;
import com.android.internal.util.ArrayUtils;
import com.android.systemui.R;
+import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.notification.ExpandAnimationParameters;
/**
@@ -39,15 +40,17 @@ public class NotificationBackgroundView extends View {
private final boolean mDontModifyCorners;
private Drawable mBackground;
private int mClipTopAmount;
- private int mActualHeight;
private int mClipBottomAmount;
private int mTintColor;
private final float[] mCornerRadii = new float[8];
private boolean mBottomIsRounded;
private int mBackgroundTop;
private boolean mBottomAmountClips = true;
+ private int mActualHeight = -1;
+ private int mActualWidth = -1;
private boolean mExpandAnimationRunning;
- private float mActualWidth;
+ private int mExpandAnimationWidth = -1;
+ private int mExpandAnimationHeight = -1;
private int mDrawableAlpha = 255;
private boolean mIsPressedAllowed;
@@ -59,11 +62,12 @@ public class NotificationBackgroundView extends View {
@Override
protected void onDraw(Canvas canvas) {
- if (mClipTopAmount + mClipBottomAmount < mActualHeight - mBackgroundTop
+ if (mClipTopAmount + mClipBottomAmount < getActualHeight() - mBackgroundTop
|| mExpandAnimationRunning) {
canvas.save();
if (!mExpandAnimationRunning) {
- canvas.clipRect(0, mClipTopAmount, getWidth(), mActualHeight - mClipBottomAmount);
+ canvas.clipRect(0, mClipTopAmount, getWidth(),
+ getActualHeight() - mClipBottomAmount);
}
draw(canvas, mBackground);
canvas.restore();
@@ -73,17 +77,23 @@ public class NotificationBackgroundView extends View {
private void draw(Canvas canvas, Drawable drawable) {
if (drawable != null) {
int top = mBackgroundTop;
- int bottom = mActualHeight;
+ int bottom = getActualHeight();
if (mBottomIsRounded
&& mBottomAmountClips
&& !mExpandAnimationRunning) {
bottom -= mClipBottomAmount;
}
- int left = 0;
- int right = getWidth();
+ final boolean isRtl = isLayoutRtl();
+ final int width = getWidth();
+ final int actualWidth = getActualWidth();
+
+ int left = isRtl ? width - actualWidth : 0;
+ int right = isRtl ? width : actualWidth;
+
if (mExpandAnimationRunning) {
- left = (int) ((getWidth() - mActualWidth) / 2.0f);
- right = (int) (left + mActualWidth);
+ // Horizontally center this background view inside of the container
+ left = (int) ((width - actualWidth) / 2.0f);
+ right = (int) (left + actualWidth);
}
drawable.setBounds(left, top, right, bottom);
drawable.draw(canvas);
@@ -152,8 +162,26 @@ public class NotificationBackgroundView extends View {
invalidate();
}
- public int getActualHeight() {
- return mActualHeight;
+ private int getActualHeight() {
+ if (mExpandAnimationRunning && mExpandAnimationHeight > -1) {
+ return mExpandAnimationHeight;
+ } else if (mActualHeight > -1) {
+ return mActualHeight;
+ }
+ return getHeight();
+ }
+
+ public void setActualWidth(int actualWidth) {
+ mActualWidth = actualWidth;
+ }
+
+ private int getActualWidth() {
+ if (mExpandAnimationRunning && mExpandAnimationWidth > -1) {
+ return mExpandAnimationWidth;
+ } else if (mActualWidth > -1) {
+ return mActualWidth;
+ }
+ return getWidth();
}
public void setClipTopAmount(int clipTopAmount) {
@@ -241,9 +269,9 @@ public class NotificationBackgroundView extends View {
}
/** Set the current expand animation size. */
- public void setExpandAnimationSize(int actualWidth, int actualHeight) {
- mActualHeight = actualHeight;
- mActualWidth = actualWidth;
+ public void setExpandAnimationSize(int width, int height) {
+ mExpandAnimationHeight = width;
+ mExpandAnimationWidth = height;
invalidate();
}
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 9655a9ce5e45..9f6a81d3a9ee 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
@@ -5497,6 +5497,17 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
}
/**
+ * @param fraction Fraction of the lockscreen to shade transition. 0f for all other states.
+ * Once the lockscreen to shade transition completes and the shade is 100% open
+ * LockscreenShadeTransitionController resets fraction to 0
+ * where it remains until the next lockscreen-to-shade transition.
+ */
+ public void setFractionToShade(float fraction) {
+ mShelf.setFractionToShade(fraction);
+ requestChildrenUpdate();
+ }
+
+ /**
* Set a listener to when scrolling changes.
*/
public void setOnScrollListener(Consumer<Integer> listener) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 0d0e5e850523..334128a2b4ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -1515,10 +1515,18 @@ public class NotificationStackScrollLayoutController {
}
/**
- * Set the amount of pixels we have currently dragged down if we're transitioning to the full
- * shade. 0.0f means we're not transitioning yet.
+ * @param amount The amount of pixels we have currently dragged down
+ * for the lockscreen to shade transition. 0f for all other states.
+ * @param fraction The fraction of lockscreen to shade transition.
+ * 0f for all other states.
+ *
+ * Once the lockscreen to shade transition completes and the shade is 100% open,
+ * LockscreenShadeTransitionController resets amount and fraction to 0, where they remain
+ * until the next lockscreen-to-shade transition.
*/
- public void setTransitionToFullShadeAmount(float amount) {
+ public void setTransitionToFullShadeAmount(float amount, float fraction) {
+ mView.setFractionToShade(fraction);
+
float extraTopInset = 0.0f;
if (mStatusBarStateController.getState() == KEYGUARD) {
float overallProgress = MathUtils.saturate(amount / mView.getHeight());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
index 0d2bddcc8b77..89b5aef00656 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -44,6 +44,7 @@ public class StackStateAnimator {
public static final int ANIMATION_DURATION_STANDARD = 360;
public static final int ANIMATION_DURATION_CORNER_RADIUS = 200;
public static final int ANIMATION_DURATION_WAKEUP = 500;
+ public static final int ANIMATION_DURATION_WAKEUP_SCRIM = 667;
public static final int ANIMATION_DURATION_GO_TO_FULL_SHADE = 448;
public static final int ANIMATION_DURATION_APPEAR_DISAPPEAR = 464;
public static final int ANIMATION_DURATION_SWIPE = 200;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
index c09c48540901..ebfed1a689cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
@@ -135,7 +135,8 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
}
}.setDuration(CONTENT_FADE_DURATION);
- private static final int MAX_VISIBLE_ICONS_ON_LOCK = 5;
+ private static final int MAX_ICONS_ON_AOD = 3;
+ public static final int MAX_ICONS_ON_LOCKSCREEN = 3;
public static final int MAX_STATIC_ICONS = 4;
private static final int MAX_DOTS = 1;
@@ -386,6 +387,19 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
}
/**
+ * @return Width of shelf for the given number of icons and overflow dot
+ */
+ public int calculateWidthFor(int numMaxIcons) {
+ if (getChildCount() == 0) {
+ return 0;
+ }
+ return (int) (getActualPaddingStart()
+ + numMaxIcons * mIconSize
+ + mOverflowWidth
+ + getActualPaddingEnd());
+ }
+
+ /**
* Calculate the horizontal translations for each notification based on how much the icons
* are inserted into the notification container.
* If this is not a whole number, the fraction means by how much the icon is appearing.
@@ -394,7 +408,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
float translationX = getActualPaddingStart();
int firstOverflowIndex = -1;
int childCount = getChildCount();
- int maxVisibleIcons = mOnLockScreen ? MAX_VISIBLE_ICONS_ON_LOCK :
+ int maxVisibleIcons = mOnLockScreen ? MAX_ICONS_ON_AOD :
mIsStaticLayout ? MAX_STATIC_ICONS : childCount;
float layoutEnd = getLayoutEnd();
float overflowStart = getMaxOverflowStart();
@@ -414,7 +428,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
}
boolean forceOverflow = mSpeedBumpIndex != -1 && i >= mSpeedBumpIndex
&& iconState.iconAppearAmount > 0.0f || i >= maxVisibleIcons;
- boolean noOverflowAfter = i == childCount - 1;
+ boolean isLastChild = i == childCount - 1;
float drawingScale = mOnLockScreen && view instanceof StatusBarIconView
? ((StatusBarIconView) view).getIconScaleIncreased()
: 1f;
@@ -423,10 +437,10 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
: StatusBarIconView.STATE_ICON;
boolean isOverflowing =
- (translationX > (noOverflowAfter ? layoutEnd - mIconSize
+ (translationX > (isLastChild ? layoutEnd - mIconSize
: overflowStart - mIconSize));
if (firstOverflowIndex == -1 && (forceOverflow || isOverflowing)) {
- firstOverflowIndex = noOverflowAfter && !forceOverflow ? i - 1 : i;
+ firstOverflowIndex = isLastChild && !forceOverflow ? i - 1 : i;
mVisualOverflowStart = layoutEnd - mOverflowWidth;
if (forceOverflow || mIsStaticLayout) {
mVisualOverflowStart = Math.min(translationX, mVisualOverflowStart);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index 9d3f19ad039a..bb0ed95cc6ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -4188,9 +4188,10 @@ public class NotificationPanelViewController extends PanelViewController
return false;
}
- // Do not allow panel expansion if bouncer is scrimmed, otherwise user would be able
- // to pull down QS or expand the shade.
- if (mStatusBar.isBouncerShowingScrimmed()) {
+ // Do not allow panel expansion if bouncer is scrimmed or showing over a dream,
+ // otherwise user would be able to pull down QS or expand the shade.
+ if (mStatusBar.isBouncerShowingScrimmed()
+ || mStatusBar.isBouncerShowingOverDream()) {
return false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
index dc6efba97ff5..c466a8ce6d3f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
@@ -73,6 +73,10 @@ import java.io.PrintWriter;
public abstract class PanelViewController {
public static final boolean DEBUG = PanelView.DEBUG;
public static final String TAG = PanelView.class.getSimpleName();
+ public static final float FLING_MAX_LENGTH_SECONDS = 0.6f;
+ public static final float FLING_SPEED_UP_FACTOR = 0.6f;
+ public static final float FLING_CLOSING_MAX_LENGTH_SECONDS = 0.6f;
+ public static final float FLING_CLOSING_SPEED_UP_FACTOR = 0.6f;
private static final int NO_FIXED_DURATION = -1;
private static final long SHADE_OPEN_SPRING_OUT_DURATION = 350L;
private static final long SHADE_OPEN_SPRING_BACK_DURATION = 400L;
@@ -269,13 +273,13 @@ public abstract class PanelViewController {
mNotificationShadeWindowController = notificationShadeWindowController;
mFlingAnimationUtils = flingAnimationUtilsBuilder
.reset()
- .setMaxLengthSeconds(0.6f)
- .setSpeedUpFactor(0.6f)
+ .setMaxLengthSeconds(FLING_MAX_LENGTH_SECONDS)
+ .setSpeedUpFactor(FLING_SPEED_UP_FACTOR)
.build();
mFlingAnimationUtilsClosing = flingAnimationUtilsBuilder
.reset()
- .setMaxLengthSeconds(0.5f)
- .setSpeedUpFactor(0.6f)
+ .setMaxLengthSeconds(FLING_CLOSING_MAX_LENGTH_SECONDS)
+ .setSpeedUpFactor(FLING_CLOSING_SPEED_UP_FACTOR)
.build();
mFlingAnimationUtilsDismissing = flingAnimationUtilsBuilder
.reset()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
index d2e1650056ac..ef5f21658d83 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimState.java
@@ -62,7 +62,7 @@ public enum ScrimState {
public void prepare(ScrimState previousState) {
mBlankScreen = false;
if (previousState == ScrimState.AOD) {
- mAnimationDuration = StackStateAnimator.ANIMATION_DURATION_WAKEUP;
+ mAnimationDuration = StackStateAnimator.ANIMATION_DURATION_WAKEUP_SCRIM;
if (mDisplayRequiresBlanking) {
// DisplayPowerManager will blank the screen, we'll just
// set our scrim to black in this frame to avoid flickering and
@@ -70,7 +70,7 @@ public enum ScrimState {
mBlankScreen = true;
}
} else if (previousState == ScrimState.KEYGUARD) {
- mAnimationDuration = StackStateAnimator.ANIMATION_DURATION_WAKEUP;
+ mAnimationDuration = StackStateAnimator.ANIMATION_DURATION_WAKEUP_SCRIM;
} else {
mAnimationDuration = ScrimController.ANIMATION_DURATION;
}
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 c09c3ca9dede..2f3300a53ad6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -150,6 +150,7 @@ import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.demomode.DemoMode;
import com.android.systemui.demomode.DemoModeController;
+import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.emergency.EmergencyGesture;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
@@ -338,6 +339,7 @@ public class StatusBar extends CoreStartable implements
}
private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
+ private final DreamOverlayStateController mDreamOverlayStateController;
private StatusBarCommandQueueCallbacks mCommandQueueCallbacks;
void onStatusBarWindowStateChanged(@WindowVisibleState int state) {
@@ -781,7 +783,8 @@ public class StatusBar extends CoreStartable implements
ActivityLaunchAnimator activityLaunchAnimator,
NotifPipelineFlags notifPipelineFlags,
InteractionJankMonitor jankMonitor,
- DeviceStateManager deviceStateManager) {
+ DeviceStateManager deviceStateManager,
+ DreamOverlayStateController dreamOverlayStateController) {
super(context);
mNotificationsController = notificationsController;
mFragmentService = fragmentService;
@@ -869,6 +872,7 @@ public class StatusBar extends CoreStartable implements
mMessageRouter = messageRouter;
mWallpaperManager = wallpaperManager;
mJankMonitor = jankMonitor;
+ mDreamOverlayStateController = dreamOverlayStateController;
mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
mStartingSurfaceOptional = startingSurfaceOptional;
@@ -2983,6 +2987,7 @@ public class StatusBar extends CoreStartable implements
}
public void showKeyguardImpl() {
+ Trace.beginSection("StatusBar#showKeyguard");
mIsKeyguard = true;
// In case we're locking while a smartspace transition is in progress, reset it.
mKeyguardUnlockAnimationController.resetSmartspaceTransition();
@@ -2997,6 +3002,7 @@ public class StatusBar extends CoreStartable implements
mStatusBarStateController.setState(StatusBarState.KEYGUARD);
}
updatePanelExpansionForKeyguard();
+ Trace.endSection();
}
private void updatePanelExpansionForKeyguard() {
@@ -4144,6 +4150,10 @@ public class StatusBar extends CoreStartable implements
return isBouncerShowing() && mStatusBarKeyguardViewManager.bouncerNeedsScrimming();
}
+ public boolean isBouncerShowingOverDream() {
+ return isBouncerShowing() && mDreamOverlayStateController.isOverlayActive();
+ }
+
/**
* When {@link KeyguardBouncer} starts to be dismissed, playing its animation.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 316e68227e0c..b833c894c43f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -29,6 +29,7 @@ import android.content.res.ColorStateList;
import android.hardware.biometrics.BiometricSourceType;
import android.os.Bundle;
import android.os.SystemClock;
+import android.os.Trace;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
@@ -51,6 +52,7 @@ import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.DejankUtils;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dock.DockManager;
+import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.navigationbar.NavigationBarView;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -111,6 +113,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
private final NotificationShadeWindowController mNotificationShadeWindowController;
private final KeyguardBouncer.Factory mKeyguardBouncerFactory;
private final KeyguardMessageAreaController.Factory mKeyguardMessageAreaFactory;
+ private final DreamOverlayStateController mDreamOverlayStateController;
private KeyguardMessageAreaController mKeyguardMessageAreaController;
private final Lazy<ShadeController> mShadeController;
private final BouncerExpansionCallback mExpansionCallback = new BouncerExpansionCallback() {
@@ -235,6 +238,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
SysuiStatusBarStateController sysuiStatusBarStateController,
ConfigurationController configurationController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
+ DreamOverlayStateController dreamOverlayStateController,
NavigationModeController navigationModeController,
DockManager dockManager,
NotificationShadeWindowController notificationShadeWindowController,
@@ -249,6 +253,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
mConfigurationController = configurationController;
mNavigationModeController = navigationModeController;
mNotificationShadeWindowController = notificationShadeWindowController;
+ mDreamOverlayStateController = dreamOverlayStateController;
mKeyguardStateController = keyguardStateController;
mMediaManager = notificationMediaManager;
mKeyguardUpdateManager = keyguardUpdateMonitor;
@@ -370,6 +375,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
*/
@Override
public void show(Bundle options) {
+ Trace.beginSection("StatusBarKeyguardViewManager#show");
mShowing = true;
mNotificationShadeWindowController.setKeyguardShowing(true);
mKeyguardStateController.notifyKeyguardState(mShowing,
@@ -377,6 +383,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
reset(true /* hideBouncerWhenShowing */);
SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_STATE_CHANGED,
SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__SHOWN);
+ Trace.endSection();
}
/**
@@ -711,6 +718,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
@Override
public void hide(long startTime, long fadeoutDuration) {
+ Trace.beginSection("StatusBarKeyguardViewManager#hide");
mShowing = false;
mKeyguardStateController.notifyKeyguardState(mShowing,
mKeyguardStateController.isOccluded());
@@ -810,6 +818,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
}
SysUiStatsLog.write(SysUiStatsLog.KEYGUARD_STATE_CHANGED,
SysUiStatsLog.KEYGUARD_STATE_CHANGED__STATE__HIDDEN);
+ Trace.endSection();
}
private boolean needsBypassFading() {
@@ -1174,7 +1183,9 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
}
public boolean bouncerNeedsScrimming() {
- return mOccluded || mBouncer.willDismissWithAction()
+ // When a dream overlay is active, scrimming will cause any expansion to immediately expand.
+ return (mOccluded && !mDreamOverlayStateController.isOverlayActive())
+ || mBouncer.willDismissWithAction()
|| mStatusBar.isFullScreenUserSwitcherState()
|| (mBouncer.isShowing() && mBouncer.isScrimmed())
|| mBouncer.isFullscreenBouncer();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
index e3b4caabb134..d6fc0a426590 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
@@ -23,6 +23,8 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Configuration;
+import android.graphics.Insets;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -87,11 +89,8 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh
this(context, theme, dismissOnDeviceLock, null);
}
- /**
- * @param udfpsDialogManager If set, UDFPS will hide if this dialog is showing.
- */
public SystemUIDialog(Context context, int theme, boolean dismissOnDeviceLock,
- SystemUIDialogManager dialogManager) {
+ @Nullable SystemUIDialogManager dialogManager) {
super(context, theme);
mContext = context;
@@ -148,7 +147,7 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh
* the device configuration changes, and the result will be used to resize this dialog window.
*/
protected int getWidth() {
- return getDefaultDialogWidth(mContext);
+ return getDefaultDialogWidth(this);
}
/**
@@ -279,36 +278,53 @@ public class SystemUIDialog extends AlertDialog implements ViewRootImpl.ConfigCh
// We need to create the dialog first, otherwise the size will be overridden when it is
// created.
dialog.create();
- dialog.getWindow().setLayout(getDefaultDialogWidth(dialog.getContext()),
- getDefaultDialogHeight());
+ dialog.getWindow().setLayout(getDefaultDialogWidth(dialog), getDefaultDialogHeight());
}
- private static int getDefaultDialogWidth(Context context) {
- boolean isOnTablet = context.getResources().getConfiguration().smallestScreenWidthDp >= 600;
- if (!isOnTablet) {
- return ViewGroup.LayoutParams.MATCH_PARENT;
- }
-
+ private static int getDefaultDialogWidth(Dialog dialog) {
+ Context context = dialog.getContext();
int flagValue = SystemProperties.getInt(FLAG_TABLET_DIALOG_WIDTH, 0);
if (flagValue == -1) {
// The width of bottom sheets (624dp).
- return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 624,
- context.getResources().getDisplayMetrics()));
+ return calculateDialogWidthWithInsets(dialog, 624);
} else if (flagValue == -2) {
// The suggested small width for all dialogs (348dp)
- return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 348,
- context.getResources().getDisplayMetrics()));
+ return calculateDialogWidthWithInsets(dialog, 348);
} else if (flagValue > 0) {
// Any given width.
- return Math.round(
- TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, flagValue,
- context.getResources().getDisplayMetrics()));
+ return calculateDialogWidthWithInsets(dialog, flagValue);
} else {
- // By default we use the same width as the notification shade in portrait mode (504dp).
- return context.getResources().getDimensionPixelSize(R.dimen.large_dialog_width);
+ // By default we use the same width as the notification shade in portrait mode.
+ int width = context.getResources().getDimensionPixelSize(R.dimen.large_dialog_width);
+ if (width > 0) {
+ // If we are neither WRAP_CONTENT or MATCH_PARENT, add the background insets so that
+ // the dialog is the desired width.
+ width += getHorizontalInsets(dialog);
+ }
+ return width;
}
}
+ /**
+ * Return the pixel width {@param dialog} should be so that it is {@param widthInDp} wide,
+ * taking its background insets into consideration.
+ */
+ private static int calculateDialogWidthWithInsets(Dialog dialog, int widthInDp) {
+ float widthInPixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, widthInDp,
+ dialog.getContext().getResources().getDisplayMetrics());
+ return Math.round(widthInPixels + getHorizontalInsets(dialog));
+ }
+
+ private static int getHorizontalInsets(Dialog dialog) {
+ if (dialog.getWindow().getDecorView() == null) {
+ return 0;
+ }
+
+ Drawable background = dialog.getWindow().getDecorView().getBackground();
+ Insets insets = background != null ? background.getOpticalInsets() : Insets.NONE;
+ return insets.left + insets.right;
+ }
+
private static int getDefaultDialogHeight() {
return ViewGroup.LayoutParams.WRAP_CONTENT;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index f5364b9363b9..d3ff4a78c893 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -40,6 +40,7 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dagger.qualifiers.UiBackground;
import com.android.systemui.demomode.DemoModeController;
+import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.fragments.FragmentService;
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
@@ -231,7 +232,8 @@ public interface StatusBarPhoneModule {
ActivityLaunchAnimator activityLaunchAnimator,
NotifPipelineFlags notifPipelineFlags,
InteractionJankMonitor jankMonitor,
- DeviceStateManager deviceStateManager) {
+ DeviceStateManager deviceStateManager,
+ DreamOverlayStateController dreamOverlayStateController) {
return new StatusBar(
context,
notificationsController,
@@ -327,7 +329,8 @@ public interface StatusBarPhoneModule {
activityLaunchAnimator,
notifPipelineFlags,
jankMonitor,
- deviceStateManager
+ deviceStateManager,
+ dreamOverlayStateController
);
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index 5d39eef999d7..c37e966f3540 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -27,10 +27,12 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -46,6 +48,7 @@ import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.ComponentInfoInternal;
+import android.hardware.biometrics.IBiometricContextListener;
import android.hardware.biometrics.IBiometricSysuiReceiver;
import android.hardware.biometrics.PromptInfo;
import android.hardware.biometrics.SensorProperties;
@@ -70,6 +73,7 @@ import androidx.test.filters.SmallTest;
import com.android.internal.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.util.concurrency.Execution;
import com.android.systemui.util.concurrency.FakeExecution;
@@ -80,6 +84,7 @@ import org.junit.runner.RunWith;
import org.mockito.AdditionalMatchers;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
+import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -99,6 +104,8 @@ public class AuthControllerTest extends SysuiTestCase {
@Mock
private IBiometricSysuiReceiver mReceiver;
@Mock
+ private IBiometricContextListener mContextListener;
+ @Mock
private AuthDialog mDialog1;
@Mock
private AuthDialog mDialog2;
@@ -120,10 +127,14 @@ public class AuthControllerTest extends SysuiTestCase {
private DisplayManager mDisplayManager;
@Mock
private WakefulnessLifecycle mWakefulnessLifecycle;
+ @Mock
+ private StatusBarStateController mStatusBarStateController;
@Captor
ArgumentCaptor<IFingerprintAuthenticatorsRegisteredCallback> mAuthenticatorsRegisteredCaptor;
@Captor
ArgumentCaptor<FingerprintStateListener> mFingerprintStateCaptor;
+ @Captor
+ ArgumentCaptor<StatusBarStateController.StateListener> mStatusBarStateListenerCaptor;
private TestableContext mContextSpy;
private Execution mExecution;
@@ -175,12 +186,15 @@ public class AuthControllerTest extends SysuiTestCase {
mAuthController = new TestableAuthController(mContextSpy, mExecution, mCommandQueue,
mActivityTaskManager, mWindowManager, mFingerprintManager, mFaceManager,
- () -> mUdfpsController, () -> mSidefpsController);
+ () -> mUdfpsController, () -> mSidefpsController, mStatusBarStateController);
mAuthController.start();
verify(mFingerprintManager).addAuthenticatorsRegisteredCallback(
mAuthenticatorsRegisteredCaptor.capture());
+ when(mStatusBarStateController.isDozing()).thenReturn(false);
+ verify(mStatusBarStateController).addCallback(mStatusBarStateListenerCaptor.capture());
+
mAuthenticatorsRegisteredCaptor.getValue().onAllAuthenticatorsRegistered(props);
// Ensures that the operations posted on the handler get executed.
@@ -198,7 +212,8 @@ public class AuthControllerTest extends SysuiTestCase {
// This test requires an uninitialized AuthController.
AuthController authController = new TestableAuthController(mContextSpy, mExecution,
mCommandQueue, mActivityTaskManager, mWindowManager, mFingerprintManager,
- mFaceManager, () -> mUdfpsController, () -> mSidefpsController);
+ mFaceManager, () -> mUdfpsController, () -> mSidefpsController,
+ mStatusBarStateController);
authController.start();
verify(mFingerprintManager).addAuthenticatorsRegisteredCallback(
@@ -221,7 +236,8 @@ public class AuthControllerTest extends SysuiTestCase {
// This test requires an uninitialized AuthController.
AuthController authController = new TestableAuthController(mContextSpy, mExecution,
mCommandQueue, mActivityTaskManager, mWindowManager, mFingerprintManager,
- mFaceManager, () -> mUdfpsController, () -> mSidefpsController);
+ mFaceManager, () -> mUdfpsController, () -> mSidefpsController,
+ mStatusBarStateController);
authController.start();
verify(mFingerprintManager).addAuthenticatorsRegisteredCallback(
@@ -656,6 +672,19 @@ public class AuthControllerTest extends SysuiTestCase {
verify(callback).onBiometricPromptDismissed();
}
+ @Test
+ public void testForwardsDozeEvent() throws RemoteException {
+ mAuthController.setBiometicContextListener(mContextListener);
+
+ mStatusBarStateListenerCaptor.getValue().onDozingChanged(false);
+ mStatusBarStateListenerCaptor.getValue().onDozingChanged(true);
+
+ InOrder order = inOrder(mContextListener);
+ // invoked twice since the initial state is false
+ order.verify(mContextListener, times(2)).onDozeChanged(eq(false));
+ order.verify(mContextListener).onDozeChanged(eq(true));
+ }
+
// Helpers
private void showDialog(int[] sensorIds, boolean credentialAllowed) {
@@ -705,10 +734,12 @@ public class AuthControllerTest extends SysuiTestCase {
FingerprintManager fingerprintManager,
FaceManager faceManager,
Provider<UdfpsController> udfpsControllerFactory,
- Provider<SidefpsController> sidefpsControllerFactory) {
+ Provider<SidefpsController> sidefpsControllerFactory,
+ StatusBarStateController statusBarStateController) {
super(context, execution, commandQueue, activityTaskManager, windowManager,
fingerprintManager, faceManager, udfpsControllerFactory,
- sidefpsControllerFactory, mDisplayManager, mWakefulnessLifecycle, mHandler);
+ sidefpsControllerFactory, mDisplayManager, mWakefulnessLifecycle,
+ statusBarStateController, mHandler);
}
@Override
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
index b3b5fa509105..d5bd67adcf09 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayServiceTest.java
@@ -91,6 +91,9 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
@Mock
DreamOverlayTouchMonitor mDreamOverlayTouchMonitor;
+ @Mock
+ DreamOverlayStateController mStateController;
+
DreamOverlayService mService;
@@ -115,6 +118,7 @@ public class DreamOverlayServiceTest extends SysuiTestCase {
mService = new DreamOverlayService(mContext, mMainExecutor,
mDreamOverlayComponentFactory,
+ mStateController,
mKeyguardUpdateMonitor);
final IBinder proxy = mService.onBind(new Intent());
final IDreamOverlay overlay = IDreamOverlay.Stub.asInterface(proxy);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java
index 7d0833db7ae4..627da3c5ec77 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/DreamOverlayStateControllerTest.java
@@ -16,11 +16,15 @@
package com.android.systemui.dreams;
+import static com.google.common.truth.Truth.assertThat;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.testing.AndroidTestingRunner;
@@ -35,6 +39,7 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.util.Collection;
@@ -56,7 +61,29 @@ public class DreamOverlayStateControllerTest extends SysuiTestCase {
}
@Test
- public void testCallback() throws Exception {
+ public void testStateChange() {
+ final DreamOverlayStateController stateController = new DreamOverlayStateController(
+ mExecutor);
+ stateController.addCallback(mCallback);
+ stateController.setOverlayActive(true);
+ mExecutor.runAllReady();
+
+ verify(mCallback).onStateChanged();
+ assertThat(stateController.isOverlayActive()).isTrue();
+
+ Mockito.clearInvocations(mCallback);
+ stateController.setOverlayActive(true);
+ mExecutor.runAllReady();
+ verify(mCallback, never()).onStateChanged();
+
+ stateController.setOverlayActive(false);
+ mExecutor.runAllReady();
+ verify(mCallback).onStateChanged();
+ assertThat(stateController.isOverlayActive()).isFalse();
+ }
+
+ @Test
+ public void testCallback() {
final DreamOverlayStateController stateController = new DreamOverlayStateController(
mExecutor);
stateController.addCallback(mCallback);
@@ -94,4 +121,43 @@ public class DreamOverlayStateControllerTest extends SysuiTestCase {
mExecutor.runAllReady();
verify(mCallback, times(1)).onComplicationsChanged();
}
+
+ @Test
+ public void testComplicationFiltering() {
+ final DreamOverlayStateController stateController =
+ new DreamOverlayStateController(mExecutor);
+
+ final Complication alwaysAvailableComplication = Mockito.mock(Complication.class);
+ final Complication weatherComplication = Mockito.mock(Complication.class);
+ when(alwaysAvailableComplication.getRequiredTypeAvailability())
+ .thenReturn(Complication.COMPLICATION_TYPE_NONE);
+ when(weatherComplication.getRequiredTypeAvailability())
+ .thenReturn(Complication.COMPLICATION_TYPE_WEATHER);
+
+ stateController.addComplication(alwaysAvailableComplication);
+ stateController.addComplication(weatherComplication);
+
+ final DreamOverlayStateController.Callback callback =
+ Mockito.mock(DreamOverlayStateController.Callback.class);
+
+ stateController.addCallback(callback);
+ mExecutor.runAllReady();
+
+ {
+ final Collection<Complication> complications = stateController.getComplications();
+ assertThat(complications.contains(alwaysAvailableComplication)).isTrue();
+ assertThat(complications.contains(weatherComplication)).isFalse();
+ }
+
+ stateController.setAvailableComplicationTypes(Complication.COMPLICATION_TYPE_WEATHER);
+ mExecutor.runAllReady();
+ verify(callback).onAvailableComplicationTypesChanged();
+
+ {
+ final Collection<Complication> complications = stateController.getComplications();
+ assertThat(complications.contains(alwaysAvailableComplication)).isTrue();
+ assertThat(complications.contains(weatherComplication)).isTrue();
+ }
+
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/SmartSpaceComplicationTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/SmartSpaceComplicationTest.java
new file mode 100644
index 000000000000..3b17a8071cb2
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/SmartSpaceComplicationTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.dreams;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.lockscreen.LockscreenSmartspaceController;
+
+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)
+public class SmartSpaceComplicationTest extends SysuiTestCase {
+ @Mock
+ private Context mContext;
+
+ @Mock
+ private LockscreenSmartspaceController mSmartspaceController;
+
+ @Mock
+ private DreamOverlayStateController mDreamOverlayStateController;
+
+ @Mock
+ private SmartSpaceComplication mComplication;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ /**
+ * Ensures {@link SmartSpaceComplication} is only registered when it is available.
+ */
+ @Test
+ public void testAvailability() {
+ when(mSmartspaceController.isEnabled()).thenReturn(false);
+
+ final SmartSpaceComplication.Registrant registrant = new SmartSpaceComplication.Registrant(
+ mContext,
+ mDreamOverlayStateController,
+ mComplication,
+ mSmartspaceController);
+ registrant.start();
+ verify(mDreamOverlayStateController, never()).addComplication(any());
+
+ when(mSmartspaceController.isEnabled()).thenReturn(true);
+ registrant.start();
+ verify(mDreamOverlayStateController).addComplication(eq(mComplication));
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationCollectionLiveDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationCollectionLiveDataTest.java
index feeea5dff7ea..5fcf414f0251 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationCollectionLiveDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationCollectionLiveDataTest.java
@@ -75,6 +75,10 @@ public class ComplicationCollectionLiveDataTest extends SysuiTestCase {
callbackCaptor.getValue().onComplicationsChanged();
verifyUpdate(observer, complications);
+
+ callbackCaptor.getValue().onAvailableComplicationTypesChanged();
+
+ verifyUpdate(observer, complications);
});
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationLayoutEngineTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationLayoutEngineTest.java
index f227a9b78c39..d5ab708f893b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationLayoutEngineTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationLayoutEngineTest.java
@@ -27,6 +27,7 @@ import android.view.View;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.test.filters.SmallTest;
+import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import org.junit.Before;
@@ -122,6 +123,34 @@ public class ComplicationLayoutEngineTest extends SysuiTestCase {
}
/**
+ * Makes sure the engine properly places a view within the {@link ConstraintLayout}.
+ */
+ @Test
+ public void testSnapToGuide() {
+ final ViewInfo firstViewInfo = new ViewInfo(
+ new ComplicationLayoutParams(
+ 100,
+ 100,
+ ComplicationLayoutParams.POSITION_TOP
+ | ComplicationLayoutParams.POSITION_END,
+ ComplicationLayoutParams.DIRECTION_DOWN,
+ 0,
+ true),
+ Complication.CATEGORY_STANDARD,
+ mLayout);
+
+ final ComplicationLayoutEngine engine = new ComplicationLayoutEngine(mLayout);
+ addComplication(engine, firstViewInfo);
+
+ // Ensure the view is added to the top end corner
+ verifyChange(firstViewInfo, true, lp -> {
+ assertThat(lp.topToTop == ConstraintLayout.LayoutParams.PARENT_ID).isTrue();
+ assertThat(lp.endToEnd == ConstraintLayout.LayoutParams.PARENT_ID).isTrue();
+ assertThat(lp.startToEnd == R.id.complication_end_guide).isTrue();
+ });
+ }
+
+ /**
* Ensures layout in a particular direction updates.
*/
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationUtilsTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationUtilsTest.java
new file mode 100644
index 000000000000..f1978b214594
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/complication/ComplicationUtilsTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dreams.complication;
+
+import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_AIR_QUALITY;
+import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_CAST_INFO;
+import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_DATE;
+import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_TIME;
+import static com.android.systemui.dreams.complication.Complication.COMPLICATION_TYPE_WEATHER;
+import static com.android.systemui.dreams.complication.ComplicationUtils.convertComplicationType;
+
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.settingslib.dream.DreamBackend;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class ComplicationUtilsTest extends SysuiTestCase {
+ @Test
+ public void testConvertComplicationType() {
+ assertThat(convertComplicationType(DreamBackend.COMPLICATION_TYPE_TIME))
+ .isEqualTo(COMPLICATION_TYPE_TIME);
+ assertThat(convertComplicationType(DreamBackend.COMPLICATION_TYPE_DATE))
+ .isEqualTo(COMPLICATION_TYPE_DATE);
+ assertThat(convertComplicationType(DreamBackend.COMPLICATION_TYPE_WEATHER))
+ .isEqualTo(COMPLICATION_TYPE_WEATHER);
+ assertThat(convertComplicationType(DreamBackend.COMPLICATION_TYPE_AIR_QUALITY))
+ .isEqualTo(COMPLICATION_TYPE_AIR_QUALITY);
+ assertThat(convertComplicationType(DreamBackend.COMPLICATION_TYPE_CAST_INFO))
+ .isEqualTo(COMPLICATION_TYPE_CAST_INFO);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
new file mode 100644
index 000000000000..1a8326fd5bd1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.dreams.touch;
+
+import static com.google.common.truth.Truth.assertThat;
+
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.animation.ValueAnimator;
+import android.testing.AndroidTestingRunner;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.shared.system.InputChannelCompat;
+import com.android.systemui.statusbar.NotificationShadeWindowController;
+import com.android.systemui.statusbar.phone.KeyguardBouncer;
+import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.wm.shell.animation.FlingAnimationUtils;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Random;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class BouncerSwipeTouchHandlerTest extends SysuiTestCase {
+ @Mock
+ StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+
+ @Mock
+ StatusBar mStatusBar;
+
+ @Mock
+ NotificationShadeWindowController mNotificationShadeWindowController;
+
+ @Mock
+ FlingAnimationUtils mFlingAnimationUtils;
+
+
+ @Mock
+ FlingAnimationUtils mFlingAnimationUtilsClosing;
+
+ @Mock
+ DreamTouchHandler.TouchSession mTouchSession;
+
+ BouncerSwipeTouchHandler mTouchHandler;
+
+ @Mock
+ BouncerSwipeTouchHandler.ValueAnimatorCreator mValueAnimatorCreator;
+
+ @Mock
+ ValueAnimator mValueAnimator;
+
+ @Mock
+ BouncerSwipeTouchHandler.VelocityTrackerFactory mVelocityTrackerFactory;
+
+ @Mock
+ VelocityTracker mVelocityTracker;
+
+ private static final float TOUCH_REGION = .3f;
+ private static final float SCREEN_HEIGHT_PX = 100;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mTouchHandler = new BouncerSwipeTouchHandler(
+ mStatusBarKeyguardViewManager,
+ mStatusBar,
+ mNotificationShadeWindowController,
+ mValueAnimatorCreator,
+ mVelocityTrackerFactory,
+ mFlingAnimationUtils,
+ mFlingAnimationUtilsClosing,
+ TOUCH_REGION);
+ when(mStatusBar.getDisplayHeight()).thenReturn(SCREEN_HEIGHT_PX);
+ when(mValueAnimatorCreator.create(anyFloat(), anyFloat())).thenReturn(mValueAnimator);
+ when(mVelocityTrackerFactory.obtain()).thenReturn(mVelocityTracker);
+ }
+
+ private static void beginValidSwipe(GestureDetector.OnGestureListener listener) {
+ listener.onDown(MotionEvent.obtain(0, 0,
+ MotionEvent.ACTION_DOWN, 0,
+ SCREEN_HEIGHT_PX - (.5f * TOUCH_REGION * SCREEN_HEIGHT_PX), 0));
+ }
+
+ /**
+ * Ensures expansion only happens when touch down happens in valid part of the screen.
+ */
+ @Test
+ public void testSessionStart() {
+ mTouchHandler.onSessionStart(mTouchSession);
+ verify(mNotificationShadeWindowController).setForcePluginOpen(eq(true), any());
+ ArgumentCaptor<InputChannelCompat.InputEventListener> eventListenerCaptor =
+ ArgumentCaptor.forClass(InputChannelCompat.InputEventListener.class);
+ ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
+ ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
+ verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
+ verify(mTouchSession).registerInputListener(eventListenerCaptor.capture());
+
+ final Random random = new Random(System.currentTimeMillis());
+
+ // If an initial touch down meeting criteria has been met, scroll behavior should be
+ // ignored.
+ assertThat(gestureListenerCaptor.getValue()
+ .onScroll(Mockito.mock(MotionEvent.class),
+ Mockito.mock(MotionEvent.class),
+ random.nextFloat(),
+ random.nextFloat())).isFalse();
+
+ // A touch at the top of the screen should also not trigger listening.
+ final MotionEvent touchDownEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_DOWN,
+ 0, 0, 0);
+
+ gestureListenerCaptor.getValue().onDown(touchDownEvent);
+ assertThat(gestureListenerCaptor.getValue()
+ .onScroll(Mockito.mock(MotionEvent.class),
+ Mockito.mock(MotionEvent.class),
+ random.nextFloat(),
+ random.nextFloat())).isFalse();
+
+ // A touch within range at the bottom of the screen should trigger listening
+ beginValidSwipe(gestureListenerCaptor.getValue());
+ assertThat(gestureListenerCaptor.getValue()
+ .onScroll(Mockito.mock(MotionEvent.class),
+ Mockito.mock(MotionEvent.class),
+ random.nextFloat(),
+ random.nextFloat())).isTrue();
+ }
+
+ /**
+ * Makes sure expansion amount is proportional to scroll.
+ */
+ @Test
+ public void testExpansionAmount() {
+ mTouchHandler.onSessionStart(mTouchSession);
+ ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
+ ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
+ verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
+
+ beginValidSwipe(gestureListenerCaptor.getValue());
+
+ final float scrollAmount = .3f;
+ final float distanceY = SCREEN_HEIGHT_PX * scrollAmount;
+
+ final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
+ 0, SCREEN_HEIGHT_PX, 0);
+ final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
+ 0, SCREEN_HEIGHT_PX - distanceY, 0);
+
+ assertThat(gestureListenerCaptor.getValue().onScroll(event1, event2, 0 , distanceY))
+ .isTrue();
+
+ // Ensure only called once
+ verify(mStatusBarKeyguardViewManager)
+ .onPanelExpansionChanged(anyFloat(), anyBoolean(), anyBoolean());
+
+ // Ensure correct expansion passed in.
+ verify(mStatusBarKeyguardViewManager)
+ .onPanelExpansionChanged(eq(1 - scrollAmount), eq(false), eq(true));
+ }
+
+ private void swipeToPosition(float position, float velocityY) {
+ mTouchHandler.onSessionStart(mTouchSession);
+ ArgumentCaptor<GestureDetector.OnGestureListener> gestureListenerCaptor =
+ ArgumentCaptor.forClass(GestureDetector.OnGestureListener.class);
+ ArgumentCaptor<InputChannelCompat.InputEventListener> inputEventListenerCaptor =
+ ArgumentCaptor.forClass(InputChannelCompat.InputEventListener.class);
+ verify(mTouchSession).registerGestureListener(gestureListenerCaptor.capture());
+ verify(mTouchSession).registerInputListener(inputEventListenerCaptor.capture());
+
+ when(mVelocityTracker.getYVelocity()).thenReturn(velocityY);
+
+ beginValidSwipe(gestureListenerCaptor.getValue());
+
+ final float distanceY = SCREEN_HEIGHT_PX * position;
+
+ final MotionEvent event1 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
+ 0, SCREEN_HEIGHT_PX, 0);
+ final MotionEvent event2 = MotionEvent.obtain(0, 0, MotionEvent.ACTION_MOVE,
+ 0, SCREEN_HEIGHT_PX - distanceY, 0);
+
+ assertThat(gestureListenerCaptor.getValue().onScroll(event1, event2, 0 , distanceY))
+ .isTrue();
+
+ final MotionEvent upEvent = MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP,
+ 0, 0, 0);
+
+ inputEventListenerCaptor.getValue().onInputEvent(upEvent);
+ }
+
+ /**
+ * Tests that ending a swipe before the set expansion threshold leads to bouncer collapsing
+ * down.
+ */
+ @Test
+ public void testCollapseOnThreshold() {
+ final float swipeUpPercentage = .3f;
+ swipeToPosition(swipeUpPercentage, -1);
+
+ verify(mValueAnimatorCreator).create(eq(1 - swipeUpPercentage),
+ eq(KeyguardBouncer.EXPANSION_VISIBLE));
+ verify(mFlingAnimationUtilsClosing).apply(eq(mValueAnimator), anyFloat(), anyFloat(),
+ anyFloat(), anyFloat());
+ verify(mValueAnimator).start();
+ }
+
+ /**
+ * Tests that ending a swipe above the set expansion threshold will continue the expansion.
+ */
+ @Test
+ public void testExpandOnThreshold() {
+ final float swipeUpPercentage = .7f;
+ swipeToPosition(swipeUpPercentage, 1);
+
+ verify(mValueAnimatorCreator).create(eq(1 - swipeUpPercentage),
+ eq(KeyguardBouncer.EXPANSION_HIDDEN));
+ verify(mFlingAnimationUtils).apply(eq(mValueAnimator), anyFloat(), anyFloat(),
+ anyFloat(), anyFloat());
+ verify(mValueAnimator).start();
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index da8ab27d7e3d..d94e2eee9ffa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -48,6 +48,7 @@ import com.android.keyguard.mediator.ScreenOnCoordinator;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.classifier.FalsingCollectorFake;
+import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.statusbar.NotificationShadeDepthController;
@@ -98,6 +99,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
private @Mock InteractionJankMonitor mInteractionJankMonitor;
private @Mock ScreenOnCoordinator mScreenOnCoordinator;
private @Mock Lazy<NotificationShadeWindowController> mNotificationShadeWindowControllerLazy;
+ private @Mock DreamOverlayStateController mDreamOverlayStateController;
private DeviceConfigProxy mDeviceConfig = new DeviceConfigProxyFake();
private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
@@ -202,6 +204,7 @@ public class KeyguardViewMediatorTest extends SysuiTestCase {
() -> mNotificationShadeDepthController,
mScreenOnCoordinator,
mInteractionJankMonitor,
+ mDreamOverlayStateController,
mNotificationShadeWindowControllerLazy);
mViewMediator.start();
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt
index a3ffb2fe4b8d..97b3b10ebcbf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaHierarchyManagerTest.kt
@@ -25,6 +25,7 @@ import androidx.test.filters.SmallTest
import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.controls.controller.ControlsControllerImplTest.Companion.eq
+import com.android.systemui.dreams.DreamOverlayStateController
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.NotificationLockscreenUserManager
@@ -85,6 +86,8 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
private lateinit var configurationController: ConfigurationController
@Mock
private lateinit var uniqueObjectHostView: UniqueObjectHostView
+ @Mock
+ private lateinit var dreamOverlayStateController: DreamOverlayStateController
@Captor
private lateinit var wakefullnessObserver: ArgumentCaptor<(WakefulnessLifecycle.Observer)>
@Captor
@@ -110,7 +113,8 @@ class MediaHierarchyManagerTest : SysuiTestCase() {
notificationLockscreenUserManager,
configurationController,
wakefulnessLifecycle,
- statusBarKeyguardViewManager)
+ statusBarKeyguardViewManager,
+ dreamOverlayStateController)
verify(wakefulnessLifecycle).addObserver(wakefullnessObserver.capture())
verify(statusBarStateController).addCallback(statusBarCallback.capture())
setupHost(lockHost, MediaHierarchyManager.LOCATION_LOCKSCREEN)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaComplicationViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaComplicationViewControllerTest.java
new file mode 100644
index 000000000000..29188da46562
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaComplicationViewControllerTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.dream;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+
+import android.testing.AndroidTestingRunner;
+import android.widget.FrameLayout;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.media.MediaHost;
+import com.android.systemui.util.animation.UniqueObjectHostView;
+
+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)
+public class MediaComplicationViewControllerTest extends SysuiTestCase {
+ @Mock
+ private MediaHost mMediaHost;
+
+ @Mock
+ private UniqueObjectHostView mView;
+
+ @Mock
+ private FrameLayout mComplicationContainer;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mMediaHost.hostView = mView;
+ }
+
+ @Test
+ public void testMediaHostViewInteraction() {
+ final MediaComplicationViewController controller = new MediaComplicationViewController(
+ mComplicationContainer, mMediaHost);
+
+ controller.init();
+
+ controller.onViewAttached();
+ verify(mComplicationContainer).addView(eq(mView));
+
+ controller.onViewDetached();
+ verify(mComplicationContainer).removeView(eq(mView));
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaDreamSentinelTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaDreamSentinelTest.java
new file mode 100644
index 000000000000..114fc90e8590
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dream/MediaDreamSentinelTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.media.dream;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dreams.DreamOverlayStateController;
+import com.android.systemui.media.MediaData;
+import com.android.systemui.media.MediaDataManager;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class MediaDreamSentinelTest extends SysuiTestCase {
+ @Mock
+ MediaDataManager mMediaDataManager;
+
+ @Mock
+ DreamOverlayStateController mDreamOverlayStateController;
+
+ @Mock
+ MediaDreamComplication mComplication;
+
+ final String mKey = "key";
+ final String mOldKey = "old_key";
+
+ @Mock
+ MediaData mData;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ }
+
+ @Test
+ public void testComplicationAddition() {
+ final MediaDreamSentinel sentinel = new MediaDreamSentinel(mContext, mMediaDataManager,
+ mDreamOverlayStateController, mComplication);
+
+ sentinel.start();
+
+ ArgumentCaptor<MediaDataManager.Listener> listenerCaptor =
+ ArgumentCaptor.forClass(MediaDataManager.Listener.class);
+ verify(mMediaDataManager).addListener(listenerCaptor.capture());
+
+ final MediaDataManager.Listener listener = listenerCaptor.getValue();
+
+ when(mMediaDataManager.hasActiveMedia()).thenReturn(false);
+ listener.onMediaDataLoaded(mKey, mOldKey, mData, true, 0);
+ verify(mDreamOverlayStateController, never()).addComplication(any());
+
+ when(mMediaDataManager.hasActiveMedia()).thenReturn(true);
+ listener.onMediaDataLoaded(mKey, mOldKey, mData, true, 0);
+ verify(mDreamOverlayStateController).addComplication(eq(mComplication));
+
+ listener.onMediaDataRemoved(mKey);
+ verify(mDreamOverlayStateController, never()).removeComplication(any());
+
+ when(mMediaDataManager.hasActiveMedia()).thenReturn(false);
+ listener.onMediaDataRemoved(mKey);
+ verify(mDreamOverlayStateController).removeComplication(eq(mComplication));
+ }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
index 42647f7b026a..d51d370eecb9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -227,7 +227,7 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
fun testDragDownAmountDoesntCallOutInLockedDownShade() {
whenever(nsslController.isInLockedDownShade).thenReturn(true)
transitionController.dragDownAmount = 10f
- verify(nsslController, never()).setTransitionToFullShadeAmount(anyFloat())
+ verify(nsslController, never()).setTransitionToFullShadeAmount(anyFloat(), anyFloat())
verify(mediaHierarchyManager, never()).setTransitionToFullShadeAmount(anyFloat())
verify(scrimController, never()).setTransitionToFullShadeProgress(anyFloat())
verify(notificationPanelController, never()).setTransitionToFullShadeAmount(anyFloat(),
@@ -238,7 +238,7 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
@Test
fun testDragDownAmountCallsOut() {
transitionController.dragDownAmount = 10f
- verify(nsslController).setTransitionToFullShadeAmount(anyFloat())
+ verify(nsslController).setTransitionToFullShadeAmount(anyFloat(), anyFloat())
verify(mediaHierarchyManager).setTransitionToFullShadeAmount(anyFloat())
verify(scrimController).setTransitionToFullShadeProgress(anyFloat())
verify(notificationPanelController).setTransitionToFullShadeAmount(anyFloat(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt
new file mode 100644
index 000000000000..d280f54e32f2
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationShelfTest.kt
@@ -0,0 +1,153 @@
+package com.android.systemui.statusbar.notification.stack
+
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.NotificationShelf
+import junit.framework.Assert.assertFalse
+import junit.framework.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mockito.*
+import org.mockito.Mockito.`when` as whenever
+
+/**
+ * Tests for {@link NotificationShelf}.
+ */
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+class NotificationShelfTest : SysuiTestCase() {
+
+ private val shelf = NotificationShelf(context, /* attrs */ null)
+ private val shelfState = shelf.viewState as NotificationShelf.ShelfState
+ private val ambientState = mock(AmbientState::class.java)
+
+ @Before
+ fun setUp() {
+ shelf.bind(ambientState, /* hostLayoutController */ null)
+ shelf.layout(/* left */ 0, /* top */ 0, /* right */ 30, /* bottom */5)
+ }
+
+ @Test
+ fun testShadeWidth_BasedOnFractionToShade() {
+ setFractionToShade(0f)
+ setOnLockscreen(true)
+
+ shelf.updateStateWidth(shelfState, /* fraction */ 0f, /* shortestWidth */ 10)
+ assertTrue(shelfState.actualWidth == 10)
+
+ shelf.updateStateWidth(shelfState, /* fraction */ 0.5f, /* shortestWidth */ 10)
+ assertTrue(shelfState.actualWidth == 20)
+
+ shelf.updateStateWidth(shelfState, /* fraction */ 1f, /* shortestWidth */ 10)
+ assertTrue(shelfState.actualWidth == 30)
+ }
+
+ @Test
+ fun testShelfIsLong_WhenNotOnLockscreen() {
+ setFractionToShade(0f)
+ setOnLockscreen(false)
+
+ shelf.updateStateWidth(shelfState, /* fraction */ 0f, /* shortestWidth */ 10)
+ assertTrue(shelfState.actualWidth == 30)
+ }
+
+ @Test
+ fun testX_inViewForClick() {
+ val isXInView = shelf.isXInView(
+ /* localX */ 5f,
+ /* slop */ 5f,
+ /* left */ 0f,
+ /* right */ 10f)
+ assertTrue(isXInView)
+ }
+
+ @Test
+ fun testXSlop_inViewForClick() {
+ val isLeftXSlopInView = shelf.isXInView(
+ /* localX */ -3f,
+ /* slop */ 5f,
+ /* left */ 0f,
+ /* right */ 10f)
+ assertTrue(isLeftXSlopInView)
+
+ val isRightXSlopInView = shelf.isXInView(
+ /* localX */ 13f,
+ /* slop */ 5f,
+ /* left */ 0f,
+ /* right */ 10f)
+ assertTrue(isRightXSlopInView)
+ }
+
+ @Test
+ fun testX_notInViewForClick() {
+ val isXLeftOfShelfInView = shelf.isXInView(
+ /* localX */ -10f,
+ /* slop */ 5f,
+ /* left */ 0f,
+ /* right */ 10f)
+ assertFalse(isXLeftOfShelfInView)
+
+ val isXRightOfShelfInView = shelf.isXInView(
+ /* localX */ 20f,
+ /* slop */ 5f,
+ /* left */ 0f,
+ /* right */ 10f)
+ assertFalse(isXRightOfShelfInView)
+ }
+
+ @Test
+ fun testY_inViewForClick() {
+ val isYInView = shelf.isYInView(
+ /* localY */ 5f,
+ /* slop */ 5f,
+ /* top */ 0f,
+ /* bottom */ 10f)
+ assertTrue(isYInView)
+ }
+
+ @Test
+ fun testYSlop_inViewForClick() {
+ val isTopYSlopInView = shelf.isYInView(
+ /* localY */ -3f,
+ /* slop */ 5f,
+ /* top */ 0f,
+ /* bottom */ 10f)
+ assertTrue(isTopYSlopInView)
+
+ val isBottomYSlopInView = shelf.isYInView(
+ /* localY */ 13f,
+ /* slop */ 5f,
+ /* top */ 0f,
+ /* bottom */ 10f)
+ assertTrue(isBottomYSlopInView)
+ }
+
+ @Test
+ fun testY_notInViewForClick() {
+ val isYAboveShelfInView = shelf.isYInView(
+ /* localY */ -10f,
+ /* slop */ 5f,
+ /* top */ 0f,
+ /* bottom */ 5f)
+ assertFalse(isYAboveShelfInView)
+
+ val isYBelowShelfInView = shelf.isYInView(
+ /* localY */ 15f,
+ /* slop */ 5f,
+ /* top */ 0f,
+ /* bottom */ 5f)
+ assertFalse(isYBelowShelfInView)
+ }
+
+ private fun setFractionToShade(fraction: Float) {
+ shelf.setFractionToShade(fraction)
+ }
+
+ private fun setOnLockscreen(isOnLockscreen: Boolean) {
+ whenever(ambientState.isOnKeyguard).thenReturn(isOnLockscreen)
+ }
+} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 5d80bca03e03..bb79941b0e53 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -43,6 +43,7 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dock.DockManager;
+import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.navigationbar.NavigationModeController;
import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import com.android.systemui.statusbar.NotificationMediaManager;
@@ -97,6 +98,8 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
private KeyguardMessageArea mKeyguardMessageArea;
@Mock
private ShadeController mShadeController;
+ @Mock
+ private DreamOverlayStateController mDreamOverlayStateController;
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
@@ -116,6 +119,7 @@ public class StatusBarKeyguardViewManagerTest extends SysuiTestCase {
mStatusBarStateController,
mock(ConfigurationController.class),
mKeyguardUpdateMonitor,
+ mDreamOverlayStateController,
mock(NavigationModeController.class),
mock(DockManager.class),
mock(NotificationShadeWindowController.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index b7c00fe5e3a1..1564dfe8cd06 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -87,6 +87,7 @@ import com.android.systemui.classifier.FalsingCollectorFake;
import com.android.systemui.classifier.FalsingManagerFake;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.demomode.DemoModeController;
+import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.fragments.FragmentService;
@@ -285,6 +286,7 @@ public class StatusBarTest extends SysuiTestCase {
@Mock private NotifLiveDataStore mNotifLiveDataStore;
@Mock private InteractionJankMonitor mJankMonitor;
@Mock private DeviceStateManager mDeviceStateManager;
+ @Mock private DreamOverlayStateController mDreamOverlayStateController;
private ShadeController mShadeController;
private final FakeSystemClock mFakeSystemClock = new FakeSystemClock();
private FakeExecutor mMainExecutor = new FakeExecutor(mFakeSystemClock);
@@ -474,7 +476,8 @@ public class StatusBarTest extends SysuiTestCase {
mActivityLaunchAnimator,
mNotifPipelineFlags,
mJankMonitor,
- mDeviceStateManager);
+ mDeviceStateManager,
+ mDreamOverlayStateController);
when(mKeyguardViewMediator.registerStatusBar(
any(StatusBar.class),
any(NotificationPanelViewController.class),
diff --git a/services/Android.bp b/services/Android.bp
index af70692a88e5..7e009868fa1a 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -95,7 +95,6 @@ filegroup {
":services.selectiontoolbar-sources",
":services.smartspace-sources",
":services.speech-sources",
- ":services.startop.iorap-sources",
":services.systemcaptions-sources",
":services.translation-sources",
":services.texttospeech-sources",
@@ -151,7 +150,6 @@ java_library {
"services.selectiontoolbar",
"services.smartspace",
"services.speech",
- "services.startop",
"services.systemcaptions",
"services.translation",
"services.texttospeech",
@@ -207,7 +205,6 @@ stubs_defaults {
" --hide-annotation android.annotation.Hide" +
" --hide InternalClasses" + // com.android.* classes are okay in this interface
// TODO: remove the --hide options below
- " --hide-package com.google.android.startop.iorap" +
" --hide DeprecationMismatch" +
" --hide HiddenTypedefConstant",
visibility: ["//frameworks/base:__subpackages__"],
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 2168fb18888f..a65d5b3b94f7 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -3346,8 +3346,10 @@ class AppWidgetServiceImpl extends IAppWidgetService.Stub implements WidgetBacku
// Isolate the changes relating to RROs. The app info must be copied to prevent
// affecting other parts of system server that may have cached this app info.
oldAppInfo = new ApplicationInfo(oldAppInfo);
- oldAppInfo.overlayPaths = newAppInfo.overlayPaths.clone();
- oldAppInfo.resourceDirs = newAppInfo.resourceDirs.clone();
+ oldAppInfo.overlayPaths = newAppInfo.overlayPaths == null
+ ? null : newAppInfo.overlayPaths.clone();
+ oldAppInfo.resourceDirs = newAppInfo.resourceDirs == null
+ ? null : newAppInfo.resourceDirs.clone();
provider.info.providerInfo.applicationInfo = oldAppInfo;
for (int j = 0, M = provider.widgets.size(); j < M; j++) {
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 095c1fc80d3e..76ee728fdb07 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -17,6 +17,7 @@
package com.android.server.autofill;
import static android.service.autofill.AutofillFieldClassificationService.EXTRA_SCORES;
+import static android.service.autofill.AutofillService.EXTRA_FILL_RESPONSE;
import static android.service.autofill.FillRequest.FLAG_ACTIVITY_START;
import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
import static android.service.autofill.FillRequest.FLAG_PASSWORD_INPUT_TYPE;
@@ -47,13 +48,16 @@ import android.annotation.Nullable;
import android.app.Activity;
import android.app.ActivityTaskManager;
import android.app.IAssistDataReceiver;
+import android.app.PendingIntent;
import android.app.assist.AssistStructure;
import android.app.assist.AssistStructure.AutofillOverlay;
import android.app.assist.AssistStructure.ViewNode;
+import android.content.BroadcastReceiver;
import android.content.ClipData;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.IntentSender;
import android.content.pm.ApplicationInfo;
import android.graphics.Bitmap;
@@ -148,6 +152,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
AutoFillUI.AutoFillUiCallback, ValueFinder {
private static final String TAG = "AutofillSession";
+ private static final String ACTION_DELAYED_FILL =
+ "android.service.autofill.action.DELAYED_FILL";
private static final String EXTRA_REQUEST_ID = "android.service.autofill.extra.REQUEST_ID";
final Object mLock;
@@ -155,6 +161,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
private final AutofillManagerServiceImpl mService;
private final Handler mHandler;
private final AutoFillUI mUi;
+ @NonNull private final Context mContext;
private final MetricsLogger mMetricsLogger = new MetricsLogger();
@@ -269,6 +276,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
*/
private boolean mHasCallback;
+ @GuardedBy("mLock")
+ private boolean mDelayedFillBroadcastReceiverRegistered;
+
+ @GuardedBy("mLock")
+ private PendingIntent mDelayedFillPendingIntent;
+
/**
* Extras sent by service on {@code onFillRequest()} calls; the most recent non-null extra is
* saved and used on subsequent {@code onFillRequest()} and {@code onSaveRequest()} calls.
@@ -356,6 +369,32 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
private final AccessibilityManager mAccessibilityManager;
+ // TODO(b/216576510): Share one BroadcastReceiver between all Sessions instead of creating a
+ // new one per Session.
+ private final BroadcastReceiver mDelayedFillBroadcastReceiver =
+ new BroadcastReceiver() {
+ // ErrorProne says mAssistReceiver#processDelayedFillLocked needs to be guarded by
+ // 'Session.this.mLock', which is the same as mLock.
+ @SuppressWarnings("GuardedBy")
+ @Override
+ public void onReceive(final Context context, final Intent intent) {
+ if (!intent.getAction().equals(ACTION_DELAYED_FILL)) {
+ Slog.wtf(TAG, "Unexpected action is received.");
+ return;
+ }
+ if (!intent.hasExtra(EXTRA_REQUEST_ID)) {
+ Slog.e(TAG, "Delay fill action is missing request id extra.");
+ return;
+ }
+ Slog.v(TAG, "mDelayedFillBroadcastReceiver delayed fill action received");
+ synchronized (mLock) {
+ int requestId = intent.getIntExtra(EXTRA_REQUEST_ID, 0);
+ FillResponse response = intent.getParcelableExtra(EXTRA_FILL_RESPONSE);
+ mAssistReceiver.processDelayedFillLocked(requestId, response);
+ }
+ }
+ };
+
void onSwitchInputMethodLocked() {
// One caveat is that for the case where the focus is on a field for which regular autofill
// returns null, and augmented autofill is triggered, and then the user switches the input
@@ -408,31 +447,24 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
*/
private final class SessionFlags {
/** Whether autofill is disabled by the service */
- @GuardedBy("mLock")
private boolean mAutofillDisabled;
/** Whether the autofill service supports inline suggestions */
- @GuardedBy("mLock")
private boolean mInlineSupportedByService;
/** True if session is for augmented only */
- @GuardedBy("mLock")
private boolean mAugmentedAutofillOnly;
/** Whether the session is currently showing the SaveUi. */
- @GuardedBy("mLock")
private boolean mShowingSaveUi;
/** Whether the current {@link FillResponse} is expired. */
- @GuardedBy("mLock")
private boolean mExpiredResponse;
/** Whether the client is using {@link android.view.autofill.AutofillRequestCallback}. */
- @GuardedBy("mLock")
private boolean mClientSuggestionsEnabled;
/** Whether the fill dialog UI is disabled. */
- @GuardedBy("mLock")
private boolean mFillDialogDisabled;
}
@@ -447,6 +479,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
private InlineSuggestionsRequest mPendingInlineSuggestionsRequest;
@GuardedBy("mLock")
private FillRequest mPendingFillRequest;
+ @GuardedBy("mLock")
+ private FillRequest mLastFillRequest;
@Nullable Consumer<InlineSuggestionsRequest> newAutofillRequestLocked(ViewState viewState,
boolean isInlineRequest) {
@@ -473,6 +507,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
mPendingInlineSuggestionsRequest = inlineRequest;
}
+ @GuardedBy("mLock")
void maybeRequestFillFromServiceLocked() {
if (mPendingFillRequest == null) {
return;
@@ -490,9 +525,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
mPendingFillRequest = new FillRequest(mPendingFillRequest.getId(),
mPendingFillRequest.getFillContexts(),
mPendingFillRequest.getClientState(),
- mPendingFillRequest.getFlags(), mPendingInlineSuggestionsRequest);
+ mPendingFillRequest.getFlags(),
+ mPendingInlineSuggestionsRequest,
+ mPendingFillRequest.getDelayedFillIntentSender());
}
}
+ mLastFillRequest = mPendingFillRequest;
mRemoteFillService.onFillRequest(mPendingFillRequest);
mPendingInlineSuggestionsRequest = null;
@@ -594,8 +632,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
final ArrayList<FillContext> contexts =
mergePreviousSessionLocked(/* forSave= */ false);
+ mDelayedFillPendingIntent = createPendingIntent(requestId);
request = new FillRequest(requestId, contexts, mClientState, flags,
- /*inlineSuggestionsRequest=*/null);
+ /*inlineSuggestionsRequest=*/ null,
+ /*delayedFillIntentSender=*/ mDelayedFillPendingIntent == null
+ ? null
+ : mDelayedFillPendingIntent.getIntentSender());
mPendingFillRequest = request;
maybeRequestFillFromServiceLocked();
@@ -610,7 +652,70 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
public void onHandleAssistScreenshot(Bitmap screenshot) {
// Do nothing
}
- };
+
+ @GuardedBy("mLock")
+ void processDelayedFillLocked(int requestId, FillResponse response) {
+ if (mLastFillRequest != null && requestId == mLastFillRequest.getId()) {
+ Slog.v(TAG, "processDelayedFillLocked: "
+ + "calling onFillRequestSuccess with new response");
+ onFillRequestSuccess(requestId, response,
+ mService.getServicePackageName(), mLastFillRequest.getFlags());
+ }
+ }
+ }
+
+ /** Creates {@link PendingIntent} for autofill service to send a delayed fill. */
+ private PendingIntent createPendingIntent(int requestId) {
+ Slog.d(TAG, "createPendingIntent for request " + requestId);
+ PendingIntent pendingIntent;
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ Intent intent = new Intent(ACTION_DELAYED_FILL).setPackage("android")
+ .putExtra(EXTRA_REQUEST_ID, requestId);
+ pendingIntent = PendingIntent.getBroadcast(
+ mContext, this.id, intent,
+ PendingIntent.FLAG_MUTABLE
+ | PendingIntent.FLAG_ONE_SHOT
+ | PendingIntent.FLAG_CANCEL_CURRENT);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ return pendingIntent;
+ }
+
+ @GuardedBy("mLock")
+ private void clearPendingIntentLocked() {
+ Slog.d(TAG, "clearPendingIntentLocked");
+ if (mDelayedFillPendingIntent == null) {
+ return;
+ }
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ mDelayedFillPendingIntent.cancel();
+ mDelayedFillPendingIntent = null;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void registerDelayedFillBroadcastLocked() {
+ if (!mDelayedFillBroadcastReceiverRegistered) {
+ Slog.v(TAG, "registerDelayedFillBroadcastLocked()");
+ IntentFilter intentFilter = new IntentFilter(ACTION_DELAYED_FILL);
+ mContext.registerReceiver(mDelayedFillBroadcastReceiver, intentFilter);
+ mDelayedFillBroadcastReceiverRegistered = true;
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void unregisterDelayedFillBroadcastLocked() {
+ if (mDelayedFillBroadcastReceiverRegistered) {
+ Slog.v(TAG, "unregisterDelayedFillBroadcastLocked()");
+ mContext.unregisterReceiver(mDelayedFillBroadcastReceiver);
+ mDelayedFillBroadcastReceiverRegistered = false;
+ }
+ }
/**
* Returns the ids of all entries in {@link #mViewStates} in the same order.
@@ -964,6 +1069,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
mHasCallback = hasCallback;
mUiLatencyHistory = uiLatencyHistory;
mWtfHistory = wtfHistory;
+ mContext = context;
mComponentName = componentName;
mCompatMode = compatMode;
mSessionState = STATE_ACTIVE;
@@ -1096,6 +1202,12 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
processNullResponseLocked(requestId, requestFlags);
return;
}
+
+ final int flags = response.getFlags();
+ if ((flags & FillResponse.FLAG_DELAY_FILL) != 0) {
+ Slog.v(TAG, "Service requested to wait for delayed fill response.");
+ registerDelayedFillBroadcastLocked();
+ }
}
mService.setLastResponse(id, response);
@@ -1206,6 +1318,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
@Nullable CharSequence message) {
boolean showMessage = !TextUtils.isEmpty(message);
synchronized (mLock) {
+ unregisterDelayedFillBroadcastLocked();
if (mDestroyed) {
Slog.w(TAG, "Call to Session#onFillRequestFailureOrTimeout(req=" + requestId
+ ") rejected - session: " + id + " destroyed");
@@ -1522,7 +1635,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
Slog.e(TAG, "Error sending input show up notification", e);
}
}
- synchronized (Session.this.mLock) {
+ synchronized (mLock) {
// stop to show fill dialog
mSessionFlags.mFillDialogDisabled = true;
}
@@ -3259,7 +3372,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
private boolean isFillDialogUiEnabled() {
// TODO read from Settings or somewhere
final boolean isSettingsEnabledFillDialog = true;
- synchronized (Session.this.mLock) {
+ synchronized (mLock) {
return isSettingsEnabledFillDialog && !mSessionFlags.mFillDialogDisabled;
}
}
@@ -3530,6 +3643,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
@GuardedBy("mLock")
private void processNullResponseLocked(int requestId, int flags) {
+ unregisterDelayedFillBroadcastLocked();
if ((flags & FLAG_MANUAL_REQUEST) != 0) {
getUiForShowing().showError(R.string.autofill_error_cannot_autofill, this);
}
@@ -3744,6 +3858,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
// only if handling the current response requires it.
mUi.hideAll(this);
+ if ((newResponse.getFlags() & FillResponse.FLAG_DELAY_FILL) == 0) {
+ Slog.d(TAG, "Service did not request to wait for delayed fill response.");
+ unregisterDelayedFillBroadcastLocked();
+ }
+
final int requestId = newResponse.getRequestId();
if (sVerbose) {
Slog.v(TAG, "processResponseLocked(): mCurrentViewId=" + mCurrentViewId
@@ -4296,6 +4415,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
return null;
}
+ clearPendingIntentLocked();
+ unregisterDelayedFillBroadcastLocked();
+
unlinkClientVultureLocked();
mUi.destroyAll(mPendingSaveUi, this, true);
mUi.clearCallback(this);
diff --git a/services/companion/java/com/android/server/companion/AssociationStoreImpl.java b/services/companion/java/com/android/server/companion/AssociationStoreImpl.java
index cda554e9d0cf..3ccabaaea2fa 100644
--- a/services/companion/java/com/android/server/companion/AssociationStoreImpl.java
+++ b/services/companion/java/com/android/server/companion/AssociationStoreImpl.java
@@ -125,7 +125,7 @@ class AssociationStoreImpl implements AssociationStore {
// Update the MacAddress-to-List<Association> map if needed.
final MacAddress updatedAddress = updated.getDeviceMacAddress();
final MacAddress currentAddress = current.getDeviceMacAddress();
- macAddressChanged = Objects.equals(currentAddress, updatedAddress);
+ macAddressChanged = !Objects.equals(currentAddress, updatedAddress);
if (macAddressChanged) {
if (currentAddress != null) {
mAddressMap.get(currentAddress).remove(id);
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index cfd37988d234..c3ab2a79e288 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -1255,7 +1255,7 @@ public class CompanionDeviceManagerService extends SystemService
}
@Override
- public void onDeviceDisconnected(BluetoothDevice device, @DisconnectReason int reason) {
+ public void onDeviceDisconnected(BluetoothDevice device, int reason) {
Slog.d(LOG_TAG, device.getAddress() + " disconnected w/ reason: (" + reason + ") "
+ BluetoothAdapter.BluetoothConnectionCallback.disconnectReasonText(reason));
CompanionDeviceManagerService.this.onDeviceDisconnected(device.getAddress());
diff --git a/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java b/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java
index dbe866b374f1..93cbe973b00e 100644
--- a/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java
+++ b/services/companion/java/com/android/server/companion/presence/BluetoothCompanionDeviceConnectionListener.java
@@ -91,7 +91,7 @@ class BluetoothCompanionDeviceConnectionListener
*/
@Override
public void onDeviceDisconnected(@NonNull BluetoothDevice device,
- @DisconnectReason int reason) {
+ int reason) {
if (DEBUG) {
Log.i(TAG, "onDevice_Disconnected() " + btDeviceToString(device));
Log.d(TAG, " reason=" + disconnectReasonText(reason));
diff --git a/services/companion/java/com/android/server/companion/virtual/InputController.java b/services/companion/java/com/android/server/companion/virtual/InputController.java
index 6c56e2f777f3..e6bfd1ff7f1a 100644
--- a/services/companion/java/com/android/server/companion/virtual/InputController.java
+++ b/services/companion/java/com/android/server/companion/virtual/InputController.java
@@ -18,8 +18,11 @@ package com.android.server.companion.virtual;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.StringDef;
import android.graphics.Point;
import android.graphics.PointF;
+import android.hardware.display.DisplayManagerInternal;
+import android.hardware.input.InputManager;
import android.hardware.input.InputManagerInternal;
import android.hardware.input.VirtualKeyEvent;
import android.hardware.input.VirtualMouseButtonEvent;
@@ -48,6 +51,20 @@ class InputController {
private static final String TAG = "VirtualInputController";
+ private static final AtomicLong sNextPhysId = new AtomicLong(1);
+
+ static final String PHYS_TYPE_KEYBOARD = "Keyboard";
+ static final String PHYS_TYPE_MOUSE = "Mouse";
+ static final String PHYS_TYPE_TOUCHSCREEN = "Touchscreen";
+ @StringDef(prefix = { "PHYS_TYPE_" }, value = {
+ PHYS_TYPE_KEYBOARD,
+ PHYS_TYPE_MOUSE,
+ PHYS_TYPE_TOUCHSCREEN,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface PhysType {
+ }
+
private final Object mLock;
/* Token -> file descriptor associations. */
@@ -56,6 +73,8 @@ class InputController {
final Map<IBinder, InputDeviceDescriptor> mInputDeviceDescriptors = new ArrayMap<>();
private final NativeWrapper mNativeWrapper;
+ private final DisplayManagerInternal mDisplayManagerInternal;
+ private final InputManagerInternal mInputManagerInternal;
/**
* Because the pointer is a singleton, it can only be targeted at one display at a time. Because
@@ -73,6 +92,8 @@ class InputController {
mLock = lock;
mNativeWrapper = nativeWrapper;
mActivePointerDisplayId = Display.INVALID_DISPLAY;
+ mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
+ mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
}
void close() {
@@ -90,7 +111,9 @@ class InputController {
int productId,
@NonNull IBinder deviceToken,
int displayId) {
- final int fd = mNativeWrapper.openUinputKeyboard(deviceName, vendorId, productId);
+ final String phys = createPhys(PHYS_TYPE_KEYBOARD);
+ setUniqueIdAssociation(displayId, phys);
+ final int fd = mNativeWrapper.openUinputKeyboard(deviceName, vendorId, productId, phys);
if (fd < 0) {
throw new RuntimeException(
"A native error occurred when creating keyboard: " + -fd);
@@ -99,7 +122,7 @@ class InputController {
synchronized (mLock) {
mInputDeviceDescriptors.put(deviceToken,
new InputDeviceDescriptor(fd, binderDeathRecipient,
- InputDeviceDescriptor.TYPE_KEYBOARD, displayId));
+ InputDeviceDescriptor.TYPE_KEYBOARD, displayId, phys));
}
try {
deviceToken.linkToDeath(binderDeathRecipient, /* flags= */ 0);
@@ -114,7 +137,9 @@ class InputController {
int productId,
@NonNull IBinder deviceToken,
int displayId) {
- final int fd = mNativeWrapper.openUinputMouse(deviceName, vendorId, productId);
+ final String phys = createPhys(PHYS_TYPE_MOUSE);
+ setUniqueIdAssociation(displayId, phys);
+ final int fd = mNativeWrapper.openUinputMouse(deviceName, vendorId, productId, phys);
if (fd < 0) {
throw new RuntimeException(
"A native error occurred when creating mouse: " + -fd);
@@ -123,11 +148,9 @@ class InputController {
synchronized (mLock) {
mInputDeviceDescriptors.put(deviceToken,
new InputDeviceDescriptor(fd, binderDeathRecipient,
- InputDeviceDescriptor.TYPE_MOUSE, displayId));
- final InputManagerInternal inputManagerInternal =
- LocalServices.getService(InputManagerInternal.class);
- inputManagerInternal.setVirtualMousePointerDisplayId(displayId);
- inputManagerInternal.setPointerAcceleration(1);
+ InputDeviceDescriptor.TYPE_MOUSE, displayId, phys));
+ mInputManagerInternal.setVirtualMousePointerDisplayId(displayId);
+ mInputManagerInternal.setPointerAcceleration(1);
mActivePointerDisplayId = displayId;
}
try {
@@ -144,7 +167,9 @@ class InputController {
@NonNull IBinder deviceToken,
int displayId,
@NonNull Point screenSize) {
- final int fd = mNativeWrapper.openUinputTouchscreen(deviceName, vendorId, productId,
+ final String phys = createPhys(PHYS_TYPE_TOUCHSCREEN);
+ setUniqueIdAssociation(displayId, phys);
+ final int fd = mNativeWrapper.openUinputTouchscreen(deviceName, vendorId, productId, phys,
screenSize.y, screenSize.x);
if (fd < 0) {
throw new RuntimeException(
@@ -154,7 +179,7 @@ class InputController {
synchronized (mLock) {
mInputDeviceDescriptors.put(deviceToken,
new InputDeviceDescriptor(fd, binderDeathRecipient,
- InputDeviceDescriptor.TYPE_TOUCHSCREEN, displayId));
+ InputDeviceDescriptor.TYPE_TOUCHSCREEN, displayId, phys));
}
try {
deviceToken.linkToDeath(binderDeathRecipient, /* flags= */ 0);
@@ -174,6 +199,7 @@ class InputController {
}
token.unlinkToDeath(inputDeviceDescriptor.getDeathRecipient(), /* flags= */ 0);
mNativeWrapper.closeUinput(inputDeviceDescriptor.getFileDescriptor());
+ InputManager.getInstance().removeUniqueIdAssociation(inputDeviceDescriptor.getPhys());
// Reset values to the default if all virtual mice are unregistered, or set display
// id if there's another mouse (choose the most recent).
@@ -197,9 +223,7 @@ class InputController {
}
}
if (mostRecentlyCreatedMouse != null) {
- final InputManagerInternal inputManagerInternal =
- LocalServices.getService(InputManagerInternal.class);
- inputManagerInternal.setVirtualMousePointerDisplayId(
+ mInputManagerInternal.setVirtualMousePointerDisplayId(
mostRecentlyCreatedMouse.getDisplayId());
mActivePointerDisplayId = mostRecentlyCreatedMouse.getDisplayId();
} else {
@@ -209,14 +233,21 @@ class InputController {
}
private void resetMouseValuesLocked() {
- final InputManagerInternal inputManagerInternal =
- LocalServices.getService(InputManagerInternal.class);
- inputManagerInternal.setVirtualMousePointerDisplayId(Display.INVALID_DISPLAY);
- inputManagerInternal.setPointerAcceleration(
+ mInputManagerInternal.setVirtualMousePointerDisplayId(Display.INVALID_DISPLAY);
+ mInputManagerInternal.setPointerAcceleration(
IInputConstants.DEFAULT_POINTER_ACCELERATION);
mActivePointerDisplayId = Display.INVALID_DISPLAY;
}
+ private static String createPhys(@PhysType String type) {
+ return String.format("virtual%s:%d", type, sNextPhysId.getAndIncrement());
+ }
+
+ private void setUniqueIdAssociation(int displayId, String phys) {
+ final String displayUniqueId = mDisplayManagerInternal.getDisplayInfo(displayId).uniqueId;
+ InputManager.getInstance().addUniqueIdAssociation(phys, displayUniqueId);
+ }
+
boolean sendKeyEvent(@NonNull IBinder token, @NonNull VirtualKeyEvent event) {
synchronized (mLock) {
final InputDeviceDescriptor inputDeviceDescriptor = mInputDeviceDescriptors.get(
@@ -321,17 +352,18 @@ class InputController {
fout.println(" creationOrder: "
+ inputDeviceDescriptor.getCreationOrderNumber());
fout.println(" type: " + inputDeviceDescriptor.getType());
+ fout.println(" phys: " + inputDeviceDescriptor.getPhys());
}
fout.println(" Active mouse display id: " + mActivePointerDisplayId);
}
}
private static native int nativeOpenUinputKeyboard(String deviceName, int vendorId,
- int productId);
- private static native int nativeOpenUinputMouse(String deviceName, int vendorId,
- int productId);
+ int productId, String phys);
+ private static native int nativeOpenUinputMouse(String deviceName, int vendorId, int productId,
+ String phys);
private static native int nativeOpenUinputTouchscreen(String deviceName, int vendorId,
- int productId, int height, int width);
+ int productId, String phys, int height, int width);
private static native boolean nativeCloseUinput(int fd);
private static native boolean nativeWriteKeyEvent(int fd, int androidKeyCode, int action);
private static native boolean nativeWriteButtonEvent(int fd, int buttonCode, int action);
@@ -345,20 +377,18 @@ class InputController {
/** Wrapper around the static native methods for tests. */
@VisibleForTesting
protected static class NativeWrapper {
- public int openUinputKeyboard(String deviceName, int vendorId, int productId) {
- return nativeOpenUinputKeyboard(deviceName, vendorId,
- productId);
+ public int openUinputKeyboard(String deviceName, int vendorId, int productId, String phys) {
+ return nativeOpenUinputKeyboard(deviceName, vendorId, productId, phys);
}
- public int openUinputMouse(String deviceName, int vendorId, int productId) {
- return nativeOpenUinputMouse(deviceName, vendorId,
- productId);
+ public int openUinputMouse(String deviceName, int vendorId, int productId, String phys) {
+ return nativeOpenUinputMouse(deviceName, vendorId, productId, phys);
}
- public int openUinputTouchscreen(String deviceName, int vendorId, int productId, int height,
- int width) {
- return nativeOpenUinputTouchscreen(deviceName, vendorId,
- productId, height, width);
+ public int openUinputTouchscreen(String deviceName, int vendorId,
+ int productId, String phys, int height, int width) {
+ return nativeOpenUinputTouchscreen(deviceName, vendorId, productId, phys, height,
+ width);
}
public boolean closeUinput(int fd) {
@@ -410,15 +440,17 @@ class InputController {
private final IBinder.DeathRecipient mDeathRecipient;
private final @Type int mType;
private final int mDisplayId;
+ private final String mPhys;
// Monotonically increasing number; devices with lower numbers were created earlier.
private final long mCreationOrderNumber;
- InputDeviceDescriptor(int fd, IBinder.DeathRecipient deathRecipient,
- @Type int type, int displayId) {
+ InputDeviceDescriptor(int fd, IBinder.DeathRecipient deathRecipient, @Type int type,
+ int displayId, String phys) {
mFd = fd;
mDeathRecipient = deathRecipient;
mType = type;
mDisplayId = displayId;
+ mPhys = phys;
mCreationOrderNumber = sNextCreationOrderNumber.getAndIncrement();
}
@@ -445,6 +477,10 @@ class InputController {
public long getCreationOrderNumber() {
return mCreationOrderNumber;
}
+
+ public String getPhys() {
+ return mPhys;
+ }
}
private final class BinderDeathRecipient implements IBinder.DeathRecipient {
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index c8ad0e88e995..5da461d8e392 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -1365,7 +1365,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
}
public void notePhoneDataConnectionState(final int dataType, final boolean hasData,
- final int serviceType) {
+ final int serviceType, final int nrFrequency) {
enforceCallingPermission();
synchronized (mLock) {
final long elapsedRealtime = SystemClock.elapsedRealtime();
@@ -1373,7 +1373,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
mHandler.post(() -> {
synchronized (mStats) {
mStats.notePhoneDataConnectionStateLocked(dataType, hasData, serviceType,
- elapsedRealtime, uptime);
+ nrFrequency, elapsedRealtime, uptime);
}
});
}
@@ -1962,6 +1962,32 @@ public final class BatteryStatsService extends IBatteryStats.Stub
}
}
+ /**
+ * Bluetooth on stat logging
+ */
+ public void noteBluetoothOn(int uid, int reason, String packageName) {
+ if (Binder.getCallingPid() != Process.myPid()) {
+ mContext.enforcePermission(android.Manifest.permission.BLUETOOTH_CONNECT,
+ Binder.getCallingPid(), uid, null);
+ }
+ FrameworkStatsLog.write_non_chained(FrameworkStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED,
+ uid, null, FrameworkStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__ENABLED,
+ reason, packageName);
+ }
+
+ /**
+ * Bluetooth off stat logging
+ */
+ public void noteBluetoothOff(int uid, int reason, String packageName) {
+ if (Binder.getCallingPid() != Process.myPid()) {
+ mContext.enforcePermission(android.Manifest.permission.BLUETOOTH_CONNECT,
+ Binder.getCallingPid(), uid, null);
+ }
+ FrameworkStatsLog.write_non_chained(FrameworkStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED,
+ uid, null, FrameworkStatsLog.BLUETOOTH_ENABLED_STATE_CHANGED__STATE__DISABLED,
+ reason, packageName);
+ }
+
@Override
public void noteBleScanStarted(final WorkSource ws, final boolean isUnoptimized) {
enforceCallingPermission();
diff --git a/services/core/java/com/android/server/am/DataConnectionStats.java b/services/core/java/com/android/server/am/DataConnectionStats.java
index 6e39a4c802d9..f0910dcb0da2 100644
--- a/services/core/java/com/android/server/am/DataConnectionStats.java
+++ b/services/core/java/com/android/server/am/DataConnectionStats.java
@@ -109,7 +109,7 @@ public class DataConnectionStats extends BroadcastReceiver {
}
try {
mBatteryStats.notePhoneDataConnectionState(networkType, visible,
- mServiceState.getState());
+ mServiceState.getState(), mServiceState.getNrFrequencyRange());
} catch (RemoteException e) {
Log.w(TAG, "Error noting data connection state", e);
}
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 42fca9b840df..47f31d505867 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -486,9 +486,7 @@ public class BtHelper {
return;
}
final BluetoothDevice btDevice = deviceList.get(0);
- final @BluetoothProfile.BtProfileState int state =
- proxy.getConnectionState(btDevice);
- if (state == BluetoothProfile.STATE_CONNECTED) {
+ if (proxy.getConnectionState(btDevice) == BluetoothProfile.STATE_CONNECTED) {
mDeviceBroker.queueOnBluetoothActiveDeviceChanged(
new AudioDeviceBroker.BtDeviceChangedData(btDevice, null,
new BtProfileConnectionInfo(profile), "mBluetoothProfileServiceListener"));
diff --git a/services/core/java/com/android/server/biometrics/log/BiometricContext.java b/services/core/java/com/android/server/biometrics/log/BiometricContext.java
new file mode 100644
index 000000000000..8d28298542dc
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/log/BiometricContext.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.log;
+
+import android.annotation.NonNull;
+import android.hardware.biometrics.common.OperationContext;
+
+import java.util.function.Consumer;
+
+/**
+ * Cache for system state not directly related to biometric operations that is used for
+ * logging or optimizations.
+ */
+public interface BiometricContext {
+ /** Gets the context source. */
+ static BiometricContext getInstance() {
+ return BiometricContextProvider.sInstance.get();
+ }
+
+ /** If the display is in AOD. */
+ boolean isAoD();
+
+ /**
+ * Subscribe to context changes.
+ *
+ * @param context context that will be modified when changed
+ * @param consumer callback when the context is modified
+ */
+ void subscribe(@NonNull OperationContext context, @NonNull Consumer<OperationContext> consumer);
+
+ /** Unsubscribe from context changes. */
+ void unsubscribe(@NonNull OperationContext context);
+}
diff --git a/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java b/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java
new file mode 100644
index 000000000000..65e9e3dec60f
--- /dev/null
+++ b/services/core/java/com/android/server/biometrics/log/BiometricContextProvider.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.log;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.hardware.biometrics.IBiometricContextListener;
+import android.hardware.biometrics.common.OperationContext;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Singleton;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.statusbar.IStatusBarService;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Consumer;
+
+/**
+ * A default provider for {@link BiometricContext}.
+ */
+class BiometricContextProvider implements BiometricContext {
+
+ private static final String TAG = "BiometricContextProvider";
+
+ static final Singleton<BiometricContextProvider> sInstance =
+ new Singleton<BiometricContextProvider>() {
+ @Override
+ protected BiometricContextProvider create() {
+ return new BiometricContextProvider(IStatusBarService.Stub.asInterface(
+ ServiceManager.getService(
+ Context.STATUS_BAR_SERVICE)), null /* handler */);
+ }
+ };
+
+ @NonNull
+ private final Map<OperationContext, Consumer<OperationContext>> mSubscribers =
+ new ConcurrentHashMap<>();
+
+ @VisibleForTesting
+ BiometricContextProvider(@NonNull IStatusBarService service, @Nullable Handler handler) {
+ try {
+ service.setBiometicContextListener(new IBiometricContextListener.Stub() {
+ @Override
+ public void onDozeChanged(boolean isDozing) {
+ mIsDozing = isDozing;
+ notifyChanged();
+ }
+
+ private void notifyChanged() {
+ if (handler != null) {
+ handler.post(() -> notifySubscribers());
+ } else {
+ notifySubscribers();
+ }
+ }
+ });
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to register biometric context listener", e);
+ }
+ }
+
+ private boolean mIsDozing = false;
+
+ @Override
+ public boolean isAoD() {
+ return mIsDozing;
+ }
+
+ @Override
+ public void subscribe(@NonNull OperationContext context,
+ @NonNull Consumer<OperationContext> consumer) {
+ mSubscribers.put(context, consumer);
+ }
+
+ @Override
+ public void unsubscribe(@NonNull OperationContext context) {
+ mSubscribers.remove(context);
+ }
+
+ private void notifySubscribers() {
+ mSubscribers.forEach((context, consumer) -> {
+ context.isAoD = mIsDozing;
+ consumer.accept(context);
+ });
+ }
+}
diff --git a/services/core/java/com/android/server/biometrics/log/BiometricLogger.java b/services/core/java/com/android/server/biometrics/log/BiometricLogger.java
index d029af38c683..018839079e22 100644
--- a/services/core/java/com/android/server/biometrics/log/BiometricLogger.java
+++ b/services/core/java/com/android/server/biometrics/log/BiometricLogger.java
@@ -79,6 +79,12 @@ public class BiometricLogger {
}
};
+ /** Get a new logger with all unknown fields (for operations that do not require logs). */
+ public static BiometricLogger ofUnknown(@NonNull Context context) {
+ return new BiometricLogger(context, BiometricsProtoEnums.MODALITY_UNKNOWN,
+ BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
+ }
+
/**
* @param context system_server context
* @param statsModality One of {@link BiometricsProtoEnums} MODALITY_* constants.
@@ -103,6 +109,11 @@ public class BiometricLogger {
mSensorManager = sensorManager;
}
+ /** Creates a new logger with the action replaced with the new action. */
+ public BiometricLogger swapAction(@NonNull Context context, int statsAction) {
+ return new BiometricLogger(context, mStatsModality, statsAction, mStatsClient);
+ }
+
/** Disable logging metrics and only log critical events, such as system health issues. */
public void disableMetrics() {
mShouldLogMetrics = false;
diff --git a/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java
index 8b8103e6e2c9..e07a68c6d94d 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AcquisitionClient.java
@@ -29,6 +29,9 @@ import android.os.VibrationEffect;
import android.os.Vibrator;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
+
import java.util.function.Supplier;
/**
@@ -57,9 +60,9 @@ public abstract class AcquisitionClient<T> extends HalClientMonitor<T> implement
public AcquisitionClient(@NonNull Context context, @NonNull Supplier<T> lazyDaemon,
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
@NonNull String owner, int cookie, int sensorId, boolean shouldVibrate,
- int statsModality, int statsAction, int statsClient) {
- super(context, lazyDaemon, token, listener, userId, owner, cookie, sensorId, statsModality,
- statsAction, statsClient);
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
+ super(context, lazyDaemon, token, listener, userId, owner, cookie, sensorId,
+ logger, biometricContext);
mPowerManager = context.getSystemService(PowerManager.class);
mShouldVibrate = shouldVibrate;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
index b715faf3ca8f..949edd0e79ed 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -29,7 +29,6 @@ import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricOverlayConstants;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
@@ -39,6 +38,8 @@ import android.util.Slog;
import com.android.server.biometrics.BiometricsProto;
import com.android.server.biometrics.Utils;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import java.util.ArrayList;
import java.util.List;
@@ -93,13 +94,13 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
public AuthenticationClient(@NonNull Context context, @NonNull Supplier<T> lazyDaemon,
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener,
int targetUserId, long operationId, boolean restricted, @NonNull String owner,
- int cookie, boolean requireConfirmation, int sensorId, boolean isStrongBiometric,
- int statsModality, int statsClient, @Nullable TaskStackListener taskStackListener,
+ int cookie, boolean requireConfirmation, int sensorId,
+ @NonNull BiometricLogger biometricLogger, @NonNull BiometricContext biometricContext,
+ boolean isStrongBiometric, @Nullable TaskStackListener taskStackListener,
@NonNull LockoutTracker lockoutTracker, boolean allowBackgroundAuthentication,
boolean shouldVibrate, boolean isKeyguardBypassEnabled) {
super(context, lazyDaemon, token, listener, targetUserId, owner, cookie, sensorId,
- shouldVibrate, statsModality, BiometricsProtoEnums.ACTION_AUTHENTICATE,
- statsClient);
+ shouldVibrate, biometricLogger, biometricContext);
mIsStrongBiometric = isStrongBiometric;
mOperationId = operationId;
mRequireConfirmation = requireConfirmation;
diff --git a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
index e1f7e2ab5461..1b2e606117e7 100644
--- a/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/BaseClientMonitor.java
@@ -21,12 +21,12 @@ import static com.android.internal.annotations.VisibleForTesting.Visibility;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.biometrics.log.BiometricContext;
import com.android.server.biometrics.log.BiometricLogger;
import java.util.NoSuchElementException;
@@ -50,6 +50,7 @@ public abstract class BaseClientMonitor implements IBinder.DeathRecipient {
@NonNull private final String mOwner;
private final int mSensorId; // sensorId as configured by the framework
@NonNull private final BiometricLogger mLogger;
+ @NonNull private final BiometricContext mBiometricContext;
@Nullable private IBinder mToken;
private long mRequestId;
@@ -82,22 +83,13 @@ public abstract class BaseClientMonitor implements IBinder.DeathRecipient {
* @param owner name of the client that owns this
* @param cookie BiometricPrompt authentication cookie (to be moved into a subclass soon)
* @param sensorId ID of the sensor that the operation should be requested of
- * @param statsModality One of {@link BiometricsProtoEnums} MODALITY_* constants
- * @param statsAction One of {@link BiometricsProtoEnums} ACTION_* constants
- * @param statsClient One of {@link BiometricsProtoEnums} CLIENT_* constants
+ * @param logger framework stats logger
+ * @param biometricContext system context metadata
*/
public BaseClientMonitor(@NonNull Context context,
@Nullable IBinder token, @Nullable ClientMonitorCallbackConverter listener, int userId,
- @NonNull String owner, int cookie, int sensorId, int statsModality, int statsAction,
- int statsClient) {
- this(context, token, listener, userId, owner, cookie, sensorId,
- new BiometricLogger(context, statsModality, statsAction, statsClient));
- }
-
- @VisibleForTesting
- BaseClientMonitor(@NonNull Context context,
- @Nullable IBinder token, @Nullable ClientMonitorCallbackConverter listener, int userId,
- @NonNull String owner, int cookie, int sensorId, @NonNull BiometricLogger logger) {
+ @NonNull String owner, int cookie, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
mSequentialId = sCount++;
mContext = context;
mToken = token;
@@ -108,6 +100,7 @@ public abstract class BaseClientMonitor implements IBinder.DeathRecipient {
mCookie = cookie;
mSensorId = sensorId;
mLogger = logger;
+ mBiometricContext = biometricContext;
try {
if (token != null) {
@@ -207,20 +200,29 @@ public abstract class BaseClientMonitor implements IBinder.DeathRecipient {
return false;
}
+ /** System context that may change during operations. */
+ @NonNull
+ protected BiometricContext getBiometricContext() {
+ return mBiometricContext;
+ }
+
/** Logger for this client */
@NonNull
public BiometricLogger getLogger() {
return mLogger;
}
+ @NonNull
public final Context getContext() {
return mContext;
}
+ @NonNull
public final String getOwnerString() {
return mOwner;
}
+ @Nullable
public final ClientMonitorCallbackConverter getListener() {
return mListener;
}
@@ -229,6 +231,7 @@ public abstract class BaseClientMonitor implements IBinder.DeathRecipient {
return mTargetUserId;
}
+ @Nullable
public final IBinder getToken() {
return mToken;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java
index 74f4931cf2aa..483ce75eae98 100644
--- a/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/EnrollClient.java
@@ -20,13 +20,14 @@ import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricOverlayConstants;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.fingerprint.FingerprintManager;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.BiometricsProto;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import java.util.Arrays;
import java.util.function.Supplier;
@@ -53,10 +54,10 @@ public abstract class EnrollClient<T> extends AcquisitionClient<T> implements En
public EnrollClient(@NonNull Context context, @NonNull Supplier<T> lazyDaemon,
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
@NonNull byte[] hardwareAuthToken, @NonNull String owner, @NonNull BiometricUtils utils,
- int timeoutSec, int statsModality, int sensorId, boolean shouldVibrate) {
+ int timeoutSec, int sensorId, boolean shouldVibrate,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
- shouldVibrate, statsModality, BiometricsProtoEnums.ACTION_ENROLL,
- BiometricsProtoEnums.CLIENT_UNKNOWN);
+ shouldVibrate, logger, biometricContext);
mBiometricUtils = utils;
mHardwareAuthToken = Arrays.copyOf(hardwareAuthToken, hardwareAuthToken.length);
mTimeoutSec = timeoutSec;
diff --git a/services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java
index 9689418b1f1a..2adf0cb3bab4 100644
--- a/services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/GenerateChallengeClient.java
@@ -18,12 +18,13 @@ package com.android.server.biometrics.sensors;
import android.annotation.NonNull;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.BiometricsProto;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import java.util.function.Supplier;
@@ -33,10 +34,10 @@ public abstract class GenerateChallengeClient<T> extends HalClientMonitor<T> {
public GenerateChallengeClient(@NonNull Context context, @NonNull Supplier<T> lazyDaemon,
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener,
- int userId, @NonNull String owner, int sensorId) {
+ int userId, @NonNull String owner, int sensorId,
+ @NonNull BiometricLogger biometricLogger, @NonNull BiometricContext biometricContext) {
super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
- BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN,
- BiometricsProtoEnums.CLIENT_UNKNOWN);
+ biometricLogger, biometricContext);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java b/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java
index 66a1c6e876ab..eabafceab590 100644
--- a/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/HalClientMonitor.java
@@ -19,9 +19,12 @@ package com.android.server.biometrics.sensors;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
+import android.hardware.biometrics.common.OperationContext;
import android.os.IBinder;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
+
import java.util.function.Supplier;
/**
@@ -33,6 +36,9 @@ public abstract class HalClientMonitor<T> extends BaseClientMonitor {
@NonNull
protected final Supplier<T> mLazyDaemon;
+ @NonNull
+ protected final OperationContext mOperationContext = new OperationContext();
+
/**
* @param context system_server context
* @param lazyDaemon pointer for lazy retrieval of the HAL
@@ -42,16 +48,15 @@ public abstract class HalClientMonitor<T> extends BaseClientMonitor {
* @param owner name of the client that owns this
* @param cookie BiometricPrompt authentication cookie (to be moved into a subclass soon)
* @param sensorId ID of the sensor that the operation should be requested of
- * @param statsModality One of {@link BiometricsProtoEnums} MODALITY_* constants
- * @param statsAction One of {@link BiometricsProtoEnums} ACTION_* constants
- * @param statsClient One of {@link BiometricsProtoEnums} CLIENT_* constants
+ * @param biometricLogger framework stats logger
+ * @param biometricContext system context metadata
*/
public HalClientMonitor(@NonNull Context context, @NonNull Supplier<T> lazyDaemon,
@Nullable IBinder token, @Nullable ClientMonitorCallbackConverter listener, int userId,
- @NonNull String owner, int cookie, int sensorId, int statsModality, int statsAction,
- int statsClient) {
- super(context, token, listener, userId, owner, cookie, sensorId, statsModality,
- statsAction, statsClient);
+ @NonNull String owner, int cookie, int sensorId,
+ @NonNull BiometricLogger biometricLogger, @NonNull BiometricContext biometricContext) {
+ super(context, token, listener, userId, owner, cookie, sensorId,
+ biometricLogger, biometricContext);
mLazyDaemon = lazyDaemon;
}
@@ -71,4 +76,12 @@ public abstract class HalClientMonitor<T> extends BaseClientMonitor {
* {@link #start(ClientMonitorCallback)}.
*/
public abstract void unableToStart();
+
+ @Override
+ public void destroy() {
+ super.destroy();
+
+ // subclasses should do this earlier in most cases, but ensure it happens now
+ getBiometricContext().unsubscribe(mOperationContext);
+ }
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
index 0e6d11ec5182..57ea812dbb3a 100644
--- a/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/InternalCleanupClient.java
@@ -19,11 +19,12 @@ package com.android.server.biometrics.sensors;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.os.IBinder;
import android.util.Slog;
import com.android.server.biometrics.BiometricsProto;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import java.util.ArrayList;
import java.util.List;
@@ -101,19 +102,22 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide
protected abstract InternalEnumerateClient<T> getEnumerateClient(Context context,
Supplier<T> lazyDaemon, IBinder token, int userId, String owner,
- List<S> enrolledList, BiometricUtils<S> utils, int sensorId);
+ List<S> enrolledList, BiometricUtils<S> utils, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext);
protected abstract RemovalClient<S, T> getRemovalClient(Context context,
Supplier<T> lazyDaemon, IBinder token, int biometricId, int userId, String owner,
- BiometricUtils<S> utils, int sensorId, Map<Integer, Long> authenticatorIds);
+ BiometricUtils<S> utils, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+ Map<Integer, Long> authenticatorIds);
protected InternalCleanupClient(@NonNull Context context, @NonNull Supplier<T> lazyDaemon,
- int userId, @NonNull String owner, int sensorId, int statsModality,
+ int userId, @NonNull String owner, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
@NonNull List<S> enrolledList, @NonNull BiometricUtils<S> utils,
@NonNull Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, null /* token */, null /* ClientMonitorCallbackConverter */,
- userId, owner, 0 /* cookie */, sensorId, statsModality,
- BiometricsProtoEnums.ACTION_ENUMERATE, BiometricsProtoEnums.CLIENT_UNKNOWN);
+ userId, owner, 0 /* cookie */, sensorId, logger, biometricContext);
mBiometricUtils = utils;
mAuthenticatorIds = authenticatorIds;
mEnrolledList = enrolledList;
@@ -127,7 +131,8 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide
mUnknownHALTemplates.remove(template);
mCurrentTask = getRemovalClient(getContext(), mLazyDaemon, getToken(),
template.mIdentifier.getBiometricId(), template.mUserId,
- getContext().getPackageName(), mBiometricUtils, getSensorId(), mAuthenticatorIds);
+ getContext().getPackageName(), mBiometricUtils, getSensorId(),
+ getLogger(), getBiometricContext(), mAuthenticatorIds);
getLogger().logUnknownEnrollmentInHal();
@@ -145,7 +150,8 @@ public abstract class InternalCleanupClient<S extends BiometricAuthenticator.Ide
// Start enumeration. Removal will start if necessary, when enumeration is completed.
mCurrentTask = getEnumerateClient(getContext(), mLazyDaemon, getToken(), getTargetUserId(),
- getOwnerString(), mEnrolledList, mBiometricUtils, getSensorId());
+ getOwnerString(), mEnrolledList, mBiometricUtils, getSensorId(), getLogger(),
+ getBiometricContext());
Slog.d(TAG, "Starting enumerate: " + mCurrentTask);
mCurrentTask.start(mEnumerateCallback);
diff --git a/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java b/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java
index 5f97f3711a60..7f8f38f3e9d2 100644
--- a/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/InternalEnumerateClient.java
@@ -19,11 +19,12 @@ package com.android.server.biometrics.sensors;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.os.IBinder;
import android.util.Slog;
import com.android.server.biometrics.BiometricsProto;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import java.util.ArrayList;
import java.util.List;
@@ -47,12 +48,14 @@ public abstract class InternalEnumerateClient<T> extends HalClientMonitor<T>
protected InternalEnumerateClient(@NonNull Context context, @NonNull Supplier<T> lazyDaemon,
@NonNull IBinder token, int userId, @NonNull String owner,
@NonNull List<? extends BiometricAuthenticator.Identifier> enrolledList,
- @NonNull BiometricUtils utils, int sensorId, int statsModality) {
+ @NonNull BiometricUtils utils, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
// Internal enumerate does not need to send results to anyone. Cleanup (enumerate + remove)
// is all done internally.
super(context, lazyDaemon, token, null /* ClientMonitorCallbackConverter */, userId, owner,
- 0 /* cookie */, sensorId, statsModality, BiometricsProtoEnums.ACTION_ENUMERATE,
- BiometricsProtoEnums.CLIENT_UNKNOWN);
+ 0 /* cookie */, sensorId, logger, biometricContext);
+ //, BiometricsProtoEnums.ACTION_ENUMERATE,
+ // BiometricsProtoEnums.CLIENT_UNKNOWN);
mEnrolledList = enrolledList;
mUtils = utils;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/InvalidationClient.java b/services/core/java/com/android/server/biometrics/sensors/InvalidationClient.java
index 697d77cfbee6..d5aa5e2c9db6 100644
--- a/services/core/java/com/android/server/biometrics/sensors/InvalidationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/InvalidationClient.java
@@ -19,12 +19,13 @@ package com.android.server.biometrics.sensors;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.IInvalidationCallback;
import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.BiometricsProto;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import java.util.Map;
import java.util.function.Supplier;
@@ -42,12 +43,13 @@ public abstract class InvalidationClient<S extends BiometricAuthenticator.Identi
@NonNull private final IInvalidationCallback mInvalidationCallback;
public InvalidationClient(@NonNull Context context, @NonNull Supplier<T> lazyDaemon,
- int userId, int sensorId, @NonNull Map<Integer, Long> authenticatorIds,
+ int userId, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+ @NonNull Map<Integer, Long> authenticatorIds,
@NonNull IInvalidationCallback callback) {
super(context, lazyDaemon, null /* token */, null /* listener */, userId,
context.getOpPackageName(), 0 /* cookie */, sensorId,
- BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN,
- BiometricsProtoEnums.CLIENT_UNKNOWN);
+ logger, biometricContext);
mAuthenticatorIds = authenticatorIds;
mInvalidationCallback = callback;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/InvalidationRequesterClient.java b/services/core/java/com/android/server/biometrics/sensors/InvalidationRequesterClient.java
index b2661a28012d..1097bb7da684 100644
--- a/services/core/java/com/android/server/biometrics/sensors/InvalidationRequesterClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/InvalidationRequesterClient.java
@@ -20,10 +20,11 @@ import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricManager;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.IInvalidationCallback;
import com.android.server.biometrics.BiometricsProto;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
/**
* ClientMonitor subclass responsible for coordination of authenticatorId invalidation of other
@@ -74,11 +75,10 @@ public class InvalidationRequesterClient<S extends BiometricAuthenticator.Identi
};
public InvalidationRequesterClient(@NonNull Context context, int userId, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
@NonNull BiometricUtils<S> utils) {
super(context, null /* token */, null /* listener */, userId,
- context.getOpPackageName(), 0 /* cookie */, sensorId,
- BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN,
- BiometricsProtoEnums.CLIENT_UNKNOWN);
+ context.getOpPackageName(), 0 /* cookie */, sensorId, logger, biometricContext);
mBiometricManager = context.getSystemService(BiometricManager.class);
mUtils = utils;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java b/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java
index a0cef94fcf48..07ce841a7cac 100644
--- a/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/RemovalClient.java
@@ -19,12 +19,13 @@ package com.android.server.biometrics.sensors;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.BiometricsProto;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import java.util.Map;
import java.util.function.Supplier;
@@ -44,10 +45,12 @@ public abstract class RemovalClient<S extends BiometricAuthenticator.Identifier,
public RemovalClient(@NonNull Context context, @NonNull Supplier<T> lazyDaemon,
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener,
int userId, @NonNull String owner, @NonNull BiometricUtils<S> utils, int sensorId,
- @NonNull Map<Integer, Long> authenticatorIds, int statsModality) {
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+ @NonNull Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
- statsModality, BiometricsProtoEnums.ACTION_REMOVE,
- BiometricsProtoEnums.CLIENT_UNKNOWN);
+ logger, biometricContext);
+ //, BiometricsProtoEnums.ACTION_REMOVE,
+ // BiometricsProtoEnums.CLIENT_UNKNOWN);
mBiometricUtils = utils;
mAuthenticatorIds = authenticatorIds;
mHasEnrollmentsBeforeStarting = !utils.getBiometricsForUser(context, userId).isEmpty();
diff --git a/services/core/java/com/android/server/biometrics/sensors/RevokeChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/RevokeChallengeClient.java
index 7d8386337ece..88f4da261d62 100644
--- a/services/core/java/com/android/server/biometrics/sensors/RevokeChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/RevokeChallengeClient.java
@@ -18,20 +18,21 @@ package com.android.server.biometrics.sensors;
import android.annotation.NonNull;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.os.IBinder;
import com.android.server.biometrics.BiometricsProto;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import java.util.function.Supplier;
public abstract class RevokeChallengeClient<T> extends HalClientMonitor<T> {
public RevokeChallengeClient(@NonNull Context context, @NonNull Supplier<T> lazyDaemon,
- @NonNull IBinder token, int userId, @NonNull String owner, int sensorId) {
+ @NonNull IBinder token, int userId, @NonNull String owner, int sensorId,
+ @NonNull BiometricLogger biometricLogger, @NonNull BiometricContext biometricContext) {
super(context, lazyDaemon, token, null /* listener */, userId, owner,
- 0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN,
- BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
+ 0 /* cookie */, sensorId, biometricLogger, biometricContext);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/StartUserClient.java b/services/core/java/com/android/server/biometrics/sensors/StartUserClient.java
index 1bc3248cd0e7..21c9f64eea5b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/StartUserClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/StartUserClient.java
@@ -19,11 +19,12 @@ package com.android.server.biometrics.sensors;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.os.IBinder;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.biometrics.BiometricsProto;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import java.util.function.Supplier;
@@ -47,10 +48,10 @@ public abstract class StartUserClient<T, U> extends HalClientMonitor<T> {
public StartUserClient(@NonNull Context context, @NonNull Supplier<T> lazyDaemon,
@Nullable IBinder token, int userId, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
@NonNull UserStartedCallback<U> callback) {
super(context, lazyDaemon, token, null /* listener */, userId, context.getOpPackageName(),
- 0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN,
- BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
+ 0 /* cookie */, sensorId, logger, biometricContext);
mUserStartedCallback = callback;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/StopUserClient.java b/services/core/java/com/android/server/biometrics/sensors/StopUserClient.java
index 3eafbb8ea9d7..e8654dc059a4 100644
--- a/services/core/java/com/android/server/biometrics/sensors/StopUserClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/StopUserClient.java
@@ -19,11 +19,12 @@ package com.android.server.biometrics.sensors;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.os.IBinder;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.biometrics.BiometricsProto;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import java.util.function.Supplier;
@@ -47,10 +48,10 @@ public abstract class StopUserClient<T> extends HalClientMonitor<T> {
public StopUserClient(@NonNull Context context, @NonNull Supplier<T> lazyDaemon,
@Nullable IBinder token, int userId, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
@NonNull UserStoppedCallback callback) {
super(context, lazyDaemon, token, null /* listener */, userId, context.getOpPackageName(),
- 0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN,
- BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
+ 0 /* cookie */, sensorId, logger, biometricContext);
mUserStoppedCallback = callback;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/AidlSession.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/AidlSession.java
index 006667ac659f..29eee6b5bb06 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/AidlSession.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/AidlSession.java
@@ -16,11 +16,11 @@
package com.android.server.biometrics.sensors.face.aidl;
+import static com.android.server.biometrics.sensors.face.aidl.Sensor.HalSessionCallback;
+
import android.annotation.NonNull;
import android.hardware.biometrics.face.ISession;
-import static com.android.server.biometrics.sensors.face.aidl.Sensor.HalSessionCallback;
-
/**
* A holder for an AIDL {@link ISession} with additional metadata about the current user
* and the backend.
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
index c4e050215134..75a1e0cf21a8 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
@@ -25,7 +25,6 @@ import android.hardware.SensorPrivacyManager;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricFaceConstants;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.common.ICancellationSignal;
import android.hardware.biometrics.common.OperationContext;
import android.hardware.biometrics.common.OperationReason;
@@ -37,7 +36,10 @@ import android.os.RemoteException;
import android.util.Slog;
import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.biometrics.Utils;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.AuthenticationClient;
import com.android.server.biometrics.sensors.BiometricNotificationUtils;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
@@ -76,19 +78,36 @@ class FaceAuthenticationClient extends AuthenticationClient<AidlSession>
@NonNull IBinder token, long requestId,
@NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
boolean restricted, String owner, int cookie, boolean requireConfirmation, int sensorId,
- boolean isStrongBiometric, int statsClient, @NonNull UsageStats usageStats,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+ boolean isStrongBiometric, @NonNull UsageStats usageStats,
@NonNull LockoutCache lockoutCache, boolean allowBackgroundAuthentication,
boolean isKeyguardBypassEnabled) {
+ this(context, lazyDaemon, token, requestId, listener, targetUserId, operationId,
+ restricted, owner, cookie, requireConfirmation, sensorId, logger, biometricContext,
+ isStrongBiometric, usageStats, lockoutCache, allowBackgroundAuthentication,
+ isKeyguardBypassEnabled, context.getSystemService(SensorPrivacyManager.class));
+ }
+
+ @VisibleForTesting
+ FaceAuthenticationClient(@NonNull Context context,
+ @NonNull Supplier<AidlSession> lazyDaemon,
+ @NonNull IBinder token, long requestId,
+ @NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
+ boolean restricted, String owner, int cookie, boolean requireConfirmation, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+ boolean isStrongBiometric, @NonNull UsageStats usageStats,
+ @NonNull LockoutCache lockoutCache, boolean allowBackgroundAuthentication,
+ boolean isKeyguardBypassEnabled, SensorPrivacyManager sensorPrivacyManager) {
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
- owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
- BiometricsProtoEnums.MODALITY_FACE, statsClient, null /* taskStackListener */,
- lockoutCache, allowBackgroundAuthentication, true /* shouldVibrate */,
+ owner, cookie, requireConfirmation, sensorId, logger, biometricContext,
+ isStrongBiometric, null /* taskStackListener */, lockoutCache,
+ allowBackgroundAuthentication, true /* shouldVibrate */,
isKeyguardBypassEnabled);
setRequestId(requestId);
mUsageStats = usageStats;
mLockoutCache = lockoutCache;
mNotificationManager = context.getSystemService(NotificationManager.class);
- mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class);
+ mSensorPrivacyManager = sensorPrivacyManager;
final Resources resources = getContext().getResources();
mBiometricPromptIgnoreList = resources.getIntArray(
@@ -139,10 +158,10 @@ class FaceAuthenticationClient extends AuthenticationClient<AidlSession>
if (session.hasContextMethods()) {
final OperationContext context = new OperationContext();
- // TODO: add reason, id, and isAoD
+ // TODO: add reason, id
context.id = 0;
context.reason = OperationReason.UNKNOWN;
- context.isAoD = false;
+ context.isAoD = getBiometricContext().isAoD();
context.isCrypto = isCryptoOperation();
return session.getSession().authenticateWithContext(mOperationId, context);
} else {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java
index 3f3db4342a7a..c79e60124c45 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceDetectClient.java
@@ -21,7 +21,6 @@ import android.annotation.Nullable;
import android.content.Context;
import android.hardware.SensorPrivacyManager;
import android.hardware.biometrics.BiometricConstants;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.common.ICancellationSignal;
import android.hardware.biometrics.common.OperationContext;
import android.hardware.biometrics.common.OperationReason;
@@ -29,7 +28,10 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.server.biometrics.BiometricsProto;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.AcquisitionClient;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
@@ -52,13 +54,26 @@ public class FaceDetectClient extends AcquisitionClient<AidlSession> implements
FaceDetectClient(@NonNull Context context, @NonNull Supplier<AidlSession> lazyDaemon,
@NonNull IBinder token, long requestId,
@NonNull ClientMonitorCallbackConverter listener, int userId,
- @NonNull String owner, int sensorId, boolean isStrongBiometric, int statsClient) {
+ @NonNull String owner, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+ boolean isStrongBiometric) {
+ this(context, lazyDaemon, token, requestId, listener, userId, owner, sensorId,
+ logger, biometricContext, isStrongBiometric,
+ context.getSystemService(SensorPrivacyManager.class));
+ }
+
+ @VisibleForTesting
+ FaceDetectClient(@NonNull Context context, @NonNull Supplier<AidlSession> lazyDaemon,
+ @NonNull IBinder token, long requestId,
+ @NonNull ClientMonitorCallbackConverter listener, int userId,
+ @NonNull String owner, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+ boolean isStrongBiometric, SensorPrivacyManager sensorPrivacyManager) {
super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
- true /* shouldVibrate */, BiometricsProtoEnums.MODALITY_FACE,
- BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient);
+ true /* shouldVibrate */, logger, biometricContext);
setRequestId(requestId);
mIsStrongBiometric = isStrongBiometric;
- mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class);
+ mSensorPrivacyManager = sensorPrivacyManager;
}
@Override
@@ -102,10 +117,10 @@ public class FaceDetectClient extends AcquisitionClient<AidlSession> implements
if (session.hasContextMethods()) {
final OperationContext context = new OperationContext();
- // TODO: add reason, id, and isAoD
+ // TODO: add reason, id
context.id = 0;
context.reason = OperationReason.UNKNOWN;
- context.isAoD = false;
+ context.isAoD = getBiometricContext().isAoD();
context.isCrypto = isCryptoOperation();
return session.getSession().detectInteractionWithContext(context);
} else {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
index 8dc53b6346a4..6f6dadc8a041 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClient.java
@@ -20,7 +20,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.hardware.biometrics.BiometricFaceConstants;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.common.ICancellationSignal;
import android.hardware.biometrics.common.OperationContext;
import android.hardware.biometrics.common.OperationReason;
@@ -40,6 +39,8 @@ import android.view.Surface;
import com.android.internal.R;
import com.android.server.biometrics.HardwareAuthTokenUtils;
import com.android.server.biometrics.Utils;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.BiometricNotificationUtils;
import com.android.server.biometrics.sensors.BiometricUtils;
@@ -89,11 +90,11 @@ public class FaceEnrollClient extends EnrollClient<AidlSession> {
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
@NonNull byte[] hardwareAuthToken, @NonNull String opPackageName, long requestId,
@NonNull BiometricUtils<Face> utils, @NonNull int[] disabledFeatures, int timeoutSec,
- @Nullable Surface previewSurface, int sensorId, int maxTemplatesPerUser,
- boolean debugConsent) {
+ @Nullable Surface previewSurface, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+ int maxTemplatesPerUser, boolean debugConsent) {
super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, opPackageName, utils,
- timeoutSec, BiometricsProtoEnums.MODALITY_FACE, sensorId,
- false /* shouldVibrate */);
+ timeoutSec, sensorId, false /* shouldVibrate */, logger, biometricContext);
setRequestId(requestId);
mEnrollIgnoreList = getContext().getResources()
.getIntArray(R.array.config_face_acquire_enroll_ignorelist);
@@ -200,10 +201,10 @@ public class FaceEnrollClient extends EnrollClient<AidlSession> {
if (session.hasContextMethods()) {
final OperationContext context = new OperationContext();
- // TODO: add reason, id, and isAoD
+ // TODO: add reason, id
context.id = 0;
context.reason = OperationReason.UNKNOWN;
- context.isAoD = false;
+ context.isAoD = getBiometricContext().isAoD();
context.isCrypto = isCryptoOperation();
return session.getSession().enrollWithContext(
hat, EnrollmentType.DEFAULT, features, mHwPreviewHandle, context);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGenerateChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGenerateChallengeClient.java
index bdad268b9422..165c3a241043 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGenerateChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGenerateChallengeClient.java
@@ -23,6 +23,8 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.GenerateChallengeClient;
@@ -37,8 +39,10 @@ public class FaceGenerateChallengeClient extends GenerateChallengeClient<AidlSes
FaceGenerateChallengeClient(@NonNull Context context,
@NonNull Supplier<AidlSession> lazyDaemon, @NonNull IBinder token,
@NonNull ClientMonitorCallbackConverter listener, int userId, @NonNull String owner,
- int sensorId) {
- super(context, lazyDaemon, token, listener, userId, owner, sensorId);
+ int sensorId, @NonNull BiometricLogger logger,
+ @NonNull BiometricContext biometricContext) {
+ super(context, lazyDaemon, token, listener, userId, owner, sensorId, logger,
+ biometricContext);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGetAuthenticatorIdClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGetAuthenticatorIdClient.java
index 2f3187bb4fa0..1f4f6127dafd 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGetAuthenticatorIdClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGetAuthenticatorIdClient.java
@@ -18,11 +18,12 @@ package com.android.server.biometrics.sensors.face.aidl;
import android.annotation.NonNull;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.BiometricsProto;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.HalClientMonitor;
@@ -38,10 +39,10 @@ class FaceGetAuthenticatorIdClient extends HalClientMonitor<AidlSession> {
FaceGetAuthenticatorIdClient(@NonNull Context context,
@NonNull Supplier<AidlSession> lazyDaemon,
int userId, @NonNull String opPackageName, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, null /* token */, null /* listener */, userId, opPackageName,
- 0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_FACE,
- BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
+ 0 /* cookie */, sensorId, logger, biometricContext);
mAuthenticatorIds = authenticatorIds;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGetFeatureClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGetFeatureClient.java
index 79479bebc759..ef3b345402bf 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGetFeatureClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceGetFeatureClient.java
@@ -20,7 +20,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.hardware.biometrics.BiometricFaceConstants;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.IFace;
import android.os.IBinder;
import android.os.RemoteException;
@@ -28,6 +27,8 @@ import android.provider.Settings;
import android.util.Slog;
import com.android.server.biometrics.BiometricsProto;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.ErrorConsumer;
@@ -48,10 +49,10 @@ public class FaceGetFeatureClient extends HalClientMonitor<AidlSession> implemen
FaceGetFeatureClient(@NonNull Context context, @NonNull Supplier<AidlSession> lazyDaemon,
@NonNull IBinder token, @Nullable ClientMonitorCallbackConverter listener, int userId,
- @NonNull String owner, int sensorId) {
+ @NonNull String owner, int sensorId, @NonNull BiometricLogger logger,
+ @NonNull BiometricContext biometricContext) {
super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
- BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN,
- BiometricsProtoEnums.CLIENT_UNKNOWN);
+ logger, biometricContext);
mUserId = userId;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java
index a2b0339b282f..54f2033b363a 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalCleanupClient.java
@@ -18,11 +18,12 @@ package com.android.server.biometrics.sensors.face.aidl;
import android.annotation.NonNull;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.IFace;
import android.hardware.face.Face;
import android.os.IBinder;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.BiometricUtils;
import com.android.server.biometrics.sensors.InternalCleanupClient;
import com.android.server.biometrics.sensors.InternalEnumerateClient;
@@ -39,29 +40,32 @@ class FaceInternalCleanupClient extends InternalCleanupClient<Face, AidlSession>
FaceInternalCleanupClient(@NonNull Context context,
@NonNull Supplier<AidlSession> lazyDaemon, int userId, @NonNull String owner,
- int sensorId, @NonNull List<Face> enrolledList, @NonNull BiometricUtils<Face> utils,
- @NonNull Map<Integer, Long> authenticatorIds) {
- super(context, lazyDaemon, userId, owner, sensorId, BiometricsProtoEnums.MODALITY_FACE,
+ int sensorId, @NonNull BiometricLogger logger,
+ @NonNull BiometricContext biometricContext, @NonNull List<Face> enrolledList,
+ @NonNull BiometricUtils<Face> utils, @NonNull Map<Integer, Long> authenticatorIds) {
+ super(context, lazyDaemon, userId, owner, sensorId, logger, biometricContext,
enrolledList, utils, authenticatorIds);
}
@Override
protected InternalEnumerateClient<AidlSession> getEnumerateClient(Context context,
Supplier<AidlSession> lazyDaemon, IBinder token, int userId, String owner,
- List<Face> enrolledList, BiometricUtils<Face> utils, int sensorId) {
+ List<Face> enrolledList, BiometricUtils<Face> utils, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
return new FaceInternalEnumerateClient(context, lazyDaemon, token, userId, owner,
- enrolledList, utils, sensorId);
+ enrolledList, utils, sensorId, logger, biometricContext);
}
@Override
protected RemovalClient<Face, AidlSession> getRemovalClient(Context context,
Supplier<AidlSession> lazyDaemon, IBinder token,
int biometricId, int userId, String owner, BiometricUtils<Face> utils, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
Map<Integer, Long> authenticatorIds) {
// Internal remove does not need to send results to anyone. Cleanup (enumerate + remove)
// is all done internally.
return new FaceRemovalClient(context, lazyDaemon, token,
null /* ClientMonitorCallbackConverter */, new int[] {biometricId}, userId, owner,
- utils, sensorId, authenticatorIds);
+ utils, sensorId, logger, biometricContext, authenticatorIds);
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalEnumerateClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalEnumerateClient.java
index 88c9d3bd1035..d85455e0e76b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalEnumerateClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInternalEnumerateClient.java
@@ -18,13 +18,14 @@ package com.android.server.biometrics.sensors.face.aidl;
import android.annotation.NonNull;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.IFace;
import android.hardware.face.Face;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.BiometricUtils;
import com.android.server.biometrics.sensors.InternalEnumerateClient;
@@ -40,9 +41,10 @@ class FaceInternalEnumerateClient extends InternalEnumerateClient<AidlSession> {
FaceInternalEnumerateClient(@NonNull Context context,
@NonNull Supplier<AidlSession> lazyDaemon, @NonNull IBinder token, int userId,
@NonNull String owner, @NonNull List<Face> enrolledList,
- @NonNull BiometricUtils<Face> utils, int sensorId) {
+ @NonNull BiometricUtils<Face> utils, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
super(context, lazyDaemon, token, userId, owner, enrolledList, utils, sensorId,
- BiometricsProtoEnums.MODALITY_FACE);
+ logger, biometricContext);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInvalidationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInvalidationClient.java
index 04ea2cfc6eff..39d8de07f652 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInvalidationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceInvalidationClient.java
@@ -23,6 +23,8 @@ import android.hardware.face.Face;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.InvalidationClient;
import java.util.Map;
@@ -33,8 +35,10 @@ public class FaceInvalidationClient extends InvalidationClient<Face, AidlSession
public FaceInvalidationClient(@NonNull Context context,
@NonNull Supplier<AidlSession> lazyDaemon, int userId, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
@NonNull Map<Integer, Long> authenticatorIds, @NonNull IInvalidationCallback callback) {
- super(context, lazyDaemon, userId, sensorId, authenticatorIds, callback);
+ super(context, lazyDaemon, userId, sensorId, logger, biometricContext,
+ authenticatorIds, callback);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
index 9d7a5529f473..64b0892e92bb 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceProvider.java
@@ -23,6 +23,7 @@ import android.app.ActivityTaskManager;
import android.app.TaskStackListener;
import android.content.Context;
import android.content.pm.UserInfo;
+import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.ComponentInfoInternal;
import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.ITestSession;
@@ -47,6 +48,8 @@ import android.view.Surface;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.biometrics.Utils;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.AuthenticationClient;
import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
@@ -237,6 +240,9 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
final FaceGetAuthenticatorIdClient client = new FaceGetAuthenticatorIdClient(
mContext, mSensors.get(sensorId).getLazySession(), userId,
mContext.getOpPackageName(), sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(),
mSensors.get(sensorId).getAuthenticatorIds());
scheduleForSensor(sensorId, client);
@@ -247,6 +253,7 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
mHandler.post(() -> {
final InvalidationRequesterClient<Face> client =
new InvalidationRequesterClient<>(mContext, userId, sensorId,
+ BiometricLogger.ofUnknown(mContext), BiometricContext.getInstance(),
FaceUtils.getInstance(sensorId));
scheduleForSensor(sensorId, client);
});
@@ -285,6 +292,9 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
mHandler.post(() -> {
final FaceInvalidationClient client = new FaceInvalidationClient(mContext,
mSensors.get(sensorId).getLazySession(), userId, sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(),
mSensors.get(sensorId).getAuthenticatorIds(), callback);
scheduleForSensor(sensorId, client);
});
@@ -311,7 +321,10 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
mHandler.post(() -> {
final FaceGenerateChallengeClient client = new FaceGenerateChallengeClient(mContext,
mSensors.get(sensorId).getLazySession(), token,
- new ClientMonitorCallbackConverter(receiver), userId, opPackageName, sensorId);
+ new ClientMonitorCallbackConverter(receiver), userId, opPackageName, sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance());
scheduleForSensor(sensorId, client);
});
}
@@ -322,7 +335,9 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
mHandler.post(() -> {
final FaceRevokeChallengeClient client = new FaceRevokeChallengeClient(mContext,
mSensors.get(sensorId).getLazySession(), token, userId, opPackageName, sensorId,
- challenge);
+ createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(), challenge);
scheduleForSensor(sensorId, client);
});
}
@@ -340,8 +355,10 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
mSensors.get(sensorId).getLazySession(), token,
new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken,
opPackageName, id, FaceUtils.getInstance(sensorId), disabledFeatures,
- ENROLL_TIMEOUT_SEC, previewSurface, sensorId, maxTemplatesPerUser,
- debugConsent);
+ ENROLL_TIMEOUT_SEC, previewSurface, sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_ENROLL,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(), maxTemplatesPerUser, debugConsent);
scheduleForSensor(sensorId, client, new ClientMonitorCallback() {
@Override
public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
@@ -372,8 +389,9 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
final FaceDetectClient client = new FaceDetectClient(mContext,
mSensors.get(sensorId).getLazySession(),
- token, id, callback, userId, opPackageName,
- sensorId, isStrongBiometric, statsClient);
+ token, id, callback, userId, opPackageName, sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
+ BiometricContext.getInstance(), isStrongBiometric);
scheduleForSensor(sensorId, client);
});
@@ -396,7 +414,9 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
final FaceAuthenticationClient client = new FaceAuthenticationClient(
mContext, mSensors.get(sensorId).getLazySession(), token, requestId, callback,
userId, operationId, restricted, opPackageName, cookie,
- false /* requireConfirmation */, sensorId, isStrongBiometric, statsClient,
+ false /* requireConfirmation */, sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
+ BiometricContext.getInstance(), isStrongBiometric,
mUsageStats, mSensors.get(sensorId).getLockoutCache(),
allowBackgroundAuthentication, isKeyguardBypassEnabled);
scheduleForSensor(sensorId, client);
@@ -450,6 +470,9 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
mSensors.get(sensorId).getLazySession(), token,
new ClientMonitorCallbackConverter(receiver), faceIds, userId,
opPackageName, FaceUtils.getInstance(sensorId), sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_REMOVE,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(),
mSensors.get(sensorId).getAuthenticatorIds());
scheduleForSensor(sensorId, client);
});
@@ -460,7 +483,10 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
mHandler.post(() -> {
final FaceResetLockoutClient client = new FaceResetLockoutClient(
mContext, mSensors.get(sensorId).getLazySession(), userId,
- mContext.getOpPackageName(), sensorId, hardwareAuthToken,
+ mContext.getOpPackageName(), sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(), hardwareAuthToken,
mSensors.get(sensorId).getLockoutCache(), mLockoutResetDispatcher);
scheduleForSensor(sensorId, client);
@@ -481,7 +507,9 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
final FaceSetFeatureClient client = new FaceSetFeatureClient(mContext,
mSensors.get(sensorId).getLazySession(), token,
new ClientMonitorCallbackConverter(receiver), userId,
- mContext.getOpPackageName(), sensorId, feature, enabled, hardwareAuthToken);
+ mContext.getOpPackageName(), sensorId,
+ BiometricLogger.ofUnknown(mContext), BiometricContext.getInstance(),
+ feature, enabled, hardwareAuthToken);
scheduleForSensor(sensorId, client);
});
}
@@ -498,7 +526,8 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
}
final FaceGetFeatureClient client = new FaceGetFeatureClient(mContext,
mSensors.get(sensorId).getLazySession(), token, callback, userId,
- mContext.getOpPackageName(), sensorId);
+ mContext.getOpPackageName(), sensorId, BiometricLogger.ofUnknown(mContext),
+ BiometricContext.getInstance());
scheduleForSensor(sensorId, client);
});
}
@@ -518,13 +547,21 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
final FaceInternalCleanupClient client =
new FaceInternalCleanupClient(mContext,
mSensors.get(sensorId).getLazySession(), userId,
- mContext.getOpPackageName(), sensorId, enrolledList,
+ mContext.getOpPackageName(), sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_ENUMERATE,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(), enrolledList,
FaceUtils.getInstance(sensorId),
mSensors.get(sensorId).getAuthenticatorIds());
scheduleForSensor(sensorId, client, callback);
});
}
+ private BiometricLogger createLogger(int statsAction, int statsClient) {
+ return new BiometricLogger(mContext, BiometricsProtoEnums.MODALITY_FACE,
+ statsAction, statsClient);
+ }
+
@Override
public void dumpProtoState(int sensorId, @NonNull ProtoOutputStream proto,
boolean clearSchedulerBuffer) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceRemovalClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceRemovalClient.java
index 130a05a861d9..0512017394af 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceRemovalClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceRemovalClient.java
@@ -18,13 +18,14 @@ package com.android.server.biometrics.sensors.face.aidl;
import android.annotation.NonNull;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.IFace;
import android.hardware.face.Face;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.BiometricUtils;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.RemovalClient;
@@ -44,9 +45,10 @@ class FaceRemovalClient extends RemovalClient<Face, AidlSession> {
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener,
int[] biometricIds, int userId, @NonNull String owner,
@NonNull BiometricUtils<Face> utils, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
@NonNull Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, token, listener, userId, owner, utils, sensorId,
- authenticatorIds, BiometricsProtoEnums.MODALITY_FACE);
+ logger, biometricContext, authenticatorIds);
mBiometricIds = biometricIds;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceResetLockoutClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceResetLockoutClient.java
index 67bf3f5b2e4f..de0a36a32b66 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceResetLockoutClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceResetLockoutClient.java
@@ -18,7 +18,6 @@ package com.android.server.biometrics.sensors.face.aidl;
import android.annotation.NonNull;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.IFace;
import android.hardware.keymaster.HardwareAuthToken;
import android.os.RemoteException;
@@ -26,6 +25,8 @@ import android.util.Slog;
import com.android.server.biometrics.BiometricsProto;
import com.android.server.biometrics.HardwareAuthTokenUtils;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.ErrorConsumer;
import com.android.server.biometrics.sensors.HalClientMonitor;
@@ -50,11 +51,11 @@ public class FaceResetLockoutClient extends HalClientMonitor<AidlSession> implem
FaceResetLockoutClient(@NonNull Context context,
@NonNull Supplier<AidlSession> lazyDaemon, int userId, String owner, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
@NonNull byte[] hardwareAuthToken, @NonNull LockoutCache lockoutTracker,
@NonNull LockoutResetDispatcher lockoutResetDispatcher) {
super(context, lazyDaemon, null /* token */, null /* listener */, userId, owner,
- 0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN,
- BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
+ 0 /* cookie */, sensorId, logger, biometricContext);
mHardwareAuthToken = HardwareAuthTokenUtils.toHardwareAuthToken(hardwareAuthToken);
mLockoutCache = lockoutTracker;
mLockoutResetDispatcher = lockoutResetDispatcher;
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceRevokeChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceRevokeChallengeClient.java
index acd2e0589ccc..8838345de4d6 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceRevokeChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceRevokeChallengeClient.java
@@ -23,6 +23,8 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.RevokeChallengeClient;
import java.util.function.Supplier;
@@ -38,8 +40,10 @@ public class FaceRevokeChallengeClient extends RevokeChallengeClient<AidlSession
FaceRevokeChallengeClient(@NonNull Context context,
@NonNull Supplier<AidlSession> lazyDaemon, @NonNull IBinder token,
- int userId, @NonNull String owner, int sensorId, long challenge) {
- super(context, lazyDaemon, token, userId, owner, sensorId);
+ int userId, @NonNull String owner, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+ long challenge) {
+ super(context, lazyDaemon, token, userId, owner, sensorId, logger, biometricContext);
mChallenge = challenge;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceSetFeatureClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceSetFeatureClient.java
index 9d535a26e12d..6c143872ff8c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceSetFeatureClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceSetFeatureClient.java
@@ -18,7 +18,6 @@ package com.android.server.biometrics.sensors.face.aidl;
import android.annotation.NonNull;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.IFace;
import android.hardware.keymaster.HardwareAuthToken;
import android.os.IBinder;
@@ -27,6 +26,8 @@ import android.util.Slog;
import com.android.server.biometrics.BiometricsProto;
import com.android.server.biometrics.HardwareAuthTokenUtils;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.ErrorConsumer;
@@ -47,11 +48,11 @@ public class FaceSetFeatureClient extends HalClientMonitor<AidlSession> implemen
FaceSetFeatureClient(@NonNull Context context, @NonNull Supplier<AidlSession> lazyDaemon,
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
- @NonNull String owner, int sensorId, int feature, boolean enabled,
- byte[] hardwareAuthToken) {
+ @NonNull String owner, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+ int feature, boolean enabled, byte[] hardwareAuthToken) {
super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
- BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN,
- BiometricsProtoEnums.CLIENT_UNKNOWN);
+ logger, biometricContext);
mFeature = feature;
mEnabled = enabled;
mHardwareAuthToken = HardwareAuthTokenUtils.toHardwareAuthToken(hardwareAuthToken);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceStartUserClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceStartUserClient.java
index f5a98ff5881b..61e7ab781e66 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceStartUserClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceStartUserClient.java
@@ -27,6 +27,8 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.StartUserClient;
@@ -40,9 +42,10 @@ public class FaceStartUserClient extends StartUserClient<IFace, ISession> {
public FaceStartUserClient(@NonNull Context context,
@NonNull Supplier<IFace> lazyDaemon,
@Nullable IBinder token, int userId, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
@NonNull ISessionCallback sessionCallback,
@NonNull UserStartedCallback<ISession> callback) {
- super(context, lazyDaemon, token, userId, sensorId, callback);
+ super(context, lazyDaemon, token, userId, sensorId, logger, biometricContext, callback);
mSessionCallback = sessionCallback;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceStopUserClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceStopUserClient.java
index 48b4856fa4b6..0110ae991ae4 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceStopUserClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceStopUserClient.java
@@ -23,6 +23,8 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.StopUserClient;
@@ -33,8 +35,9 @@ public class FaceStopUserClient extends StopUserClient<AidlSession> {
public FaceStopUserClient(@NonNull Context context, @NonNull Supplier<AidlSession> lazyDaemon,
@Nullable IBinder token, int userId, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
@NonNull UserStoppedCallback callback) {
- super(context, lazyDaemon, token, userId, sensorId, callback);
+ super(context, lazyDaemon, token, userId, sensorId, logger, biometricContext, callback);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
index 33e6fa4ebf93..fa07d120eb71 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/Sensor.java
@@ -42,12 +42,15 @@ import android.os.UserManager;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.biometrics.HardwareAuthTokenUtils;
import com.android.server.biometrics.SensorServiceStateProto;
import com.android.server.biometrics.SensorStateProto;
import com.android.server.biometrics.UserStateProto;
import com.android.server.biometrics.Utils;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.AuthenticationConsumer;
import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.BiometricScheduler;
@@ -88,7 +91,8 @@ public class Sensor {
@NonNull private final Supplier<AidlSession> mLazySession;
@Nullable private AidlSession mCurrentSession;
- static class HalSessionCallback extends ISessionCallback.Stub {
+ @VisibleForTesting
+ public static class HalSessionCallback extends ISessionCallback.Stub {
/**
* Interface to sends results to the HalSessionCallback's owner.
*/
@@ -487,7 +491,9 @@ public class Sensor {
@Override
public StopUserClient<?> getStopUserClient(int userId) {
return new FaceStopUserClient(mContext, mLazySession, mToken, userId,
- mSensorProperties.sensorId, () -> mCurrentSession = null);
+ mSensorProperties.sensorId,
+ BiometricLogger.ofUnknown(mContext), BiometricContext.getInstance(),
+ () -> mCurrentSession = null);
}
@NonNull
@@ -523,6 +529,7 @@ public class Sensor {
return new FaceStartUserClient(mContext, provider::getHalInstance,
mToken, newUserId, mSensorProperties.sensorId,
+ BiometricLogger.ofUnknown(mContext), BiometricContext.getInstance(),
resultController, userStartedCallback);
}
});
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
index 586abe2d6298..be1ed7d92aeb 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/Face10.java
@@ -55,6 +55,8 @@ import com.android.server.biometrics.SensorServiceStateProto;
import com.android.server.biometrics.SensorStateProto;
import com.android.server.biometrics.UserStateProto;
import com.android.server.biometrics.Utils;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.AcquisitionClient;
import com.android.server.biometrics.sensors.AuthenticationConsumer;
import com.android.server.biometrics.sensors.BaseClientMonitor;
@@ -533,7 +535,10 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
final FaceGenerateChallengeClient client = new FaceGenerateChallengeClient(mContext,
mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver), userId,
- opPackageName, mSensorId, sSystemClock.millis());
+ opPackageName, mSensorId,
+ createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(), sSystemClock.millis());
mGeneratedChallengeCache = client;
mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() {
@Override
@@ -562,7 +567,10 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
mGeneratedChallengeCache = null;
final FaceRevokeChallengeClient client = new FaceRevokeChallengeClient(mContext,
- mLazyDaemon, token, userId, opPackageName, mSensorId);
+ mLazyDaemon, token, userId, opPackageName, mSensorId,
+ createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance());
mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() {
@Override
public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
@@ -590,7 +598,10 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
final FaceEnrollClient client = new FaceEnrollClient(mContext, mLazyDaemon, token,
new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken,
opPackageName, id, FaceUtils.getLegacyInstance(mSensorId), disabledFeatures,
- ENROLL_TIMEOUT_SEC, previewSurface, mSensorId);
+ ENROLL_TIMEOUT_SEC, previewSurface, mSensorId,
+ createLogger(BiometricsProtoEnums.ACTION_ENROLL,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance());
mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() {
@Override
@@ -637,7 +648,8 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
final FaceAuthenticationClient client = new FaceAuthenticationClient(mContext,
mLazyDaemon, token, requestId, receiver, userId, operationId, restricted,
opPackageName, cookie, false /* requireConfirmation */, mSensorId,
- isStrongBiometric, statsClient, mLockoutTracker, mUsageStats,
+ createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
+ BiometricContext.getInstance(), isStrongBiometric, mLockoutTracker, mUsageStats,
allowBackgroundAuthentication, isKeyguardBypassEnabled);
mScheduler.scheduleClientMonitor(client);
});
@@ -670,7 +682,10 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
final FaceRemovalClient client = new FaceRemovalClient(mContext, mLazyDaemon, token,
new ClientMonitorCallbackConverter(receiver), faceId, userId, opPackageName,
- FaceUtils.getLegacyInstance(mSensorId), mSensorId, mAuthenticatorIds);
+ FaceUtils.getLegacyInstance(mSensorId), mSensorId,
+ createLogger(BiometricsProtoEnums.ACTION_REMOVE,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(), mAuthenticatorIds);
mScheduler.scheduleClientMonitor(client);
});
}
@@ -685,7 +700,10 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
final FaceRemovalClient client = new FaceRemovalClient(mContext, mLazyDaemon, token,
new ClientMonitorCallbackConverter(receiver), 0 /* faceId */, userId,
opPackageName,
- FaceUtils.getLegacyInstance(mSensorId), mSensorId, mAuthenticatorIds);
+ FaceUtils.getLegacyInstance(mSensorId), mSensorId,
+ createLogger(BiometricsProtoEnums.ACTION_REMOVE,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(), mAuthenticatorIds);
mScheduler.scheduleClientMonitor(client);
});
}
@@ -702,7 +720,9 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
final FaceResetLockoutClient client = new FaceResetLockoutClient(mContext,
mLazyDaemon, userId, mContext.getOpPackageName(), mSensorId,
- hardwareAuthToken);
+ createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(), hardwareAuthToken);
mScheduler.scheduleClientMonitor(client);
});
}
@@ -723,7 +743,8 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
final int faceId = faces.get(0).getBiometricId();
final FaceSetFeatureClient client = new FaceSetFeatureClient(mContext,
mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver), userId,
- opPackageName, mSensorId, feature, enabled, hardwareAuthToken, faceId);
+ opPackageName, mSensorId, BiometricLogger.ofUnknown(mContext),
+ BiometricContext.getInstance(), feature, enabled, hardwareAuthToken, faceId);
mScheduler.scheduleClientMonitor(client);
});
}
@@ -742,7 +763,9 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
final int faceId = faces.get(0).getBiometricId();
final FaceGetFeatureClient client = new FaceGetFeatureClient(mContext, mLazyDaemon,
- token, listener, userId, opPackageName, mSensorId, feature, faceId);
+ token, listener, userId, opPackageName, mSensorId,
+ BiometricLogger.ofUnknown(mContext), BiometricContext.getInstance(),
+ feature, faceId);
mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() {
@Override
public void onClientFinished(
@@ -767,7 +790,10 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
final List<Face> enrolledList = getEnrolledFaces(mSensorId, userId);
final FaceInternalCleanupClient client = new FaceInternalCleanupClient(mContext,
- mLazyDaemon, userId, mContext.getOpPackageName(), mSensorId, enrolledList,
+ mLazyDaemon, userId, mContext.getOpPackageName(), mSensorId,
+ createLogger(BiometricsProtoEnums.ACTION_ENUMERATE,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(), enrolledList,
FaceUtils.getLegacyInstance(mSensorId), mAuthenticatorIds);
mScheduler.scheduleClientMonitor(client, callback);
});
@@ -890,7 +916,9 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
final boolean hasEnrolled = !getEnrolledFaces(mSensorId, targetUserId).isEmpty();
final FaceUpdateActiveUserClient client = new FaceUpdateActiveUserClient(mContext,
mLazyDaemon, targetUserId, mContext.getOpPackageName(), mSensorId,
- hasEnrolled, mAuthenticatorIds);
+ createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(), hasEnrolled, mAuthenticatorIds);
mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() {
@Override
public void onClientFinished(@NonNull BaseClientMonitor clientMonitor,
@@ -904,6 +932,11 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
});
}
+ private BiometricLogger createLogger(int statsAction, int statsClient) {
+ return new BiometricLogger(mContext, BiometricsProtoEnums.MODALITY_FACE,
+ statsAction, statsClient);
+ }
+
/**
* Sends a debug message to the HAL with the provided FileDescriptor and arguments.
*/
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
index 9038435c1021..8d76e9f031f7 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceAuthenticationClient.java
@@ -23,7 +23,6 @@ import android.hardware.SensorPrivacyManager;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricFaceConstants;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
import android.hardware.face.FaceManager;
import android.os.IBinder;
@@ -32,6 +31,8 @@ import android.util.Slog;
import com.android.internal.R;
import com.android.server.biometrics.Utils;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.AuthenticationClient;
import com.android.server.biometrics.sensors.BiometricNotificationUtils;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
@@ -66,12 +67,13 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> {
@NonNull IBinder token, long requestId,
@NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
boolean restricted, String owner, int cookie, boolean requireConfirmation, int sensorId,
- boolean isStrongBiometric, int statsClient, @NonNull LockoutTracker lockoutTracker,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+ boolean isStrongBiometric, @NonNull LockoutTracker lockoutTracker,
@NonNull UsageStats usageStats, boolean allowBackgroundAuthentication,
boolean isKeyguardBypassEnabled) {
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
- owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
- BiometricsProtoEnums.MODALITY_FACE, statsClient, null /* taskStackListener */,
+ owner, cookie, requireConfirmation, sensorId, logger, biometricContext,
+ isStrongBiometric, null /* taskStackListener */,
lockoutTracker, allowBackgroundAuthentication, true /* shouldVibrate */,
isKeyguardBypassEnabled);
setRequestId(requestId);
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java
index 92f7253779ed..226e458ad07b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceEnrollClient.java
@@ -20,7 +20,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.hardware.biometrics.BiometricFaceConstants;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
import android.hardware.biometrics.face.V1_0.Status;
import android.hardware.face.Face;
@@ -32,6 +31,8 @@ import android.view.Surface;
import com.android.internal.R;
import com.android.server.biometrics.Utils;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.BiometricUtils;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
@@ -58,10 +59,10 @@ public class FaceEnrollClient extends EnrollClient<IBiometricsFace> {
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
@NonNull byte[] hardwareAuthToken, @NonNull String owner, long requestId,
@NonNull BiometricUtils<Face> utils, @NonNull int[] disabledFeatures, int timeoutSec,
- @Nullable Surface previewSurface, int sensorId) {
+ @Nullable Surface previewSurface, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils,
- timeoutSec, BiometricsProtoEnums.MODALITY_FACE, sensorId,
- false /* shouldVibrate */);
+ timeoutSec, sensorId, false /* shouldVibrate */, logger, biometricContext);
setRequestId(requestId);
mDisabledFeatures = Arrays.copyOf(disabledFeatures, disabledFeatures.length);
mEnrollIgnoreList = getContext().getResources()
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGenerateChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGenerateChallengeClient.java
index b66ad608b4ca..97838a70cbd1 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGenerateChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGenerateChallengeClient.java
@@ -25,6 +25,8 @@ import android.os.RemoteException;
import android.util.Slog;
import com.android.internal.util.Preconditions;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.GenerateChallengeClient;
@@ -51,8 +53,10 @@ public class FaceGenerateChallengeClient extends GenerateChallengeClient<IBiomet
FaceGenerateChallengeClient(@NonNull Context context,
@NonNull Supplier<IBiometricsFace> lazyDaemon, @NonNull IBinder token,
@NonNull ClientMonitorCallbackConverter listener, int userId, @NonNull String owner,
- int sensorId, long now) {
- super(context, lazyDaemon, token, listener, userId, owner, sensorId);
+ int sensorId, @NonNull BiometricLogger logger,
+ @NonNull BiometricContext biometricContext, long now) {
+ super(context, lazyDaemon, token, listener, userId, owner, sensorId, logger,
+ biometricContext);
mCreatedAt = now;
mWaiting = new ArrayList<>();
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGetFeatureClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGetFeatureClient.java
index 1b387bf7879a..981253699322 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGetFeatureClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceGetFeatureClient.java
@@ -19,7 +19,6 @@ package com.android.server.biometrics.sensors.face.hidl;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
import android.hardware.biometrics.face.V1_0.OptionalBool;
import android.hardware.biometrics.face.V1_0.Status;
@@ -28,6 +27,8 @@ import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.BiometricsProto;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.HalClientMonitor;
@@ -48,13 +49,13 @@ public class FaceGetFeatureClient extends HalClientMonitor<IBiometricsFace> {
FaceGetFeatureClient(@NonNull Context context, @NonNull Supplier<IBiometricsFace> lazyDaemon,
@NonNull IBinder token, @Nullable ClientMonitorCallbackConverter listener, int userId,
- @NonNull String owner, int sensorId, int feature, int faceId) {
+ @NonNull String owner, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+ int feature, int faceId) {
super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
- BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN,
- BiometricsProtoEnums.CLIENT_UNKNOWN);
+ logger, biometricContext);
mFeature = feature;
mFaceId = faceId;
-
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalCleanupClient.java
index 93a2913fbfa1..d21a7501e516 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalCleanupClient.java
@@ -18,11 +18,12 @@ package com.android.server.biometrics.sensors.face.hidl;
import android.annotation.NonNull;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
import android.hardware.face.Face;
import android.os.IBinder;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.BiometricUtils;
import com.android.server.biometrics.sensors.InternalCleanupClient;
import com.android.server.biometrics.sensors.InternalEnumerateClient;
@@ -40,29 +41,32 @@ class FaceInternalCleanupClient extends InternalCleanupClient<Face, IBiometricsF
FaceInternalCleanupClient(@NonNull Context context,
@NonNull Supplier<IBiometricsFace> lazyDaemon, int userId, @NonNull String owner,
- int sensorId, @NonNull List<Face> enrolledList, @NonNull BiometricUtils<Face> utils,
- @NonNull Map<Integer, Long> authenticatorIds) {
- super(context, lazyDaemon, userId, owner, sensorId, BiometricsProtoEnums.MODALITY_FACE,
+ int sensorId, @NonNull BiometricLogger logger,
+ @NonNull BiometricContext biometricContext, @NonNull List<Face> enrolledList,
+ @NonNull BiometricUtils<Face> utils, @NonNull Map<Integer, Long> authenticatorIds) {
+ super(context, lazyDaemon, userId, owner, sensorId, logger, biometricContext,
enrolledList, utils, authenticatorIds);
}
@Override
protected InternalEnumerateClient<IBiometricsFace> getEnumerateClient(Context context,
Supplier<IBiometricsFace> lazyDaemon, IBinder token, int userId, String owner,
- List<Face> enrolledList, BiometricUtils<Face> utils, int sensorId) {
+ List<Face> enrolledList, BiometricUtils<Face> utils, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
return new FaceInternalEnumerateClient(context, lazyDaemon, token, userId, owner,
- enrolledList, utils, sensorId);
+ enrolledList, utils, sensorId, logger, biometricContext);
}
@Override
protected RemovalClient<Face, IBiometricsFace> getRemovalClient(Context context,
Supplier<IBiometricsFace> lazyDaemon, IBinder token,
int biometricId, int userId, String owner, BiometricUtils<Face> utils, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
Map<Integer, Long> authenticatorIds) {
// Internal remove does not need to send results to anyone. Cleanup (enumerate + remove)
// is all done internally.
return new FaceRemovalClient(context, lazyDaemon, token,
null /* ClientMonitorCallbackConverter */, biometricId, userId, owner, utils,
- sensorId, authenticatorIds);
+ sensorId, logger, biometricContext, authenticatorIds);
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalEnumerateClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalEnumerateClient.java
index f1788de38565..250dd7e0cdef 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalEnumerateClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceInternalEnumerateClient.java
@@ -18,13 +18,14 @@ package com.android.server.biometrics.sensors.face.hidl;
import android.annotation.NonNull;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
import android.hardware.face.Face;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.BiometricUtils;
import com.android.server.biometrics.sensors.InternalEnumerateClient;
@@ -41,9 +42,10 @@ class FaceInternalEnumerateClient extends InternalEnumerateClient<IBiometricsFac
FaceInternalEnumerateClient(@NonNull Context context,
@NonNull Supplier<IBiometricsFace> lazyDaemon, @NonNull IBinder token, int userId,
@NonNull String owner, @NonNull List<Face> enrolledList,
- @NonNull BiometricUtils<Face> utils, int sensorId) {
+ @NonNull BiometricUtils<Face> utils, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
super(context, lazyDaemon, token, userId, owner, enrolledList, utils, sensorId,
- BiometricsProtoEnums.MODALITY_FACE);
+ logger, biometricContext);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceRemovalClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceRemovalClient.java
index cbc23e49f4d8..0ee7a354d5a4 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceRemovalClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceRemovalClient.java
@@ -18,13 +18,14 @@ package com.android.server.biometrics.sensors.face.hidl;
import android.annotation.NonNull;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
import android.hardware.face.Face;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.BiometricUtils;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.RemovalClient;
@@ -44,9 +45,11 @@ class FaceRemovalClient extends RemovalClient<Face, IBiometricsFace> {
FaceRemovalClient(@NonNull Context context, @NonNull Supplier<IBiometricsFace> lazyDaemon,
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener,
int biometricId, int userId, @NonNull String owner, @NonNull BiometricUtils<Face> utils,
- int sensorId, @NonNull Map<Integer, Long> authenticatorIds) {
- super(context, lazyDaemon, token, listener, userId, owner, utils, sensorId,
- authenticatorIds, BiometricsProtoEnums.MODALITY_FACE);
+ int sensorId, @NonNull BiometricLogger logger,
+ @NonNull BiometricContext biometricContext,
+ @NonNull Map<Integer, Long> authenticatorIds) {
+ super(context, lazyDaemon, token, listener, userId, owner, utils, sensorId, logger,
+ biometricContext, authenticatorIds);
mBiometricId = biometricId;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceResetLockoutClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceResetLockoutClient.java
index 88e2318b0570..6e74d3622c1a 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceResetLockoutClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceResetLockoutClient.java
@@ -18,12 +18,13 @@ package com.android.server.biometrics.sensors.face.hidl;
import android.annotation.NonNull;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.BiometricsProto;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.HalClientMonitor;
@@ -42,10 +43,10 @@ public class FaceResetLockoutClient extends HalClientMonitor<IBiometricsFace> {
FaceResetLockoutClient(@NonNull Context context,
@NonNull Supplier<IBiometricsFace> lazyDaemon, int userId, String owner, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
@NonNull byte[] hardwareAuthToken) {
super(context, lazyDaemon, null /* token */, null /* listener */, userId, owner,
- 0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN,
- BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
+ 0 /* cookie */, sensorId, logger, biometricContext);
mHardwareAuthToken = new ArrayList<>();
for (byte b : hardwareAuthToken) {
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceRevokeChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceRevokeChallengeClient.java
index ab8d16145fab..b7b0dc046633 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceRevokeChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceRevokeChallengeClient.java
@@ -23,6 +23,8 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.RevokeChallengeClient;
import java.util.function.Supplier;
@@ -37,8 +39,9 @@ public class FaceRevokeChallengeClient extends RevokeChallengeClient<IBiometrics
FaceRevokeChallengeClient(@NonNull Context context,
@NonNull Supplier<IBiometricsFace> lazyDaemon, @NonNull IBinder token,
- int userId, @NonNull String owner, int sensorId) {
- super(context, lazyDaemon, token, userId, owner, sensorId);
+ int userId, @NonNull String owner, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
+ super(context, lazyDaemon, token, userId, owner, sensorId, logger, biometricContext);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceSetFeatureClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceSetFeatureClient.java
index b2b52e713ec9..3c82f9c73700 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceSetFeatureClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceSetFeatureClient.java
@@ -18,7 +18,6 @@ package com.android.server.biometrics.sensors.face.hidl;
import android.annotation.NonNull;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
import android.hardware.biometrics.face.V1_0.Status;
import android.os.IBinder;
@@ -26,6 +25,8 @@ import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.BiometricsProto;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.HalClientMonitor;
@@ -48,11 +49,11 @@ public class FaceSetFeatureClient extends HalClientMonitor<IBiometricsFace> {
FaceSetFeatureClient(@NonNull Context context, @NonNull Supplier<IBiometricsFace> lazyDaemon,
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
- @NonNull String owner, int sensorId, int feature, boolean enabled,
- byte[] hardwareAuthToken, int faceId) {
+ @NonNull String owner, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+ int feature, boolean enabled, byte[] hardwareAuthToken, int faceId) {
super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
- BiometricsProtoEnums.MODALITY_UNKNOWN, BiometricsProtoEnums.ACTION_UNKNOWN,
- BiometricsProtoEnums.CLIENT_UNKNOWN);
+ logger, biometricContext);
mFeature = feature;
mEnabled = enabled;
mFaceId = faceId;
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceUpdateActiveUserClient.java b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceUpdateActiveUserClient.java
index 04b93274e42b..8385c3fa7103 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceUpdateActiveUserClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/hidl/FaceUpdateActiveUserClient.java
@@ -18,13 +18,14 @@ package com.android.server.biometrics.sensors.face.hidl;
import android.annotation.NonNull;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.face.V1_0.IBiometricsFace;
import android.os.Environment;
import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.BiometricsProto;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.HalClientMonitor;
@@ -41,11 +42,11 @@ public class FaceUpdateActiveUserClient extends HalClientMonitor<IBiometricsFace
FaceUpdateActiveUserClient(@NonNull Context context,
@NonNull Supplier<IBiometricsFace> lazyDaemon, int userId, @NonNull String owner,
- int sensorId, boolean hasEnrolledBiometrics,
+ int sensorId, @NonNull BiometricLogger logger,
+ @NonNull BiometricContext biometricContext, boolean hasEnrolledBiometrics,
@NonNull Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, null /* token */, null /* listener */, userId, owner,
- 0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN,
- BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
+ 0 /* cookie */, sensorId, logger, biometricContext);
mHasEnrolledBiometrics = hasEnrolledBiometrics;
mAuthenticatorIds = authenticatorIds;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlSession.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlSession.java
index 727101a69b06..55861bb4cc6f 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlSession.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/AidlSession.java
@@ -16,11 +16,11 @@
package com.android.server.biometrics.sensors.fingerprint.aidl;
+import static com.android.server.biometrics.sensors.fingerprint.aidl.Sensor.HalSessionCallback;
+
import android.annotation.NonNull;
import android.hardware.biometrics.fingerprint.ISession;
-import static com.android.server.biometrics.sensors.fingerprint.aidl.Sensor.HalSessionCallback;
-
/**
* A holder for an AIDL {@link ISession} with additional metadata about the current user
* and the backend.
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
index 2c1c80ccabb3..184e1ea7d003 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClient.java
@@ -23,9 +23,7 @@ import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricFingerprintConstants;
import android.hardware.biometrics.BiometricFingerprintConstants.FingerprintAcquired;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.common.ICancellationSignal;
-import android.hardware.biometrics.common.OperationContext;
import android.hardware.biometrics.common.OperationReason;
import android.hardware.biometrics.fingerprint.PointerContext;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
@@ -35,6 +33,8 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.log.CallbackWithProbe;
import com.android.server.biometrics.log.Probe;
import com.android.server.biometrics.sensors.AuthenticationClient;
@@ -72,15 +72,18 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession>
@NonNull IBinder token, long requestId,
@NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
boolean restricted, @NonNull String owner, int cookie, boolean requireConfirmation,
- int sensorId, boolean isStrongBiometric, int statsClient,
+ int sensorId,
+ @NonNull BiometricLogger biometricLogger, @NonNull BiometricContext biometricContext,
+ boolean isStrongBiometric,
@Nullable TaskStackListener taskStackListener, @NonNull LockoutCache lockoutCache,
@Nullable IUdfpsOverlayController udfpsOverlayController,
@Nullable ISidefpsController sidefpsController,
boolean allowBackgroundAuthentication,
@NonNull FingerprintSensorPropertiesInternal sensorProps) {
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted, owner,
- cookie, requireConfirmation, sensorId, isStrongBiometric,
- BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener,
+ cookie, requireConfirmation, sensorId,
+ biometricLogger, biometricContext,
+ isStrongBiometric, taskStackListener,
lockoutCache, allowBackgroundAuthentication, true /* shouldVibrate */,
false /* isKeyguardBypassEnabled */);
setRequestId(requestId);
@@ -175,13 +178,12 @@ class FingerprintAuthenticationClient extends AuthenticationClient<AidlSession>
final AidlSession session = getFreshDaemon();
if (session.hasContextMethods()) {
- final OperationContext context = new OperationContext();
- // TODO: add reason, id, and isAoD
- context.id = 0;
- context.reason = OperationReason.UNKNOWN;
- context.isAoD = false;
- context.isCrypto = isCryptoOperation();
- return session.getSession().authenticateWithContext(mOperationId, context);
+ // TODO: add reason, id
+ mOperationContext.id = 0;
+ mOperationContext.reason = OperationReason.UNKNOWN;
+ mOperationContext.isAoD = getBiometricContext().isAoD();
+ mOperationContext.isCrypto = isCryptoOperation();
+ return session.getSession().authenticateWithContext(mOperationId, mOperationContext);
} else {
return session.getSession().authenticate(mOperationId);
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
index 6645332c1fac..9d348e118b46 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClient.java
@@ -20,7 +20,6 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.hardware.biometrics.BiometricOverlayConstants;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.common.ICancellationSignal;
import android.hardware.biometrics.common.OperationContext;
import android.hardware.biometrics.common.OperationReason;
@@ -30,6 +29,8 @@ import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.BiometricsProto;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.AcquisitionClient;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
@@ -54,11 +55,10 @@ class FingerprintDetectClient extends AcquisitionClient<AidlSession> implements
@NonNull IBinder token, long requestId,
@NonNull ClientMonitorCallbackConverter listener, int userId,
@NonNull String owner, int sensorId,
- @Nullable IUdfpsOverlayController udfpsOverlayController, boolean isStrongBiometric,
- int statsClient) {
+ @NonNull BiometricLogger biometricLogger, @NonNull BiometricContext biometricContext,
+ @Nullable IUdfpsOverlayController udfpsOverlayController, boolean isStrongBiometric) {
super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
- true /* shouldVibrate */, BiometricsProtoEnums.MODALITY_FINGERPRINT,
- BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient);
+ true /* shouldVibrate */, biometricLogger, biometricContext);
setRequestId(requestId);
mIsStrongBiometric = isStrongBiometric;
mSensorOverlays = new SensorOverlays(udfpsOverlayController, null /* sideFpsController*/);
@@ -100,10 +100,10 @@ class FingerprintDetectClient extends AcquisitionClient<AidlSession> implements
if (session.hasContextMethods()) {
final OperationContext context = new OperationContext();
- // TODO: add reason, id, and isAoD
+ // TODO: add reason, id
context.id = 0;
context.reason = OperationReason.UNKNOWN;
- context.isAoD = false;
+ context.isAoD = getBiometricContext().isAoD();
context.isCrypto = isCryptoOperation();
return session.getSession().detectInteractionWithContext(context);
} else {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
index d0c5bb8851e6..ed16a6dd3b5c 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClient.java
@@ -22,7 +22,6 @@ import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricFingerprintConstants;
import android.hardware.biometrics.BiometricFingerprintConstants.FingerprintAcquired;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.common.ICancellationSignal;
import android.hardware.biometrics.common.OperationContext;
import android.hardware.biometrics.common.OperationReason;
@@ -38,6 +37,8 @@ import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.HardwareAuthTokenUtils;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.BiometricNotificationUtils;
import com.android.server.biometrics.sensors.BiometricUtils;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
@@ -68,14 +69,15 @@ class FingerprintEnrollClient extends EnrollClient<AidlSession> implements Udfps
@NonNull ClientMonitorCallbackConverter listener, int userId,
@NonNull byte[] hardwareAuthToken, @NonNull String owner,
@NonNull BiometricUtils<Fingerprint> utils, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
@NonNull FingerprintSensorPropertiesInternal sensorProps,
@Nullable IUdfpsOverlayController udfpsOverlayController,
@Nullable ISidefpsController sidefpsController,
int maxTemplatesPerUser, @FingerprintManager.EnrollReason int enrollReason) {
// UDFPS haptics occur when an image is acquired (instead of when the result is known)
super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils,
- 0 /* timeoutSec */, BiometricsProtoEnums.MODALITY_FINGERPRINT, sensorId,
- !sensorProps.isAnyUdfpsType() /* shouldVibrate */);
+ 0 /* timeoutSec */, sensorId,
+ !sensorProps.isAnyUdfpsType() /* shouldVibrate */, logger, biometricContext);
setRequestId(requestId);
mSensorProps = sensorProps;
mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
@@ -177,10 +179,10 @@ class FingerprintEnrollClient extends EnrollClient<AidlSession> implements Udfps
if (session.hasContextMethods()) {
final OperationContext context = new OperationContext();
- // TODO: add reason, id, and isAoD
+ // TODO: add reason, id
context.id = 0;
context.reason = OperationReason.UNKNOWN;
- context.isAoD = false;
+ context.isAoD = getBiometricContext().isAoD();
context.isCrypto = isCryptoOperation();
return session.getSession().enrollWithContext(hat, context);
} else {
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGenerateChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGenerateChallengeClient.java
index 04a7ca086ced..ddae8bedf7c1 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGenerateChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGenerateChallengeClient.java
@@ -23,6 +23,8 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.GenerateChallengeClient;
@@ -38,8 +40,10 @@ class FingerprintGenerateChallengeClient extends GenerateChallengeClient<AidlSes
@NonNull Supplier<AidlSession> lazyDaemon,
@NonNull IBinder token,
@NonNull ClientMonitorCallbackConverter listener,
- int userId, @NonNull String owner, int sensorId) {
- super(context, lazyDaemon, token, listener, userId, owner, sensorId);
+ int userId, @NonNull String owner, int sensorId,
+ @NonNull BiometricLogger biometricLogger, @NonNull BiometricContext biometricContext) {
+ super(context, lazyDaemon, token, listener, userId, owner, sensorId,
+ biometricLogger, biometricContext);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGetAuthenticatorIdClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGetAuthenticatorIdClient.java
index 3a487fc98ca4..ea1a622c36ab 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGetAuthenticatorIdClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintGetAuthenticatorIdClient.java
@@ -18,11 +18,12 @@ package com.android.server.biometrics.sensors.fingerprint.aidl;
import android.annotation.NonNull;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.BiometricsProto;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.HalClientMonitor;
@@ -36,11 +37,12 @@ class FingerprintGetAuthenticatorIdClient extends HalClientMonitor<AidlSession>
private final Map<Integer, Long> mAuthenticatorIds;
FingerprintGetAuthenticatorIdClient(@NonNull Context context,
- @NonNull Supplier<AidlSession> lazyDaemon, int userId, @NonNull String owner,
- int sensorId, Map<Integer, Long> authenticatorIds) {
+ @NonNull Supplier<AidlSession> lazyDaemon,
+ int userId, @NonNull String owner, int sensorId,
+ @NonNull BiometricLogger biometricLogger, @NonNull BiometricContext biometricContext,
+ Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, null /* token */, null /* listener */, userId, owner,
- 0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_FINGERPRINT,
- BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
+ 0 /* cookie */, sensorId, biometricLogger, biometricContext);
mAuthenticatorIds = authenticatorIds;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java
index 0ecad725cbeb..09bdd6de49f0 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalCleanupClient.java
@@ -22,6 +22,8 @@ import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.fingerprint.Fingerprint;
import android.os.IBinder;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.BiometricUtils;
import com.android.server.biometrics.sensors.InternalCleanupClient;
import com.android.server.biometrics.sensors.InternalEnumerateClient;
@@ -39,28 +41,35 @@ import java.util.function.Supplier;
class FingerprintInternalCleanupClient extends InternalCleanupClient<Fingerprint, AidlSession> {
FingerprintInternalCleanupClient(@NonNull Context context,
- @NonNull Supplier<AidlSession> lazyDaemon, int userId, @NonNull String owner,
- int sensorId, @NonNull List<Fingerprint> enrolledList,
+ @NonNull Supplier<AidlSession> lazyDaemon,
+ int userId, @NonNull String owner, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+ @NonNull List<Fingerprint> enrolledList,
@NonNull FingerprintUtils utils, @NonNull Map<Integer, Long> authenticatorIds) {
- super(context, lazyDaemon, userId, owner, sensorId,
- BiometricsProtoEnums.MODALITY_FINGERPRINT, enrolledList, utils, authenticatorIds);
+ super(context, lazyDaemon, userId, owner, sensorId, logger, biometricContext,
+ enrolledList, utils, authenticatorIds);
}
@Override
protected InternalEnumerateClient<AidlSession> getEnumerateClient(Context context,
Supplier<AidlSession> lazyDaemon, IBinder token, int userId, String owner,
- List<Fingerprint> enrolledList, BiometricUtils<Fingerprint> utils, int sensorId) {
+ List<Fingerprint> enrolledList, BiometricUtils<Fingerprint> utils, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
return new FingerprintInternalEnumerateClient(context, lazyDaemon, token, userId, owner,
- enrolledList, utils, sensorId);
+ enrolledList, utils, sensorId,
+ logger.swapAction(context, BiometricsProtoEnums.ACTION_ENUMERATE),
+ biometricContext);
}
@Override
protected RemovalClient<Fingerprint, AidlSession> getRemovalClient(Context context,
Supplier<AidlSession> lazyDaemon, IBinder token, int biometricId, int userId,
String owner, BiometricUtils<Fingerprint> utils, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
Map<Integer, Long> authenticatorIds) {
return new FingerprintRemovalClient(context, lazyDaemon, token,
null /* ClientMonitorCallbackConverter */, new int[] {biometricId}, userId, owner,
- utils, sensorId, authenticatorIds);
+ utils, sensorId, logger.swapAction(context, BiometricsProtoEnums.ACTION_REMOVE),
+ biometricContext, authenticatorIds);
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalEnumerateClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalEnumerateClient.java
index 06ba6d45b407..a5a832aaaf59 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalEnumerateClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInternalEnumerateClient.java
@@ -18,12 +18,13 @@ package com.android.server.biometrics.sensors.fingerprint.aidl;
import android.annotation.NonNull;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.fingerprint.Fingerprint;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.BiometricUtils;
import com.android.server.biometrics.sensors.InternalEnumerateClient;
@@ -40,9 +41,10 @@ class FingerprintInternalEnumerateClient extends InternalEnumerateClient<AidlSes
protected FingerprintInternalEnumerateClient(@NonNull Context context,
@NonNull Supplier<AidlSession> lazyDaemon, @NonNull IBinder token, int userId,
@NonNull String owner, @NonNull List<Fingerprint> enrolledList,
- @NonNull BiometricUtils<Fingerprint> utils, int sensorId) {
+ @NonNull BiometricUtils<Fingerprint> utils, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
super(context, lazyDaemon, token, userId, owner, enrolledList, utils, sensorId,
- BiometricsProtoEnums.MODALITY_FINGERPRINT);
+ logger, biometricContext);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInvalidationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInvalidationClient.java
index 1ee32e986ca6..bc02897ef5c4 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInvalidationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintInvalidationClient.java
@@ -23,6 +23,8 @@ import android.hardware.fingerprint.Fingerprint;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.InvalidationClient;
import java.util.Map;
@@ -33,8 +35,10 @@ public class FingerprintInvalidationClient extends InvalidationClient<Fingerprin
public FingerprintInvalidationClient(@NonNull Context context,
@NonNull Supplier<AidlSession> lazyDaemon, int userId, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
@NonNull Map<Integer, Long> authenticatorIds, @NonNull IInvalidationCallback callback) {
- super(context, lazyDaemon, userId, sensorId, authenticatorIds, callback);
+ super(context, lazyDaemon, userId, sensorId, logger, biometricContext,
+ authenticatorIds, callback);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
index efc93045f957..221ff94141e2 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintProvider.java
@@ -26,6 +26,7 @@ import android.app.TaskStackListener;
import android.content.Context;
import android.content.pm.UserInfo;
import android.content.res.TypedArray;
+import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.ComponentInfoInternal;
import android.hardware.biometrics.IInvalidationCallback;
import android.hardware.biometrics.ITestSession;
@@ -53,6 +54,8 @@ import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.biometrics.Utils;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.AuthenticationClient;
import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
@@ -298,6 +301,9 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
new FingerprintGetAuthenticatorIdClient(mContext,
mSensors.get(sensorId).getLazySession(), userId,
mContext.getOpPackageName(), sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(),
mSensors.get(sensorId).getAuthenticatorIds());
scheduleForSensor(sensorId, client);
});
@@ -307,6 +313,7 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
mHandler.post(() -> {
final InvalidationRequesterClient<Fingerprint> client =
new InvalidationRequesterClient<>(mContext, userId, sensorId,
+ BiometricLogger.ofUnknown(mContext), BiometricContext.getInstance(),
FingerprintUtils.getInstance(sensorId));
scheduleForSensor(sensorId, client);
});
@@ -317,7 +324,10 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
mHandler.post(() -> {
final FingerprintResetLockoutClient client = new FingerprintResetLockoutClient(
mContext, mSensors.get(sensorId).getLazySession(), userId,
- mContext.getOpPackageName(), sensorId, hardwareAuthToken,
+ mContext.getOpPackageName(), sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(), hardwareAuthToken,
mSensors.get(sensorId).getLockoutCache(), mLockoutResetDispatcher);
scheduleForSensor(sensorId, client);
});
@@ -331,7 +341,9 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
new FingerprintGenerateChallengeClient(mContext,
mSensors.get(sensorId).getLazySession(), token,
new ClientMonitorCallbackConverter(receiver), userId, opPackageName,
- sensorId);
+ sensorId, createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance());
scheduleForSensor(sensorId, client);
});
}
@@ -343,7 +355,10 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
final FingerprintRevokeChallengeClient client =
new FingerprintRevokeChallengeClient(mContext,
mSensors.get(sensorId).getLazySession(), token,
- userId, opPackageName, sensorId, challenge);
+ userId, opPackageName, sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(), challenge);
scheduleForSensor(sensorId, client);
});
}
@@ -361,6 +376,9 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
mSensors.get(sensorId).getLazySession(), token, id,
new ClientMonitorCallbackConverter(receiver), userId, hardwareAuthToken,
opPackageName, FingerprintUtils.getInstance(sensorId), sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_ENROLL,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(),
mSensors.get(sensorId).getSensorProperties(),
mUdfpsOverlayController, mSidefpsController, maxTemplatesPerUser, enrollReason);
scheduleForSensor(sensorId, client, new ClientMonitorCallback() {
@@ -399,8 +417,10 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
final FingerprintDetectClient client = new FingerprintDetectClient(mContext,
mSensors.get(sensorId).getLazySession(), token, id, callback, userId,
- opPackageName, sensorId, mUdfpsOverlayController, isStrongBiometric,
- statsClient);
+ opPackageName, sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
+ BiometricContext.getInstance(),
+ mUdfpsOverlayController, isStrongBiometric);
scheduleForSensor(sensorId, client, mFingerprintStateCallback);
});
@@ -417,7 +437,9 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
final FingerprintAuthenticationClient client = new FingerprintAuthenticationClient(
mContext, mSensors.get(sensorId).getLazySession(), token, requestId, callback,
userId, operationId, restricted, opPackageName, cookie,
- false /* requireConfirmation */, sensorId, isStrongBiometric, statsClient,
+ false /* requireConfirmation */, sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
+ BiometricContext.getInstance(), isStrongBiometric,
mTaskStackListener, mSensors.get(sensorId).getLockoutCache(),
mUdfpsOverlayController, mSidefpsController, allowBackgroundAuthentication,
mSensors.get(sensorId).getSensorProperties());
@@ -479,6 +501,9 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
mSensors.get(sensorId).getLazySession(), token,
new ClientMonitorCallbackConverter(receiver), fingerprintIds, userId,
opPackageName, FingerprintUtils.getInstance(sensorId), sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_REMOVE,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(),
mSensors.get(sensorId).getAuthenticatorIds());
scheduleForSensor(sensorId, client, mFingerprintStateCallback);
});
@@ -492,14 +517,22 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
final FingerprintInternalCleanupClient client =
new FingerprintInternalCleanupClient(mContext,
mSensors.get(sensorId).getLazySession(), userId,
- mContext.getOpPackageName(), sensorId, enrolledList,
- FingerprintUtils.getInstance(sensorId),
+ mContext.getOpPackageName(), sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_ENUMERATE,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(),
+ enrolledList, FingerprintUtils.getInstance(sensorId),
mSensors.get(sensorId).getAuthenticatorIds());
scheduleForSensor(sensorId, client, new ClientMonitorCompositeCallback(callback,
mFingerprintStateCallback));
});
}
+ private BiometricLogger createLogger(int statsAction, int statsClient) {
+ return new BiometricLogger(mContext, BiometricsProtoEnums.MODALITY_FINGERPRINT,
+ statsAction, statsClient);
+ }
+
@Override
public boolean isHardwareDetected(int sensorId) {
return hasHalInstance();
@@ -524,6 +557,9 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
final FingerprintInvalidationClient client =
new FingerprintInvalidationClient(mContext,
mSensors.get(sensorId).getLazySession(), userId, sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(),
mSensors.get(sensorId).getAuthenticatorIds(), callback);
scheduleForSensor(sensorId, client);
});
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintRemovalClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintRemovalClient.java
index fbc1dc08b726..d559bb1d72f1 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintRemovalClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintRemovalClient.java
@@ -19,12 +19,13 @@ package com.android.server.biometrics.sensors.fingerprint.aidl;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.fingerprint.Fingerprint;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.BiometricUtils;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.RemovalClient;
@@ -45,9 +46,10 @@ class FingerprintRemovalClient extends RemovalClient<Fingerprint, AidlSession> {
@NonNull Supplier<AidlSession> lazyDaemon, @NonNull IBinder token,
@Nullable ClientMonitorCallbackConverter listener, int[] biometricIds, int userId,
@NonNull String owner, @NonNull BiometricUtils<Fingerprint> utils, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
@NonNull Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, token, listener, userId, owner, utils, sensorId,
- authenticatorIds, BiometricsProtoEnums.MODALITY_FINGERPRINT);
+ logger, biometricContext, authenticatorIds);
mBiometricIds = biometricIds;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintResetLockoutClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintResetLockoutClient.java
index 0e64dab5d325..f90cba79dac2 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintResetLockoutClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintResetLockoutClient.java
@@ -18,7 +18,6 @@ package com.android.server.biometrics.sensors.fingerprint.aidl;
import android.annotation.NonNull;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.fingerprint.IFingerprint;
import android.hardware.keymaster.HardwareAuthToken;
import android.os.RemoteException;
@@ -26,6 +25,8 @@ import android.util.Slog;
import com.android.server.biometrics.BiometricsProto;
import com.android.server.biometrics.HardwareAuthTokenUtils;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.ErrorConsumer;
import com.android.server.biometrics.sensors.HalClientMonitor;
@@ -50,11 +51,11 @@ class FingerprintResetLockoutClient extends HalClientMonitor<AidlSession> implem
FingerprintResetLockoutClient(@NonNull Context context,
@NonNull Supplier<AidlSession> lazyDaemon, int userId, String owner, int sensorId,
+ @NonNull BiometricLogger biometricLogger, @NonNull BiometricContext biometricContext,
@NonNull byte[] hardwareAuthToken, @NonNull LockoutCache lockoutTracker,
@NonNull LockoutResetDispatcher lockoutResetDispatcher) {
super(context, lazyDaemon, null /* token */, null /* listener */, userId, owner,
- 0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN,
- BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
+ 0 /* cookie */, sensorId, biometricLogger, biometricContext);
mHardwareAuthToken = HardwareAuthTokenUtils.toHardwareAuthToken(hardwareAuthToken);
mLockoutCache = lockoutTracker;
mLockoutResetDispatcher = lockoutResetDispatcher;
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintRevokeChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintRevokeChallengeClient.java
index fd938677105c..afa62e2e3173 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintRevokeChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintRevokeChallengeClient.java
@@ -23,6 +23,8 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.RevokeChallengeClient;
import java.util.function.Supplier;
@@ -38,8 +40,10 @@ class FingerprintRevokeChallengeClient extends RevokeChallengeClient<AidlSession
FingerprintRevokeChallengeClient(@NonNull Context context,
@NonNull Supplier<AidlSession> lazyDaemon, @NonNull IBinder token,
- int userId, @NonNull String owner, int sensorId, long challenge) {
- super(context, lazyDaemon, token, userId, owner, sensorId);
+ int userId, @NonNull String owner, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+ long challenge) {
+ super(context, lazyDaemon, token, userId, owner, sensorId, logger, biometricContext);
mChallenge = challenge;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintStartUserClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintStartUserClient.java
index 9dc06e1e0665..52305a31a644 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintStartUserClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintStartUserClient.java
@@ -27,6 +27,8 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.StartUserClient;
@@ -40,9 +42,10 @@ public class FingerprintStartUserClient extends StartUserClient<IFingerprint, IS
public FingerprintStartUserClient(@NonNull Context context,
@NonNull Supplier<IFingerprint> lazyDaemon,
@Nullable IBinder token, int userId, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
@NonNull ISessionCallback sessionCallback,
@NonNull UserStartedCallback<ISession> callback) {
- super(context, lazyDaemon, token, userId, sensorId, callback);
+ super(context, lazyDaemon, token, userId, sensorId, logger, biometricContext, callback);
mSessionCallback = sessionCallback;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintStopUserClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintStopUserClient.java
index fac17f2cc16a..2cc1879c0851 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintStopUserClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintStopUserClient.java
@@ -23,6 +23,8 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.StopUserClient;
@@ -33,8 +35,10 @@ public class FingerprintStopUserClient extends StopUserClient<AidlSession> {
public FingerprintStopUserClient(@NonNull Context context,
@NonNull Supplier<AidlSession> lazyDaemon, @Nullable IBinder token, int userId,
- int sensorId, @NonNull UserStoppedCallback callback) {
- super(context, lazyDaemon, token, userId, sensorId, callback);
+ int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+ @NonNull UserStoppedCallback callback) {
+ super(context, lazyDaemon, token, userId, sensorId, logger, biometricContext, callback);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
index 22762329926b..27226b30f548 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/aidl/Sensor.java
@@ -39,12 +39,15 @@ import android.os.UserManager;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.biometrics.HardwareAuthTokenUtils;
import com.android.server.biometrics.SensorServiceStateProto;
import com.android.server.biometrics.SensorStateProto;
import com.android.server.biometrics.UserStateProto;
import com.android.server.biometrics.Utils;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.AcquisitionClient;
import com.android.server.biometrics.sensors.AuthenticationConsumer;
import com.android.server.biometrics.sensors.BaseClientMonitor;
@@ -72,7 +75,7 @@ import java.util.function.Supplier;
* {@link android.hardware.biometrics.fingerprint.IFingerprint} HAL.
*/
@SuppressWarnings("deprecation")
-class Sensor {
+public class Sensor {
private boolean mTestHalEnabled;
@@ -89,7 +92,8 @@ class Sensor {
@Nullable private AidlSession mCurrentSession;
@NonNull private final Supplier<AidlSession> mLazySession;
- static class HalSessionCallback extends ISessionCallback.Stub {
+ @VisibleForTesting
+ public static class HalSessionCallback extends ISessionCallback.Stub {
/**
* Interface to sends results to the HalSessionCallback's owner.
@@ -442,7 +446,9 @@ class Sensor {
@Override
public StopUserClient<?> getStopUserClient(int userId) {
return new FingerprintStopUserClient(mContext, mLazySession, mToken,
- userId, mSensorProperties.sensorId, () -> mCurrentSession = null);
+ userId, mSensorProperties.sensorId,
+ BiometricLogger.ofUnknown(mContext), BiometricContext.getInstance(),
+ () -> mCurrentSession = null);
}
@NonNull
@@ -478,6 +484,7 @@ class Sensor {
return new FingerprintStartUserClient(mContext, provider::getHalInstance,
mToken, newUserId, mSensorProperties.sensorId,
+ BiometricLogger.ofUnknown(mContext), BiometricContext.getInstance(),
resultController, userStartedCallback);
}
});
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
index 29d460fc1204..6c35c8c91448 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/Fingerprint21.java
@@ -57,6 +57,8 @@ import com.android.server.biometrics.Utils;
import com.android.server.biometrics.fingerprint.FingerprintServiceDumpProto;
import com.android.server.biometrics.fingerprint.FingerprintUserStatsProto;
import com.android.server.biometrics.fingerprint.PerformanceStatsProto;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.AcquisitionClient;
import com.android.server.biometrics.sensors.AuthenticationClient;
import com.android.server.biometrics.sensors.AuthenticationConsumer;
@@ -493,6 +495,9 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
final FingerprintUpdateActiveUserClient client =
new FingerprintUpdateActiveUserClient(mContext, mLazyDaemon, targetUserId,
mContext.getOpPackageName(), mSensorProperties.sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(),
this::getCurrentUser, hasEnrolled, mAuthenticatorIds, force);
mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() {
@Override
@@ -536,7 +541,10 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
// thread.
mHandler.post(() -> {
final FingerprintResetLockoutClient client = new FingerprintResetLockoutClient(mContext,
- userId, mContext.getOpPackageName(), sensorId, mLockoutTracker);
+ userId, mContext.getOpPackageName(), sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(), mLockoutTracker);
mScheduler.scheduleClientMonitor(client);
});
}
@@ -548,7 +556,10 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
final FingerprintGenerateChallengeClient client =
new FingerprintGenerateChallengeClient(mContext, mLazyDaemon, token,
new ClientMonitorCallbackConverter(receiver), userId, opPackageName,
- mSensorProperties.sensorId);
+ mSensorProperties.sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance());
mScheduler.scheduleClientMonitor(client);
});
}
@@ -559,7 +570,10 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
mHandler.post(() -> {
final FingerprintRevokeChallengeClient client = new FingerprintRevokeChallengeClient(
mContext, mLazyDaemon, token, userId, opPackageName,
- mSensorProperties.sensorId);
+ mSensorProperties.sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_UNKNOWN,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance());
mScheduler.scheduleClientMonitor(client);
});
}
@@ -577,7 +591,11 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
mLazyDaemon, token, id, new ClientMonitorCallbackConverter(receiver),
userId, hardwareAuthToken, opPackageName,
FingerprintUtils.getLegacyInstance(mSensorId), ENROLL_TIMEOUT_SEC,
- mSensorProperties.sensorId, mUdfpsOverlayController, mSidefpsController,
+ mSensorProperties.sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_ENROLL,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(),
+ mUdfpsOverlayController, mSidefpsController,
enrollReason);
mScheduler.scheduleClientMonitor(client, new ClientMonitorCallback() {
@Override
@@ -616,8 +634,9 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
final boolean isStrongBiometric = Utils.isStrongBiometric(mSensorProperties.sensorId);
final FingerprintDetectClient client = new FingerprintDetectClient(mContext,
mLazyDaemon, token, id, listener, userId, opPackageName,
- mSensorProperties.sensorId, mUdfpsOverlayController, isStrongBiometric,
- statsClient);
+ mSensorProperties.sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
+ BiometricContext.getInstance(), mUdfpsOverlayController, isStrongBiometric);
mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback);
});
@@ -636,7 +655,9 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
final FingerprintAuthenticationClient client = new FingerprintAuthenticationClient(
mContext, mLazyDaemon, token, requestId, listener, userId, operationId,
restricted, opPackageName, cookie, false /* requireConfirmation */,
- mSensorProperties.sensorId, isStrongBiometric, statsClient,
+ mSensorProperties.sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient),
+ BiometricContext.getInstance(), isStrongBiometric,
mTaskStackListener, mLockoutTracker,
mUdfpsOverlayController, mSidefpsController,
allowBackgroundAuthentication, mSensorProperties);
@@ -678,7 +699,10 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
final FingerprintRemovalClient client = new FingerprintRemovalClient(mContext,
mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver), fingerId,
userId, opPackageName, FingerprintUtils.getLegacyInstance(mSensorId),
- mSensorProperties.sensorId, mAuthenticatorIds);
+ mSensorProperties.sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_REMOVE,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(), mAuthenticatorIds);
mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback);
});
}
@@ -695,7 +719,10 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
mLazyDaemon, token, new ClientMonitorCallbackConverter(receiver),
0 /* fingerprintId */, userId, opPackageName,
FingerprintUtils.getLegacyInstance(mSensorId),
- mSensorProperties.sensorId, mAuthenticatorIds);
+ mSensorProperties.sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_REMOVE,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(), mAuthenticatorIds);
mScheduler.scheduleClientMonitor(client, mFingerprintStateCallback);
});
}
@@ -709,7 +736,10 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
mSensorProperties.sensorId, userId);
final FingerprintInternalCleanupClient client = new FingerprintInternalCleanupClient(
mContext, mLazyDaemon, userId, mContext.getOpPackageName(),
- mSensorProperties.sensorId, enrolledList,
+ mSensorProperties.sensorId,
+ createLogger(BiometricsProtoEnums.ACTION_ENUMERATE,
+ BiometricsProtoEnums.CLIENT_UNKNOWN),
+ BiometricContext.getInstance(), enrolledList,
FingerprintUtils.getLegacyInstance(mSensorId), mAuthenticatorIds);
mScheduler.scheduleClientMonitor(client, callback);
});
@@ -722,6 +752,11 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
mFingerprintStateCallback));
}
+ private BiometricLogger createLogger(int statsAction, int statsClient) {
+ return new BiometricLogger(mContext, BiometricsProtoEnums.MODALITY_FINGERPRINT,
+ statsAction, statsClient);
+ }
+
@Override
public boolean isHardwareDetected(int sensorId) {
return getDaemon() != null;
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
index 589bfcfba992..97fbb5f6e4fe 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintAuthenticationClient.java
@@ -23,7 +23,6 @@ import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricFingerprintConstants;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.ISidefpsController;
@@ -32,6 +31,8 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.log.CallbackWithProbe;
import com.android.server.biometrics.log.Probe;
import com.android.server.biometrics.sensors.AuthenticationClient;
@@ -69,7 +70,8 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
@NonNull IBinder token, long requestId,
@NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
boolean restricted, @NonNull String owner, int cookie, boolean requireConfirmation,
- int sensorId, boolean isStrongBiometric, int statsClient,
+ int sensorId, @NonNull BiometricLogger logger,
+ @NonNull BiometricContext biometricContext, boolean isStrongBiometric,
@NonNull TaskStackListener taskStackListener,
@NonNull LockoutFrameworkImpl lockoutTracker,
@Nullable IUdfpsOverlayController udfpsOverlayController,
@@ -77,10 +79,9 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
boolean allowBackgroundAuthentication,
@NonNull FingerprintSensorPropertiesInternal sensorProps) {
super(context, lazyDaemon, token, listener, targetUserId, operationId, restricted,
- owner, cookie, requireConfirmation, sensorId, isStrongBiometric,
- BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener,
- lockoutTracker, allowBackgroundAuthentication, true /* shouldVibrate */,
- false /* isKeyguardBypassEnabled */);
+ owner, cookie, requireConfirmation, sensorId, logger, biometricContext,
+ isStrongBiometric, taskStackListener, lockoutTracker, allowBackgroundAuthentication,
+ true /* shouldVibrate */, false /* isKeyguardBypassEnabled */);
setRequestId(requestId);
mLockoutFrameworkImpl = lockoutTracker;
mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
index 88487462e51a..f10d4e409b0e 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintDetectClient.java
@@ -22,7 +22,6 @@ import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricFingerprintConstants;
import android.hardware.biometrics.BiometricOverlayConstants;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
import android.hardware.fingerprint.IUdfpsOverlayController;
import android.os.IBinder;
@@ -30,6 +29,8 @@ import android.os.RemoteException;
import android.util.Slog;
import com.android.server.biometrics.BiometricsProto;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.AcquisitionClient;
import com.android.server.biometrics.sensors.AuthenticationConsumer;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
@@ -59,11 +60,11 @@ class FingerprintDetectClient extends AcquisitionClient<IBiometricsFingerprint>
@NonNull Supplier<IBiometricsFingerprint> lazyDaemon,
@NonNull IBinder token, long requestId,
@NonNull ClientMonitorCallbackConverter listener, int userId, @NonNull String owner,
- int sensorId, @Nullable IUdfpsOverlayController udfpsOverlayController,
- boolean isStrongBiometric, int statsClient) {
+ int sensorId,
+ @NonNull BiometricLogger biometricLogger, @NonNull BiometricContext biometricContext,
+ @Nullable IUdfpsOverlayController udfpsOverlayController, boolean isStrongBiometric) {
super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
- true /* shouldVibrate */, BiometricsProtoEnums.MODALITY_FINGERPRINT,
- BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient);
+ true /* shouldVibrate */, biometricLogger, biometricContext);
setRequestId(requestId);
mSensorOverlays = new SensorOverlays(udfpsOverlayController, null /* sideFpsController */);
mIsStrongBiometric = isStrongBiometric;
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
index c69deac371d9..1d478e53fd38 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintEnrollClient.java
@@ -21,7 +21,6 @@ import android.annotation.Nullable;
import android.content.Context;
import android.hardware.biometrics.BiometricAuthenticator;
import android.hardware.biometrics.BiometricFingerprintConstants;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintManager;
@@ -31,6 +30,8 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.BiometricNotificationUtils;
import com.android.server.biometrics.sensors.BiometricUtils;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
@@ -62,12 +63,13 @@ public class FingerprintEnrollClient extends EnrollClient<IBiometricsFingerprint
long requestId, @NonNull ClientMonitorCallbackConverter listener, int userId,
@NonNull byte[] hardwareAuthToken, @NonNull String owner,
@NonNull BiometricUtils<Fingerprint> utils, int timeoutSec, int sensorId,
+ @NonNull BiometricLogger biometricLogger, @NonNull BiometricContext biometricContext,
@Nullable IUdfpsOverlayController udfpsOverlayController,
@Nullable ISidefpsController sidefpsController,
@FingerprintManager.EnrollReason int enrollReason) {
super(context, lazyDaemon, token, listener, userId, hardwareAuthToken, owner, utils,
- timeoutSec, BiometricsProtoEnums.MODALITY_FINGERPRINT, sensorId,
- true /* shouldVibrate */);
+ timeoutSec, sensorId, true /* shouldVibrate */, biometricLogger,
+ biometricContext);
setRequestId(requestId);
mSensorOverlays = new SensorOverlays(udfpsOverlayController, sidefpsController);
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintGenerateChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintGenerateChallengeClient.java
index 591f542396ef..3bb7135a3e06 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintGenerateChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintGenerateChallengeClient.java
@@ -23,6 +23,8 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.GenerateChallengeClient;
@@ -41,8 +43,10 @@ public class FingerprintGenerateChallengeClient
FingerprintGenerateChallengeClient(@NonNull Context context,
@NonNull Supplier<IBiometricsFingerprint> lazyDaemon, @NonNull IBinder token,
@NonNull ClientMonitorCallbackConverter listener, int userId, @NonNull String owner,
- int sensorId) {
- super(context, lazyDaemon, token, listener, userId, owner, sensorId);
+ int sensorId, @NonNull BiometricLogger logger,
+ @NonNull BiometricContext biometricContext) {
+ super(context, lazyDaemon, token, listener, userId, owner, sensorId, logger,
+ biometricContext);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalCleanupClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalCleanupClient.java
index 403602b8839d..5e7cf3578411 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalCleanupClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalCleanupClient.java
@@ -18,11 +18,12 @@ package com.android.server.biometrics.sensors.fingerprint.hidl;
import android.annotation.NonNull;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
import android.hardware.fingerprint.Fingerprint;
import android.os.IBinder;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.BiometricUtils;
import com.android.server.biometrics.sensors.InternalCleanupClient;
import com.android.server.biometrics.sensors.InternalEnumerateClient;
@@ -42,31 +43,35 @@ class FingerprintInternalCleanupClient
FingerprintInternalCleanupClient(@NonNull Context context,
@NonNull Supplier<IBiometricsFingerprint> lazyDaemon, int userId,
- @NonNull String owner, int sensorId, @NonNull List<Fingerprint> enrolledList,
+ @NonNull String owner, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+ @NonNull List<Fingerprint> enrolledList,
@NonNull BiometricUtils<Fingerprint> utils,
@NonNull Map<Integer, Long> authenticatorIds) {
- super(context, lazyDaemon, userId, owner, sensorId,
- BiometricsProtoEnums.MODALITY_FINGERPRINT, enrolledList, utils, authenticatorIds);
+ super(context, lazyDaemon, userId, owner, sensorId, logger, biometricContext,
+ enrolledList, utils, authenticatorIds);
}
@Override
protected InternalEnumerateClient<IBiometricsFingerprint> getEnumerateClient(
Context context, Supplier<IBiometricsFingerprint> lazyDaemon, IBinder token,
int userId, String owner, List<Fingerprint> enrolledList,
- BiometricUtils<Fingerprint> utils, int sensorId) {
+ BiometricUtils<Fingerprint> utils, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
return new FingerprintInternalEnumerateClient(context, lazyDaemon, token, userId, owner,
- enrolledList, utils, sensorId);
+ enrolledList, utils, sensorId, logger, biometricContext);
}
@Override
protected RemovalClient<Fingerprint, IBiometricsFingerprint> getRemovalClient(Context context,
Supplier<IBiometricsFingerprint> lazyDaemon, IBinder token,
int biometricId, int userId, String owner, BiometricUtils<Fingerprint> utils,
- int sensorId, Map<Integer, Long> authenticatorIds) {
+ int sensorId, @NonNull BiometricLogger logger,
+ @NonNull BiometricContext biometricContext, Map<Integer, Long> authenticatorIds) {
// Internal remove does not need to send results to anyone. Cleanup (enumerate + remove)
// is all done internally.
return new FingerprintRemovalClient(context, lazyDaemon, token,
null /* ClientMonitorCallbackConverter */, biometricId, userId, owner, utils,
- sensorId, authenticatorIds);
+ sensorId, logger, biometricContext, authenticatorIds);
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalEnumerateClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalEnumerateClient.java
index def8ed0735f5..0840f1b36903 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalEnumerateClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintInternalEnumerateClient.java
@@ -18,13 +18,14 @@ package com.android.server.biometrics.sensors.fingerprint.hidl;
import android.annotation.NonNull;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
import android.hardware.fingerprint.Fingerprint;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.BiometricUtils;
import com.android.server.biometrics.sensors.InternalEnumerateClient;
@@ -42,9 +43,10 @@ class FingerprintInternalEnumerateClient extends InternalEnumerateClient<IBiomet
FingerprintInternalEnumerateClient(@NonNull Context context,
@NonNull Supplier<IBiometricsFingerprint> lazyDaemon, @NonNull IBinder token,
int userId, @NonNull String owner, @NonNull List<Fingerprint> enrolledList,
- @NonNull BiometricUtils<Fingerprint> utils, int sensorId) {
+ @NonNull BiometricUtils<Fingerprint> utils, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
super(context, lazyDaemon, token, userId, owner, enrolledList, utils, sensorId,
- BiometricsProtoEnums.MODALITY_FINGERPRINT);
+ logger, biometricContext);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintRemovalClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintRemovalClient.java
index 77c201c5ec97..9ec56c2a7dcd 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintRemovalClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintRemovalClient.java
@@ -18,13 +18,14 @@ package com.android.server.biometrics.sensors.fingerprint.hidl;
import android.annotation.NonNull;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
import android.hardware.fingerprint.Fingerprint;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.BiometricUtils;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
import com.android.server.biometrics.sensors.RemovalClient;
@@ -46,9 +47,10 @@ class FingerprintRemovalClient extends RemovalClient<Fingerprint, IBiometricsFin
@NonNull Supplier<IBiometricsFingerprint> lazyDaemon, @NonNull IBinder token,
@NonNull ClientMonitorCallbackConverter listener, int biometricId, int userId,
@NonNull String owner, @NonNull BiometricUtils<Fingerprint> utils, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
@NonNull Map<Integer, Long> authenticatorIds) {
super(context, lazyDaemon, token, listener, userId, owner, utils, sensorId,
- authenticatorIds, BiometricsProtoEnums.MODALITY_FINGERPRINT);
+ logger, biometricContext, authenticatorIds);
mBiometricId = biometricId;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintResetLockoutClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintResetLockoutClient.java
index ed28e3ff481e..559ca0633c42 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintResetLockoutClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintResetLockoutClient.java
@@ -18,9 +18,10 @@ package com.android.server.biometrics.sensors.fingerprint.hidl;
import android.annotation.NonNull;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import com.android.server.biometrics.BiometricsProto;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.BaseClientMonitor;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
@@ -33,10 +34,11 @@ public class FingerprintResetLockoutClient extends BaseClientMonitor {
@NonNull final LockoutFrameworkImpl mLockoutTracker;
public FingerprintResetLockoutClient(@NonNull Context context, int userId,
- @NonNull String owner, int sensorId, @NonNull LockoutFrameworkImpl lockoutTracker) {
+ @NonNull String owner, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+ @NonNull LockoutFrameworkImpl lockoutTracker) {
super(context, null /* token */, null /* listener */, userId, owner, 0 /* cookie */,
- sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN,
- BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
+ sensorId, logger, biometricContext);
mLockoutTracker = lockoutTracker;
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintRevokeChallengeClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintRevokeChallengeClient.java
index 0180a466d7d6..6273417eb0db 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintRevokeChallengeClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintRevokeChallengeClient.java
@@ -23,6 +23,8 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.RevokeChallengeClient;
import java.util.function.Supplier;
@@ -39,8 +41,9 @@ public class FingerprintRevokeChallengeClient
FingerprintRevokeChallengeClient(@NonNull Context context,
@NonNull Supplier<IBiometricsFingerprint> lazyDaemon, @NonNull IBinder token,
- int userId, @NonNull String owner, int sensorId) {
- super(context, lazyDaemon, token, userId, owner, sensorId);
+ int userId, @NonNull String owner, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext) {
+ super(context, lazyDaemon, token, userId, owner, sensorId, logger, biometricContext);
}
@Override
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintUpdateActiveUserClient.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintUpdateActiveUserClient.java
index cb9c33eb9956..a4e602553101 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintUpdateActiveUserClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/hidl/FingerprintUpdateActiveUserClient.java
@@ -18,7 +18,6 @@ package com.android.server.biometrics.sensors.fingerprint.hidl;
import android.annotation.NonNull;
import android.content.Context;
-import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
import android.os.Build;
import android.os.Environment;
@@ -27,6 +26,8 @@ import android.os.SELinux;
import android.util.Slog;
import com.android.server.biometrics.BiometricsProto;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.HalClientMonitor;
@@ -50,12 +51,13 @@ public class FingerprintUpdateActiveUserClient extends HalClientMonitor<IBiometr
FingerprintUpdateActiveUserClient(@NonNull Context context,
@NonNull Supplier<IBiometricsFingerprint> lazyDaemon, int userId,
- @NonNull String owner, int sensorId, Supplier<Integer> currentUserId,
+ @NonNull String owner, int sensorId,
+ @NonNull BiometricLogger logger, @NonNull BiometricContext biometricContext,
+ Supplier<Integer> currentUserId,
boolean hasEnrolledBiometrics, @NonNull Map<Integer, Long> authenticatorIds,
boolean forceUpdateAuthenticatorId) {
super(context, lazyDaemon, null /* token */, null /* listener */, userId, owner,
- 0 /* cookie */, sensorId, BiometricsProtoEnums.MODALITY_UNKNOWN,
- BiometricsProtoEnums.ACTION_UNKNOWN, BiometricsProtoEnums.CLIENT_UNKNOWN);
+ 0 /* cookie */, sensorId, logger, biometricContext);
mCurrentUserId = currentUserId;
mForceUpdateAuthenticatorId = forceUpdateAuthenticatorId;
mHasEnrolledBiometrics = hasEnrolledBiometrics;
diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java
index 1e00ea9161a8..1b0341c1ce26 100644
--- a/services/core/java/com/android/server/camera/CameraServiceProxy.java
+++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java
@@ -308,7 +308,8 @@ public class CameraServiceProxy extends SystemService
public void onFixedRotationFinished(int displayId) { }
@Override
- public void onKeepClearAreasChanged(int displayId, List<Rect> keepClearArea) { }
+ public void onKeepClearAreasChanged(int displayId, List<Rect> restricted,
+ List<Rect> unrestricted) { }
}
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
index c2ca3a502153..d0e39ccb3214 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
@@ -23,7 +23,6 @@ import static android.hardware.devicestate.DeviceStateManager.MINIMUM_DEVICE_STA
import static com.android.server.devicestate.DeviceState.FLAG_CANCEL_OVERRIDE_REQUESTS;
import static com.android.server.devicestate.OverrideRequestController.STATUS_ACTIVE;
import static com.android.server.devicestate.OverrideRequestController.STATUS_CANCELED;
-import static com.android.server.devicestate.OverrideRequestController.STATUS_SUSPENDED;
import android.annotation.IntDef;
import android.annotation.IntRange;
@@ -348,7 +347,7 @@ public final class DeviceStateManagerService extends SystemService {
mBaseState = Optional.of(baseState);
if (baseState.hasFlag(FLAG_CANCEL_OVERRIDE_REQUESTS)) {
- mOverrideRequestController.cancelOverrideRequests();
+ mOverrideRequestController.cancelOverrideRequest();
}
mOverrideRequestController.handleBaseStateChanged();
updatePendingStateLocked();
@@ -503,7 +502,7 @@ public final class DeviceStateManagerService extends SystemService {
@OverrideRequestController.RequestStatus int status) {
if (status == STATUS_ACTIVE) {
mActiveOverride = Optional.of(request);
- } else if (status == STATUS_SUSPENDED || status == STATUS_CANCELED) {
+ } else if (status == STATUS_CANCELED) {
if (mActiveOverride.isPresent() && mActiveOverride.get() == request) {
mActiveOverride = Optional.empty();
}
@@ -528,8 +527,6 @@ public final class DeviceStateManagerService extends SystemService {
// Schedule the notification now.
processRecord.notifyRequestActiveAsync(request.getToken());
}
- } else if (status == STATUS_SUSPENDED) {
- processRecord.notifyRequestSuspendedAsync(request.getToken());
} else {
processRecord.notifyRequestCanceledAsync(request.getToken());
}
@@ -595,15 +592,14 @@ public final class DeviceStateManagerService extends SystemService {
}
}
- private void cancelRequestInternal(int callingPid, @NonNull IBinder token) {
+ private void cancelStateRequestInternal(int callingPid) {
synchronized (mLock) {
final ProcessRecord processRecord = mProcessRecords.get(callingPid);
if (processRecord == null) {
throw new IllegalStateException("Process " + callingPid
+ " has no registered callback.");
}
-
- mOverrideRequestController.cancelRequest(token);
+ mActiveOverride.ifPresent(mOverrideRequestController::cancelRequest);
}
}
@@ -628,6 +624,23 @@ public final class DeviceStateManagerService extends SystemService {
}
}
+ /**
+ * Allow top processes to request or cancel a device state change. If the calling process ID is
+ * not the top app, then check if this process holds the CONTROL_DEVICE_STATE permission.
+ * @param callingPid
+ */
+ private void checkCanControlDeviceState(int callingPid) {
+ // Allow top processes to request a device state change
+ // If the calling process ID is not the top app, then we check if this process
+ // holds a permission to CONTROL_DEVICE_STATE
+ final WindowProcessController topApp = mActivityTaskManagerInternal.getTopApp();
+ if (topApp == null || topApp.getPid() != callingPid) {
+ getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
+ "Permission required to request device state, "
+ + "or the call must come from the top focused app.");
+ }
+ }
+
private final class DeviceStateProviderListener implements DeviceStateProvider.Listener {
@Override
public void onSupportedDeviceStatesChanged(DeviceState[] newDeviceStates) {
@@ -716,24 +729,6 @@ public final class DeviceStateManagerService extends SystemService {
});
}
- public void notifyRequestSuspendedAsync(IBinder token) {
- @RequestStatus Integer lastStatus = mLastNotifiedStatus.get(token);
- if (lastStatus != null
- && (lastStatus == STATUS_SUSPENDED || lastStatus == STATUS_CANCELED)) {
- return;
- }
-
- mLastNotifiedStatus.put(token, STATUS_SUSPENDED);
- mHandler.post(() -> {
- try {
- mCallback.onRequestSuspended(token);
- } catch (RemoteException ex) {
- Slog.w(TAG, "Failed to notify process " + mPid + " that request state changed.",
- ex);
- }
- });
- }
-
public void notifyRequestCanceledAsync(IBinder token) {
@RequestStatus Integer lastStatus = mLastNotifiedStatus.get(token);
if (lastStatus != null && lastStatus == STATUS_CANCELED) {
@@ -782,12 +777,7 @@ public final class DeviceStateManagerService extends SystemService {
// Allow top processes to request a device state change
// If the calling process ID is not the top app, then we check if this process
// holds a permission to CONTROL_DEVICE_STATE
- final WindowProcessController topApp = mActivityTaskManagerInternal.getTopApp();
- if (topApp.getPid() != callingPid) {
- getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
- "Permission required to request device state, "
- + "or the call must come from the top focused app.");
- }
+ checkCanControlDeviceState(callingPid);
if (token == null) {
throw new IllegalArgumentException("Request token must not be null.");
@@ -802,25 +792,16 @@ public final class DeviceStateManagerService extends SystemService {
}
@Override // Binder call
- public void cancelRequest(IBinder token) {
+ public void cancelStateRequest() {
final int callingPid = Binder.getCallingPid();
// Allow top processes to cancel a device state change
// If the calling process ID is not the top app, then we check if this process
// holds a permission to CONTROL_DEVICE_STATE
- final WindowProcessController topApp = mActivityTaskManagerInternal.getTopApp();
- if (topApp.getPid() != callingPid) {
- getContext().enforceCallingOrSelfPermission(CONTROL_DEVICE_STATE,
- "Permission required to cancel device state, "
- + "or the call must come from the top focused app.");
- }
-
- if (token == null) {
- throw new IllegalArgumentException("Request token must not be null.");
- }
+ checkCanControlDeviceState(callingPid);
final long callingIdentity = Binder.clearCallingIdentity();
try {
- cancelRequestInternal(callingPid, token);
+ cancelStateRequestInternal(callingPid);
} finally {
Binder.restoreCallingIdentity(callingIdentity);
}
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerShellCommand.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerShellCommand.java
index eed68f8b1300..659ee75de453 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerShellCommand.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerShellCommand.java
@@ -97,7 +97,7 @@ public class DeviceStateManagerShellCommand extends ShellCommand {
try {
if ("reset".equals(nextArg)) {
if (sLastRequest != null) {
- mClient.cancelRequest(sLastRequest);
+ mClient.cancelStateRequest();
sLastRequest = null;
}
} else {
@@ -105,9 +105,6 @@ public class DeviceStateManagerShellCommand extends ShellCommand {
DeviceStateRequest request = DeviceStateRequest.newBuilder(requestedState).build();
mClient.requestState(request, null /* executor */, null /* callback */);
- if (sLastRequest != null) {
- mClient.cancelRequest(sLastRequest);
- }
sLastRequest = request;
}
diff --git a/services/core/java/com/android/server/devicestate/OverrideRequestController.java b/services/core/java/com/android/server/devicestate/OverrideRequestController.java
index 36cb4162accc..01f5a09323cf 100644
--- a/services/core/java/com/android/server/devicestate/OverrideRequestController.java
+++ b/services/core/java/com/android/server/devicestate/OverrideRequestController.java
@@ -18,15 +18,13 @@ package com.android.server.devicestate;
import android.annotation.IntDef;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.hardware.devicestate.DeviceStateRequest;
import android.os.IBinder;
+import android.util.Slog;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.List;
/**
* Manages the lifecycle of override requests.
@@ -36,29 +34,26 @@ import java.util.List;
* <ul>
* <li>A new request is added with {@link #addRequest(OverrideRequest)}, in which case the
* request will become suspended.</li>
- * <li>The request is cancelled with {@link #cancelRequest(IBinder)} or as a side effect
+ * <li>The request is cancelled with {@link #cancelRequest} or as a side effect
* of other methods calls, such as {@link #handleProcessDied(int)}.</li>
* </ul>
*/
final class OverrideRequestController {
+ private static final String TAG = "OverrideRequestController";
+
static final int STATUS_UNKNOWN = 0;
/**
* The request is the top-most request.
*/
static final int STATUS_ACTIVE = 1;
/**
- * The request is still present but is being superseded by another request.
- */
- static final int STATUS_SUSPENDED = 2;
- /**
* The request is not longer valid.
*/
- static final int STATUS_CANCELED = 3;
+ static final int STATUS_CANCELED = 2;
@IntDef(prefix = {"STATUS_"}, value = {
STATUS_UNKNOWN,
STATUS_ACTIVE,
- STATUS_SUSPENDED,
STATUS_CANCELED
})
@Retention(RetentionPolicy.SOURCE)
@@ -68,8 +63,6 @@ final class OverrideRequestController {
switch (status) {
case STATUS_ACTIVE:
return "ACTIVE";
- case STATUS_SUSPENDED:
- return "SUSPENDED";
case STATUS_CANCELED:
return "CANCELED";
case STATUS_UNKNOWN:
@@ -79,15 +72,13 @@ final class OverrideRequestController {
}
private final StatusChangeListener mListener;
- private final List<OverrideRequest> mTmpRequestsToCancel = new ArrayList<>();
- // List of override requests with the most recent override request at the end.
- private final ArrayList<OverrideRequest> mRequests = new ArrayList<>();
+ // Handle to the current override request, null if none.
+ private OverrideRequest mRequest;
private boolean mStickyRequestsAllowed;
- // List of override requests that have outlived their process and will only be cancelled through
- // a call to cancelStickyRequests().
- private final ArrayList<OverrideRequest> mStickyRequests = new ArrayList<>();
+ // The current request has outlived their process.
+ private boolean mStickyRequest;
OverrideRequestController(@NonNull StatusChangeListener listener) {
mListener = listener;
@@ -97,26 +88,26 @@ final class OverrideRequestController {
* Sets sticky requests as either allowed or disallowed. When sticky requests are allowed a call
* to {@link #handleProcessDied(int)} will not result in the request being cancelled
* immediately. Instead, the request will be marked sticky and must be cancelled with a call
- * to {@link #cancelStickyRequests()}.
+ * to {@link #cancelStickyRequest()}.
*/
void setStickyRequestsAllowed(boolean stickyRequestsAllowed) {
mStickyRequestsAllowed = stickyRequestsAllowed;
if (!mStickyRequestsAllowed) {
- cancelStickyRequests();
+ cancelStickyRequest();
}
}
/**
- * Adds a request to the top of the stack and notifies the listener of all changes to request
- * status as a result of this operation.
+ * Sets the new request as active and cancels the previous override request, notifies the
+ * listener of all changes to request status as a result of this operation.
*/
void addRequest(@NonNull OverrideRequest request) {
- mRequests.add(request);
+ OverrideRequest previousRequest = mRequest;
+ mRequest = request;
mListener.onStatusChanged(request, STATUS_ACTIVE);
- if (mRequests.size() > 1) {
- OverrideRequest prevRequest = mRequests.get(mRequests.size() - 2);
- mListener.onStatusChanged(prevRequest, STATUS_SUSPENDED);
+ if (previousRequest != null) {
+ cancelRequestLocked(previousRequest);
}
}
@@ -124,42 +115,32 @@ final class OverrideRequestController {
* Cancels the request with the specified {@code token} and notifies the listener of all changes
* to request status as a result of this operation.
*/
- void cancelRequest(@NonNull IBinder token) {
- int index = getRequestIndex(token);
- if (index == -1) {
+ void cancelRequest(@NonNull OverrideRequest request) {
+ // Either don't have a current request or attempting to cancel an already cancelled request
+ if (!hasRequest(request.getToken())) {
return;
}
-
- OverrideRequest request = mRequests.remove(index);
- if (index == mRequests.size() && mRequests.size() > 0) {
- // We removed the current active request so we need to set the new active request
- // before cancelling this request.
- OverrideRequest newTop = getLast(mRequests);
- mListener.onStatusChanged(newTop, STATUS_ACTIVE);
- }
- mListener.onStatusChanged(request, STATUS_CANCELED);
+ cancelCurrentRequestLocked();
}
/**
- * Cancels all requests that are currently marked sticky and notifies the listener of all
+ * Cancels a request that is currently marked sticky and notifies the listener of all
* changes to request status as a result of this operation.
*
* @see #setStickyRequestsAllowed(boolean)
*/
- void cancelStickyRequests() {
- mTmpRequestsToCancel.clear();
- mTmpRequestsToCancel.addAll(mStickyRequests);
- cancelRequestsLocked(mTmpRequestsToCancel);
+ void cancelStickyRequest() {
+ if (mStickyRequest) {
+ cancelCurrentRequestLocked();
+ }
}
/**
- * Cancels all override requests, this could be due to the device being put
+ * Cancels the current override request, this could be due to the device being put
* into a hardware state that declares the flag "FLAG_CANCEL_OVERRIDE_REQUESTS"
*/
- void cancelOverrideRequests() {
- mTmpRequestsToCancel.clear();
- mTmpRequestsToCancel.addAll(mRequests);
- cancelRequestsLocked(mTmpRequestsToCancel);
+ void cancelOverrideRequest() {
+ cancelCurrentRequestLocked();
}
/**
@@ -167,7 +148,7 @@ final class OverrideRequestController {
* {@code token}, {@code false} otherwise.
*/
boolean hasRequest(@NonNull IBinder token) {
- return getRequestIndex(token) != -1;
+ return mRequest != null && token == mRequest.getToken();
}
/**
@@ -176,139 +157,79 @@ final class OverrideRequestController {
* operation.
*/
void handleProcessDied(int pid) {
- if (mRequests.isEmpty()) {
+ if (mRequest == null) {
return;
}
- mTmpRequestsToCancel.clear();
- OverrideRequest prevActiveRequest = getLast(mRequests);
- for (OverrideRequest request : mRequests) {
- if (request.getPid() == pid) {
- mTmpRequestsToCancel.add(request);
+ if (mRequest.getPid() == pid) {
+ if (mStickyRequestsAllowed) {
+ // Do not cancel the requests now because sticky requests are allowed. These
+ // requests will be cancelled on a call to cancelStickyRequests().
+ mStickyRequest = true;
+ return;
}
+ cancelCurrentRequestLocked();
}
-
- if (mStickyRequestsAllowed) {
- // Do not cancel the requests now because sticky requests are allowed. These
- // requests will be cancelled on a call to cancelStickyRequests().
- mStickyRequests.addAll(mTmpRequestsToCancel);
- return;
- }
-
- cancelRequestsLocked(mTmpRequestsToCancel);
}
/**
* Notifies the controller that the base state has changed. The controller will notify the
* listener of all changes to request status as a result of this change.
- *
- * @return {@code true} if calling this method has lead to a new active request, {@code false}
- * otherwise.
*/
- boolean handleBaseStateChanged() {
- if (mRequests.isEmpty()) {
- return false;
+ void handleBaseStateChanged() {
+ if (mRequest == null) {
+ return;
}
- mTmpRequestsToCancel.clear();
- OverrideRequest prevActiveRequest = getLast(mRequests);
- for (int i = 0; i < mRequests.size(); i++) {
- OverrideRequest request = mRequests.get(i);
- if ((request.getFlags() & DeviceStateRequest.FLAG_CANCEL_WHEN_BASE_CHANGES) != 0) {
- mTmpRequestsToCancel.add(request);
- }
+ if ((mRequest.getFlags()
+ & DeviceStateRequest.FLAG_CANCEL_WHEN_BASE_CHANGES) != 0) {
+ cancelCurrentRequestLocked();
}
-
- final boolean newActiveRequest = cancelRequestsLocked(mTmpRequestsToCancel);
- return newActiveRequest;
}
/**
* Notifies the controller that the set of supported states has changed. The controller will
* notify the listener of all changes to request status as a result of this change.
- *
- * @return {@code true} if calling this method has lead to a new active request, {@code false}
- * otherwise.
*/
- boolean handleNewSupportedStates(int[] newSupportedStates) {
- if (mRequests.isEmpty()) {
- return false;
+ void handleNewSupportedStates(int[] newSupportedStates) {
+ if (mRequest == null) {
+ return;
}
- mTmpRequestsToCancel.clear();
- for (int i = 0; i < mRequests.size(); i++) {
- OverrideRequest request = mRequests.get(i);
- if (!contains(newSupportedStates, request.getRequestedState())) {
- mTmpRequestsToCancel.add(request);
- }
+ if (!contains(newSupportedStates, mRequest.getRequestedState())) {
+ cancelCurrentRequestLocked();
}
-
- final boolean newActiveRequest = cancelRequestsLocked(mTmpRequestsToCancel);
- return newActiveRequest;
}
void dumpInternal(PrintWriter pw) {
- final int requestCount = mRequests.size();
+ OverrideRequest overrideRequest = mRequest;
+ final boolean requestActive = overrideRequest != null;
pw.println();
- pw.println("Override requests: size=" + requestCount);
- for (int i = 0; i < requestCount; i++) {
- OverrideRequest overrideRequest = mRequests.get(i);
- int status = (i == requestCount - 1) ? STATUS_ACTIVE : STATUS_SUSPENDED;
- pw.println(" " + i + ": mPid=" + overrideRequest.getPid()
+ pw.println("Override Request active: " + requestActive);
+ if (requestActive) {
+ pw.println("Request: mPid=" + overrideRequest.getPid()
+ ", mRequestedState=" + overrideRequest.getRequestedState()
+ ", mFlags=" + overrideRequest.getFlags()
- + ", mStatus=" + statusToString(status));
+ + ", mStatus=" + statusToString(STATUS_ACTIVE));
}
}
- /**
- * Handles cancelling a set of requests. If the set of requests to cancel will lead to a new
- * request becoming active this request will also be notified of its change in state.
- *
- * @return {@code true} if calling this method has lead to a new active request, {@code false}
- * otherwise.
- */
- private boolean cancelRequestsLocked(List<OverrideRequest> requestsToCancel) {
- if (requestsToCancel.isEmpty()) {
- return false;
- }
-
- OverrideRequest prevActiveRequest = getLast(mRequests);
- boolean causedNewRequestToBecomeActive = false;
- mRequests.removeAll(requestsToCancel);
- mStickyRequests.removeAll(requestsToCancel);
- if (!mRequests.isEmpty()) {
- OverrideRequest newActiveRequest = getLast(mRequests);
- if (newActiveRequest != prevActiveRequest) {
- mListener.onStatusChanged(newActiveRequest, STATUS_ACTIVE);
- causedNewRequestToBecomeActive = true;
- }
- }
-
- for (int i = 0; i < requestsToCancel.size(); i++) {
- mListener.onStatusChanged(requestsToCancel.get(i), STATUS_CANCELED);
- }
- return causedNewRequestToBecomeActive;
+ private void cancelRequestLocked(@NonNull OverrideRequest requestToCancel) {
+ mListener.onStatusChanged(requestToCancel, STATUS_CANCELED);
}
- private int getRequestIndex(@NonNull IBinder token) {
- final int numberOfRequests = mRequests.size();
- if (numberOfRequests == 0) {
- return -1;
- }
-
- for (int i = 0; i < numberOfRequests; i++) {
- OverrideRequest request = mRequests.get(i);
- if (request.getToken() == token) {
- return i;
- }
+ /**
+ * Handles cancelling {@code mRequest}.
+ * Notifies the listener of the canceled status as well.
+ */
+ private void cancelCurrentRequestLocked() {
+ if (mRequest == null) {
+ Slog.w(TAG, "Attempted to cancel a null OverrideRequest");
+ return;
}
- return -1;
- }
-
- @Nullable
- private static <T> T getLast(List<T> list) {
- return list.size() > 0 ? list.get(list.size() - 1) : null;
+ mStickyRequest = false;
+ mListener.onStatusChanged(mRequest, STATUS_CANCELED);
+ mRequest = null;
}
private static boolean contains(int[] array, int value) {
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 7ad497972462..4e88acd11fac 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -141,7 +141,6 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -1756,10 +1755,6 @@ public final class DisplayManagerService extends SystemService {
void setUserPreferredDisplayModeInternal(int displayId, Display.Mode mode) {
synchronized (mSyncRoot) {
- if (Objects.equals(mUserPreferredMode, mode) && displayId == Display.INVALID_DISPLAY) {
- return;
- }
-
if (mode != null && !isResolutionAndRefreshRateValid(mode)
&& displayId == Display.INVALID_DISPLAY) {
throw new IllegalArgumentException("width, height and refresh rate of mode should "
@@ -1813,7 +1808,15 @@ public final class DisplayManagerService extends SystemService {
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.USER_PREFERRED_RESOLUTION_WIDTH, resolutionWidth);
mDisplayDeviceRepo.forEachLocked((DisplayDevice device) -> {
- device.setUserPreferredDisplayModeLocked(mode);
+ // If there is a display specific mode, don't override that
+ final Point deviceUserPreferredResolution =
+ mPersistentDataStore.getUserPreferredResolution(device);
+ final float deviceRefreshRate =
+ mPersistentDataStore.getUserPreferredRefreshRate(device);
+ if (!isValidResolution(deviceUserPreferredResolution)
+ && !isValidRefreshRate(deviceRefreshRate)) {
+ device.setUserPreferredDisplayModeLocked(mode);
+ }
});
}
@@ -3533,6 +3536,14 @@ public final class DisplayManagerService extends SystemService {
&& (brightness <= PowerManager.BRIGHTNESS_MAX);
}
+ private static boolean isValidResolution(Point resolution) {
+ return (resolution != null) && (resolution.x > 0) && (resolution.y > 0);
+ }
+
+ private static boolean isValidRefreshRate(float refreshRate) {
+ return !Float.isNaN(refreshRate) && (refreshRate > 0.0f);
+ }
+
private final class LocalService extends DisplayManagerInternal {
@Override
diff --git a/services/core/java/com/android/server/display/HighBrightnessModeController.java b/services/core/java/com/android/server/display/HighBrightnessModeController.java
index 534ed5d8491a..23c17f5af10d 100644
--- a/services/core/java/com/android/server/display/HighBrightnessModeController.java
+++ b/services/core/java/com/android/server/display/HighBrightnessModeController.java
@@ -521,6 +521,10 @@ class HighBrightnessModeController {
} else if (mIsBlockedByLowPowerMode) {
reason = FrameworkStatsLog
.DISPLAY_HBM_STATE_CHANGED__REASON__HBM_SV_OFF_BATTERY_SAVE_ON;
+ } else if (mBrightness <= mHbmData.transitionPoint) {
+ // This must be after external thermal check.
+ reason = FrameworkStatsLog
+ .DISPLAY_HBM_STATE_CHANGED__REASON__HBM_SV_OFF_LOW_REQUESTED_BRIGHTNESS;
}
}
diff --git a/services/core/java/com/android/server/dreams/DreamManagerService.java b/services/core/java/com/android/server/dreams/DreamManagerService.java
index 611b28850efe..f0a6af3c8834 100644
--- a/services/core/java/com/android/server/dreams/DreamManagerService.java
+++ b/services/core/java/com/android/server/dreams/DreamManagerService.java
@@ -416,13 +416,14 @@ public final class DreamManagerService extends SystemService {
mCurrentDreamCanDoze = canDoze;
mCurrentDreamUserId = userId;
+ if (!mCurrentDreamName.equals(mAmbientDisplayComponent)) {
+ mUiEventLogger.log(DreamManagerEvent.DREAM_START);
+ }
+
PowerManager.WakeLock wakeLock = mPowerManager
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "startDream");
mHandler.post(wakeLock.wrap(() -> {
mAtmInternal.notifyDreamStateChanged(true);
- if (!mCurrentDreamName.equals(mAmbientDisplayComponent)) {
- mUiEventLogger.log(DreamManagerEvent.DREAM_START);
- }
mController.startDream(newToken, name, isTest, canDoze, userId, wakeLock,
mDreamOverlayServiceName);
}));
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index de933cc47005..783a88ca29bf 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -2285,14 +2285,8 @@ public class InputManagerService extends IInputManager.Stub
nativeNotifyPortAssociationsChanged(mPtr);
}
- /**
- * Add a runtime association between the input device name and the display unique id.
- * @param inputDeviceName The name of the input device.
- * @param displayUniqueId The unique id of the associated display.
- */
@Override // Binder call
- public void addUniqueIdAssociation(@NonNull String inputDeviceName,
- @NonNull String displayUniqueId) {
+ public void addUniqueIdAssociation(@NonNull String inputPort, @NonNull String displayUniqueId) {
if (!checkCallingPermission(
android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY,
"addNameAssociation()")) {
@@ -2300,20 +2294,16 @@ public class InputManagerService extends IInputManager.Stub
"Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY permission");
}
- Objects.requireNonNull(inputDeviceName);
+ Objects.requireNonNull(inputPort);
Objects.requireNonNull(displayUniqueId);
synchronized (mAssociationsLock) {
- mUniqueIdAssociations.put(inputDeviceName, displayUniqueId);
+ mUniqueIdAssociations.put(inputPort, displayUniqueId);
}
nativeChangeUniqueIdAssociation(mPtr);
}
- /**
- * Remove the runtime association between the input device and the display.
- * @param inputDeviceName The port of the input device to be cleared.
- */
@Override // Binder call
- public void removeUniqueIdAssociation(@NonNull String inputDeviceName) {
+ public void removeUniqueIdAssociation(@NonNull String inputPort) {
if (!checkCallingPermission(
android.Manifest.permission.ASSOCIATE_INPUT_DEVICE_TO_DISPLAY,
"removeUniqueIdAssociation()")) {
@@ -2321,9 +2311,9 @@ public class InputManagerService extends IInputManager.Stub
"Requires ASSOCIATE_INPUT_DEVICE_TO_DISPLAY permission");
}
- Objects.requireNonNull(inputDeviceName);
+ Objects.requireNonNull(inputPort);
synchronized (mAssociationsLock) {
- mUniqueIdAssociations.remove(inputDeviceName);
+ mUniqueIdAssociations.remove(inputPort);
}
nativeChangeUniqueIdAssociation(mPtr);
}
@@ -2594,6 +2584,13 @@ public class InputManagerService extends IInputManager.Stub
pw.println(" display: " + v);
});
}
+ if (!mUniqueIdAssociations.isEmpty()) {
+ pw.println("Unique Id Associations:");
+ mUniqueIdAssociations.forEach((k, v) -> {
+ pw.print(" port: " + k);
+ pw.println(" uniqueId: " + v);
+ });
+ }
}
}
diff --git a/services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java b/services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java
index c87ca92d632e..6cb3b3b6740d 100644
--- a/services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java
+++ b/services/core/java/com/android/server/inputmethod/IInputMethodInvoker.java
@@ -107,9 +107,11 @@ final class IInputMethodInvoker {
@AnyThread
void initializeInternal(IBinder token, IInputMethodPrivilegedOperations privOps,
- int configChanges, boolean stylusHwSupported) {
+ int configChanges, boolean stylusHwSupported,
+ boolean shouldShowImeSwitcherWhenImeIsShown) {
try {
- mTarget.initializeInternal(token, privOps, configChanges, stylusHwSupported);
+ mTarget.initializeInternal(token, privOps, configChanges, stylusHwSupported,
+ shouldShowImeSwitcherWhenImeIsShown);
} catch (RemoteException e) {
logRemoteException(e);
}
@@ -145,9 +147,20 @@ final class IInputMethodInvoker {
@AnyThread
void startInput(IBinder startInputToken, IInputContext inputContext, EditorInfo attribute,
- boolean restarting) {
+ boolean restarting, boolean shouldShowImeSwitcherWhenImeIsShown) {
try {
- mTarget.startInput(startInputToken, inputContext, attribute, restarting);
+ mTarget.startInput(startInputToken, inputContext, attribute, restarting,
+ shouldShowImeSwitcherWhenImeIsShown);
+ } catch (RemoteException e) {
+ logRemoteException(e);
+ }
+ }
+
+ @AnyThread
+ void onShouldShowImeSwitcherWhenImeIsShownChanged(boolean shouldShowImeSwitcherWhenImeIsShown) {
+ try {
+ mTarget.onShouldShowImeSwitcherWhenImeIsShownChanged(
+ shouldShowImeSwitcherWhenImeIsShown);
} catch (RemoteException e) {
logRemoteException(e);
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 936b1a20e326..c207738a4f88 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -2325,10 +2325,12 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
true /* direct */);
}
+ final boolean shouldShowImeSwitcherWhenImeIsShown =
+ shouldShowImeSwitcherWhenImeIsShownLocked();
final SessionState session = mCurClient.curSession;
setEnabledSessionLocked(session);
- session.method.startInput(startInputToken, mCurInputContext, mCurAttribute, restarting);
-
+ session.method.startInput(startInputToken, mCurInputContext, mCurAttribute, restarting,
+ shouldShowImeSwitcherWhenImeIsShown);
if (mShowRequested) {
if (DEBUG) Slog.v(TAG, "Attach new input asks to show input");
showCurrentInputLocked(mCurFocusedWindow, getAppShowFlagsLocked(), null,
@@ -2528,7 +2530,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
+ mCurTokenDisplayId);
}
inputMethod.initializeInternal(token, new InputMethodPrivilegedOperationsImpl(this, token),
- configChanges, supportStylusHw);
+ configChanges, supportStylusHw, shouldShowImeSwitcherWhenImeIsShownLocked());
}
@AnyThread
@@ -2731,6 +2733,12 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
@GuardedBy("ImfLock.class")
+ boolean shouldShowImeSwitcherWhenImeIsShownLocked() {
+ return shouldShowImeSwitcherLocked(
+ InputMethodService.IME_ACTIVE | InputMethodService.IME_VISIBLE);
+ }
+
+ @GuardedBy("ImfLock.class")
private boolean shouldShowImeSwitcherLocked(int visibility) {
if (!mShowOngoingImeSwitcherForPhones) return false;
if (mMenuController.getSwitchingDialogLocked() != null) return false;
@@ -2990,6 +2998,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
// the same enabled IMEs list.
mSwitchingController.resetCircularListLocked(mContext);
+ sendShouldShowImeSwitcherWhenImeIsShownLocked();
}
@GuardedBy("ImfLock.class")
@@ -4308,6 +4317,7 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
updateImeWindowStatus(msg.arg1 == 1);
return true;
}
+
// ---------------------------------------------------------
case MSG_UNBIND_CLIENT:
@@ -4368,6 +4378,9 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
// --------------------------------------------------------------
case MSG_HARD_KEYBOARD_SWITCH_CHANGED:
mMenuController.handleHardKeyboardStatusChange(msg.arg1 == 1);
+ synchronized (ImfLock.class) {
+ sendShouldShowImeSwitcherWhenImeIsShownLocked();
+ }
return true;
case MSG_SYSTEM_UNLOCK_USER: {
final int userId = msg.arg1;
@@ -4638,6 +4651,8 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
// the same enabled IMEs list.
mSwitchingController.resetCircularListLocked(mContext);
+ sendShouldShowImeSwitcherWhenImeIsShownLocked();
+
// Notify InputMethodListListeners of the new installed InputMethods.
final List<InputMethodInfo> inputMethodList = new ArrayList<>(mMethodList);
mHandler.obtainMessage(MSG_DISPATCH_ON_INPUT_METHOD_LIST_UPDATED,
@@ -4645,6 +4660,17 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
}
@GuardedBy("ImfLock.class")
+ void sendShouldShowImeSwitcherWhenImeIsShownLocked() {
+ final IInputMethodInvoker curMethod = mBindingController.getCurMethod();
+ if (curMethod == null) {
+ // No need to send the data if the IME is not yet bound.
+ return;
+ }
+ curMethod.onShouldShowImeSwitcherWhenImeIsShownChanged(
+ shouldShowImeSwitcherWhenImeIsShownLocked());
+ }
+
+ @GuardedBy("ImfLock.class")
private void updateDefaultVoiceImeIfNeededLocked() {
final String systemSpeechRecognizer =
mContext.getString(com.android.internal.R.string.config_systemSpeechRecognizer);
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
index 348bb2d868a2..98bde11ad517 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
@@ -203,6 +203,7 @@ final class InputMethodMenuController {
attrs.setTitle("Select input method");
w.setAttributes(attrs);
mService.updateSystemUiLocked();
+ mService.sendShouldShowImeSwitcherWhenImeIsShownLocked();
mSwitchingDialog.show();
}
}
@@ -238,6 +239,7 @@ final class InputMethodMenuController {
mSwitchingDialogTitleView = null;
mService.updateSystemUiLocked();
+ mService.sendShouldShowImeSwitcherWhenImeIsShownLocked();
mDialogBuilder = null;
mIms = null;
}
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index aa1fa9ba1221..0c3f9f0e26c6 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -17,6 +17,7 @@
package com.android.server.location;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
import static android.app.compat.CompatChanges.isChangeEnabled;
import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE;
import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
@@ -829,16 +830,12 @@ public class LocationManagerService extends ILocationManager.Stub implements
"only verified adas packages may use adas gnss bypass requests");
}
if (!isLocationProvider) {
- mContext.enforceCallingOrSelfPermission(
- permission.WRITE_SECURE_SETTINGS,
- "adas gnss bypass requires " + permission.WRITE_SECURE_SETTINGS);
+ LocationPermissions.enforceCallingOrSelfBypassPermission(mContext);
}
}
if (request.isLocationSettingsIgnored()) {
if (!isLocationProvider) {
- mContext.enforceCallingOrSelfPermission(
- permission.WRITE_SECURE_SETTINGS,
- "ignoring location settings requires " + permission.WRITE_SECURE_SETTINGS);
+ LocationPermissions.enforceCallingOrSelfBypassPermission(mContext);
}
}
@@ -933,16 +930,12 @@ public class LocationManagerService extends ILocationManager.Stub implements
"only verified adas packages may use adas gnss bypass requests");
}
if (!isLocationProvider) {
- mContext.enforceCallingOrSelfPermission(
- permission.WRITE_SECURE_SETTINGS,
- "adas gnss bypass requires " + permission.WRITE_SECURE_SETTINGS);
+ LocationPermissions.enforceCallingOrSelfBypassPermission(mContext);
}
}
if (request.isLocationSettingsIgnored()) {
if (!isLocationProvider) {
- mContext.enforceCallingOrSelfPermission(
- permission.WRITE_SECURE_SETTINGS,
- "ignoring location settings requires " + permission.WRITE_SECURE_SETTINGS);
+ LocationPermissions.enforceCallingOrSelfBypassPermission(mContext);
}
}
@@ -1202,7 +1195,7 @@ public class LocationManagerService extends ILocationManager.Stub implements
userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, false, false, "setLocationEnabledForUser", null);
- mContext.enforceCallingOrSelfPermission(permission.WRITE_SECURE_SETTINGS, null);
+ mContext.enforceCallingOrSelfPermission(WRITE_SECURE_SETTINGS, null);
LocationManager.invalidateLocalLocationEnabledCaches();
mInjector.getSettingsHelper().setLocationEnabled(enabled, userId);
@@ -1220,7 +1213,7 @@ public class LocationManagerService extends ILocationManager.Stub implements
userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, false, false, "setAdasGnssLocationEnabledForUser", null);
- mContext.enforceCallingOrSelfPermission(permission.WRITE_SECURE_SETTINGS, null);
+ LocationPermissions.enforceCallingOrSelfBypassPermission(mContext);
mInjector.getLocationSettings().updateUserSettings(userId,
settings -> settings.withAdasGnssLocationEnabled(enabled));
diff --git a/services/core/java/com/android/server/location/LocationPermissions.java b/services/core/java/com/android/server/location/LocationPermissions.java
index 7528f8b6ea64..be702d906d3b 100644
--- a/services/core/java/com/android/server/location/LocationPermissions.java
+++ b/services/core/java/com/android/server/location/LocationPermissions.java
@@ -18,6 +18,8 @@ package com.android.server.location;
import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
+import static android.Manifest.permission.LOCATION_BYPASS;
+import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import android.annotation.IntDef;
@@ -121,6 +123,29 @@ public final class LocationPermissions {
}
/**
+ * Throws a security exception if the caller does not hold the required bypass permissions.
+ */
+ public static void enforceCallingOrSelfBypassPermission(Context context) {
+ enforceBypassPermission(context, Binder.getCallingUid(), Binder.getCallingPid());
+ }
+
+ /**
+ * Throws a security exception if the given uid/pid does not hold the required bypass
+ * perissions.
+ */
+ public static void enforceBypassPermission(Context context, int uid, int pid) {
+ if (context.checkPermission(WRITE_SECURE_SETTINGS, pid, uid) == PERMISSION_GRANTED) {
+ // TODO: disallow WRITE_SECURE_SETTINGS permission.
+ return;
+ }
+ if (context.checkPermission(LOCATION_BYPASS, pid, uid) == PERMISSION_GRANTED) {
+ return;
+ }
+ throw new SecurityException("uid" + uid + " does not have " + LOCATION_BYPASS
+ + "or " + WRITE_SECURE_SETTINGS + ".");
+ }
+
+ /**
* Returns false if the caller does not hold the required location permissions.
*/
public static boolean checkCallingOrSelfLocationPermission(Context context,
diff --git a/services/core/java/com/android/server/location/LocationShellCommand.java b/services/core/java/com/android/server/location/LocationShellCommand.java
index b65338d9691d..9c85d18515af 100644
--- a/services/core/java/com/android/server/location/LocationShellCommand.java
+++ b/services/core/java/com/android/server/location/LocationShellCommand.java
@@ -69,6 +69,14 @@ class LocationShellCommand extends BasicShellCommandHandler {
handleSetAdasGnssLocationEnabled();
return 0;
}
+ case "set-automotive-gnss-suspended": {
+ handleSetAutomotiveGnssSuspended();
+ return 0;
+ }
+ case "is-automotive-gnss-suspended": {
+ handleIsAutomotiveGnssSuspended();
+ return 0;
+ }
case "providers": {
String command = getNextArgRequired();
return parseProvidersCommand(command);
@@ -189,6 +197,24 @@ class LocationShellCommand extends BasicShellCommandHandler {
mService.setAdasGnssLocationEnabledForUser(enabled, userId);
}
+ private void handleSetAutomotiveGnssSuspended() {
+ if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+ throw new IllegalStateException("command only recognized on automotive devices");
+ }
+
+ boolean suspended = Boolean.parseBoolean(getNextArgRequired());
+
+ mService.setAutomotiveGnssSuspended(suspended);
+ }
+
+ private void handleIsAutomotiveGnssSuspended() {
+ if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE)) {
+ throw new IllegalStateException("command only recognized on automotive devices");
+ }
+
+ getOutPrintWriter().println(mService.isAutomotiveGnssSuspended());
+ }
+
private void handleAddTestProvider() {
String provider = getNextArgRequired();
@@ -359,6 +385,10 @@ class LocationShellCommand extends BasicShellCommandHandler {
pw.println(" set-adas-gnss-location-enabled true|false [--user <USER_ID>]");
pw.println(" Sets the ADAS GNSS location enabled state. If no user is specified,");
pw.println(" the current user is assumed.");
+ pw.println(" is-automotive-gnss-suspended");
+ pw.println(" Gets the automotive GNSS suspended state.");
+ pw.println(" set-automotive-gnss-suspended true|false");
+ pw.println(" Sets the automotive GNSS suspended state.");
}
pw.println(" providers");
pw.println(" The providers command is followed by a subcommand, as listed below:");
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 8f051303bf03..2d2edfa51896 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -20,6 +20,7 @@ import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE;
import static android.Manifest.permission.MANAGE_BIOMETRIC;
import static android.Manifest.permission.READ_CONTACTS;
import static android.Manifest.permission.SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS;
+import static android.Manifest.permission.SET_INITIAL_LOCK;
import static android.app.admin.DevicePolicyResources.Strings.Core.PROFILE_ENCRYPTED_DETAIL;
import static android.app.admin.DevicePolicyResources.Strings.Core.PROFILE_ENCRYPTED_MESSAGE;
import static android.app.admin.DevicePolicyResources.Strings.Core.PROFILE_ENCRYPTED_TITLE;
@@ -1650,9 +1651,13 @@ public class LockSettingsService extends ILockSettings.Stub {
"This operation requires secure lock screen feature");
}
if (!hasPermission(PERMISSION) && !hasPermission(SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS)) {
- throw new SecurityException(
- "setLockCredential requires SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS or "
- + PERMISSION);
+ if (hasPermission(SET_INITIAL_LOCK) && savedCredential.isNone()) {
+ // SET_INITIAL_LOCK can only be used if credential is not set.
+ } else {
+ throw new SecurityException(
+ "setLockCredential requires SET_AND_VERIFY_LOCKSCREEN_CREDENTIALS or "
+ + PERMISSION);
+ }
}
final long identity = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 303ab4669855..7f997df3b222 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -677,9 +677,9 @@ class MediaRouter2ServiceImpl {
UserRecord userRecord = routerRecord.mUserRecord;
userRecord.mRouterRecords.remove(routerRecord);
routerRecord.mUserRecord.mHandler.sendMessage(
- obtainMessage(UserHandler::notifyPreferredFeaturesChangedToManagers,
+ obtainMessage(UserHandler::notifyDiscoveryPreferenceChangedToManagers,
routerRecord.mUserRecord.mHandler,
- routerRecord.mPackageName, /* preferredFeatures=*/ null));
+ routerRecord.mPackageName, null));
userRecord.mHandler.sendMessage(
obtainMessage(UserHandler::updateDiscoveryPreferenceOnHandler,
userRecord.mHandler));
@@ -694,10 +694,10 @@ class MediaRouter2ServiceImpl {
}
routerRecord.mDiscoveryPreference = discoveryRequest;
routerRecord.mUserRecord.mHandler.sendMessage(
- obtainMessage(UserHandler::notifyPreferredFeaturesChangedToManagers,
+ obtainMessage(UserHandler::notifyDiscoveryPreferenceChangedToManagers,
routerRecord.mUserRecord.mHandler,
routerRecord.mPackageName,
- routerRecord.mDiscoveryPreference.getPreferredFeatures()));
+ routerRecord.mDiscoveryPreference));
routerRecord.mUserRecord.mHandler.sendMessage(
obtainMessage(UserHandler::updateDiscoveryPreferenceOnHandler,
routerRecord.mUserRecord.mHandler));
@@ -921,7 +921,7 @@ class MediaRouter2ServiceImpl {
// TODO: UserRecord <-> routerRecord, why do they reference each other?
// How about removing mUserRecord from routerRecord?
routerRecord.mUserRecord.mHandler.sendMessage(
- obtainMessage(UserHandler::notifyPreferredFeaturesChangedToManager,
+ obtainMessage(UserHandler::notifyDiscoveryPreferenceChangedToManager,
routerRecord.mUserRecord.mHandler, routerRecord, manager));
}
@@ -2118,19 +2118,19 @@ class MediaRouter2ServiceImpl {
}
}
- private void notifyPreferredFeaturesChangedToManager(@NonNull RouterRecord routerRecord,
+ private void notifyDiscoveryPreferenceChangedToManager(@NonNull RouterRecord routerRecord,
@NonNull IMediaRouter2Manager manager) {
try {
- manager.notifyPreferredFeaturesChanged(routerRecord.mPackageName,
- routerRecord.mDiscoveryPreference.getPreferredFeatures());
+ manager.notifyDiscoveryPreferenceChanged(routerRecord.mPackageName,
+ routerRecord.mDiscoveryPreference);
} catch (RemoteException ex) {
Slog.w(TAG, "Failed to notify preferred features changed."
+ " Manager probably died.", ex);
}
}
- private void notifyPreferredFeaturesChangedToManagers(@NonNull String routerPackageName,
- @Nullable List<String> preferredFeatures) {
+ private void notifyDiscoveryPreferenceChangedToManagers(@NonNull String routerPackageName,
+ @Nullable RouteDiscoveryPreference discoveryPreference) {
MediaRouter2ServiceImpl service = mServiceRef.get();
if (service == null) {
return;
@@ -2143,7 +2143,8 @@ class MediaRouter2ServiceImpl {
}
for (IMediaRouter2Manager manager : managers) {
try {
- manager.notifyPreferredFeaturesChanged(routerPackageName, preferredFeatures);
+ manager.notifyDiscoveryPreferenceChanged(routerPackageName,
+ discoveryPreference);
} catch (RemoteException ex) {
Slog.w(TAG, "Failed to notify preferred features changed."
+ " Manager probably died.", ex);
diff --git a/services/core/java/com/android/server/notification/NotificationComparator.java b/services/core/java/com/android/server/notification/NotificationComparator.java
index 583cdd599780..647a89efcbbf 100644
--- a/services/core/java/com/android/server/notification/NotificationComparator.java
+++ b/services/core/java/com/android/server/notification/NotificationComparator.java
@@ -104,6 +104,12 @@ public class NotificationComparator
return -1 * Boolean.compare(leftPeople, rightPeople);
}
+ boolean leftSystemMax = isSystemMax(left);
+ boolean rightSystemMax = isSystemMax(right);
+ if (leftSystemMax != rightSystemMax) {
+ return -1 * Boolean.compare(leftSystemMax, rightSystemMax);
+ }
+
if (leftImportance != rightImportance) {
// by importance, high to low
return -1 * Integer.compare(leftImportance, rightImportance);
@@ -173,6 +179,20 @@ public class NotificationComparator
return mMessagingUtil.isImportantMessaging(record.getSbn(), record.getImportance());
}
+ protected boolean isSystemMax(NotificationRecord record) {
+ if (record.getImportance() < NotificationManager.IMPORTANCE_HIGH) {
+ return false;
+ }
+ String packageName = record.getSbn().getPackageName();
+ if ("android".equals(packageName)) {
+ return true;
+ }
+ if ("com.android.systemui".equals(packageName)) {
+ return true;
+ }
+ return false;
+ }
+
private boolean isOngoing(NotificationRecord record) {
final int ongoingFlags = Notification.FLAG_FOREGROUND_SERVICE;
return (record.getNotification().flags & ongoingFlags) != 0;
diff --git a/services/core/java/com/android/server/notification/PermissionHelper.java b/services/core/java/com/android/server/notification/PermissionHelper.java
index 0cbdbc18ad39..5d18069ea205 100644
--- a/services/core/java/com/android/server/notification/PermissionHelper.java
+++ b/services/core/java/com/android/server/notification/PermissionHelper.java
@@ -19,7 +19,7 @@ package com.android.server.notification;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
import static android.content.pm.PackageManager.GET_PERMISSIONS;
-import static android.permission.PermissionManager.PERMISSION_GRANTED;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import android.Manifest;
import android.annotation.NonNull;
@@ -77,7 +77,8 @@ public final class PermissionHelper {
assertFlag();
final long callingId = Binder.clearCallingIdentity();
try {
- return mPmi.checkUidPermission(uid, NOTIFICATION_PERMISSION) == PERMISSION_GRANTED;
+ return mPmi.checkPostNotificationsPermissionGrantedOrLegacyAccess(uid)
+ == PERMISSION_GRANTED;
} finally {
Binder.restoreCallingIdentity(callingId);
}
diff --git a/services/core/java/com/android/server/notification/ZenModeFiltering.java b/services/core/java/com/android/server/notification/ZenModeFiltering.java
index b186f610d498..29aad63a1f4b 100644
--- a/services/core/java/com/android/server/notification/ZenModeFiltering.java
+++ b/services/core/java/com/android/server/notification/ZenModeFiltering.java
@@ -24,11 +24,14 @@ import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Context;
import android.media.AudioAttributes;
+import android.net.Uri;
import android.os.Bundle;
import android.os.UserHandle;
import android.provider.Settings.Global;
import android.service.notification.ZenModeConfig;
import android.telecom.TelecomManager;
+import android.telephony.PhoneNumberUtils;
+import android.telephony.TelephonyManager;
import android.util.ArrayMap;
import android.util.Slog;
@@ -36,6 +39,8 @@ import com.android.internal.messages.nano.SystemMessageProto;
import com.android.internal.util.NotificationMessagingUtil;
import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
import java.util.Date;
public class ZenModeFiltering {
@@ -64,13 +69,22 @@ public class ZenModeFiltering {
pw.print(prefix); pw.print("RepeatCallers.mThresholdMinutes=");
pw.println(REPEAT_CALLERS.mThresholdMinutes);
synchronized (REPEAT_CALLERS) {
- if (!REPEAT_CALLERS.mCalls.isEmpty()) {
- pw.print(prefix); pw.println("RepeatCallers.mCalls=");
- for (int i = 0; i < REPEAT_CALLERS.mCalls.size(); i++) {
+ if (!REPEAT_CALLERS.mTelCalls.isEmpty()) {
+ pw.print(prefix); pw.println("RepeatCallers.mTelCalls=");
+ for (int i = 0; i < REPEAT_CALLERS.mTelCalls.size(); i++) {
pw.print(prefix); pw.print(" ");
- pw.print(REPEAT_CALLERS.mCalls.keyAt(i));
+ pw.print(REPEAT_CALLERS.mTelCalls.keyAt(i));
pw.print(" at ");
- pw.println(ts(REPEAT_CALLERS.mCalls.valueAt(i)));
+ pw.println(ts(REPEAT_CALLERS.mTelCalls.valueAt(i)));
+ }
+ }
+ if (!REPEAT_CALLERS.mOtherCalls.isEmpty()) {
+ pw.print(prefix); pw.println("RepeatCallers.mOtherCalls=");
+ for (int i = 0; i < REPEAT_CALLERS.mOtherCalls.size(); i++) {
+ pw.print(prefix); pw.print(" ");
+ pw.print(REPEAT_CALLERS.mOtherCalls.keyAt(i));
+ pw.print(" at ");
+ pw.println(ts(REPEAT_CALLERS.mOtherCalls.valueAt(i)));
}
}
}
@@ -330,34 +344,39 @@ public class ZenModeFiltering {
}
private static class RepeatCallers {
- // Person : time
- private final ArrayMap<String, Long> mCalls = new ArrayMap<>();
+ // We keep a separate map per uri scheme to do more generous number-matching
+ // handling on telephone numbers specifically. For other inputs, we
+ // simply match directly on the string.
+ private final ArrayMap<String, Long> mTelCalls = new ArrayMap<>();
+ private final ArrayMap<String, Long> mOtherCalls = new ArrayMap<>();
private int mThresholdMinutes;
private synchronized void recordCall(Context context, Bundle extras) {
setThresholdMinutes(context);
if (mThresholdMinutes <= 0 || extras == null) return;
- final String peopleString = peopleString(extras);
- if (peopleString == null) return;
+ final String[] extraPeople = ValidateNotificationPeople.getExtraPeople(extras);
+ if (extraPeople == null || extraPeople.length == 0) return;
final long now = System.currentTimeMillis();
- cleanUp(mCalls, now);
- mCalls.put(peopleString, now);
+ cleanUp(mTelCalls, now);
+ cleanUp(mOtherCalls, now);
+ recordCallers(extraPeople, now);
}
private synchronized boolean isRepeat(Context context, Bundle extras) {
setThresholdMinutes(context);
if (mThresholdMinutes <= 0 || extras == null) return false;
- final String peopleString = peopleString(extras);
- if (peopleString == null) return false;
+ final String[] extraPeople = ValidateNotificationPeople.getExtraPeople(extras);
+ if (extraPeople == null || extraPeople.length == 0) return false;
final long now = System.currentTimeMillis();
- cleanUp(mCalls, now);
- return mCalls.containsKey(peopleString);
+ cleanUp(mTelCalls, now);
+ cleanUp(mOtherCalls, now);
+ return checkCallers(context, extraPeople);
}
private synchronized void cleanUp(ArrayMap<String, Long> calls, long now) {
final int N = calls.size();
for (int i = N - 1; i >= 0; i--) {
- final long time = mCalls.valueAt(i);
+ final long time = calls.valueAt(i);
if (time > now || (now - time) > mThresholdMinutes * 1000 * 60) {
calls.removeAt(i);
}
@@ -367,10 +386,16 @@ public class ZenModeFiltering {
// Clean up all calls that occurred after the given time.
// Used only for tests, to clean up after testing.
private synchronized void cleanUpCallsAfter(long timeThreshold) {
- for (int i = mCalls.size() - 1; i >= 0; i--) {
- final long time = mCalls.valueAt(i);
+ for (int i = mTelCalls.size() - 1; i >= 0; i--) {
+ final long time = mTelCalls.valueAt(i);
if (time > timeThreshold) {
- mCalls.removeAt(i);
+ mTelCalls.removeAt(i);
+ }
+ }
+ for (int j = mOtherCalls.size() - 1; j >= 0; j--) {
+ final long time = mOtherCalls.valueAt(j);
+ if (time > timeThreshold) {
+ mOtherCalls.removeAt(j);
}
}
}
@@ -382,21 +407,65 @@ public class ZenModeFiltering {
}
}
- private static String peopleString(Bundle extras) {
- final String[] extraPeople = ValidateNotificationPeople.getExtraPeople(extras);
- if (extraPeople == null || extraPeople.length == 0) return null;
- final StringBuilder sb = new StringBuilder();
- for (int i = 0; i < extraPeople.length; i++) {
- String extraPerson = extraPeople[i];
- if (extraPerson == null) continue;
- extraPerson = extraPerson.trim();
- if (extraPerson.isEmpty()) continue;
- if (sb.length() > 0) {
- sb.append('|');
+ private synchronized void recordCallers(String[] people, long now) {
+ for (int i = 0; i < people.length; i++) {
+ String person = people[i];
+ if (person == null) continue;
+ final Uri uri = Uri.parse(person);
+ if ("tel".equals(uri.getScheme())) {
+ String tel = uri.getSchemeSpecificPart();
+ // while ideally we should not need to do this, sometimes we have seen tel
+ // numbers given in a url-encoded format
+ try {
+ tel = URLDecoder.decode(tel, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ // ignore, keep the original tel string
+ Slog.w(TAG, "unsupported encoding in tel: uri input");
+ }
+ mTelCalls.put(tel, now);
+ } else {
+ // for non-tel calls, store the entire string, uri-component and all
+ mOtherCalls.put(person, now);
}
- sb.append(extraPerson);
}
- return sb.length() == 0 ? null : sb.toString();
+ }
+
+ private synchronized boolean checkCallers(Context context, String[] people) {
+ // get the default country code for checking telephone numbers
+ final String defaultCountryCode =
+ context.getSystemService(TelephonyManager.class).getNetworkCountryIso();
+ for (int i = 0; i < people.length; i++) {
+ String person = people[i];
+ if (person == null) continue;
+ final Uri uri = Uri.parse(person);
+ if ("tel".equals(uri.getScheme())) {
+ String number = uri.getSchemeSpecificPart();
+ if (mTelCalls.containsKey(number)) {
+ // check directly via map first
+ return true;
+ } else {
+ // see if a number that matches via areSameNumber exists
+ String numberToCheck = number;
+ try {
+ numberToCheck = URLDecoder.decode(number, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ // ignore, continue to use the original string
+ Slog.w(TAG, "unsupported encoding in tel: uri input");
+ }
+ for (String prev : mTelCalls.keySet()) {
+ if (PhoneNumberUtils.areSamePhoneNumber(
+ numberToCheck, prev, defaultCountryCode)) {
+ return true;
+ }
+ }
+ }
+ } else {
+ if (mOtherCalls.containsKey(person)) {
+ return true;
+ }
+ }
+ }
+ return false;
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 99f70b206b65..4b592062c888 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -922,7 +922,7 @@ class PackageManagerShellCommand extends ShellCommand {
final List<SharedLibraryInfo> libs = libsSlice.getList();
for (int l = 0, lsize = libs.size(); l < lsize; ++l) {
SharedLibraryInfo lib = libs.get(l);
- if (lib.getType() == SharedLibraryInfo.TYPE_SDK) {
+ if (lib.getType() == SharedLibraryInfo.TYPE_SDK_PACKAGE) {
name = lib.getName() + ":" + lib.getLongVersion();
break;
}
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 1fa901352c3d..9bcb7242b645 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -285,6 +285,19 @@ public class UserRestrictionsUtils {
);
/**
+ * User restrictions available to a device owner whose type is
+ * {@link android.app.admin.DevicePolicyManager#DEVICE_OWNER_TYPE_FINANCED}.
+ */
+ private static final Set<String> FINANCED_DEVICE_OWNER_RESTRICTIONS = Sets.newArraySet(
+ UserManager.DISALLOW_ADD_USER,
+ UserManager.DISALLOW_DEBUGGING_FEATURES,
+ UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES,
+ UserManager.DISALLOW_SAFE_BOOT,
+ UserManager.DISALLOW_CONFIG_DATE_TIME,
+ UserManager.DISALLOW_OUTGOING_CALLS
+ );
+
+ /**
* Returns whether the given restriction name is valid (and logs it if it isn't).
*/
public static boolean isValidRestriction(@NonNull String restriction) {
@@ -458,6 +471,15 @@ public class UserRestrictionsUtils {
}
/**
+ * @return {@code true} only if the restriction is allowed for financed devices and can be set
+ * by a device owner. Otherwise, {@code false} would be returned.
+ */
+ public static boolean canFinancedDeviceOwnerChange(String restriction) {
+ return FINANCED_DEVICE_OWNER_RESTRICTIONS.contains(restriction)
+ && canDeviceOwnerChange(restriction);
+ }
+
+ /**
* Whether given user restriction should be enforced globally.
*/
public static boolean isGlobal(@UserManagerInternal.OwnerType int restrictionOwnerType,
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
index 7e59bd669824..f2b1a7119b84 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
@@ -92,7 +92,7 @@ public class AndroidPackageUtils {
AndroidPackageUtils.getAllCodePaths(pkg),
pkg.getSdkLibName(),
pkg.getSdkLibVersionMajor(),
- SharedLibraryInfo.TYPE_SDK,
+ SharedLibraryInfo.TYPE_SDK_PACKAGE,
new VersionedPackage(pkg.getManifestPackageName(),
pkg.getLongVersionCode()),
null, null, false /* isNative */);
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 317730a9f606..79c5ea2efefe 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -17,6 +17,7 @@
package com.android.server.pm.permission;
import static android.Manifest.permission.CAPTURE_AUDIO_HOTWORD;
+import static android.Manifest.permission.POST_NOTIFICATIONS;
import static android.Manifest.permission.RECORD_AUDIO;
import static android.Manifest.permission.UPDATE_APP_OPS_STATS;
import static android.app.AppOpsManager.ATTRIBUTION_CHAIN_ID_NONE;
@@ -608,6 +609,21 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
@Override
+ public int checkPostNotificationsPermissionGrantedOrLegacyAccess(int uid) {
+ int granted = PermissionManagerService.this.checkUidPermission(uid,
+ POST_NOTIFICATIONS);
+ AndroidPackage pkg = mPackageManagerInt.getPackage(uid);
+ if (granted != PermissionManager.PERMISSION_GRANTED) {
+ int flags = PermissionManagerService.this.getPermissionFlags(pkg.getPackageName(),
+ POST_NOTIFICATIONS, UserHandle.getUserId(uid));
+ if ((flags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
+ return PermissionManager.PERMISSION_GRANTED;
+ }
+ }
+ return granted;
+ }
+
+ @Override
public void startShellPermissionIdentityDelegation(int uid, @NonNull String packageName,
@Nullable List<String> permissionNames) {
Objects.requireNonNull(packageName, "packageName");
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index d2c4ec4cc5a5..812d7a04dc13 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -63,6 +63,17 @@ public interface PermissionManagerServiceInternal extends PermissionManagerInter
int checkUidPermission(int uid, @NonNull String permissionName);
/**
+ * Check whether a particular UID has been granted the POST_NOTIFICATIONS permission, or if
+ * access should be granted based on legacy access (currently symbolized by the REVIEW_REQUIRED
+ * permission flag
+ *
+ * @param uid the UID
+ * @return {@code PERMISSION_GRANTED} if the permission is granted, or legacy access is granted,
+ * {@code PERMISSION_DENIED} otherwise
+ */
+ int checkPostNotificationsPermissionGrantedOrLegacyAccess(int uid);
+
+ /**
* Adds a listener for runtime permission state (permissions or flags) changes.
*
* @param listener The listener.
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index e71ff784dc23..344edbbef9c7 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -47,6 +47,7 @@ import android.content.pm.ResolveInfo;
import android.graphics.drawable.Icon;
import android.hardware.biometrics.BiometricAuthenticator.Modality;
import android.hardware.biometrics.BiometricManager.BiometricMultiSensorMode;
+import android.hardware.biometrics.IBiometricContextListener;
import android.hardware.biometrics.IBiometricSysuiReceiver;
import android.hardware.biometrics.PromptInfo;
import android.hardware.display.DisplayManager;
@@ -894,6 +895,17 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
}
@Override
+ public void setBiometicContextListener(IBiometricContextListener listener) {
+ enforceStatusBarService();
+ if (mBar != null) {
+ try {
+ mBar.setBiometicContextListener(listener);
+ } catch (RemoteException ex) {
+ }
+ }
+ }
+
+ @Override
public void setUdfpsHbmListener(IUdfpsHbmListener listener) {
enforceStatusBarService();
if (mBar != null) {
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 9bed24d05f3d..52f7d101ce99 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -122,7 +122,8 @@ public class TrustManagerService extends SystemService {
private static final int MSG_DISPATCH_UNLOCK_LOCKOUT = 13;
private static final int MSG_REFRESH_DEVICE_LOCKED_FOR_USER = 14;
private static final int MSG_SCHEDULE_TRUST_TIMEOUT = 15;
- public static final int MSG_USER_REQUESTED_UNLOCK = 16;
+ private static final int MSG_USER_REQUESTED_UNLOCK = 16;
+ private static final int MSG_ENABLE_TRUST_AGENT = 17;
private static final String REFRESH_DEVICE_LOCKED_EXCEPT_USER = "except";
@@ -631,6 +632,24 @@ public class TrustManagerService extends SystemService {
}
}
+
+ /**
+ * Uses {@link LockPatternUtils} to enable the setting for trust agent in the specified
+ * component name. This should only be used for testing.
+ */
+ private void enableTrustAgentForUserForTest(@NonNull ComponentName componentName, int userId) {
+ Log.i(TAG,
+ "Enabling trust agent " + componentName.flattenToString() + " for user " + userId);
+ List<ComponentName> agents =
+ new ArrayList<>(mLockPatternUtils.getEnabledTrustAgents(userId));
+ if (!agents.contains(componentName)) {
+ agents.add(componentName);
+ }
+ // Even if the agent was already there, we still call setEnabledTrustAgents to trigger a
+ // refresh of installed agents.
+ mLockPatternUtils.setEnabledTrustAgents(agents, userId);
+ }
+
boolean isDeviceLockedInner(int userId) {
synchronized (mDeviceLockedForUser) {
return mDeviceLockedForUser.get(userId, true);
@@ -929,6 +948,7 @@ public class TrustManagerService extends SystemService {
continue;
}
allowedAgents.add(resolveInfo);
+ if (DEBUG) Slog.d(TAG, "Adding agent " + getComponentName(resolveInfo));
}
return allowedAgents;
}
@@ -1158,6 +1178,13 @@ public class TrustManagerService extends SystemService {
}
@Override
+ public void enableTrustAgentForUserForTest(ComponentName componentName, int userId)
+ throws RemoteException {
+ enforceReportPermission();
+ mHandler.obtainMessage(MSG_ENABLE_TRUST_AGENT, userId, 0, componentName).sendToTarget();
+ }
+
+ @Override
public void reportKeyguardShowingChanged() throws RemoteException {
enforceReportPermission();
// coalesce refresh messages.
@@ -1433,6 +1460,9 @@ public class TrustManagerService extends SystemService {
// This is also called when the security mode of a user changes.
refreshDeviceLockedForUser(UserHandle.USER_ALL);
break;
+ case MSG_ENABLE_TRUST_AGENT:
+ enableTrustAgentForUserForTest((ComponentName) msg.obj, msg.arg1);
+ break;
case MSG_KEYGUARD_SHOWING_CHANGED:
refreshDeviceLockedForUser(mCurrentUser);
break;
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 3908874d854d..3fe616660284 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -716,6 +716,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
@Nullable
private Rect mLetterboxBoundsForFixedOrientationAndAspectRatio;
+ // Whether the activity is eligible to be letterboxed for fixed orientation with respect to its
+ // requested orientation, even when it's letterbox for another reason (e.g., size compat mode)
+ // and therefore #isLetterboxedForFixedOrientationAndAspectRatio returns false.
+ private boolean mIsEligibleForFixedOrientationLetterbox;
+
// State of the Camera app compat control which is used to correct stretched viewfinder
// in apps that don't handle all possible configurations and changes between them correctly.
@CameraCompatControlState
@@ -6929,7 +6934,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
@Override
void prepareSurfaces() {
- final boolean show = isVisible() || isAnimating(TRANSITION | PARENTS,
+ final boolean show = isVisible() || isAnimating(PARENTS,
ANIMATION_TYPE_APP_TRANSITION | ANIMATION_TYPE_RECENTS);
if (mSurfaceControl != null) {
@@ -7627,6 +7632,24 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
/**
+ * Whether this activity is eligible for letterbox eduction.
+ *
+ * <p>Conditions that need to be met:
+ *
+ * <ul>
+ * <li>{@link LetterboxConfiguration#getIsEducationEnabled} is true.
+ * <li>The activity is eligible for fixed orientation letterbox.
+ * <li>The activity is in fullscreen.
+ * </ul>
+ */
+ // TODO(b/215316431): Add tests
+ boolean isEligibleForLetterboxEducation() {
+ return mWmService.mLetterboxConfiguration.getIsEducationEnabled()
+ && mIsEligibleForFixedOrientationLetterbox
+ && getWindowingMode() == WINDOWING_MODE_FULLSCREEN;
+ }
+
+ /**
* In some cases, applying insets to bounds changes the orientation. For example, if a
* close-to-square display rotates to portrait to respect a portrait orientation activity, after
* insets such as the status and nav bars are applied, the activity may actually have a
@@ -7688,6 +7711,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
private void resolveFixedOrientationConfiguration(@NonNull Configuration newParentConfig,
int windowingMode) {
mLetterboxBoundsForFixedOrientationAndAspectRatio = null;
+ mIsEligibleForFixedOrientationLetterbox = false;
final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
final Rect stableBounds = new Rect();
// If orientation is respected when insets are applied, then stableBounds will be empty.
@@ -7727,8 +7751,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// make it fit the available bounds by scaling down its bounds.
final int forcedOrientation = getRequestedConfigurationOrientation();
- if (forcedOrientation == ORIENTATION_UNDEFINED
- || (forcedOrientation == parentOrientation && orientationRespectedWithInsets)) {
+ mIsEligibleForFixedOrientationLetterbox = forcedOrientation != ORIENTATION_UNDEFINED
+ && forcedOrientation != parentOrientation;
+
+ if (!mIsEligibleForFixedOrientationLetterbox && (forcedOrientation == ORIENTATION_UNDEFINED
+ || orientationRespectedWithInsets)) {
return;
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 4009220d1008..c87027dde3ad 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -5486,26 +5486,46 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}
void updateKeepClearAreas() {
+ final List<Rect> restrictedKeepClearAreas = new ArrayList();
+ final List<Rect> unrestrictedKeepClearAreas = new ArrayList();
+ getKeepClearAreas(restrictedKeepClearAreas, unrestrictedKeepClearAreas);
mWmService.mDisplayNotificationController.dispatchKeepClearAreasChanged(
- this, getKeepClearAreas());
+ this, restrictedKeepClearAreas, unrestrictedKeepClearAreas);
}
/**
- * Returns all keep-clear areas from visible windows on this display.
+ * Fills {@param outRestricted} with all keep-clear areas from visible, relevant windows
+ * on this display, which set restricted keep-clear areas.
+ * Fills {@param outUnrestricted} with keep-clear areas from visible, relevant windows on this
+ * display, which set unrestricted keep-clear areas.
+ *
+ * For context on restricted vs unrestricted keep-clear areas, see
+ * {@link android.Manifest.permission.USE_UNRESTRICTED_KEEP_CLEAR_AREAS}.
*/
- ArrayList<Rect> getKeepClearAreas() {
- final ArrayList<Rect> keepClearAreas = new ArrayList<Rect>();
+ void getKeepClearAreas(List<Rect> outRestricted, List<Rect> outUnrestricted) {
final Matrix tmpMatrix = new Matrix();
final float[] tmpFloat9 = new float[9];
forAllWindows(w -> {
if (w.isVisible() && !w.inPinnedWindowingMode()) {
- keepClearAreas.addAll(w.getKeepClearAreas(tmpMatrix, tmpFloat9));
+ if (w.mSession.mSetsUnrestrictedKeepClearAreas) {
+ outUnrestricted.addAll(w.getKeepClearAreas(tmpMatrix, tmpFloat9));
+ } else {
+ outRestricted.addAll(w.getKeepClearAreas(tmpMatrix, tmpFloat9));
+ }
}
// We stop traversing when we reach the base of a fullscreen app.
return w.getWindowType() == TYPE_BASE_APPLICATION
&& w.getWindowingMode() == WINDOWING_MODE_FULLSCREEN;
}, true);
+ }
+
+ /**
+ * Returns all keep-clear areas from visible, relevant windows on this display.
+ */
+ ArrayList<Rect> getKeepClearAreas() {
+ final ArrayList<Rect> keepClearAreas = new ArrayList<Rect>();
+ getKeepClearAreas(keepClearAreas, keepClearAreas);
return keepClearAreas;
}
diff --git a/services/core/java/com/android/server/wm/DisplayWindowListenerController.java b/services/core/java/com/android/server/wm/DisplayWindowListenerController.java
index 276dbe9c844a..e18d5396831a 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowListenerController.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowListenerController.java
@@ -120,12 +120,13 @@ class DisplayWindowListenerController {
mDisplayListeners.finishBroadcast();
}
- void dispatchKeepClearAreasChanged(DisplayContent display, List<Rect> keepClearAreas) {
+ void dispatchKeepClearAreasChanged(DisplayContent display, List<Rect> restricted,
+ List<Rect> unrestricted) {
int count = mDisplayListeners.beginBroadcast();
for (int i = 0; i < count; ++i) {
try {
mDisplayListeners.getBroadcastItem(i).onKeepClearAreasChanged(
- display.mDisplayId, keepClearAreas);
+ display.mDisplayId, restricted, unrestricted);
} catch (RemoteException e) {
}
}
diff --git a/services/core/java/com/android/server/wm/LetterboxConfiguration.java b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
index 1955e30aab30..ad2767c41e82 100644
--- a/services/core/java/com/android/server/wm/LetterboxConfiguration.java
+++ b/services/core/java/com/android/server/wm/LetterboxConfiguration.java
@@ -126,6 +126,9 @@ final class LetterboxConfiguration {
@LetterboxReachabilityPosition
private volatile int mLetterboxPositionForReachability;
+ // Whether education is allowed for letterboxed fullscreen apps.
+ private boolean mIsEducationEnabled;
+
LetterboxConfiguration(Context systemUiContext) {
mContext = systemUiContext;
mFixedOrientationLetterboxAspectRatio = mContext.getResources().getFloat(
@@ -143,6 +146,8 @@ final class LetterboxConfiguration {
R.bool.config_letterboxIsReachabilityEnabled);
mDefaultPositionForReachability = readLetterboxReachabilityPositionFromConfig(mContext);
mLetterboxPositionForReachability = mDefaultPositionForReachability;
+ mIsEducationEnabled = mContext.getResources().getBoolean(
+ R.bool.config_letterboxIsEducationEnabled);
}
/**
@@ -501,4 +506,27 @@ final class LetterboxConfiguration {
mLetterboxPositionForReachability = Math.max(mLetterboxPositionForReachability - 1, 0);
}
+ /**
+ * Whether education is allowed for letterboxed fullscreen apps.
+ */
+ boolean getIsEducationEnabled() {
+ return mIsEducationEnabled;
+ }
+
+ /**
+ * Overrides whether education is allowed for letterboxed fullscreen apps.
+ */
+ void setIsEducationEnabled(boolean enabled) {
+ mIsEducationEnabled = enabled;
+ }
+
+ /**
+ * Resets whether education is allowed for letterboxed fullscreen apps to
+ * {@link R.bool.config_letterboxIsEducationEnabled}.
+ */
+ void resetIsEducationEnabled() {
+ mIsEducationEnabled = mContext.getResources().getBoolean(
+ R.bool.config_letterboxIsEducationEnabled);
+ }
+
}
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 98acc4607d18..2ae2b4370522 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -19,6 +19,7 @@ package com.android.server.wm;
import static android.Manifest.permission.HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
import static android.Manifest.permission.HIDE_OVERLAY_WINDOWS;
import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
+import static android.Manifest.permission.SET_UNRESTRICTED_KEEP_CLEAR_AREAS;
import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
import static android.Manifest.permission.SYSTEM_APPLICATION_OVERLAY;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
@@ -114,6 +115,7 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
private String mRelayoutTag;
private final InsetsVisibilities mDummyRequestedVisibilities = new InsetsVisibilities();
private final InsetsSourceControl[] mDummyControls = new InsetsSourceControl[0];
+ final boolean mSetsUnrestrictedKeepClearAreas;
public Session(WindowManagerService service, IWindowSessionCallback callback) {
mService = service;
@@ -132,6 +134,9 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
== PERMISSION_GRANTED;
mCanStartTasksFromRecents = service.mContext.checkCallingOrSelfPermission(
START_TASKS_FROM_RECENTS) == PERMISSION_GRANTED;
+ mSetsUnrestrictedKeepClearAreas =
+ service.mContext.checkCallingOrSelfPermission(SET_UNRESTRICTED_KEEP_CLEAR_AREAS)
+ == PERMISSION_GRANTED;
mShowingAlertWindowNotificationAllowed = mService.mShowAlertWindowNotifications;
mDragDropController = mService.mDragDropController;
StringBuilder sb = new StringBuilder();
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 7d06526e18b5..97735a29b027 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3434,6 +3434,9 @@ class Task extends TaskFragment {
// Whether the direct top activity is in size compat mode on foreground.
info.topActivityInSizeCompat = isTopActivityResumed
&& mReuseActivitiesReport.top.inSizeCompatMode();
+ // Whether the direct top activity is eligible for letterbox education.
+ info.topActivityEligibleForLetterboxEducation = isTopActivityResumed
+ && mReuseActivitiesReport.top.isEligibleForLetterboxEducation();
// Whether the direct top activity requested showing camera compat control.
info.cameraCompatControlState = isTopActivityResumed
? mReuseActivitiesReport.top.getCameraCompatControlState()
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index 0f8587c99958..1cf4c1b0fbb2 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -822,6 +822,29 @@ public class WindowManagerShellCommand extends ShellCommand {
return 0;
}
+ private int runSetLetterboxIsEducationEnabled(PrintWriter pw) throws RemoteException {
+ String arg = getNextArg();
+ final boolean enabled;
+ switch (arg) {
+ case "true":
+ case "1":
+ enabled = true;
+ break;
+ case "false":
+ case "0":
+ enabled = false;
+ break;
+ default:
+ getErrPrintWriter().println("Error: expected true, 1, false, 0, but got " + arg);
+ return -1;
+ }
+
+ synchronized (mInternal.mGlobalLock) {
+ mLetterboxConfiguration.setIsEducationEnabled(enabled);
+ }
+ return 0;
+ }
+
private int runSetLetterboxStyle(PrintWriter pw) throws RemoteException {
if (peekNextArg() == null) {
getErrPrintWriter().println("Error: No arguments provided.");
@@ -859,6 +882,9 @@ public class WindowManagerShellCommand extends ShellCommand {
case "--defaultPositionForReachability":
runSetLetterboxDefaultPositionForReachability(pw);
break;
+ case "--isEducationEnabled":
+ runSetLetterboxIsEducationEnabled(pw);
+ break;
default:
getErrPrintWriter().println(
"Error: Unrecognized letterbox style option: " + arg);
@@ -903,6 +929,9 @@ public class WindowManagerShellCommand extends ShellCommand {
case "defaultPositionForReachability":
mLetterboxConfiguration.getDefaultPositionForReachability();
break;
+ case "isEducationEnabled":
+ mLetterboxConfiguration.getIsEducationEnabled();
+ break;
default:
getErrPrintWriter().println(
"Error: Unrecognized letterbox style option: " + arg);
@@ -998,6 +1027,7 @@ public class WindowManagerShellCommand extends ShellCommand {
mLetterboxConfiguration.resetLetterboxHorizontalPositionMultiplier();
mLetterboxConfiguration.resetIsReachabilityEnabled();
mLetterboxConfiguration.resetDefaultPositionForReachability();
+ mLetterboxConfiguration.resetIsEducationEnabled();
}
}
@@ -1014,6 +1044,8 @@ public class WindowManagerShellCommand extends ShellCommand {
pw.println("Default position for reachability: "
+ LetterboxConfiguration.letterboxReachabilityPositionToString(
mLetterboxConfiguration.getDefaultPositionForReachability()));
+ pw.println("Is education enabled: "
+ + mLetterboxConfiguration.getIsEducationEnabled());
pw.println("Background type: "
+ LetterboxConfiguration.letterboxBackgroundTypeToString(
@@ -1154,10 +1186,12 @@ public class WindowManagerShellCommand extends ShellCommand {
pw.println(" --defaultPositionForReachability [left|center|right]");
pw.println(" Default horizontal position of app window when reachability is.");
pw.println(" enabled.");
+ pw.println(" --isEducationEnabled [true|1|false|0]");
+ pw.println(" Whether education is allowed for letterboxed fullscreen apps.");
pw.println(" reset-letterbox-style [aspectRatio|cornerRadius|backgroundType");
pw.println(" |backgroundColor|wallpaperBlurRadius|wallpaperDarkScrimAlpha");
pw.println(" |horizontalPositionMultiplier|isReachabilityEnabled");
- pw.println(" |defaultPositionMultiplierForReachability]");
+ pw.println(" isEducationEnabled||defaultPositionMultiplierForReachability]");
pw.println(" Resets overrides to default values for specified properties separated");
pw.println(" by space, e.g. 'reset-letterbox-style aspectRatio cornerRadius'.");
pw.println(" If no arguments provided, all values will be reset.");
diff --git a/services/core/jni/com_android_server_companion_virtual_InputController.cpp b/services/core/jni/com_android_server_companion_virtual_InputController.cpp
index 43018a900f4c..adc91fc3f2e8 100644
--- a/services/core/jni/com_android_server_companion_virtual_InputController.cpp
+++ b/services/core/jni/com_android_server_companion_virtual_InputController.cpp
@@ -186,7 +186,7 @@ static std::map<int, int> KEY_CODE_MAPPING = {
};
/** Creates a new uinput device and assigns a file descriptor. */
-static int openUinput(const char* readableName, jint vendorId, jint productId,
+static int openUinput(const char* readableName, jint vendorId, jint productId, const char* phys,
DeviceType deviceType, jint screenHeight, jint screenWidth) {
android::base::unique_fd fd(TEMP_FAILURE_RETRY(::open("/dev/uinput", O_WRONLY | O_NONBLOCK)));
if (fd < 0) {
@@ -194,6 +194,8 @@ static int openUinput(const char* readableName, jint vendorId, jint productId,
return -errno;
}
+ ioctl(fd, UI_SET_PHYS, phys);
+
ioctl(fd, UI_SET_EVBIT, EV_KEY);
ioctl(fd, UI_SET_EVBIT, EV_SYN);
switch (deviceType) {
@@ -295,28 +297,30 @@ static int openUinput(const char* readableName, jint vendorId, jint productId,
return fd.release();
}
-static int openUinputJni(JNIEnv* env, jstring name, jint vendorId, jint productId,
+static int openUinputJni(JNIEnv* env, jstring name, jint vendorId, jint productId, jstring phys,
DeviceType deviceType, int screenHeight, int screenWidth) {
ScopedUtfChars readableName(env, name);
- return openUinput(readableName.c_str(), vendorId, productId, deviceType, screenHeight,
- screenWidth);
+ ScopedUtfChars readablePhys(env, phys);
+ return openUinput(readableName.c_str(), vendorId, productId, readablePhys.c_str(), deviceType,
+ screenHeight, screenWidth);
}
static int nativeOpenUinputKeyboard(JNIEnv* env, jobject thiz, jstring name, jint vendorId,
- jint productId) {
- return openUinputJni(env, name, vendorId, productId, DeviceType::KEYBOARD, /* screenHeight */ 0,
- /* screenWidth */ 0);
+ jint productId, jstring phys) {
+ return openUinputJni(env, name, vendorId, productId, phys, DeviceType::KEYBOARD,
+ /* screenHeight */ 0, /* screenWidth */ 0);
}
static int nativeOpenUinputMouse(JNIEnv* env, jobject thiz, jstring name, jint vendorId,
- jint productId) {
- return openUinputJni(env, name, vendorId, productId, DeviceType::MOUSE, /* screenHeight */ 0,
- /* screenWidth */ 0);
+ jint productId, jstring phys) {
+ return openUinputJni(env, name, vendorId, productId, phys, DeviceType::MOUSE,
+ /* screenHeight */ 0, /* screenWidth */ 0);
}
static int nativeOpenUinputTouchscreen(JNIEnv* env, jobject thiz, jstring name, jint vendorId,
- jint productId, jint height, jint width) {
- return openUinputJni(env, name, vendorId, productId, DeviceType::TOUCHSCREEN, height, width);
+ jint productId, jstring phys, jint height, jint width) {
+ return openUinputJni(env, name, vendorId, productId, phys, DeviceType::TOUCHSCREEN, height,
+ width);
}
static bool nativeCloseUinput(JNIEnv* env, jobject thiz, jint fd) {
@@ -435,9 +439,11 @@ static bool nativeWriteScrollEvent(JNIEnv* env, jobject thiz, jint fd, jfloat xA
}
static JNINativeMethod methods[] = {
- {"nativeOpenUinputKeyboard", "(Ljava/lang/String;II)I", (void*)nativeOpenUinputKeyboard},
- {"nativeOpenUinputMouse", "(Ljava/lang/String;II)I", (void*)nativeOpenUinputMouse},
- {"nativeOpenUinputTouchscreen", "(Ljava/lang/String;IIII)I",
+ {"nativeOpenUinputKeyboard", "(Ljava/lang/String;IILjava/lang/String;)I",
+ (void*)nativeOpenUinputKeyboard},
+ {"nativeOpenUinputMouse", "(Ljava/lang/String;IILjava/lang/String;)I",
+ (void*)nativeOpenUinputMouse},
+ {"nativeOpenUinputTouchscreen", "(Ljava/lang/String;IILjava/lang/String;II)I",
(void*)nativeOpenUinputTouchscreen},
{"nativeCloseUinput", "(I)Z", (void*)nativeCloseUinput},
{"nativeWriteKeyEvent", "(III)Z", (void*)nativeWriteKeyEvent},
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 0da8f7ef0dea..161d7ce350fc 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -1504,11 +1504,14 @@ static jboolean android_location_gnss_hal_GnssNative_set_position_mode(
JNIEnv* /* env */, jclass, jint mode, jint recurrence, jint min_interval,
jint preferred_accuracy, jint preferred_time, jboolean low_power_mode) {
if (gnssHalAidl != nullptr && gnssHalAidl->getInterfaceVersion() >= 2) {
- auto status = gnssHalAidl->setPositionMode(static_cast<IGnssAidl::GnssPositionMode>(mode),
- static_cast<IGnssAidl::GnssPositionRecurrence>(
- recurrence),
- min_interval, preferred_accuracy, preferred_time,
- low_power_mode);
+ IGnssAidl::PositionModeOptions options;
+ options.mode = static_cast<IGnssAidl::GnssPositionMode>(mode);
+ options.recurrence = static_cast<IGnssAidl::GnssPositionRecurrence>(recurrence);
+ options.minIntervalMs = min_interval;
+ options.preferredAccuracyMeters = preferred_accuracy;
+ options.preferredTimeMs = preferred_time;
+ options.lowPowerMode = low_power_mode;
+ auto status = gnssHalAidl->setPositionMode(options);
return checkAidlStatus(status, "IGnssAidl setPositionMode() failed.");
}
diff --git a/services/core/jni/gnss/AGnssRil.cpp b/services/core/jni/gnss/AGnssRil.cpp
index d760b4d2195e..424ffd463713 100644
--- a/services/core/jni/gnss/AGnssRil.cpp
+++ b/services/core/jni/gnss/AGnssRil.cpp
@@ -41,7 +41,7 @@ jboolean AGnssRil::setCallback(const std::unique_ptr<AGnssRilCallback>& callback
jboolean AGnssRil::setSetId(jint type, const jstring& setid_string) {
JNIEnv* env = getJniEnv();
ScopedJniString jniSetId{env, setid_string};
- auto status = mIAGnssRil->setSetId((IAGnssRil::SetIDType)type, jniSetId.c_str());
+ auto status = mIAGnssRil->setSetId((IAGnssRil::SetIdType)type, jniSetId.c_str());
return checkAidlStatus(status, "IAGnssRilAidl setSetId() failed.");
}
diff --git a/services/core/jni/gnss/GnssMeasurementCallback.cpp b/services/core/jni/gnss/GnssMeasurementCallback.cpp
index fbdeec6b897e..6c0d5d984980 100644
--- a/services/core/jni/gnss/GnssMeasurementCallback.cpp
+++ b/services/core/jni/gnss/GnssMeasurementCallback.cpp
@@ -359,9 +359,7 @@ void GnssMeasurementCallbackAidl::translateAndSetGnssData(const GnssData& data)
jobjectArray measurementArray = translateAllGnssMeasurements(env, data.measurements);
jobjectArray gnssAgcArray = nullptr;
- if (data.gnssAgcs.has_value()) {
- gnssAgcArray = translateAllGnssAgcs(env, data.gnssAgcs.value());
- }
+ gnssAgcArray = translateAllGnssAgcs(env, data.gnssAgcs);
setMeasurementData(env, mCallbacksObj, clock, measurementArray, gnssAgcArray);
env->DeleteLocalRef(clock);
@@ -508,8 +506,8 @@ jobjectArray GnssMeasurementCallbackAidl::translateAllGnssMeasurements(
return gnssMeasurementArray;
}
-jobjectArray GnssMeasurementCallbackAidl::translateAllGnssAgcs(
- JNIEnv* env, const std::vector<std::optional<GnssAgc>>& agcs) {
+jobjectArray GnssMeasurementCallbackAidl::translateAllGnssAgcs(JNIEnv* env,
+ const std::vector<GnssAgc>& agcs) {
if (agcs.size() == 0) {
return nullptr;
}
@@ -518,10 +516,7 @@ jobjectArray GnssMeasurementCallbackAidl::translateAllGnssAgcs(
env->NewObjectArray(agcs.size(), class_gnssAgc, nullptr /* initialElement */);
for (uint16_t i = 0; i < agcs.size(); ++i) {
- if (!agcs[i].has_value()) {
- continue;
- }
- const GnssAgc& gnssAgc = agcs[i].value();
+ const GnssAgc& gnssAgc = agcs[i];
jobject agcBuilderObject = env->NewObject(class_gnssAgcBuilder, method_gnssAgcBuilderCtor);
env->CallObjectMethod(agcBuilderObject, method_gnssAgcBuilderSetLevelDb,
diff --git a/services/core/jni/gnss/GnssMeasurementCallback.h b/services/core/jni/gnss/GnssMeasurementCallback.h
index 9b346312db38..17af94939666 100644
--- a/services/core/jni/gnss/GnssMeasurementCallback.h
+++ b/services/core/jni/gnss/GnssMeasurementCallback.h
@@ -62,8 +62,8 @@ private:
jobjectArray translateAllGnssMeasurements(
JNIEnv* env, const std::vector<hardware::gnss::GnssMeasurement>& measurements);
- jobjectArray translateAllGnssAgcs(
- JNIEnv* env, const std::vector<std::optional<hardware::gnss::GnssData::GnssAgc>>& agcs);
+ jobjectArray translateAllGnssAgcs(JNIEnv* env,
+ const std::vector<hardware::gnss::GnssData::GnssAgc>& agcs);
void translateAndSetGnssData(const hardware::gnss::GnssData& data);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 733cfcdfaea5..3bda7bf049c4 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -56,6 +56,8 @@ import static android.app.admin.DevicePolicyManager.DELEGATION_NETWORK_LOGGING;
import static android.app.admin.DevicePolicyManager.DELEGATION_PACKAGE_ACCESS;
import static android.app.admin.DevicePolicyManager.DELEGATION_PERMISSION_GRANT;
import static android.app.admin.DevicePolicyManager.DELEGATION_SECURITY_LOGGING;
+import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_DEFAULT;
+import static android.app.admin.DevicePolicyManager.DEVICE_OWNER_TYPE_FINANCED;
import static android.app.admin.DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER;
import static android.app.admin.DevicePolicyManager.EXTRA_RESOURCE_ID;
import static android.app.admin.DevicePolicyManager.EXTRA_RESOURCE_TYPE_DRAWABLE;
@@ -66,9 +68,12 @@ import static android.app.admin.DevicePolicyManager.ID_TYPE_INDIVIDUAL_ATTESTATI
import static android.app.admin.DevicePolicyManager.ID_TYPE_MEID;
import static android.app.admin.DevicePolicyManager.ID_TYPE_SERIAL;
import static android.app.admin.DevicePolicyManager.LEAVE_ALL_SYSTEM_APPS_ENABLED;
+import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_HOME;
+import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS;
import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW;
+import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO;
import static android.app.admin.DevicePolicyManager.NEARBY_STREAMING_NOT_CONTROLLED_BY_POLICY;
import static android.app.admin.DevicePolicyManager.NON_ORG_OWNED_PROFILE_KEYGUARD_FEATURES_AFFECT_OWNER;
import static android.app.admin.DevicePolicyManager.OPERATION_SAFETY_REASON_NONE;
@@ -3918,8 +3923,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(
- isProfileOwner(caller) || isDeviceOwner(caller) || isSystemUid(caller)
- || isPasswordLimitingAdminTargetingP(caller));
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller)
+ || isSystemUid(caller) || isPasswordLimitingAdminTargetingP(caller));
if (parent) {
Preconditions.checkCallAuthorization(
@@ -4772,7 +4777,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(admin, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
+ || isProfileOwner(caller));
Preconditions.checkCallingUser(isManagedProfile(caller.getUserId()));
return !isSeparateProfileChallengeEnabled(caller.getUserId());
@@ -4860,12 +4866,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
enforceUserUnlocked(caller.getUserId());
if (parent) {
Preconditions.checkCallAuthorization(
- isDeviceOwner(caller) || isProfileOwner(caller) || isSystemUid(caller),
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller) || isSystemUid(caller),
"Only profile owner, device owner and system may call this method on parent.");
} else {
Preconditions.checkCallAuthorization(
hasCallingOrSelfPermission(REQUEST_PASSWORD_COMPLEXITY)
- || isDeviceOwner(caller) || isProfileOwner(caller),
+ || isDefaultDeviceOwner(caller) || isProfileOwner(caller),
"Must have " + REQUEST_PASSWORD_COMPLEXITY
+ " permission, or be a profile owner or device owner.");
}
@@ -4888,7 +4894,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
"Provided complexity is not one of the allowed values.");
final CallerIdentity caller = getCallerIdentity();
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller));
Preconditions.checkArgument(!calledOnParent || isProfileOwner(caller));
synchronized (getLockObject()) {
@@ -4968,7 +4975,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(
- isDeviceOwner(caller) || isProfileOwner(caller));
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller));
Preconditions.checkArgument(!calledOnParent || isProfileOwner(caller));
@@ -5160,7 +5167,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
// If caller has PO (or DO) throw or fail silently depending on its target SDK level.
- if (isDeviceOwner(caller) || isProfileOwner(caller)) {
+ if (isDefaultDeviceOwner(caller) || isProfileOwner(caller)) {
synchronized (getLockObject()) {
ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
if (getTargetSdk(admin.info.getPackageName(), userHandle) < Build.VERSION_CODES.O) {
@@ -5219,7 +5226,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return false;
}
- boolean callerIsDeviceOwnerAdmin = isDeviceOwner(caller);
+ boolean callerIsDeviceOwnerAdmin = isDefaultDeviceOwner(caller);
boolean doNotAskCredentialsOnBoot =
(flags & DevicePolicyManager.RESET_PASSWORD_DO_NOT_ASK_CREDENTIALS_ON_BOOT) != 0;
if (callerIsDeviceOwnerAdmin && doNotAskCredentialsOnBoot) {
@@ -5406,7 +5413,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(who, "ComponentName is null");
Preconditions.checkArgument(timeoutMs >= 0, "Timeout must not be a negative number.");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller));
// timeoutMs with value 0 means that the admin doesn't participate
// timeoutMs is clamped to the interval in case the internal constants change in the future
final long minimumStrongAuthTimeout = getMinimumStrongAuthTimeoutMs();
@@ -5575,7 +5583,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
private boolean canManageCaCerts(CallerIdentity caller) {
- return (caller.hasAdminComponent() && (isDeviceOwner(caller) || isProfileOwner(caller)))
+ return (caller.hasAdminComponent() && (isDefaultDeviceOwner(caller)
+ || isProfileOwner(caller)))
|| (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_CERT_INSTALL))
|| hasCallingOrSelfPermission(MANAGE_CA_CERTIFICATES);
}
@@ -5689,7 +5698,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final boolean isCallerDelegate = isCallerDelegate(caller, DELEGATION_CERT_INSTALL);
final boolean isCredentialManagementApp = isCredentialManagementApp(caller);
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDeviceOwner(caller)))
+ && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
|| (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
if (isCredentialManagementApp) {
Preconditions.checkCallAuthorization(!isUserSelectable, "The credential "
@@ -5754,7 +5763,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final boolean isCallerDelegate = isCallerDelegate(caller, DELEGATION_CERT_INSTALL);
final boolean isCredentialManagementApp = isCredentialManagementApp(caller);
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDeviceOwner(caller)))
+ && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
|| (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
if (isCredentialManagementApp) {
Preconditions.checkCallAuthorization(
@@ -5818,12 +5827,12 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
private boolean canInstallCertificates(CallerIdentity caller) {
- return isProfileOwner(caller) || isDeviceOwner(caller)
+ return isProfileOwner(caller) || isDefaultDeviceOwner(caller)
|| isCallerDelegate(caller, DELEGATION_CERT_INSTALL);
}
private boolean canChooseCertificates(CallerIdentity caller) {
- return isProfileOwner(caller) || isDeviceOwner(caller)
+ return isProfileOwner(caller) || isDefaultDeviceOwner(caller)
|| isCallerDelegate(caller, DELEGATION_CERT_SELECTION);
}
@@ -5871,7 +5880,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDeviceOwner(caller)))
+ && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
|| (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_CERT_SELECTION)));
final int granteeUid;
@@ -5984,7 +5993,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// If not, fall back to the device owner check.
Preconditions.checkCallAuthorization(
- isDeviceOwner(caller) || isCallerDelegate(caller, DELEGATION_CERT_INSTALL));
+ isDefaultDeviceOwner(caller) || isCallerDelegate(caller, DELEGATION_CERT_INSTALL));
}
@VisibleForTesting
@@ -6047,7 +6056,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
enforceIndividualAttestationSupportedIfRequested(attestationUtilsFlags);
} else {
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDeviceOwner(caller)))
+ && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
|| (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
if (isCredentialManagementApp) {
Preconditions.checkCallAuthorization(
@@ -6182,7 +6191,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final boolean isCallerDelegate = isCallerDelegate(caller, DELEGATION_CERT_INSTALL);
final boolean isCredentialManagementApp = isCredentialManagementApp(caller);
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDeviceOwner(caller)))
+ && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
|| (caller.hasPackage() && (isCallerDelegate || isCredentialManagementApp)));
if (isCredentialManagementApp) {
Preconditions.checkCallAuthorization(
@@ -6337,14 +6346,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final int userId = caller.getUserId();
// Ensure calling process is device/profile owner.
if (!Collections.disjoint(scopes, DEVICE_OWNER_OR_MANAGED_PROFILE_OWNER_DELEGATIONS)) {
- Preconditions.checkCallAuthorization(isDeviceOwner(caller)
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
|| (isProfileOwner(caller) && isManagedProfile(caller.getUserId())));
} else if (!Collections.disjoint(
scopes, DEVICE_OWNER_OR_ORGANIZATION_OWNED_MANAGED_PROFILE_OWNER_DELEGATIONS)) {
- Preconditions.checkCallAuthorization(isDeviceOwner(caller)
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
|| isProfileOwnerOfOrganizationOwnedDevice(caller));
} else {
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller));
}
synchronized (getLockObject()) {
@@ -6434,7 +6444,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// * Either it's a profile owner / device owner, if componentName is provided
// * Or it's an app querying its own delegation scopes
if (caller.hasAdminComponent()) {
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller));
} else {
Preconditions.checkCallAuthorization(isPackage(caller, delegatePackage),
String.format("Caller with uid %d is not %s", caller.getUid(),
@@ -6467,7 +6478,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// Retrieve the user ID of the calling process.
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller));
synchronized (getLockObject()) {
return getDelegatePackagesInternalLocked(scope, caller.getUserId());
}
@@ -6600,7 +6612,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final CallerIdentity caller = getCallerIdentity(who);
// Ensure calling process is device/profile owner.
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller));
synchronized (getLockObject()) {
final DevicePolicyData policy = getUserData(caller.getUserId());
@@ -6712,7 +6725,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller));
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_ALWAYS_ON_VPN_PACKAGE);
if (vpnPackage == null) {
@@ -6792,7 +6806,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(admin, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller));
return mInjector.binderWithCleanCallingIdentity(
() -> mInjector.getVpnManager().getAlwaysOnVpnPackageForUser(caller.getUserId()));
@@ -6818,7 +6833,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
caller = getCallerIdentity();
} else {
caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller));
}
return mInjector.binderWithCleanCallingIdentity(
@@ -6841,7 +6857,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(admin, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller));
return mInjector.binderWithCleanCallingIdentity(
() -> mInjector.getVpnManager().getVpnLockdownAllowlist(caller.getUserId()));
@@ -6946,8 +6963,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
+ "organization-owned device.");
}
if ((flags & WIPE_RESET_PROTECTION_DATA) != 0) {
- Preconditions.checkCallAuthorization(isDeviceOwner(caller)
- || calledByProfileOwnerOnOrgOwnedDevice,
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
+ || calledByProfileOwnerOnOrgOwnedDevice
+ || isFinancedDeviceOwner(caller),
"Only device owners or profile owners of organization-owned device can set "
+ "WIPE_RESET_PROTECTION_DATA");
}
@@ -7139,8 +7157,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
Preconditions.checkNotNull(who, "ComponentName is null");
CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller)
- || isProfileOwnerOfOrganizationOwnedDevice(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller));
checkCanExecuteOrThrowUnsafe(DevicePolicyManager
.OPERATION_SET_FACTORY_RESET_PROTECTION_POLICY);
@@ -7189,7 +7207,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
UserHandle.getUserId(frpManagementAgentUid));
} else {
Preconditions.checkCallAuthorization(
- isDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller));
+ isDefaultDeviceOwner(caller)
+ || isProfileOwnerOfOrganizationOwnedDevice(caller));
admin = getProfileOwnerOrDeviceOwnerLocked(caller);
}
}
@@ -7617,7 +7636,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public void setRecommendedGlobalProxy(ComponentName who, ProxyInfo proxyInfo) {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
checkAllUsersAreAffiliatedWithDevice();
mInjector.binderWithCleanCallingIdentity(
() -> mInjector.getConnectivityManager().setGlobalProxy(proxyInfo));
@@ -7915,7 +7934,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
final CallerIdentity caller = getCallerIdentity();
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller));
synchronized (getLockObject()) {
final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
@@ -7934,8 +7954,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(
- isProfileOwner(caller)
- || isDeviceOwner(caller)
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller)
|| hasCallingOrSelfPermission(permission.READ_NEARBY_STREAMING_POLICY));
synchronized (getLockObject()) {
@@ -7955,7 +7974,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
final CallerIdentity caller = getCallerIdentity();
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller));
synchronized (getLockObject()) {
final ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
@@ -7974,8 +7994,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(
- isProfileOwner(caller)
- || isDeviceOwner(caller)
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller)
|| hasCallingOrSelfPermission(permission.READ_NEARBY_STREAMING_POLICY));
synchronized (getLockObject()) {
@@ -8067,7 +8086,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isProfileOwnerOnUser0(caller)
- || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDeviceOwner(caller));
+ || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(caller));
mInjector.binderWithCleanCallingIdentity(() ->
mInjector.settingsGlobalPutInt(Settings.Global.AUTO_TIME, enabled ? 1 : 0));
@@ -8091,7 +8110,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isProfileOwnerOnUser0(caller)
- || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDeviceOwner(caller));
+ || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(caller));
return mInjector.settingsGlobalGetInt(Global.AUTO_TIME, 0) > 0;
}
@@ -8108,7 +8127,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isProfileOwnerOnUser0(caller)
- || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDeviceOwner(caller));
+ || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(caller));
mInjector.binderWithCleanCallingIdentity(() ->
mInjector.settingsGlobalPutInt(Global.AUTO_TIME_ZONE, enabled ? 1 : 0));
@@ -8132,7 +8151,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(isProfileOwnerOnUser0(caller)
- || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDeviceOwner(caller));
+ || isProfileOwnerOfOrganizationOwnedDevice(caller) || isDefaultDeviceOwner(caller));
return mInjector.settingsGlobalGetInt(Global.AUTO_TIME_ZONE, 0) > 0;
}
@@ -8161,7 +8180,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// which could still contain data related to that user. Should we disallow that, e.g. until
// next boot? Might not be needed given that this still requires user consent.
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
checkAllUsersAreAffiliatedWithDevice();
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_REQUEST_BUGREPORT);
@@ -8472,7 +8491,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
Objects.requireNonNull(packageList, "packageList is null");
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
- Preconditions.checkCallAuthorization((caller.hasAdminComponent() && isDeviceOwner(caller))
+ Preconditions.checkCallAuthorization((caller.hasAdminComponent()
+ && isDefaultDeviceOwner(caller))
|| (caller.hasPackage()
&& isCallerDelegate(caller, DELEGATION_KEEP_UNINSTALLED_PACKAGES)));
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_KEEP_UNINSTALLED_PACKAGES);
@@ -8501,7 +8521,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return null;
}
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
- Preconditions.checkCallAuthorization((caller.hasAdminComponent() && isDeviceOwner(caller))
+ Preconditions.checkCallAuthorization((caller.hasAdminComponent()
+ && isDefaultDeviceOwner(caller))
|| (caller.hasPackage()
&& isCallerDelegate(caller, DELEGATION_KEEP_UNINSTALLED_PACKAGES)));
@@ -8615,8 +8636,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public boolean hasDeviceOwner() {
final CallerIdentity caller = getCallerIdentity();
- Preconditions.checkCallAuthorization(isDeviceOwner(caller)
- || canManageUsers(caller)
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
+ || canManageUsers(caller) || isFinancedDeviceOwner(caller)
|| hasCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
return mOwners.hasDeviceOwner();
}
@@ -8633,17 +8654,29 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
- private boolean isDeviceOwner(CallerIdentity caller) {
+ /**
+ * Returns {@code true} <b>only if</b> the caller is the device owner and the device owner type
+ * is {@link DevicePolicyManager#DEVICE_OWNER_TYPE_DEFAULT}. {@code false} is returned for the
+ * case where the caller is not the device owner, there is no device owner, or the device owner
+ * type is not {@link DevicePolicyManager#DEVICE_OWNER_TYPE_DEFAULT}.
+ *
+ */
+ private boolean isDefaultDeviceOwner(CallerIdentity caller) {
synchronized (getLockObject()) {
- if (!mOwners.hasDeviceOwner() || mOwners.getDeviceOwnerUserId() != caller.getUserId()) {
- return false;
- }
+ return isDeviceOwnerLocked(caller) && getDeviceOwnerTypeLocked(
+ mOwners.getDeviceOwnerPackageName()) == DEVICE_OWNER_TYPE_DEFAULT;
+ }
+ }
- if (caller.hasAdminComponent()) {
- return mOwners.getDeviceOwnerComponent().equals(caller.getComponentName());
- } else {
- return isUidDeviceOwnerLocked(caller.getUid());
- }
+ private boolean isDeviceOwnerLocked(CallerIdentity caller) {
+ if (!mOwners.hasDeviceOwner() || mOwners.getDeviceOwnerUserId() != caller.getUserId()) {
+ return false;
+ }
+
+ if (caller.hasAdminComponent()) {
+ return mOwners.getDeviceOwnerComponent().equals(caller.getComponentName());
+ } else {
+ return isUidDeviceOwnerLocked(caller.getUid());
}
}
@@ -9073,8 +9106,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller)
- || isProfileOwnerOfOrganizationOwnedDevice(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller));
mInjector.binderWithCleanCallingIdentity(() ->
mLockPatternUtils.setDeviceOwnerInfo(info != null ? info.toString() : null));
@@ -9258,7 +9291,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final CallerIdentity caller = getCallerIdentity(who);
final int userId = caller.getUserId();
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller));
Preconditions.checkCallingUser(isManagedProfile(userId));
synchronized (getLockObject()) {
@@ -9289,7 +9323,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller));
mInjector.binderWithCleanCallingIdentity(() -> {
mUserManager.setUserName(caller.getUserId(), profileName);
@@ -9725,7 +9760,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
private void enforceCanCallLockTaskLocked(CallerIdentity caller) {
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isProfileOwner(caller)
+ || isDefaultDeviceOwner(caller) || isFinancedDeviceOwner(caller));
final int userId = caller.getUserId();
if (!canUserUseLockTaskLocked(userId)) {
@@ -9982,7 +10018,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
ComponentName activity) {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isProfileOwner(caller)
+ || isDefaultDeviceOwner(caller) || isFinancedDeviceOwner(caller));
final int userHandle = caller.getUserId();
synchronized (getLockObject()) {
@@ -10009,7 +10046,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public void clearPackagePersistentPreferredActivities(ComponentName who, String packageName) {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isProfileOwner(caller)
+ || isDefaultDeviceOwner(caller) || isFinancedDeviceOwner(caller));
final int userHandle = caller.getUserId();
synchronized (getLockObject()) {
@@ -10030,7 +10068,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(admin, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller)
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
|| (parent && isProfileOwnerOfOrganizationOwnedDevice(caller)));
if (parent) {
mInjector.binderWithCleanCallingIdentity(() -> enforcePackageIsSystemPackage(
@@ -10070,7 +10108,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
String packageName, Bundle settings) {
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDeviceOwner(caller)))
+ && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
|| (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_APP_RESTRICTIONS)));
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_APPLICATION_RESTRICTIONS);
@@ -10168,7 +10206,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public void setRestrictionsProvider(ComponentName who, ComponentName permissionProvider) {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller));
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_RESTRICTIONS_PROVIDER);
synchronized (getLockObject()) {
@@ -10193,7 +10232,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public void addCrossProfileIntentFilter(ComponentName who, IntentFilter filter, int flags) {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller));
int callingUserId = caller.getUserId();
synchronized (getLockObject()) {
long id = mInjector.binderClearCallingIdentity();
@@ -10242,7 +10282,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public void clearCrossProfileIntentFilters(ComponentName who) {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller));
int callingUserId = caller.getUserId();
synchronized (getLockObject()) {
@@ -10382,7 +10423,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller));
synchronized (getLockObject()) {
ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
@@ -10495,7 +10537,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
+ "system input methods when called on the parent instance of an "
+ "organization-owned device");
} else {
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller));
}
if (packageList != null) {
@@ -10553,7 +10596,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (calledOnParentInstance) {
Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice(caller));
} else {
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller));
}
synchronized (getLockObject()) {
@@ -10732,7 +10776,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// Only allow the system user to use this method
Preconditions.checkCallAuthorization(caller.getUserHandle().isSystem(),
"createAndManageUser was called from non-system user");
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_CREATE_AND_MANAGE_USER);
final boolean ephemeral = (flags & DevicePolicyManager.MAKE_USER_EPHEMERAL) != 0;
@@ -10974,7 +11018,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(who, "ComponentName is null");
Objects.requireNonNull(userHandle, "UserHandle is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_REMOVE_USER);
return mInjector.binderWithCleanCallingIdentity(() -> {
@@ -11008,7 +11052,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public boolean switchUser(ComponentName who, UserHandle userHandle) {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SWITCH_USER);
boolean switched = false;
@@ -11083,7 +11127,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(who, "ComponentName is null");
Objects.requireNonNull(userHandle, "UserHandle is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_START_USER_IN_BACKGROUND);
final int userId = userHandle.getIdentifier();
@@ -11119,7 +11163,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(who, "ComponentName is null");
Objects.requireNonNull(userHandle, "UserHandle is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_STOP_USER);
final int userId = userHandle.getIdentifier();
@@ -11135,7 +11179,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public int logoutUser(ComponentName who) {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller));
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_LOGOUT_USER);
final int callingUserId = caller.getUserId();
@@ -11224,7 +11269,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public List<UserHandle> getSecondaryUsers(ComponentName who) {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
return mInjector.binderWithCleanCallingIdentity(() -> {
final List<UserInfo> userInfos = mInjector.getUserManager().getAliveUsers();
@@ -11244,7 +11289,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller));
return mInjector.binderWithCleanCallingIdentity(
() -> mInjector.getUserManager().isUserEphemeral(caller.getUserId()));
@@ -11255,7 +11301,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
String packageName) {
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDeviceOwner(caller)))
+ && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
|| (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_APP_RESTRICTIONS)));
return mInjector.binderWithCleanCallingIdentity(() -> {
@@ -11306,7 +11352,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(packageNames, "array of packages cannot be null");
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDeviceOwner(caller)))
+ && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
|| (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_PACKAGE_ACCESS)));
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_PACKAGES_SUSPENDED);
@@ -11369,7 +11415,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public boolean isPackageSuspended(ComponentName who, String callerPackage, String packageName) {
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDeviceOwner(caller)))
+ && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
|| (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_PACKAGE_ACCESS)));
synchronized (getLockObject()) {
@@ -11390,8 +11436,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public List<String> listPolicyExemptApps() {
CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(
- hasCallingOrSelfPermission(permission.MANAGE_DEVICE_ADMINS) || isDeviceOwner(caller)
- || isProfileOwner(caller));
+ hasCallingOrSelfPermission(permission.MANAGE_DEVICE_ADMINS)
+ || isDefaultDeviceOwner(caller) || isProfileOwner(caller));
return listPolicyExemptAppsUnchecked();
}
@@ -11432,12 +11478,19 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final ActiveAdmin activeAdmin = getParentOfAdminIfRequired(
getProfileOwnerOrDeviceOwnerLocked(caller), parent);
- if (isDeviceOwner(caller)) {
+ if (isDefaultDeviceOwner(caller)) {
if (!UserRestrictionsUtils.canDeviceOwnerChange(key)) {
throw new SecurityException("Device owner cannot set user restriction " + key);
}
Preconditions.checkArgument(!parent,
"Cannot use the parent instance in Device Owner mode");
+ } else if (isFinancedDeviceOwner(caller)) {
+ if (!UserRestrictionsUtils.canFinancedDeviceOwnerChange(key)) {
+ throw new SecurityException("Cannot set user restriction " + key
+ + " when managing a financed device");
+ }
+ Preconditions.checkArgument(!parent,
+ "Cannot use the parent instance in Financed Device Owner mode");
} else {
boolean profileOwnerCanChangeOnItself = !parent
&& UserRestrictionsUtils.canProfileOwnerChange(key, userHandle);
@@ -11546,7 +11599,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller)
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
+ || isProfileOwner(caller)
|| (parent && isProfileOwnerOfOrganizationOwnedDevice(caller)));
synchronized (getLockObject()) {
@@ -11561,7 +11615,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
boolean hidden, boolean parent) {
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDeviceOwner(caller)))
+ && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
|| (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_PACKAGE_ACCESS)));
List<String> exemptApps = listPolicyExemptAppsUnchecked();
@@ -11607,7 +11661,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
String packageName, boolean parent) {
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDeviceOwner(caller)))
+ && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
|| (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_PACKAGE_ACCESS)));
final int userId = parent ? getProfileParentId(caller.getUserId()) : caller.getUserId();
@@ -11643,7 +11697,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public void enableSystemApp(ComponentName who, String callerPackage, String packageName) {
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDeviceOwner(caller)))
+ && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
|| (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_ENABLE_SYSTEM_APP)));
synchronized (getLockObject()) {
@@ -11687,7 +11741,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public int enableSystemAppWithIntent(ComponentName who, String callerPackage, Intent intent) {
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDeviceOwner(caller)))
+ && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
|| (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_ENABLE_SYSTEM_APP)));
int numberOfAppsInstalled = 0;
@@ -11756,7 +11810,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
String packageName) {
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDeviceOwner(caller)))
+ && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
|| (caller.hasPackage()
&& isCallerDelegate(caller, DELEGATION_INSTALL_EXISTING_PACKAGE)));
@@ -11872,7 +11926,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
boolean uninstallBlocked) {
final CallerIdentity caller = getCallerIdentity(who, callerPackage);
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDeviceOwner(caller)))
+ && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)
+ || isFinancedDeviceOwner(caller)))
|| (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_BLOCK_UNINSTALL)));
final int userId = caller.getUserId();
@@ -11913,7 +11968,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (who != null) {
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(
- isProfileOwner(caller) || isDeviceOwner(caller));
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller)
+ || isFinancedDeviceOwner(caller));
}
try {
return mIPackageManager.getBlockUninstallForUser(packageName, userId);
@@ -12087,7 +12143,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller));
synchronized (getLockObject()) {
ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
@@ -12111,7 +12168,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller));
synchronized (getLockObject()) {
ActiveAdmin admin = getProfileOwnerOrDeviceOwnerLocked(caller);
@@ -12136,7 +12194,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
// Check can set secondary lockscreen enabled
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller));
Preconditions.checkCallAuthorization(!isManagedProfile(caller.getUserId()),
"User %d is not allowed to call setSecondaryLockscreenEnabled",
caller.getUserId());
@@ -12325,6 +12384,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final int userHandle = caller.getUserId();
synchronized (getLockObject()) {
enforceCanCallLockTaskLocked(caller);
+ enforceCanSetLockTaskFeaturesOnFinancedDevice(caller, flags);
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_LOCK_TASK_FEATURES);
setLockTaskFeaturesLocked(userHandle, flags);
}
@@ -12373,6 +12433,24 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
});
}
+ private void enforceCanSetLockTaskFeaturesOnFinancedDevice(CallerIdentity caller, int flags) {
+ int allowedFlags = LOCK_TASK_FEATURE_SYSTEM_INFO | LOCK_TASK_FEATURE_KEYGUARD
+ | LOCK_TASK_FEATURE_HOME | LOCK_TASK_FEATURE_GLOBAL_ACTIONS
+ | LOCK_TASK_FEATURE_NOTIFICATIONS;
+
+ if (!isFinancedDeviceOwner(caller)) {
+ return;
+ }
+
+ if ((flags == 0) || ((flags & ~(allowedFlags)) != 0)) {
+ throw new SecurityException(
+ "Permitted lock task features when managing a financed device: "
+ + "LOCK_TASK_FEATURE_SYSTEM_INFO, LOCK_TASK_FEATURE_KEYGUARD, "
+ + "LOCK_TASK_FEATURE_HOME, LOCK_TASK_FEATURE_GLOBAL_ACTIONS, "
+ + "or LOCK_TASK_FEATURE_NOTIFICATIONS");
+ }
+ }
+
@Override
public void notifyLockTaskModeChanged(boolean isEnabled, String pkg, int userHandle) {
Preconditions.checkCallAuthorization(isSystemUid(getCallerIdentity()),
@@ -12413,7 +12491,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public void setGlobalSetting(ComponentName who, String setting, String value) {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
DevicePolicyEventLogger
.createEvent(DevicePolicyEnums.SET_GLOBAL_SETTING)
@@ -12454,7 +12532,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(who, "ComponentName is null");
Preconditions.checkStringNotEmpty(setting, "String setting is null or empty");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller));
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_SYSTEM_SETTING);
synchronized (getLockObject()) {
@@ -12476,8 +12555,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Preconditions.checkNotNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller)
- || isProfileOwnerOfOrganizationOwnedDevice(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller));
mInjector.binderWithCleanCallingIdentity(() ->
mInjector.settingsGlobalPutInt(Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN,
@@ -12498,8 +12577,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Preconditions.checkNotNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller)
- || isProfileOwnerOfOrganizationOwnedDevice(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller));
return mInjector.binderWithCleanCallingIdentity(() ->
mInjector.settingsGlobalGetInt(Global.WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN, 0) > 0);
@@ -12510,7 +12589,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Preconditions.checkNotNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
UserHandle userHandle = caller.getUserHandle();
if (mIsAutomotive && !locationEnabled) {
@@ -12592,8 +12671,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller)
- || isProfileOwnerOfOrganizationOwnedDevice(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller));
// Don't allow set time when auto time is on.
if (mInjector.settingsGlobalGetInt(Global.AUTO_TIME, 0) == 1) {
@@ -12612,8 +12691,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller)
- || isProfileOwnerOfOrganizationOwnedDevice(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller));
// Don't allow set timezone when auto timezone is on.
if (mInjector.settingsGlobalGetInt(Global.AUTO_TIME_ZONE, 0) == 1) {
@@ -12633,7 +12712,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public void setSecureSetting(ComponentName who, String setting, String value) {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller));
int callingUserId = caller.getUserId();
synchronized (getLockObject()) {
@@ -12720,7 +12800,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public void setMasterVolumeMuted(ComponentName who, boolean on) {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller));
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_MASTER_VOLUME_MUTED);
synchronized (getLockObject()) {
@@ -12737,7 +12818,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public boolean isMasterVolumeMuted(ComponentName who) {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller));
synchronized (getLockObject()) {
AudioManager audioManager =
@@ -12750,7 +12832,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public void setUserIcon(ComponentName who, Bitmap icon) {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller));
synchronized (getLockObject()) {
mInjector.binderWithCleanCallingIdentity(
@@ -12766,7 +12849,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public boolean setKeyguardDisabled(ComponentName who, boolean disabled) {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller));
final int userId = caller.getUserId();
synchronized (getLockObject()) {
@@ -12808,7 +12892,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public boolean setStatusBarDisabled(ComponentName who, boolean disabled) {
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller));
int userId = caller.getUserId();
synchronized (getLockObject()) {
@@ -13042,7 +13127,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public boolean isActiveDeviceOwner(int uid) {
- return isDeviceOwner(new CallerIdentity(uid, null, null));
+ return isDefaultDeviceOwner(new CallerIdentity(uid, null, null));
}
@Override
@@ -13633,7 +13718,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
synchronized (getLockObject()) {
Preconditions.checkCallAuthorization(isProfileOwnerOfOrganizationOwnedDevice(caller)
- || isDeviceOwner(caller));
+ || isDefaultDeviceOwner(caller));
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_SYSTEM_UPDATE_POLICY);
if (policy == null) {
@@ -13831,7 +13916,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(admin, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller));
return mOwners.getSystemUpdateInfo();
}
@@ -13840,7 +13926,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public void setPermissionPolicy(ComponentName admin, String callerPackage, int policy) {
final CallerIdentity caller = getCallerIdentity(admin, callerPackage);
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDeviceOwner(caller)))
+ && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
|| (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_PERMISSION_GRANT)));
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_PERMISSION_POLICY);
@@ -13882,11 +13968,15 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final CallerIdentity caller = getCallerIdentity(admin, callerPackage);
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDeviceOwner(caller)))
+ && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)
+ || isFinancedDeviceOwner(caller)))
|| (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_PERMISSION_GRANT)));
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_PERMISSION_GRANT_STATE);
synchronized (getLockObject()) {
+ if (isFinancedDeviceOwner(caller)) {
+ enforceCanSetPermissionGrantOnFinancedDevice(packageName, permission);
+ }
long ident = mInjector.binderClearCallingIdentity();
try {
boolean isPostQAdmin = getTargetSdk(caller.getPackageName(), caller.getUserId())
@@ -13946,12 +14036,23 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
+ private void enforceCanSetPermissionGrantOnFinancedDevice(
+ String packageName, String permission) {
+ if (!Manifest.permission.READ_PHONE_STATE.equals(permission)) {
+ throw new SecurityException("Cannot grant " + permission
+ + " when managing a financed device");
+ } else if (!mOwners.getDeviceOwnerPackageName().equals(packageName)) {
+ throw new SecurityException("Cannot grant permission to a package that is not"
+ + " the device owner");
+ }
+ }
+
@Override
public int getPermissionGrantState(ComponentName admin, String callerPackage,
String packageName, String permission) throws RemoteException {
final CallerIdentity caller = getCallerIdentity(admin, callerPackage);
Preconditions.checkCallAuthorization(isSystemUid(caller) || (caller.hasAdminComponent()
- && (isProfileOwner(caller) || isDeviceOwner(caller)))
+ && (isProfileOwner(caller) || isDefaultDeviceOwner(caller)))
|| (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_PERMISSION_GRANT)));
synchronized (getLockObject()) {
@@ -14231,7 +14332,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
private void checkIsDeviceOwner(CallerIdentity caller) {
- Preconditions.checkCallAuthorization(isDeviceOwner(caller), caller.getUid()
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller), caller.getUid()
+ " is not device owner");
}
@@ -14263,8 +14364,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(admin, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller)
- || isProfileOwnerOfOrganizationOwnedDevice(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller));
return mInjector.binderWithCleanCallingIdentity(() -> {
String[] macAddresses = mInjector.getWifiManager().getFactoryMacAddresses();
@@ -14299,7 +14400,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(admin, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller));
return isManagedProfile(caller.getUserId());
}
@@ -14308,7 +14410,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public void reboot(ComponentName admin) {
Objects.requireNonNull(admin, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_REBOOT);
mInjector.binderWithCleanCallingIdentity(() -> {
// Make sure there are no ongoing calls on the device.
@@ -14542,7 +14644,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return null;
}
final CallerIdentity caller = getCallerIdentity();
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || canManageUsers(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
+ || canManageUsers(caller) || isFinancedDeviceOwner(caller));
synchronized (getLockObject()) {
final ActiveAdmin deviceOwnerAdmin = getDeviceOwnerAdminLocked();
return deviceOwnerAdmin == null ? null : deviceOwnerAdmin.organizationName;
@@ -14576,7 +14679,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(who);
Objects.requireNonNull(packageNames);
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller),
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller),
"Admin %s does not own the profile", caller.getComponentName());
if (!mHasFeature) {
@@ -14627,7 +14731,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return new ArrayList<>();
}
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller),
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller),
"Admin %s does not own the profile", caller.getComponentName());
synchronized (getLockObject()) {
@@ -14766,7 +14871,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final Set<String> affiliationIds = new ArraySet<>(ids);
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller));
final int callingUserId = caller.getUserId();
synchronized (getLockObject()) {
@@ -14797,7 +14903,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(admin);
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller));
synchronized (getLockObject()) {
return new ArrayList<String>(getUserData(caller.getUserId()).mAffiliationIds);
@@ -14891,7 +14998,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (admin != null) {
Preconditions.checkCallAuthorization(
isProfileOwnerOfOrganizationOwnedDevice(caller)
- || isDeviceOwner(caller));
+ || isDefaultDeviceOwner(caller));
} else {
// A delegate app passes a null admin component, which is expected
Preconditions.checkCallAuthorization(
@@ -14928,7 +15035,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (admin != null) {
Preconditions.checkCallAuthorization(
isProfileOwnerOfOrganizationOwnedDevice(caller)
- || isDeviceOwner(caller));
+ || isDefaultDeviceOwner(caller));
} else {
// A delegate app passes a null admin component, which is expected
Preconditions.checkCallAuthorization(
@@ -14961,7 +15068,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (admin != null) {
Preconditions.checkCallAuthorization(
isProfileOwnerOfOrganizationOwnedDevice(caller)
- || isDeviceOwner(caller));
+ || isDefaultDeviceOwner(caller));
} else {
// A delegate app passes a null admin component, which is expected
Preconditions.checkCallAuthorization(
@@ -15007,7 +15114,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (admin != null) {
Preconditions.checkCallAuthorization(
isProfileOwnerOfOrganizationOwnedDevice(caller)
- || isDeviceOwner(caller));
+ || isDefaultDeviceOwner(caller));
} else {
// A delegate app passes a null admin component, which is expected
Preconditions.checkCallAuthorization(
@@ -15246,7 +15353,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(admin, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
+ || isProfileOwner(caller) || isFinancedDeviceOwner(caller));
toggleBackupServiceActive(caller.getUserId(), enabled);
}
@@ -15259,7 +15367,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(admin, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
+ || isProfileOwner(caller) || isFinancedDeviceOwner(caller));
return mInjector.binderWithCleanCallingIdentity(() -> {
synchronized (getLockObject()) {
@@ -15334,7 +15443,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
Objects.requireNonNull(admin);
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller));
synchronized (getLockObject()) {
final int callingUserId = caller.getUserId();
@@ -15462,7 +15572,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final boolean isManagedProfileOwner = isProfileOwner(caller)
&& isManagedProfile(caller.getUserId());
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isDeviceOwner(caller) || isManagedProfileOwner))
+ && (isDefaultDeviceOwner(caller) || isManagedProfileOwner))
|| (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_NETWORK_LOGGING)));
synchronized (getLockObject()) {
@@ -15622,7 +15732,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
final CallerIdentity caller = getCallerIdentity(admin, packageName);
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isDeviceOwner(caller)
+ && (isDefaultDeviceOwner(caller)
|| (isProfileOwner(caller) && isManagedProfile(caller.getUserId()))))
|| (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_NETWORK_LOGGING))
|| hasCallingOrSelfPermission(permission.MANAGE_USERS));
@@ -15654,7 +15764,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final boolean isManagedProfileOwner = isProfileOwner(caller)
&& isManagedProfile(caller.getUserId());
Preconditions.checkCallAuthorization((caller.hasAdminComponent()
- && (isDeviceOwner(caller) || isManagedProfileOwner))
+ && (isDefaultDeviceOwner(caller) || isManagedProfileOwner))
|| (caller.hasPackage() && isCallerDelegate(caller, DELEGATION_NETWORK_LOGGING)));
if (mOwners.hasDeviceOwner()) {
checkAllUsersAreAffiliatedWithDevice();
@@ -15815,14 +15925,16 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public long getLastSecurityLogRetrievalTime() {
final CallerIdentity caller = getCallerIdentity();
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || canManageUsers(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || canManageUsers(caller));
return getUserData(UserHandle.USER_SYSTEM).mLastSecurityLogRetrievalTime;
}
@Override
public long getLastBugReportRequestTime() {
final CallerIdentity caller = getCallerIdentity();
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || canManageUsers(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || canManageUsers(caller));
return getUserData(UserHandle.USER_SYSTEM).mLastBugReportRequestTime;
}
@@ -15830,7 +15942,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public long getLastNetworkLogRetrievalTime() {
final CallerIdentity caller = getCallerIdentity();
- Preconditions.checkCallAuthorization(isDeviceOwner(caller)
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
|| (isProfileOwner(caller) && isManagedProfile(caller.getUserId()))
|| canManageUsers(caller));
final int affectedUserId = getNetworkLoggingAffectedUser();
@@ -15846,7 +15958,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
throw new IllegalArgumentException("token must be at least 32-byte long");
}
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller));
synchronized (getLockObject()) {
final int userHandle = caller.getUserId();
@@ -15870,7 +15983,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return false;
}
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller));
synchronized (getLockObject()) {
final int userHandle = caller.getUserId();
@@ -15895,7 +16009,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return false;
}
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller));
synchronized (getLockObject()) {
return isResetPasswordTokenActiveForUserLocked(caller.getUserId());
@@ -15920,7 +16035,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(token);
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller));
synchronized (getLockObject()) {
DevicePolicyData policy = getUserData(caller.getUserId());
@@ -15945,7 +16061,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Override
public boolean isCurrentInputMethodSetByOwner() {
final CallerIdentity caller = getCallerIdentity();
- Preconditions.checkCallAuthorization(isDeviceOwner(caller)
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller)
|| isProfileOwner(caller) || isSystemUid(caller),
"Only profile owner, device owner and system may call this method.");
return getUserData(caller.getUserId()).mCurrentInputMethodSet;
@@ -15956,7 +16072,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final int userId = user.getIdentifier();
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization((userId == caller.getUserId())
- || isProfileOwner(caller) || isDeviceOwner(caller)
+ || isProfileOwner(caller) || isDefaultDeviceOwner(caller)
|| hasFullCrossUsersPermission(caller, userId));
synchronized (getLockObject()) {
@@ -15973,7 +16089,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(callback, "callback is null");
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller));
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_CLEAR_APPLICATION_USER_DATA);
long ident = mInjector.binderClearCallingIdentity();
@@ -16005,7 +16122,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
Objects.requireNonNull(admin, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_LOGOUT_ENABLED);
synchronized (getLockObject()) {
@@ -16054,7 +16171,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
"Provided administrator and target have the same package name.");
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller));
final int callingUserId = caller.getUserId();
final DevicePolicyData policy = getUserData(callingUserId);
@@ -16096,7 +16214,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (isUserAffiliatedWithDeviceLocked(callingUserId)) {
notifyAffiliatedProfileTransferOwnershipComplete(callingUserId);
}
- } else if (isDeviceOwner(caller)) {
+ } else if (isDefaultDeviceOwner(caller)) {
ownerType = ADMIN_TYPE_DEVICE_OWNER;
prepareTransfer(admin, target, bundle, callingUserId,
ADMIN_TYPE_DEVICE_OWNER);
@@ -16177,7 +16295,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
Objects.requireNonNull(admin, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
final String startUserSessionMessageString =
startUserSessionMessage != null ? startUserSessionMessage.toString() : null;
@@ -16202,7 +16320,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
Objects.requireNonNull(admin, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
final String endUserSessionMessageString =
endUserSessionMessage != null ? endUserSessionMessage.toString() : null;
@@ -16227,7 +16345,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
Objects.requireNonNull(admin, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
synchronized (getLockObject()) {
final ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
@@ -16242,7 +16360,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
Objects.requireNonNull(admin, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
synchronized (getLockObject()) {
final ActiveAdmin deviceOwner = getDeviceOwnerAdminLocked();
@@ -16258,7 +16376,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@Nullable
public PersistableBundle getTransferOwnershipBundle() {
final CallerIdentity caller = getCallerIdentity();
- Preconditions.checkCallAuthorization(isProfileOwner(caller) || isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isProfileOwner(caller) || isDefaultDeviceOwner(caller));
synchronized (getLockObject()) {
final int callingUserId = caller.getUserId();
@@ -16288,7 +16407,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(who, "ComponentName is null");
Objects.requireNonNull(apnSetting, "ApnSetting is null in addOverrideApn");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
if (tm != null) {
@@ -16309,7 +16428,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(who, "ComponentName is null");
Objects.requireNonNull(apnSetting, "ApnSetting is null in updateOverrideApn");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
if (apnId < 0) {
return false;
@@ -16331,7 +16450,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
return removeOverrideApnUnchecked(apnId);
}
@@ -16352,7 +16471,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
return getOverrideApnsUnchecked();
}
@@ -16373,7 +16492,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_OVERRIDE_APNS_ENABLED);
setOverrideApnsEnabledUnchecked(enabled);
@@ -16393,7 +16512,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
Cursor enforceCursor = mInjector.binderWithCleanCallingIdentity(
() -> mContext.getContentResolver().query(
@@ -16476,7 +16595,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
checkAllUsersAreAffiliatedWithDevice();
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_SET_GLOBAL_PRIVATE_DNS);
@@ -16515,7 +16634,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
final int currentMode = ConnectivitySettingsManager.getPrivateDnsMode(mContext);
switch (currentMode) {
@@ -16537,7 +16656,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller));
return mInjector.settingsGlobalGetString(PRIVATE_DNS_SPECIFIER);
}
@@ -16547,8 +16666,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(admin, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(admin);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller)
- || isProfileOwnerOfOrganizationOwnedDevice(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller));
checkCanExecuteOrThrowUnsafe(DevicePolicyManager.OPERATION_INSTALL_SYSTEM_UPDATE);
DevicePolicyEventLogger
@@ -16923,7 +17042,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(who, "ComponentName is null");
Objects.requireNonNull(packages, "packages is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isFinancedDeviceOwner(caller));
checkCanExecuteOrThrowUnsafe(
DevicePolicyManager.OPERATION_SET_USER_CONTROL_DISABLED_PACKAGES);
@@ -16942,7 +17062,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(who, "ComponentName is null");
final CallerIdentity caller = getCallerIdentity(who);
- Preconditions.checkCallAuthorization(isDeviceOwner(caller));
+ Preconditions.checkCallAuthorization(
+ isDefaultDeviceOwner(caller) || isFinancedDeviceOwner(caller));
synchronized (getLockObject()) {
return mOwners.getDeviceOwnerProtectedPackages(who.getPackageName());
@@ -16954,7 +17075,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(who, "Admin component name must be provided");
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(
- isDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller),
+ isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller),
"Common Criteria mode can only be controlled by a device owner or "
+ "a profile owner on an organization-owned device.");
synchronized (getLockObject()) {
@@ -16974,7 +17095,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
if (who != null) {
final CallerIdentity caller = getCallerIdentity(who);
Preconditions.checkCallAuthorization(
- isDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller),
+ isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller),
"Common Criteria mode can only be controlled by a device owner or "
+ "a profile owner on an organization-owned device.");
@@ -17446,7 +17567,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final CallerIdentity caller = getCallerIdentity(callerPackage);
Preconditions.checkCallAuthorization(
- isDeviceOwner(caller) || isProfileOwner(caller)
+ isDefaultDeviceOwner(caller) || isProfileOwner(caller)
|| isCallerDelegate(caller, DELEGATION_CERT_INSTALL));
synchronized (getLockObject()) {
@@ -17467,7 +17588,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
final CallerIdentity caller = getCallerIdentity(callerPackage);
// Only the DPC can set this ID.
- Preconditions.checkCallAuthorization(isDeviceOwner(caller) || isProfileOwner(caller),
+ Preconditions.checkCallAuthorization(isDefaultDeviceOwner(caller) || isProfileOwner(caller),
"Only a Device Owner or Profile Owner may set the Enterprise ID.");
// Empty enterprise ID must not be provided in calls to this method.
Preconditions.checkArgument(!TextUtils.isEmpty(organizationId),
@@ -18141,27 +18262,51 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
@DeviceOwnerType int deviceOwnerType) {
Preconditions.checkCallAuthorization(hasCallingOrSelfPermission(
permission.MANAGE_PROFILE_AND_DEVICE_OWNERS));
- verifyDeviceOwnerTypePreconditions(admin);
- final String packageName = admin.getPackageName();
+ synchronized (getLockObject()) {
+ setDeviceOwnerTypeLocked(admin, deviceOwnerType);
+ }
+ }
+
+ private void setDeviceOwnerTypeLocked(ComponentName admin,
+ @DeviceOwnerType int deviceOwnerType) {
+ String packageName = admin.getPackageName();
+
+ verifyDeviceOwnerTypePreconditionsLocked(admin);
Preconditions.checkState(!mOwners.isDeviceOwnerTypeSetForDeviceOwner(packageName),
"The device owner type has already been set for " + packageName);
- synchronized (getLockObject()) {
- mOwners.setDeviceOwnerType(packageName, deviceOwnerType);
- }
+ mOwners.setDeviceOwnerType(packageName, deviceOwnerType);
}
@Override
@DeviceOwnerType
public int getDeviceOwnerType(@NonNull ComponentName admin) {
- verifyDeviceOwnerTypePreconditions(admin);
synchronized (getLockObject()) {
- return mOwners.getDeviceOwnerType(admin.getPackageName());
+ verifyDeviceOwnerTypePreconditionsLocked(admin);
+ return getDeviceOwnerTypeLocked(admin.getPackageName());
+ }
+ }
+
+ @DeviceOwnerType
+ private int getDeviceOwnerTypeLocked(String packageName) {
+ return mOwners.getDeviceOwnerType(packageName);
+ }
+
+ /**
+ * {@code true} is returned <b>only if</b> the caller is the device owner and the device owner
+ * type is {@link DevicePolicyManager#DEVICE_OWNER_TYPE_FINANCED}. {@code false} is returned for
+ * the case where the caller is not the device owner, there is no device owner, or the device
+ * owner type is not {@link DevicePolicyManager#DEVICE_OWNER_TYPE_FINANCED}.
+ */
+ private boolean isFinancedDeviceOwner(CallerIdentity caller) {
+ synchronized (getLockObject()) {
+ return isDeviceOwnerLocked(caller) && getDeviceOwnerTypeLocked(
+ mOwners.getDeviceOwnerPackageName()) == DEVICE_OWNER_TYPE_FINANCED;
}
}
- private void verifyDeviceOwnerTypePreconditions(@NonNull ComponentName admin) {
+ private void verifyDeviceOwnerTypePreconditionsLocked(@NonNull ComponentName admin) {
Preconditions.checkState(mOwners.hasDeviceOwner(), "there is no device owner");
Preconditions.checkState(mOwners.getDeviceOwnerComponent().equals(admin),
"admin is not the device owner");
@@ -18172,7 +18317,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Objects.requireNonNull(packageName, "Admin package name must be provided");
final CallerIdentity caller = getCallerIdentity(packageName);
Preconditions.checkCallAuthorization(
- isDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller),
+ isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller),
"USB data signaling can only be controlled by a device owner or "
+ "a profile owner on an organization-owned device.");
Preconditions.checkState(canUsbDataSignalingBeDisabled(),
@@ -18213,7 +18358,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
synchronized (getLockObject()) {
// If the caller is an admin, return the policy set by itself. Otherwise
// return the device-wide policy.
- if (isDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller)) {
+ if (isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller)) {
return getProfileOwnerOrDeviceOwnerLocked(caller).mUsbDataSignalingEnabled;
} else {
return isUsbDataSignalingEnabledInternalLocked();
@@ -18254,7 +18399,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public void setMinimumRequiredWifiSecurityLevel(int level) {
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(
- isDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller),
+ isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller),
"Wi-Fi minimum security level can only be controlled by a device owner or "
+ "a profile owner on an organization-owned device.");
@@ -18284,7 +18429,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public void setSsidAllowlist(List<String> ssids) {
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(
- isDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller),
+ isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller),
"SSID allowlist can only be controlled by a device owner or "
+ "a profile owner on an organization-owned device.");
@@ -18306,7 +18451,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public List<String> getSsidAllowlist() {
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(
- isDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller)
+ isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller)
|| isSystemUid(caller),
"SSID allowlist can only be retrieved by a device owner or "
+ "a profile owner on an organization-owned device or a system app.");
@@ -18322,7 +18467,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public void setSsidDenylist(List<String> ssids) {
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(
- isDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller),
+ isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller),
"SSID denylist can only be controlled by a device owner or "
+ "a profile owner on an organization-owned device.");
@@ -18344,7 +18489,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
public List<String> getSsidDenylist() {
final CallerIdentity caller = getCallerIdentity();
Preconditions.checkCallAuthorization(
- isDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller)
+ isDefaultDeviceOwner(caller) || isProfileOwnerOfOrganizationOwnedDevice(caller)
|| isSystemUid(caller),
"SSID denylist can only be retrieved by a device owner or "
+ "a profile owner on an organization-owned device or a system app.");
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java b/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java
index 685cf0580a48..598f9e88ac6d 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/OverlayPackagesProvider.java
@@ -34,6 +34,7 @@ import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.admin.DeviceAdminReceiver;
import android.app.admin.DevicePolicyManager;
+import android.app.role.RoleManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -41,6 +42,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.os.Binder;
import android.util.ArraySet;
import android.util.IndentingPrintWriter;
import android.view.inputmethod.InputMethodInfo;
@@ -91,6 +93,8 @@ public class OverlayPackagesProvider {
List<InputMethodInfo> getInputMethodListAsUser(@UserIdInt int userId);
String getActiveApexPackageNameContainingPackage(String packageName);
+
+ String getDeviceManagerRoleHolderPackageName(Context context);
}
private static final class DefaultInjector implements Injector {
@@ -104,6 +108,19 @@ public class OverlayPackagesProvider {
public String getActiveApexPackageNameContainingPackage(String packageName) {
return ApexManager.getInstance().getActiveApexPackageNameContainingPackage(packageName);
}
+
+ @Override
+ public String getDeviceManagerRoleHolderPackageName(Context context) {
+ return Binder.withCleanCallingIdentity(() -> {
+ RoleManager roleManager = context.getSystemService(RoleManager.class);
+ List<String> roleHolders =
+ roleManager.getRoleHolders(RoleManager.ROLE_DEVICE_MANAGER);
+ if (roleHolders.isEmpty()) {
+ return null;
+ }
+ return roleHolders.get(0);
+ });
+ }
}
@VisibleForTesting
@@ -142,9 +159,20 @@ public class OverlayPackagesProvider {
nonRequiredApps.addAll(getDisallowedApps(provisioningAction));
nonRequiredApps.removeAll(
getRequiredAppsMainlineModules(nonRequiredApps, provisioningAction));
+ nonRequiredApps.removeAll(getDeviceManagerRoleHolders());
return nonRequiredApps;
}
+ private Set<String> getDeviceManagerRoleHolders() {
+ HashSet<String> result = new HashSet<>();
+ String deviceManagerRoleHolderPackageName =
+ mInjector.getDeviceManagerRoleHolderPackageName(mContext);
+ if (deviceManagerRoleHolderPackageName != null) {
+ result.add(deviceManagerRoleHolderPackageName);
+ }
+ return result;
+ }
+
/**
* Returns a subset of {@code packageNames} whose packages are mainline modules declared as
* required apps via their app metadata.
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 74e04ed6e58b..3fd5cd167d95 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -213,8 +213,6 @@ import com.android.server.wm.WindowManagerService;
import dalvik.system.VMRuntime;
-import com.google.android.startop.iorap.IorapForwardingService;
-
import java.io.File;
import java.io.FileDescriptor;
import java.io.IOException;
@@ -265,8 +263,6 @@ public final class SystemServer implements Dumpable {
"/apex/com.android.os.statsd/javalib/service-statsd.jar";
private static final String CONNECTIVITY_SERVICE_APEX_PATH =
"/apex/com.android.tethering/javalib/service-connectivity.jar";
- private static final String NEARBY_SERVICE_APEX_PATH =
- "/apex/com.android.nearby/javalib/service-nearby.jar";
private static final String STATS_COMPANION_LIFECYCLE_CLASS =
"com.android.server.stats.StatsCompanion$Lifecycle";
private static final String STATS_PULL_ATOM_SERVICE_CLASS =
@@ -277,8 +273,6 @@ public final class SystemServer implements Dumpable {
"com.android.server.usb.UsbService$Lifecycle";
private static final String MIDI_SERVICE_CLASS =
"com.android.server.midi.MidiService$Lifecycle";
- private static final String NEARBY_SERVICE_CLASS =
- "com.android.server.nearby.NearbyService";
private static final String WIFI_APEX_SERVICE_JAR_PATH =
"/apex/com.android.wifi/javalib/service-wifi.jar";
private static final String WIFI_SERVICE_CLASS =
@@ -1621,10 +1615,6 @@ public final class SystemServer implements Dumpable {
mSystemServiceManager.startService(PinnerService.class);
t.traceEnd();
- t.traceBegin("IorapForwardingService");
- mSystemServiceManager.startService(IorapForwardingService.class);
- t.traceEnd();
-
if (Build.IS_DEBUGGABLE && ProfcollectForwardingService.enabled()) {
t.traceBegin("ProfcollectForwardingService");
mSystemServiceManager.startService(ProfcollectForwardingService.class);
@@ -2000,16 +1990,6 @@ public final class SystemServer implements Dumpable {
}
t.traceEnd();
- // Start Nearby Service.
- t.traceBegin("StartNearbyService");
- try {
- mSystemServiceManager.startServiceFromJar(NEARBY_SERVICE_CLASS,
- NEARBY_SERVICE_APEX_PATH);
- } catch (Throwable e) {
- reportWtf("starting NearbyService", e);
- }
- t.traceEnd();
-
t.traceBegin("StartConnectivityService");
// This has to be called after NetworkManagementService, NetworkStatsService
// and NetworkPolicyManager because ConnectivityService needs to take these
diff --git a/services/startop/Android.bp b/services/startop/Android.bp
deleted file mode 100644
index c56c463d0168..000000000000
--- a/services/startop/Android.bp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_base_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- // SPDX-license-identifier-MIT
- // SPDX-license-identifier-Unicode-DFS
- default_applicable_licenses: ["frameworks_base_license"],
-}
-
-java_library_static {
- name: "services.startop",
- defaults: ["platform_service_defaults"],
-
- static_libs: [
- // frameworks/base/startop/iorap
- "services.startop.iorap",
- ],
-}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java
new file mode 100644
index 000000000000..ec884f59014f
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricContextProviderTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.log;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.same;
+import static org.mockito.Mockito.verify;
+
+import android.hardware.biometrics.IBiometricContextListener;
+import android.hardware.biometrics.common.OperationContext;
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.statusbar.IStatusBarService;
+
+import com.google.common.collect.ImmutableList;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
+
+@Presubmit
+@SmallTest
+public class BiometricContextProviderTest {
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Mock
+ private IStatusBarService mStatusBarService;
+
+ private OperationContext mOpContext = new OperationContext();
+ private IBiometricContextListener mListener;
+ private BiometricContextProvider mProvider;
+
+ @Before
+ public void setup() throws RemoteException {
+ mProvider = new BiometricContextProvider(mStatusBarService, null /* handler */);
+ ArgumentCaptor<IBiometricContextListener> captor =
+ ArgumentCaptor.forClass(IBiometricContextListener.class);
+ verify(mStatusBarService).setBiometicContextListener(captor.capture());
+ mListener = captor.getValue();
+ }
+
+ @Test
+ public void testIsAoD() throws RemoteException {
+ mListener.onDozeChanged(true);
+ assertThat(mProvider.isAoD()).isTrue();
+ mListener.onDozeChanged(false);
+ assertThat(mProvider.isAoD()).isFalse();
+ }
+
+ @Test
+ public void testSubscribesToAoD() throws RemoteException {
+ final List<Boolean> expected = ImmutableList.of(true, false, true, true, false);
+ final List<Boolean> actual = new ArrayList<>();
+
+ mProvider.subscribe(mOpContext, ctx -> {
+ assertThat(ctx).isSameInstanceAs(mOpContext);
+ actual.add(ctx.isAoD);
+ });
+
+ for (boolean v : expected) {
+ mListener.onDozeChanged(v);
+ }
+
+ assertThat(actual).containsExactlyElementsIn(expected).inOrder();
+ }
+
+ @Test
+ public void testUnsubscribes() throws RemoteException {
+ final Consumer<OperationContext> emptyConsumer = mock(Consumer.class);
+ mProvider.subscribe(mOpContext, emptyConsumer);
+ mProvider.unsubscribe(mOpContext);
+
+ mListener.onDozeChanged(true);
+
+ final Consumer<OperationContext> nonEmptyConsumer = mock(Consumer.class);
+ mProvider.subscribe(mOpContext, nonEmptyConsumer);
+ mListener.onDozeChanged(false);
+ mProvider.unsubscribe(mOpContext);
+ mListener.onDozeChanged(true);
+
+ verify(emptyConsumer, never()).accept(any());
+ verify(nonEmptyConsumer).accept(same(mOpContext));
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java
index 2b72fabe7cca..b0eb810b5da9 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricLoggerTest.java
@@ -44,7 +44,8 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
@Presubmit
@SmallTest
@@ -55,6 +56,9 @@ public class BiometricLoggerTest {
private static final int DEFAULT_CLIENT = BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT;
@Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Rule
public TestableContext mContext = new TestableContext(
InstrumentationRegistry.getInstrumentation().getContext());
@Mock
@@ -68,8 +72,6 @@ public class BiometricLoggerTest {
@Before
public void setUp() {
- MockitoAnnotations.initMocks(this);
-
mContext.addMockSystemService(SensorManager.class, mSensorManager);
when(mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT)).thenReturn(
new Sensor(new InputSensorInfo("", "", 0, 0, Sensor.TYPE_LIGHT, 0, 0, 0, 0, 0, 0,
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/AcquisitionClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/AcquisitionClientTest.java
index 9bb722f8a853..2d9d868f2f74 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/AcquisitionClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/AcquisitionClientTest.java
@@ -22,6 +22,7 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
@@ -34,6 +35,9 @@ import android.platform.test.annotations.Presubmit;
import androidx.annotation.NonNull;
import androidx.test.filters.SmallTest;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
+
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
@@ -92,9 +96,8 @@ public class AcquisitionClientTest {
@NonNull Supplier<Object> lazyDaemon, @NonNull IBinder token,
@NonNull ClientMonitorCallbackConverter callback) {
super(context, lazyDaemon, token, callback, 0 /* userId */, "Test", 0 /* cookie */,
- TEST_SENSOR_ID /* sensorId */, true /* shouldVibrate */, 0 /* statsModality */,
- 0 /* statsAction */,
- 0 /* statsClient */);
+ TEST_SENSOR_ID /* sensorId */, true /* shouldVibrate */,
+ mock(BiometricLogger.class), mock(BiometricContext.class));
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BaseClientMonitorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BaseClientMonitorTest.java
index 51d234d5afeb..8e6d90c839d8 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BaseClientMonitorTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BaseClientMonitorTest.java
@@ -30,6 +30,7 @@ import android.platform.test.annotations.Presubmit;
import androidx.annotation.NonNull;
import androidx.test.filters.SmallTest;
+import com.android.server.biometrics.log.BiometricContext;
import com.android.server.biometrics.log.BiometricLogger;
import org.junit.Before;
@@ -49,6 +50,8 @@ public class BaseClientMonitorTest {
@Mock
private BiometricLogger mLogger;
@Mock
+ private BiometricContext mBiometricContext;
+ @Mock
private ClientMonitorCallback mCallback;
private TestClientMonitor mClientMonitor;
@@ -109,7 +112,7 @@ public class BaseClientMonitorTest {
TestClientMonitor() {
super(mContext, mToken, mListener, 9 /* userId */, "foo" /* owner */, 2 /* cookie */,
- 5 /* sensorId */, mLogger);
+ 5 /* sensorId */, mLogger, mBiometricContext);
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerOperationTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerOperationTest.java
index 8751cf3810bf..64be56906d4b 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerOperationTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerOperationTest.java
@@ -36,6 +36,9 @@ import android.testing.TestableLooper;
import androidx.test.filters.SmallTest;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -54,7 +57,8 @@ public class BiometricSchedulerOperationTest {
public abstract static class InterruptableMonitor<T>
extends HalClientMonitor<T> implements Interruptable {
public InterruptableMonitor() {
- super(null, null, null, null, 0, null, 0, 0, 0, 0, 0);
+ super(null, null, null, null, 0, null, 0, 0,
+ mock(BiometricLogger.class), mock(BiometricContext.class));
}
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
index ecd9abcb80e6..0fa2b41e8b32 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/BiometricSchedulerTest.java
@@ -51,6 +51,8 @@ import androidx.annotation.Nullable;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.nano.BiometricSchedulerProto;
import com.android.server.biometrics.nano.BiometricsProto;
@@ -526,10 +528,10 @@ public class BiometricSchedulerTest {
@NonNull ClientMonitorCallbackConverter listener) {
super(context, lazyDaemon, token, listener, 0 /* targetUserId */, 0 /* operationId */,
false /* restricted */, TAG, 1 /* cookie */, false /* requireConfirmation */,
- TEST_SENSOR_ID, true /* isStrongBiometric */, 0 /* statsModality */,
- 0 /* statsClient */, null /* taskStackListener */, mock(LockoutTracker.class),
- false /* isKeyguard */, true /* shouldVibrate */,
- false /* isKeyguardBypassEnabled */);
+ TEST_SENSOR_ID, mock(BiometricLogger.class), mock(BiometricContext.class),
+ true /* isStrongBiometric */, null /* taskStackListener */,
+ mock(LockoutTracker.class), false /* isKeyguard */,
+ true /* shouldVibrate */, false /* isKeyguardBypassEnabled */);
}
@Override
@@ -573,8 +575,9 @@ public class BiometricSchedulerTest {
@NonNull ClientMonitorCallbackConverter listener) {
super(context, lazyDaemon, token, listener, 0 /* userId */, new byte[69],
"test" /* owner */, mock(BiometricUtils.class),
- 5 /* timeoutSec */, 0 /* statsModality */, TEST_SENSOR_ID,
- true /* shouldVibrate */);
+ 5 /* timeoutSec */, TEST_SENSOR_ID,
+ true /* shouldVibrate */,
+ mock(BiometricLogger.class), mock(BiometricContext.class));
}
@Override
@@ -613,8 +616,8 @@ public class BiometricSchedulerTest {
TestHalClientMonitor(@NonNull Context context, @NonNull IBinder token,
@NonNull Supplier<Object> lazyDaemon, int cookie, int protoEnum) {
super(context, lazyDaemon, token /* token */, null /* listener */, 0 /* userId */,
- TAG, cookie, TEST_SENSOR_ID, 0 /* statsModality */,
- 0 /* statsAction */, 0 /* statsClient */);
+ TAG, cookie, TEST_SENSOR_ID,
+ mock(BiometricLogger.class), mock(BiometricContext.class));
mProtoEnum = protoEnum;
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/CompositeCallbackTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/CompositeCallbackTest.java
index 587bb600f409..092ca191acba 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/CompositeCallbackTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/CompositeCallbackTest.java
@@ -64,7 +64,7 @@ public class CompositeCallbackTest {
ClientMonitorCompositeCallback callback = new ClientMonitorCompositeCallback(callbacks);
callback.onClientStarted(mClientMonitor);
- final InOrder order = inOrder(expected);
+ final InOrder order = inOrder((Object[]) expected);
for (ClientMonitorCallback cb : expected) {
order.verify(cb).onClientStarted(eq(mClientMonitor));
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java
index 30777cd79a0c..52eee9a55cc7 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/UserAwareBiometricSchedulerTest.java
@@ -41,6 +41,9 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.test.filters.SmallTest;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -66,6 +69,10 @@ public class UserAwareBiometricSchedulerTest {
private Context mContext;
@Mock
private IBiometricService mBiometricService;
+ @Mock
+ private BiometricLogger mBiometricLogger;
+ @Mock
+ private BiometricContext mBiometricContext;
private TestUserStartedCallback mUserStartedCallback = new TestUserStartedCallback();
private TestUserStoppedCallback mUserStoppedCallback = new TestUserStoppedCallback();
@@ -88,7 +95,8 @@ public class UserAwareBiometricSchedulerTest {
@Override
public StopUserClient<?> getStopUserClient(int userId) {
return new TestStopUserClient(mContext, Object::new, mToken, userId,
- TEST_SENSOR_ID, mUserStoppedCallback);
+ TEST_SENSOR_ID, mBiometricLogger, mBiometricContext,
+ mUserStoppedCallback);
}
@NonNull
@@ -96,7 +104,8 @@ public class UserAwareBiometricSchedulerTest {
public StartUserClient<?, ?> getStartUserClient(int newUserId) {
mStartUserClientCount++;
return new TestStartUserClient(mContext, Object::new, mToken, newUserId,
- TEST_SENSOR_ID, mUserStartedCallback, mStartOperationsFinish);
+ TEST_SENSOR_ID, mBiometricLogger, mBiometricContext,
+ mUserStartedCallback, mStartOperationsFinish);
}
},
CoexCoordinator.getInstance());
@@ -226,8 +235,10 @@ public class UserAwareBiometricSchedulerTest {
private static class TestStopUserClient extends StopUserClient<Object> {
public TestStopUserClient(@NonNull Context context,
@NonNull Supplier<Object> lazyDaemon, @Nullable IBinder token, int userId,
- int sensorId, @NonNull UserStoppedCallback callback) {
- super(context, lazyDaemon, token, userId, sensorId, callback);
+ int sensorId, @NonNull BiometricLogger logger,
+ @NonNull BiometricContext biometricContext,
+ @NonNull UserStoppedCallback callback) {
+ super(context, lazyDaemon, token, userId, sensorId, logger, biometricContext, callback);
}
@Override
@@ -254,8 +265,10 @@ public class UserAwareBiometricSchedulerTest {
public TestStartUserClient(@NonNull Context context,
@NonNull Supplier<Object> lazyDaemon, @Nullable IBinder token, int userId,
- int sensorId, @NonNull UserStartedCallback<Object> callback, boolean shouldFinish) {
- super(context, lazyDaemon, token, userId, sensorId, callback);
+ int sensorId, @NonNull BiometricLogger logger,
+ @NonNull BiometricContext biometricContext,
+ @NonNull UserStartedCallback<Object> callback, boolean shouldFinish) {
+ super(context, lazyDaemon, token, userId, sensorId, logger, biometricContext, callback);
mShouldFinish = shouldFinish;
}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
new file mode 100644
index 000000000000..25585dd0cfc3
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClientTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors.face.aidl;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.hardware.biometrics.common.OperationContext;
+import android.hardware.biometrics.face.ISession;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+import android.testing.TestableContext;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
+import com.android.server.biometrics.sensors.ClientMonitorCallback;
+import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
+import com.android.server.biometrics.sensors.LockoutCache;
+import com.android.server.biometrics.sensors.face.UsageStats;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+@Presubmit
+@SmallTest
+public class FaceAuthenticationClientTest {
+
+ private static final int USER_ID = 12;
+ private static final long OP_ID = 32;
+ private static final boolean HAS_AOD = true;
+
+ @Rule
+ public final TestableContext mContext = new TestableContext(
+ InstrumentationRegistry.getInstrumentation().getTargetContext(), null);
+
+ @Mock
+ private ISession mHal;
+ @Mock
+ private IBinder mToken;
+ @Mock
+ private ClientMonitorCallbackConverter mClientMonitorCallbackConverter;
+ @Mock
+ private BiometricLogger mBiometricLogger;
+ @Mock
+ private BiometricContext mBiometricContext;
+ @Mock
+ private LockoutCache mLockoutCache;
+ @Mock
+ private UsageStats mUsageStats;
+ @Mock
+ private ClientMonitorCallback mCallback;
+ @Mock
+ private Sensor.HalSessionCallback mHalSessionCallback;
+ @Captor
+ private ArgumentCaptor<OperationContext> mOperationContextCaptor;
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Before
+ public void setup() {
+ when(mBiometricContext.isAoD()).thenReturn(HAS_AOD);
+ }
+
+ @Test
+ public void authNoContext_v1() throws RemoteException {
+ final FaceAuthenticationClient client = createClient(1);
+ client.start(mCallback);
+
+ verify(mHal).authenticate(eq(OP_ID));
+ verify(mHal, never()).authenticateWithContext(anyLong(), any());
+ }
+
+ @Test
+ public void authWithContext_v2() throws RemoteException {
+ final FaceAuthenticationClient client = createClient(2);
+ client.start(mCallback);
+
+ verify(mHal).authenticateWithContext(eq(OP_ID), mOperationContextCaptor.capture());
+ verify(mHal, never()).authenticate(anyLong());
+
+ final OperationContext opContext = mOperationContextCaptor.getValue();
+ assertThat(opContext.isAoD).isEqualTo(HAS_AOD);
+ }
+
+ private FaceAuthenticationClient createClient(int version) throws RemoteException {
+ when(mHal.getInterfaceVersion()).thenReturn(version);
+
+ final AidlSession aidl = new AidlSession(version, mHal, USER_ID, mHalSessionCallback);
+ return new FaceAuthenticationClient(mContext, () -> aidl, mToken,
+ 2 /* requestId */, mClientMonitorCallbackConverter, 5 /* targetUserId */, OP_ID,
+ false /* restricted */, "test-owner", 4 /* cookie */,
+ false /* requireConfirmation */, 9 /* sensorId */,
+ mBiometricLogger, mBiometricContext, true /* isStrongBiometric */,
+ mUsageStats, mLockoutCache, false /* allowBackgroundAuthentication */,
+ false /* isKeyguardBypassEnabled */, null /* sensorPrivacyManager */);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceDetectClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceDetectClientTest.java
new file mode 100644
index 000000000000..6c72ebfd3674
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceDetectClientTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors.face.aidl;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.hardware.biometrics.common.OperationContext;
+import android.hardware.biometrics.face.ISession;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+import android.testing.TestableContext;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
+import com.android.server.biometrics.sensors.ClientMonitorCallback;
+import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+@Presubmit
+@SmallTest
+public class FaceDetectClientTest {
+
+ private static final int USER_ID = 12;
+ private static final boolean HAS_AOD = true;
+
+ @Rule
+ public final TestableContext mContext = new TestableContext(
+ InstrumentationRegistry.getInstrumentation().getTargetContext(), null);
+
+ @Mock
+ private ISession mHal;
+ @Mock
+ private IBinder mToken;
+ @Mock
+ private ClientMonitorCallbackConverter mClientMonitorCallbackConverter;
+ @Mock
+ private BiometricLogger mBiometricLogger;
+ @Mock
+ private BiometricContext mBiometricContext;
+ @Mock
+ private ClientMonitorCallback mCallback;
+ @Mock
+ private Sensor.HalSessionCallback mHalSessionCallback;
+ @Captor
+ private ArgumentCaptor<OperationContext> mOperationContextCaptor;
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Before
+ public void setup() {
+ when(mBiometricContext.isAoD()).thenReturn(HAS_AOD);
+ }
+
+ @Test
+ public void detectNoContext_v1() throws RemoteException {
+ final FaceDetectClient client = createClient(1);
+ client.start(mCallback);
+
+ verify(mHal).detectInteraction();
+ verify(mHal, never()).detectInteractionWithContext(any());
+ }
+
+ @Test
+ public void detectWithContext_v2() throws RemoteException {
+ final FaceDetectClient client = createClient(2);
+ client.start(mCallback);
+
+ verify(mHal).detectInteractionWithContext(mOperationContextCaptor.capture());
+ verify(mHal, never()).detectInteraction();
+
+ final OperationContext opContext = mOperationContextCaptor.getValue();
+ assertThat(opContext.isAoD).isEqualTo(HAS_AOD);
+ }
+
+ private FaceDetectClient createClient(int version) throws RemoteException {
+ when(mHal.getInterfaceVersion()).thenReturn(version);
+
+ final AidlSession aidl = new AidlSession(version, mHal, USER_ID, mHalSessionCallback);
+ return new FaceDetectClient(mContext, () -> aidl, mToken,
+ 99 /* requestId */, mClientMonitorCallbackConverter, USER_ID,
+ "own-it", 5 /* sensorId */, mBiometricLogger, mBiometricContext,
+ false /* isStrongBiometric */, null /* sensorPrivacyManager */);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClientTest.java
new file mode 100644
index 000000000000..22070e9579ee
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/FaceEnrollClientTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors.face.aidl;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyByte;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.hardware.biometrics.face.ISession;
+import android.hardware.face.Face;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+import android.testing.TestableContext;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
+import com.android.server.biometrics.sensors.BiometricUtils;
+import com.android.server.biometrics.sensors.ClientMonitorCallback;
+import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+@Presubmit
+@SmallTest
+public class FaceEnrollClientTest {
+
+ private static final byte[] HAT = new byte[69];
+ private static final int USER_ID = 12;
+
+ @Rule
+ public final TestableContext mContext = new TestableContext(
+ InstrumentationRegistry.getInstrumentation().getTargetContext(), null);
+
+ @Mock
+ private ISession mHal;
+ @Mock
+ private IBinder mToken;
+ @Mock
+ private ClientMonitorCallbackConverter mClientMonitorCallbackConverter;
+ @Mock
+ private BiometricLogger mBiometricLogger;
+ @Mock
+ private BiometricContext mBiometricContext;
+ @Mock
+ private BiometricUtils<Face> mUtils;
+ @Mock
+ private ClientMonitorCallback mCallback;
+ @Mock
+ private Sensor.HalSessionCallback mHalSessionCallback;
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Test
+ public void enrollNoContext_v1() throws RemoteException {
+ final FaceEnrollClient client = createClient(1);
+ client.start(mCallback);
+
+ verify(mHal).enroll(any(), anyByte(), any(), any());
+ verify(mHal, never()).enrollWithContext(any(), anyByte(), any(), any(), any());
+ }
+
+ @Test
+ public void enrollWithContext_v2() throws RemoteException {
+ final FaceEnrollClient client = createClient(2);
+ client.start(mCallback);
+
+ verify(mHal).enrollWithContext(any(), anyByte(), any(), any(), any());
+ verify(mHal, never()).enroll(any(), anyByte(), any(), any());
+ }
+
+ private FaceEnrollClient createClient(int version) throws RemoteException {
+ when(mHal.getInterfaceVersion()).thenReturn(version);
+
+ final AidlSession aidl = new AidlSession(version, mHal, USER_ID, mHalSessionCallback);
+ return new FaceEnrollClient(mContext, () -> aidl, mToken, mClientMonitorCallbackConverter,
+ USER_ID, HAT, "com.foo.bar", 44 /* requestId */,
+ mUtils, new int[0] /* disabledFeatures */, 6 /* timeoutSec */,
+ null /* previewSurface */, 8 /* sensorId */,
+ mBiometricLogger, mBiometricContext, 5 /* maxTemplatesPerUser */,
+ true /* debugConsent */);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java
index 61e4776e9c50..b60324e88f15 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/aidl/SensorTest.java
@@ -32,6 +32,8 @@ import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.BiometricScheduler;
import com.android.server.biometrics.sensors.CoexCoordinator;
import com.android.server.biometrics.sensors.LockoutCache;
@@ -66,6 +68,10 @@ public class SensorTest {
private Sensor.HalSessionCallback.Callback mHalSessionCallback;
@Mock
private LockoutResetDispatcher mLockoutResetDispatcher;
+ @Mock
+ private BiometricLogger mBiometricLogger;
+ @Mock
+ private BiometricContext mBiometricContext;
private final TestLooper mLooper = new TestLooper();
private final LockoutCache mLockoutCache = new LockoutCache();
@@ -102,7 +108,8 @@ public class SensorTest {
mScheduler.scheduleClientMonitor(new FaceResetLockoutClient(mContext,
() -> new AidlSession(1, mSession, USER_ID, mHalCallback),
- USER_ID, TAG, SENSOR_ID, HAT, mLockoutCache, mLockoutResetDispatcher));
+ USER_ID, TAG, SENSOR_ID, mBiometricLogger, mBiometricContext,
+ HAT, mLockoutCache, mLockoutResetDispatcher));
mLooper.dispatchAll();
verifyNotLocked();
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/FaceGenerateChallengeClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/FaceGenerateChallengeClientTest.java
index 931fad14888e..ec083294c0bd 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/FaceGenerateChallengeClientTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/face/hidl/FaceGenerateChallengeClientTest.java
@@ -34,6 +34,8 @@ import android.platform.test.annotations.Presubmit;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.SmallTest;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.ClientMonitorCallback;
import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
@@ -62,6 +64,10 @@ public class FaceGenerateChallengeClientTest {
private IFaceServiceReceiver mOtherReceiver;
@Mock
private ClientMonitorCallback mMonitorCallback;
+ @Mock
+ private BiometricLogger mBiometricLogger;
+ @Mock
+ private BiometricContext mBiometricContext;
private FaceGenerateChallengeClient mClient;
@@ -75,7 +81,7 @@ public class FaceGenerateChallengeClientTest {
mClient = new FaceGenerateChallengeClient(mContext, () -> mIBiometricsFace, new Binder(),
new ClientMonitorCallbackConverter(mClientReceiver), USER_ID,
- TAG, SENSOR_ID, START_TIME);
+ TAG, SENSOR_ID, mBiometricLogger, mBiometricContext , START_TIME);
}
@Test
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
new file mode 100644
index 000000000000..5c360e9147c1
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintAuthenticationClientTest.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors.fingerprint.aidl;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyFloat;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyLong;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.hardware.biometrics.common.OperationContext;
+import android.hardware.biometrics.fingerprint.ISession;
+import android.hardware.biometrics.fingerprint.PointerContext;
+import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
+import android.hardware.fingerprint.ISidefpsController;
+import android.hardware.fingerprint.IUdfpsOverlayController;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+import android.testing.TestableContext;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
+import com.android.server.biometrics.log.CallbackWithProbe;
+import com.android.server.biometrics.log.Probe;
+import com.android.server.biometrics.sensors.ClientMonitorCallback;
+import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
+import com.android.server.biometrics.sensors.LockoutCache;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.function.Consumer;
+
+@Presubmit
+@SmallTest
+public class FingerprintAuthenticationClientTest {
+
+ private static final int USER_ID = 8;
+ private static final long OP_ID = 7;
+ private static final boolean HAS_AOD = true;
+ private static final int POINTER_ID = 0;
+ private static final int TOUCH_X = 8;
+ private static final int TOUCH_Y = 20;
+ private static final float TOUCH_MAJOR = 4.4f;
+ private static final float TOUCH_MINOR = 5.5f;
+
+ @Rule
+ public final TestableContext mContext = new TestableContext(
+ InstrumentationRegistry.getInstrumentation().getTargetContext(), null);
+
+ @Mock
+ private ISession mHal;
+ @Mock
+ private IBinder mToken;
+ @Mock
+ private ClientMonitorCallbackConverter mClientMonitorCallbackConverter;
+ @Mock
+ private BiometricLogger mBiometricLogger;
+ @Mock
+ private BiometricContext mBiometricContext;
+ @Mock
+ private LockoutCache mLockoutCache;
+ @Mock
+ private IUdfpsOverlayController mUdfpsOverlayController;
+ @Mock
+ private ISidefpsController mSideFpsController;
+ @Mock
+ private FingerprintSensorPropertiesInternal mSensorProps;
+ @Mock
+ private ClientMonitorCallback mCallback;
+ @Mock
+ private Sensor.HalSessionCallback mHalSessionCallback;
+ @Mock
+ private Probe mLuxProbe;
+ @Captor
+ private ArgumentCaptor<OperationContext> mOperationContextCaptor;
+ @Captor
+ private ArgumentCaptor<PointerContext> mPointerContextCaptor;
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Before
+ public void setup() {
+ when(mBiometricLogger.createALSCallback(anyBoolean())).thenAnswer(i ->
+ new CallbackWithProbe<>(mLuxProbe, i.getArgument(0)));
+ when(mBiometricContext.isAoD()).thenReturn(HAS_AOD);
+ }
+
+ @Test
+ public void authNoContext_v1() throws RemoteException {
+ final FingerprintAuthenticationClient client = createClient(1);
+ client.start(mCallback);
+
+ verify(mHal).authenticate(eq(OP_ID));
+ verify(mHal, never()).authenticateWithContext(anyLong(), any());
+ }
+
+ @Test
+ public void authWithContext_v2() throws RemoteException {
+ final FingerprintAuthenticationClient client = createClient(2);
+ client.start(mCallback);
+
+ verify(mHal).authenticateWithContext(eq(OP_ID), mOperationContextCaptor.capture());
+ verify(mHal, never()).authenticate(anyLong());
+
+ final OperationContext opContext = mOperationContextCaptor.getValue();
+ assertThat(opContext.isAoD).isEqualTo(HAS_AOD);
+ }
+
+ @Test
+ public void pointerUp_v1() throws RemoteException {
+ final FingerprintAuthenticationClient client = createClient(1);
+ client.start(mCallback);
+ client.onPointerUp();
+
+ verify(mHal).onPointerUp(eq(POINTER_ID));
+ verify(mHal, never()).onPointerUpWithContext(any());
+ }
+
+ @Test
+ public void pointerDown_v1() throws RemoteException {
+ final FingerprintAuthenticationClient client = createClient(1);
+ client.start(mCallback);
+ client.onPointerDown(TOUCH_X, TOUCH_Y, TOUCH_MAJOR, TOUCH_MINOR);
+
+ verify(mHal).onPointerDown(eq(0),
+ eq(TOUCH_X), eq(TOUCH_Y), eq(TOUCH_MAJOR), eq(TOUCH_MINOR));
+ verify(mHal, never()).onPointerDownWithContext(any());
+ }
+
+ @Test
+ public void pointerUpWithContext_v2() throws RemoteException {
+ final FingerprintAuthenticationClient client = createClient(2);
+ client.start(mCallback);
+ client.onPointerUp();
+
+ verify(mHal).onPointerUpWithContext(mPointerContextCaptor.capture());
+ verify(mHal, never()).onPointerUp(eq(POINTER_ID));
+
+ final PointerContext pContext = mPointerContextCaptor.getValue();
+ assertThat(pContext.pointerId).isEqualTo(POINTER_ID);
+ }
+
+ @Test
+ public void pointerDownWithContext_v2() throws RemoteException {
+ final FingerprintAuthenticationClient client = createClient(2);
+ client.start(mCallback);
+ client.onPointerDown(TOUCH_X, TOUCH_Y, TOUCH_MAJOR, TOUCH_MINOR);
+
+ verify(mHal).onPointerDownWithContext(mPointerContextCaptor.capture());
+ verify(mHal, never()).onPointerDown(anyInt(), anyInt(), anyInt(), anyFloat(), anyFloat());
+
+ final PointerContext pContext = mPointerContextCaptor.getValue();
+ assertThat(pContext.pointerId).isEqualTo(POINTER_ID);
+ }
+
+ @Test
+ public void luxProbeWhenFingerDown() throws RemoteException {
+ final FingerprintAuthenticationClient client = createClient();
+ client.start(mCallback);
+
+ client.onPointerDown(TOUCH_X, TOUCH_Y, TOUCH_MAJOR, TOUCH_MINOR);
+ verify(mLuxProbe).enable();
+
+ client.onAcquired(2, 0);
+ verify(mLuxProbe, never()).disable();
+
+ client.onPointerUp();
+ verify(mLuxProbe).disable();
+
+ client.onPointerDown(TOUCH_X, TOUCH_Y, TOUCH_MAJOR, TOUCH_MINOR);
+ verify(mLuxProbe, times(2)).enable();
+ }
+
+ @Test
+ public void showHideOverlay_cancel() throws RemoteException {
+ showHideOverlay(c -> c.cancel());
+ }
+
+ @Test
+ public void showHideOverlay_stop() throws RemoteException {
+ showHideOverlay(c -> c.stopHalOperation());
+ }
+
+ @Test
+ public void showHideOverlay_error() throws RemoteException {
+ showHideOverlay(c -> c.onError(0, 0));
+ verify(mCallback).onClientFinished(any(), eq(false));
+ }
+
+ @Test
+ public void showHideOverlay_lockout() throws RemoteException {
+ showHideOverlay(c -> c.onLockoutTimed(5000));
+ }
+
+ @Test
+ public void showHideOverlay_lockoutPerm() throws RemoteException {
+ showHideOverlay(c -> c.onLockoutPermanent());
+ }
+
+ private void showHideOverlay(Consumer<FingerprintAuthenticationClient> block)
+ throws RemoteException {
+ final FingerprintAuthenticationClient client = createClient();
+
+ client.start(mCallback);
+
+ verify(mUdfpsOverlayController).showUdfpsOverlay(anyInt(), anyInt(), any());
+ verify(mSideFpsController).show(anyInt(), anyInt());
+
+ block.accept(client);
+
+ verify(mUdfpsOverlayController).hideUdfpsOverlay(anyInt());
+ verify(mSideFpsController).hide(anyInt());
+ }
+
+ private FingerprintAuthenticationClient createClient() throws RemoteException {
+ return createClient(100);
+ }
+
+ private FingerprintAuthenticationClient createClient(int version) throws RemoteException {
+ when(mHal.getInterfaceVersion()).thenReturn(version);
+
+ final AidlSession aidl = new AidlSession(version, mHal, USER_ID, mHalSessionCallback);
+ return new FingerprintAuthenticationClient(mContext, () -> aidl, mToken,
+ 2 /* requestId */, mClientMonitorCallbackConverter, 5 /* targetUserId */, OP_ID,
+ false /* restricted */, "test-owner", 4 /* cookie */, false /* requireConfirmation */,
+ 9 /* sensorId */, mBiometricLogger, mBiometricContext,
+ true /* isStrongBiometric */,
+ null /* taskStackListener */, mLockoutCache,
+ mUdfpsOverlayController, mSideFpsController,
+ false /* allowBackgroundAuthentication */, mSensorProps);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java
new file mode 100644
index 000000000000..295fe4766a85
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintDetectClientTest.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors.fingerprint.aidl;
+
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.hardware.biometrics.common.OperationContext;
+import android.hardware.biometrics.fingerprint.ISession;
+import android.hardware.fingerprint.IUdfpsOverlayController;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+import android.testing.TestableContext;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
+import com.android.server.biometrics.sensors.ClientMonitorCallback;
+import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+@Presubmit
+@SmallTest
+public class FingerprintDetectClientTest {
+
+ private static final int USER_ID = 8;
+ private static final boolean HAS_AOD = true;
+
+ @Rule
+ public final TestableContext mContext = new TestableContext(
+ InstrumentationRegistry.getInstrumentation().getTargetContext(), null);
+
+ @Mock
+ private ISession mHal;
+ @Mock
+ private IBinder mToken;
+ @Mock
+ private ClientMonitorCallbackConverter mClientMonitorCallbackConverter;
+ @Mock
+ private BiometricLogger mBiometricLogger;
+ @Mock
+ private BiometricContext mBiometricContext;
+ @Mock
+ private IUdfpsOverlayController mUdfpsOverlayController;
+ @Mock
+ private ClientMonitorCallback mCallback;
+ @Mock
+ private Sensor.HalSessionCallback mHalSessionCallback;
+ @Captor
+ private ArgumentCaptor<OperationContext> mOperationContextCaptor;
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Before
+ public void setup() {
+ when(mBiometricContext.isAoD()).thenReturn(HAS_AOD);
+ }
+
+ @Test
+ public void detectNoContext_v1() throws RemoteException {
+ final FingerprintDetectClient client = createClient(1);
+
+ client.start(mCallback);
+
+ verify(mHal).detectInteraction();
+ verify(mHal, never()).detectInteractionWithContext(any());
+ }
+
+ @Test
+ public void detectNoContext_v2() throws RemoteException {
+ final FingerprintDetectClient client = createClient(2);
+
+ client.start(mCallback);
+
+ verify(mHal).detectInteractionWithContext(mOperationContextCaptor.capture());
+ verify(mHal, never()).detectInteraction();
+ }
+
+ private FingerprintDetectClient createClient(int version) throws RemoteException {
+ when(mHal.getInterfaceVersion()).thenReturn(version);
+
+ final AidlSession aidl = new AidlSession(version, mHal, USER_ID, mHalSessionCallback);
+ return new FingerprintDetectClient(mContext, () -> aidl, mToken,
+ 6 /* requestId */, mClientMonitorCallbackConverter, 2 /* userId */,
+ "a-test", 1 /* sensorId */, mBiometricLogger, mBiometricContext,
+ mUdfpsOverlayController, true /* isStrongBiometric */);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
new file mode 100644
index 000000000000..7e44eab0a556
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/FingerprintEnrollClientTest.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.biometrics.sensors.fingerprint.aidl;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.hardware.biometrics.common.OperationContext;
+import android.hardware.biometrics.fingerprint.ISession;
+import android.hardware.biometrics.fingerprint.PointerContext;
+import android.hardware.fingerprint.Fingerprint;
+import android.hardware.fingerprint.FingerprintManager;
+import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
+import android.hardware.fingerprint.ISidefpsController;
+import android.hardware.fingerprint.IUdfpsOverlayController;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+import android.testing.TestableContext;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
+import com.android.server.biometrics.sensors.BiometricUtils;
+import com.android.server.biometrics.sensors.ClientMonitorCallback;
+import com.android.server.biometrics.sensors.ClientMonitorCallbackConverter;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+import java.util.function.Consumer;
+
+@Presubmit
+@SmallTest
+public class FingerprintEnrollClientTest {
+
+ private static final byte[] HAT = new byte[69];
+ private static final int USER_ID = 8;
+ private static final int POINTER_ID = 0;
+ private static final int TOUCH_X = 8;
+ private static final int TOUCH_Y = 20;
+ private static final float TOUCH_MAJOR = 4.4f;
+ private static final float TOUCH_MINOR = 5.5f;
+
+ @Rule
+ public final TestableContext mContext = new TestableContext(
+ InstrumentationRegistry.getInstrumentation().getTargetContext(), null);
+
+ @Mock
+ private ISession mHal;
+ @Mock
+ private IBinder mToken;
+ @Mock
+ private ClientMonitorCallbackConverter mClientMonitorCallbackConverter;
+ @Mock
+ private BiometricLogger mBiometricLogger;
+ @Mock
+ private BiometricContext mBiometricContext;
+ @Mock
+ private BiometricUtils<Fingerprint> mBiometricUtils;
+ @Mock
+ private IUdfpsOverlayController mUdfpsOverlayController;
+ @Mock
+ private ISidefpsController mSideFpsController;
+ @Mock
+ private FingerprintSensorPropertiesInternal mSensorProps;
+ @Mock
+ private ClientMonitorCallback mCallback;
+ @Mock
+ private Sensor.HalSessionCallback mHalSessionCallback;
+ @Captor
+ private ArgumentCaptor<OperationContext> mOperationContextCaptor;
+ @Captor
+ private ArgumentCaptor<PointerContext> mPointerContextCaptor;
+
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Test
+ public void enrollNoContext_v1() throws RemoteException {
+ final FingerprintEnrollClient client = createClient(1);
+
+ client.start(mCallback);
+
+ verify(mHal).enroll(any());
+ verify(mHal, never()).enrollWithContext(any(), any());
+ }
+
+ @Test
+ public void enrollWithContext_v2() throws RemoteException {
+ final FingerprintEnrollClient client = createClient(2);
+
+ client.start(mCallback);
+
+ verify(mHal).enrollWithContext(any(), mOperationContextCaptor.capture());
+ verify(mHal, never()).enroll(any());
+ }
+
+ @Test
+ public void pointerUp_v1() throws RemoteException {
+ final FingerprintEnrollClient client = createClient(1);
+ client.start(mCallback);
+ client.onPointerUp();
+
+ verify(mHal).onPointerUp(eq(POINTER_ID));
+ verify(mHal, never()).onPointerUpWithContext(any());
+ }
+
+ @Test
+ public void pointerDown_v1() throws RemoteException {
+ final FingerprintEnrollClient client = createClient(1);
+ client.start(mCallback);
+ client.onPointerDown(TOUCH_X, TOUCH_Y, TOUCH_MAJOR, TOUCH_MINOR);
+
+ verify(mHal).onPointerDown(eq(0),
+ eq(TOUCH_X), eq(TOUCH_Y), eq(TOUCH_MAJOR), eq(TOUCH_MINOR));
+ verify(mHal, never()).onPointerDownWithContext(any());
+ }
+
+ @Test
+ public void pointerUpWithContext_v2() throws RemoteException {
+ final FingerprintEnrollClient client = createClient(2);
+ client.start(mCallback);
+ client.onPointerUp();
+
+ verify(mHal).onPointerUpWithContext(mPointerContextCaptor.capture());
+ verify(mHal, never()).onPointerUp(eq(POINTER_ID));
+
+ final PointerContext pContext = mPointerContextCaptor.getValue();
+ assertThat(pContext.pointerId).isEqualTo(POINTER_ID);
+ }
+
+ @Test
+ public void pointerDownWithContext_v2() throws RemoteException {
+ final FingerprintEnrollClient client = createClient(2);
+ client.start(mCallback);
+ client.onPointerDown(TOUCH_X, TOUCH_Y, TOUCH_MAJOR, TOUCH_MINOR);
+
+ verify(mHal).onPointerDownWithContext(mPointerContextCaptor.capture());
+ verify(mHal, never()).onPointerDown(anyInt(), anyInt(), anyInt(), anyFloat(), anyFloat());
+
+ final PointerContext pContext = mPointerContextCaptor.getValue();
+ assertThat(pContext.pointerId).isEqualTo(POINTER_ID);
+ }
+
+ @Test
+ public void showHideOverlay_cancel() throws RemoteException {
+ showHideOverlay(c -> c.cancel());
+ }
+
+ @Test
+ public void showHideOverlay_stop() throws RemoteException {
+ showHideOverlay(c -> c.stopHalOperation());
+ }
+
+ @Test
+ public void showHideOverlay_error() throws RemoteException {
+ showHideOverlay(c -> c.onError(0, 0));
+ verify(mCallback).onClientFinished(any(), eq(false));
+ }
+
+ @Test
+ public void showHideOverlay_result() throws RemoteException {
+ showHideOverlay(c -> c.onEnrollResult(new Fingerprint("", 1, 1), 0));
+ }
+
+ private void showHideOverlay(Consumer<FingerprintEnrollClient> block)
+ throws RemoteException {
+ final FingerprintEnrollClient client = createClient();
+
+ client.start(mCallback);
+
+ verify(mUdfpsOverlayController).showUdfpsOverlay(anyInt(), anyInt(), any());
+ verify(mSideFpsController).show(anyInt(), anyInt());
+
+ block.accept(client);
+
+ verify(mUdfpsOverlayController).hideUdfpsOverlay(anyInt());
+ verify(mSideFpsController).hide(anyInt());
+ }
+
+ private FingerprintEnrollClient createClient() throws RemoteException {
+ return createClient(500);
+ }
+
+ private FingerprintEnrollClient createClient(int version) throws RemoteException {
+ when(mHal.getInterfaceVersion()).thenReturn(version);
+
+ final AidlSession aidl = new AidlSession(version, mHal, USER_ID, mHalSessionCallback);
+ return new FingerprintEnrollClient(mContext, () -> aidl, mToken, 6 /* requestId */,
+ mClientMonitorCallbackConverter, 0 /* userId */,
+ HAT, "owner", mBiometricUtils, 8 /* sensorId */,
+ mBiometricLogger, mBiometricContext, mSensorProps, mUdfpsOverlayController,
+ mSideFpsController, 6 /* maxTemplatesPerUser */, FingerprintManager.ENROLL_ENROLL);
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/SensorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/SensorTest.java
index 8b7b484b8462..e1a4a2d9f969 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/SensorTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/fingerprint/aidl/SensorTest.java
@@ -32,6 +32,8 @@ import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
+import com.android.server.biometrics.log.BiometricContext;
+import com.android.server.biometrics.log.BiometricLogger;
import com.android.server.biometrics.sensors.BiometricScheduler;
import com.android.server.biometrics.sensors.CoexCoordinator;
import com.android.server.biometrics.sensors.LockoutCache;
@@ -66,6 +68,10 @@ public class SensorTest {
private Sensor.HalSessionCallback.Callback mHalSessionCallback;
@Mock
private LockoutResetDispatcher mLockoutResetDispatcher;
+ @Mock
+ private BiometricLogger mLogger;
+ @Mock
+ private BiometricContext mBiometricContext;
private final TestLooper mLooper = new TestLooper();
private final LockoutCache mLockoutCache = new LockoutCache();
@@ -102,7 +108,8 @@ public class SensorTest {
mScheduler.scheduleClientMonitor(new FingerprintResetLockoutClient(mContext,
() -> new AidlSession(1, mSession, USER_ID, mHalCallback),
- USER_ID, TAG, SENSOR_ID, HAT, mLockoutCache, mLockoutResetDispatcher));
+ USER_ID, TAG, SENSOR_ID, mLogger, mBiometricContext, HAT, mLockoutCache,
+ mLockoutResetDispatcher));
mLooper.dispatchAll();
verifyNotLocked();
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java
index ff1b6f66ef85..83fa7ac02503 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/InputControllerTest.java
@@ -17,17 +17,23 @@
package com.android.server.companion.virtual;
import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import android.hardware.display.DisplayManagerInternal;
+import android.hardware.input.IInputManager;
+import android.hardware.input.InputManager;
import android.hardware.input.InputManagerInternal;
import android.os.Binder;
import android.os.IBinder;
import android.os.IInputConstants;
import android.platform.test.annotations.Presubmit;
import android.view.Display;
+import android.view.DisplayInfo;
import androidx.test.runner.AndroidJUnit4;
@@ -46,18 +52,31 @@ public class InputControllerTest {
@Mock
private InputManagerInternal mInputManagerInternalMock;
@Mock
+ private DisplayManagerInternal mDisplayManagerInternalMock;
+ @Mock
private InputController.NativeWrapper mNativeWrapperMock;
+ @Mock
+ private IInputManager mIInputManagerMock;
private InputController mInputController;
@Before
- public void setUp() {
+ public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
doNothing().when(mInputManagerInternalMock).setVirtualMousePointerDisplayId(anyInt());
LocalServices.removeServiceForTest(InputManagerInternal.class);
LocalServices.addService(InputManagerInternal.class, mInputManagerInternalMock);
+ final DisplayInfo displayInfo = new DisplayInfo();
+ displayInfo.uniqueId = "uniqueId";
+ doReturn(displayInfo).when(mDisplayManagerInternalMock).getDisplayInfo(anyInt());
+ LocalServices.removeServiceForTest(DisplayManagerInternal.class);
+ LocalServices.addService(DisplayManagerInternal.class, mDisplayManagerInternalMock);
+
+ InputManager.resetInstance(mIInputManagerMock);
+ doNothing().when(mIInputManagerMock).addUniqueIdAssociation(anyString(), anyString());
+ doNothing().when(mIInputManagerMock).removeUniqueIdAssociation(anyString());
mInputController = new InputController(new Object(), mNativeWrapperMock);
}
diff --git a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
index e36263e247bf..ceb723a407f9 100644
--- a/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/companion/virtual/VirtualDeviceManagerServiceTest.java
@@ -25,6 +25,7 @@ import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
import static org.mockito.Mockito.doCallRealMethod;
import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -57,6 +58,7 @@ import android.os.WorkSource;
import android.platform.test.annotations.Presubmit;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import android.view.DisplayInfo;
import android.view.KeyEvent;
import androidx.test.InstrumentationRegistry;
@@ -80,6 +82,8 @@ public class VirtualDeviceManagerServiceTest {
private static final int DISPLAY_ID = 2;
private static final int PRODUCT_ID = 10;
private static final int VENDOR_ID = 5;
+ private static final String UNIQUE_ID = "uniqueid";
+ private static final String PHYS = "phys";
private static final int HEIGHT = 1800;
private static final int WIDTH = 900;
private static final Binder BINDER = new Binder("binder");
@@ -116,6 +120,12 @@ public class VirtualDeviceManagerServiceTest {
LocalServices.removeServiceForTest(InputManagerInternal.class);
LocalServices.addService(InputManagerInternal.class, mInputManagerInternalMock);
+ final DisplayInfo displayInfo = new DisplayInfo();
+ displayInfo.uniqueId = UNIQUE_ID;
+ doReturn(displayInfo).when(mDisplayManagerInternalMock).getDisplayInfo(anyInt());
+ LocalServices.removeServiceForTest(DisplayManagerInternal.class);
+ LocalServices.addService(DisplayManagerInternal.class, mDisplayManagerInternalMock);
+
mContext = Mockito.spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
doNothing().when(mContext).enforceCallingOrSelfPermission(
eq(Manifest.permission.CREATE_VIRTUAL_DEVICE), anyString());
@@ -274,7 +284,8 @@ public class VirtualDeviceManagerServiceTest {
BINDER);
assertWithMessage("Virtual keyboard should register fd when the display matches")
.that(mInputController.mInputDeviceDescriptors).isNotEmpty();
- verify(mNativeWrapperMock).openUinputKeyboard(DEVICE_NAME, VENDOR_ID, PRODUCT_ID);
+ verify(mNativeWrapperMock).openUinputKeyboard(eq(DEVICE_NAME), eq(VENDOR_ID),
+ eq(PRODUCT_ID), anyString());
}
@Test
@@ -284,7 +295,8 @@ public class VirtualDeviceManagerServiceTest {
BINDER);
assertWithMessage("Virtual keyboard should register fd when the display matches")
.that(mInputController.mInputDeviceDescriptors).isNotEmpty();
- verify(mNativeWrapperMock).openUinputMouse(DEVICE_NAME, VENDOR_ID, PRODUCT_ID);
+ verify(mNativeWrapperMock).openUinputMouse(eq(DEVICE_NAME), eq(VENDOR_ID), eq(PRODUCT_ID),
+ anyString());
}
@Test
@@ -294,8 +306,8 @@ public class VirtualDeviceManagerServiceTest {
BINDER, new Point(WIDTH, HEIGHT));
assertWithMessage("Virtual keyboard should register fd when the display matches")
.that(mInputController.mInputDeviceDescriptors).isNotEmpty();
- verify(mNativeWrapperMock).openUinputTouchscreen(DEVICE_NAME, VENDOR_ID, PRODUCT_ID, HEIGHT,
- WIDTH);
+ verify(mNativeWrapperMock).openUinputTouchscreen(eq(DEVICE_NAME), eq(VENDOR_ID),
+ eq(PRODUCT_ID), anyString(), eq(HEIGHT), eq(WIDTH));
}
@Test
@@ -315,7 +327,7 @@ public class VirtualDeviceManagerServiceTest {
final int action = VirtualKeyEvent.ACTION_UP;
mInputController.mInputDeviceDescriptors.put(BINDER,
new InputController.InputDeviceDescriptor(fd, () -> {}, /* type= */ 1,
- /* displayId= */ 1));
+ /* displayId= */ 1, PHYS));
mDeviceImpl.sendKeyEvent(BINDER, new VirtualKeyEvent.Builder().setKeyCode(keyCode)
.setAction(action).build());
verify(mNativeWrapperMock).writeKeyEvent(fd, keyCode, action);
@@ -340,7 +352,7 @@ public class VirtualDeviceManagerServiceTest {
final int action = VirtualMouseButtonEvent.ACTION_BUTTON_PRESS;
mInputController.mInputDeviceDescriptors.put(BINDER,
new InputController.InputDeviceDescriptor(fd, () -> {}, /* type= */ 2,
- /* displayId= */ 1));
+ /* displayId= */ 1, PHYS));
mInputController.mActivePointerDisplayId = 1;
mDeviceImpl.sendButtonEvent(BINDER, new VirtualMouseButtonEvent.Builder()
.setButtonCode(buttonCode)
@@ -355,7 +367,7 @@ public class VirtualDeviceManagerServiceTest {
final int action = VirtualMouseButtonEvent.ACTION_BUTTON_PRESS;
mInputController.mInputDeviceDescriptors.put(BINDER,
new InputController.InputDeviceDescriptor(fd, () -> {}, /* type= */ 2,
- /* displayId= */ 1));
+ /* displayId= */ 1, PHYS));
assertThrows(
IllegalStateException.class,
() ->
@@ -381,7 +393,7 @@ public class VirtualDeviceManagerServiceTest {
final float y = 0.7f;
mInputController.mInputDeviceDescriptors.put(BINDER,
new InputController.InputDeviceDescriptor(fd, () -> {}, /* type= */ 2,
- /* displayId= */ 1));
+ /* displayId= */ 1, PHYS));
mInputController.mActivePointerDisplayId = 1;
mDeviceImpl.sendRelativeEvent(BINDER, new VirtualMouseRelativeEvent.Builder()
.setRelativeX(x).setRelativeY(y).build());
@@ -395,7 +407,7 @@ public class VirtualDeviceManagerServiceTest {
final float y = 0.7f;
mInputController.mInputDeviceDescriptors.put(BINDER,
new InputController.InputDeviceDescriptor(fd, () -> {}, /* type= */ 2,
- /* displayId= */ 1));
+ /* displayId= */ 1, PHYS));
assertThrows(
IllegalStateException.class,
() ->
@@ -422,7 +434,7 @@ public class VirtualDeviceManagerServiceTest {
final float y = 1f;
mInputController.mInputDeviceDescriptors.put(BINDER,
new InputController.InputDeviceDescriptor(fd, () -> {}, /* type= */ 2,
- /* displayId= */ 1));
+ /* displayId= */ 1, PHYS));
mInputController.mActivePointerDisplayId = 1;
mDeviceImpl.sendScrollEvent(BINDER, new VirtualMouseScrollEvent.Builder()
.setXAxisMovement(x)
@@ -437,7 +449,7 @@ public class VirtualDeviceManagerServiceTest {
final float y = 1f;
mInputController.mInputDeviceDescriptors.put(BINDER,
new InputController.InputDeviceDescriptor(fd, () -> {}, /* type= */ 2,
- /* displayId= */ 1));
+ /* displayId= */ 1, PHYS));
assertThrows(
IllegalStateException.class,
() ->
@@ -470,7 +482,7 @@ public class VirtualDeviceManagerServiceTest {
final int action = VirtualTouchEvent.ACTION_UP;
mInputController.mInputDeviceDescriptors.put(BINDER,
new InputController.InputDeviceDescriptor(fd, () -> {}, /* type= */ 3,
- /* displayId= */ 1));
+ /* displayId= */ 1, PHYS));
mDeviceImpl.sendTouchEvent(BINDER, new VirtualTouchEvent.Builder().setX(x)
.setY(y).setAction(action).setPointerId(pointerId).setToolType(toolType).build());
verify(mNativeWrapperMock).writeTouchEvent(fd, pointerId, toolType, action, x, y, Float.NaN,
@@ -489,7 +501,7 @@ public class VirtualDeviceManagerServiceTest {
final float majorAxisSize = 10.0f;
mInputController.mInputDeviceDescriptors.put(BINDER,
new InputController.InputDeviceDescriptor(fd, () -> {}, /* type= */ 3,
- /* displayId= */ 1));
+ /* displayId= */ 1, PHYS));
mDeviceImpl.sendTouchEvent(BINDER, new VirtualTouchEvent.Builder().setX(x)
.setY(y).setAction(action).setPointerId(pointerId).setToolType(toolType)
.setPressure(pressure).setMajorAxisSize(majorAxisSize).build());
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 564c4e439d86..64ce6b282f17 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -28,6 +28,14 @@ import static android.app.admin.DevicePolicyManager.ID_TYPE_BASE_INFO;
import static android.app.admin.DevicePolicyManager.ID_TYPE_IMEI;
import static android.app.admin.DevicePolicyManager.ID_TYPE_MEID;
import static android.app.admin.DevicePolicyManager.ID_TYPE_SERIAL;
+import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK;
+import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_GLOBAL_ACTIONS;
+import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_HOME;
+import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_KEYGUARD;
+import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NONE;
+import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_NOTIFICATIONS;
+import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_OVERVIEW;
+import static android.app.admin.DevicePolicyManager.LOCK_TASK_FEATURE_SYSTEM_INFO;
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_HIGH;
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_LOW;
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_MEDIUM;
@@ -101,6 +109,7 @@ import android.app.admin.WifiSsidPolicy;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Intent;
+import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
@@ -138,6 +147,9 @@ import com.android.internal.widget.LockscreenCredential;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.devicepolicy.DevicePolicyManagerService.RestrictionsListener;
+import com.android.server.pm.RestrictionsSet;
+import com.android.server.pm.UserManagerInternal;
+import com.android.server.pm.UserRestrictionsUtils;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
@@ -7764,6 +7776,296 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
@Test
+ public void testSetUserRestriction_financeDo_invalidRestrictions_restrictionNotSet()
+ throws Exception {
+ setDeviceOwner();
+ dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+
+ for (String restriction : UserRestrictionsUtils.USER_RESTRICTIONS) {
+ if (!UserRestrictionsUtils.canFinancedDeviceOwnerChange(restriction)) {
+ assertNoDeviceOwnerRestrictions();
+ assertExpectException(SecurityException.class, /* messageRegex= */ null,
+ () -> dpm.addUserRestriction(admin1, restriction));
+
+ verify(getServices().userManagerInternal, never())
+ .setDevicePolicyUserRestrictions(anyInt(), any(), any(), anyBoolean());
+ }
+ }
+ }
+
+ @Test
+ public void testSetUserRestriction_financeDo_validRestrictions_setsRestriction()
+ throws Exception {
+ setDeviceOwner();
+ dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+
+ for (String restriction : UserRestrictionsUtils.USER_RESTRICTIONS) {
+ if (UserRestrictionsUtils.canFinancedDeviceOwnerChange(restriction)) {
+ assertNoDeviceOwnerRestrictions();
+ dpm.addUserRestriction(admin1, restriction);
+
+ Bundle globalRestrictions =
+ dpms.getDeviceOwnerAdminLocked().getGlobalUserRestrictions(
+ UserManagerInternal.OWNER_TYPE_DEVICE_OWNER);
+ RestrictionsSet localRestrictions = new RestrictionsSet();
+ localRestrictions.updateRestrictions(
+ UserHandle.USER_SYSTEM,
+ dpms.getDeviceOwnerAdminLocked().getLocalUserRestrictions(
+ UserManagerInternal.OWNER_TYPE_DEVICE_OWNER));
+ verify(getServices().userManagerInternal)
+ .setDevicePolicyUserRestrictions(eq(UserHandle.USER_SYSTEM),
+ MockUtils.checkUserRestrictions(globalRestrictions),
+ MockUtils.checkUserRestrictions(
+ UserHandle.USER_SYSTEM, localRestrictions),
+ eq(true));
+ reset(getServices().userManagerInternal);
+
+ dpm.clearUserRestriction(admin1, restriction);
+ reset(getServices().userManagerInternal);
+ }
+ }
+ }
+
+ @Test
+ public void testSetLockTaskFeatures_financeDo_validLockTaskFeatures_lockTaskFeaturesSet()
+ throws Exception {
+ int validLockTaskFeatures = LOCK_TASK_FEATURE_SYSTEM_INFO | LOCK_TASK_FEATURE_KEYGUARD
+ | LOCK_TASK_FEATURE_HOME | LOCK_TASK_FEATURE_GLOBAL_ACTIONS
+ | LOCK_TASK_FEATURE_NOTIFICATIONS;
+ setDeviceOwner();
+ dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+
+ dpm.setLockTaskFeatures(admin1, validLockTaskFeatures);
+
+ verify(getServices().iactivityTaskManager)
+ .updateLockTaskFeatures(eq(UserHandle.USER_SYSTEM), eq(validLockTaskFeatures));
+ }
+
+ @Test
+ public void testSetLockTaskFeatures_financeDo_invalidLockTaskFeatures_throwsException()
+ throws Exception {
+ int invalidLockTaskFeatures = LOCK_TASK_FEATURE_NONE | LOCK_TASK_FEATURE_OVERVIEW
+ | LOCK_TASK_FEATURE_HOME | LOCK_TASK_FEATURE_BLOCK_ACTIVITY_START_IN_TASK;
+ setDeviceOwner();
+ dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+ // Called during setup.
+ verify(getServices().iactivityTaskManager).updateLockTaskFeatures(anyInt(), anyInt());
+
+ assertExpectException(SecurityException.class, /* messageRegex= */ null,
+ () -> dpm.setLockTaskFeatures(admin1, invalidLockTaskFeatures));
+
+ verifyNoMoreInteractions(getServices().iactivityTaskManager);
+ }
+
+ @Test
+ public void testIsUninstallBlocked_financeDo_success() throws Exception {
+ String packageName = "com.android.foo.package";
+ setDeviceOwner();
+ dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+ when(getServices().ipackageManager.getBlockUninstallForUser(
+ eq(packageName), eq(UserHandle.USER_SYSTEM)))
+ .thenReturn(true);
+
+ assertThat(dpm.isUninstallBlocked(admin1, packageName)).isTrue();
+ }
+
+ @Test
+ public void testSetUninstallBlocked_financeDo_success() throws Exception {
+ String packageName = "com.android.foo.package";
+ setDeviceOwner();
+ dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+
+ dpm.setUninstallBlocked(admin1, packageName, false);
+
+ verify(getServices().ipackageManager)
+ .setBlockUninstallForUser(eq(packageName), eq(false),
+ eq(UserHandle.USER_SYSTEM));
+ }
+
+ @Test
+ public void testSetUserControlDisabledPackages_financeDo_success() throws Exception {
+ List<String> packages = new ArrayList<>();
+ packages.add("com.android.foo.package");
+ setDeviceOwner();
+ dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+
+ dpm.setUserControlDisabledPackages(admin1, packages);
+
+ verify(getServices().packageManagerInternal)
+ .setDeviceOwnerProtectedPackages(eq(admin1.getPackageName()), eq(packages));
+ }
+
+ @Test
+ public void testGetUserControlDisabledPackages_financeDo_success() throws Exception {
+ setDeviceOwner();
+ dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+
+ assertThat(dpm.getUserControlDisabledPackages(admin1)).isEmpty();
+ }
+
+ @Test
+ public void testSetOrganizationName_financeDo_success() throws Exception {
+ String organizationName = "Test Organization";
+ setDeviceOwner();
+ dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+
+ dpm.setOrganizationName(admin1, organizationName);
+
+ assertThat(dpm.getDeviceOwnerOrganizationName()).isEqualTo(organizationName);
+ }
+
+ @Test
+ public void testSetShortSupportMessage_financeDo_success() throws Exception {
+ String supportMessage = "Test short support message";
+ setDeviceOwner();
+ dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+
+ dpm.setShortSupportMessage(admin1, supportMessage);
+
+ assertThat(dpm.getShortSupportMessage(admin1)).isEqualTo(supportMessage);
+ }
+
+ @Test
+ public void testIsBackupServiceEnabled_financeDo_success() throws Exception {
+ setDeviceOwner();
+ dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+ when(getServices().ibackupManager.isBackupServiceActive(eq(UserHandle.USER_SYSTEM)))
+ .thenReturn(true);
+
+ assertThat(dpm.isBackupServiceEnabled(admin1)).isTrue();
+ }
+
+ @Test
+ public void testSetBackupServiceEnabled_financeDo_success() throws Exception {
+ setDeviceOwner();
+ dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+
+ dpm.setBackupServiceEnabled(admin1, true);
+
+ verify(getServices().ibackupManager)
+ .setBackupServiceActive(eq(UserHandle.USER_SYSTEM), eq(true));
+ }
+
+ @Test
+ public void testIsLockTaskPermitted_financeDo_success() throws Exception {
+ String packageName = "com.android.foo.package";
+ mockPolicyExemptApps(packageName);
+ mockVendorPolicyExemptApps();
+ setDeviceOwner();
+ dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+
+ assertThat(dpm.isLockTaskPermitted(packageName)).isTrue();
+ }
+
+ @Test
+ public void testSetLockTaskPackages_financeDo_success() throws Exception {
+ String[] packages = {"com.android.foo.package"};
+ mockEmptyPolicyExemptApps();
+ setDeviceOwner();
+ dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+
+ dpm.setLockTaskPackages(admin1, packages);
+
+ verify(getServices().iactivityManager)
+ .updateLockTaskPackages(eq(UserHandle.USER_SYSTEM), eq(packages));
+ }
+
+ @Test
+ public void testAddPersistentPreferredActivity_financeDo_success() throws Exception {
+ IntentFilter filter = new IntentFilter();
+ ComponentName target = new ComponentName(admin2.getPackageName(), "test.class");
+ setDeviceOwner();
+ dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+
+ dpm.addPersistentPreferredActivity(admin1, filter, target);
+
+ verify(getServices().ipackageManager)
+ .addPersistentPreferredActivity(eq(filter), eq(target), eq(UserHandle.USER_SYSTEM));
+ verify(getServices().ipackageManager)
+ .flushPackageRestrictionsAsUser(eq(UserHandle.USER_SYSTEM));
+ }
+
+ @Test
+ public void testClearPackagePersistentPreferredActvities_financeDo_success() throws Exception {
+ String packageName = admin2.getPackageName();
+ setDeviceOwner();
+ dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+
+ dpm.clearPackagePersistentPreferredActivities(admin1, packageName);
+
+ verify(getServices().ipackageManager)
+ .clearPackagePersistentPreferredActivities(
+ eq(packageName), eq(UserHandle.USER_SYSTEM));
+ verify(getServices().ipackageManager)
+ .flushPackageRestrictionsAsUser(eq(UserHandle.USER_SYSTEM));
+ }
+
+ @Test
+ public void testWipeData_financeDo_success() throws Exception {
+ setDeviceOwner();
+ dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+ when(getServices().userManager.getUserRestrictionSource(
+ UserManager.DISALLOW_FACTORY_RESET,
+ UserHandle.SYSTEM))
+ .thenReturn(UserManager.RESTRICTION_SOURCE_DEVICE_OWNER);
+ when(mMockContext.getResources()
+ .getString(R.string.work_profile_deleted_description_dpm_wipe))
+ .thenReturn("Test string");
+
+ dpm.wipeData(0);
+
+ verifyRebootWipeUserData(/* wipeEuicc= */ false);
+ }
+
+ @Test
+ public void testIsDeviceOwnerApp_financeDo_success() throws Exception {
+ setDeviceOwner();
+ dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+
+ assertThat(dpm.isDeviceOwnerApp(admin1.getPackageName())).isTrue();
+ }
+
+ @Test
+ public void testClearDeviceOwnerApp_financeDo_success() throws Exception {
+ setDeviceOwner();
+ dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+
+ dpm.clearDeviceOwnerApp(admin1.getPackageName());
+
+ assertThat(dpm.getDeviceOwnerComponentOnAnyUser()).isNull();
+ assertThat(dpm.isAdminActiveAsUser(admin1, UserHandle.USER_SYSTEM)).isFalse();
+ verify(mMockContext.spiedContext, times(2))
+ .sendBroadcastAsUser(
+ MockUtils.checkIntentAction(
+ DevicePolicyManager.ACTION_DEVICE_OWNER_CHANGED),
+ eq(UserHandle.SYSTEM));
+ }
+
+ @Test
+ public void testSetPermissionGrantState_financeDo_notReadPhoneStatePermission_throwsException()
+ throws Exception {
+ setDeviceOwner();
+ dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+
+ assertExpectException(SecurityException.class, /* messageRegex= */ null,
+ () -> dpm.setPermissionGrantState(admin1, admin1.getPackageName(),
+ permission.READ_CALENDAR,
+ DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED));
+ }
+
+ @Test
+ public void testSetPermissionGrantState_financeDo_grantPermissionToNonDeviceOwnerPackage_throwsException()
+ throws Exception {
+ setDeviceOwner();
+ dpm.setDeviceOwnerType(admin1, DEVICE_OWNER_TYPE_FINANCED);
+
+ assertExpectException(SecurityException.class, /* messageRegex= */ null,
+ () -> dpm.setPermissionGrantState(admin1, "com.android.foo.package",
+ permission.READ_PHONE_STATE,
+ DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED));
+ }
+
+ @Test
public void testSetUsbDataSignalingEnabled_noDeviceOwnerOrPoOfOrgOwnedDevice() {
assertThrows(SecurityException.class,
() -> dpm.setUsbDataSignalingEnabled(true));
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
index 15f3ed1be552..4cb46b4047b0 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
@@ -109,6 +109,14 @@ public class MockUtils {
public static Bundle checkUserRestrictions(String... keys) {
final Bundle expected = DpmTestUtils.newRestrictions(
java.util.Objects.requireNonNull(keys));
+ return checkUserRestrictions(expected);
+ }
+
+ public static Bundle checkUserRestrictions(Bundle expected) {
+ return createUserRestrictionsBundleMatcher(expected);
+ }
+
+ private static Bundle createUserRestrictionsBundleMatcher(Bundle expected) {
final Matcher<Bundle> m = new BaseMatcher<Bundle>() {
@Override
public boolean matches(Object item) {
@@ -129,6 +137,15 @@ public class MockUtils {
public static RestrictionsSet checkUserRestrictions(int userId, String... keys) {
final RestrictionsSet expected = DpmTestUtils.newRestrictions(userId,
java.util.Objects.requireNonNull(keys));
+ return checkUserRestrictions(userId, expected);
+ }
+
+ public static RestrictionsSet checkUserRestrictions(int userId, RestrictionsSet expected) {
+ return createUserRestrictionsSetMatcher(userId, expected);
+ }
+
+ private static RestrictionsSet createUserRestrictionsSetMatcher(
+ int userId, RestrictionsSet expected) {
final Matcher<RestrictionsSet> m = new BaseMatcher<RestrictionsSet>() {
@Override
public boolean matches(Object item) {
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java
index a8f24ce5e11d..533fb2d8d214 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/OverlayPackagesProviderTest.java
@@ -26,6 +26,7 @@ import static android.app.admin.DevicePolicyManager.REQUIRED_APP_MANAGED_USER;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;
@@ -76,6 +77,7 @@ public class OverlayPackagesProviderTest {
private static final ComponentName TEST_MDM_COMPONENT_NAME = new ComponentName(
TEST_DPC_PACKAGE_NAME, "pc.package.name.DeviceAdmin");
private static final int TEST_USER_ID = 123;
+ private static final String ROLE_HOLDER_PACKAGE_NAME = "test.role.holder.package.name";
private @Mock Resources mResources;
@@ -305,6 +307,26 @@ public class OverlayPackagesProviderTest {
ACTION_PROVISION_MANAGED_PROFILE, "package1", "package2", "package3");
}
+ @Test
+ public void testGetNonRequiredApps_managedProfile_roleHolder_works() {
+ when(mInjector.getDeviceManagerRoleHolderPackageName(any()))
+ .thenReturn(ROLE_HOLDER_PACKAGE_NAME);
+ setSystemAppsWithLauncher("package1", "package2", ROLE_HOLDER_PACKAGE_NAME);
+
+ verifyAppsAreNonRequired(
+ ACTION_PROVISION_MANAGED_PROFILE, "package1", "package2");
+ }
+
+ @Test
+ public void testGetNonRequiredApps_managedDevice_roleHolder_works() {
+ when(mInjector.getDeviceManagerRoleHolderPackageName(any()))
+ .thenReturn(ROLE_HOLDER_PACKAGE_NAME);
+ setSystemAppsWithLauncher("package1", "package2", ROLE_HOLDER_PACKAGE_NAME);
+
+ verifyAppsAreNonRequired(
+ ACTION_PROVISION_MANAGED_DEVICE, "package1", "package2");
+ }
+
private void setupRegularModulesWithManagedUser(String... regularModules) {
setupRegularModulesWithMetadata(regularModules, REQUIRED_APP_MANAGED_USER);
}
diff --git a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
index d2cff0ea1968..fe3034dc569d 100644
--- a/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicestate/DeviceStateManagerServiceTest.java
@@ -326,7 +326,7 @@ public final class DeviceStateManagerServiceTest {
assertEquals(callback.getLastNotifiedInfo().currentState,
OTHER_DEVICE_STATE.getIdentifier());
- mService.getBinderService().cancelRequest(token);
+ mService.getBinderService().cancelStateRequest();
flushHandler();
assertEquals(callback.getLastNotifiedStatus(token),
@@ -378,9 +378,9 @@ public final class DeviceStateManagerServiceTest {
mPolicy.resumeConfigureOnce();
flushHandler();
- // First request status is now suspended as there is another pending request.
+ // First request status is now canceled as there is another pending request.
assertEquals(callback.getLastNotifiedStatus(firstRequestToken),
- TestDeviceStateManagerCallback.STATUS_SUSPENDED);
+ TestDeviceStateManagerCallback.STATUS_CANCELED);
// Second request status still unknown because the service is still awaiting policy
// callback.
assertEquals(callback.getLastNotifiedStatus(secondRequestToken),
@@ -402,19 +402,19 @@ public final class DeviceStateManagerServiceTest {
DEFAULT_DEVICE_STATE.getIdentifier());
// Now cancel the second request to make the first request active.
- mService.getBinderService().cancelRequest(secondRequestToken);
+ mService.getBinderService().cancelStateRequest();
flushHandler();
assertEquals(callback.getLastNotifiedStatus(firstRequestToken),
- TestDeviceStateManagerCallback.STATUS_ACTIVE);
+ TestDeviceStateManagerCallback.STATUS_CANCELED);
assertEquals(callback.getLastNotifiedStatus(secondRequestToken),
TestDeviceStateManagerCallback.STATUS_CANCELED);
- assertEquals(mService.getCommittedState(), Optional.of(OTHER_DEVICE_STATE));
+ assertEquals(mService.getCommittedState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mService.getPendingState(), Optional.empty());
assertEquals(mService.getBaseState(), Optional.of(DEFAULT_DEVICE_STATE));
assertEquals(mPolicy.getMostRecentRequestedStateToConfigure(),
- OTHER_DEVICE_STATE.getIdentifier());
+ DEFAULT_DEVICE_STATE.getIdentifier());
}
@Test
@@ -656,11 +656,6 @@ public final class DeviceStateManagerServiceTest {
}
@Override
- public void onRequestSuspended(IBinder token) {
- mLastNotifiedStatus.put(token, STATUS_SUSPENDED);
- }
-
- @Override
public void onRequestCanceled(IBinder token) {
mLastNotifiedStatus.put(token, STATUS_CANCELED);
}
diff --git a/services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java b/services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java
index b94fc4308ce2..2297c91818c0 100644
--- a/services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicestate/OverrideRequestControllerTest.java
@@ -18,7 +18,6 @@ package com.android.server.devicestate;
import static com.android.server.devicestate.OverrideRequestController.STATUS_ACTIVE;
import static com.android.server.devicestate.OverrideRequestController.STATUS_CANCELED;
-import static com.android.server.devicestate.OverrideRequestController.STATUS_SUSPENDED;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNull;
@@ -66,7 +65,7 @@ public final class OverrideRequestControllerTest {
}
@Test
- public void addRequest_suspendExistingRequest() {
+ public void addRequest_cancelExistingRequestThroughNewRequest() {
OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
0 /* requestedState */, 0 /* flags */);
assertNull(mStatusListener.getLastStatus(firstRequest));
@@ -75,92 +74,52 @@ public final class OverrideRequestControllerTest {
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
OverrideRequest secondRequest = new OverrideRequest(new Binder(), 0 /* pid */,
- 0 /* requestedState */, 0 /* flags */);
+ 1 /* requestedState */, 0 /* flags */);
assertNull(mStatusListener.getLastStatus(secondRequest));
mController.addRequest(secondRequest);
assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
- assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
}
@Test
public void addRequest_cancelActiveRequest() {
OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
0 /* requestedState */, 0 /* flags */);
- OverrideRequest secondRequest = new OverrideRequest(new Binder(), 0 /* pid */,
- 0 /* requestedState */, 0 /* flags */);
mController.addRequest(firstRequest);
- mController.addRequest(secondRequest);
-
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
- assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
- mController.cancelRequest(secondRequest.getToken());
-
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_CANCELED);
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
- }
- @Test
- public void addRequest_cancelSuspendedRequest() {
- OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
- 0 /* requestedState */, 0 /* flags */);
- OverrideRequest secondRequest = new OverrideRequest(new Binder(), 0 /* pid */,
- 0 /* requestedState */, 0 /* flags */);
+ mController.cancelOverrideRequest();
- mController.addRequest(firstRequest);
- mController.addRequest(secondRequest);
-
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
- assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
-
- mController.cancelRequest(firstRequest.getToken());
-
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
}
@Test
public void handleBaseStateChanged() {
OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
- 0 /* requestedState */, 0 /* flags */);
- OverrideRequest secondRequest = new OverrideRequest(new Binder(), 0 /* pid */,
0 /* requestedState */,
DeviceStateRequest.FLAG_CANCEL_WHEN_BASE_CHANGES /* flags */);
mController.addRequest(firstRequest);
- mController.addRequest(secondRequest);
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
- assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
mController.handleBaseStateChanged();
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_CANCELED);
- assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
}
@Test
public void handleProcessDied() {
OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
0 /* requestedState */, 0 /* flags */);
- OverrideRequest secondRequest = new OverrideRequest(new Binder(), 1 /* pid */,
- 0 /* requestedState */, 0 /* flags */);
mController.addRequest(firstRequest);
- mController.addRequest(secondRequest);
-
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
- assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
-
- mController.handleProcessDied(1);
-
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_CANCELED);
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
mController.handleProcessDied(0);
-
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
}
@@ -170,46 +129,29 @@ public final class OverrideRequestControllerTest {
OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
0 /* requestedState */, 0 /* flags */);
- OverrideRequest secondRequest = new OverrideRequest(new Binder(), 1 /* pid */,
- 0 /* requestedState */, 0 /* flags */);
mController.addRequest(firstRequest);
- mController.addRequest(secondRequest);
-
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
- assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
-
- mController.handleProcessDied(1);
-
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
- assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
-
- mController.cancelStickyRequests();
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_CANCELED);
+ mController.handleProcessDied(0);
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
+
+ mController.cancelStickyRequest();
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
}
@Test
public void handleNewSupportedStates() {
OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
1 /* requestedState */, 0 /* flags */);
- OverrideRequest secondRequest = new OverrideRequest(new Binder(), 0 /* pid */,
- 2 /* requestedState */, 0 /* flags */);
mController.addRequest(firstRequest);
- mController.addRequest(secondRequest);
-
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
- assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
mController.handleNewSupportedStates(new int[]{ 0, 1 });
-
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_CANCELED);
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
mController.handleNewSupportedStates(new int[]{ 0 });
-
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
}
@@ -217,18 +159,11 @@ public final class OverrideRequestControllerTest {
public void cancelOverrideRequestsTest() {
OverrideRequest firstRequest = new OverrideRequest(new Binder(), 0 /* pid */,
1 /* requestedState */, 0 /* flags */);
- OverrideRequest secondRequest = new OverrideRequest(new Binder(), 0 /* pid */,
- 2 /* requestedState */, 0 /* flags */);
mController.addRequest(firstRequest);
- mController.addRequest(secondRequest);
-
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_ACTIVE);
- assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_SUSPENDED);
-
- mController.cancelOverrideRequests();
+ assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_ACTIVE);
- assertEquals(mStatusListener.getLastStatus(secondRequest).intValue(), STATUS_CANCELED);
+ mController.cancelOverrideRequest();
assertEquals(mStatusListener.getLastStatus(firstRequest).intValue(), STATUS_CANCELED);
}
diff --git a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
index b7af010103bc..6203c2f54f07 100644
--- a/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/HighBrightnessModeControllerTest.java
@@ -663,6 +663,30 @@ public class HighBrightnessModeControllerTest {
eq(FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__REASON__HBM_SV_OFF_HDR_PLAYING));
}
+ @Test
+ public void tetHbmStats_LowRequestedBrightness() {
+ final HighBrightnessModeController hbmc = createDefaultHbm(new OffsettableClock());
+ final int displayStatsId = mDisplayUniqueId.hashCode();
+
+ hbmc.setAutoBrightnessEnabled(AUTO_BRIGHTNESS_ENABLED);
+ hbmc.onAmbientLuxChange(MINIMUM_LUX + 1);
+ hbmcOnBrightnessChanged(hbmc, TRANSITION_POINT + 0.01f);
+ advanceTime(0);
+ // verify in HBM sunlight mode
+ assertEquals(HIGH_BRIGHTNESS_MODE_SUNLIGHT, hbmc.getHighBrightnessMode());
+ // verify HBM_ON_SUNLIGHT
+ verify(mInjectorMock).reportHbmStateChange(eq(displayStatsId),
+ eq(FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_ON_SUNLIGHT),
+ eq(FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__REASON__HBM_TRANSITION_REASON_UNKNOWN));
+
+ hbmcOnBrightnessChanged(hbmc, DEFAULT_MIN);
+ // verify HBM_SV_OFF due to LOW_REQUESTED_BRIGHTNESS
+ verify(mInjectorMock).reportHbmStateChange(eq(displayStatsId),
+ eq(FrameworkStatsLog.DISPLAY_HBM_STATE_CHANGED__STATE__HBM_OFF),
+ eq(FrameworkStatsLog
+ .DISPLAY_HBM_STATE_CHANGED__REASON__HBM_SV_OFF_LOW_REQUESTED_BRIGHTNESS));
+ }
+
private void assertState(HighBrightnessModeController hbmc,
float brightnessMin, float brightnessMax, int hbmMode) {
assertEquals(brightnessMin, hbmc.getCurrentBrightnessMin(), EPSILON);
diff --git a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
index 4a24bbdb09ac..8e53ca1d599d 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
@@ -17,7 +17,7 @@
package com.android.server.pm;
import static android.content.pm.SharedLibraryInfo.TYPE_DYNAMIC;
-import static android.content.pm.SharedLibraryInfo.TYPE_SDK;
+import static android.content.pm.SharedLibraryInfo.TYPE_SDK_PACKAGE;
import static android.content.pm.SharedLibraryInfo.TYPE_STATIC;
import static android.content.pm.SharedLibraryInfo.VERSION_UNDEFINED;
@@ -258,7 +258,7 @@ public class ScanTests {
assertThat(scanResult.mSdkSharedLibraryInfo.getPackageName(), is("ogl.sdk_123"));
assertThat(scanResult.mSdkSharedLibraryInfo.getName(), is("ogl.sdk"));
assertThat(scanResult.mSdkSharedLibraryInfo.getLongVersion(), is(123L));
- assertThat(scanResult.mSdkSharedLibraryInfo.getType(), is(TYPE_SDK));
+ assertThat(scanResult.mSdkSharedLibraryInfo.getType(), is(TYPE_SDK_PACKAGE));
assertThat(scanResult.mSdkSharedLibraryInfo.getDeclaringPackage().getPackageName(),
is("ogl.sdk_123"));
assertThat(scanResult.mSdkSharedLibraryInfo.getDeclaringPackage().getLongVersionCode(),
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationComparatorTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationComparatorTest.java
index 5eed30be9279..91d4f8f63f38 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationComparatorTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationComparatorTest.java
@@ -67,6 +67,7 @@ public class NotificationComparatorTest extends UiServiceTestCase {
@Mock Vibrator mVibrator;
private final String callPkg = "com.android.server.notification";
+ private final String sysPkg = "android";
private final int callUid = 10;
private String smsPkg;
private final int smsUid = 11;
@@ -79,6 +80,7 @@ public class NotificationComparatorTest extends UiServiceTestCase {
private NotificationRecord mRecordHighCall;
private NotificationRecord mRecordHighCallStyle;
private NotificationRecord mRecordEmail;
+ private NotificationRecord mRecordSystemMax;
private NotificationRecord mRecordInlineReply;
private NotificationRecord mRecordSms;
private NotificationRecord mRecordStarredContact;
@@ -191,6 +193,12 @@ public class NotificationComparatorTest extends UiServiceTestCase {
mRecordContact.setContactAffinity(ValidateNotificationPeople.VALID_CONTACT);
mRecordContact.setSystemImportance(NotificationManager.IMPORTANCE_DEFAULT);
+ Notification nSystemMax = new Notification.Builder(mContext, TEST_CHANNEL_ID).build();
+ mRecordSystemMax = new NotificationRecord(mContext, new StatusBarNotification(sysPkg,
+ sysPkg, 1, "systemmax", uid2, uid2, nSystemMax, new UserHandle(userId),
+ "", 1244), getDefaultChannel());
+ mRecordSystemMax.setSystemImportance(NotificationManager.IMPORTANCE_HIGH);
+
Notification n8 = new Notification.Builder(mContext, TEST_CHANNEL_ID).build();
mRecordUrgent = new NotificationRecord(mContext, new StatusBarNotification(pkg2,
pkg2, 1, "urgent", uid2, uid2, n8, new UserHandle(userId),
@@ -267,6 +275,7 @@ public class NotificationComparatorTest extends UiServiceTestCase {
}
expected.add(mRecordStarredContact);
expected.add(mRecordContact);
+ expected.add(mRecordSystemMax);
expected.add(mRecordEmail);
expected.add(mRecordUrgent);
expected.add(mNoMediaSessionMedia);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java
index fa294dd61ea3..3b6718207c83 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java
@@ -20,8 +20,8 @@ import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
import static android.content.pm.PackageManager.GET_PERMISSIONS;
-import static android.permission.PermissionManager.PERMISSION_GRANTED;
-import static android.permission.PermissionManager.PERMISSION_SOFT_DENIED;
+import static android.content.pm.PackageManager.PERMISSION_DENIED;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static com.google.common.truth.Truth.assertThat;
@@ -130,13 +130,13 @@ public class PermissionHelperTest extends UiServiceTestCase {
@Test
public void testHasPermission() throws Exception {
- when(mPmi.checkUidPermission(anyInt(), eq(Manifest.permission.POST_NOTIFICATIONS)))
+ when(mPmi.checkPostNotificationsPermissionGrantedOrLegacyAccess(anyInt()))
.thenReturn(PERMISSION_GRANTED);
assertThat(mPermissionHelper.hasPermission(1)).isTrue();
- when(mPmi.checkUidPermission(anyInt(), eq(Manifest.permission.POST_NOTIFICATIONS)))
- .thenReturn(PERMISSION_SOFT_DENIED);
+ when(mPmi.checkPostNotificationsPermissionGrantedOrLegacyAccess(anyInt()))
+ .thenReturn(PERMISSION_DENIED);
assertThat(mPermissionHelper.hasPermission(1)).isFalse();
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
index fb1508842c9d..0f18cc61a95a 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeFilteringTest.java
@@ -17,7 +17,6 @@
package com.android.server.notification;
import static android.app.Notification.CATEGORY_CALL;
-import static android.app.Notification.CATEGORY_MESSAGE;
import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_ANYONE;
import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT;
@@ -25,6 +24,7 @@ import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_NONE;
import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CALLS;
import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS;
import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES;
+import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS;
import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
import static android.provider.Settings.Global.ZEN_MODE_ALARMS;
@@ -43,8 +43,10 @@ import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager.Policy;
import android.media.AudioAttributes;
+import android.os.Bundle;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
+import android.telephony.TelephonyManager;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -68,10 +70,15 @@ public class ZenModeFilteringTest extends UiServiceTestCase {
private NotificationMessagingUtil mMessagingUtil;
private ZenModeFiltering mZenModeFiltering;
+ @Mock private TelephonyManager mTelephonyManager;
+
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mZenModeFiltering = new ZenModeFiltering(mContext, mMessagingUtil);
+
+ // for repeat callers / matchesCallFilter
+ mContext.addMockSystemService(TelephonyManager.class, mTelephonyManager);
}
private NotificationRecord getNotificationRecord() {
@@ -95,6 +102,23 @@ public class ZenModeFilteringTest extends UiServiceTestCase {
return r;
}
+ private Bundle makeExtrasBundleWithPeople(String[] people) {
+ Bundle extras = new Bundle();
+ extras.putObject(Notification.EXTRA_PEOPLE_LIST, people);
+ return extras;
+ }
+
+ private NotificationRecord getNotificationRecordWithPeople(String[] people) {
+ // set up notification record
+ NotificationRecord r = mock(NotificationRecord.class);
+ StatusBarNotification sbn = mock(StatusBarNotification.class);
+ Notification notification = mock(Notification.class);
+ notification.extras = makeExtrasBundleWithPeople(people);
+ when(sbn.getNotification()).thenReturn(notification);
+ when(r.getSbn()).thenReturn(sbn);
+ return r;
+ }
+
@Test
public void testIsMessage() {
NotificationRecord r = getNotificationRecord();
@@ -309,4 +333,111 @@ public class ZenModeFilteringTest extends UiServiceTestCase {
assertFalse(mZenModeFiltering.shouldIntercept(ZEN_MODE_IMPORTANT_INTERRUPTIONS, policy, r));
}
+
+ @Test
+ public void testMatchesCallFilter_repeatCallers_directMatch() {
+ // after calls given an email with an exact string match, make sure that
+ // matchesCallFilter returns the right thing
+ String[] mailSource = new String[]{"mailto:hello.world"};
+ mZenModeFiltering.recordCall(getNotificationRecordWithPeople(mailSource));
+
+ // set up policy to only allow repeat callers
+ Policy policy = new Policy(
+ PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0, CONVERSATION_SENDERS_NONE);
+
+ // check whether matchesCallFilter returns the right thing
+ Bundle inputMatches = makeExtrasBundleWithPeople(new String[]{"mailto:hello.world"});
+ Bundle inputWrong = makeExtrasBundleWithPeople(new String[]{"mailto:nope"});
+ assertTrue(ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ policy, UserHandle.SYSTEM,
+ inputMatches, null, 0, 0));
+ assertFalse(ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ policy, UserHandle.SYSTEM,
+ inputWrong, null, 0, 0));
+ }
+
+ @Test
+ public void testMatchesCallFilter_repeatCallers_telephoneVariants() {
+ // set up telephony manager behavior
+ when(mTelephonyManager.getNetworkCountryIso()).thenReturn("us");
+
+ String[] telSource = new String[]{"tel:+1-617-555-1212"};
+ mZenModeFiltering.recordCall(getNotificationRecordWithPeople(telSource));
+
+ // set up policy to only allow repeat callers
+ Policy policy = new Policy(
+ PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0, CONVERSATION_SENDERS_NONE);
+
+ // cases to test:
+ // - identical number
+ // - same number, different formatting
+ // - different number
+ // - garbage
+ Bundle identical = makeExtrasBundleWithPeople(new String[]{"tel:+1-617-555-1212"});
+ Bundle same = makeExtrasBundleWithPeople(new String[]{"tel:16175551212"});
+ Bundle different = makeExtrasBundleWithPeople(new String[]{"tel:123-456-7890"});
+ Bundle garbage = makeExtrasBundleWithPeople(new String[]{"asdfghjkl;"});
+
+ assertTrue("identical numbers should match",
+ ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ policy, UserHandle.SYSTEM,
+ identical, null, 0, 0));
+ assertTrue("equivalent but non-identical numbers should match",
+ ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ policy, UserHandle.SYSTEM,
+ same, null, 0, 0));
+ assertFalse("non-equivalent numbers should not match",
+ ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ policy, UserHandle.SYSTEM,
+ different, null, 0, 0));
+ assertFalse("non-tel strings should not match",
+ ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ policy, UserHandle.SYSTEM,
+ garbage, null, 0, 0));
+ }
+
+ @Test
+ public void testMatchesCallFilter_repeatCallers_urlEncodedTels() {
+ // this is not intended to be a supported case but is one that we have seen
+ // sometimes in the wild, so make sure we handle url-encoded telephone numbers correctly
+ // when somebody provides one.
+
+ // set up telephony manager behavior
+ when(mTelephonyManager.getNetworkCountryIso()).thenReturn("us");
+
+ String[] telSource = new String[]{"tel:%2B16175551212"};
+ mZenModeFiltering.recordCall(getNotificationRecordWithPeople(telSource));
+
+ // set up policy to only allow repeat callers
+ Policy policy = new Policy(
+ PRIORITY_CATEGORY_REPEAT_CALLERS, 0, 0, 0, CONVERSATION_SENDERS_NONE);
+
+ // test cases for various forms of the same phone number and different ones
+ Bundle same1 = makeExtrasBundleWithPeople(new String[]{"tel:+1-617-555-1212"});
+ Bundle same2 = makeExtrasBundleWithPeople(new String[]{"tel:%2B1-617-555-1212"});
+ Bundle same3 = makeExtrasBundleWithPeople(new String[]{"tel:6175551212"});
+ Bundle different1 = makeExtrasBundleWithPeople(new String[]{"tel:%2B16175553434"});
+ Bundle different2 = makeExtrasBundleWithPeople(new String[]{"tel:+16175553434"});
+
+ assertTrue("same number should match",
+ ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ policy, UserHandle.SYSTEM,
+ same1, null, 0, 0));
+ assertTrue("same number should match",
+ ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ policy, UserHandle.SYSTEM,
+ same2, null, 0, 0));
+ assertTrue("same number should match",
+ ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ policy, UserHandle.SYSTEM,
+ same3, null, 0, 0));
+ assertFalse("different number should not match",
+ ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ policy, UserHandle.SYSTEM,
+ different1, null, 0, 0));
+ assertFalse("different number should not match",
+ ZenModeFiltering.matchesCallFilter(mContext, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
+ policy, UserHandle.SYSTEM,
+ different2, null, 0, 0));
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 30ad1f93bdf3..3298d1184cdc 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -85,7 +85,6 @@ import static com.android.server.wm.ActivityRecord.State.STARTED;
import static com.android.server.wm.ActivityRecord.State.STOPPED;
import static com.android.server.wm.ActivityRecord.State.STOPPING;
import static com.android.server.wm.ActivityTaskManagerService.INSTRUMENTATION_KEY_DISPATCHING_TIMEOUT_MILLIS;
-import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
import static com.android.server.wm.TaskFragment.TASK_FRAGMENT_VISIBILITY_INVISIBLE;
import static com.android.server.wm.TaskFragment.TASK_FRAGMENT_VISIBILITY_VISIBLE;
import static com.android.server.wm.TaskFragment.TASK_FRAGMENT_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT;
@@ -3114,7 +3113,7 @@ public class ActivityRecordTests extends WindowTestsBase {
}
@Test
- public void testInClosingAnimation_doNotHideSurface() {
+ public void testInClosingAnimation_visibilityNotCommitted_doNotHideSurface() {
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
makeWindowVisibleAndDrawn(app);
@@ -3123,16 +3122,45 @@ public class ActivityRecordTests extends WindowTestsBase {
mDisplayContent.mClosingApps.add(app.mActivityRecord);
mDisplayContent.prepareAppTransition(TRANSIT_CLOSE);
- // Update visibility and call to remove window
- app.mActivityRecord.commitVisibility(false, false);
+ // Remove window during transition, so it is requested to hide, but won't be committed until
+ // the transition is finished.
+ app.mActivityRecord.onRemovedFromDisplay();
+
+ assertTrue(mDisplayContent.mClosingApps.contains(app.mActivityRecord));
+ assertFalse(app.mActivityRecord.isVisibleRequested());
+ assertTrue(app.mActivityRecord.isVisible());
+ assertTrue(app.mActivityRecord.isSurfaceShowing());
+
+ // Start transition.
app.mActivityRecord.prepareSurfaces();
// Because the app is waiting for transition, it should not hide the surface.
assertTrue(app.mActivityRecord.isSurfaceShowing());
+ }
+
+ @Test
+ public void testInClosingAnimation_visibilityCommitted_hideSurface() {
+ final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
+ makeWindowVisibleAndDrawn(app);
+
+ // Put the activity in close transition.
+ mDisplayContent.mOpeningApps.clear();
+ mDisplayContent.mClosingApps.add(app.mActivityRecord);
+ mDisplayContent.prepareAppTransition(TRANSIT_CLOSE);
+
+ // Commit visibility before start transition.
+ app.mActivityRecord.commitVisibility(false, false);
+
+ assertFalse(app.mActivityRecord.isVisibleRequested());
+ assertFalse(app.mActivityRecord.isVisible());
+ assertTrue(app.mActivityRecord.isSurfaceShowing());
+
+ // Start transition.
+ app.mActivityRecord.prepareSurfaces();
- // Ensure onAnimationFinished will callback when the closing animation is finished.
- verify(app.mActivityRecord).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION),
- eq(null));
+ // Because the app visibility has been committed before the transition start, it should hide
+ // the surface.
+ assertFalse(app.mActivityRecord.isSurfaceShowing());
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index 7c340ecac2c7..8ada97147dd3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -191,7 +191,8 @@ public class ActivityTaskManagerServiceTests extends WindowTestsBase {
public void onFixedRotationFinished(int displayId) {}
@Override
- public void onKeepClearAreasChanged(int displayId, List<Rect> keepClearAreas) {}
+ public void onKeepClearAreasChanged(int displayId, List<Rect> restricted,
+ List<Rect> unrestricted) {}
};
int[] displayIds = mAtm.mWindowManager.registerDisplayWindowListener(listener);
for (int i = 0; i < displayIds.length; i++) {
diff --git a/services/usage/java/com/android/server/usage/BroadcastResponseStatsTracker.java b/services/usage/java/com/android/server/usage/BroadcastResponseStatsTracker.java
index 24fda17dbe79..e65501329cdf 100644
--- a/services/usage/java/com/android/server/usage/BroadcastResponseStatsTracker.java
+++ b/services/usage/java/com/android/server/usage/BroadcastResponseStatsTracker.java
@@ -69,6 +69,12 @@ class BroadcastResponseStatsTracker {
private SparseArray<SparseArray<UserBroadcastResponseStats>> mUserResponseStats =
new SparseArray<>();
+ private AppStandbyInternal mAppStandby;
+
+ BroadcastResponseStatsTracker(@NonNull AppStandbyInternal appStandby) {
+ mAppStandby = appStandby;
+ }
+
// TODO (206518114): Move all callbacks handling to a handler thread.
void reportBroadcastDispatchEvent(int sourceUid, @NonNull String targetPackage,
UserHandle targetUser, long idForResponseEvent,
@@ -132,8 +138,7 @@ class BroadcastResponseStatsTracker {
if (dispatchTimestampMs >= timestampMs) {
continue;
}
- // TODO (206518114): Make the constant configurable.
- if (elapsedDurationMs <= 2 * 60 * 1000) {
+ if (elapsedDurationMs <= mAppStandby.getBroadcastResponseWindowDurationMs()) {
final BroadcastEvent broadcastEvent = broadcastEvents.valueAt(i);
final BroadcastResponseStats responseStats =
getBroadcastResponseStats(broadcastEvent);
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index e90d28a11e1d..6906f20f26c2 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -281,7 +281,7 @@ public class UsageStatsService extends SystemService implements
mHandler = new H(BackgroundThread.get().getLooper());
mAppStandby = mInjector.getAppStandbyController(getContext());
- mResponseStatsTracker = new BroadcastResponseStatsTracker();
+ mResponseStatsTracker = new BroadcastResponseStatsTracker(mAppStandby);
mAppTimeLimit = new AppTimeLimitController(getContext(),
new AppTimeLimitController.TimeLimitCallbackListener() {
diff --git a/startop/iorap/Android.bp b/startop/iorap/Android.bp
deleted file mode 100644
index 4fdf34cc1814..000000000000
--- a/startop/iorap/Android.bp
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (C) 2018 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_base_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["frameworks_base_license"],
-}
-
-filegroup {
- name: "services.startop.iorap-javasources",
- srcs: ["src/**/*.java"],
- path: "src",
- visibility: ["//visibility:private"],
-}
-
-filegroup {
- name: "services.startop.iorap-sources",
- srcs: [
- ":services.startop.iorap-javasources",
- ":iorap-aidl",
- ],
- visibility: ["//frameworks/base/services:__subpackages__"],
-}
-
-java_library_static {
- name: "services.startop.iorap",
- srcs: [":services.startop.iorap-sources"],
- libs: ["services.core"],
-}
diff --git a/startop/iorap/TEST_MAPPING b/startop/iorap/TEST_MAPPING
deleted file mode 100644
index 8c9d4dfb0894..000000000000
--- a/startop/iorap/TEST_MAPPING
+++ /dev/null
@@ -1,12 +0,0 @@
-{
- "presubmit": [
- {
- "name": "libiorap-java-tests"
- }
- ],
- "imports": [
- {
- "path": "system/iorap"
- }
- ]
-}
diff --git a/startop/iorap/functional_tests/Android.bp b/startop/iorap/functional_tests/Android.bp
deleted file mode 100644
index 43c61551cdec..000000000000
--- a/startop/iorap/functional_tests/Android.bp
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_base_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["frameworks_base_license"],
-}
-
-android_test {
- name: "iorap-functional-tests",
- srcs: ["src/**/*.java"],
- data: [":iorap-functional-test-apps"],
- static_libs: [
- // Non-test dependencies
- // library under test
- "services.startop.iorap",
- // Test Dependencies
- // test android dependencies
- "platform-test-annotations",
- "androidx.test.rules",
- "androidx.test.ext.junit",
- "androidx.test.uiautomator_uiautomator",
- // test framework dependencies
- "truth-prebuilt",
- ],
- dxflags: ["--multi-dex"],
- test_suites: ["device-tests"],
- compile_multilib: "both",
- libs: [
- "android.test.base",
- "android.test.runner",
- ],
- certificate: "platform",
- platform_apis: true,
-}
diff --git a/startop/iorap/functional_tests/AndroidManifest.xml b/startop/iorap/functional_tests/AndroidManifest.xml
deleted file mode 100644
index 6bddc4a39577..000000000000
--- a/startop/iorap/functional_tests/AndroidManifest.xml
+++ /dev/null
@@ -1,38 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 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.
--->
-<!--suppress AndroidUnknownAttribute -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.google.android.startop.iorap.tests"
- android:sharedUserId="com.google.android.startop.iorap.tests.functional"
- android:versionCode="1"
- android:versionName="1.0" >
-
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
- <!--suppress AndroidDomInspection -->
- <instrumentation
- android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.google.android.startop.iorap.tests" />
-
- <!--
- 'debuggable=true' is required to properly load mockito jvmti dependencies,
- otherwise it gives the following error at runtime:
-
- Openjdkjvmti plugin was loaded on a non-debuggable Runtime.
- Plugin was loaded too late to change runtime state to DEBUGGABLE. -->
- <application android:debuggable="true">
- <uses-library android:name="android.test.runner" />
- </application>
-</manifest>
diff --git a/startop/iorap/functional_tests/AndroidTest.xml b/startop/iorap/functional_tests/AndroidTest.xml
deleted file mode 100644
index 31d4f6c47b11..000000000000
--- a/startop/iorap/functional_tests/AndroidTest.xml
+++ /dev/null
@@ -1,70 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2020 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.
--->
-
-<configuration description="Runs iorap-functional-tests.">
- <option name="test-suite-tag" value="apct" />
- <option name="test-suite-tag" value="apct-instrumentation" />
- <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
- <option name="cleanup-apks" value="true" />
- <option name="test-file-name" value="iorap-functional-tests.apk" />
- </target_preparer>
-
- <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
-
- <target_preparer
- class="com.android.tradefed.targetprep.DeviceSetup">
-
- <!-- iorapd does not pick up the above changes until we restart it -->
- <option name="run-command" value="stop iorapd" />
-
- <!-- Clean up the existing iorap database. -->
- <option name="run-command" value="rm -r /data/misc/iorapd/*" />
- <option name="run-command" value="sleep 1" />
-
- <!-- Set system properties to enable perfetto tracing, readahead and detailed logging. -->
- <option name="run-command" value="setprop iorapd.perfetto.enable true" />
- <option name="run-command" value="setprop iorapd.readahead.enable true" />
- <option name="run-command" value="setprop iorapd.log.verbose true" />
-
- <option name="run-command" value="start iorapd" />
-
- <!-- give it some time to restart the service; otherwise the first unit test might fail -->
- <option name="run-command" value="sleep 1" />
- </target_preparer>
-
- <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
- <option name="cleanup" value="true" />
- <option name="abort-on-push-failure" value="true" />
- <option name="push-file"
- key="iorap_test_app_v1.apk"
- value="/data/misc/iorapd/iorap_test_app_v1.apk" />
- <option name="push-file"
- key="iorap_test_app_v2.apk"
- value="/data/misc/iorapd/iorap_test_app_v2.apk" />
- <option name="push-file"
- key="iorap_test_app_v3.apk"
- value="/data/misc/iorapd/iorap_test_app_v3.apk" />
- </target_preparer>
-
- <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="com.google.android.startop.iorap.tests" />
- <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
- <!-- test-timeout unit is ms, value = 30 min -->
- <option name="test-timeout" value="1800000" />
- </test>
-
-</configuration>
-
diff --git a/startop/iorap/functional_tests/src/com/google/android/startop/iorap/IorapWorkFlowTest.java b/startop/iorap/functional_tests/src/com/google/android/startop/iorap/IorapWorkFlowTest.java
deleted file mode 100644
index 5352be6f283f..000000000000
--- a/startop/iorap/functional_tests/src/com/google/android/startop/iorap/IorapWorkFlowTest.java
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * Copyright (C) 2020 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.google.android.startop.iorapd;
-
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-
-import static org.hamcrest.CoreMatchers.notNullValue;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-
-import android.content.Context;
-import android.content.Intent;
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.database.sqlite.SQLiteDatabase;
-import android.util.Log;
-
-import androidx.test.InstrumentationRegistry;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.uiautomator.By;
-import androidx.test.uiautomator.UiDevice;
-import androidx.test.uiautomator.Until;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.io.File;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.time.Duration;
-import java.util.ArrayList;
-import java.util.concurrent.TimeUnit;
-import java.util.Date;
-import java.util.function.BooleanSupplier;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.List;
-import java.text.SimpleDateFormat;
-
-/**
- * Test for the work flow of iorap.
- *
- * <p> This test tests the function of iorap from:
- * perfetto collection -> compilation -> prefetching -> version update -> perfetto collection.
- */
-@RunWith(AndroidJUnit4.class)
-public class IorapWorkFlowTest {
- private static final String TAG = "IorapWorkFlowTest";
-
- private static final String TEST_APP_VERSION_ONE_PATH = "/data/misc/iorapd/iorap_test_app_v1.apk";
- private static final String TEST_APP_VERSION_TWO_PATH = "/data/misc/iorapd/iorap_test_app_v2.apk";
- private static final String TEST_APP_VERSION_THREE_PATH = "/data/misc/iorapd/iorap_test_app_v3.apk";
-
- private static final String DB_PATH = "/data/misc/iorapd/sqlite.db";
- private static final Duration TIMEOUT = Duration.ofSeconds(300L);
-
- private UiDevice mDevice;
-
- @Before
- public void setUp() throws Exception {
- // Initialize UiDevice instance
- mDevice = UiDevice.getInstance(getInstrumentation());
-
- // Start from the home screen
- mDevice.pressHome();
-
- // Wait for launcher
- final String launcherPackage = mDevice.getLauncherPackageName();
- assertThat(launcherPackage, notNullValue());
- mDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), TIMEOUT.getSeconds());
- }
-
- @After
- public void tearDown() throws Exception {
- String packageName = "com.example.ioraptestapp";
- uninstallApk(packageName);
- }
-
- @Test (timeout = 300000)
- public void testNormalWorkFlow() throws Exception {
- assertThat(mDevice, notNullValue());
-
- // Install test app version one
- installApk(TEST_APP_VERSION_ONE_PATH);
- String packageName = "com.example.ioraptestapp";
- String activityName = "com.example.ioraptestapp.MainActivity";
-
- // Perfetto trace collection phase.
- assertTrue(startAppForPerfettoTrace(
- packageName, activityName, /*version=*/1L));
- assertTrue(startAppForPerfettoTrace(
- packageName, activityName, /*version=*/1L));
- assertTrue(startAppForPerfettoTrace(
- packageName, activityName, /*version=*/1L));
-
- // Trigger maintenance service for compilation.
- TimeUnit.SECONDS.sleep(5L);
- assertTrue(compile(packageName, activityName, /*version=*/1L));
-
- // Run app with prefetching
- assertTrue(startAppWithCompiledTrace(
- packageName, activityName, /*version=*/1L));
- }
-
- @Test (timeout = 300000)
- public void testUpdateApp() throws Exception {
- assertThat(mDevice, notNullValue());
-
- // Install test app version two,
- String packageName = "com.example.ioraptestapp";
- String activityName = "com.example.ioraptestapp.MainActivity";
- installApk(TEST_APP_VERSION_TWO_PATH);
-
- // Perfetto trace collection phase.
- assertTrue(startAppForPerfettoTrace(
- packageName, activityName, /*version=*/2L));
- assertTrue(startAppForPerfettoTrace(
- packageName, activityName, /*version=*/2L));
- assertTrue(startAppForPerfettoTrace(
- packageName, activityName, /*version=*/2L));
-
- // Trigger maintenance service for compilation.
- TimeUnit.SECONDS.sleep(5L);
- assertTrue(compile(packageName, activityName, /*version=*/2L));
-
- // Run app with prefetching
- assertTrue(startAppWithCompiledTrace(
- packageName, activityName, /*version=*/2L));
-
- // Update test app to version 3
- installApk(TEST_APP_VERSION_THREE_PATH);
-
- // Rerun app, should do pefetto tracing.
- assertTrue(startAppForPerfettoTrace(
- packageName, activityName, /*version=*/3L));
- }
-
- private static void installApk(String apkPath) throws Exception {
- // Disable the selinux to allow pm install apk in the dir.
- executeShellCommand("setenforce 0");
- executeShellCommand("pm install -r -d " + apkPath);
- executeShellCommand("setenforce 1");
-
- }
-
- private static void uninstallApk(String apkPath) throws Exception {
- executeShellCommand("pm uninstall " + apkPath);
- }
-
- /**
- * Starts the testing app to collect the perfetto trace.
- *
- * @param expectPerfettoTraceCount is the expected count of perfetto traces.
- */
- private boolean startAppForPerfettoTrace(
- String packageName, String activityName, long version)
- throws Exception {
- LogcatTimestamp timestamp = runAppOnce(packageName, activityName);
- return waitForPerfettoTraceSavedFromLogcat(
- packageName, activityName, version, timestamp);
- }
-
- private boolean startAppWithCompiledTrace(
- String packageName, String activityName, long version)
- throws Exception {
- LogcatTimestamp timestamp = runAppOnce(packageName, activityName);
- return waitForPrefetchingFromLogcat(
- packageName, activityName, version, timestamp);
- }
-
- private LogcatTimestamp runAppOnce(String packageName, String activityName) throws Exception {
- // Close the specified app if it's open
- closeApp(packageName);
- LogcatTimestamp timestamp = new LogcatTimestamp();
- // Launch the specified app
- startApp(packageName, activityName);
- // Wait for the app to appear
- mDevice.wait(Until.hasObject(By.pkg(packageName).depth(0)), TIMEOUT.getSeconds());
- return timestamp;
- }
-
- // Invokes the maintenance to compile the perfetto traces to compiled trace.
- private boolean compile(
- String packageName, String activityName, long version) throws Exception {
- // The job id (283673059) is defined in class IorapForwardingService.
- executeShellCommandViaTmpFile("cmd jobscheduler run -f android 283673059");
- return waitForFileExistence(getCompiledTracePath(packageName, activityName, version));
- }
-
- private String getCompiledTracePath(
- String packageName, String activityName, long version) {
- return String.format(
- "/data/misc/iorapd/%s/%d/%s/compiled_traces/compiled_trace.pb",
- packageName, version, activityName);
- }
-
- /**
- * Starts the testing app.
- */
- private void startApp(String packageName, String activityName) throws Exception {
- executeShellCommandViaTmpFile(
- String.format("am start %s/%s", packageName, activityName));
- }
-
- /**
- * Closes the testing app.
- * <p> Keep trying to kill the process of the app until no process of the app package
- * appears.</p>
- */
- private void closeApp(String packageName) throws Exception {
- while (true) {
- String pid = executeShellCommand("pidof " + packageName);
- if (pid.isEmpty()) {
- Log.i(TAG, "Closed app " + packageName);
- return;
- }
- executeShellCommand("kill -9 " + pid);
- TimeUnit.SECONDS.sleep(1L);
- }
- }
-
- /** Waits for a file to appear. */
- private boolean waitForFileExistence(String fileName) throws Exception {
- return retryWithTimeout(TIMEOUT, () -> {
- try {
- String fileExists = executeShellCommandViaTmpFile(
- String.format("test -f %s; echo $?", fileName));
- Log.i(TAG, fileName + " existence is " + fileExists);
- return fileExists.trim().equals("0");
- } catch (Exception e) {
- Log.i(TAG, e.getMessage());
- return false;
- }
- });
- }
-
- /** Waits for the perfetto trace saved message from logcat. */
- private boolean waitForPerfettoTraceSavedFromLogcat(
- String packageName, String activityName, long version, LogcatTimestamp timestamp)
- throws Exception {
- Pattern p = Pattern.compile(".*"
- + getPerfettoTraceSavedIndicator(packageName, activityName, version)
- + "(.*[.]perfetto_trace[.]pb)\n.*", Pattern.DOTALL);
-
- return retryWithTimeout(TIMEOUT, () -> {
- try {
- String log = timestamp.getLogcatAfter();
- Matcher m = p.matcher(log);
- Log.d(TAG, "Tries to find perfetto trace...");
- if (!m.matches()) {
- Log.i(TAG, "Cannot find perfetto trace saved in log.");
- return false;
- }
- String filePath = m.group(1);
- Log.i(TAG, "Perfetto trace is saved to " + filePath);
- return true;
- } catch(Exception e) {
- Log.e(TAG, e.getMessage());
- return false;
- }
- });
- }
-
- private String getPerfettoTraceSavedIndicator(
- String packageName, String activityName, long version) {
- return String.format(
- "Perfetto TraceBuffer saved to file: /data/misc/iorapd/%s/%d/%s/raw_traces/",
- packageName, version, activityName);
- }
-
- /**
- * Waits for the prefetching log in the logcat.
- *
- * <p> When prefetching works, the perfetto traces should not be collected. </p>
- */
- private boolean waitForPrefetchingFromLogcat(
- String packageName, String activityName, long version, LogcatTimestamp timestamp)
- throws Exception {
- Pattern p = Pattern.compile(
- ".*" + getReadaheadIndicator(packageName, activityName, version) +
- ".*Total File Paths=(\\d+) \\(good: (\\d+[.]?\\d*)%\\)\n"
- + ".*Total Entries=(\\d+) \\(good: (\\d+[.]?\\d*)%\\)\n"
- + ".*Total Bytes=(\\d+) \\(good: (\\d+[.]?\\d*)%\\).*",
- Pattern.DOTALL);
-
- return retryWithTimeout(TIMEOUT, () -> {
- try {
- String log = timestamp.getLogcatAfter();
- Matcher m = p.matcher(log);
- if (!m.matches()) {
- Log.i(TAG, "Cannot find readahead log.");
- return false;
- }
-
- int totalFilePath = Integer.parseInt(m.group(1));
- float totalFilePathGoodRate = Float.parseFloat(m.group(2)) / 100;
- int totalEntries = Integer.parseInt(m.group(3));
- float totalEntriesGoodRate = Float.parseFloat(m.group(4)) / 100;
- int totalBytes = Integer.parseInt(m.group(5));
- float totalBytesGoodRate = Float.parseFloat(m.group(6)) / 100;
-
- Log.i(TAG, String.format(
- "totalFilePath: %d (good %.2f) totalEntries: %d (good %.2f) totalBytes: %d (good %.2f)",
- totalFilePath, totalFilePathGoodRate, totalEntries, totalEntriesGoodRate, totalBytes,
- totalBytesGoodRate));
-
- return totalFilePath > 0 &&
- totalEntries > 0 &&
- totalBytes > 0 &&
- totalFilePathGoodRate > 0.5 &&
- totalEntriesGoodRate > 0.5 &&
- totalBytesGoodRate > 0.5;
- } catch(Exception e) {
- return false;
- }
- });
- }
-
- private static String getReadaheadIndicator(
- String packageName, String activityName, long version) {
- return String.format(
- "Description = /data/misc/iorapd/%s/%d/%s/compiled_traces/compiled_trace.pb",
- packageName, version, activityName);
- }
-
- /** Retry until timeout. */
- private boolean retryWithTimeout(Duration timeout, BooleanSupplier supplier) throws Exception {
- long totalSleepTimeSeconds = 0L;
- long sleepIntervalSeconds = 2L;
- while (true) {
- if (supplier.getAsBoolean()) {
- return true;
- }
- TimeUnit.SECONDS.sleep(sleepIntervalSeconds);
- totalSleepTimeSeconds += sleepIntervalSeconds;
- if (totalSleepTimeSeconds > timeout.getSeconds()) {
- return false;
- }
- }
- }
-
- /**
- * Executes command in adb shell via a tmp file.
- *
- * <p> This should be run as root.</p>
- */
- private static String executeShellCommandViaTmpFile(String cmd) throws Exception {
- Log.i(TAG, "Execute via tmp file: " + cmd);
- Path tmp = null;
- try {
- tmp = Files.createTempFile(/*prefix=*/null, /*suffix=*/".sh");
- Files.write(tmp, cmd.getBytes(StandardCharsets.UTF_8));
- tmp.toFile().setExecutable(true);
- return UiDevice.getInstance(
- InstrumentationRegistry.getInstrumentation()).
- executeShellCommand(tmp.toString());
- } finally {
- if (tmp != null) {
- Files.delete(tmp);
- }
- }
- }
-
- /**
- * Executes command in adb shell.
- *
- * <p> This should be run as root.</p>
- */
- private static String executeShellCommand(String cmd) throws Exception {
- Log.i(TAG, "Execute: " + cmd);
- return UiDevice.getInstance(
- InstrumentationRegistry.getInstrumentation()).executeShellCommand(cmd);
- }
-
- static class LogcatTimestamp {
- private String epochTime;
-
- public LogcatTimestamp() throws Exception{
- long currentTimeMillis = System.currentTimeMillis();
- epochTime = String.format(
- "%d.%03d", currentTimeMillis/1000, currentTimeMillis%1000);
- Log.i(TAG, "Current logcat timestamp is " + epochTime);
- }
-
- // For example, 1585264100.000
- public String getEpochTime() {
- return epochTime;
- }
-
- // Gets the logcat after this epoch time.
- public String getLogcatAfter() throws Exception {
- return executeShellCommandViaTmpFile(
- "logcat -v epoch -t '" + epochTime + "'");
- }
- }
-}
-
diff --git a/startop/iorap/src/com/google/android/startop/iorap/ActivityHintEvent.java b/startop/iorap/src/com/google/android/startop/iorap/ActivityHintEvent.java
deleted file mode 100644
index 1d38f4c1e23d..000000000000
--- a/startop/iorap/src/com/google/android/startop/iorap/ActivityHintEvent.java
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.startop.iorap;
-
-import android.os.Parcelable;
-import android.os.Parcel;
-
-import android.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Objects;
-
-/**
- * Provide a hint to iorapd that an activity has transitioned state.<br /><br />
- *
- * Knowledge of when an activity starts/stops can be used by iorapd to increase system
- * performance (e.g. by launching perfetto tracing to record an io profile, or by
- * playing back an ioprofile via readahead) over the long run.<br /><br />
- *
- * /@see com.google.android.startop.iorap.IIorap#onActivityHintEvent<br /><br />
- *
- * Once an activity hint is in {@link #TYPE_STARTED} it must transition to another type.
- * All other states could be terminal, see below: <br /><br />
- *
- * <pre>
- *
- * ┌──────────────────────────────────────┐
- * │ ▼
- * ┌─────────┐ ╔════════════════╗ ╔═══════════╗
- * ──▶ │ STARTED │ ──▶ ║ COMPLETED ║ ──▶ ║ CANCELLED ║
- * └─────────┘ ╚════════════════╝ ╚═══════════╝
- * │
- * │
- * ▼
- * ╔════════════════╗
- * ║ POST_COMPLETED ║
- * ╚════════════════╝
- *
- * </pre> <!-- system/iorap/docs/binder/ActivityHint.dot -->
- *
- * @hide
- */
-public class ActivityHintEvent implements Parcelable {
-
- public static final int TYPE_STARTED = 0;
- public static final int TYPE_CANCELLED = 1;
- public static final int TYPE_COMPLETED = 2;
- public static final int TYPE_POST_COMPLETED = 3;
- private static final int TYPE_MAX = TYPE_POST_COMPLETED;
-
- /** @hide */
- @IntDef(flag = true, prefix = { "TYPE_" }, value = {
- TYPE_STARTED,
- TYPE_CANCELLED,
- TYPE_COMPLETED,
- TYPE_POST_COMPLETED,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Type {}
-
- @Type public final int type;
- public final ActivityInfo activityInfo;
-
- public ActivityHintEvent(@Type int type, ActivityInfo activityInfo) {
- this.type = type;
- this.activityInfo = activityInfo;
- checkConstructorArguments();
- }
-
- private void checkConstructorArguments() {
- CheckHelpers.checkTypeInRange(type, TYPE_MAX);
- Objects.requireNonNull(activityInfo, "activityInfo");
- }
-
- @Override
- public String toString() {
- return String.format("{type: %d, activityInfo: %s}", type, activityInfo);
- }
-
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- } else if (other instanceof ActivityHintEvent) {
- return equals((ActivityHintEvent) other);
- }
- return false;
- }
-
- private boolean equals(ActivityHintEvent other) {
- return type == other.type &&
- Objects.equals(activityInfo, other.activityInfo);
- }
-
- //<editor-fold desc="Binder boilerplate">
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(type);
- activityInfo.writeToParcel(out, flags);
- }
-
- private ActivityHintEvent(Parcel in) {
- this.type = in.readInt();
- this.activityInfo = ActivityInfo.CREATOR.createFromParcel(in);
- checkConstructorArguments();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Parcelable.Creator<ActivityHintEvent> CREATOR
- = new Parcelable.Creator<ActivityHintEvent>() {
- public ActivityHintEvent createFromParcel(Parcel in) {
- return new ActivityHintEvent(in);
- }
-
- public ActivityHintEvent[] newArray(int size) {
- return new ActivityHintEvent[size];
- }
- };
- //</editor-fold>
-}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/ActivityInfo.java b/startop/iorap/src/com/google/android/startop/iorap/ActivityInfo.java
deleted file mode 100644
index f47a42cffdd8..000000000000
--- a/startop/iorap/src/com/google/android/startop/iorap/ActivityInfo.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.startop.iorap;
-
-import java.util.Objects;
-
-import android.os.Parcelable;
-import android.os.Parcel;
-
-/**
- * Provide minimal information for launched activities to iorap.<br /><br />
- *
- * This uniquely identifies a system-wide activity by providing the {@link #packageName} and
- * {@link #activityName}.
- *
- * @see ActivityHintEvent
- * @see AppIntentEvent
- *
- * @hide
- */
-public class ActivityInfo implements Parcelable {
-
- /** The name of the package, for example {@code com.android.calculator}. */
- public final String packageName;
- /** The name of the activity, for example {@code .activities.activity.MainActivity} */
- public final String activityName;
-
- public ActivityInfo(String packageName, String activityName) {
- this.packageName = packageName;
- this.activityName = activityName;
-
- checkConstructorArguments();
- }
-
- private void checkConstructorArguments() {
- Objects.requireNonNull(packageName, "packageName");
- Objects.requireNonNull(activityName, "activityName");
- }
-
- @Override
- public String toString() {
- return String.format("{packageName: %s, activityName: %s}", packageName, activityName);
- }
-
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- } else if (other instanceof ActivityInfo) {
- return equals((ActivityInfo) other);
- }
- return false;
- }
-
- private boolean equals(ActivityInfo other) {
- return Objects.equals(packageName, other.packageName) &&
- Objects.equals(activityName, other.activityName);
- }
-
- //<editor-fold desc="Binder boilerplate">
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeString(packageName);
- out.writeString(activityName);
- }
-
- private ActivityInfo(Parcel in) {
- packageName = in.readString();
- activityName = in.readString();
-
- checkConstructorArguments();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Parcelable.Creator<ActivityInfo> CREATOR
- = new Parcelable.Creator<ActivityInfo>() {
- public ActivityInfo createFromParcel(Parcel in) {
- return new ActivityInfo(in);
- }
-
- public ActivityInfo[] newArray(int size) {
- return new ActivityInfo[size];
- }
- };
- //</editor-fold>
-}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/AppIntentEvent.java b/startop/iorap/src/com/google/android/startop/iorap/AppIntentEvent.java
deleted file mode 100644
index 1cd37b5546b9..000000000000
--- a/startop/iorap/src/com/google/android/startop/iorap/AppIntentEvent.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.startop.iorap;
-
-import android.os.Parcelable;
-import android.os.Parcel;
-
-import android.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Objects;
-
-/**
- * Notifications for iorapd specifying when a system-wide intent defaults change.<br /><br />
- *
- * Intent defaults provide a mechanism for an app to register itself as an automatic handler.
- * For example the camera app might be registered as the default handler for
- * {@link android.provider.MediaStore#INTENT_ACTION_STILL_IMAGE_CAMERA} intent. Subsequently,
- * if an arbitrary other app requests for a still image camera photo to be taken, the system
- * will launch the respective default camera app to be launched to handle that request.<br /><br />
- *
- * In some cases iorapd might need to know default intents, e.g. for boot-time pinning of
- * applications that resolve from the default intent. If the application would now be resolved
- * differently, iorapd would unpin the old application and pin the new application.<br /><br />
- *
- * @hide
- */
-public class AppIntentEvent implements Parcelable {
-
- /** @see android.content.Intent#CATEGORY_DEFAULT */
- public static final int TYPE_DEFAULT_INTENT_CHANGED = 0;
- private static final int TYPE_MAX = 0;
-
- /** @hide */
- @IntDef(flag = true, prefix = { "TYPE_" }, value = {
- TYPE_DEFAULT_INTENT_CHANGED,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Type {}
-
- @Type public final int type;
-
- public final ActivityInfo oldActivityInfo;
- public final ActivityInfo newActivityInfo;
-
- // TODO: Probably need the corresponding action here as well.
-
- public static AppIntentEvent createDefaultIntentChanged(ActivityInfo oldActivityInfo,
- ActivityInfo newActivityInfo) {
- return new AppIntentEvent(TYPE_DEFAULT_INTENT_CHANGED, oldActivityInfo,
- newActivityInfo);
- }
-
- private AppIntentEvent(@Type int type, ActivityInfo oldActivityInfo,
- ActivityInfo newActivityInfo) {
- this.type = type;
- this.oldActivityInfo = oldActivityInfo;
- this.newActivityInfo = newActivityInfo;
-
- checkConstructorArguments();
- }
-
- private void checkConstructorArguments() {
- CheckHelpers.checkTypeInRange(type, TYPE_MAX);
- Objects.requireNonNull(oldActivityInfo, "oldActivityInfo");
- Objects.requireNonNull(oldActivityInfo, "newActivityInfo");
- }
-
- @Override
- public String toString() {
- return String.format("{oldActivityInfo: %s, newActivityInfo: %s}", oldActivityInfo,
- newActivityInfo);
- }
-
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- } else if (other instanceof AppIntentEvent) {
- return equals((AppIntentEvent) other);
- }
- return false;
- }
-
- private boolean equals(AppIntentEvent other) {
- return type == other.type &&
- Objects.equals(oldActivityInfo, other.oldActivityInfo) &&
- Objects.equals(newActivityInfo, other.newActivityInfo);
- }
-
- //<editor-fold desc="Binder boilerplate">
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(type);
- oldActivityInfo.writeToParcel(out, flags);
- newActivityInfo.writeToParcel(out, flags);
- }
-
- private AppIntentEvent(Parcel in) {
- this.type = in.readInt();
- this.oldActivityInfo = ActivityInfo.CREATOR.createFromParcel(in);
- this.newActivityInfo = ActivityInfo.CREATOR.createFromParcel(in);
-
- checkConstructorArguments();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Parcelable.Creator<AppIntentEvent> CREATOR
- = new Parcelable.Creator<AppIntentEvent>() {
- public AppIntentEvent createFromParcel(Parcel in) {
- return new AppIntentEvent(in);
- }
-
- public AppIntentEvent[] newArray(int size) {
- return new AppIntentEvent[size];
- }
- };
- //</editor-fold>
-}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/AppLaunchEvent.java b/startop/iorap/src/com/google/android/startop/iorap/AppLaunchEvent.java
deleted file mode 100644
index 8263e0af4422..000000000000
--- a/startop/iorap/src/com/google/android/startop/iorap/AppLaunchEvent.java
+++ /dev/null
@@ -1,459 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.startop.iorap;
-
-import android.annotation.LongDef;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.proto.ProtoOutputStream;
-
-import com.android.server.wm.ActivityMetricsLaunchObserver;
-import com.android.server.wm.ActivityMetricsLaunchObserver.ActivityRecordProto;
-import com.android.server.wm.ActivityMetricsLaunchObserver.Temperature;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.reflect.InvocationTargetException;
-import java.util.Arrays;
-import java.util.Objects;
-
-/**
- * Provide a hint to iorapd that an app launch sequence has transitioned state.<br /><br />
- *
- * Knowledge of when an activity starts/stops can be used by iorapd to increase system
- * performance (e.g. by launching perfetto tracing to record an io profile, or by
- * playing back an ioprofile via readahead) over the long run.<br /><br />
- *
- * /@see com.google.android.startop.iorap.IIorap#onAppLaunchEvent <br /><br />
- * @see com.android.server.wm.ActivityMetricsLaunchObserver
- * ActivityMetricsLaunchObserver for the possible event states.
- * @hide
- */
-public abstract class AppLaunchEvent implements Parcelable {
- @LongDef
- @Retention(RetentionPolicy.SOURCE)
- public @interface SequenceId {}
-
- public final @SequenceId
- long sequenceId;
-
- protected AppLaunchEvent(@SequenceId long sequenceId) {
- this.sequenceId = sequenceId;
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof AppLaunchEvent) {
- return equals((AppLaunchEvent) other);
- }
- return false;
- }
-
- protected boolean equals(AppLaunchEvent other) {
- return sequenceId == other.sequenceId;
- }
-
-
- @Override
- public String toString() {
- return getClass().getSimpleName() +
- "{" + "sequenceId=" + Long.toString(sequenceId) +
- toStringBody() + "}";
- }
-
- protected String toStringBody() { return ""; };
-
- // List of possible variants:
-
- public static final class IntentStarted extends AppLaunchEvent {
- @NonNull
- public final Intent intent;
- public final long timestampNs;
-
- public IntentStarted(@SequenceId long sequenceId,
- Intent intent,
- long timestampNs) {
- super(sequenceId);
- this.intent = intent;
- this.timestampNs = timestampNs;
-
- Objects.requireNonNull(intent, "intent");
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof IntentStarted) {
- return intent.equals(((IntentStarted)other).intent) &&
- timestampNs == ((IntentStarted)other).timestampNs &&
- super.equals(other);
- }
- return false;
- }
-
- @Override
- protected String toStringBody() {
- return ", intent=" + intent.toString() +
- " , timestampNs=" + Long.toString(timestampNs);
- }
-
-
- @Override
- protected void writeToParcelImpl(Parcel p, int flags) {
- super.writeToParcelImpl(p, flags);
- IntentProtoParcelable.write(p, intent, flags);
- p.writeLong(timestampNs);
- }
-
- IntentStarted(Parcel p) {
- super(p);
- intent = IntentProtoParcelable.create(p);
- timestampNs = p.readLong();
- }
- }
-
- public static final class IntentFailed extends AppLaunchEvent {
- public IntentFailed(@SequenceId long sequenceId) {
- super(sequenceId);
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof IntentFailed) {
- return super.equals(other);
- }
- return false;
- }
-
- IntentFailed(Parcel p) {
- super(p);
- }
- }
-
- public static abstract class BaseWithActivityRecordData extends AppLaunchEvent {
- public final @NonNull
- @ActivityRecordProto byte[] activityRecordSnapshot;
-
- protected BaseWithActivityRecordData(@SequenceId long sequenceId,
- @NonNull @ActivityRecordProto byte[] snapshot) {
- super(sequenceId);
- activityRecordSnapshot = snapshot;
-
- Objects.requireNonNull(snapshot, "snapshot");
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof BaseWithActivityRecordData) {
- return (Arrays.equals(activityRecordSnapshot,
- ((BaseWithActivityRecordData)other).activityRecordSnapshot)) &&
- super.equals(other);
- }
- return false;
- }
-
- @Override
- protected String toStringBody() {
- return ", " + new String(activityRecordSnapshot);
- }
-
- @Override
- protected void writeToParcelImpl(Parcel p, int flags) {
- super.writeToParcelImpl(p, flags);
- ActivityRecordProtoParcelable.write(p, activityRecordSnapshot, flags);
- }
-
- BaseWithActivityRecordData(Parcel p) {
- super(p);
- activityRecordSnapshot = ActivityRecordProtoParcelable.create(p);
- }
- }
-
- public static final class ActivityLaunched extends BaseWithActivityRecordData {
- public final @ActivityMetricsLaunchObserver.Temperature
- int temperature;
-
- public ActivityLaunched(@SequenceId long sequenceId,
- @NonNull @ActivityRecordProto byte[] snapshot,
- @ActivityMetricsLaunchObserver.Temperature int temperature) {
- super(sequenceId, snapshot);
- this.temperature = temperature;
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof ActivityLaunched) {
- return temperature == ((ActivityLaunched)other).temperature &&
- super.equals(other);
- }
- return false;
- }
-
- @Override
- protected String toStringBody() {
- return super.toStringBody() + ", temperature=" + Integer.toString(temperature);
- }
-
- @Override
- protected void writeToParcelImpl(Parcel p, int flags) {
- super.writeToParcelImpl(p, flags);
- p.writeInt(temperature);
- }
-
- ActivityLaunched(Parcel p) {
- super(p);
- temperature = p.readInt();
- }
- }
-
- public static final class ActivityLaunchFinished extends BaseWithActivityRecordData {
- public final long timestampNs;
-
- public ActivityLaunchFinished(@SequenceId long sequenceId,
- @NonNull @ActivityRecordProto byte[] snapshot,
- long timestampNs) {
- super(sequenceId, snapshot);
- this.timestampNs = timestampNs;
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof ActivityLaunchFinished) {
- return timestampNs == ((ActivityLaunchFinished)other).timestampNs &&
- super.equals(other);
- }
- return false;
- }
-
- @Override
- protected String toStringBody() {
- return super.toStringBody() + ", timestampNs=" + Long.toString(timestampNs);
- }
-
- @Override
- protected void writeToParcelImpl(Parcel p, int flags) {
- super.writeToParcelImpl(p, flags);
- p.writeLong(timestampNs);
- }
-
- ActivityLaunchFinished(Parcel p) {
- super(p);
- timestampNs = p.readLong();
- }
- }
-
- public static class ActivityLaunchCancelled extends AppLaunchEvent {
- public final @Nullable @ActivityRecordProto byte[] activityRecordSnapshot;
-
- public ActivityLaunchCancelled(@SequenceId long sequenceId,
- @Nullable @ActivityRecordProto byte[] snapshot) {
- super(sequenceId);
- activityRecordSnapshot = snapshot;
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof ActivityLaunchCancelled) {
- return Arrays.equals(activityRecordSnapshot,
- ((ActivityLaunchCancelled)other).activityRecordSnapshot) &&
- super.equals(other);
- }
- return false;
- }
-
- @Override
- protected String toStringBody() {
- return super.toStringBody() + ", " + new String(activityRecordSnapshot);
- }
-
- @Override
- protected void writeToParcelImpl(Parcel p, int flags) {
- super.writeToParcelImpl(p, flags);
- if (activityRecordSnapshot != null) {
- p.writeBoolean(true);
- ActivityRecordProtoParcelable.write(p, activityRecordSnapshot, flags);
- } else {
- p.writeBoolean(false);
- }
- }
-
- ActivityLaunchCancelled(Parcel p) {
- super(p);
- if (p.readBoolean()) {
- activityRecordSnapshot = ActivityRecordProtoParcelable.create(p);
- } else {
- activityRecordSnapshot = null;
- }
- }
- }
-
- public static final class ReportFullyDrawn extends BaseWithActivityRecordData {
- public final long timestampNs;
-
- public ReportFullyDrawn(@SequenceId long sequenceId,
- @NonNull @ActivityRecordProto byte[] snapshot,
- long timestampNs) {
- super(sequenceId, snapshot);
- this.timestampNs = timestampNs;
- }
-
- @Override
- public boolean equals(Object other) {
- if (other instanceof ReportFullyDrawn) {
- return timestampNs == ((ReportFullyDrawn)other).timestampNs &&
- super.equals(other);
- }
- return false;
- }
-
- @Override
- protected String toStringBody() {
- return super.toStringBody() + ", timestampNs=" + Long.toString(timestampNs);
- }
-
- @Override
- protected void writeToParcelImpl(Parcel p, int flags) {
- super.writeToParcelImpl(p, flags);
- p.writeLong(timestampNs);
- }
-
- ReportFullyDrawn(Parcel p) {
- super(p);
- timestampNs = p.readLong();
- }
- }
-
- @Override
- public @ContentsFlags int describeContents() { return 0; }
-
- @Override
- public void writeToParcel(Parcel p, @WriteFlags int flags) {
- p.writeInt(getTypeIndex());
-
- writeToParcelImpl(p, flags);
- }
-
-
- public static Creator<AppLaunchEvent> CREATOR =
- new Creator<AppLaunchEvent>() {
- @Override
- public AppLaunchEvent createFromParcel(Parcel source) {
- int typeIndex = source.readInt();
-
- Class<?> kls = getClassFromTypeIndex(typeIndex);
- if (kls == null) {
- throw new IllegalArgumentException("Invalid type index: " + typeIndex);
- }
-
- try {
- return (AppLaunchEvent) kls.getConstructor(Parcel.class).newInstance(source);
- } catch (InstantiationException e) {
- throw new AssertionError(e);
- } catch (IllegalAccessException e) {
- throw new AssertionError(e);
- } catch (InvocationTargetException e) {
- throw new AssertionError(e);
- } catch (NoSuchMethodException e) {
- throw new AssertionError(e);
- }
- }
-
- @Override
- public AppLaunchEvent[] newArray(int size) {
- return new AppLaunchEvent[0];
- }
- };
-
- protected void writeToParcelImpl(Parcel p, int flags) {
- p.writeLong(sequenceId);
- }
-
- protected AppLaunchEvent(Parcel p) {
- sequenceId = p.readLong();
- }
-
- private int getTypeIndex() {
- for (int i = 0; i < sTypes.length; ++i) {
- if (sTypes[i].equals(this.getClass())) {
- return i;
- }
- }
- throw new AssertionError("sTypes did not include this type: " + this.getClass());
- }
-
- private static @Nullable Class<?> getClassFromTypeIndex(int typeIndex) {
- if (typeIndex >= 0 && typeIndex < sTypes.length) {
- return sTypes[typeIndex];
- }
- return null;
- }
-
- // Index position matters: It is used to encode the specific type in parceling.
- // Keep up-to-date with C++ side.
- private static Class<?>[] sTypes = new Class[] {
- IntentStarted.class,
- IntentFailed.class,
- ActivityLaunched.class,
- ActivityLaunchFinished.class,
- ActivityLaunchCancelled.class,
- ReportFullyDrawn.class,
- };
-
- public static class ActivityRecordProtoParcelable {
- public static void write(Parcel p, @ActivityRecordProto byte[] activityRecordSnapshot,
- int flags) {
- p.writeByteArray(activityRecordSnapshot);
- }
-
- public static @ActivityRecordProto byte[] create(Parcel p) {
- byte[] data = p.createByteArray();
-
- return data;
- }
- }
-
- public static class IntentProtoParcelable {
- private static final int INTENT_PROTO_CHUNK_SIZE = 1024;
-
- public static void write(Parcel p, @NonNull Intent intent, int flags) {
- // There does not appear to be a way to 'reset' a ProtoOutputBuffer stream,
- // so create a new one every time.
- final ProtoOutputStream protoOutputStream =
- new ProtoOutputStream(INTENT_PROTO_CHUNK_SIZE);
- // Write this data out as the top-most IntentProto (i.e. it is not a sub-object).
- intent.dumpDebug(protoOutputStream);
- final byte[] bytes = protoOutputStream.getBytes();
-
- p.writeByteArray(bytes);
- }
-
- // TODO: Should be mockable for testing?
- // We cannot deserialize in the platform because we don't have a 'readFromProto'
- // code.
- public static @NonNull Intent create(Parcel p) {
- // This will "read" the correct amount of data, but then we discard it.
- byte[] data = p.createByteArray();
-
- // Never called by real code in a platform, this binder API is implemented only in C++.
- return new Intent("<cannot deserialize IntentProto>");
- }
- }
-}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/CheckHelpers.java b/startop/iorap/src/com/google/android/startop/iorap/CheckHelpers.java
deleted file mode 100644
index 34aedd7685d8..000000000000
--- a/startop/iorap/src/com/google/android/startop/iorap/CheckHelpers.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.google.android.startop.iorap;
-
-/**
- * Convenience short-hand to throw {@link IllegalAccessException} when the arguments
- * are out-of-range.
- */
-public class CheckHelpers {
- /** @throws IllegalAccessException if {@param type} is not in {@code [0..maxValue]} */
- public static void checkTypeInRange(int type, int maxValue) {
- if (type < 0) {
- throw new IllegalArgumentException(
- String.format("type must be non-negative (value=%d)", type));
- }
- if (type > maxValue) {
- throw new IllegalArgumentException(
- String.format("type out of range (value=%d, max=%d)", type, maxValue));
- }
- }
-
- /** @throws IllegalAccessException if {@param state} is not in {@code [0..maxValue]} */
- public static void checkStateInRange(int state, int maxValue) {
- if (state < 0) {
- throw new IllegalArgumentException(
- String.format("state must be non-negative (value=%d)", state));
- }
- if (state > maxValue) {
- throw new IllegalArgumentException(
- String.format("state out of range (value=%d, max=%d)", state, maxValue));
- }
- }
-}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/DexOptEvent.java b/startop/iorap/src/com/google/android/startop/iorap/DexOptEvent.java
deleted file mode 100644
index 72c5eaa84c96..000000000000
--- a/startop/iorap/src/com/google/android/startop/iorap/DexOptEvent.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2020 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.google.android.startop.iorap;
-
-import android.annotation.NonNull;
-import android.os.Parcelable;
-import android.os.Parcel;
-
-import android.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Objects;
-
-/**
- * Notifications for iorapd specifying when a package is updated by dexopt service.<br /><br />
- *
- * @hide
- */
-public class DexOptEvent implements Parcelable {
- public static final int TYPE_PACKAGE_UPDATE = 0;
- private static final int TYPE_MAX = 0;
-
- /** @hide */
- @IntDef(flag = true, prefix = { "TYPE_" }, value = {
- TYPE_PACKAGE_UPDATE,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Type {}
-
- @Type public final int type;
- public final String packageName;
-
- @NonNull
- public static DexOptEvent createPackageUpdate(String packageName) {
- return new DexOptEvent(TYPE_PACKAGE_UPDATE, packageName);
- }
-
- private DexOptEvent(@Type int type, String packageName) {
- this.type = type;
- this.packageName = packageName;
-
- checkConstructorArguments();
- }
-
- private void checkConstructorArguments() {
- CheckHelpers.checkTypeInRange(type, TYPE_MAX);
- Objects.requireNonNull(packageName, "packageName");
- }
-
- @Override
- public String toString() {
- return String.format("{DexOptEvent: packageName: %s}", packageName);
- }
-
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- } else if (other instanceof DexOptEvent) {
- return equals((DexOptEvent) other);
- }
- return false;
- }
-
- private boolean equals(DexOptEvent other) {
- return packageName.equals(other.packageName);
- }
-
- //<editor-fold desc="Binder boilerplate">
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(type);
- out.writeString(packageName);
- }
-
- private DexOptEvent(Parcel in) {
- this.type = in.readInt();
- this.packageName = in.readString();
-
- checkConstructorArguments();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Parcelable.Creator<DexOptEvent> CREATOR
- = new Parcelable.Creator<DexOptEvent>() {
- public DexOptEvent createFromParcel(Parcel in) {
- return new DexOptEvent(in);
- }
-
- public DexOptEvent[] newArray(int size) {
- return new DexOptEvent[size];
- }
- };
- //</editor-fold>
-}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/EventSequenceValidator.java b/startop/iorap/src/com/google/android/startop/iorap/EventSequenceValidator.java
deleted file mode 100644
index dcaff26b79c6..000000000000
--- a/startop/iorap/src/com/google/android/startop/iorap/EventSequenceValidator.java
+++ /dev/null
@@ -1,267 +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.google.android.startop.iorap;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Intent;
-import android.util.Log;
-
-import com.android.server.wm.ActivityMetricsLaunchObserver;
-
-import java.io.StringWriter;
-import java.io.PrintWriter;
-
-/**
- * A validator to check the correctness of event sequence during app startup.
- *
- * <p> A valid state transition of event sequence is shown as the following:
- *
- * <pre>
- *
- * +--------------------+
- * | |
- * | INIT |
- * | |
- * +--------------------+
- * |
- * |
- * ↓
- * +--------------------+
- * | |
- * +-------------------| INTENT_STARTED | ←--------------------------------+
- * | | | |
- * | +--------------------+ |
- * | | |
- * | | |
- * ↓ ↓ |
- * +--------------------+ +--------------------+ |
- * | | | | |
- * | INTENT_FAILED | | ACTIVITY_LAUNCHED |------------------+ |
- * | | | | | |
- * +--------------------+ +--------------------+ | |
- * | | | |
- * | ↓ ↓ |
- * | +--------------------+ +--------------------+ |
- * | | | | | |
- * +------------------ | ACTIVITY_FINISHED | | ACTIVITY_CANCELLED | |
- * | | | | | |
- * | +--------------------+ +--------------------+ |
- * | | | |
- * | | | |
- * | ↓ | |
- * | +--------------------+ | |
- * | | | | |
- * | | REPORT_FULLY_DRAWN | | |
- * | | | | |
- * | +--------------------+ | |
- * | | | |
- * | | | |
- * | ↓ | |
- * | +--------------------+ | |
- * | | | | |
- * +-----------------→ | END |←-----------------+ |
- * | | |
- * +--------------------+ |
- * | |
- * | |
- * | |
- * +---------------------------------------------
- *
- * <p> END is not a real state in implementation. All states that points to END directly
- * could transition to INTENT_STARTED.
- *
- * <p> If any bad transition happened, the state becomse UNKNOWN. The UNKNOWN state
- * could be accumulated, because during the UNKNOWN state more IntentStarted may
- * be triggered. To recover from UNKNOWN to INIT, all the accumualted IntentStarted
- * should termniate.
- *
- * <p> During UNKNOWN state, each IntentStarted increases the accumulation, and any of
- * IntentFailed, ActivityLaunchCancelled and ActivityFinished decreases the accumulation.
- * ReportFullyDrawn doesn't impact the accumulation.
- */
-public class EventSequenceValidator implements ActivityMetricsLaunchObserver {
- static final String TAG = "EventSequenceValidator";
- /** $> adb shell 'setprop log.tag.EventSequenceValidator VERBOSE' */
- public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- private State state = State.INIT;
- private long accIntentStartedEvents = 0;
-
- @Override
- public void onIntentStarted(@NonNull Intent intent, long timestampNs) {
- if (state == State.UNKNOWN) {
- logWarningWithStackTrace("IntentStarted during UNKNOWN. " + intent);
- incAccIntentStartedEvents();
- return;
- }
-
- if (state != State.INIT &&
- state != State.INTENT_FAILED &&
- state != State.ACTIVITY_CANCELLED &&
- state != State.ACTIVITY_FINISHED &&
- state != State.REPORT_FULLY_DRAWN) {
- logWarningWithStackTrace(
- String.format("Cannot transition from %s to %s", state, State.INTENT_STARTED));
- incAccIntentStartedEvents();
- incAccIntentStartedEvents();
- return;
- }
-
- Log.i(TAG, String.format("Transition from %s to %s", state, State.INTENT_STARTED));
- state = State.INTENT_STARTED;
- }
-
- @Override
- public void onIntentFailed() {
- if (state == State.UNKNOWN) {
- logWarningWithStackTrace("onIntentFailed during UNKNOWN.");
- decAccIntentStartedEvents();
- return;
- }
- if (state != State.INTENT_STARTED) {
- logWarningWithStackTrace(
- String.format("Cannot transition from %s to %s", state, State.INTENT_FAILED));
- incAccIntentStartedEvents();
- return;
- }
-
- Log.i(TAG, String.format("Transition from %s to %s", state, State.INTENT_FAILED));
- state = State.INTENT_FAILED;
- }
-
- @Override
- public void onActivityLaunched(@NonNull @ActivityRecordProto byte[] activity,
- @Temperature int temperature) {
- if (state == State.UNKNOWN) {
- logWarningWithStackTrace("onActivityLaunched during UNKNOWN.");
- return;
- }
- if (state != State.INTENT_STARTED) {
- logWarningWithStackTrace(
- String.format("Cannot transition from %s to %s", state, State.ACTIVITY_LAUNCHED));
- incAccIntentStartedEvents();
- return;
- }
-
- Log.i(TAG, String.format("Transition from %s to %s", state, State.ACTIVITY_LAUNCHED));
- state = State.ACTIVITY_LAUNCHED;
- }
-
- @Override
- public void onActivityLaunchCancelled(@Nullable @ActivityRecordProto byte[] activity) {
- if (state == State.UNKNOWN) {
- logWarningWithStackTrace("onActivityLaunchCancelled during UNKNOWN.");
- decAccIntentStartedEvents();
- return;
- }
- if (state != State.ACTIVITY_LAUNCHED) {
- logWarningWithStackTrace(
- String.format("Cannot transition from %s to %s", state, State.ACTIVITY_CANCELLED));
- incAccIntentStartedEvents();
- return;
- }
-
- Log.i(TAG, String.format("Transition from %s to %s", state, State.ACTIVITY_CANCELLED));
- state = State.ACTIVITY_CANCELLED;
- }
-
- @Override
- public void onActivityLaunchFinished(@NonNull @ActivityRecordProto byte[] activity,
- long timestampNs) {
- if (state == State.UNKNOWN) {
- logWarningWithStackTrace("onActivityLaunchFinished during UNKNOWN.");
- decAccIntentStartedEvents();
- return;
- }
-
- if (state != State.ACTIVITY_LAUNCHED) {
- logWarningWithStackTrace(
- String.format("Cannot transition from %s to %s", state, State.ACTIVITY_FINISHED));
- incAccIntentStartedEvents();
- return;
- }
-
- Log.i(TAG, String.format("Transition from %s to %s", state, State.ACTIVITY_FINISHED));
- state = State.ACTIVITY_FINISHED;
- }
-
- @Override
- public void onReportFullyDrawn(@NonNull @ActivityRecordProto byte[] activity,
- long timestampNs) {
- if (state == State.UNKNOWN) {
- logWarningWithStackTrace("onReportFullyDrawn during UNKNOWN.");
- return;
- }
- if (state == State.INIT) {
- return;
- }
-
- if (state != State.ACTIVITY_FINISHED) {
- logWarningWithStackTrace(
- String.format("Cannot transition from %s to %s", state, State.REPORT_FULLY_DRAWN));
- return;
- }
-
- Log.i(TAG, String.format("Transition from %s to %s", state, State.REPORT_FULLY_DRAWN));
- state = State.REPORT_FULLY_DRAWN;
- }
-
- enum State {
- INIT,
- INTENT_STARTED,
- INTENT_FAILED,
- ACTIVITY_LAUNCHED,
- ACTIVITY_CANCELLED,
- ACTIVITY_FINISHED,
- REPORT_FULLY_DRAWN,
- UNKNOWN,
- }
-
- private void incAccIntentStartedEvents() {
- if (accIntentStartedEvents < 0) {
- throw new AssertionError("The number of unknowns cannot be negative");
- }
- if (accIntentStartedEvents == 0) {
- state = State.UNKNOWN;
- }
- ++accIntentStartedEvents;
- Log.i(TAG,
- String.format("inc AccIntentStartedEvents to %d", accIntentStartedEvents));
- }
-
- private void decAccIntentStartedEvents() {
- if (accIntentStartedEvents <= 0) {
- throw new AssertionError("The number of unknowns cannot be negative");
- }
- if(accIntentStartedEvents == 1) {
- state = State.INIT;
- }
- --accIntentStartedEvents;
- Log.i(TAG,
- String.format("dec AccIntentStartedEvents to %d", accIntentStartedEvents));
- }
-
- private void logWarningWithStackTrace(String log) {
- if (DEBUG) {
- StringWriter sw = new StringWriter();
- PrintWriter pw = new PrintWriter(sw);
- new Throwable("EventSequenceValidator#getStackTrace").printStackTrace(pw);
- Log.wtf(TAG, String.format("%s\n%s", log, sw));
- }
- }
-}
-
diff --git a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java b/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
deleted file mode 100644
index 77046f2276e9..000000000000
--- a/startop/iorap/src/com/google/android/startop/iorap/IorapForwardingService.java
+++ /dev/null
@@ -1,806 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.startop.iorap;
-// TODO: rename to com.android.server.startop.iorap
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.job.JobInfo;
-import android.app.job.JobParameters;
-import android.app.job.JobScheduler;
-import android.app.job.JobService;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Handler;
-import android.os.IBinder.DeathRecipient;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemProperties;
-import android.provider.DeviceConfig;
-import android.util.ArraySet;
-import android.util.Log;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.IoThread;
-import com.android.server.LocalServices;
-import com.android.server.SystemService;
-import com.android.server.pm.BackgroundDexOptService;
-import com.android.server.pm.PackageManagerService;
-import com.android.server.wm.ActivityMetricsLaunchObserver;
-import com.android.server.wm.ActivityMetricsLaunchObserverRegistry;
-import com.android.server.wm.ActivityTaskManagerInternal;
-
-import java.time.Duration;
-import java.util.HashMap;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.BooleanSupplier;
-
-/**
- * System-server-local proxy into the {@code IIorap} native service.
- */
-public class IorapForwardingService extends SystemService {
-
- public static final String TAG = "IorapForwardingService";
- /** $> adb shell 'setprop log.tag.IorapForwardingService VERBOSE' */
- public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- /** $> adb shell 'setprop ro.iorapd.enable true' */
- private static boolean IS_ENABLED = SystemProperties.getBoolean("ro.iorapd.enable", true);
- /** $> adb shell 'setprop iorapd.forwarding_service.wtf_crash true' */
- private static boolean WTF_CRASH = SystemProperties.getBoolean(
- "iorapd.forwarding_service.wtf_crash", false);
- private static final Duration TIMEOUT = Duration.ofSeconds(600L);
-
- // "Unique" job ID from the service name. Also equal to 283673059.
- public static final int JOB_ID_IORAPD = encodeEnglishAlphabetStringIntoInt("iorapd");
- // Run every 24 hours.
- public static final long JOB_INTERVAL_MS = TimeUnit.HOURS.toMillis(24);
-
- private IIorap mIorapRemote;
- private final Object mLock = new Object();
- /** Handle onBinderDeath by periodically trying to reconnect. */
- private final Handler mHandler =
- new BinderConnectionHandler(IoThread.getHandler().getLooper());
-
- private volatile IorapdJobService mJobService; // Write-once (null -> non-null forever).
- private volatile static IorapForwardingService sSelfService; // Write once (null -> non-null).
-
-
- /**
- * Atomics set to true if the JobScheduler requests an abort.
- */
- private final AtomicBoolean mAbortIdleCompilation = new AtomicBoolean(false);
-
- /**
- * Initializes the system service.
- * <p>
- * Subclasses must define a single argument constructor that accepts the context
- * and passes it to super.
- * </p>
- *
- * @param context The system server context.
- */
- public IorapForwardingService(Context context) {
- super(context);
-
- if (DEBUG) {
- Log.v(TAG, "IorapForwardingService (Context=" + context.toString() + ")");
- }
-
- if (sSelfService != null) {
- throw new AssertionError("only one service instance allowed");
- }
- sSelfService = this;
- }
-
- //<editor-fold desc="Providers">
- /*
- * Providers for external dependencies:
- * - These are marked as protected to allow tests to inject different values via mocks.
- */
-
- @VisibleForTesting
- protected ActivityMetricsLaunchObserverRegistry provideLaunchObserverRegistry() {
- ActivityTaskManagerInternal amtInternal =
- LocalServices.getService(ActivityTaskManagerInternal.class);
- ActivityMetricsLaunchObserverRegistry launchObserverRegistry =
- amtInternal.getLaunchObserverRegistry();
- return launchObserverRegistry;
- }
-
- @VisibleForTesting
- protected IIorap provideIorapRemote() {
- IIorap iorap;
- try {
- iorap = IIorap.Stub.asInterface(ServiceManager.getServiceOrThrow("iorapd"));
- } catch (ServiceManager.ServiceNotFoundException e) {
- Log.w(TAG, e.getMessage());
- return null;
- }
-
- try {
- iorap.asBinder().linkToDeath(provideDeathRecipient(), /*flags*/0);
- } catch (RemoteException e) {
- handleRemoteError(e);
- return null;
- }
-
- return iorap;
- }
-
- @VisibleForTesting
- protected DeathRecipient provideDeathRecipient() {
- return new DeathRecipient() {
- @Override
- public void binderDied() {
- Log.w(TAG, "iorapd has died");
- retryConnectToRemoteAndConfigure(/*attempts*/0);
-
- if (mJobService != null) {
- mJobService.onIorapdDisconnected();
- }
- }
- };
- }
-
- @VisibleForTesting
- protected boolean isIorapEnabled() {
- // These two mendel flags should match those in iorapd native process
- // system/iorapd/src/common/property.h
- boolean isTracingEnabled =
- getMendelFlag("iorap_perfetto_enable", "iorapd.perfetto.enable", false);
- boolean isReadAheadEnabled =
- getMendelFlag("iorap_readahead_enable", "iorapd.readahead.enable", false);
- // Same as the property in iorapd.rc -- disabling this will mean the 'iorapd' binder process
- // never comes up, so all binder connections will fail indefinitely.
- return IS_ENABLED && (isTracingEnabled || isReadAheadEnabled);
- }
-
- private boolean getMendelFlag(String mendelFlag, String sysProperty, boolean defaultValue) {
- // TODO(yawanng) use DeviceConfig to get mendel property.
- // DeviceConfig doesn't work and the reason is not clear.
- // Provider service is already up before IORapForwardService.
- String mendelProperty = "persist.device_config."
- + DeviceConfig.NAMESPACE_RUNTIME_NATIVE_BOOT
- + "."
- + mendelFlag;
- return SystemProperties.getBoolean(mendelProperty,
- SystemProperties.getBoolean(sysProperty, defaultValue));
- }
-
- //</editor-fold>
-
- @Override
- public void onStart() {
- if (DEBUG) {
- Log.v(TAG, "onStart");
- }
-
- retryConnectToRemoteAndConfigure(/*attempts*/0);
- }
-
- @Override
- public void onBootPhase(int phase) {
- if (phase == PHASE_BOOT_COMPLETED) {
- if (DEBUG) {
- Log.v(TAG, "onBootPhase(PHASE_BOOT_COMPLETED)");
- }
-
- if (isIorapEnabled()) {
- // Set up a recurring background job. This has to be done in a later phase since it
- // has a dependency the job scheduler.
- //
- // Doing this too early can result in a ServiceNotFoundException for 'jobservice'
- // or a null reference for #getSystemService(JobScheduler.class)
- mJobService = new IorapdJobService(getContext());
- }
- }
- }
-
- private class BinderConnectionHandler extends Handler {
- public BinderConnectionHandler(android.os.Looper looper) {
- super(looper);
- }
-
- public static final int MESSAGE_BINDER_CONNECT = 0;
-
- private int mAttempts = 0;
-
- @Override
- public void handleMessage(android.os.Message message) {
- switch (message.what) {
- case MESSAGE_BINDER_CONNECT:
- if (!retryConnectToRemoteAndConfigure(mAttempts)) {
- mAttempts++;
- } else {
- mAttempts = 0;
- }
- break;
- default:
- throw new AssertionError("Unknown message: " + message.toString());
- }
- }
- }
-
- /**
- * Handle iorapd shutdowns and crashes, by attempting to reconnect
- * until the service is reached again.
- *
- * <p>The first connection attempt is synchronous,
- * subsequent attempts are done by posting delayed tasks to the IoThread.</p>
- *
- * @return true if connection succeeded now, or false if it failed now [and needs to requeue].
- */
- private boolean retryConnectToRemoteAndConfigure(int attempts) {
- final int sleepTime = 1000; // ms
-
- if (DEBUG) {
- Log.v(TAG, "retryConnectToRemoteAndConfigure - attempt #" + attempts);
- }
-
- if (connectToRemoteAndConfigure()) {
- return true;
- }
-
- // Either 'iorapd' is stuck in a crash loop (ouch!!) or we manually
- // called 'adb shell stop iorapd' , which means this would loop until it comes back
- // up.
- //
- // TODO: it would be good to get nodified of 'adb shell stop iorapd' to avoid
- // printing this warning.
- if (DEBUG) {
- Log.v(TAG, "Failed to connect to iorapd, is it down? Delay for " + sleepTime);
- }
-
- // Use a handler instead of Thread#sleep to avoid backing up the binder thread
- // when this is called from the death recipient callback.
- mHandler.sendMessageDelayed(
- mHandler.obtainMessage(BinderConnectionHandler.MESSAGE_BINDER_CONNECT),
- sleepTime);
-
- return false;
-
- // Log.e(TAG, "Can't connect to iorapd - giving up after " + attempts + " attempts");
- }
-
- private boolean connectToRemoteAndConfigure() {
- synchronized (mLock) {
- // Synchronize against any concurrent calls to this via the DeathRecipient.
- return connectToRemoteAndConfigureLocked();
- }
- }
-
- private boolean connectToRemoteAndConfigureLocked() {
- if (!isIorapEnabled()) {
- if (DEBUG) {
- Log.v(TAG, "connectToRemoteAndConfigure - iorapd is disabled, skip rest of work");
- }
- // When we see that iorapd is disabled (when system server comes up),
- // it stays disabled permanently until the next system server reset.
-
- // TODO: consider listening to property changes as a callback, then we can
- // be more dynamic about handling enable/disable.
- return true;
- }
-
- // Connect to the native binder service.
- mIorapRemote = provideIorapRemote();
- if (mIorapRemote == null) {
- if (DEBUG) {
- Log.e(TAG, "connectToRemoteAndConfigure - null iorap remote. check for Log.wtf?");
- }
- return false;
- }
- invokeRemote(mIorapRemote,
- (IIorap remote) -> remote.setTaskListener(new RemoteTaskListener()) );
- registerInProcessListenersLocked();
-
- Log.i(TAG, "Connected to iorapd native service.");
-
- return true;
- }
-
- private final AppLaunchObserver mAppLaunchObserver = new AppLaunchObserver();
- private final EventSequenceValidator mEventSequenceValidator = new EventSequenceValidator();
- private final DexOptPackagesUpdated mDexOptPackagesUpdated = new DexOptPackagesUpdated();
- private boolean mRegisteredListeners = false;
-
- private void registerInProcessListenersLocked() {
- if (mRegisteredListeners) {
- // Listeners are registered only once (idempotent operation).
- //
- // Today listeners are tolerant of the remote side going away
- // by handling remote errors.
- //
- // We could try to 'unregister' the listener when we get a binder disconnect,
- // but we'd still have to handle the case of encountering synchronous errors so
- // it really wouldn't be a win (other than having less log spew).
- return;
- }
-
- // Listen to App Launch Sequence events from ActivityTaskManager,
- // and forward them to the native binder service.
- ActivityMetricsLaunchObserverRegistry launchObserverRegistry =
- provideLaunchObserverRegistry();
- launchObserverRegistry.registerLaunchObserver(mAppLaunchObserver);
- launchObserverRegistry.registerLaunchObserver(mEventSequenceValidator);
-
- BackgroundDexOptService.getService().addPackagesUpdatedListener(
- mDexOptPackagesUpdated);
-
-
- mRegisteredListeners = true;
- }
-
- private class DexOptPackagesUpdated implements BackgroundDexOptService.PackagesUpdatedListener {
- @Override
- public void onPackagesUpdated(ArraySet<String> updatedPackages) {
- String[] updated = updatedPackages.toArray(new String[0]);
- for (String packageName : updated) {
- Log.d(TAG, "onPackagesUpdated: " + packageName);
- invokeRemote(mIorapRemote,
- (IIorap remote) ->
- remote.onDexOptEvent(RequestId.nextValueForSequence(),
- DexOptEvent.createPackageUpdate(packageName))
- );
- }
- }
- }
-
- private class AppLaunchObserver implements ActivityMetricsLaunchObserver {
- // We add a synthetic sequence ID here to make it easier to differentiate new
- // launch sequences on the native side.
- private @AppLaunchEvent.SequenceId long mSequenceId = -1;
-
- // All callbacks occur on the same background thread. Don't synchronize explicitly.
-
- @Override
- public void onIntentStarted(@NonNull Intent intent, long timestampNs) {
- // #onIntentStarted [is the only transition that] initiates a new launch sequence.
- ++mSequenceId;
-
- if (DEBUG) {
- Log.v(TAG, String.format("AppLaunchObserver#onIntentStarted(%d, %s, %d)",
- mSequenceId, intent, timestampNs));
- }
-
- invokeRemote(mIorapRemote,
- (IIorap remote) ->
- remote.onAppLaunchEvent(RequestId.nextValueForSequence(),
- new AppLaunchEvent.IntentStarted(mSequenceId, intent, timestampNs))
- );
- }
-
- @Override
- public void onIntentFailed() {
- if (DEBUG) {
- Log.v(TAG, String.format("AppLaunchObserver#onIntentFailed(%d)", mSequenceId));
- }
-
- invokeRemote(mIorapRemote,
- (IIorap remote) ->
- remote.onAppLaunchEvent(RequestId.nextValueForSequence(),
- new AppLaunchEvent.IntentFailed(mSequenceId))
- );
- }
-
- @Override
- public void onActivityLaunched(@NonNull @ActivityRecordProto byte[] activity,
- @Temperature int temperature) {
- if (DEBUG) {
- Log.v(TAG, String.format("AppLaunchObserver#onActivityLaunched(%d, %s, %d)",
- mSequenceId, activity, temperature));
- }
-
- invokeRemote(mIorapRemote,
- (IIorap remote) ->
- remote.onAppLaunchEvent(RequestId.nextValueForSequence(),
- new AppLaunchEvent.ActivityLaunched(mSequenceId, activity, temperature))
- );
- }
-
- @Override
- public void onActivityLaunchCancelled(@Nullable @ActivityRecordProto byte[] activity) {
- if (DEBUG) {
- Log.v(TAG, String.format("AppLaunchObserver#onActivityLaunchCancelled(%d, %s)",
- mSequenceId, activity));
- }
-
- invokeRemote(mIorapRemote,
- (IIorap remote) ->
- remote.onAppLaunchEvent(RequestId.nextValueForSequence(),
- new AppLaunchEvent.ActivityLaunchCancelled(mSequenceId,
- activity)));
- }
-
- @Override
- public void onActivityLaunchFinished(@NonNull @ActivityRecordProto byte[] activity,
- long timestampNs) {
- if (DEBUG) {
- Log.v(TAG, String.format("AppLaunchObserver#onActivityLaunchFinished(%d, %s, %d)",
- mSequenceId, activity, timestampNs));
- }
-
- invokeRemote(mIorapRemote,
- (IIorap remote) ->
- remote.onAppLaunchEvent(RequestId.nextValueForSequence(),
- new AppLaunchEvent.ActivityLaunchFinished(mSequenceId,
- activity,
- timestampNs))
- );
- }
-
- @Override
- public void onReportFullyDrawn(@NonNull @ActivityRecordProto byte[] activity,
- long timestampNs) {
- if (DEBUG) {
- Log.v(TAG, String.format("AppLaunchObserver#onReportFullyDrawn(%d, %s, %d)",
- mSequenceId, activity, timestampNs));
- }
-
- invokeRemote(mIorapRemote,
- (IIorap remote) ->
- remote.onAppLaunchEvent(RequestId.nextValueForSequence(),
- new AppLaunchEvent.ReportFullyDrawn(mSequenceId, activity, timestampNs))
- );
- }
- }
-
- /**
- * Debugging:
- *
- * $> adb shell dumpsys jobscheduler
- *
- * Search for 'IorapdJobServiceProxy'.
- *
- * JOB #1000/283673059: 6e54ed android/com.google.android.startop.iorap.IorapForwardingService$IorapdJobServiceProxy
- * ^ ^ ^
- * (uid, job id) ComponentName(package/class)
- *
- * Forcing the job to be run, ignoring constraints:
- *
- * $> adb shell cmd jobscheduler run -f android 283673059
- * ^ ^
- * package job_id
- *
- * ------------------------------------------------------------
- *
- * This class is instantiated newly by the JobService every time
- * it wants to run a new job.
- *
- * We need to forward invocations to the current running instance of
- * IorapForwardingService#IorapdJobService.
- *
- * Visibility: Must be accessible from android.app.AppComponentFactory
- */
- public static class IorapdJobServiceProxy extends JobService {
-
- public IorapdJobServiceProxy() {
- getActualIorapdJobService().bindProxy(this);
- }
-
-
- @NonNull
- private IorapdJobService getActualIorapdJobService() {
- // Can't ever be null, because the guarantee is that the
- // IorapForwardingService is always running.
- // We are in the same process as Job Service.
- return sSelfService.mJobService;
- }
-
- // Called by system to start the job.
- @Override
- public boolean onStartJob(JobParameters params) {
- return getActualIorapdJobService().onStartJob(params);
- }
-
- // Called by system to prematurely stop the job.
- @Override
- public boolean onStopJob(JobParameters params) {
- return getActualIorapdJobService().onStopJob(params);
- }
- }
-
- private class IorapdJobService extends JobService {
- private final ComponentName IORAPD_COMPONENT_NAME;
-
- private final Object mLock = new Object();
- // Jobs currently running remotely on iorapd.
- // They were started by the JobScheduler and need to be finished.
- private final HashMap<RequestId, JobParameters> mRunningJobs = new HashMap<>();
-
- private final JobInfo IORAPD_JOB_INFO;
-
- private volatile IorapdJobServiceProxy mProxy;
-
- public void bindProxy(IorapdJobServiceProxy proxy) {
- mProxy = proxy;
- }
-
- // Create a new job service which immediately schedules a 24-hour idle maintenance mode
- // background job to execute.
- public IorapdJobService(Context context) {
- if (DEBUG) {
- Log.v(TAG, "IorapdJobService (Context=" + context.toString() + ")");
- }
-
- // Schedule the proxy class to be instantiated by the JobScheduler
- // when it is time to invoke background jobs for IorapForwardingService.
-
-
- // This also needs a BIND_JOB_SERVICE permission in
- // frameworks/base/core/res/AndroidManifest.xml
- IORAPD_COMPONENT_NAME = new ComponentName(context, IorapdJobServiceProxy.class);
-
- JobInfo.Builder builder = new JobInfo.Builder(JOB_ID_IORAPD, IORAPD_COMPONENT_NAME);
- builder.setPeriodic(JOB_INTERVAL_MS);
-
- builder.setRequiresCharging(true);
- builder.setRequiresDeviceIdle(true);
-
- builder.setRequiresStorageNotLow(true);
-
- IORAPD_JOB_INFO = builder.build();
-
- JobScheduler js = context.getSystemService(JobScheduler.class);
- js.schedule(IORAPD_JOB_INFO);
- Log.d(TAG,
- "BgJob Scheduled (jobId=" + JOB_ID_IORAPD
- + ", interval: " + JOB_INTERVAL_MS + "ms)");
- }
-
- // Called by system to start the job.
- @Override
- public boolean onStartJob(JobParameters params) {
- // Tell iorapd to start a background job.
- Log.d(TAG, "Starting background job: " + params.toString());
-
- mAbortIdleCompilation.set(false);
- // PackageManagerService starts before IORap service.
- PackageManagerService pm = (PackageManagerService)ServiceManager.getService("package");
- List<String> pkgs = pm.getAllPackages();
- runIdleCompilationAsync(params, pkgs);
- return true;
- }
-
- private void runIdleCompilationAsync(final JobParameters params, final List<String> pkgs) {
- new Thread("IORap_IdleCompilation") {
- @Override
- public void run() {
- for (int i = 0; i < pkgs.size(); i++) {
- String pkg = pkgs.get(i);
- if (mAbortIdleCompilation.get()) {
- Log.i(TAG, "The idle compilation is aborted");
- return;
- }
-
- // We wait until that job's sequence ID returns to us with 'Completed',
- RequestId request;
- synchronized (mLock) {
- // TODO: would be cleaner if we got the request from the
- // 'invokeRemote' function. Better yet, consider
- // a Pair<RequestId, Future<TaskResult>> or similar.
- request = RequestId.nextValueForSequence();
- mRunningJobs.put(request, params);
- }
-
- Log.i(TAG, String.format("IORap compile package: %s, [%d/%d]",
- pkg, i + 1, pkgs.size()));
- boolean shouldUpdateVersions = (i == 0);
- if (!invokeRemote(mIorapRemote, (IIorap remote) ->
- remote.onJobScheduledEvent(request,
- JobScheduledEvent.createIdleMaintenance(
- JobScheduledEvent.TYPE_START_JOB,
- params,
- pkg,
- shouldUpdateVersions)))) {
- synchronized (mLock) {
- mRunningJobs.remove(request); // Avoid memory leaks.
- }
- }
-
- // Wait until the job is complete and removed from the running jobs.
- retryWithTimeout(TIMEOUT, () -> {
- synchronized (mLock) {
- return !mRunningJobs.containsKey(request);
- }
- });
- }
-
- // Finish the job after all packages are compiled.
- if (mProxy != null) {
- mProxy.jobFinished(params, /*reschedule*/false);
- }
- }
- }.start();
- }
-
- /** Retry until timeout. */
- private boolean retryWithTimeout(final Duration timeout, BooleanSupplier supplier) {
- long totalSleepTimeMs = 0L;
- long sleepIntervalMs = 10L;
- while (true) {
- if (supplier.getAsBoolean()) {
- return true;
- }
- try {
- TimeUnit.MILLISECONDS.sleep(sleepIntervalMs);
- } catch (InterruptedException e) {
- Log.e(TAG, e.getMessage());
- return false;
- }
-
- totalSleepTimeMs += sleepIntervalMs;
- if (totalSleepTimeMs > timeout.toMillis()) {
- return false;
- }
- }
- }
-
- // Called by system to prematurely stop the job.
- @Override
- public boolean onStopJob(JobParameters params) {
- // As this is unexpected behavior, print a warning.
- Log.w(TAG, "onStopJob(params=" + params.toString() + ")");
- mAbortIdleCompilation.set(true);
-
- // Yes, retry the job at a later time no matter what.
- return true;
- }
-
- // Listen to *all* task completes for all requests.
- // The majority of these might be unrelated to background jobs.
- public void onIorapdTaskCompleted(RequestId requestId) {
- JobParameters jobParameters;
- synchronized (mLock) {
- jobParameters = mRunningJobs.remove(requestId);
- }
-
- // Typical case: This was a task callback unrelated to our jobs.
- if (jobParameters == null) {
- return;
- }
-
- if (DEBUG) {
- Log.v(TAG,
- String.format("IorapdJobService#onIorapdTaskCompleted(%s), found params=%s",
- requestId, jobParameters));
- }
-
- Log.d(TAG, "Finished background job: " + jobParameters.toString());
- }
-
- public void onIorapdDisconnected() {
- synchronized (mLock) {
- mRunningJobs.clear();
- }
-
- if (DEBUG) {
- Log.v(TAG, String.format("IorapdJobService#onIorapdDisconnected"));
- }
-
- // TODO: should we try to resubmit all incomplete jobs after it's reconnected?
- }
- }
-
- private class RemoteTaskListener extends ITaskListener.Stub {
- @Override
- public void onProgress(RequestId requestId, TaskResult result) throws RemoteException {
- if (DEBUG) {
- Log.v(TAG,
- String.format("RemoteTaskListener#onProgress(%s, %s)", requestId, result));
- }
-
- // TODO: implement rest.
- }
-
- @Override
- public void onComplete(RequestId requestId, TaskResult result) throws RemoteException {
- if (DEBUG) {
- Log.v(TAG,
- String.format("RemoteTaskListener#onComplete(%s, %s)", requestId, result));
- }
-
- if (mJobService != null) {
- mJobService.onIorapdTaskCompleted(requestId);
- }
-
- // TODO: implement rest.
- }
- }
-
- /** Allow passing lambdas to #invokeRemote */
- private interface RemoteRunnable {
- // TODO: run(RequestId) ?
- void run(IIorap iorap) throws RemoteException;
- }
-
- // Always pass in the iorap directly here to avoid data race.
- private static boolean invokeRemote(IIorap iorap, RemoteRunnable r) {
- if (iorap == null) {
- Log.w(TAG, "IIorap went to null in this thread, drop invokeRemote.");
- return false;
- }
- try {
- r.run(iorap);
- return true;
- } catch (RemoteException e) {
- // This could be a logic error (remote side returning error), which we need to fix.
- //
- // This could also be a DeadObjectException in which case its probably just iorapd
- // being manually restarted.
- //
- // Don't make any assumption, since DeadObjectException could also mean iorapd crashed
- // unexpectedly.
- //
- // DeadObjectExceptions are recovered from using DeathRecipient and #linkToDeath.
- handleRemoteError(e);
- return false;
- }
- }
-
- private static void handleRemoteError(Throwable t) {
- if (WTF_CRASH) {
- // In development modes, we just want to crash.
- throw new AssertionError("unexpected remote error", t);
- } else {
- // Log to wtf which gets sent to dropbox, and in system_server this does not crash.
- Log.wtf(TAG, t);
- }
- }
-
- // Encode A-Z bitstring into bits. Every character is bits.
- // Characters outside of the range [a,z] are considered out of range.
- //
- // The least significant bits hold the last character.
- // First 2 bits are left as 0.
- private static int encodeEnglishAlphabetStringIntoInt(String name) {
- int value = 0;
-
- final int CHARS_PER_INT = 6;
- final int BITS_PER_CHAR = 5;
- // Note: 2 top bits are unused, this also means our values are non-negative.
- final char CHAR_LOWER = 'a';
- final char CHAR_UPPER = 'z';
-
- if (name.length() > CHARS_PER_INT) {
- throw new IllegalArgumentException(
- "String too long. Cannot encode more than 6 chars: " + name);
- }
-
- for (int i = 0; i < name.length(); ++i) {
- char c = name.charAt(i);
-
- if (c < CHAR_LOWER || c > CHAR_UPPER) {
- throw new IllegalArgumentException("String has out-of-range [a-z] chars: " + name);
- }
-
- // Avoid sign extension during promotion.
- int cur_value = (c & 0xFFFF) - (CHAR_LOWER & 0xFFFF);
- if (cur_value >= (1 << BITS_PER_CHAR)) {
- throw new AssertionError("wtf? i=" + i + ", name=" + name);
- }
-
- value = value << BITS_PER_CHAR;
- value = value | cur_value;
- }
-
- return value;
- }
-}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/JobScheduledEvent.java b/startop/iorap/src/com/google/android/startop/iorap/JobScheduledEvent.java
deleted file mode 100644
index b91dd71fd28c..000000000000
--- a/startop/iorap/src/com/google/android/startop/iorap/JobScheduledEvent.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.startop.iorap;
-
-import android.app.job.JobParameters;
-import android.annotation.NonNull;
-import android.os.Parcelable;
-import android.os.Parcel;
-
-import android.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Forward JobService events to iorapd. <br /><br />
- *
- * iorapd sometimes need to use background jobs. Forwarding these events to iorapd
- * notifies iorapd when it is an opportune time to execute these background jobs.
- *
- * @hide
- */
-public class JobScheduledEvent implements Parcelable {
-
- /** JobService#onJobStarted */
- public static final int TYPE_START_JOB = 0;
- /** JobService#onJobStopped */
- public static final int TYPE_STOP_JOB = 1;
- private static final int TYPE_MAX = 1;
-
- /** @hide */
- @IntDef(flag = true, prefix = { "TYPE_" }, value = {
- TYPE_START_JOB,
- TYPE_STOP_JOB,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Type {}
-
- @Type public final int type;
-
- /** @see JobParameters#getJobId() */
- public final int jobId;
-
- public final String packageName;
-
- public final boolean shouldUpdateVersions;
-
- /** Device is 'idle' and it's charging (plugged in). */
- public static final int SORT_IDLE_MAINTENANCE = 0;
- private static final int SORT_MAX = 0;
-
- /** @hide */
- @IntDef(flag = true, prefix = { "SORT_" }, value = {
- SORT_IDLE_MAINTENANCE,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Sort {}
-
- /**
- * Roughly corresponds to the {@code extras} fields in a JobParameters.
- */
- @Sort public final int sort;
-
- /**
- * Creates a {@link #SORT_IDLE_MAINTENANCE} event from the type and job parameters.
- *
- * Only the job ID is retained from {@code jobParams}, all other param info is dropped.
- */
- @NonNull
- public static JobScheduledEvent createIdleMaintenance(
- @Type int type, JobParameters jobParams, String packageName, boolean shouldUpdateVersions) {
- return new JobScheduledEvent(
- type, jobParams.getJobId(), SORT_IDLE_MAINTENANCE, packageName, shouldUpdateVersions);
- }
-
- private JobScheduledEvent(@Type int type,
- int jobId,
- @Sort int sort,
- String packageName,
- boolean shouldUpdateVersions) {
- this.type = type;
- this.jobId = jobId;
- this.sort = sort;
- this.packageName = packageName;
- this.shouldUpdateVersions = shouldUpdateVersions;
-
- checkConstructorArguments();
- }
-
- private void checkConstructorArguments() {
- CheckHelpers.checkTypeInRange(type, TYPE_MAX);
- // No check for 'jobId': any int is valid.
- CheckHelpers.checkTypeInRange(sort, SORT_MAX);
- }
-
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- } else if (other instanceof JobScheduledEvent) {
- return equals((JobScheduledEvent) other);
- }
- return false;
- }
-
- private boolean equals(JobScheduledEvent other) {
- return type == other.type &&
- jobId == other.jobId &&
- sort == other.sort &&
- packageName.equals(other.packageName) &&
- shouldUpdateVersions == other.shouldUpdateVersions;
- }
-
- @Override
- public String toString() {
- return String.format(
- "{type: %d, jobId: %d, sort: %d, packageName: %s, shouldUpdateVersions %b}",
- type, jobId, sort, packageName, shouldUpdateVersions);
- }
-
- //<editor-fold desc="Binder boilerplate">
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(type);
- out.writeInt(jobId);
- out.writeInt(sort);
- out.writeString(packageName);
- out.writeBoolean(shouldUpdateVersions);
-
- // We do not parcel the entire JobParameters here because there is no C++ equivalent
- // of that class [which the iorapd side of the binder interface requires].
- }
-
- private JobScheduledEvent(Parcel in) {
- this.type = in.readInt();
- this.jobId = in.readInt();
- this.sort = in.readInt();
- this.packageName = in.readString();
- this.shouldUpdateVersions = in.readBoolean();
-
- checkConstructorArguments();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Parcelable.Creator<JobScheduledEvent> CREATOR
- = new Parcelable.Creator<JobScheduledEvent>() {
- public JobScheduledEvent createFromParcel(Parcel in) {
- return new JobScheduledEvent(in);
- }
-
- public JobScheduledEvent[] newArray(int size) {
- return new JobScheduledEvent[size];
- }
- };
- //</editor-fold>
-}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/PackageEvent.java b/startop/iorap/src/com/google/android/startop/iorap/PackageEvent.java
deleted file mode 100644
index aa4eea716363..000000000000
--- a/startop/iorap/src/com/google/android/startop/iorap/PackageEvent.java
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.startop.iorap;
-
-import android.annotation.NonNull;
-import android.os.Parcelable;
-import android.os.Parcel;
-import android.net.Uri;
-
-import android.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Objects;
-
-/**
- * Forward package manager events to iorapd. <br /><br />
- *
- * Knowing when packages are modified by the system are a useful tidbit to help with performance:
- * for example when a package is replaced, it could be a hint used to invalidate any collected
- * io profiles used for prefetching or pinning.
- *
- * @hide
- */
-public class PackageEvent implements Parcelable {
-
- /** @see android.content.Intent#ACTION_PACKAGE_REPLACED */
- public static final int TYPE_REPLACED = 0;
- private static final int TYPE_MAX = 0;
-
- /** @hide */
- @IntDef(flag = true, prefix = { "TYPE_" }, value = {
- TYPE_REPLACED,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Type {}
-
- @Type public final int type;
-
- /** The path that a package is installed in, for example {@code /data/app/.../base.apk}. */
- public final Uri packageUri;
- /** The name of the package, for example {@code com.android.calculator}. */
- public final String packageName;
-
- @NonNull
- public static PackageEvent createReplaced(Uri packageUri, String packageName) {
- return new PackageEvent(TYPE_REPLACED, packageUri, packageName);
- }
-
- private PackageEvent(@Type int type, Uri packageUri, String packageName) {
- this.type = type;
- this.packageUri = packageUri;
- this.packageName = packageName;
-
- checkConstructorArguments();
- }
-
- private void checkConstructorArguments() {
- CheckHelpers.checkTypeInRange(type, TYPE_MAX);
- Objects.requireNonNull(packageUri, "packageUri");
- Objects.requireNonNull(packageName, "packageName");
- }
-
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- } else if (other instanceof PackageEvent) {
- return equals((PackageEvent) other);
- }
- return false;
- }
-
- private boolean equals(PackageEvent other) {
- return type == other.type &&
- Objects.equals(packageUri, other.packageUri) &&
- Objects.equals(packageName, other.packageName);
- }
-
- @Override
- public String toString() {
- return String.format("{packageUri: %s, packageName: %s}", packageUri, packageName);
- }
-
- //<editor-fold desc="Binder boilerplate">
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(type);
- packageUri.writeToParcel(out, flags);
- out.writeString(packageName);
- }
-
- private PackageEvent(Parcel in) {
- this.type = in.readInt();
- this.packageUri = Uri.CREATOR.createFromParcel(in);
- this.packageName = in.readString();
-
- checkConstructorArguments();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Parcelable.Creator<PackageEvent> CREATOR
- = new Parcelable.Creator<PackageEvent>() {
- public PackageEvent createFromParcel(Parcel in) {
- return new PackageEvent(in);
- }
-
- public PackageEvent[] newArray(int size) {
- return new PackageEvent[size];
- }
- };
- //</editor-fold>
-}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/RequestId.java b/startop/iorap/src/com/google/android/startop/iorap/RequestId.java
deleted file mode 100644
index 503e1c633581..000000000000
--- a/startop/iorap/src/com/google/android/startop/iorap/RequestId.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.startop.iorap;
-
-import android.os.Parcelable;
-import android.os.Parcel;
-
-import android.annotation.NonNull;
-
-/**
- * Uniquely identify an {@link com.google.android.startop.iorap.IIorap} method invocation,
- * used for asynchronous callbacks by the server. <br /><br />
- *
- * As all system server binder calls must be {@code oneway}, this means all invocations
- * into {@link com.google.android.startop.iorap.IIorap} are non-blocking. The request ID
- * exists to associate all calls with their respective callbacks in
- * {@link com.google.android.startop.iorap.ITaskListener}.
- *
- * @see com.google.android.startop.iorap.IIorap
- *
- * @hide
- */
-public class RequestId implements Parcelable {
-
- public final long requestId;
-
- private static Object mLock = new Object();
- private static long mNextRequestId = 0;
-
- /**
- * Create a monotonically increasing request ID.<br /><br />
- *
- * It is invalid to re-use the same request ID for multiple method calls on
- * {@link com.google.android.startop.iorap.IIorap}; a new request ID must be created
- * each time.
- */
- @NonNull public static RequestId nextValueForSequence() {
- long currentRequestId;
- synchronized (mLock) {
- currentRequestId = mNextRequestId;
- ++mNextRequestId;
- }
- return new RequestId(currentRequestId);
- }
-
- private RequestId(long requestId) {
- this.requestId = requestId;
-
- checkConstructorArguments();
- }
-
- private void checkConstructorArguments() {
- if (requestId < 0) {
- throw new IllegalArgumentException("request id must be non-negative");
- }
- }
-
- @Override
- public String toString() {
- return String.format("{requestId: %d}", requestId);
- }
-
- @Override
- public int hashCode() {
- return Long.hashCode(requestId);
- }
-
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- } else if (other instanceof RequestId) {
- return equals((RequestId) other);
- }
- return false;
- }
-
- private boolean equals(RequestId other) {
- return requestId == other.requestId;
- }
-
-
- //<editor-fold desc="Binder boilerplate">
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeLong(requestId);
- }
-
- private RequestId(Parcel in) {
- requestId = in.readLong();
-
- checkConstructorArguments();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Parcelable.Creator<RequestId> CREATOR
- = new Parcelable.Creator<RequestId>() {
- public RequestId createFromParcel(Parcel in) {
- return new RequestId(in);
- }
-
- public RequestId[] newArray(int size) {
- return new RequestId[size];
- }
- };
- //</editor-fold>
-}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/SystemServiceEvent.java b/startop/iorap/src/com/google/android/startop/iorap/SystemServiceEvent.java
deleted file mode 100644
index 75d47f9e3d17..000000000000
--- a/startop/iorap/src/com/google/android/startop/iorap/SystemServiceEvent.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.startop.iorap;
-
-import android.os.Parcelable;
-import android.os.Parcel;
-
-import android.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Forward system service events to iorapd.
- *
- * @see com.android.server.SystemService
- *
- * @hide
- */
-public class SystemServiceEvent implements Parcelable {
-
- /** @see com.android.server.SystemService#onBootPhase */
- public static final int TYPE_BOOT_PHASE = 0;
- /** @see com.android.server.SystemService#onStart */
- public static final int TYPE_START = 1;
- private static final int TYPE_MAX = TYPE_START;
-
- /** @hide */
- @IntDef(flag = true, prefix = { "TYPE_" }, value = {
- TYPE_BOOT_PHASE,
- TYPE_START,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Type {}
-
- @Type public final int type;
-
- // TODO: do we want to pass the exact build phase enum?
-
- public SystemServiceEvent(@Type int type) {
- this.type = type;
- checkConstructorArguments();
- }
-
- private void checkConstructorArguments() {
- CheckHelpers.checkTypeInRange(type, TYPE_MAX);
- }
-
- @Override
- public String toString() {
- return String.format("{type: %d}", type);
- }
-
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- } else if (other instanceof SystemServiceEvent) {
- return equals((SystemServiceEvent) other);
- }
- return false;
- }
-
- private boolean equals(SystemServiceEvent other) {
- return type == other.type;
- }
-
- //<editor-fold desc="Binder boilerplate">
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(type);
- }
-
- private SystemServiceEvent(Parcel in) {
- this.type = in.readInt();
- checkConstructorArguments();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Parcelable.Creator<SystemServiceEvent> CREATOR
- = new Parcelable.Creator<SystemServiceEvent>() {
- public SystemServiceEvent createFromParcel(Parcel in) {
- return new SystemServiceEvent(in);
- }
-
- public SystemServiceEvent[] newArray(int size) {
- return new SystemServiceEvent[size];
- }
- };
- //</editor-fold>
-}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/SystemServiceUserEvent.java b/startop/iorap/src/com/google/android/startop/iorap/SystemServiceUserEvent.java
deleted file mode 100644
index 2e7bafe7bdbf..000000000000
--- a/startop/iorap/src/com/google/android/startop/iorap/SystemServiceUserEvent.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.startop.iorap;
-
-import android.os.Parcelable;
-import android.os.Parcel;
-
-import android.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Forward user events to iorapd.<br /><br />
- *
- * Knowledge of the logged-in user is reserved to be used to set-up appropriate policies
- * by iorapd (e.g. to handle user default pinned applications changing).
- *
- * @see com.android.server.SystemService
- *
- * @hide
- */
-public class SystemServiceUserEvent implements Parcelable {
-
- /** @see com.android.server.SystemService#onUserStarting */
- public static final int TYPE_START_USER = 0;
- /** @see com.android.server.SystemService#onUserUnlocking */
- public static final int TYPE_UNLOCK_USER = 1;
- /** @see com.android.server.SystemService#onUserSwitching*/
- public static final int TYPE_SWITCH_USER = 2;
- /** @see com.android.server.SystemService#onUserStopping */
- public static final int TYPE_STOP_USER = 3;
- /** @see com.android.server.SystemService#onUserStopped */
- public static final int TYPE_CLEANUP_USER = 4;
- private static final int TYPE_MAX = TYPE_CLEANUP_USER;
-
- /** @hide */
- @IntDef(flag = true, prefix = { "TYPE_" }, value = {
- TYPE_START_USER,
- TYPE_UNLOCK_USER,
- TYPE_SWITCH_USER,
- TYPE_STOP_USER,
- TYPE_CLEANUP_USER,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface Type {}
-
- @Type public final int type;
- public final int userHandle;
-
- public SystemServiceUserEvent(@Type int type, int userHandle) {
- this.type = type;
- this.userHandle = userHandle;
- checkConstructorArguments();
- }
-
- private void checkConstructorArguments() {
- CheckHelpers.checkTypeInRange(type, TYPE_MAX);
- if (userHandle < 0) {
- throw new IllegalArgumentException("userHandle must be non-negative");
- }
- }
-
- @Override
- public String toString() {
- return String.format("{type: %d, userHandle: %d}", type, userHandle);
- }
-
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- } else if (other instanceof SystemServiceUserEvent) {
- return equals((SystemServiceUserEvent) other);
- }
- return false;
- }
-
- private boolean equals(SystemServiceUserEvent other) {
- return type == other.type &&
- userHandle == other.userHandle;
- }
-
- //<editor-fold desc="Binder boilerplate">
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(type);
- out.writeInt(userHandle);
- }
-
- private SystemServiceUserEvent(Parcel in) {
- this.type = in.readInt();
- this.userHandle = in.readInt();
- checkConstructorArguments();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Parcelable.Creator<SystemServiceUserEvent> CREATOR
- = new Parcelable.Creator<SystemServiceUserEvent>() {
- public SystemServiceUserEvent createFromParcel(Parcel in) {
- return new SystemServiceUserEvent(in);
- }
-
- public SystemServiceUserEvent[] newArray(int size) {
- return new SystemServiceUserEvent[size];
- }
- };
- //</editor-fold>
-}
diff --git a/startop/iorap/src/com/google/android/startop/iorap/TaskResult.java b/startop/iorap/src/com/google/android/startop/iorap/TaskResult.java
deleted file mode 100644
index b5fd6d8d1c45..000000000000
--- a/startop/iorap/src/com/google/android/startop/iorap/TaskResult.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.android.startop.iorap;
-
-import android.os.Parcelable;
-import android.os.Parcel;
-
-import android.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Result data accompanying a request for {@link com.google.android.startop.iorap.ITaskListener}
- * callbacks.<br /><br />
- *
- * Following {@link com.google.android.startop.iorap.IIorap} method invocation,
- * iorapd will issue in-order callbacks for that corresponding {@link RequestId}.<br /><br />
- *
- * State transitions are as follows: <br /><br />
- *
- * <pre>
- * ┌─────────────────────────────┐
- * │ ▼
- * ┌───────┐ ┌─────────┐ ╔═══════════╗
- * ──▶ │ BEGAN │ ──▶ │ ONGOING │ ──▶ ║ COMPLETED ║
- * └───────┘ └─────────┘ ╚═══════════╝
- * │ │
- * │ │
- * ▼ │
- * ╔═══════╗ │
- * ──▶ ║ ERROR ║ ◀─────┘
- * ╚═══════╝
- *
- * </pre> <!-- system/iorap/docs/binder/TaskResult.dot -->
- *
- * @hide
- */
-public class TaskResult implements Parcelable {
-
- public static final int STATE_BEGAN = 0;
- public static final int STATE_ONGOING = 1;
- public static final int STATE_COMPLETED = 2;
- public static final int STATE_ERROR = 3;
- private static final int STATE_MAX = STATE_ERROR;
-
- /** @hide */
- @IntDef(flag = true, prefix = { "STATE_" }, value = {
- STATE_BEGAN,
- STATE_ONGOING,
- STATE_COMPLETED,
- STATE_ERROR,
- })
- @Retention(RetentionPolicy.SOURCE)
- public @interface State {}
-
- @State public final int state;
-
- @Override
- public String toString() {
- return String.format("{state: %d}", state);
- }
-
- @Override
- public boolean equals(Object other) {
- if (this == other) {
- return true;
- } else if (other instanceof TaskResult) {
- return equals((TaskResult) other);
- }
- return false;
- }
-
- private boolean equals(TaskResult other) {
- return state == other.state;
- }
-
- public TaskResult(@State int state) {
- this.state = state;
-
- checkConstructorArguments();
- }
-
- private void checkConstructorArguments() {
- CheckHelpers.checkStateInRange(state, STATE_MAX);
- }
-
- //<editor-fold desc="Binder boilerplate">
- @Override
- public void writeToParcel(Parcel out, int flags) {
- out.writeInt(state);
- }
-
- private TaskResult(Parcel in) {
- state = in.readInt();
-
- checkConstructorArguments();
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- public static final Parcelable.Creator<TaskResult> CREATOR
- = new Parcelable.Creator<TaskResult>() {
- public TaskResult createFromParcel(Parcel in) {
- return new TaskResult(in);
- }
-
- public TaskResult[] newArray(int size) {
- return new TaskResult[size];
- }
- };
- //</editor-fold>
-}
diff --git a/startop/iorap/stress/Android.bp b/startop/iorap/stress/Android.bp
deleted file mode 100644
index 6e8725d091fb..000000000000
--- a/startop/iorap/stress/Android.bp
+++ /dev/null
@@ -1,42 +0,0 @@
-//
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_base_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["frameworks_base_license"],
-}
-
-cc_binary {
- name: "iorap.stress.memory",
- srcs: ["main_memory.cc"],
-
- cflags: [
- "-Wall",
- "-Wextra",
- "-Werror",
- "-Wno-unused-parameter"
- ],
-
- shared_libs: [
- "libbase"
- ],
-
- host_supported: true,
-}
diff --git a/startop/iorap/stress/main_memory.cc b/startop/iorap/stress/main_memory.cc
deleted file mode 100644
index 1f268619e4d9..000000000000
--- a/startop/iorap/stress/main_memory.cc
+++ /dev/null
@@ -1,126 +0,0 @@
-//
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#include <chrono>
-#include <fstream>
-#include <iostream>
-#include <random>
-#include <string>
-
-#include <string.h>
-#include <stdlib.h>
-#include <sys/mman.h>
-
-#include <android-base/parseint.h>
-
-static constexpr size_t kBytesPerMb = 1048576;
-const size_t kMemoryAllocationSize = 2 * 1024 * kBytesPerMb;
-
-#define USE_MLOCKALL 0
-
-std::string GetProcessStatus(const char* key) {
- // Build search pattern of key and separator.
- std::string pattern(key);
- pattern.push_back(':');
-
- // Search for status lines starting with pattern.
- std::ifstream fs("/proc/self/status");
- std::string line;
- while (std::getline(fs, line)) {
- if (strncmp(pattern.c_str(), line.c_str(), pattern.size()) == 0) {
- // Skip whitespace in matching line (if any).
- size_t pos = line.find_first_not_of(" \t", pattern.size());
- if (pos == std::string::npos) {
- break;
- }
- return std::string(line, pos);
- }
- }
- return "<unknown>";
-}
-
-int main(int argc, char** argv) {
- size_t allocationSize = 0;
- if (argc >= 2) {
- if (!android::base::ParseUint(argv[1], /*out*/&allocationSize)) {
- std::cerr << "Failed to parse the allocation size (must be 0,MAX_SIZE_T)" << std::endl;
- return 1;
- }
- } else {
- allocationSize = kMemoryAllocationSize;
- }
-
- void* mem = malloc(allocationSize);
- if (mem == nullptr) {
- std::cerr << "Malloc failed" << std::endl;
- return 1;
- }
-
- volatile int* imem = static_cast<int *>(mem); // don't optimize out memory usage
-
- size_t imemCount = allocationSize / sizeof(int);
-
- std::cout << "Allocated " << allocationSize << " bytes" << std::endl;
-
- auto seed = std::chrono::high_resolution_clock::now().time_since_epoch().count();
- std::mt19937 mt_rand(seed);
-
- size_t randPrintCount = 10;
-
- // Write random numbers:
- // * Ensures each page is resident
- // * Avoids zeroed out pages (zRAM)
- // * Avoids same-page merging
- for (size_t i = 0; i < imemCount; ++i) {
- imem[i] = mt_rand();
-
- if (i < randPrintCount) {
- std::cout << "Generated random value: " << imem[i] << std::endl;
- }
- }
-
-#if USE_MLOCKALL
- /*
- * Lock all pages from the address space of this process.
- */
- if (mlockall(MCL_CURRENT | MCL_FUTURE) != 0) {
- std::cerr << "Mlockall failed" << std::endl;
- return 1;
- }
-#else
- // Use mlock because of the predictable VmLck size.
- // Using mlockall tends to bring in anywhere from 2-2.5GB depending on the device.
- if (mlock(mem, allocationSize) != 0) {
- std::cerr << "Mlock failed" << std::endl;
- return 1;
- }
-#endif
-
- // Validate memory is actually resident and locked with:
- // $> cat /proc/$(pidof iorap.stress.memory)/status | grep VmLck
- std::cout << "Locked memory (VmLck) = " << GetProcessStatus("VmLck") << std::endl;
-
- std::cout << "Press any key to terminate" << std::endl;
- int any_input;
- std::cin >> any_input;
-
- std::cout << "Terminating..." << std::endl;
-
- munlockall();
- free(mem);
-
- return 0;
-}
diff --git a/startop/iorap/tests/Android.bp b/startop/iorap/tests/Android.bp
deleted file mode 100644
index ad3d001ad7d4..000000000000
--- a/startop/iorap/tests/Android.bp
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (C) 2018 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// TODO: once b/80095087 is fixed, rewrite this back to android_test
-package {
- // See: http://go/android-license-faq
- // A large-scale-change added 'default_applicable_licenses' to import
- // all of the 'license_kinds' from "frameworks_base_license"
- // to get the below license kinds:
- // SPDX-license-identifier-Apache-2.0
- default_applicable_licenses: ["frameworks_base_license"],
-}
-
-java_library {
- name: "libiorap-java-test-lib",
- srcs: ["src/**/*.kt"],
- static_libs: [
- // Non-test dependencies
- // library under test
- "services.startop.iorap",
- // need the system_server code to be on the classpath,
- "services.core",
- // Test Dependencies
- // test android dependencies
- "platform-test-annotations",
- "androidx.test.rules",
- // test framework dependencies
- "mockito-target-inline-minus-junit4",
- // "mockito-target-minus-junit4",
- // Mockito also requires JNI (see Android.mk)
- // and android:debuggable=true (see AndroidManifest.xml)
- "truth-prebuilt",
- ],
- // sdk_version: "current",
- // certificate: "platform",
- libs: [
- "android.test.base",
- "android.test.runner",
- ],
- // test_suites: ["device-tests"],
-}
-
-android_test {
- name: "libiorap-java-tests",
- dxflags: ["--multi-dex"],
- test_suites: ["device-tests"],
- static_libs: ["libiorap-java-test-lib"],
- compile_multilib: "both",
- jni_libs: [
- "libdexmakerjvmtiagent",
- "libstaticjvmtiagent",
- "libmultiplejvmtiagentsinterferenceagent",
- ],
- libs: [
- "android.test.base",
- "android.test.runner",
- ],
- // Use private APIs
- certificate: "platform",
- platform_apis: true,
-}
diff --git a/startop/iorap/tests/AndroidManifest.xml b/startop/iorap/tests/AndroidManifest.xml
deleted file mode 100644
index b967e7207a3f..000000000000
--- a/startop/iorap/tests/AndroidManifest.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<!--suppress AndroidUnknownAttribute -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.google.android.startop.iorap.tests"
- android:sharedUserId="com.google.android.startop.iorap.tests"
- android:versionCode="1"
- android:versionName="1.0" >
-
- <!--suppress AndroidDomInspection -->
- <instrumentation
- android:name="androidx.test.runner.AndroidJUnitRunner"
- android:targetPackage="com.google.android.startop.iorap.tests" />
-
- <!--
- 'debuggable=true' is required to properly load mockito jvmti dependencies,
- otherwise it gives the following error at runtime:
-
- Openjdkjvmti plugin was loaded on a non-debuggable Runtime.
- Plugin was loaded too late to change runtime state to DEBUGGABLE. -->
- <application android:debuggable="true">
- <uses-library android:name="android.test.runner" />
- </application>
-</manifest>
diff --git a/startop/iorap/tests/AndroidTest.xml b/startop/iorap/tests/AndroidTest.xml
deleted file mode 100644
index 6102c44e61bf..000000000000
--- a/startop/iorap/tests/AndroidTest.xml
+++ /dev/null
@@ -1,66 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-
-<configuration description="Runs libiorap-java-tests.">
- <option name="test-suite-tag" value="apct" />
- <option name="test-suite-tag" value="apct-instrumentation" />
- <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
- <option name="cleanup-apks" value="true" />
- <option name="test-file-name" value="libiorap-java-tests.apk" />
- </target_preparer>
-
- <!--
- Our IIorapIntegrationTest.kt requires setlinux to be disabled:
- it connects to the iorapd binder service but this requires selinux permissions:
-
- avc: denied { find } for service=iorapd pid=2738 uid=10050
- scontext=u:r:platform_app:s0:c512,c768 tcontext=u:object_r:iorapd_service:s0
- tclass=service_manager permissive=0
- -->
- <target_preparer class="com.android.tradefed.targetprep.DisableSELinuxTargetPreparer">
- </target_preparer>
-
- <!-- do not use DeviceSetup#set-property because it reboots the device b/136200738.
- furthermore the changes in /data/local.prop don't actually seem to get picked up.
- -->
- <target_preparer
- class="com.android.tradefed.targetprep.DeviceSetup">
- <!-- we need this magic flag, otherwise it always reboots and breaks the selinux -->
- <option name="force-skip-system-props" value="true" />
-
- <!-- Crash instead of using Log.wtf within the system_server iorap code. -->
- <option name="run-command" value="setprop iorapd.forwarding_service.wtf_crash true" />
- <!-- IIorapd has fake behavior: it doesn't do anything but reply with 'DONE' status -->
- <option name="run-command" value="setprop iorapd.binder.fake true" />
-
- <!-- iorapd does not pick up the above changes until we restart it -->
- <option name="run-command" value="stop iorapd" />
- <option name="run-command" value="start iorapd" />
- <!-- give it some time to restart the service; otherwise the first unit test might fail -->
- <option name="run-command" value="sleep 1" />
- </target_preparer>
-
- <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
- <option name="package" value="com.google.android.startop.iorap.tests" />
- <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
- </test>
-
- <!-- using DeviceSetup again does not work. we simply leave the device in a semi-bad
- state. there is no way to clean this up as far as I know.
- -->
-
-</configuration>
-
diff --git a/startop/iorap/tests/src/com/google/android/startop/iorap/AppLaunchEventTest.kt b/startop/iorap/tests/src/com/google/android/startop/iorap/AppLaunchEventTest.kt
deleted file mode 100644
index 51e407d4cbff..000000000000
--- a/startop/iorap/tests/src/com/google/android/startop/iorap/AppLaunchEventTest.kt
+++ /dev/null
@@ -1,181 +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.google.android.startop.iorap
-
-import android.content.Intent;
-import android.net.Uri
-import android.os.Parcel
-import android.os.Parcelable
-import androidx.test.filters.SmallTest
-import com.google.android.startop.iorap.AppLaunchEvent;
-import com.google.android.startop.iorap.AppLaunchEvent.ActivityLaunched
-import com.google.android.startop.iorap.AppLaunchEvent.ActivityLaunchCancelled
-import com.google.android.startop.iorap.AppLaunchEvent.ActivityLaunchFinished
-import com.google.android.startop.iorap.AppLaunchEvent.IntentStarted;
-import com.google.android.startop.iorap.AppLaunchEvent.IntentFailed;
-import com.google.android.startop.iorap.AppLaunchEvent.ReportFullyDrawn
-import com.google.common.truth.Truth.assertThat
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.junit.runners.Parameterized
-
-
-/**
- * Basic unit tests to test all of the [AppLaunchEvent]s in [com.google.android.startop.iorap].
- */
-@SmallTest
-class AppLaunchEventTest {
- /**
- * Test for IntentStarted.
- */
- @Test
- fun testIntentStarted() {
- var intent = Intent()
- val valid = IntentStarted(/* sequenceId= */2L, intent, /* timestampNs= */ 1L)
- val copy = IntentStarted(/* sequenceId= */2L, intent, /* timestampNs= */ 1L)
- val noneCopy1 = IntentStarted(/* sequenceId= */1L, intent, /* timestampNs= */ 1L)
- val noneCopy2 = IntentStarted(/* sequenceId= */2L, intent, /* timestampNs= */ 2L)
- val noneCopy3 = IntentStarted(/* sequenceId= */2L, Intent(), /* timestampNs= */ 1L)
-
- // equals(Object other)
- assertThat(valid).isEqualTo(copy)
- assertThat(valid).isNotEqualTo(noneCopy1)
- assertThat(valid).isNotEqualTo(noneCopy2)
- assertThat(valid).isNotEqualTo(noneCopy3)
-
- // test toString()
- val result = valid.toString()
- assertThat(result).isEqualTo("IntentStarted{sequenceId=2, intent=Intent { } , timestampNs=1}")
- }
-
- /**
- * Test for IntentFailed.
- */
- @Test
- fun testIntentFailed() {
- val valid = IntentFailed(/* sequenceId= */2L)
- val copy = IntentFailed(/* sequenceId= */2L)
- val noneCopy = IntentFailed(/* sequenceId= */1L)
-
- // equals(Object other)
- assertThat(valid).isEqualTo(copy)
- assertThat(valid).isNotEqualTo(noneCopy)
-
- // test toString()
- val result = valid.toString()
- assertThat(result).isEqualTo("IntentFailed{sequenceId=2}")
- }
-
- /**
- * Test for ActivityLaunched.
- */
- @Test
- fun testActivityLaunched() {
- //var activityRecord =
- val valid = ActivityLaunched(/* sequenceId= */2L, "test".toByteArray(),
- /* temperature= */ 0)
- val copy = ActivityLaunched(/* sequenceId= */2L, "test".toByteArray(),
- /* temperature= */ 0)
- val noneCopy1 = ActivityLaunched(/* sequenceId= */1L, "test".toByteArray(),
- /* temperature= */ 0)
- val noneCopy2 = ActivityLaunched(/* sequenceId= */1L, "test".toByteArray(),
- /* temperature= */ 1)
- val noneCopy3 = ActivityLaunched(/* sequenceId= */1L, "test1".toByteArray(),
- /* temperature= */ 0)
-
- // equals(Object other)
- assertThat(valid).isEqualTo(copy)
- assertThat(valid).isNotEqualTo(noneCopy1)
- assertThat(valid).isNotEqualTo(noneCopy2)
- assertThat(valid).isNotEqualTo(noneCopy3)
-
- // test toString()
- val result = valid.toString()
- assertThat(result).isEqualTo("ActivityLaunched{sequenceId=2, test, temperature=0}")
- }
-
-
- /**
- * Test for ActivityLaunchFinished.
- */
- @Test
- fun testActivityLaunchFinished() {
- val valid = ActivityLaunchFinished(/* sequenceId= */2L, "test".toByteArray(),
- /* timestampNs= */ 1L)
- val copy = ActivityLaunchFinished(/* sequenceId= */2L, "test".toByteArray(),
- /* timestampNs= */ 1L)
- val noneCopy1 = ActivityLaunchFinished(/* sequenceId= */1L, "test".toByteArray(),
- /* timestampNs= */ 1L)
- val noneCopy2 = ActivityLaunchFinished(/* sequenceId= */1L, "test".toByteArray(),
- /* timestampNs= */ 2L)
- val noneCopy3 = ActivityLaunchFinished(/* sequenceId= */2L, "test1".toByteArray(),
- /* timestampNs= */ 1L)
-
- // equals(Object other)
- assertThat(valid).isEqualTo(copy)
- assertThat(valid).isNotEqualTo(noneCopy1)
- assertThat(valid).isNotEqualTo(noneCopy2)
- assertThat(valid).isNotEqualTo(noneCopy3)
-
- // test toString()
- val result = valid.toString()
- assertThat(result).isEqualTo("ActivityLaunchFinished{sequenceId=2, test, timestampNs=1}")
- }
-
- /**
- * Test for ActivityLaunchCancelled.
- */
- @Test
- fun testActivityLaunchCancelled() {
- val valid = ActivityLaunchCancelled(/* sequenceId= */2L, "test".toByteArray())
- val copy = ActivityLaunchCancelled(/* sequenceId= */2L, "test".toByteArray())
- val noneCopy1 = ActivityLaunchCancelled(/* sequenceId= */1L, "test".toByteArray())
- val noneCopy2 = ActivityLaunchCancelled(/* sequenceId= */2L, "test1".toByteArray())
-
- // equals(Object other)
- assertThat(valid).isEqualTo(copy)
- assertThat(valid).isNotEqualTo(noneCopy1)
- assertThat(valid).isNotEqualTo(noneCopy2)
-
- // test toString()
- val result = valid.toString()
- assertThat(result).isEqualTo("ActivityLaunchCancelled{sequenceId=2, test}")
- }
-
- /**
- * Test for ReportFullyDrawn.
- */
- @Test
- fun testReportFullyDrawn() {
- val valid = ReportFullyDrawn(/* sequenceId= */2L, "test".toByteArray(), /* timestampNs= */ 1L)
- val copy = ReportFullyDrawn(/* sequenceId= */2L, "test".toByteArray(), /* timestampNs= */ 1L)
- val noneCopy1 = ReportFullyDrawn(/* sequenceId= */1L, "test".toByteArray(),
- /* timestampNs= */ 1L)
- val noneCopy2 = ReportFullyDrawn(/* sequenceId= */1L, "test".toByteArray(),
- /* timestampNs= */ 1L)
- val noneCopy3 = ReportFullyDrawn(/* sequenceId= */2L, "test1".toByteArray(),
- /* timestampNs= */ 1L)
-
- // equals(Object other)
- assertThat(valid).isEqualTo(copy)
- assertThat(valid).isNotEqualTo(noneCopy1)
- assertThat(valid).isNotEqualTo(noneCopy2)
- assertThat(valid).isNotEqualTo(noneCopy3)
-
- // test toString()
- val result = valid.toString()
- assertThat(result).isEqualTo("ReportFullyDrawn{sequenceId=2, test, timestampNs=1}")
- }
-}
diff --git a/startop/iorap/tests/src/com/google/android/startop/iorap/IIorapIntegrationTest.kt b/startop/iorap/tests/src/com/google/android/startop/iorap/IIorapIntegrationTest.kt
deleted file mode 100644
index 18c249136d05..000000000000
--- a/startop/iorap/tests/src/com/google/android/startop/iorap/IIorapIntegrationTest.kt
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.google.android.startop.iorap
-
-import android.net.Uri
-import android.os.ServiceManager
-import androidx.test.filters.FlakyTest
-import androidx.test.filters.MediumTest
-import org.junit.Test
-import org.mockito.Mockito.argThat
-import org.mockito.Mockito.eq
-import org.mockito.Mockito.inOrder
-import org.mockito.Mockito.spy
-import org.mockito.Mockito.timeout
-
-// @Ignore("Test is disabled until iorapd is added to init and there's selinux policies for it")
-@MediumTest
-@FlakyTest(bugId = 149098310) // Failing on cuttlefish with SecurityException.
-class IIorapIntegrationTest {
- /**
- * @throws ServiceManager.ServiceNotFoundException if iorapd service could not be found
- */
- private val iorapService: IIorap by lazy {
- // TODO: connect to 'iorapd.stub' which doesn't actually do any work other than reply.
- IIorap.Stub.asInterface(ServiceManager.getServiceOrThrow("iorapd"))
-
- // Use 'adb shell setenforce 0' otherwise this whole test fails,
- // because the servicemanager is not allowed to hand out the binder token for iorapd.
-
- // TODO: implement the selinux policies for iorapd.
- }
-
- // A dummy binder stub implementation is required to use with mockito#spy.
- // Mockito overrides the methods at runtime and tracks how methods were invoked.
- open class DummyTaskListener : ITaskListener.Stub() {
- // Note: make parameters nullable to avoid the kotlin IllegalStateExceptions
- // from using the mockito matchers (eq, argThat, etc).
- override fun onProgress(requestId: RequestId?, result: TaskResult?) {
- }
-
- override fun onComplete(requestId: RequestId?, result: TaskResult?) {
- }
- }
-
- private fun testAnyMethod(func: (RequestId) -> Unit) {
- val taskListener = spy(DummyTaskListener())!!
-
- // FIXME: b/149098310
- return
-
- try {
- iorapService.setTaskListener(taskListener)
- // Note: Binder guarantees total order for oneway messages sent to the same binder
- // interface, so we don't need any additional blocking here before sending later calls.
-
- // Every new method call should have a unique request id.
- val requestId = RequestId.nextValueForSequence()!!
-
- // Apply the specific function under test.
- func(requestId)
-
- // Typical mockito behavior is to allow any-order callbacks, but we want to test order.
- val inOrder = inOrder(taskListener)
-
- // The "stub" behavior of iorapd is that every request immediately gets a response of
- // BEGAN,ONGOING,COMPLETED
- inOrder.verify(taskListener, timeout(100))
- .onProgress(eq(requestId), argThat { it!!.state == TaskResult.STATE_BEGAN })
- inOrder.verify(taskListener, timeout(100))
- .onProgress(eq(requestId), argThat { it!!.state == TaskResult.STATE_ONGOING })
- inOrder.verify(taskListener, timeout(100))
- .onComplete(eq(requestId), argThat { it!!.state == TaskResult.STATE_COMPLETED })
- inOrder.verifyNoMoreInteractions()
- } finally {
- // iorapService.setTaskListener(null)
- // FIXME: null is broken, C++ side sees a non-null object.
- }
- }
-
- @Test
- fun testOnPackageEvent() {
- // FIXME (b/137134253): implement PackageEvent parsing on the C++ side.
- // This is currently (silently: b/137135024) failing because IIorap is 'oneway' and the
- // C++ PackageEvent un-parceling fails since its not implemented fully.
- /*
- testAnyMethod { requestId : RequestId ->
- iorapService.onPackageEvent(requestId,
- PackageEvent.createReplaced(
- Uri.parse("https://www.google.com"), "com.fake.package"))
- }
- */
- }
-
- @Test
- fun testOnAppIntentEvent() {
- testAnyMethod { requestId: RequestId ->
- iorapService.onAppIntentEvent(requestId, AppIntentEvent.createDefaultIntentChanged(
- ActivityInfo("dont care", "dont care"),
- ActivityInfo("dont care 2", "dont care 2")))
- }
- }
-
- @Test
- fun testOnAppLaunchEvent() {
- testAnyMethod { requestId : RequestId ->
- iorapService.onAppLaunchEvent(requestId, AppLaunchEvent.IntentFailed(/*sequenceId*/123))
- }
- }
-
- @Test
- fun testOnSystemServiceEvent() {
- testAnyMethod { requestId: RequestId ->
- iorapService.onSystemServiceEvent(requestId,
- SystemServiceEvent(SystemServiceEvent.TYPE_START))
- }
- }
-
- @Test
- fun testOnSystemServiceUserEvent() {
- testAnyMethod { requestId: RequestId ->
- iorapService.onSystemServiceUserEvent(requestId,
- SystemServiceUserEvent(SystemServiceUserEvent.TYPE_START_USER, 0))
- }
- }
-}
diff --git a/startop/iorap/tests/src/com/google/android/startop/iorap/ParcelablesTest.kt b/startop/iorap/tests/src/com/google/android/startop/iorap/ParcelablesTest.kt
deleted file mode 100644
index 150577a21f5a..000000000000
--- a/startop/iorap/tests/src/com/google/android/startop/iorap/ParcelablesTest.kt
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under the
- * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the specific language governing
- * permissions and limitations under the License.
- */
-
-package com.google.android.startop.iorap
-
-import android.net.Uri
-import android.os.Parcel
-import android.os.Parcelable
-import androidx.test.filters.SmallTest
-import org.junit.Test
-import org.junit.runner.RunWith
-import com.google.common.truth.Truth.assertThat
-import org.junit.runners.Parameterized
-
-/**
- * Basic unit tests to ensure that all of the [Parcelable]s in [com.google.android.startop.iorap]
- * have a valid-conforming interface implementation.
- */
-@SmallTest
-@RunWith(Parameterized::class)
-class ParcelablesTest<T : Parcelable>(private val inputData: InputData<T>) {
- companion object {
- private val initialRequestId = RequestId.nextValueForSequence()!!
-
- @JvmStatic
- @Parameterized.Parameters
- fun data() = listOf(
- InputData(
- newActivityInfo(),
- newActivityInfo(),
- ActivityInfo("some package", "some other activity")),
- InputData(
- ActivityHintEvent(ActivityHintEvent.TYPE_COMPLETED, newActivityInfo()),
- ActivityHintEvent(ActivityHintEvent.TYPE_COMPLETED, newActivityInfo()),
- ActivityHintEvent(ActivityHintEvent.TYPE_POST_COMPLETED,
- newActivityInfo())),
- InputData(
- AppIntentEvent.createDefaultIntentChanged(newActivityInfo(),
- newActivityInfoOther()),
- AppIntentEvent.createDefaultIntentChanged(newActivityInfo(),
- newActivityInfoOther()),
- AppIntentEvent.createDefaultIntentChanged(newActivityInfoOther(),
- newActivityInfo())),
- InputData(
- PackageEvent.createReplaced(newUri(), "some package"),
- PackageEvent.createReplaced(newUri(), "some package"),
- PackageEvent.createReplaced(newUri(), "some other package")
- ),
- InputData(initialRequestId, cloneRequestId(initialRequestId),
- RequestId.nextValueForSequence()),
- InputData(
- SystemServiceEvent(SystemServiceEvent.TYPE_BOOT_PHASE),
- SystemServiceEvent(SystemServiceEvent.TYPE_BOOT_PHASE),
- SystemServiceEvent(SystemServiceEvent.TYPE_START)),
- InputData(
- SystemServiceUserEvent(SystemServiceUserEvent.TYPE_START_USER, 12345),
- SystemServiceUserEvent(SystemServiceUserEvent.TYPE_START_USER, 12345),
- SystemServiceUserEvent(SystemServiceUserEvent.TYPE_CLEANUP_USER, 12345)),
- InputData(
- TaskResult(TaskResult.STATE_COMPLETED),
- TaskResult(TaskResult.STATE_COMPLETED),
- TaskResult(TaskResult.STATE_ONGOING))
- )
-
- private fun newActivityInfo(): ActivityInfo {
- return ActivityInfo("some package", "some activity")
- }
-
- private fun newActivityInfoOther(): ActivityInfo {
- return ActivityInfo("some package 2", "some activity 2")
- }
-
- private fun newUri(): Uri {
- return Uri.parse("https://www.google.com")
- }
-
- private fun cloneRequestId(requestId: RequestId): RequestId {
- val constructor = requestId::class.java.declaredConstructors[0]
- constructor.isAccessible = true
- return constructor.newInstance(requestId.requestId) as RequestId
- }
- }
-
- /**
- * Test for [Object.equals] implementation.
- */
- @Test
- fun testEquality() {
- assertThat(inputData.valid).isEqualTo(inputData.valid)
- assertThat(inputData.valid).isEqualTo(inputData.validCopy)
- assertThat(inputData.valid).isNotEqualTo(inputData.validOther)
- }
-
- /**
- * Test for [Parcelable] implementation.
- */
- @Test
- fun testParcelRoundTrip() {
- // calling writeToParcel and then T::CREATOR.createFromParcel would return the same data.
- val assertParcels = { it: T, data: InputData<T> ->
- val parcel = Parcel.obtain()
- it.writeToParcel(parcel, 0)
- parcel.setDataPosition(0) // future reads will see all previous writes.
- assertThat(it).isEqualTo(data.createFromParcel(parcel))
- parcel.recycle()
- }
-
- assertParcels(inputData.valid, inputData)
- assertParcels(inputData.validCopy, inputData)
- assertParcels(inputData.validOther, inputData)
- }
-
- data class InputData<T : Parcelable>(val valid: T, val validCopy: T, val validOther: T) {
- val kls = valid.javaClass
- init {
- assertThat(valid).isNotSameInstanceAs(validCopy)
- // Don't use isInstanceOf because of phantom warnings in intellij about Class!
- assertThat(validCopy.javaClass).isEqualTo(valid.javaClass)
- assertThat(validOther.javaClass).isEqualTo(valid.javaClass)
- }
-
- fun createFromParcel(parcel: Parcel): T {
- val field = kls.getDeclaredField("CREATOR")
- val creator = field.get(null) as Parcelable.Creator<T>
-
- return creator.createFromParcel(parcel)
- }
- }
-}
diff --git a/startop/scripts/app_startup/analyze_metrics.py b/startop/scripts/app_startup/analyze_metrics.py
deleted file mode 100755
index d74d6f68d823..000000000000
--- a/startop/scripts/app_startup/analyze_metrics.py
+++ /dev/null
@@ -1,457 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 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.
-
-"""
-Perform statistical analysis on measurements produced by app_startup_runner.py
-
-Install:
-$> sudo apt-get install python3-scipy
-
-Usage:
-$> ./analyze_metrics.py <filename.csv> [<filename2.csv> ...]
-$> ./analyze_metrics.py --help
-"""
-
-import argparse
-import csv
-import itertools
-import os
-import subprocess
-import sys
-import tempfile
-from typing import Any, List, Dict, Iterable, TextIO, Tuple
-
-from scipy import stats as sc
-import numpy as np
-
-
-# These CSV columns are considered labels. Everything after them in the same row are metrics.
-_LABEL_COLUMNS=['packages', 'readaheads', 'compiler_filters']
-# The metric series with the 'cold' readahead is the baseline.
-# All others (warm, jit, etc) are the potential improvements.
-
-#fixme: this should probably be an option
-_BASELINE=('readaheads', 'cold')
-# ignore this for some statistic calculations
-_IGNORE_PAIR=('readaheads', 'warm')
-_PLOT_SUBKEY='readaheads'
-_PLOT_GROUPKEY='packages'
-_PLOT_DATA_INDEX = 0
-_DELTA=50
-_DELTA2=100
-_PVALUE_THRESHOLD=0.10
-_debug = False # See -d/--debug flag.
-
-def parse_options(argv: List[str] = None):
- """Parse command line arguments and return an argparse Namespace object."""
- parser = argparse.ArgumentParser(description="Perform statistical analysis on measurements produced by app_start_runner.py.")
- parser.add_argument('input_files', metavar='file.csv', nargs='+', help='CSV file produced by app_startup_runner.py')
-
- parser.add_argument('-d', '--debug', dest='debug', action='store_true', help='Add extra debugging output')
- parser.add_argument('-os', '--output-samples', dest='output_samples', default='/dev/null', action='store', help='Store CSV for per-sample data')
- parser.add_argument('-oc', '--output-comparable', dest='output_comparable', default='/dev/null', action='store', help='Output CSV for comparable against baseline')
- parser.add_argument('-ocs', '--output-comparable-significant', dest='output_comparable_significant', default='/dev/null', action='store', help='Output CSV for comparable against baseline (significant only)')
- parser.add_argument('-pt', '--pvalue-threshold', dest='pvalue_threshold', type=float, default=_PVALUE_THRESHOLD, action='store')
- parser.add_argument('-dt', '--delta-threshold', dest='delta_threshold', type=int, default=_DELTA, action='store')
-
- return parser.parse_args(argv)
-
-def _debug_print(*args, **kwargs):
- """Print the args to sys.stderr if the --debug/-d flag was passed in."""
- global _debug
- if _debug:
- print(*args, **kwargs, file=sys.stderr)
-
-def _expand_gen_repr(args):
- new_args_list = []
- for i in args:
- # detect iterable objects that do not have their own override of __str__
- if hasattr(i, '__iter__'):
- to_str = getattr(i, '__str__')
- if to_str.__objclass__ == object:
- # the repr for a generator is just type+address, expand it out instead.
- new_args_list.append([_expand_gen_repr([j])[0] for j in i])
- continue
- # normal case: uses the built-in to-string
- new_args_list.append(i)
- return new_args_list
-
-def _debug_print_gen(*args, **kwargs):
- """Like _debug_print but will turn any iterable args into a list."""
- if not _debug:
- return
-
- new_args_list = _expand_gen_repr(args)
- _debug_print(*new_args_list, **kwargs)
-
-def read_headers(input_file: TextIO) -> Tuple[List[str], List[str]]:
- _debug_print("read_headers for file: ", input_file.name)
- csv_reader = csv.reader(input_file)
-
- label_num_columns = len(_LABEL_COLUMNS)
-
- try:
- header = next(csv_reader)
- except StopIteration:
- header = None
- _debug_print('header', header)
-
- if not header:
- return (None, None)
-
- labels = header[0:label_num_columns]
- data = header[label_num_columns:]
-
- return (labels, data)
-
-def read_labels_and_data(input_file: TextIO) -> Iterable[Tuple[List[str], List[int]]]:
- _debug_print("print_analysis for file: ", input_file.name)
- csv_reader = csv.reader(input_file)
-
- # Skip the header because it doesn't contain any data.
- # To get the header see read_headers function.
- try:
- header = next(csv_reader)
- except StopIteration:
- header = None
-
- label_num_columns = len(_LABEL_COLUMNS)
-
- for row in csv_reader:
- if len(row) > 0 and row[0][0] == ';':
- _debug_print("skip comment line", row)
- continue
-
- labels = row[0:label_num_columns]
- data = [int(i) for i in row[label_num_columns:]]
-
-# _debug_print("labels:", labels)
-# _debug_print("data:", data)
-
- yield (labels, data)
-
-def group_metrics_by_label(it: Iterable[Tuple[List[str], List[int]]]):
- prev_labels = None
- data_2d = []
-
- for label_list, data_list in it:
- if prev_labels != label_list:
- if prev_labels:
-# _debug_print("grouped labels:", prev_labels, "data_2d:", data_2d)
- yield (prev_labels, data_2d)
- data_2d = []
-
- data_2d.append(data_list)
- prev_labels = label_list
-
- if prev_labels:
-# _debug_print("grouped labels:", prev_labels, "data_2d:", data_2d)
- yield (prev_labels, data_2d)
-
-def data_to_numpy(it: Iterable[Tuple[List[str], List[List[int]]]]) -> Iterable[Tuple[List[str], Any]]:
- for label_list, data_2d in it:
- yield (label_list, np.asarray(data_2d, dtype=int))
-
-def iterate_columns(np_data_2d):
- for col in range(np_data_2d.shape[1]):
- col_as_array = np_data_2d[:, col]
- yield col_as_array
-
-def confidence_interval(np_data_2d, percent=0.95):
- """
- Given some data [[a,b,c],[d,e,f,]...]
-
- We assume the same metric is in the column (e.g. [a,d])
- and that data in the rows (e.g. [b,e]) are separate metric values.
-
- We then calculate the CI for each metric individually returning it as a list of tuples.
- """
- arr = []
- for col_2d in iterate_columns(np_data_2d):
- mean = col_2d.mean()
- sigma = col_2d.std()
-
- ci = sc.norm.interval(percent, loc=mean, scale=sigma / np.sqrt(len(col_2d)))
- arr.append(ci)
-
- # TODO: This seems to be returning NaN when all the samples have the same exact value
- # (e.g. stddev=0, which can trivially happen when sample count = 1).
-
- return arr
-
-def print_analysis(it, label_header: List[str], data_header: List[str], output_samples: str):
- print(label_header)
-
- with open(output_samples, "w") as output_file:
-
- csv_writer = csv.writer(output_file)
- csv_writer.writerow(label_header + ['mean', 'std', 'confidence_interval_a', 'confidence_interval_b'])
-
- for label_list, np_data_2d in it:
- print("**********************")
- print(label_list)
- print()
- print(" ", data_header)
- # aggregate computation column-wise
- print("Mean: ", np_data_2d.mean(axis=0))
- print("Std: ", np_data_2d.std(axis=0))
- print("CI95%:", confidence_interval(np_data_2d))
- print("SEM: ", stats_standard_error_one(np_data_2d, axis=0))
-
- #ci = confidence_interval(np_data_2d)[_PLOT_DATA_INDEX]
- sem = stats_standard_error_one(np_data_2d, axis=0)[_PLOT_DATA_INDEX]
- mean = np_data_2d.mean(axis=0)[_PLOT_DATA_INDEX]
-
- ci = (mean - sem, mean + sem)
-
- csv_writer.writerow(label_list + [mean, np_data_2d.std(axis=0)[_PLOT_DATA_INDEX], ci[0], ci[1]])
-
-def from_file_group_by_labels(input_file):
- (label_header, data_header) = read_headers(input_file)
- label_data_iter = read_labels_and_data(input_file)
- grouped_iter = group_metrics_by_label(label_data_iter)
- grouped_numpy_iter = data_to_numpy(grouped_iter)
-
- return grouped_numpy_iter, label_header, data_header
-
-def list_without_index(list, index):
- return list[:index] + list[index+1:]
-
-def group_by_without_baseline_key(grouped_numpy_iter, label_header):
- """
- Data is considered comparable if the only difference is the baseline key
- (i.e. the readahead is different but the package, compilation filter, etc, are the same).
-
- Returns iterator that's grouped by the non-baseline labels to an iterator of
- (label_list, data_2d).
- """
- baseline_index = label_header.index(_BASELINE[0])
-
- def get_label_without_baseline(tpl):
- label_list, _ = tpl
- return list_without_index(label_list, baseline_index)
- # [['pkgname', 'compfilter', 'warm'], [data]]
- # [['pkgname', 'compfilter', 'cold'], [data2]]
- # [['pkgname2', 'compfilter', 'warm'], [data3]]
- #
- # ->
- # ( [['pkgname', 'compfilter', 'warm'], [data]] # ignore baseline label change.
- # [['pkgname', 'compfilter', 'cold'], [data2]] ), # split here because the pkgname changed.
- # ( [['pkgname2', 'compfilter', 'warm'], [data3]] )
- for group_info, it in itertools.groupby(grouped_numpy_iter, key = get_label_without_baseline):
- yield it
-
- # TODO: replace this messy manual iteration/grouping with pandas
-
-def iterate_comparable_metrics(without_baseline_iter, label_header):
- baseline_index = label_header.index(_BASELINE[0])
- baseline_value = _BASELINE[1]
-
- _debug_print("iterate comparables")
-
- def is_baseline_fun(tp):
- ll, dat = tp
- return ll[baseline_index] == baseline_value
-
- # iterating here when everything but the baseline key is the same.
- for it in without_baseline_iter:
- it1, it2 = itertools.tee(it)
-
- # find all the baseline data.
- baseline_filter_it = filter(is_baseline_fun, it1)
-
- # find non-baseline data.
- nonbaseline_filter_it = itertools.filterfalse(is_baseline_fun, it2)
-
- yield itertools.product(baseline_filter_it, nonbaseline_filter_it)
-
-def stats_standard_error_one(a, axis):
- a_std = a.std(axis=axis, ddof=0)
- a_len = a.shape[axis]
-
- return a_std / np.sqrt(a_len)
-
-def stats_standard_error(a, b, axis):
- a_std = a.std(axis=axis, ddof=0)
- b_std = b.std(axis=axis, ddof=0)
-
- a_len = a.shape[axis]
- b_len = b.shape[axis]
-
- temp1 = a_std*a_std/a_len
- temp2 = b_std*b_std/b_len
-
- return np.sqrt(temp1 + temp2)
-
-def stats_tvalue(a, b, axis, delta = 0):
- a_mean = a.mean(axis=axis)
- b_mean = b.mean(axis=axis)
-
- return (a_mean - b_mean - delta) / stats_standard_error(a, b, axis)
-
-def stats_pvalue(a, b, axis, delta, left:bool = False):
- """
- Single-tailed 2-sample t-test.
-
- Returns p-value for the null hypothesis: mean(a) - mean(b) >= delta.
- :param a: numpy 2d array
- :param b: numpy 2d array
- :param axis: which axis to do the calculations across
- :param delta: test value of mean differences
- :param left: if true then use <= delta instead of >= delta
- :return: p-value
- """
- # implement our own pvalue calculation because the built-in t-test (t,p values)
- # only offer delta=0 , e.g. m1-m1 ? 0
- # we are however interested in m1-m2 ? delta
- t_value = stats_tvalue(a, b, axis, delta)
-
- # 2-sample degrees of freedom is using the array sizes - 2.
- dof = a.shape[axis] + b.shape[axis] - 2
-
- if left:
- # left tailed test. e.g. m1-m2 <= delta
- return sc.t.cdf(t_value, dof)
- else:
- # right tailed test. e.g. m1-m2 >= delta
- return sc.t.sf(t_value, dof)
- # a left+right tailed test is a 2-tail t-test and can be done using ttest_ind for delta=0
-
-def print_comparable_analysis(comparable_metrics_iter, label_header, data_header, output_comparable: str, output_comparable_significant: str):
- baseline_value = _BASELINE[1]
- baseline_index = label_header.index(_BASELINE[0])
-
- old_baseline_label_list = None
- delta = _DELTA
- filter_value = _IGNORE_PAIR[1]
- filter_index = label_header.index(_IGNORE_PAIR[0])
-
- pvalue_threshold = _PVALUE_THRESHOLD
- ci_threshold = (1 - _PVALUE_THRESHOLD) * 100.0
-
- with open(output_comparable, "w") as output_file:
-
- csv_writer = csv.writer(output_file)
- csv_writer.writerow(label_header + ['mean', 'mean_diff', 'sem', 'pvalue_2tailed', 'pvalue_gt%d' %(_DELTA), 'pvalue_gt%d' %(_DELTA2)])
-
- print("------------------------------------------------------------------")
- print("Comparison against the baseline %s = %s" %(_BASELINE, baseline_value))
- print("--- Right-tailed t-test checks if the baseline >= current %s by at least %d" %(_BASELINE[0], delta))
- print()
-
- global_stats = {'better_than_delta': [], 'better_than_delta_p95': []}
-
- for nested_it in comparable_metrics_iter:
- print("************************")
-
- better_than_delta = []
- better_than_delta_p95 = []
-
- saw_baseline_once = False
-
- for ((baseline_label_list, baseline_np_data_2d), (rest_label_list, rest_np_data_2d)) in nested_it:
- _debug_print("baseline_label_list:", baseline_label_list)
- _debug_print("baseline_np_data_2d:", baseline_np_data_2d)
- _debug_print("rest_label_list:", rest_label_list)
- _debug_print("rest_np_data_2d:", rest_np_data_2d)
-
- mean_diff = baseline_np_data_2d.mean(axis=0) - rest_np_data_2d.mean(axis=0)
- # 2-sample 2-tailed t-test with delta=0
- # e.g. "Is it true that usually the two sample means are different?"
- t_statistic, t_pvalue = sc.ttest_ind(baseline_np_data_2d, rest_np_data_2d, axis=0)
-
- # 2-sample 1-tailed t-test with delta=50
- # e.g. "Is it true that usually the sample means better than 50ms?"
- t2 = stats_tvalue(baseline_np_data_2d, rest_np_data_2d, axis=0, delta=delta)
- p2 = stats_pvalue(baseline_np_data_2d, rest_np_data_2d, axis=0, delta=delta)
-
- t2_b = stats_tvalue(baseline_np_data_2d, rest_np_data_2d, axis=0, delta=_DELTA2)
- p2_b = stats_pvalue(baseline_np_data_2d, rest_np_data_2d, axis=0, delta=_DELTA2)
-
- print("%s vs %s" %(rest_label_list, baseline_value))
- print(" ", data_header)
- print("Mean Difference: ", mean_diff)
- print("T-test (2-tailed) != 0: t=%s, p=%s" %(t_statistic, t_pvalue))
- print("T-test (right-tailed) >= %d: t=%s, p=%s" %(_DELTA, t2, p2))
- print("T-test (right-tailed) >= %d: t=%s, p=%s" %(_DELTA2, t2_b, p2_b))
-
- def write_out_values(label_list, *args):
- csv_writer.writerow(label_list + [i[_PLOT_DATA_INDEX] for i in args])
-
- sem = stats_standard_error(baseline_np_data_2d, rest_np_data_2d, axis=0)
- if saw_baseline_once == False:
- saw_baseline_once = True
- base_sem = stats_standard_error_one(baseline_np_data_2d, axis=0)
- write_out_values(baseline_label_list, baseline_np_data_2d.mean(axis=0), [0], base_sem, [None], [None], [None])
- write_out_values(rest_label_list, rest_np_data_2d.mean(axis=0), mean_diff, sem, t_pvalue, p2, p2_b)
-
- # now do the global statistics aggregation
-
- if rest_label_list[filter_index] == filter_value:
- continue
-
- if mean_diff > delta:
- better_than_delta.append((mean_diff, p2, rest_label_list))
-
- if p2 <= pvalue_threshold:
- better_than_delta_p95.append((mean_diff, rest_label_list))
-
- if better_than_delta:
- global_stats['better_than_delta'].append(better_than_delta)
- if better_than_delta_p95:
- global_stats['better_than_delta_p95'].append(better_than_delta_p95)
-
- print("------------------------")
- print("Global statistics:")
- print("//// Rows with %s=%s are ignored here." %_IGNORE_PAIR)
- print("- # of results with mean diff better than delta(%d) = %d" %(delta, len(global_stats['better_than_delta'])))
- print(" > (meandiff, pvalue, labels)")
- for i in global_stats['better_than_delta']:
- print(" > %s" %i)
- print("- # of results with mean diff better than delta(%d) CI%d%% = %d" %(delta, ci_threshold, len(global_stats['better_than_delta_p95'])))
- print(" > (meandiff, labels)")
- for i in global_stats['better_than_delta_p95']:
- print(" > %s" %i)
-
-def main():
- global _debug
- global _DELTA
- global _PVALUE_THRESHOLD
-
- opts = parse_options()
- _debug = opts.debug
- _debug_print("parsed options: ", opts)
-
- _PVALUE_THRESHOLD = opts.pvalue_threshold or _PVALUE_THRESHOLD
-
- for file_name in opts.input_files:
- with open(file_name, 'r') as input_file:
- (grouped_numpy_iter, label_header, data_header) = from_file_group_by_labels(input_file)
- print_analysis(grouped_numpy_iter, label_header, data_header, opts.output_samples)
-
- with open(file_name, 'r') as input_file:
- (grouped_numpy_iter, label_header, data_header) = from_file_group_by_labels(input_file)
- without_baseline_iter = group_by_without_baseline_key(grouped_numpy_iter, label_header)
- #_debug_print_gen(without_baseline_iter)
-
- comparable_metrics_iter = iterate_comparable_metrics(without_baseline_iter, label_header)
- print_comparable_analysis(comparable_metrics_iter, label_header, data_header, opts.output_comparable, opts.output_comparable_significant)
-
- return 0
-
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/startop/scripts/app_startup/app_startup_runner.py b/startop/scripts/app_startup/app_startup_runner.py
deleted file mode 100755
index 25ee6f7368c8..000000000000
--- a/startop/scripts/app_startup/app_startup_runner.py
+++ /dev/null
@@ -1,393 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 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.
-
-#
-#
-# Measure application start-up time by launching applications under various combinations.
-# See --help for more details.
-#
-#
-# Sample usage:
-# $> ./app_startup_runner.py -p com.google.android.calculator -r warm -r cold -lc 10 -o out.csv
-# $> ./analyze_metrics.py out.csv
-#
-#
-
-import argparse
-import csv
-import itertools
-import os
-import sys
-import tempfile
-from datetime import timedelta
-from typing import Any, Callable, Iterable, List, NamedTuple, TextIO, Tuple, \
- TypeVar, Union, Optional
-
-# local import
-DIR = os.path.abspath(os.path.dirname(__file__))
-sys.path.append(os.path.dirname(DIR))
-import lib.cmd_utils as cmd_utils
-import lib.print_utils as print_utils
-from app_startup.run_app_with_prefetch import PrefetchAppRunner
-import app_startup.lib.args_utils as args_utils
-from app_startup.lib.data_frame import DataFrame
-from app_startup.lib.perfetto_trace_collector import PerfettoTraceCollector
-from iorap.compiler import CompilerType
-import iorap.compiler as compiler
-
-# The following command line options participate in the combinatorial generation.
-# All other arguments have a global effect.
-_COMBINATORIAL_OPTIONS = ['package', 'readahead', 'compiler_filter',
- 'activity', 'trace_duration']
-_TRACING_READAHEADS = ['mlock', 'fadvise']
-_FORWARD_OPTIONS = {'loop_count': '--count'}
-_RUN_SCRIPT = os.path.join(os.path.dirname(os.path.realpath(__file__)),
- 'run_app_with_prefetch.py')
-
-CollectorPackageInfo = NamedTuple('CollectorPackageInfo',
- [('package', str), ('compiler_filter', str)])
-# by 2; systrace starts up slowly.
-
-_UNLOCK_SCREEN_SCRIPT = os.path.join(
- os.path.dirname(os.path.realpath(__file__)), 'unlock_screen')
-
-RunCommandArgs = NamedTuple('RunCommandArgs',
- [('package', str),
- ('readahead', str),
- ('activity', Optional[str]),
- ('compiler_filter', Optional[str]),
- ('timeout', Optional[int]),
- ('debug', bool),
- ('simulate', bool),
- ('input', Optional[str]),
- ('trace_duration', Optional[timedelta])])
-
-# This must be the only mutable global variable. All other global variables are constants to avoid magic literals.
-_debug = False # See -d/--debug flag.
-_DEBUG_FORCE = None # Ignore -d/--debug if this is not none.
-_PERFETTO_TRACE_DURATION_MS = 5000 # milliseconds
-_PERFETTO_TRACE_DURATION = timedelta(milliseconds=_PERFETTO_TRACE_DURATION_MS)
-
-# Type hinting names.
-T = TypeVar('T')
-NamedTupleMeta = Callable[
- ..., T] # approximation of a (S : NamedTuple<T> where S() == T) metatype.
-
-def parse_options(argv: List[str] = None):
- """Parse command line arguments and return an argparse Namespace object."""
- parser = argparse.ArgumentParser(description="Run one or more Android "
- "applications under various "
- "settings in order to measure "
- "startup time.")
- # argparse considers args starting with - and -- optional in --help, even though required=True.
- # by using a named argument group --help will clearly say that it's required instead of optional.
- required_named = parser.add_argument_group('required named arguments')
- required_named.add_argument('-p', '--package', action='append',
- dest='packages',
- help='package of the application', required=True)
- required_named.add_argument('-r', '--readahead', action='append',
- dest='readaheads',
- help='which readahead mode to use',
- choices=('warm', 'cold', 'mlock', 'fadvise'),
- required=True)
-
- # optional arguments
- # use a group here to get the required arguments to appear 'above' the optional arguments in help.
- optional_named = parser.add_argument_group('optional named arguments')
- optional_named.add_argument('-c', '--compiler-filter', action='append',
- dest='compiler_filters',
- help='which compiler filter to use. if omitted it does not enforce the app\'s compiler filter',
- choices=('speed', 'speed-profile', 'quicken'))
- optional_named.add_argument('-s', '--simulate', dest='simulate',
- action='store_true',
- help='Print which commands will run, but don\'t run the apps')
- optional_named.add_argument('-d', '--debug', dest='debug',
- action='store_true',
- help='Add extra debugging output')
- optional_named.add_argument('-o', '--output', dest='output', action='store',
- help='Write CSV output to file.')
- optional_named.add_argument('-t', '--timeout', dest='timeout', action='store',
- type=int, default=10,
- help='Timeout after this many seconds when executing a single run.')
- optional_named.add_argument('-lc', '--loop-count', dest='loop_count',
- default=1, type=int, action='store',
- help='How many times to loop a single run.')
- optional_named.add_argument('-in', '--inodes', dest='inodes', type=str,
- action='store',
- help='Path to inodes file (system/extras/pagecache/pagecache.py -d inodes)')
- optional_named.add_argument('--compiler-trace-duration-ms',
- dest='trace_duration',
- type=lambda ms_str: timedelta(milliseconds=int(ms_str)),
- action='append',
- help='The trace duration (milliseconds) in '
- 'compilation')
- optional_named.add_argument('--compiler-type', dest='compiler_type',
- type=CompilerType, choices=list(CompilerType),
- default=CompilerType.DEVICE,
- help='The type of compiler.')
-
- return parser.parse_args(argv)
-
-def key_to_cmdline_flag(key: str) -> str:
- """Convert key into a command line flag, e.g. 'foo-bars' -> '--foo-bar' """
- if key.endswith("s"):
- key = key[:-1]
- return "--" + key.replace("_", "-")
-
-def as_run_command(tpl: NamedTuple) -> List[Union[str, Any]]:
- """
- Convert a named tuple into a command-line compatible arguments list.
-
- Example: ABC(1, 2, 3) -> ['--a', 1, '--b', 2, '--c', 3]
- """
- args = []
- for key, value in tpl._asdict().items():
- if value is None:
- continue
- args.append(key_to_cmdline_flag(key))
- args.append(value)
- return args
-
-def run_perfetto_collector(collector_info: CollectorPackageInfo,
- timeout: int,
- simulate: bool) -> Tuple[bool, TextIO]:
- """Run collector to collect prefetching trace.
-
- Returns:
- A tuple of whether the collection succeeds and the generated trace file.
- """
- tmp_output_file = tempfile.NamedTemporaryFile()
-
- collector = PerfettoTraceCollector(package=collector_info.package,
- activity=None,
- compiler_filter=collector_info.compiler_filter,
- timeout=timeout,
- simulate=simulate,
- trace_duration=_PERFETTO_TRACE_DURATION,
- save_destination_file_path=tmp_output_file.name)
- result = collector.run()
-
- return result is not None, tmp_output_file
-
-def parse_run_script_csv_file(csv_file: TextIO) -> DataFrame:
- """Parse a CSV file full of integers into a DataFrame."""
- csv_reader = csv.reader(csv_file)
-
- try:
- header_list = next(csv_reader)
- except StopIteration:
- header_list = []
-
- if not header_list:
- return None
-
- headers = [i for i in header_list]
-
- d = {}
- for row in csv_reader:
- header_idx = 0
-
- for i in row:
- v = i
- if i:
- v = int(i)
-
- header_key = headers[header_idx]
- l = d.get(header_key, [])
- l.append(v)
- d[header_key] = l
-
- header_idx = header_idx + 1
-
- return DataFrame(d)
-
-def build_ri_compiler_argv(inodes_path: str,
- perfetto_trace_file: str,
- trace_duration: Optional[timedelta]
- ) -> str:
- argv = ['-i', inodes_path, '--perfetto-trace',
- perfetto_trace_file]
-
- if trace_duration is not None:
- argv += ['--duration', str(int(trace_duration.total_seconds()
- * PerfettoTraceCollector.MS_PER_SEC))]
-
- print_utils.debug_print(argv)
- return argv
-
-def execute_run_using_perfetto_trace(collector_info,
- run_combos: Iterable[RunCommandArgs],
- simulate: bool,
- inodes_path: str,
- timeout: int,
- compiler_type: CompilerType,
- requires_trace_collection: bool) -> DataFrame:
- """ Executes run based on perfetto trace. """
- if requires_trace_collection:
- passed, perfetto_trace_file = run_perfetto_collector(collector_info,
- timeout,
- simulate)
- if not passed:
- raise RuntimeError('Cannot run perfetto collector!')
- else:
- perfetto_trace_file = tempfile.NamedTemporaryFile()
-
- with perfetto_trace_file:
- for combos in run_combos:
- if combos.readahead in _TRACING_READAHEADS:
- if simulate:
- compiler_trace_file = tempfile.NamedTemporaryFile()
- else:
- ri_compiler_argv = build_ri_compiler_argv(inodes_path,
- perfetto_trace_file.name,
- combos.trace_duration)
- compiler_trace_file = compiler.compile(compiler_type,
- inodes_path,
- ri_compiler_argv,
- combos.package,
- combos.activity)
-
- with compiler_trace_file:
- combos = combos._replace(input=compiler_trace_file.name)
- print_utils.debug_print(combos)
- output = PrefetchAppRunner(**combos._asdict()).run()
- else:
- print_utils.debug_print(combos)
- output = PrefetchAppRunner(**combos._asdict()).run()
-
- yield DataFrame(dict((x, [y]) for x, y in output)) if output else None
-
-def execute_run_combos(
- grouped_run_combos: Iterable[Tuple[CollectorPackageInfo, Iterable[RunCommandArgs]]],
- simulate: bool,
- inodes_path: str,
- timeout: int,
- compiler_type: CompilerType,
- requires_trace_collection: bool):
- # nothing will work if the screen isn't unlocked first.
- cmd_utils.execute_arbitrary_command([_UNLOCK_SCREEN_SCRIPT],
- timeout,
- simulate=simulate,
- shell=False)
-
- for collector_info, run_combos in grouped_run_combos:
- yield from execute_run_using_perfetto_trace(collector_info,
- run_combos,
- simulate,
- inodes_path,
- timeout,
- compiler_type,
- requires_trace_collection)
-
-def gather_results(commands: Iterable[Tuple[DataFrame]],
- key_list: List[str], value_list: List[Tuple[str, ...]]):
- print_utils.debug_print("gather_results: key_list = ", key_list)
- stringify_none = lambda s: s is None and "<none>" or s
- # yield key_list + ["time(ms)"]
- for (run_result_list, values) in itertools.zip_longest(commands, value_list):
- print_utils.debug_print("run_result_list = ", run_result_list)
- print_utils.debug_print("values = ", values)
-
- if not run_result_list:
- continue
-
- # RunCommandArgs(package='com.whatever', readahead='warm', compiler_filter=None)
- # -> {'package':['com.whatever'], 'readahead':['warm'], 'compiler_filter':[None]}
- values_dict = {}
- for k, v in values._asdict().items():
- if not k in key_list:
- continue
- values_dict[k] = [stringify_none(v)]
-
- values_df = DataFrame(values_dict)
- # project 'values_df' to be same number of rows as run_result_list.
- values_df = values_df.repeat(run_result_list.data_row_len)
-
- # the results are added as right-hand-side columns onto the existing labels for the table.
- values_df.merge_data_columns(run_result_list)
-
- yield values_df
-
-def eval_and_save_to_csv(output, annotated_result_values):
- printed_header = False
-
- csv_writer = csv.writer(output)
- for row in annotated_result_values:
- if not printed_header:
- headers = row.headers
- csv_writer.writerow(headers)
- printed_header = True
- # TODO: what about when headers change?
-
- for data_row in row.data_table:
- data_row = [d for d in data_row]
- csv_writer.writerow(data_row)
-
- output.flush() # see the output live.
-
-def coerce_to_list(opts: dict):
- """Tranform values of the dictionary to list.
- For example:
- 1 -> [1], None -> [None], [1,2,3] -> [1,2,3]
- [[1],[2]] -> [[1],[2]], {1:1, 2:2} -> [{1:1, 2:2}]
- """
- result = {}
- for key in opts:
- val = opts[key]
- result[key] = val if issubclass(type(val), list) else [val]
- return result
-
-def main():
- global _debug
-
- opts = parse_options()
- _debug = opts.debug
- if _DEBUG_FORCE is not None:
- _debug = _DEBUG_FORCE
-
- print_utils.DEBUG = _debug
- cmd_utils.SIMULATE = opts.simulate
-
- print_utils.debug_print("parsed options: ", opts)
-
- output_file = opts.output and open(opts.output, 'w') or sys.stdout
-
- combos = lambda: args_utils.generate_run_combinations(
- RunCommandArgs,
- coerce_to_list(vars(opts)),
- opts.loop_count)
- print_utils.debug_print_gen("run combinations: ", combos())
-
- grouped_combos = lambda: args_utils.generate_group_run_combinations(combos(),
- CollectorPackageInfo)
-
- print_utils.debug_print_gen("grouped run combinations: ", grouped_combos())
- requires_trace_collection = any(i in _TRACING_READAHEADS for i in opts.readaheads)
- exec = execute_run_combos(grouped_combos(),
- opts.simulate,
- opts.inodes,
- opts.timeout,
- opts.compiler_type,
- requires_trace_collection)
-
- results = gather_results(exec, _COMBINATORIAL_OPTIONS, combos())
-
- eval_and_save_to_csv(output_file, results)
-
- return 1
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/startop/scripts/app_startup/app_startup_runner_test.py b/startop/scripts/app_startup/app_startup_runner_test.py
deleted file mode 100755
index 0c2bbea04f6a..000000000000
--- a/startop/scripts/app_startup/app_startup_runner_test.py
+++ /dev/null
@@ -1,176 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 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.
-#
-
-"""
-Unit tests for the app_startup_runner.py script.
-
-Install:
- $> sudo apt-get install python3-pytest ## OR
- $> pip install -U pytest
-See also https://docs.pytest.org/en/latest/getting-started.html
-
-Usage:
- $> ./app_startup_runner_test.py
- $> pytest app_startup_runner_test.py
- $> python -m pytest app_startup_runner_test.py
-
-See also https://docs.pytest.org/en/latest/usage.html
-"""
-
-import io
-import shlex
-import sys
-import typing
-# global imports
-from contextlib import contextmanager
-
-# local imports
-import app_startup_runner as asr
-# pip imports
-import pytest
-
-#
-# Argument Parsing Helpers
-#
-
-@contextmanager
-def ignore_stdout_stderr():
- """Ignore stdout/stderr output for duration of this context."""
- old_stdout = sys.stdout
- old_stderr = sys.stderr
- sys.stdout = io.StringIO()
- sys.stderr = io.StringIO()
- try:
- yield
- finally:
- sys.stdout = old_stdout
- sys.stderr = old_stderr
-
-@contextmanager
-def argparse_bad_argument(msg):
- """
- Assert that a SystemExit is raised when executing this context.
- If the assertion fails, print the message 'msg'.
- """
- with pytest.raises(SystemExit, message=msg):
- with ignore_stdout_stderr():
- yield
-
-def assert_bad_argument(args, msg):
- """
- Assert that the command line arguments in 'args' are malformed.
- Prints 'msg' if the assertion fails.
- """
- with argparse_bad_argument(msg):
- parse_args(args)
-
-def parse_args(args):
- """
- :param args: command-line like arguments as a single string
- :return: dictionary of parsed key/values
- """
- # "-a b -c d" => ['-a', 'b', '-c', 'd']
- return vars(asr.parse_options(shlex.split(args)))
-
-def default_dict_for_parsed_args(**kwargs):
- """
- # Combine it with all of the "optional" parameters' default values.
- """
- d = {'compiler_filters': None, 'simulate': False, 'debug': False,
- 'output': None, 'timeout': 10, 'loop_count': 1, 'inodes': None,
- 'trace_duration': None, 'compiler_type': asr.CompilerType.DEVICE}
- d.update(kwargs)
- return d
-
-def default_mock_dict_for_parsed_args(include_optional=True, **kwargs):
- """
- Combine default dict with all optional parameters with some mock required parameters.
- """
- d = {'packages': ['com.fake.package'], 'readaheads': ['warm']}
- if include_optional:
- d.update(default_dict_for_parsed_args())
- d.update(kwargs)
- return d
-
-def parse_optional_args(str):
- """
- Parse an argument string which already includes all the required arguments
- in default_mock_dict_for_parsed_args.
- """
- req = "--package com.fake.package --readahead warm"
- return parse_args("%s %s" % (req, str))
-
-def test_argparse():
- # missing arguments
- assert_bad_argument("", "-p and -r are required")
- assert_bad_argument("-r warm", "-p is required")
- assert_bad_argument("--readahead warm", "-p is required")
- assert_bad_argument("-p com.fake.package", "-r is required")
- assert_bad_argument("--package com.fake.package", "-r is required")
-
- # required arguments are parsed correctly
- ad = default_dict_for_parsed_args # assert dict
-
- assert parse_args("--package xyz --readahead warm") == ad(packages=['xyz'],
- readaheads=['warm'])
- assert parse_args("-p xyz -r warm") == ad(packages=['xyz'],
- readaheads=['warm'])
-
- assert parse_args("-p xyz -r warm -s") == ad(packages=['xyz'],
- readaheads=['warm'],
- simulate=True)
- assert parse_args("-p xyz -r warm --simulate") == ad(packages=['xyz'],
- readaheads=['warm'],
- simulate=True)
-
- # optional arguments are parsed correctly.
- mad = default_mock_dict_for_parsed_args # mock assert dict
- assert parse_optional_args("--output filename.csv") == mad(
- output='filename.csv')
- assert parse_optional_args("-o filename.csv") == mad(output='filename.csv')
-
- assert parse_optional_args("--timeout 123") == mad(timeout=123)
- assert parse_optional_args("-t 456") == mad(timeout=456)
-
- assert parse_optional_args("--loop-count 123") == mad(loop_count=123)
- assert parse_optional_args("-lc 456") == mad(loop_count=456)
-
- assert parse_optional_args("--inodes bar") == mad(inodes="bar")
- assert parse_optional_args("-in baz") == mad(inodes="baz")
-
-
-
-def test_key_to_cmdline_flag():
- assert asr.key_to_cmdline_flag("abc") == "--abc"
- assert asr.key_to_cmdline_flag("foos") == "--foo"
- assert asr.key_to_cmdline_flag("ba_r") == "--ba-r"
- assert asr.key_to_cmdline_flag("ba_zs") == "--ba-z"
-
-def test_parse_run_script_csv_file():
- # empty file -> empty list
- f = io.StringIO("")
- assert asr.parse_run_script_csv_file(f) == None
-
- # common case
- f = io.StringIO("TotalTime_ms,Displayed_ms\n1,2")
- df = asr.DataFrame({'TotalTime_ms': [1], 'Displayed_ms': [2]})
-
- pf = asr.parse_run_script_csv_file(f)
- assert pf == df
-
-if __name__ == '__main__':
- pytest.main()
diff --git a/startop/scripts/app_startup/force_compiler_filter b/startop/scripts/app_startup/force_compiler_filter
deleted file mode 100755
index 08f983d92bea..000000000000
--- a/startop/scripts/app_startup/force_compiler_filter
+++ /dev/null
@@ -1,143 +0,0 @@
-#!/bin/bash
-#
-# Copyright 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.
-
-#
-# Forces an application APK to be compiled (by ART's dex2oat)
-# with a specific compiler filter.
-#
-# Example usage:
-# $> ./force_compiler_filter -p com.google.android.apps.maps -c speed-profile
-#
-# (The application may be started/stopped as a side effect)
-#
-
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-source "$DIR/lib/common"
-
-usage() {
- cat <<EOF
-Usage: $(basename $0) [OPTION]...
-
- Required:
- -p, --package package of the app to recompile
- -c, --compiler-filter override the compiler filter if set (default none)
- valid options are listed by: adb shell cmd package, under compile -m
-
- Optional:
- -a, --activity activity of the app to recompile
- -h, --help usage information (this)
- -v, --verbose enable extra verbose printing
- -w, --wait_time how long to wait for app startup (default 10) in seconds
-EOF
-}
-
-wait_time="10" # seconds
-
-parse_arguments() {
- while [[ $# -gt 0 ]]; do
- case "$1" in
- -a|--activity)
- activity="$2"
- shift
- ;;
- -h|--help)
- usage
- exit 0
- ;;
- -p|--package)
- package="$2"
- shift
- ;;
- -w|--wait_time)
- wait_time="$2"
- shift
- ;;
- -c|--compiler-filter)
- compiler_filter="$2"
- shift
- ;;
- -v|--verbose)
- verbose="y"
- ;;
- esac
- shift
- done
-
- if [[ -z "$compiler_filter" ]]; then
- echo "Missing required --compiler-filter" >&2
- echo ""
- usage
- exit 1
- fi
- if [[ -z "$package" ]]; then
- echo "Missing required --package" >&2
- echo ""
- usage
- exit 1
- fi
-
- if [[ "$activity" == "" ]]; then
- activity="$(get_activity_name "$package")"
- if [[ "$activity" == "" ]]; then
- echo "Activity name could not be found, invalid package name?" 1>&2
- exit 1
- else
- verbose_print "Activity name inferred: " "$activity"
- fi
- fi
-}
-
-force_package_compilation() {
- local arg_compiler_filter="$1"
- local arg_package="$2"
-
- if [[ $arg_compiler_filter == speed-profile ]]; then
- # Force the running app to dump its profiles to disk.
- remote_pkill "$arg_package" -SIGUSR1
- sleep 1 # give some time for above to complete.
- fi
-
- adb shell cmd package compile -m "$arg_compiler_filter" -f "$arg_package"
-}
-
-main() {
- parse_arguments "$@"
-
- if [[ $compiler_filter == speed-profile ]]; then
- # screen needs to be unlocked in order to run an app
- "$DIR"/unlock_screen
-
- local output=$("$DIR"/launch_application "$package" "$activity")
- if [[ $? -ne 0 ]]; then
- echo "launching application failed" >&2
- exit 1
- fi
-
- verbose_print "$output"
- # give some time for app startup to complete.
- # this is supposed to be an upper bound for measuring startup time.
- sleep "$wait_time"
- fi
-
- force_package_compilation "$compiler_filter" "$package"
-
- # kill the application to ensure next time it's started,
- # it picks up the correct compilation filter.
- adb shell am force-stop "$package"
- remote_pkill "$package"
-}
-
-main "$@"
diff --git a/startop/scripts/app_startup/launch_application b/startop/scripts/app_startup/launch_application
deleted file mode 100755
index 6704a5a97aa0..000000000000
--- a/startop/scripts/app_startup/launch_application
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/bin/bash
-#
-# Copyright 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.
-
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-source "$DIR/lib/common"
-
-launch_application_usage() {
- cat <<EOF
-Usage: $(basename $0) <package> <activity>
-
- Positional Arguments:
- <package> package of the app to test
- <activity> activity to use
-
- Named Arguments:
- -h, --help usage information (this)
-EOF
-}
-
-launch_application() {
- local package="$1"
- local activity="$2"
-
- # if there's any $s inside of the activity name, it needs to be escaped to \$.
- # example '.app.honeycomb.Shell$HomeActivity'
- # if the $ is not escaped, adb shell will try to evaluate $HomeActivity to a variable.
- activity=${activity//\$/\\$}
-
- adb shell am start -S -W "$package"/"$activity"
-
- # pipe this into 'parse_metrics' to parse the output.
-}
-
-if [[ $# -lt 2 ]]; then
- launch_application_usage
- exit 1
-fi
-
-launch_application "$@"
diff --git a/startop/scripts/app_startup/lib/adb_utils.py b/startop/scripts/app_startup/lib/adb_utils.py
deleted file mode 100644
index 3cebc9a97a50..000000000000
--- a/startop/scripts/app_startup/lib/adb_utils.py
+++ /dev/null
@@ -1,126 +0,0 @@
-#!/usr/bin/env python3
-#
-# 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.
-
-"""Helper util libraries for calling adb command line."""
-
-import datetime
-import os
-import re
-import sys
-import time
-from typing import Optional
-
-sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(
- os.path.abspath(__file__)))))
-import lib.cmd_utils as cmd_utils
-import lib.logcat_utils as logcat_utils
-
-
-def logcat_save_timestamp() -> str:
- """Gets the current logcat timestamp.
-
- Returns:
- A string of timestamp.
- """
- _, output = cmd_utils.run_adb_shell_command(
- "date -u +\'%Y-%m-%d %H:%M:%S.%N\'")
- return output
-
-def vm_drop_cache():
- """Free pagecache and slab object."""
- cmd_utils.run_adb_shell_command('echo 3 > /proc/sys/vm/drop_caches')
- # Sleep a little bit to provide enough time for cache cleanup.
- time.sleep(1)
-
-def root():
- """Roots adb and successive adb commands will run under root."""
- cmd_utils.run_shell_command('adb root')
-
-def disable_selinux():
- """Disables selinux setting."""
- _, output = cmd_utils.run_adb_shell_command('getenforce')
- if output == 'Permissive':
- return
-
- print('Disable selinux permissions and restart framework.')
- cmd_utils.run_adb_shell_command('setenforce 0')
- cmd_utils.run_adb_shell_command('stop')
- cmd_utils.run_adb_shell_command('start')
- cmd_utils.run_shell_command('adb wait-for-device')
-
-def pkill(procname: str):
- """Kills a process on device specified by the substring pattern in procname"""
- _, pids = cmd_utils.run_shell_command('adb shell ps | grep "{}" | '
- 'awk \'{{print $2;}}\''.
- format(procname))
-
- for pid in pids.split('\n'):
- pid = pid.strip()
- if pid:
- passed,_ = cmd_utils.run_adb_shell_command('kill {}'.format(pid))
- time.sleep(1)
-
-def parse_time_to_milliseconds(time: str) -> int:
- """Parses the time string to milliseconds."""
- # Example: +1s56ms, +56ms
- regex = r'\+((?P<second>\d+?)s)?(?P<millisecond>\d+?)ms'
- result = re.search(regex, time)
- second = 0
- if result.group('second'):
- second = int(result.group('second'))
- ms = int(result.group('millisecond'))
- return second * 1000 + ms
-
-def blocking_wait_for_logcat_displayed_time(timestamp: datetime.datetime,
- package: str,
- timeout: int) -> Optional[int]:
- """Parses the displayed time in the logcat.
-
- Returns:
- the displayed time.
- """
- pattern = re.compile('.*ActivityTaskManager: Displayed {}.*'.format(package))
- # 2019-07-02 22:28:34.469453349 -> 2019-07-02 22:28:34.469453
- timestamp = datetime.datetime.strptime(timestamp[:-3],
- '%Y-%m-%d %H:%M:%S.%f')
- timeout_dt = timestamp + datetime.timedelta(0, timeout)
- # 2019-07-01 14:54:21.946 27365 27392 I ActivityTaskManager:
- # Displayed com.android.settings/.Settings: +927ms
- result = logcat_utils.blocking_wait_for_logcat_pattern(timestamp,
- pattern,
- timeout_dt)
- if not result or not '+' in result:
- return None
- displayed_time = result[result.rfind('+'):]
-
- return parse_time_to_milliseconds(displayed_time)
-
-def delete_file_on_device(file_path: str) -> None:
- """ Deletes a file on the device. """
- cmd_utils.run_adb_shell_command(
- "[[ -f '{file_path}' ]] && rm -f '{file_path}' || "
- "exit 0".format(file_path=file_path))
-
-def set_prop(property: str, value: str) -> None:
- """ Sets property using adb shell. """
- cmd_utils.run_adb_shell_command('setprop "{property}" "{value}"'.format(
- property=property, value=value))
-
-def pull_file(device_file_path: str, output_file_path: str) -> None:
- """ Pulls file from device to output """
- cmd_utils.run_shell_command('adb pull "{device_file_path}" "{output_file_path}"'.
- format(device_file_path=device_file_path,
- output_file_path=output_file_path))
diff --git a/startop/scripts/app_startup/lib/adb_utils_test.py b/startop/scripts/app_startup/lib/adb_utils_test.py
deleted file mode 100644
index e590fed568e3..000000000000
--- a/startop/scripts/app_startup/lib/adb_utils_test.py
+++ /dev/null
@@ -1,16 +0,0 @@
-import adb_utils
-
-# pip imports
-import pytest
-
-def test_parse_time_to_milliseconds():
- # Act
- result1 = adb_utils.parse_time_to_milliseconds('+1s7ms')
- result2 = adb_utils.parse_time_to_milliseconds('+523ms')
-
- # Assert
- assert result1 == 1007
- assert result2 == 523
-
-if __name__ == '__main__':
- pytest.main()
diff --git a/startop/scripts/app_startup/lib/app_runner.py b/startop/scripts/app_startup/lib/app_runner.py
deleted file mode 100644
index 78873fa51ab5..000000000000
--- a/startop/scripts/app_startup/lib/app_runner.py
+++ /dev/null
@@ -1,266 +0,0 @@
-# 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.
-
-"""Class to run an app."""
-import os
-import sys
-from typing import Optional, List, Tuple
-
-# local import
-sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(
- os.path.abspath(__file__)))))
-
-import app_startup.lib.adb_utils as adb_utils
-import lib.cmd_utils as cmd_utils
-import lib.print_utils as print_utils
-
-class AppRunnerListener(object):
- """Interface for lisenter of AppRunner. """
-
- def preprocess(self) -> None:
- """Preprocess callback to initialized before the app is running. """
- pass
-
- def postprocess(self, pre_launch_timestamp: str) -> None:
- """Postprocess callback to cleanup after the app is running.
-
- param:
- 'pre_launch_timestamp': indicates the timestamp when the app is
- launching.. """
- pass
-
- def metrics_selector(self, am_start_output: str,
- pre_launch_timestamp: str) -> None:
- """A metrics selection callback that waits for the desired metrics to
- show up in logcat.
- params:
- 'am_start_output': indicates the output of app startup.
- 'pre_launch_timestamp': indicates the timestamp when the app is
- launching.
- returns:
- a string in the format of "<metric>=<value>\n<metric>=<value>\n..."
- for further parsing. For example "TotalTime=123\nDisplayedTime=121".
- Return an empty string if no metrics need to be parsed further.
- """
- pass
-
-class AppRunner(object):
- """ Class to run an app. """
- # static variables
- DIR = os.path.abspath(os.path.dirname(__file__))
- APP_STARTUP_DIR = os.path.dirname(DIR)
- IORAP_COMMON_BASH_SCRIPT = os.path.realpath(os.path.join(DIR,
- '../../iorap/common'))
- DEFAULT_TIMEOUT = 30 # seconds
-
- def __init__(self,
- package: str,
- activity: Optional[str],
- compiler_filter: Optional[str],
- timeout: Optional[int],
- simulate: bool):
- self.package = package
- self.simulate = simulate
-
- # If the argument activity is None, try to set it.
- self.activity = activity
- if self.simulate:
- self.activity = 'act'
- if self.activity is None:
- self.activity = AppRunner.get_activity(self.package)
-
- self.compiler_filter = compiler_filter
- self.timeout = timeout if timeout else AppRunner.DEFAULT_TIMEOUT
-
- self.listeners = []
-
- def add_callbacks(self, listener: AppRunnerListener):
- self.listeners.append(listener)
-
- def remove_callbacks(self, listener: AppRunnerListener):
- self.listeners.remove(listener)
-
- @staticmethod
- def get_activity(package: str) -> str:
- """ Tries to set the activity based on the package. """
- passed, activity = cmd_utils.run_shell_func(
- AppRunner.IORAP_COMMON_BASH_SCRIPT,
- 'get_activity_name',
- [package])
-
- if not passed or not activity:
- raise ValueError(
- 'Activity name could not be found, invalid package name?!')
-
- return activity
-
- def configure_compiler_filter(self) -> bool:
- """Configures compiler filter (e.g. speed).
-
- Returns:
- A bool indicates whether configure of compiler filer succeeds or not.
- """
- if not self.compiler_filter:
- print_utils.debug_print('No --compiler-filter specified, don\'t'
- ' need to force it.')
- return True
-
- passed, current_compiler_filter_info = \
- cmd_utils.run_shell_command(
- '{} --package {}'.format(os.path.join(AppRunner.APP_STARTUP_DIR,
- 'query_compiler_filter.py'),
- self.package))
-
- if passed != 0:
- return passed
-
- # TODO: call query_compiler_filter directly as a python function instead of
- # these shell calls.
- current_compiler_filter, current_reason, current_isa = \
- current_compiler_filter_info.split(' ')
- print_utils.debug_print('Compiler Filter={} Reason={} Isa={}'.format(
- current_compiler_filter, current_reason, current_isa))
-
- # Don't trust reasons that aren't 'unknown' because that means
- # we didn't manually force the compilation filter.
- # (e.g. if any automatic system-triggered compilations are not unknown).
- if current_reason != 'unknown' or \
- current_compiler_filter != self.compiler_filter:
- passed, _ = adb_utils.run_shell_command('{}/force_compiler_filter '
- '--compiler-filter "{}" '
- '--package "{}"'
- ' --activity "{}'.
- format(AppRunner.APP_STARTUP_DIR,
- self.compiler_filter,
- self.package,
- self.activity))
- else:
- adb_utils.debug_print('Queried compiler-filter matched requested '
- 'compiler-filter, skip forcing.')
- passed = False
- return passed
-
- def run(self) -> Optional[List[Tuple[str]]]:
- """Runs an app.
-
- Returns:
- A list of (metric, value) tuples.
- """
- print_utils.debug_print('==========================================')
- print_utils.debug_print('===== START =====')
- print_utils.debug_print('==========================================')
- # Run the preprocess.
- for listener in self.listeners:
- listener.preprocess()
-
- # Ensure the APK is currently compiled with whatever we passed in
- # via --compiler-filter.
- # No-op if this option was not passed in.
- if not self.configure_compiler_filter():
- print_utils.error_print('Compiler filter configuration failed!')
- return None
-
- pre_launch_timestamp = adb_utils.logcat_save_timestamp()
- # Launch the app.
- results = self.launch_app(pre_launch_timestamp)
-
- # Run the postprocess.
- for listener in self.listeners:
- listener.postprocess(pre_launch_timestamp)
-
- return results
-
- def launch_app(self, pre_launch_timestamp: str) -> Optional[List[Tuple[str]]]:
- """ Launches the app.
-
- Returns:
- A list of (metric, value) tuples.
- """
- print_utils.debug_print('Running with timeout {}'.format(self.timeout))
-
- passed, am_start_output = cmd_utils.run_shell_command('timeout {timeout} '
- '"{DIR}/launch_application" '
- '"{package}" '
- '"{activity}"'.
- format(timeout=self.timeout,
- DIR=AppRunner.APP_STARTUP_DIR,
- package=self.package,
- activity=self.activity))
- if not passed and not self.simulate:
- return None
-
- return self.wait_for_app_finish(pre_launch_timestamp, am_start_output)
-
- def wait_for_app_finish(self,
- pre_launch_timestamp: str,
- am_start_output: str) -> Optional[List[Tuple[str]]]:
- """ Wait for app finish and all metrics are shown in logcat.
-
- Returns:
- A list of (metric, value) tuples.
- """
- if self.simulate:
- return [('TotalTime', '123')]
-
- ret = []
- for listener in self.listeners:
- output = listener.metrics_selector(am_start_output,
- pre_launch_timestamp)
- ret = ret + AppRunner.parse_metrics_output(output)
-
- return ret
-
- @staticmethod
- def parse_metrics_output(input: str) -> List[
- Tuple[str, str, str]]:
- """Parses output of app startup to metrics and corresponding values.
-
- It converts 'a=b\nc=d\ne=f\n...' into '[(a,b,''),(c,d,''),(e,f,'')]'
-
- Returns:
- A list of tuples that including metric name, metric value and rest info.
- """
- all_metrics = []
- for line in input.split('\n'):
- if not line:
- continue
- splits = line.split('=')
- if len(splits) < 2:
- print_utils.error_print('Bad line "{}"'.format(line))
- continue
- metric_name = splits[0]
- metric_value = splits[1]
- rest = splits[2] if len(splits) > 2 else ''
- if rest:
- print_utils.error_print('Corrupt line "{}"'.format(line))
- print_utils.debug_print('metric: "{metric_name}", '
- 'value: "{metric_value}" '.
- format(metric_name=metric_name,
- metric_value=metric_value))
-
- all_metrics.append((metric_name, metric_value))
- return all_metrics
-
- @staticmethod
- def parse_total_time( am_start_output: str) -> Optional[str]:
- """Parses the total time from 'adb shell am start pkg' output.
-
- Returns:
- the total time of app startup.
- """
- for line in am_start_output.split('\n'):
- if 'TotalTime:' in line:
- return line[len('TotalTime:'):].strip()
- return None
-
diff --git a/startop/scripts/app_startup/lib/app_runner_test.py b/startop/scripts/app_startup/lib/app_runner_test.py
deleted file mode 100644
index 33d233b03aab..000000000000
--- a/startop/scripts/app_startup/lib/app_runner_test.py
+++ /dev/null
@@ -1,104 +0,0 @@
-# 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.
-#
-
-"""Unit tests for the AppRunner."""
-import os
-import sys
-from pathlib import Path
-
-from app_runner import AppRunner, AppRunnerListener
-from mock import Mock, call, patch
-
-# The path is "frameworks/base/startop/scripts/"
-sys.path.append(Path(os.path.realpath(__file__)).parents[2])
-import lib.cmd_utils as cmd_utils
-
-class AppRunnerTestListener(AppRunnerListener):
- def preprocess(self) -> None:
- cmd_utils.run_shell_command('pre'),
-
- def postprocess(self, pre_launch_timestamp: str) -> None:
- cmd_utils.run_shell_command('post'),
-
- def metrics_selector(self, am_start_output: str,
- pre_launch_timestamp: str) -> None:
- return 'TotalTime=123\n'
-
-RUNNER = AppRunner(package='music',
- activity='MainActivity',
- compiler_filter='speed',
- timeout=None,
- simulate=False)
-
-
-
-def test_configure_compiler_filter():
- with patch('lib.cmd_utils.run_shell_command',
- new_callable=Mock) as mock_run_shell_command:
- mock_run_shell_command.return_value = (True, 'speed arm64 kUpToDate')
-
- RUNNER.configure_compiler_filter()
-
- calls = [call(os.path.realpath(
- os.path.join(RUNNER.DIR,
- '../query_compiler_filter.py')) + ' --package music')]
- mock_run_shell_command.assert_has_calls(calls)
-
-def test_parse_metrics_output():
- input = 'a1=b1\nc1=d1\ne1=f1'
- ret = RUNNER.parse_metrics_output(input)
-
- assert ret == [('a1', 'b1'), ('c1', 'd1'), ('e1', 'f1')]
-
-def _mocked_run_shell_command(*args, **kwargs):
- if args[0] == 'adb shell "date -u +\'%Y-%m-%d %H:%M:%S.%N\'"':
- return (True, "2019-07-02 23:20:06.972674825")
- elif args[0] == 'adb shell ps | grep "music" | awk \'{print $2;}\'':
- return (True, '9999')
- else:
- return (True, 'a1=b1\nc1=d1=d2\ne1=f1')
-
-@patch('app_startup.lib.adb_utils.blocking_wait_for_logcat_displayed_time')
-@patch('lib.cmd_utils.run_shell_command')
-def test_run(mock_run_shell_command,
- mock_blocking_wait_for_logcat_displayed_time):
- mock_run_shell_command.side_effect = _mocked_run_shell_command
- mock_blocking_wait_for_logcat_displayed_time.return_value = 123
-
- test_listener = AppRunnerTestListener()
- RUNNER.add_callbacks(test_listener)
-
- result = RUNNER.run()
-
- RUNNER.remove_callbacks(test_listener)
-
- calls = [call('pre'),
- call(os.path.realpath(
- os.path.join(RUNNER.DIR,
- '../query_compiler_filter.py')) +
- ' --package music'),
- call('adb shell "date -u +\'%Y-%m-%d %H:%M:%S.%N\'"'),
- call(
- 'timeout {timeout} "{DIR}/launch_application" "{package}" "{activity}"'
- .format(timeout=30,
- DIR=os.path.realpath(os.path.dirname(RUNNER.DIR)),
- package='music',
- activity='MainActivity',
- timestamp='2019-07-02 23:20:06.972674825')),
- call('post')
- ]
- mock_run_shell_command.assert_has_calls(calls)
- assert result == [('TotalTime', '123')]
- assert len(RUNNER.listeners) == 0 \ No newline at end of file
diff --git a/startop/scripts/app_startup/lib/args_utils.py b/startop/scripts/app_startup/lib/args_utils.py
deleted file mode 100644
index 080f3b53157b..000000000000
--- a/startop/scripts/app_startup/lib/args_utils.py
+++ /dev/null
@@ -1,77 +0,0 @@
-import itertools
-import os
-import sys
-from typing import Any, Callable, Dict, Iterable, List, NamedTuple, Tuple, \
- TypeVar, Optional
-
-# local import
-sys.path.append(os.path.dirname(os.path.dirname(os.path.dirname(
- os.path.abspath(__file__)))))
-import lib.print_utils as print_utils
-
-T = TypeVar('T')
-NamedTupleMeta = Callable[
- ..., T] # approximation of a (S : NamedTuple<T> where S() == T) metatype.
-FilterFuncType = Callable[[NamedTuple], bool]
-
-def dict_lookup_any_key(dictionary: dict, *keys: List[Any]):
- for k in keys:
- if k in dictionary:
- return dictionary[k]
-
-
- print_utils.debug_print("None of the keys {} were in the dictionary".format(
- keys))
- return [None]
-
-def generate_run_combinations(named_tuple: NamedTupleMeta[T],
- opts_dict: Dict[str, List[Optional[object]]],
- loop_count: int = 1) -> Iterable[T]:
- """
- Create all possible combinations given the values in opts_dict[named_tuple._fields].
-
- :type T: type annotation for the named_tuple type.
- :param named_tuple: named tuple type, whose fields are used to make combinations for
- :param opts_dict: dictionary of keys to value list. keys correspond to the named_tuple fields.
- :param loop_count: number of repetitions.
- :return: an iterable over named_tuple instances.
- """
- combinations_list = []
- for k in named_tuple._fields:
- # the key can be either singular or plural , e.g. 'package' or 'packages'
- val = dict_lookup_any_key(opts_dict, k, k + "s")
-
- # treat {'x': None} key value pairs as if it was [None]
- # otherwise itertools.product throws an exception about not being able to iterate None.
- combinations_list.append(val or [None])
-
- print_utils.debug_print("opts_dict: ", opts_dict)
- print_utils.debug_print_nd("named_tuple: ", named_tuple)
- print_utils.debug_print("combinations_list: ", combinations_list)
-
- for i in range(loop_count):
- for combo in itertools.product(*combinations_list):
- yield named_tuple(*combo)
-
-def filter_run_combinations(named_tuple: NamedTuple,
- filters: List[FilterFuncType]) -> bool:
- for filter in filters:
- if filter(named_tuple):
- return False
- return True
-
-def generate_group_run_combinations(run_combinations: Iterable[NamedTuple],
- dst_nt: NamedTupleMeta[T]) \
- -> Iterable[Tuple[T, Iterable[NamedTuple]]]:
- def group_by_keys(src_nt):
- src_d = src_nt._asdict()
- # now remove the keys that aren't legal in dst.
- for illegal_key in set(src_d.keys()) - set(dst_nt._fields):
- if illegal_key in src_d:
- del src_d[illegal_key]
-
- return dst_nt(**src_d)
-
- for args_list_it in itertools.groupby(run_combinations, group_by_keys):
- (group_key_value, args_it) = args_list_it
- yield (group_key_value, args_it)
diff --git a/startop/scripts/app_startup/lib/args_utils_test.py b/startop/scripts/app_startup/lib/args_utils_test.py
deleted file mode 100644
index 4b7e0fa20627..000000000000
--- a/startop/scripts/app_startup/lib/args_utils_test.py
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 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.
-#
-
-"""Unit tests for the args_utils.py script."""
-
-import typing
-
-import args_utils
-
-def generate_run_combinations(*args):
- # expand out the generator values so that assert x == y works properly.
- return [i for i in args_utils.generate_run_combinations(*args)]
-
-def test_generate_run_combinations():
- blank_nd = typing.NamedTuple('Blank')
- assert generate_run_combinations(blank_nd, {}, 1) == [()], "empty"
- assert generate_run_combinations(blank_nd, {'a': ['a1', 'a2']}) == [
- ()], "empty filter"
- a_nd = typing.NamedTuple('A', [('a', str)])
- assert generate_run_combinations(a_nd, {'a': None}) == [(None,)], "None"
- assert generate_run_combinations(a_nd, {'a': ['a1', 'a2']}) == [('a1',), (
- 'a2',)], "one item"
- assert generate_run_combinations(a_nd,
- {'a': ['a1', 'a2'], 'b': ['b1', 'b2']}) == [
- ('a1',), ('a2',)], \
- "one item filter"
- assert generate_run_combinations(a_nd, {'a': ['a1', 'a2']}, 2) == [('a1',), (
- 'a2',), ('a1',), ('a2',)], "one item"
- ab_nd = typing.NamedTuple('AB', [('a', str), ('b', str)])
- assert generate_run_combinations(ab_nd,
- {'a': ['a1', 'a2'],
- 'b': ['b1', 'b2']}) == [ab_nd('a1', 'b1'),
- ab_nd('a1', 'b2'),
- ab_nd('a2', 'b1'),
- ab_nd('a2', 'b2')], \
- "two items"
-
- assert generate_run_combinations(ab_nd,
- {'as': ['a1', 'a2'],
- 'bs': ['b1', 'b2']}) == [ab_nd('a1', 'b1'),
- ab_nd('a1', 'b2'),
- ab_nd('a2', 'b1'),
- ab_nd('a2', 'b2')], \
- "two items plural"
diff --git a/startop/scripts/app_startup/lib/common b/startop/scripts/app_startup/lib/common
deleted file mode 100755
index bedaa1e10288..000000000000
--- a/startop/scripts/app_startup/lib/common
+++ /dev/null
@@ -1,198 +0,0 @@
-#!/bin/bash
-# Copyright 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.
-
-if [[ -z $ANDROID_BUILD_TOP ]]; then
- echo "Please run source build/envsetup.sh first" >&2
- exit 1
-fi
-
-source $ANDROID_BUILD_TOP/build/envsetup.sh
-
-verbose_print() {
- if [[ "$verbose" == "y" ]]; then
- echo "$@" >&2
- fi
-}
-
-remote_pidof() {
- local procname="$1"
- adb shell ps | grep "$procname" | awk '{print $2;}'
-}
-
-remote_pkill() {
- local procname="$1"
- shift
-
- local the_pids=$(remote_pidof "$procname")
- local pid
-
- for pid in $the_pids; do
- verbose_print adb shell kill "$@" "$pid"
- adb shell kill "$@" "$pid"
- done
-}
-
-get_activity_name() {
- local package="$1"
- local action_key="android.intent.action.MAIN:"
-
- # Example query-activities output being parsed:
- #
- # Activity #14:
- # priority=0 preferredOrder=0 match=0x108000 specificIndex=-1 isDefault=true
- # com.google.android.videos/com.google.android.youtube.videos.EntryPoint
- # Activity #15:
- # priority=0 preferredOrder=0 match=0x108000 specificIndex=-1 isDefault=true
- # com.google.android.youtube/.app.honeycomb.Shell$HomeActivity
-
- # Given package 'com.google.android.youtube' return '.app.honeycomb.Shell$HomeActivity'
-
- local activity_line="$(adb shell cmd package query-activities --brief -a android.intent.action.MAIN -c android.intent.category.LAUNCHER | grep "$package/")"
- IFS="/" read -a array <<< "$activity_line"
- local activity_name="${array[1]}"
-
- # Activities starting with '.' are shorthand for having their package name prefixed.
- if [[ $activity_name == .* ]]; then
- activity_name="${package}${activity_name}"
- fi
- echo "$activity_name"
-}
-
-# Use with logcat_from_timestamp to skip all past log-lines.
-logcat_save_timestamp() {
- adb shell 'date -u +"%Y-%m-%d %H:%M:%S.%N"'
-}
-
-# Roll forward logcat to only show events
-# since the specified timestamp.
-#
-# i.e. don't look at historical logcat,
-# only look at FUTURE logcat.
-#
-# First use 'logcat_save_timestamp'
-# Then do whatever action you want.
-# Then use 'logcat_from_timestamp_bg $timestamp'
-logcat_from_timestamp_bg() {
- local timestamp="$1"
- shift # drop timestamp from args.
- verbose_print adb logcat -T \"$timestamp\" \"$@\"
- adb logcat -v UTC -T "$timestamp" "$@" &
- logcat_from_timestamp_pid=$!
-}
-
-# Starting at timestamp $2, wait until we seen pattern $3
-# or until a timeout happens in $1 seconds.
-# If successful, also echo the line that matched the pattern.
-#
-# Set VERBOSE_LOGCAT=1 to debug every line of logcat it tries to parse.
-logcat_select_pattern() {
- local timeout="$1"
- local timestamp="$2"
- local pattern="$3"
-
- local logcat_fd
-
- coproc logcat_fd {
- kill_children_quietly() {
- kill "$logcat_pidd"
- wait "$logcat_pidd" 2>/dev/null
- }
-
- trap 'kill_children_quietly' EXIT # kill logcat when this coproc is killed.
-
- # run logcat in the background so it can be killed.
- logcat_from_timestamp_bg "$timestamp"
- logcat_pidd=$logcat_from_timestamp_pid
- wait "$logcat_pidd"
- }
- local logcat_pid="$!"
- verbose_print "[LOGCAT] Spawn pid $logcat_pid"
-
- local timeout_ts="$(date -d "now + ${timeout} seconds" '+%s')"
- local now_ts="0"
-
- local return_code=1
-
- verbose_print "logcat_wait_for_pattern begin"
-
- while read -t "$timeout" -r -u "${logcat_fd[0]}" logcat_output; do
- if (( $VERBOSE_LOGCAT )); then
- verbose_print "LOGCAT: $logcat_output"
- fi
- if [[ "$logcat_output:" == *"$pattern"* ]]; then
- verbose_print "LOGCAT: " "$logcat_output"
- verbose_print "WE DID SEE PATTERN" '<<' "$pattern" '>>.'
- echo "$logcat_output"
- return_code=0
- break
- fi
- now_ts="$(date -d "now" '+%s')"
- if (( now_ts >= timeout_ts )); then
- verbose_print "DID TIMEOUT BEFORE SEEING ANYTHING (timeout=$timeout seconds) " '<<' "$pattern" '>>.'
- break
- fi
- done
-
- # Don't leave logcat lying around since it will keep going.
- kill "$logcat_pid"
- # Suppress annoying 'Terminated...' message.
- wait "$logcat_pid" 2>/dev/null
-
- verbose_print "[LOGCAT] $logcat_pid should be killed"
-
- return $return_code
-}
-
-# Starting at timestamp $2, wait until we seen pattern $3
-# or until a timeout happens in $1 seconds.
-#
-# Set VERBOSE_LOGCAT=1 to debug every line of logcat it tries to parse.
-logcat_wait_for_pattern() {
- logcat_select_pattern "$@" > /dev/null
-}
-
-# Starting at timestamp $2, wait until we seen pattern $3
-# or until a timeout happens in $1 seconds.
-# If successful, extract with the regular expression pattern in #4
-# and return the first capture group.
-#
-# Set VERBOSE_LOGCAT=1 to debug every line of logcat it tries to parse.
-logcat_extract_pattern() {
- local timeout="$1"
- local timestamp="$2"
- local pattern="$3"
- local re_pattern="$4"
-
- local result
- local exit_code
-
- result="$(logcat_select_pattern "$@")"
- exit_code=$?
-
- if [[ $exit_code -ne 0 ]]; then
- return $exit_code
- fi
-
- echo "$result" | sed 's/'"$re_pattern"'/\1/g'
-}
-
-# Join array
-# FOO=(a b c)
-# join_by , "${FOO[@]}" #a,b,c
-join_by() {
- local IFS="$1"
- shift
- echo "$*"
-}
diff --git a/startop/scripts/app_startup/lib/data_frame.py b/startop/scripts/app_startup/lib/data_frame.py
deleted file mode 100644
index 20a2308637f2..000000000000
--- a/startop/scripts/app_startup/lib/data_frame.py
+++ /dev/null
@@ -1,201 +0,0 @@
-import itertools
-from typing import Dict, List
-
-class DataFrame:
- """Table-like class for storing a 2D cells table with named columns."""
- def __init__(self, data: Dict[str, List[object]] = {}):
- """
- Create a new DataFrame from a dictionary (keys = headers,
- values = columns).
- """
- self._headers = [i for i in data.keys()]
- self._rows = []
-
- row_num = 0
-
- def get_data_row(idx):
- r = {}
- for header, header_data in data.items():
-
- if not len(header_data) > idx:
- continue
-
- r[header] = header_data[idx]
-
- return r
-
- while True:
- row_dict = get_data_row(row_num)
- if len(row_dict) == 0:
- break
-
- self._append_row(row_dict.keys(), row_dict.values())
- row_num = row_num + 1
-
- def concat_rows(self, other: 'DataFrame') -> None:
- """
- In-place concatenate rows of other into the rows of the
- current DataFrame.
-
- None is added in pre-existing cells if new headers
- are introduced.
- """
- other_datas = other._data_only()
-
- other_headers = other.headers
-
- for d in other_datas:
- self._append_row(other_headers, d)
-
- def _append_row(self, headers: List[str], data: List[object]):
- new_row = {k:v for k,v in zip(headers, data)}
- self._rows.append(new_row)
-
- for header in headers:
- if not header in self._headers:
- self._headers.append(header)
-
- def __repr__(self):
-# return repr(self._rows)
- repr = ""
-
- header_list = self._headers_only()
-
- row_format = u""
- for header in header_list:
- row_format = row_format + u"{:>%d}" %(len(header) + 1)
-
- repr = row_format.format(*header_list) + "\n"
-
- for v in self._data_only():
- repr = repr + row_format.format(*v) + "\n"
-
- return repr
-
- def __eq__(self, other):
- if isinstance(other, self.__class__):
- return self.headers == other.headers and self.data_table == other.data_table
- else:
- print("wrong instance", other.__class__)
- return False
-
- @property
- def headers(self) -> List[str]:
- return [i for i in self._headers_only()]
-
- @property
- def data_table(self) -> List[List[object]]:
- return list(self._data_only())
-
- @property
- def data_table_transposed(self) -> List[List[object]]:
- return list(self._transposed_data())
-
- @property
- def data_row_len(self) -> int:
- return len(self._rows)
-
- def data_row_at(self, idx) -> List[object]:
- """
- Return a single data row at the specified index (0th based).
-
- Accepts negative indices, e.g. -1 is last row.
- """
- row_dict = self._rows[idx]
- l = []
-
- for h in self._headers_only():
- l.append(row_dict.get(h)) # Adds None in blank spots.
-
- return l
-
- def copy(self) -> 'DataFrame':
- """
- Shallow copy of this DataFrame.
- """
- return self.repeat(count=0)
-
- def repeat(self, count: int) -> 'DataFrame':
- """
- Returns a new DataFrame where each row of this dataframe is repeated count times.
- A repeat of a row is adjacent to other repeats of that same row.
- """
- df = DataFrame()
- df._headers = self._headers.copy()
-
- rows = []
- for row in self._rows:
- for i in range(count):
- rows.append(row.copy())
-
- df._rows = rows
-
- return df
-
- def merge_data_columns(self, other: 'DataFrame'):
- """
- Merge self and another DataFrame by adding the data from other column-wise.
- For any headers that are the same, data from 'other' is preferred.
- """
- for h in other._headers:
- if not h in self._headers:
- self._headers.append(h)
-
- append_rows = []
-
- for self_dict, other_dict in itertools.zip_longest(self._rows, other._rows):
- if not self_dict:
- d = {}
- append_rows.append(d)
- else:
- d = self_dict
-
- d_other = other_dict
- if d_other:
- for k,v in d_other.items():
- d[k] = v
-
- for r in append_rows:
- self._rows.append(r)
-
- def data_row_reduce(self, fnc) -> 'DataFrame':
- """
- Reduces the data row-wise by applying the fnc to each row (column-wise).
- Empty cells are skipped.
-
- fnc(Iterable[object]) -> object
- fnc is applied over every non-empty cell in that column (descending row-wise).
-
- Example:
- DataFrame({'a':[1,2,3]}).data_row_reduce(sum) == DataFrame({'a':[6]})
-
- Returns a new single-row DataFrame.
- """
- df = DataFrame()
- df._headers = self._headers.copy()
-
- def yield_by_column(header_key):
- for row_dict in self._rows:
- val = row_dict.get(header_key)
- if val:
- yield val
-
- new_row_dict = {}
- for h in df._headers:
- cell_value = fnc(yield_by_column(h))
- new_row_dict[h] = cell_value
-
- df._rows = [new_row_dict]
- return df
-
- def _headers_only(self):
- return self._headers
-
- def _data_only(self):
- row_len = len(self._rows)
-
- for i in range(row_len):
- yield self.data_row_at(i)
-
- def _transposed_data(self):
- return zip(*self._data_only()) \ No newline at end of file
diff --git a/startop/scripts/app_startup/lib/data_frame_test.py b/startop/scripts/app_startup/lib/data_frame_test.py
deleted file mode 100644
index 1cbc1cbe45cb..000000000000
--- a/startop/scripts/app_startup/lib/data_frame_test.py
+++ /dev/null
@@ -1,128 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 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.
-#
-
-"""Unit tests for the data_frame.py script."""
-
-from data_frame import DataFrame
-
-def test_data_frame():
- # trivial empty data frame
- df = DataFrame()
- assert df.headers == []
- assert df.data_table == []
- assert df.data_table_transposed == []
-
- # common case, same number of values in each place.
- df = DataFrame({'TotalTime_ms': [1, 2, 3], 'Displayed_ms': [4, 5, 6]})
- assert df.headers == ['TotalTime_ms', 'Displayed_ms']
- assert df.data_table == [[1, 4], [2, 5], [3, 6]]
- assert df.data_table_transposed == [(1, 2, 3), (4, 5, 6)]
-
- # varying num values.
- df = DataFrame({'many': [1, 2], 'none': []})
- assert df.headers == ['many', 'none']
- assert df.data_table == [[1, None], [2, None]]
- assert df.data_table_transposed == [(1, 2), (None, None)]
-
- df = DataFrame({'many': [], 'none': [1, 2]})
- assert df.headers == ['many', 'none']
- assert df.data_table == [[None, 1], [None, 2]]
- assert df.data_table_transposed == [(None, None), (1, 2)]
-
- # merge multiple data frames
- df = DataFrame()
- df.concat_rows(DataFrame())
- assert df.headers == []
- assert df.data_table == []
- assert df.data_table_transposed == []
-
- df = DataFrame()
- df2 = DataFrame({'TotalTime_ms': [1, 2, 3], 'Displayed_ms': [4, 5, 6]})
-
- df.concat_rows(df2)
- assert df.headers == ['TotalTime_ms', 'Displayed_ms']
- assert df.data_table == [[1, 4], [2, 5], [3, 6]]
- assert df.data_table_transposed == [(1, 2, 3), (4, 5, 6)]
-
- df = DataFrame({'TotalTime_ms': [1, 2]})
- df2 = DataFrame({'Displayed_ms': [4, 5]})
-
- df.concat_rows(df2)
- assert df.headers == ['TotalTime_ms', 'Displayed_ms']
- assert df.data_table == [[1, None], [2, None], [None, 4], [None, 5]]
-
- df = DataFrame({'TotalTime_ms': [1, 2]})
- df2 = DataFrame({'TotalTime_ms': [3, 4], 'Displayed_ms': [5, 6]})
-
- df.concat_rows(df2)
- assert df.headers == ['TotalTime_ms', 'Displayed_ms']
- assert df.data_table == [[1, None], [2, None], [3, 5], [4, 6]]
-
- # data_row_at
- df = DataFrame({'TotalTime_ms': [1, 2, 3], 'Displayed_ms': [4, 5, 6]})
- assert df.data_row_at(-1) == [3, 6]
- assert df.data_row_at(2) == [3, 6]
- assert df.data_row_at(1) == [2, 5]
-
- # repeat
- df = DataFrame({'TotalTime_ms': [1], 'Displayed_ms': [4]})
- df2 = DataFrame({'TotalTime_ms': [1, 1, 1], 'Displayed_ms': [4, 4, 4]})
- assert df.repeat(3) == df2
-
- # repeat
- df = DataFrame({'TotalTime_ms': [1, 1, 1], 'Displayed_ms': [4, 4, 4]})
- assert df.data_row_len == 3
- df = DataFrame({'TotalTime_ms': [1, 1]})
- assert df.data_row_len == 2
-
- # repeat
- df = DataFrame({'TotalTime_ms': [1, 1, 1], 'Displayed_ms': [4, 4, 4]})
- assert df.data_row_len == 3
- df = DataFrame({'TotalTime_ms': [1, 1]})
- assert df.data_row_len == 2
-
- # data_row_reduce
- df = DataFrame({'TotalTime_ms': [1, 1, 1], 'Displayed_ms': [4, 4, 4]})
- df_sum = DataFrame({'TotalTime_ms': [3], 'Displayed_ms': [12]})
- assert df.data_row_reduce(sum) == df_sum
-
- # merge_data_columns
- df = DataFrame({'TotalTime_ms': [1, 2, 3]})
- df2 = DataFrame({'Displayed_ms': [3, 4, 5, 6]})
-
- df.merge_data_columns(df2)
- assert df == DataFrame(
- {'TotalTime_ms': [1, 2, 3], 'Displayed_ms': [3, 4, 5, 6]})
-
- df = DataFrame({'TotalTime_ms': [1, 2, 3]})
- df2 = DataFrame({'Displayed_ms': [3, 4]})
-
- df.merge_data_columns(df2)
- assert df == DataFrame(
- {'TotalTime_ms': [1, 2, 3], 'Displayed_ms': [3, 4]})
-
- df = DataFrame({'TotalTime_ms': [1, 2, 3]})
- df2 = DataFrame({'TotalTime_ms': [10, 11]})
-
- df.merge_data_columns(df2)
- assert df == DataFrame({'TotalTime_ms': [10, 11, 3]})
-
- df = DataFrame({'TotalTime_ms': []})
- df2 = DataFrame({'TotalTime_ms': [10, 11]})
-
- df.merge_data_columns(df2)
- assert df == DataFrame({'TotalTime_ms': [10, 11]})
diff --git a/startop/scripts/app_startup/lib/perfetto_trace_collector.py b/startop/scripts/app_startup/lib/perfetto_trace_collector.py
deleted file mode 100644
index 9ffb3494da49..000000000000
--- a/startop/scripts/app_startup/lib/perfetto_trace_collector.py
+++ /dev/null
@@ -1,166 +0,0 @@
-# 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.
-
-"""Class to collector perfetto trace."""
-import datetime
-import os
-import re
-import sys
-import time
-from datetime import timedelta
-from typing import Optional, List, Tuple
-
-# global variables
-DIR = os.path.abspath(os.path.dirname(__file__))
-
-sys.path.append(os.path.dirname(os.path.dirname(DIR)))
-
-import app_startup.lib.adb_utils as adb_utils
-from app_startup.lib.app_runner import AppRunner, AppRunnerListener
-import lib.print_utils as print_utils
-import lib.logcat_utils as logcat_utils
-import iorap.lib.iorapd_utils as iorapd_utils
-
-class PerfettoTraceCollector(AppRunnerListener):
- """ Class to collect perfetto trace.
-
- To set trace duration of perfetto, change the 'trace_duration_ms'.
- To pull the generated perfetto trace on device, set the 'output'.
- """
- TRACE_FILE_SUFFIX = 'perfetto_trace.pb'
- TRACE_DURATION_PROP = 'iorapd.perfetto.trace_duration_ms'
- MS_PER_SEC = 1000
- DEFAULT_TRACE_DURATION = timedelta(milliseconds=5000) # 5 seconds
- _COLLECTOR_TIMEOUT_MULTIPLIER = 10 # take the regular timeout and multiply
-
- def __init__(self,
- package: str,
- activity: Optional[str],
- compiler_filter: Optional[str],
- timeout: Optional[int],
- simulate: bool,
- trace_duration: timedelta = DEFAULT_TRACE_DURATION,
- save_destination_file_path: Optional[str] = None):
- """ Initialize the perfetto trace collector. """
- self.app_runner = AppRunner(package,
- activity,
- compiler_filter,
- timeout,
- simulate)
- self.app_runner.add_callbacks(self)
-
- self.trace_duration = trace_duration
- self.save_destination_file_path = save_destination_file_path
-
- def purge_file(self, suffix: str) -> None:
- print_utils.debug_print('iorapd-perfetto: purge file in ' +
- self._get_remote_path())
- adb_utils.delete_file_on_device(self._get_remote_path())
-
- def run(self) -> Optional[List[Tuple[str]]]:
- """Runs an app.
-
- Returns:
- A list of (metric, value) tuples.
- """
- return self.app_runner.run()
-
- def preprocess(self):
- # Sets up adb environment.
- adb_utils.root()
- adb_utils.disable_selinux()
- time.sleep(1)
-
- # Kill any existing process of this app
- adb_utils.pkill(self.app_runner.package)
-
- # Remove existing trace and compiler files
- self.purge_file(PerfettoTraceCollector.TRACE_FILE_SUFFIX)
-
- # Set perfetto trace duration prop to milliseconds.
- adb_utils.set_prop(PerfettoTraceCollector.TRACE_DURATION_PROP,
- int(self.trace_duration.total_seconds()*
- PerfettoTraceCollector.MS_PER_SEC))
-
- if not iorapd_utils.stop_iorapd():
- raise RuntimeError('Cannot stop iorapd!')
-
- if not iorapd_utils.enable_iorapd_perfetto():
- raise RuntimeError('Cannot enable perfetto!')
-
- if not iorapd_utils.disable_iorapd_readahead():
- raise RuntimeError('Cannot disable readahead!')
-
- if not iorapd_utils.start_iorapd():
- raise RuntimeError('Cannot start iorapd!')
-
- # Drop all caches to get cold starts.
- adb_utils.vm_drop_cache()
-
- def postprocess(self, pre_launch_timestamp: str):
- # Kill any existing process of this app
- adb_utils.pkill(self.app_runner.package)
-
- iorapd_utils.disable_iorapd_perfetto()
-
- if self.save_destination_file_path is not None:
- adb_utils.pull_file(self._get_remote_path(),
- self.save_destination_file_path)
-
- def metrics_selector(self, am_start_output: str,
- pre_launch_timestamp: str) -> str:
- """Parses the metric after app startup by reading from logcat in a blocking
- manner until all metrics have been found".
-
- Returns:
- An empty string because the metric needs no further parsing.
- """
- if not self._wait_for_perfetto_trace(pre_launch_timestamp):
- raise RuntimeError('Could not save perfetto app trace file!')
-
- return ''
-
- def _wait_for_perfetto_trace(self, pre_launch_timestamp) -> Optional[str]:
- """ Waits for the perfetto trace being saved to file.
-
- The string is in the format of r".*Perfetto TraceBuffer saved to file:
- <file path>.*"
-
- Returns:
- the string what the program waits for. If the string doesn't show up,
- return None.
- """
- pattern = re.compile(r'.*Perfetto TraceBuffer saved to file: {}.*'.
- format(self._get_remote_path()))
-
- # The pre_launch_timestamp is longer than what the datetime can parse. Trim
- # last three digits to make them align. For example:
- # 2019-07-02 23:20:06.972674825999 -> 2019-07-02 23:20:06.972674825
- assert len(pre_launch_timestamp) == len('2019-07-02 23:20:06.972674825')
- timestamp = datetime.datetime.strptime(pre_launch_timestamp[:-3],
- '%Y-%m-%d %H:%M:%S.%f')
-
- # The timeout of perfetto trace is longer than the normal app run timeout.
- timeout_dt = self.app_runner.timeout * PerfettoTraceCollector._COLLECTOR_TIMEOUT_MULTIPLIER
- timeout_end = timestamp + datetime.timedelta(seconds=timeout_dt)
-
- return logcat_utils.blocking_wait_for_logcat_pattern(timestamp,
- pattern,
- timeout_end)
-
- def _get_remote_path(self):
- # For example: android.music%2Fmusic.TopLevelActivity.perfetto_trace.pb
- return iorapd_utils._iorapd_path_to_data_file(self.app_runner.package,
- self.app_runner.activity,
- PerfettoTraceCollector.TRACE_FILE_SUFFIX)
diff --git a/startop/scripts/app_startup/lib/perfetto_trace_collector_test.py b/startop/scripts/app_startup/lib/perfetto_trace_collector_test.py
deleted file mode 100644
index 8d94fc58bede..000000000000
--- a/startop/scripts/app_startup/lib/perfetto_trace_collector_test.py
+++ /dev/null
@@ -1,101 +0,0 @@
-#!/usr/bin/env python3
-#
-# 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.
-#
-
-"""Unit tests for the data_frame.py script."""
-import os
-import sys
-from pathlib import Path
-from datetime import timedelta
-
-from mock import call, patch
-from perfetto_trace_collector import PerfettoTraceCollector
-
-sys.path.append(Path(os.path.realpath(__file__)).parents[2])
-from app_startup.lib.app_runner import AppRunner
-
-RUNNER = PerfettoTraceCollector(package='music',
- activity='MainActivity',
- compiler_filter=None,
- timeout=10,
- simulate=False,
- trace_duration = timedelta(milliseconds=1000),
- # No actual file will be created. Just to
- # check the command.
- save_destination_file_path='/tmp/trace.pb')
-
-def _mocked_run_shell_command(*args, **kwargs):
- if args[0] == 'adb shell ps | grep "music" | awk \'{print $2;}\'':
- return (True, '9999')
- else:
- return (True, '')
-
-@patch('lib.logcat_utils.blocking_wait_for_logcat_pattern')
-@patch('lib.cmd_utils.run_shell_command')
-def test_perfetto_trace_collector_preprocess(mock_run_shell_command,
- mock_blocking_wait_for_logcat_pattern):
- mock_run_shell_command.side_effect = _mocked_run_shell_command
- mock_blocking_wait_for_logcat_pattern.return_value = "Succeed!"
-
- RUNNER.preprocess()
-
- calls = [call('adb root'),
- call('adb shell "getenforce"'),
- call('adb shell "setenforce 0"'),
- call('adb shell "stop"'),
- call('adb shell "start"'),
- call('adb wait-for-device'),
- call('adb shell ps | grep "music" | awk \'{print $2;}\''),
- call('adb shell "kill 9999"'),
- call(
- 'adb shell "[[ -f \'/data/misc/iorapd/music%2FMainActivity.perfetto_trace.pb\' ]] '
- '&& rm -f \'/data/misc/iorapd/music%2FMainActivity.perfetto_trace.pb\' || exit 0"'),
- call('adb shell "setprop "iorapd.perfetto.trace_duration_ms" "1000""'),
- call(
- 'bash -c "source {}; iorapd_stop"'.format(
- AppRunner.IORAP_COMMON_BASH_SCRIPT)),
- call(
- 'bash -c "source {}; iorapd_perfetto_enable"'.format(
- AppRunner.IORAP_COMMON_BASH_SCRIPT)),
- call(
- 'bash -c "source {}; iorapd_readahead_disable"'.format(
- AppRunner.IORAP_COMMON_BASH_SCRIPT)),
- call(
- 'bash -c "source {}; iorapd_start"'.format(
- AppRunner.IORAP_COMMON_BASH_SCRIPT)),
- call('adb shell "echo 3 > /proc/sys/vm/drop_caches"')]
-
- mock_run_shell_command.assert_has_calls(calls)
-
-@patch('lib.logcat_utils.blocking_wait_for_logcat_pattern')
-@patch('lib.cmd_utils.run_shell_command')
-def test_perfetto_trace_collector_postprocess(mock_run_shell_command,
- mock_blocking_wait_for_logcat_pattern):
- mock_run_shell_command.side_effect = _mocked_run_shell_command
- mock_blocking_wait_for_logcat_pattern.return_value = "Succeed!"
-
- RUNNER.postprocess('2019-07-02 23:20:06.972674825')
-
- calls = [call('adb shell ps | grep "music" | awk \'{print $2;}\''),
- call('adb shell "kill 9999"'),
- call(
- 'bash -c "source {}; iorapd_perfetto_disable"'.format(
- AppRunner.IORAP_COMMON_BASH_SCRIPT)),
- call('adb pull '
- '"/data/misc/iorapd/music%2FMainActivity.perfetto_trace.pb" '
- '"/tmp/trace.pb"')]
-
- mock_run_shell_command.assert_has_calls(calls)
diff --git a/startop/scripts/app_startup/parse_metrics b/startop/scripts/app_startup/parse_metrics
deleted file mode 100755
index 3fa1462bc56e..000000000000
--- a/startop/scripts/app_startup/parse_metrics
+++ /dev/null
@@ -1,215 +0,0 @@
-#!/bin/bash
-#
-# 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.
-
-usage() {
- cat <<EOF
-Usage: launch_application package activity | parse_metrics --package <name> --timestamp <timestamp> [OPTIONS]...
-
- Reads from stdin the result of 'am start' metrics. May also parse logcat
- for additional metrics.
-
- Output form:
-
- MetricName_unit=numeric_value
- MetricName2_unit=numeric_value2
-
- This may block until all desired metrics are parsed from logcat.
- To get a list of metrics without doing real parsing, use --simulate.
-
- To add package-specific metrics, add a script called 'metrics/\$full_package_name'
- that exposes additional metrics in same way as above.
-
- (required)
- -p, --package <name> package of the app that is being used
- -ts, --timestamp <name> logcat timestamp [only looks at logcat entries after this timestamp].
-
- (optional)
- -s, --simulate prints dummy values instead of real metrics
- -a, --activity <name> activity to use (default: inferred)
- -h, --help usage information (this)
- -v, --verbose enable extra verbose printing
- -t, --timeout <sec> how many seconds to timeout when trying to wait for logcat to change
- -rfd, --reportfullydrawn wait for report fully drawn (default: off)
-EOF
-}
-
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-source "$DIR/lib/common"
-
-report_fully_drawn="n"
-package=""
-activity=""
-timeout=5
-simulate="n"
-parse_arguments() {
- while [[ $# -gt 0 ]]; do
- case "$1" in
- -h|--help)
- usage
- exit 0
- ;;
- -p|--package)
- package="$2"
- shift
- ;;
- -a|--activity)
- activity="$2"
- shift
- ;;
- -v|--verbose)
- export verbose="y"
- ;;
- -t|--timeout)
- timeout="$2"
- shift
- ;;
- -ts|--timestamp)
- timestamp="$2"
- shift
- ;;
- -s|--simulate)
- simulate="y"
- ;;
- -rfd|--reportfullydrawn)
- report_fully_drawn="y"
- ;;
-
-
- *)
- echo "Invalid argument: $1" >&2
- exit 1
- esac
- shift
- done
-}
-
-# Main entry point
-if [[ $# -eq 0 ]]; then
- usage
- exit 1
-else
- parse_arguments "$@"
-
- # if we do not have have package exit early with an error
- [[ "$package" == "" ]] && echo "--package not specified" 1>&2 && exit 64
-
- # ignore timestamp for --simulate. it's optional.
- if [[ $simulate == y ]]; then
- timestamp=0
- fi
-
- # if we do not have timestamp, exit early with an error
- [[ "$timestamp" == "" ]] && echo "--timestamp not specified" 1>&2 && exit 64
-
- if [[ "$activity" == "" ]] && [[ "$simulate" != "y" ]]; then
- activity="$(get_activity_name "$package")"
- if [[ "$activity" == "" ]]; then
- echo "Activity name could not be found, invalid package name?" 1>&2
- exit 64
- else
- verbose_print "Activity name inferred: " "$activity"
- fi
- fi
-fi
-
-parse_metric_from_logcat() {
- local metric_name="$1"
- local pattern="$2"
- local re_pattern="$3"
- local retcode
- local result
- local sec
- local ms
-
- # parse logcat for 'Displayed...' and that other one...
-
- # 05-06 14:34:08.854 29460 29481 I ActivityTaskManager: Displayed com.google.android.dialer/.extensions.GoogleDialtactsActivity: +361ms
- verbose_print "parse_metric_from_logcat: $re_pattern"
-
-
- echo -ne "$metric_name="
-
- if [[ $simulate == y ]]; then
- echo "-1"
- return 0
- fi
-
- result="$(logcat_extract_pattern "$timeout" "$timestamp" "$pattern" "$re_pattern")"
- retcode=$?
-
- if [[ $retcode -ne 0 ]]; then
- # Timed out before finding the pattern. Could also mean the pattern is wrong.
- echo "Parse $re_pattern from logcat TIMED OUT after $timeout seconds." >&2
- echo "-$?"
- return $retcode
- fi
-
- # "10s123ms" -> "10s123"
- result=${result/ms/}
- if [[ $result =~ s ]]; then
- ms=${result/*s/}
- sec=${result/s*/}
- else
- sec=0
- ms=$result
- fi
- ((result=sec*1000+ms))
-
- echo "$result"
- return $retcode
-}
-
-
-total_time="-1"
-if [[ $simulate != y ]]; then
- verbose_print 'logcat timestamp NOW: ' $(logcat_save_timestamp)
-
- # parse stdin for 'am start' result
- while read -t "$timeout" -r input_line; do
- verbose_print 'stdin:' "$input_line"
- if [[ $input_line == *TotalTime:* ]]; then
- total_time="$(echo "$input_line" | sed 's/TotalTime: \([[:digit:]]\+\)/\1/g')"
- # but keep reading the rest from stdin until <EOF>
- fi
- done
-fi
-
-echo "TotalTime_ms=$total_time"
-
-# parse logcat for 'Displayed...' and that other one...
-
-# 05-06 14:34:08.854 29460 29481 I ActivityTaskManager: Displayed com.google.android.dialer/.extensions.GoogleDialtactsActivity: +361ms
-pattern="ActivityTaskManager: Displayed ${package}"
-re_pattern='.*Displayed[[:blank:]]\+'"${package}"'[/][^[:blank:]]\+[[:blank:]]+\([[:digit:]]\+ms\|[[:digit:]]\+s[[:digit:]]\+ms\).*'
-
-parse_metric_from_logcat "Displayed_ms" "$pattern" "$re_pattern"
-
-# Only track ReportFullyDrawn with --reportfullydrawn/-rfd flags
-if [[ $report_fully_drawn == y ]]; then
- # 01-16 17:31:44.550 11172 11204 I ActivityTaskManager: Fully drawn com.google.android.GoogleCamera/com.android.camera.CameraLauncher: +10s897ms
- pattern="ActivityTaskManager: Fully drawn ${package}"
- #re_pattern='.*Fully drawn[[:blank:]]\+'"${package}"'[/][^[:blank:]]\+[[:blank:]]+\([[:digit:]]\+\).*'
- re_pattern='.*Fully drawn[[:blank:]]\+'"${package}"'[/][^[:blank:]]\+[[:blank:]]+\([[:digit:]]\+ms\|[[:digit:]]\+s[[:digit:]]\+ms\).*'
-
- parse_metric_from_logcat "Fully_drawn_ms" "$pattern" "$re_pattern"
-fi
-
-# also call into package-specific scripts if there are additional metrics
-if [[ -x "$DIR/metrics/$package" ]]; then
- source "$DIR/metrics/$package" "$timestamp"
-else
- verbose_print parse_metrics: no per-package metrics script found at "$DIR/metrics/$package"
-fi
diff --git a/startop/scripts/app_startup/query_compiler_filter.py b/startop/scripts/app_startup/query_compiler_filter.py
deleted file mode 100755
index ea14264b4a1c..000000000000
--- a/startop/scripts/app_startup/query_compiler_filter.py
+++ /dev/null
@@ -1,232 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 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.
-
-#
-#
-# Query the current compiler filter for an application by its package name.
-# (By parsing the results of the 'adb shell dumpsys package $package' command).
-# The output is a string "$compilation_filter $compilation_reason $isa".
-#
-# See --help for more details.
-#
-# -----------------------------------
-#
-# Sample usage:
-#
-# $> ./query_compiler_filter.py --package com.google.android.calculator
-# speed-profile unknown arm64
-#
-
-import argparse
-import os
-import re
-import sys
-
-# TODO: refactor this with a common library file with analyze_metrics.py
-DIR = os.path.abspath(os.path.dirname(__file__))
-sys.path.append(os.path.dirname(DIR))
-import lib.cmd_utils as cmd_utils
-import lib.print_utils as print_utils
-
-from typing import List, NamedTuple, Iterable
-
-_DEBUG_FORCE = None # Ignore -d/--debug if this is not none.
-
-def parse_options(argv: List[str] = None):
- """Parse command line arguments and return an argparse Namespace object."""
- parser = argparse.ArgumentParser(description="Query the compiler filter for a package.")
- # argparse considers args starting with - and -- optional in --help, even though required=True.
- # by using a named argument group --help will clearly say that it's required instead of optional.
- required_named = parser.add_argument_group('required named arguments')
- required_named.add_argument('-p', '--package', action='store', dest='package', help='package of the application', required=True)
-
- # optional arguments
- # use a group here to get the required arguments to appear 'above' the optional arguments in help.
- optional_named = parser.add_argument_group('optional named arguments')
- optional_named.add_argument('-i', '--isa', '--instruction-set', action='store', dest='instruction_set', help='which instruction set to select. defaults to the first one available if not specified.', choices=('arm64', 'arm', 'x86_64', 'x86'))
- optional_named.add_argument('-s', '--simulate', dest='simulate', action='store_true', help='Print which commands will run, but don\'t run the apps')
- optional_named.add_argument('-d', '--debug', dest='debug', action='store_true', help='Add extra debugging output')
-
- return parser.parse_args(argv)
-
-def remote_dumpsys_package(package: str, simulate: bool) -> str:
- # --simulate is used for interactive debugging/development, but also for the unit test.
- if simulate:
- return """
-Dexopt state:
- [%s]
- path: /data/app/%s-D7s8PLidqqEq7Jc7UH_a5A==/base.apk
- arm64: [status=speed-profile] [reason=unknown]
- path: /data/app/%s-D7s8PLidqqEq7Jc7UH_a5A==/base.apk
- arm: [status=speed] [reason=first-boot]
- path: /data/app/%s-D7s8PLidqqEq7Jc7UH_a5A==/base.apk
- x86: [status=quicken] [reason=install]
-""" %(package, package, package, package)
-
- code, res = cmd_utils.execute_arbitrary_command(['adb', 'shell', 'dumpsys',
- 'package', package],
- simulate=False,
- timeout=5,
- shell=False)
- if code:
- return res
- else:
- raise AssertionError("Failed to dumpsys package, errors = %s", res)
-
-ParseTree = NamedTuple('ParseTree', [('label', str), ('children', List['ParseTree'])])
-DexoptState = ParseTree # With the Dexopt state: label
-ParseResult = NamedTuple('ParseResult', [('remainder', List[str]), ('tree', ParseTree)])
-
-def find_parse_subtree(parse_tree: ParseTree, match_regex: str) -> ParseTree:
- if re.match(match_regex, parse_tree.label):
- return parse_tree
-
- for node in parse_tree.children:
- res = find_parse_subtree(node, match_regex)
- if res:
- return res
-
- return None
-
-def find_parse_children(parse_tree: ParseTree, match_regex: str) -> Iterable[ParseTree]:
- for node in parse_tree.children:
- if re.match(match_regex, node.label):
- yield node
-
-def parse_tab_subtree(label: str, str_lines: List[str], separator=' ', indent=-1) -> ParseResult:
- children = []
-
- get_indent_level = lambda line: len(line) - len(line.lstrip())
-
- line_num = 0
-
- keep_going = True
- while keep_going:
- keep_going = False
-
- for line_num in range(len(str_lines)):
- line = str_lines[line_num]
- current_indent = get_indent_level(line)
-
- print_utils.debug_print("INDENT=%d, LINE=%s" %(current_indent, line))
-
- current_label = line.lstrip()
-
- # skip empty lines
- if line.lstrip() == "":
- continue
-
- if current_indent > indent:
- parse_result = parse_tab_subtree(current_label, str_lines[line_num+1::], separator, current_indent)
- str_lines = parse_result.remainder
- children.append(parse_result.tree)
- keep_going = True
- else:
- # current_indent <= indent
- keep_going = False
-
- break
-
- new_remainder = str_lines[line_num::]
- print_utils.debug_print("NEW REMAINDER: ", new_remainder)
-
- parse_tree = ParseTree(label, children)
- return ParseResult(new_remainder, parse_tree)
-
-def parse_tab_tree(str_tree: str, separator=' ', indentation_level=-1) -> ParseTree:
-
- label = None
- lst = []
-
- line_num = 0
- line_lst = str_tree.split("\n")
-
- return parse_tab_subtree("", line_lst, separator, indentation_level).tree
-
-def parse_dexopt_state(dumpsys_tree: ParseTree) -> DexoptState:
- res = find_parse_subtree(dumpsys_tree, "Dexopt(\s+)state[:]?")
- if not res:
- raise AssertionError("Could not find the Dexopt state")
- return res
-
-def find_first_compiler_filter(dexopt_state: DexoptState, package: str, instruction_set: str) -> str:
- lst = find_all_compiler_filters(dexopt_state, package)
-
- print_utils.debug_print("all compiler filters: ", lst)
-
- for compiler_filter_info in lst:
- if not instruction_set:
- return compiler_filter_info
-
- if compiler_filter_info.isa == instruction_set:
- return compiler_filter_info
-
- return None
-
-CompilerFilterInfo = NamedTuple('CompilerFilterInfo', [('isa', str), ('status', str), ('reason', str)])
-
-def find_all_compiler_filters(dexopt_state: DexoptState, package: str) -> List[CompilerFilterInfo]:
-
- lst = []
- package_tree = find_parse_subtree(dexopt_state, re.escape("[%s]" %package))
-
- if not package_tree:
- raise AssertionError("Could not find any package subtree for package %s" %(package))
-
- print_utils.debug_print("package tree: ", package_tree)
-
- for path_tree in find_parse_children(package_tree, "path: "):
- print_utils.debug_print("path tree: ", path_tree)
-
- matchre = re.compile("([^:]+):\s+\[status=([^\]]+)\]\s+\[reason=([^\]]+)\]")
-
- for isa_node in find_parse_children(path_tree, matchre):
-
- matches = re.match(matchre, isa_node.label).groups()
-
- info = CompilerFilterInfo(*matches)
- lst.append(info)
-
- return lst
-
-def main() -> int:
- opts = parse_options()
- cmd_utils._debug = opts.debug
- if _DEBUG_FORCE is not None:
- cmd_utils._debug = _DEBUG_FORCE
- print_utils.debug_print("parsed options: ", opts)
-
- # Note: This can often 'fail' if the package isn't actually installed.
- package_dumpsys = remote_dumpsys_package(opts.package, opts.simulate)
- print_utils.debug_print("package dumpsys: ", package_dumpsys)
- dumpsys_parse_tree = parse_tab_tree(package_dumpsys, package_dumpsys)
- print_utils.debug_print("parse tree: ", dumpsys_parse_tree)
- dexopt_state = parse_dexopt_state(dumpsys_parse_tree)
-
- filter = find_first_compiler_filter(dexopt_state, opts.package, opts.instruction_set)
-
- if filter:
- print(filter.status, end=' ')
- print(filter.reason, end=' ')
- print(filter.isa)
- else:
- print("ERROR: Could not find any compiler-filter for package %s, isa %s" %(opts.package, opts.instruction_set), file=sys.stderr)
- return 1
-
- return 0
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/startop/scripts/app_startup/query_compiler_filter_test.py b/startop/scripts/app_startup/query_compiler_filter_test.py
deleted file mode 100755
index a751a43d1d6c..000000000000
--- a/startop/scripts/app_startup/query_compiler_filter_test.py
+++ /dev/null
@@ -1,116 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 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.
-#
-
-"""
-Unit tests for the query_compiler_filter.py script.
-
-Install:
- $> sudo apt-get install python3-pytest ## OR
- $> pip install -U pytest
-See also https://docs.pytest.org/en/latest/getting-started.html
-
-Usage:
- $> ./query_compiler_filter.py
- $> pytest query_compiler_filter.py
- $> python -m pytest query_compiler_filter.py
-
-See also https://docs.pytest.org/en/latest/usage.html
-"""
-
-# global imports
-from contextlib import contextmanager
-import io
-import shlex
-import sys
-import typing
-
-# pip imports
-import pytest
-
-# local imports
-import query_compiler_filter as qcf
-
-@contextmanager
-def redirect_stdout_stderr():
- """Redirect stdout/stderr to a new StringIO for duration of context."""
- old_stdout = sys.stdout
- old_stderr = sys.stderr
- new_stdout = io.StringIO()
- sys.stdout = new_stdout
- new_stderr = io.StringIO()
- sys.stderr = new_stderr
- try:
- yield (new_stdout, new_stderr)
- finally:
- sys.stdout = old_stdout
- sys.stderr = old_stderr
- # Seek back to the beginning so we can read whatever was written into it.
- new_stdout.seek(0)
- new_stderr.seek(0)
-
-@contextmanager
-def replace_argv(argv):
- """ Temporarily replace argv for duration of this context."""
- old_argv = sys.argv
- sys.argv = [sys.argv[0]] + argv
- try:
- yield
- finally:
- sys.argv = old_argv
-
-def exec_main(argv):
- """Run the query_compiler_filter main function with the provided arguments.
-
- Returns the stdout result when successful, assertion failure otherwise.
- """
- try:
- with redirect_stdout_stderr() as (the_stdout, the_stderr):
- with replace_argv(argv):
- code = qcf.main()
- assert 0 == code, the_stderr.readlines()
-
- all_lines = the_stdout.readlines()
- return "".join(all_lines)
- finally:
- the_stdout.close()
- the_stderr.close()
-
-def test_query_compiler_filter():
- # no --instruction-set specified: provide whatever was the 'first' filter.
- assert exec_main(['--simulate',
- '--package', 'com.google.android.apps.maps']) == \
- "speed-profile unknown arm64\n"
-
- # specifying an instruction set finds the exact compiler filter match.
- assert exec_main(['--simulate',
- '--package', 'com.google.android.apps.maps',
- '--instruction-set', 'arm64']) == \
- "speed-profile unknown arm64\n"
-
- assert exec_main(['--simulate',
- '--package', 'com.google.android.apps.maps',
- '--instruction-set', 'arm']) == \
- "speed first-boot arm\n"
-
- assert exec_main(['--simulate',
- '--debug',
- '--package', 'com.google.android.apps.maps',
- '--instruction-set', 'x86']) == \
- "quicken install x86\n"
-
-if __name__ == '__main__':
- pytest.main()
diff --git a/startop/scripts/app_startup/run_app_with_prefetch b/startop/scripts/app_startup/run_app_with_prefetch
deleted file mode 100755
index 31f625334b1e..000000000000
--- a/startop/scripts/app_startup/run_app_with_prefetch
+++ /dev/null
@@ -1,487 +0,0 @@
-#!/bin/bash
-#
-# Copyright 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.
-
-usage() {
- cat <<EOF
-Usage: run_app_with_prefetch --package <name> [OPTIONS]...
-
- -p, --package <name> package of the app to test
- -a, --activity <name> activity to use
- -h, --help usage information (this)
- -v, --verbose enable extra verbose printing
- -i, --input <file> trace file protobuf (default 'TraceFile.pb')
- -r, --readahead <mode> cold, warm, fadvise, mlock (default 'warm')
- -w, --when <when> aot or jit (default 'jit')
- -c, --count <count> how many times to run (default 1)
- -s, --sleep <sec> how long to sleep after readahead
- -t, --timeout <sec> how many seconds to timeout in between each app run (default 10)
- -o, --output <file.csv> what file to write the performance results into as csv (default stdout)
-EOF
-}
-
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-source "$DIR/../iorap/common"
-
-report_fully_drawn="n"
-needs_trace_file="n"
-input_file=""
-package=""
-mode='warm'
-count=2
-sleep_time=2
-timeout=10
-output="" # stdout by default
-when="jit"
-parse_arguments() {
- while [[ $# -gt 0 ]]; do
- case "$1" in
- -h|--help)
- usage
- exit 0
- ;;
- -p|--package)
- package="$2"
- shift
- ;;
- -a|--activity)
- activity="$2"
- shift
- ;;
- -i|--input)
- input_file="$2"
- shift
- ;;
- -v|--verbose)
- export verbose="y"
- ;;
- -r|--readahead)
- mode="$2"
- shift
- ;;
- -rfd|--reportfullydrawn)
- report_fully_drawn="y"
- shift
- ;;
- -c|--count)
- count="$2"
- ((count+=1))
- shift
- ;;
- -s|--sleep)
- sleep_time="$2"
- shift
- ;;
- -t|--timeout)
- timeout="$2"
- shift
- ;;
- -o|--output)
- output="$2"
- shift
- ;;
- -w|--when)
- when="$2"
- shift
- ;;
- --compiler-filter)
- compiler_filter="$2"
- shift
- ;;
- *)
- echo "Invalid argument: $1" >&2
- exit 1
- esac
- shift
- done
-
- if [[ $when == "aot" ]]; then
- # TODO: re-implement aot later for experimenting.
- echo "Error: --when $when is unsupported" >&2
- exit 1
- elif [[ $when != "jit" ]]; then
- echo "Error: --when must be one of (aot jit)." >&2
- exit 1
- fi
-}
-
-echo_to_output_file() {
- if [[ "x$output" != x ]]; then
- echo "$@" >> $output
- fi
- # Always echo to stdout as well.
- echo "$@"
-}
-
-find_package_path() {
- local pkg="$1"
-
- res="$(adb shell find "/data/app/$pkg"-'*' -maxdepth 0 2> /dev/null)"
- if [[ -z $res ]]; then
- res="$(adb shell find "/system/app/$pkg"-'*' -maxdepth 0 2> /dev/null)"
- fi
- echo "$res"
-}
-
-# Main entry point
-if [[ $# -eq 0 ]]; then
- usage
- exit 1
-else
- parse_arguments "$@"
-
- # if we do not have have package exit early with an error
- [[ "$package" == "" ]] && echo "--package not specified" 1>&2 && exit 1
-
- if [[ $mode != "cold" && $mode != "warm" ]]; then
- needs_trace_file="y"
- if [[ -z "$input_file" ]] || ! [[ -f $input_file ]]; then
- echo "--input not specified" 1>&2
- exit 1
- fi
- fi
-
- if [[ "$activity" == "" ]]; then
- activity="$(get_activity_name "$package")"
- if [[ "$activity" == "" ]]; then
- echo "Activity name could not be found, invalid package name?" 1>&2
- exit 1
- else
- verbose_print "Activity name inferred: " "$activity"
- fi
- fi
-fi
-
-adb root > /dev/null
-
-if [[ ($when == jit) || ($when == aot) ]] && [[ "$(adb shell getenforce)" != "Permissive" ]]; then
- echo "Disable selinux permissions and restart framework."
- adb shell setenforce 0
- adb shell stop
- adb shell start
- adb wait-for-device
-fi
-
-# TODO: set performance governor etc, preferrably only once
-# before every single app run.
-
-# Kill everything before running.
-remote_pkill "$package"
-sleep 1
-
-timings_array=()
-
-package_path="$(find_package_path "$package")"
-if [[ $? -ne 0 ]]; then
- echo "Failed to detect package path for '$package'" >&2
- exit 1
-fi
-verbose_print "Package was in path '$package_path'"
-
-application_trace_file_path="$package_path/TraceFile.pb"
-trace_file_directory="$package_path"
-if [[ $needs_trace_file == y ]]; then
- # system server always passes down the package path in a hardcoded spot.
- if [[ $when == "jit" ]]; then
- if ! iorapd_compiler_install_trace_file "$package" "$activity" "$input_file"; then
- echo "Error: Failed to install compiled TraceFile.pb for '$package/$activity'" >&2
- exit 1
- fi
- keep_application_trace_file="y"
- else
- echo "TODO: --readahead=aot is non-functional and needs to be fixed." >&2
- exit 1
- # otherwise use a temporary directory to get normal non-jit behavior.
- trace_file_directory="/data/local/tmp/prefetch/$package"
- adb shell mkdir -p "$trace_file_directory"
- verbose_print adb push "$input_file" "$trace_file_directory/TraceFile.pb"
- adb push "$input_file" "$trace_file_directory/TraceFile.pb"
- fi
-fi
-
-# Everything other than JIT: remove the trace file,
-# otherwise system server activity hints will kick in
-# and the new just-in-time app pre-warmup will happen.
-if [[ $keep_application_trace_file == "n" ]]; then
- iorapd_compiler_purge_trace_file "$package" "$activity"
-fi
-
-# Perform AOT readahead/pinning/etc when an application is about to be launched.
-# For JIT readahead, we allow the system to handle it itself (this is a no-op).
-#
-# For warm, cold, etc modes which don't need readahead this is always a no-op.
-perform_aot() {
- local the_when="$1" # user: aot, jit
- local the_mode="$2" # warm, cold, fadvise, mlock, etc.
-
- # iorapd readahead for jit+(mlock/fadvise)
- if [[ $the_when == "jit" && $the_mode != 'warm' && $the_mode != 'cold' ]]; then
- iorapd_readahead_enable
- return 0
- fi
-
- if [[ $the_when != "aot" ]]; then
- # TODO: just in time implementation.. should probably use system server.
- return 0
- fi
-
- # any non-warm/non-cold modes should use the iorap-activity-hint wrapper script.
- if [[ $the_mode != 'warm' && $the_mode != 'cold' ]]; then
-
- # TODO: add activity_hint_sender.exp
- verbose_print "starting with package=$package package_path=$trace_file_directory"
- coproc hint_sender_fd { $ANDROID_BUILD_TOP/system/iorap/src/sh/activity_hint_sender.exp "$package" "$trace_file_directory" "$the_mode"; }
- hint_sender_pid=$!
- verbose_print "Activity hint sender began"
-
- notification_success="n"
- while read -r -u "${hint_sender_fd[0]}" hint_sender_output; do
- verbose_print "$hint_sender_output"
- if [[ "$hint_sender_output" == "Press any key to send completed event..."* ]]; then
- verbose_print "WE DID SEE NOTIFICATION SUCCESS."
- notification_success='y'
- # Give it some time to actually perform the readaheads.
- sleep $sleep_time
- break
- fi
- done
-
- if [[ $notification_success == 'n' ]]; then
- echo "[FATAL] Activity hint notification failed." 1>&2
- exit 1
- fi
- fi
-}
-
-# Perform cleanup at the end of each loop iteration.
-perform_post_launch_cleanup() {
- local the_when="$1" # user: aot, jit
- local the_mode="$2" # warm, cold, fadvise, mlock, etc.
- local logcat_timestamp="$3" # timestamp from before am start.
- local res
-
- if [[ $the_when != "aot" ]]; then
- if [[ $the_mode != 'warm' && $the_mode != 'cold' ]]; then
- # Validate that readahead completes.
- # If this fails for some reason, then this will also discard the timing of the run.
- iorapd_readahead_wait_until_finished "$package" "$activity" "$logcat_timestamp" "$timeout"
- res=$?
-
- iorapd_readahead_disable
-
- return $res
- fi
- # Don't need to do anything for warm or cold.
- return 0
- fi
-
- # any non-warm/non-cold modes should use the iorap-activity-hint wrapper script.
- if [[ $the_mode != 'warm' && $the_mode != 'cold' ]]; then
- # Clean up the hint sender by telling it that the launch was completed,
- # and to shutdown the watcher.
- echo "Done\n" >&"${hint_sender_fd[1]}"
-
- while read -r -u "${hint_sender_fd[0]}" hint_sender_output; do
- verbose_print "$hint_sender_output"
- done
-
- wait $hint_sender_pid
- fi
-}
-
-configure_compiler_filter() {
- local the_compiler_filter="$1"
- local the_package="$2"
- local the_activity="$3"
-
- if [[ -z $the_compiler_filter ]]; then
- verbose_print "No --compiler-filter specified, don't need to force it."
- return 0
- fi
-
- local current_compiler_filter_info="$("$DIR"/query_compiler_filter.py --package "$the_package")"
- local res=$?
- if [[ $res -ne 0 ]]; then
- return $res
- fi
-
- local current_compiler_filter
- local current_reason
- local current_isa
- read current_compiler_filter current_reason current_isa <<< "$current_compiler_filter_info"
-
- verbose_print "Compiler Filter="$current_compiler_filter "Reason="$current_reason "Isa="$current_isa
-
- # Don't trust reasons that aren't 'unknown' because that means we didn't manually force the compilation filter.
- # (e.g. if any automatic system-triggered compilations are not unknown).
- if [[ $current_reason != "unknown" ]] || [[ $current_compiler_filter != $the_compiler_filter ]]; then
- verbose_print "$DIR"/force_compiler_filter --compiler-filter "$the_compiler_filter" --package "$the_package" --activity "$the_activity"
- "$DIR"/force_compiler_filter --compiler-filter "$the_compiler_filter" --package "$the_package" --activity "$the_activity"
- res=$?
- else
- verbose_print "Queried compiler-filter matched requested compiler-filter, skip forcing."
- res=0
- fi
-
- return $res
-}
-
-# Ensure the APK is currently compiled with whatever we passed in via --compiler-filter.
-# No-op if this option was not passed in.
-configure_compiler_filter "$compiler_filter" "$package" "$activity" || exit 1
-
-# convert 'a=b\nc=d\ne=f\n...' into 'b,d,f,...'
-parse_metrics_output_string() {
- # single string with newlines in it.
- local input="$1"
-
- local metric_name
- local metric_value
- local rest
-
- local all_metrics=()
-
- # (n1=v1 n2=v2 n3=v3 ...)
- readarray -t all_metrics <<< "$input"
-
- local kv_pair=()
- local i
-
- for i in "${all_metrics[@]}"
- do
- verbose_print "parse_metrics_output: element '$i'"
- # name=value
-
- IFS='=' read -r metric_name metric_value rest <<< "$i"
-
- verbose_print "parse_metrics_output: metric_value '$metric_value'"
-
- # (value1 value2 value3 ...)
- all_metrics+=(${metric_value})
- done
-
- # "value1,value2,value3,..."
- join_by ',' "${all_metrics[@]}"
-}
-
-# convert 'a=b\nc=d\ne=f\n... into b,d,f,...'
-parse_metrics_output() {
- local metric_name
- local metric_value
- local rest
-
- local all_metrics=()
-
- while IFS='=' read -r metric_name metric_value rest; do
- verbose_print "metric: $metric_name, value: $metric_value; rest: $rest"
- all_metrics+=($metric_value)
- done
-
- join_by ',' "${all_metrics[@]}"
-}
-
-# convert 'a=b\nc=d\ne=f\n... into b,d,f,...'
-parse_metrics_header() {
- local metric_name
- local metric_value
- local rest
-
- local all_metrics=()
-
- while IFS='=' read -r metric_name metric_value rest; do
- verbose_print "metric: $metric_name, value: $metric_value; rest: $rest"
- all_metrics+=($metric_name)
- done
-
- join_by ',' "${all_metrics[@]}"
-}
-
-if [[ $report_fully_drawn == y ]]; then
- metrics_header="$("$DIR/parse_metrics" --package "$package" --activity "$activity" --simulate --reportfullydrawn | parse_metrics_header)"
-else
- metrics_header="$("$DIR/parse_metrics" --package "$package" --activity "$activity" --simulate | parse_metrics_header)"
-fi
-
-# TODO: This loop logic could probably be moved into app_startup_runner.py
-for ((i=0;i<count;++i)) do
- verbose_print "=========================================="
- verbose_print "==== ITERATION $i ===="
- verbose_print "=========================================="
- if [[ $mode != "warm" ]]; then
- # The package must be killed **before** we drop caches, otherwise pages will stay resident.
- verbose_print "Kill package for non-warm start."
- remote_pkill "$package"
- verbose_print "Drop caches for non-warm start."
- # Drop all caches to get cold starts.
- adb shell "echo 3 > /proc/sys/vm/drop_caches"
- fi
-
- perform_aot "$when" "$mode"
-
- verbose_print "Running with timeout $timeout"
-
- pre_launch_timestamp="$(logcat_save_timestamp)"
-
- # TODO: multiple metrics output.
-
-if [[ $report_fully_drawn == y ]]; then
- total_time="$(timeout $timeout "$DIR/launch_application" "$package" "$activity" | "$DIR/parse_metrics" --package "$package" --activity "$activity" --timestamp "$pre_launch_timestamp" --reportfullydrawn | parse_metrics_output)"
-else
- total_time="$(timeout $timeout "$DIR/launch_application" "$package" "$activity" | "$DIR/parse_metrics" --package "$package" --activity "$activity" --timestamp "$pre_launch_timestamp" | parse_metrics_output)"
-fi
-
- if [[ $? -ne 0 ]]; then
- echo "WARNING: Skip bad result, try iteration again." >&2
- ((i=i-1))
- continue
- fi
-
- perform_post_launch_cleanup "$when" "$mode" "$pre_launch_timestamp"
-
- if [[ $? -ne 0 ]]; then
- echo "WARNING: Skip bad cleanup, try iteration again." >&2
- ((i=i-1))
- continue
- fi
-
- echo "Iteration $i. Total time was: $total_time"
-
- timings_array+=("$total_time")
-done
-
-# drop the first result which is usually garbage.
-timings_array=("${timings_array[@]:1}")
-
-# Print the CSV header first.
-echo_to_output_file "$metrics_header"
-
-# Print out interactive/debugging timings and averages.
-# Other scripts should use the --output flag and parse the CSV.
-for tim in "${timings_array[@]}"; do
- echo_to_output_file "$tim"
-done
-
-if [[ x$output != x ]]; then
- echo " Saved results to '$output'"
-fi
-
-if [[ $needs_trace_file == y ]] ; then
- iorapd_compiler_purge_trace_file "$package" "$activity"
-fi
-
-# Kill the process to ensure AM isn't keeping it around.
-remote_pkill "$package"
-
-exit 0
diff --git a/startop/scripts/app_startup/run_app_with_prefetch.py b/startop/scripts/app_startup/run_app_with_prefetch.py
deleted file mode 100755
index 2f1eff2c41f6..000000000000
--- a/startop/scripts/app_startup/run_app_with_prefetch.py
+++ /dev/null
@@ -1,230 +0,0 @@
-#!/usr/bin/env python3
-#
-# 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.
-
-"""Runner of one test given a setting.
-
-Run app and gather the measurement in a certain configuration.
-Print the result to stdout.
-See --help for more details.
-
-Sample usage:
- $> ./python run_app_with_prefetch.py -p com.android.settings -a
- com.android.settings.Settings -r fadvise -i input
-
-"""
-
-import argparse
-import os
-import sys
-import time
-from typing import List, Tuple, Optional
-
-# local imports
-import lib.adb_utils as adb_utils
-from lib.app_runner import AppRunner, AppRunnerListener
-
-# global variables
-DIR = os.path.abspath(os.path.dirname(__file__))
-
-sys.path.append(os.path.dirname(DIR))
-import lib.print_utils as print_utils
-import lib.cmd_utils as cmd_utils
-import iorap.lib.iorapd_utils as iorapd_utils
-
-class PrefetchAppRunner(AppRunnerListener):
- def __init__(self,
- package: str,
- activity: Optional[str],
- readahead: str,
- compiler_filter: Optional[str],
- timeout: Optional[int],
- simulate: bool,
- debug: bool,
- input:Optional[str],
- **kwargs):
- self.app_runner = AppRunner(package,
- activity,
- compiler_filter,
- timeout,
- simulate)
- self.app_runner.add_callbacks(self)
-
- self.simulate = simulate
- self.readahead = readahead
- self.debug = debug
- self.input = input
- print_utils.DEBUG = self.debug
- cmd_utils.SIMULATE = self.simulate
-
-
- def run(self) -> Optional[List[Tuple[str]]]:
- """Runs an app.
-
- Returns:
- A list of (metric, value) tuples.
- """
- return self.app_runner.run()
-
- def preprocess(self):
- passed = self.validate_options()
- if not passed:
- return
-
- # Sets up adb environment.
- adb_utils.root()
- adb_utils.disable_selinux()
- time.sleep(1)
-
- # Kill any existing process of this app
- adb_utils.pkill(self.app_runner.package)
-
- if self.readahead != 'warm':
- print_utils.debug_print('Drop caches for non-warm start.')
- # Drop all caches to get cold starts.
- adb_utils.vm_drop_cache()
-
- if self.readahead != 'warm' and self.readahead != 'cold':
- iorapd_utils.enable_iorapd_readahead()
-
- def postprocess(self, pre_launch_timestamp: str):
- passed = self._perform_post_launch_cleanup(pre_launch_timestamp)
- if not passed and not self.app_runner.simulate:
- print_utils.error_print('Cannot perform post launch cleanup!')
- return None
-
- # Kill any existing process of this app
- adb_utils.pkill(self.app_runner.package)
-
- def _perform_post_launch_cleanup(self, logcat_timestamp: str) -> bool:
- """Performs cleanup at the end of each loop iteration.
-
- Returns:
- A bool indicates whether the cleanup succeeds or not.
- """
- if self.readahead != 'warm' and self.readahead != 'cold':
- passed = iorapd_utils.wait_for_iorapd_finish(self.app_runner.package,
- self.app_runner.activity,
- self.app_runner.timeout,
- self.debug,
- logcat_timestamp)
-
- if not passed:
- return passed
-
- return iorapd_utils.disable_iorapd_readahead()
-
- # Don't need to do anything for warm or cold.
- return True
-
- def metrics_selector(self, am_start_output: str,
- pre_launch_timestamp: str) -> str:
- """Parses the metric after app startup by reading from logcat in a blocking
- manner until all metrics have been found".
-
- Returns:
- the total time and displayed time of app startup.
- For example: "TotalTime=123\nDisplayedTime=121
- """
- total_time = AppRunner.parse_total_time(am_start_output)
- displayed_time = adb_utils.blocking_wait_for_logcat_displayed_time(
- pre_launch_timestamp, self.app_runner.package, self.app_runner.timeout)
-
- return 'TotalTime={}\nDisplayedTime={}'.format(total_time, displayed_time)
-
- def validate_options(self) -> bool:
- """Validates the activity and trace file if needed.
-
- Returns:
- A bool indicates whether the activity is valid.
- """
- needs_trace_file = self.readahead != 'cold' and self.readahead != 'warm'
- if needs_trace_file and (self.input is None or
- not os.path.exists(self.input)):
- print_utils.error_print('--input not specified!')
- return False
-
- # Install necessary trace file. This must be after the activity checking.
- if needs_trace_file:
- passed = iorapd_utils.iorapd_compiler_install_trace_file(
- self.app_runner.package, self.app_runner.activity, self.input)
- if not cmd_utils.SIMULATE and not passed:
- print_utils.error_print('Failed to install compiled TraceFile.pb for '
- '"{}/{}"'.
- format(self.app_runner.package,
- self.app_runner.activity))
- return False
-
- return True
-
-
-
-def parse_options(argv: List[str] = None):
- """Parses command line arguments and return an argparse Namespace object."""
- parser = argparse.ArgumentParser(
- description='Run an Android application once and measure startup time.'
- )
-
- required_named = parser.add_argument_group('required named arguments')
- required_named.add_argument('-p', '--package', action='store', dest='package',
- help='package of the application', required=True)
-
- # optional arguments
- # use a group here to get the required arguments to appear 'above' the
- # optional arguments in help.
- optional_named = parser.add_argument_group('optional named arguments')
- optional_named.add_argument('-a', '--activity', action='store',
- dest='activity',
- help='launch activity of the application')
- optional_named.add_argument('-s', '--simulate', dest='simulate',
- action='store_true',
- help='simulate the process without executing '
- 'any shell commands')
- optional_named.add_argument('-d', '--debug', dest='debug',
- action='store_true',
- help='Add extra debugging output')
- optional_named.add_argument('-i', '--input', action='store', dest='input',
- help='perfetto trace file protobuf',
- default='TraceFile.pb')
- optional_named.add_argument('-r', '--readahead', action='store',
- dest='readahead',
- help='which readahead mode to use',
- default='cold',
- choices=('warm', 'cold', 'mlock', 'fadvise'))
- optional_named.add_argument('-t', '--timeout', dest='timeout', action='store',
- type=int,
- help='Timeout after this many seconds when '
- 'executing a single run.',
- default=10)
- optional_named.add_argument('--compiler-filter', dest='compiler_filter',
- action='store',
- help='Which compiler filter to use.',
- default=None)
-
- return parser.parse_args(argv)
-
-def main():
- opts = parse_options()
- runner = PrefetchAppRunner(**vars(opts))
- result = runner.run()
-
- if result is None:
- return 1
-
- print(result)
- return 0
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/startop/scripts/app_startup/run_app_with_prefetch_test.py b/startop/scripts/app_startup/run_app_with_prefetch_test.py
deleted file mode 100644
index 8a588e4463e9..000000000000
--- a/startop/scripts/app_startup/run_app_with_prefetch_test.py
+++ /dev/null
@@ -1,286 +0,0 @@
-#!/usr/bin/env python3
-#
-# 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.
-#
-"""Unit tests for the run_app_with_prefetch_test.py script.
-
-Install:
- $> sudo apt-get install python3-pytest ## OR
- $> pip install -U pytest
-See also https://docs.pytest.org/en/latest/getting-started.html
-
-Usage:
- $> ./run_app_with_prefetch_test.py
- $> pytest run_app_with_prefetch_test.py
- $> python -m pytest run_app_with_prefetch_test.py
-
-See also https://docs.pytest.org/en/latest/usage.html
-"""
-
-import io
-import os
-import shlex
-import sys
-import tempfile
-# global imports
-from contextlib import contextmanager
-
-# pip imports
-import pytest
-# local imports
-import run_app_with_prefetch as runner
-from mock import call, patch, Mock
-
-sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
-from app_startup.lib.app_runner import AppRunner
-#
-# Argument Parsing Helpers
-#
-
-@contextmanager
-def ignore_stdout_stderr():
- """Ignore stdout/stderr output for duration of this context."""
- old_stdout = sys.stdout
- old_stderr = sys.stderr
- sys.stdout = io.StringIO()
- sys.stderr = io.StringIO()
- try:
- yield
- finally:
- sys.stdout = old_stdout
- sys.stderr = old_stderr
-
-@contextmanager
-def argparse_bad_argument(msg):
- """Asserts that a SystemExit is raised when executing this context.
-
- If the assertion fails, print the message 'msg'.
- """
- with pytest.raises(SystemExit, message=msg):
- with ignore_stdout_stderr():
- yield
-
-def assert_bad_argument(args, msg):
- """Asserts that the command line arguments in 'args' are malformed.
-
- Prints 'msg' if the assertion fails.
- """
- with argparse_bad_argument(msg):
- parse_args(args)
-
-def parse_args(args):
- """
- :param args: command-line like arguments as a single string
- :return: dictionary of parsed key/values
- """
- # "-a b -c d" => ['-a', 'b', '-c', 'd']
- return vars(runner.parse_options(shlex.split(args)))
-
-def default_dict_for_parsed_args(**kwargs):
- """Combines it with all of the "optional" parameters' default values."""
- d = {
- 'readahead': 'cold',
- 'simulate': None,
- 'simulate': False,
- 'debug': False,
- 'input': 'TraceFile.pb',
- 'timeout': 10,
- 'compiler_filter': None,
- 'activity': None
- }
- d.update(kwargs)
- return d
-
-def default_mock_dict_for_parsed_args(include_optional=True, **kwargs):
- """Combines default dict with all optional parameters with some mock required
- parameters.
- """
- d = {'package': 'com.fake.package'}
- if include_optional:
- d.update(default_dict_for_parsed_args())
- d.update(kwargs)
- return d
-
-def parse_optional_args(str):
- """
- Parses an argument string which already includes all the required arguments
- in default_mock_dict_for_parsed_args.
- """
- req = '--package com.fake.package'
- return parse_args('%s %s' % (req, str))
-
-def test_argparse():
- # missing arguments
- assert_bad_argument('', '-p are required')
-
- # required arguments are parsed correctly
- ad = default_dict_for_parsed_args # assert dict
- assert parse_args('--package xyz') == ad(package='xyz')
-
- assert parse_args('-p xyz') == ad(package='xyz')
-
- assert parse_args('-p xyz -s') == ad(package='xyz', simulate=True)
- assert parse_args('-p xyz --simulate') == ad(package='xyz', simulate=True)
-
- # optional arguments are parsed correctly.
- mad = default_mock_dict_for_parsed_args # mock assert dict
- assert parse_optional_args('--input trace.pb') == mad(input='trace.pb')
-
- assert parse_optional_args('--compiler-filter speed') == \
- mad(compiler_filter='speed')
-
- assert parse_optional_args('-d') == mad(debug=True)
- assert parse_optional_args('--debug') == mad(debug=True)
-
- assert parse_optional_args('--timeout 123') == mad(timeout=123)
- assert parse_optional_args('-t 456') == mad(timeout=456)
-
- assert parse_optional_args('-r warm') == mad(readahead='warm')
- assert parse_optional_args('--readahead warm') == mad(readahead='warm')
-
- assert parse_optional_args('-a act') == mad(activity='act')
- assert parse_optional_args('--activity act') == mad(activity='act')
-
-def test_main():
- args = '--package com.fake.package --activity act -s'
- opts = runner.parse_options(shlex.split(args))
- result = runner.PrefetchAppRunner(**vars(opts)).run()
- assert result == [('TotalTime', '123')]
-
-def _mocked_run_shell_command(*args, **kwargs):
- if args[0] == 'adb shell ps | grep "music" | awk \'{print $2;}\'':
- return (True, '9999')
- else:
- return (True, '')
-
-def test_preprocess_no_cache_drop():
- with patch('lib.cmd_utils.run_shell_command',
- new_callable=Mock) as mock_run_shell_command:
- mock_run_shell_command.side_effect = _mocked_run_shell_command
- prefetch_app_runner = runner.PrefetchAppRunner(package='music',
- activity='MainActivity',
- readahead='warm',
- compiler_filter=None,
- timeout=None,
- simulate=False,
- debug=False,
- input=None)
-
- prefetch_app_runner.preprocess()
-
- calls = [call('adb root'),
- call('adb shell "getenforce"'),
- call('adb shell "setenforce 0"'),
- call('adb shell "stop"'),
- call('adb shell "start"'),
- call('adb wait-for-device'),
- call('adb shell ps | grep "music" | awk \'{print $2;}\''),
- call('adb shell "kill 9999"')]
- mock_run_shell_command.assert_has_calls(calls)
-
-def test_preprocess_with_cache_drop():
- with patch('lib.cmd_utils.run_shell_command',
- new_callable=Mock) as mock_run_shell_command:
- mock_run_shell_command.side_effect = _mocked_run_shell_command
- prefetch_app_runner = runner.PrefetchAppRunner(package='music',
- activity='MainActivity',
- readahead='cold',
- compiler_filter=None,
- timeout=None,
- simulate=False,
- debug=False,
- input=None)
-
- prefetch_app_runner.preprocess()
-
- calls = [call('adb root'),
- call('adb shell "getenforce"'),
- call('adb shell "setenforce 0"'),
- call('adb shell "stop"'),
- call('adb shell "start"'),
- call('adb wait-for-device'),
- call('adb shell ps | grep "music" | awk \'{print $2;}\''),
- call('adb shell "kill 9999"'),
- call('adb shell "echo 3 > /proc/sys/vm/drop_caches"')]
- mock_run_shell_command.assert_has_calls(calls)
-
-def test_preprocess_with_cache_drop_and_iorapd_enabled():
- with patch('lib.cmd_utils.run_shell_command',
- new_callable=Mock) as mock_run_shell_command:
- mock_run_shell_command.side_effect = _mocked_run_shell_command
-
- with tempfile.NamedTemporaryFile() as input:
- prefetch_app_runner = runner.PrefetchAppRunner(package='music',
- activity='MainActivity',
- readahead='fadvise',
- compiler_filter=None,
- timeout=None,
- simulate=False,
- debug=False,
- input=input.name)
-
- prefetch_app_runner.preprocess()
-
- calls = [call('adb root'),
- call('adb shell "getenforce"'),
- call('adb shell "setenforce 0"'),
- call('adb shell "stop"'),
- call('adb shell "start"'),
- call('adb wait-for-device'),
- call(
- 'adb shell ps | grep "music" | awk \'{print $2;}\''),
- call('adb shell "kill 9999"'),
- call('adb shell "echo 3 > /proc/sys/vm/drop_caches"'),
- call('bash -c "source {}; iorapd_readahead_enable"'.
- format(AppRunner.IORAP_COMMON_BASH_SCRIPT))]
- mock_run_shell_command.assert_has_calls(calls)
-
-@patch('lib.adb_utils.blocking_wait_for_logcat_displayed_time')
-@patch('lib.cmd_utils.run_shell_command')
-def test_postprocess_with_launch_cleanup(
- mock_run_shell_command,
- mock_blocking_wait_for_logcat_displayed_time):
- mock_run_shell_command.side_effect = _mocked_run_shell_command
- mock_blocking_wait_for_logcat_displayed_time.return_value = 123
-
- with tempfile.NamedTemporaryFile() as input:
- prefetch_app_runner = runner.PrefetchAppRunner(package='music',
- activity='MainActivity',
- readahead='fadvise',
- compiler_filter=None,
- timeout=10,
- simulate=False,
- debug=False,
- input=input.name)
-
- prefetch_app_runner.postprocess('2019-07-02 23:20:06.972674825')
-
- calls = [
- call('bash -c "source {script_path}; '
- 'iorapd_readahead_wait_until_finished '
- '\'{package}\' \'{activity}\' \'{timestamp}\' \'{timeout}\'"'.
- format(timeout=10,
- package='music',
- activity='MainActivity',
- timestamp='2019-07-02 23:20:06.972674825',
- script_path=AppRunner.IORAP_COMMON_BASH_SCRIPT)),
- call('bash -c "source {}; iorapd_readahead_disable"'.
- format(AppRunner.IORAP_COMMON_BASH_SCRIPT)),
- call('adb shell ps | grep "music" | awk \'{print $2;}\''),
- call('adb shell "kill 9999"')]
- mock_run_shell_command.assert_has_calls(calls)
-
-if __name__ == '__main__':
- pytest.main()
diff --git a/startop/scripts/app_startup/unlock_screen b/startop/scripts/app_startup/unlock_screen
deleted file mode 100755
index 478294c9f35d..000000000000
--- a/startop/scripts/app_startup/unlock_screen
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-#
-# Copyright 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.
-
-# This turns the screen on if it's off.
-# If it's on it does nothing unless its on the home screen, in which case it opens up some background
-# menu.
-#
-# However, this menu is ignored because "am start" commands still work as expected.
-adb shell input keyevent MENU
diff --git a/startop/scripts/iorap/analyze_prefetch_file.py b/startop/scripts/iorap/analyze_prefetch_file.py
deleted file mode 100755
index 343cd54b7174..000000000000
--- a/startop/scripts/iorap/analyze_prefetch_file.py
+++ /dev/null
@@ -1,168 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright 2020, 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.
-
-import argparse
-import os
-import sys
-from typing import Dict, List, NamedTuple, Tuple
-
-DIR = os.path.abspath(os.path.dirname(__file__))
-sys.path.append(os.path.dirname(DIR)) # framework/base/startop/script
-import lib.print_utils as print_utils
-
-# Include generated protos.
-dir_name = os.path.dirname(os.path.realpath(__file__))
-sys.path.append(dir_name + "/generated")
-
-from TraceFile_pb2 import *
-
-def parse_options(argv: List[str] = None):
- """Parses command line arguments and returns an argparse Namespace object."""
- parser = argparse.ArgumentParser(description="Analyze compiled_trace iorap protos.")
- required_named = parser.add_argument_group('required named arguments')
-
- required_named.add_argument('-i', dest='input', metavar='FILE',
- help='Read protobuf file as input')
-
- optional_named = parser.add_argument_group('optional named arguments')
-
- optional_named.add_argument('-up', dest='upper_percent', type=float,
- default=95.0,
- help='Only show the top-most entries up to this value.')
-
- optional_named.add_argument('-r', dest='raw', action='store_true',
- help='Output entire raw file.')
- optional_named.add_argument('-o', dest='output',
- help='The results are stored into the output file')
- optional_named.add_argument('-d', dest='debug', action='store_true'
- , help='Activity of the app to be compiled')
-
- return parser.parse_args(argv)
-
-def open_iorap_prefetch_file(file_path: str) -> TraceFile:
- with open(file_path, "rb") as f:
- tf = TraceFile()
- tf.ParseFromString(f.read())
- return tf
-
-def print_stats_summary(trace_file: TraceFile, upper_percent):
- tf_dict = convert_to_dict(trace_file)
- print_utils.debug_print(tf_dict)
-
- total_length = 0
- summaries = []
- for name, entries_list in tf_dict.items():
- summary = entries_sum(entries_list)
- summaries.append(summary)
-
- total_length += summary.length
-
- # Sort by length
- summaries.sort(reverse=True, key=lambda s: s.length)
-
- percent_sum = 0.0
- skipped_entries = 0
-
- print("===========================================")
- print("Total length: {:,} bytes".format(total_length))
- print("Displayed upper percent: {:0.2f}%".format(upper_percent))
- print("===========================================")
- print("")
- print("name,length,percent_of_total,upper_percent")
- for sum in summaries:
- percent_of_total = (sum.length * 1.0) / (total_length * 1.0) * 100.0
-
- percent_sum += percent_of_total
-
- if percent_sum > upper_percent:
- skipped_entries = skipped_entries + 1
- continue
-
- #print("%s,%d,%.2f%%" %(sum.name, sum.length, percent_of_total))
- print("{:s},{:d},{:0.2f}%,{:0.2f}%".format(sum.name, sum.length, percent_of_total, percent_sum))
-
- if skipped_entries > 0:
- print("[WARNING] Skipped {:d} entries, use -up=100 to show everything".format(skipped_entries))
-
- pass
-
-class FileEntry(NamedTuple):
- id: int
- name: str
- offset: int
- length: int
-
-class FileEntrySummary(NamedTuple):
- name: str
- length: int
-
-def entries_sum(entries: List[FileEntry]) -> FileEntrySummary:
- if not entries:
- return None
-
- summary = FileEntrySummary(name=entries[0].name, length=0)
- for entry in entries:
- summary = FileEntrySummary(summary.name, summary.length + entry.length)
-
- return summary
-
-def convert_to_dict(trace_file: TraceFile) -> Dict[str, FileEntry]:
- trace_file_index = trace_file.index
-
- # entries.id -> entry.file_name
- entries_map = {}
-
- index_entries = trace_file_index.entries
- for entry in index_entries:
- entries_map[entry.id] = entry.file_name
-
- final_map = {}
-
- file_entries_map = {}
- file_entries = trace_file.list.entries
- for entry in file_entries:
- print_utils.debug_print(entry)
-
- lst = file_entries_map.get(entry.index_id, [])
- file_entries_map[entry.index_id] = lst
-
- file_name = entries_map[entry.index_id]
- file_entry = \
- FileEntry(id=entry.index_id, name=file_name, offset=entry.file_offset, length=entry.file_length)
-
- lst.append(file_entry)
-
- final_map[file_name] = lst
-
- return final_map
-
-def main(argv: List[str]) -> int:
- opts = parse_options(argv[1:])
- if opts.debug:
- print_utils.DEBUG = opts.debug
- print_utils.debug_print(opts)
-
- prefetch_file = open_iorap_prefetch_file(opts.input)
-
- if opts.raw:
- print(prefetch_file)
-
- print_stats_summary(prefetch_file, opts.upper_percent)
-
- return 0
-
-if __name__ == '__main__':
- sys.exit(main(sys.argv))
diff --git a/startop/scripts/iorap/collector b/startop/scripts/iorap/collector
deleted file mode 100755
index 3dc080a5ac9c..000000000000
--- a/startop/scripts/iorap/collector
+++ /dev/null
@@ -1,403 +0,0 @@
-#!/bin/bash
-#
-# 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.
-
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-APP_STARTUP_DIR="$DIR/../app_startup/"
-source "$DIR/common"
-
-usage() {
- cat <<EOF
-Usage: collector [OPTIONS]...
-
-Runs an application, causes an iorap trace to be collected for it, and then invokes the iorap
-compiler to generate a TraceFile.pb.
-
- -p, --package package of the app to test
- -a, --activity activity of the app to test
- -h, --help usage information (this)
- -v, --verbose enable extra verbose printing
- -i, --inodes path to inodes file (system/extras/pagecache/pagecache.py -d inodes)
- -b, --trace_buffer_size how big to make trace buffer size (default 32768)
- -w, --wait_time how long to run systrace for (default 10) in seconds
- -c, --compiler-filter override the compilation filter if set (default none)
- -o, --output output trace file protobuf (default 'TraceFile.pb')
-EOF
-}
-
-
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-
-trace_buffer_size=32768
-wait_time=10
-comp_filter=""
-output_dest="TraceFile.pb"
-
-parse_arguments() {
- while [[ $# -gt 0 ]]; do
- case "$1" in
- -a|--activity)
- activity="$2"
- shift
- ;;
- -h|--help)
- usage
- exit 0
- ;;
- -p|--package)
- package="$2"
- shift
- ;;
- -i|--inodes)
- inodes="$2"
- shift
- ;;
- -b|--trace_buffer_size)
- trace_buffer_size="$2"
- shift
- ;;
- -w|--wait_time)
- wait_time="$2"
- shift
- ;;
- -c|--compiler-filter)
- comp_filter="$2"
- shift
- ;;
- -o|--output)
- output_dest="$2"
- shift
- ;;
- -v|--verbose)
- verbose="y"
- ;;
- esac
- shift
- done
-}
-
-remote_pidof() {
- local procname="$1"
- adb shell ps | grep "$procname" | awk '{print $2;}'
-}
-
-remote_pkill() {
- local procname="$1"
- shift
-
- local the_pids=$(remote_pidof "$procname")
- local pid
-
- for pid in $the_pids; do
- verbose_print adb shell kill "$@" "$pid"
- adb shell kill "$@" "$pid"
- done
-}
-
-force_package_compilation() {
- local arg_comp_filter="$1"
- local arg_package="$2"
-
- if [[ $arg_comp_filter == speed-profile ]]; then
- # Force the running app to dump its profiles to disk.
- remote_pkill "$arg_package" -SIGUSR1
- sleep 1 # give some time for above to complete.
- fi
-
- adb shell cmd package compile -m "$arg_comp_filter" -f "$arg_package"
-}
-
-parse_package_dumpsys_line() {
- local what_left="$1"
- local what_right="$2"
- local line="$3"
-
- if [[ $line == *${what_left}*${what_right}* ]]; then
- found="${line#*$what_left}"
- found="${found%$what_right*}"
- echo "$found"
- return 0
- fi
-
- return 1
-}
-
-parse_package_dumpsys_section() {
- local what_left="$1"
- local what_right="$2"
- shift
- local lines="$@"
-
- lines="${lines//$'\n'/}"
-
- local new_lines=()
-
- local current_line=""
- local newline=n
- local line
- for line in "${lines[@]}"; do
- if [[ $line == *: ]]; then
- newline=y
- current_line=""
- new_lines+=("$current_line")
-
- parse_package_dumpsys_line "$what_left" "$what_right" "$current_line" && return 0
- else
- # strip all spaces from the start
- line="${line//$' '/}"
- current_line+="$line"
- #prepend to current line
- fi
- done
- [[ "$current_line" != "" ]] && new_lines+=("$current_line")
-
- parse_package_dumpsys_line "$what_left" "$what_right" "$current_line" && return 0
-
- return 1
-}
-
-parse_package_compilation() {
- local pkg="$1"
-# [com.google.android.apps.maps]
-
- local compilation_filter
- local is_prebuilt
- local isa
- local etc
-
- local ret_code
-
- read compilation_filter is_prebuilt isa etc <<< "$("$APP_STARTUP_DIR"/query_compiler_filter.py --package "$pkg")"
- ret_code=$?
-
- if [[ $ret_code -eq 0 && x$compilation_filter != x ]]; then
- verbose_print "Package compilation info for $pkg was '$compilation_filter'"
- echo "$compilation_filter"
- return 0
- else
- verbose_print "query failed ret code $ret_code filter=$compilation_filter"
- fi
-
- return $ret_code
-}
-
-# Main entry point
-if [[ $# -eq 0 ]]; then
- usage
- exit 1
-else
- parse_arguments "$@"
-
- # if we do not have have package exit early with an error
- [[ "$package" == "" ]] && echo "--package not specified" 1>&2 && exit 1
-
- if [[ -z "$inodes" ]] || ! [[ -f $inodes ]]; then
- echo "--inodes not specified" 1>&2
- exit 1
- fi
-
- if [[ "$activity" == "" ]]; then
- activity="$(get_activity_name "$package")"
- if [[ "$activity" == "" ]]; then
- echo "Activity name could not be found, invalid package name?" 1>&2
- exit 1
- else
- verbose_print "Activity name inferred: " "$activity"
- fi
- fi
-fi
-
-adb root > /dev/null
-
-if [[ "$(adb shell getenforce)" != "Permissive" ]]; then
- adb shell setenforce 0
- adb shell stop
- adb shell start
- adb wait-for-device
-fi
-
-compilation_was="$(parse_package_compilation "$package")"
-if [[ $? -ne 0 ]]; then
- echo "Could not determine package compilation filter; was this package installed?" >&2
- exit 1
-fi
-verbose_print "Package compilation: $compilation_was"
-
-# Cannot downgrade (e.g. from speed-profile to quicken) without forceful recompilation.
-# Forceful recompilation will recompile even if compilation filter was unchanged.
-# Therefore avoid recompiling unless the filter is actually different than what we asked for.
-if [[ "x$comp_filter" != "x" ]] && [[ "$compilation_was" != "$comp_filter" ]]; then
- echo "Current compilation filter is '$compilation_was'; force recompile to '$comp_filter'" >&2
- #TODO: this matching seems hopelessly broken, it will always recompile.
-
- force_package_compilation "$comp_filter" "$package"
-fi
-
-# Drop all caches prior to beginning a systrace, otherwise we won't record anything already in pagecache.
-adb shell "echo 3 > /proc/sys/vm/drop_caches"
-
-trace_tmp_file="$(mktemp -t trace.XXXXXXXXX.html)"
-
-function finish {
- [[ -f "$trace_tmp_file" ]] && rm "$trace_tmp_file"
-}
-trap finish EXIT
-
-launch_application_and_wait_for_trace() {
- local package="$1"
- local activity="$2"
- local timeout=30 # seconds
-
- # Ensure application isn't running already.
- remote_pkill "$package"
-
- # 5 second trace of Home screen causes
- # a trace of the home screen.
- # There is no way to abort the trace
- # so just wait for it to complete instead.
- sleep 30
-
- local time_now="$(logcat_save_timestamp)"
- local retcode=0
-
- verbose_print "Drop caches for non-warm start."
- # Drop all caches to get cold starts.
- adb shell "echo 3 > /proc/sys/vm/drop_caches"
-
- verbose_print "now launching application"
- # Launch an application
- "$APP_STARTUP_DIR"/launch_application "$package" "$activity"
- retcode=$?
- if [[ $retcode -ne 0 ]]; then
- echo "FATAL: Application launch failed." >&2
- return $retcode
- fi
-
- # This blocks until 'am start' returns at which point the application is
- # already to be considered "started" as the first frame has been drawn.
-
- # TODO: check for cold start w.r.t to activitymanager?
-
- # Wait for application to start from the point of view of ActivityTaskManager.
- local pattern="ActivityTaskManager: Displayed $package"
- logcat_wait_for_pattern "$timeout" "$time_now" "$pattern"
- retcode=$?
- if [[ $retcode -ne 0 ]]; then
- echo "FATAL: Could not find '$pattern' in logcat." >&2
- return $retcode
- fi
-
- # Wait for iorapd to finish writing out the perfetto traces for this app.
- iorapd_perfetto_wait_for_app_trace "$package" "$activity" "$timeout" "$time_now"
- retcode=$?
- if [[ $retcode -ne 0 ]]; then
- echo "FATAL: Could not save perfetto app trace file." >&2
- return $retcode
- fi
-
- verbose_print "iorapd has finished collecting app trace file for $package/$activity"
-}
-
-collector_main() {
- # don't even bother trying to run anything until the screen is unlocked.
- "$APP_STARTUP_DIR"/unlock_screen
-
- # Don't mutate state while iorapd is running.
- iorapd_stop || return $?
-
- # Remove all existing metadata for a package/activity in iorapd.
- iorapd_perfetto_purge_app_trace "$package" "$activity" || return $?
- iorapd_compiler_purge_trace_file "$package" "$activity" || return $?
-
- iorapd_perfetto_enable || return $?
- iorapd_readahead_disable || return $?
- iorapd_start || return $?
-
- # Wait for perfetto trace to finished writing itself out.
- launch_application_and_wait_for_trace "$package" "$activity" || return $?
-
- # Pull the perfetto trace for manual inspection.
- iorapd_perfetto_pull_trace_file "$package" "$activity" "perfetto_trace.pb"
-
- # Compile the trace so that the next app run can use prefetching.
- iorapd_compiler_for_app_trace "$package" "$activity" "$inodes" || return $?
-
- # Save TraceFile.pb to local file.
- iorapd_compiler_pull_trace_file "$package" "$activity" "$output_dest" || return $?
- # Remove the TraceFile.pb from the device.
- iorapd_compiler_purge_trace_file "$package" "$activity" || return $?
-
- # TODO: better transactional support for restoring iorapd global properties
- iorapd_perfetto_disable || return $?
-}
-
-collector_main "$@"
-
-verbose_print "Collector finished. Children: "
-if [[ $verbose == y ]]; then
- jobs -p
- ps f -g$$
-fi
-
-exit $?
-
-
-verbose_print "About to begin systrace"
-coproc systrace_fd {
- # Disable stdout buffering since we need to know the output of systrace RIGHT AWAY.
- stdbuf -oL "$ANDROID_BUILD_TOP"/external/chromium-trace/systrace.py --target=android -b "$trace_buffer_size" -t "$wait_time" am pagecache dalvik -o "$trace_tmp_file"
-}
-
-verbose_print "Systrace began"
-
-systrace_pid="$!"
-
-while read -r -u "${systrace_fd[0]}" systrace_output; do
- verbose_print "$systrace_output"
- if [[ "$systrace_output" == *"Starting tracing"* ]]; then
- verbose_print "WE DID SEE STARTING TRACING."
- break
- fi
-done
-# Systrace has begun recording the tracing.
-# Run the application and collect the results.
-
-am_output="$(adb shell am start -S -W "$package"/"$activity")"
-if [[ $? -ne 0 ]]; then
- echo "am start failed" >&2
-
- exit 1
-fi
-
-verbose_print "$am_output"
-total_time="$(echo "$am_output" | grep 'TotalTime:' | sed 's/TotalTime: //g')"
-verbose_print "total time: $total_time"
-
-# Now wait for systrace to finish.
-
-wait "$systrace_pid" || { echo "Systrace finished before am start was finished, try a longer --wait_time"; exit 1; }
-verbose_print "Systrace has now finished"
-verbose_print "$(ls -la "$trace_tmp_file")"
-
-
-iorapd_perfetto_disable
-
-# Now that systrace has finished, convert the trace file html file to a protobuf.
-
-"$ANDROID_BUILD_TOP"/system/iorap/src/py/collector/trace_parser.py -i "$inodes" -t "$trace_tmp_file" -o "$output_dest" || exit 1
-
-echo "Trace file collection complete, trace file saved to \"$output_dest\"!" >&2
-
-finish
diff --git a/startop/scripts/iorap/common b/startop/scripts/iorap/common
deleted file mode 100755
index 387e45d431bd..000000000000
--- a/startop/scripts/iorap/common
+++ /dev/null
@@ -1,253 +0,0 @@
-#!/bin/bash
-#
-# 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.
-
-DIR_IORAP_COMMON="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-APP_STARTUP_DIR="$DIR_IORAP_COMMON/../app_startup/"
-source "$APP_STARTUP_DIR/lib/common"
-
-IORAPD_DATA_PATH="/data/misc/iorapd"
-
-iorapd_start() {
- verbose_print 'iorapd_start'
- adb shell start iorapd
- sleep 1
- # TODO: block until logcat prints successfully connecting
-}
-
-iorapd_stop() {
- verbose_print 'iorapd_stop'
- adb shell stop iorapd
-}
-
-iorapd_reset() {
- iorapd_stop
- iorapd_start
-}
-
-# Enable perfetto tracing.
-# Subsequent launches of an application will record a perfetto trace protobuf.
-iorapd_perfetto_enable() {
- verbose_print 'enable perfetto'
- adb shell setprop iorapd.perfetto.enable true
- iorapd_reset # iorapd only reads this flag when initializing
-}
-
-# Disable perfetto tracing.
-# Subsequent launches of applications will no longer record perfetto trace protobufs.
-iorapd_perfetto_disable() {
- verbose_print 'disable perfetto'
- adb shell setprop iorapd.perfetto.enable false
- iorapd_reset # iorapd only reads this flag when initializing
-}
-
-# Enable readahead
-# Subsequent launches of an application will be sped up by iorapd readahead prefetching
-# (Provided an appropriate compiled trace exists for that application)
-iorapd_readahead_enable() {
- if [[ "$(adb shell getprop iorapd.readahead.enable)" == true ]]; then
- verbose_print 'enable readahead [already enabled]'
- return 0
- fi
- verbose_print 'enable readahead [reset iorapd]'
- adb shell setprop iorapd.readahead.enable true
- iorapd_reset # iorapd only reads this flag when initializing
-}
-
-# Disable readahead
-# Subsequent launches of an application will be not be sped up by iorapd readahead prefetching.
-iorapd_readahead_disable() {
- if [[ "$(adb shell getprop iorapd.readahead.enable)" == false ]]; then
- verbose_print 'disable readahead [already disabled]'
- return 0
- fi
- verbose_print 'disable readahead [reset iorapd]'
- adb shell setprop iorapd.readahead.enable false
- iorapd_reset # iorapd only reads this flag when initializing
-}
-
-_iorapd_path_to_data_file() {
- local package="$1"
- local activity="$2"
- local suffix="$3"
-
- # Match logic of 'AppComponentName' in iorap::compiler C++ code.
- echo "${IORAPD_DATA_PATH}/${package}%2F${activity}.${suffix}"
-}
-
-iorapd_perfetto_wait_for_app_trace() {
- local package="$1"
- local activity="$2"
- local timeout="$3"
- local timestamp="$4"
-
- local remote_path="$(_iorapd_path_to_data_file "$package" "$activity" "perfetto_trace.pb")"
-
- verbose_print "iorapd_perfetto_wait_for_app_trace on file '$remote_path'"
-
- # see event_manager.cc
- local pattern="Perfetto TraceBuffer saved to file: $remote_path"
- logcat_wait_for_pattern "$timeout" "$timestamp" "$pattern"
-}
-
-# Purge all perfetto traces for a given application.
-iorapd_perfetto_purge_app_trace() {
- local package="$1"
- local activity="$2"
-
- local remote_path="$(_iorapd_path_to_data_file "$package" "$activity" "perfetto_trace.pb")"
-
- verbose_print 'iorapd-perfetto: purge app trace in ' "$remote_path"
- adb shell "[[ -f '$remote_path' ]] && rm -f '$remote_path' || exit 0"
-}
-
-# Pull the remote perfetto trace file into a local file.
-iorapd_perfetto_pull_trace_file() {
- local package="$1"
- local activity="$2"
- local output_file="$3" # local path
-
- local compiled_path="$(_iorapd_path_to_data_file "$package" "$activity" "perfetto_trace.pb")"
-
- if ! adb shell "[[ -f '$compiled_path' ]]"; then
- echo "Error: Remote path '$compiled_path' invalid" >&2
- return 1
- fi
- if ! mkdir -p "$(dirname "$output_file")"; then
- echo "Error: Fail to make output directory for '$output_file'" >&2
- return 1
- fi
- verbose_print adb pull "$compiled_path" "$output_file"
- adb pull "$compiled_path" "$output_file"
-}
-
-# Compile a perfetto trace for a given application.
-# This requires the app has run at least once with perfetto tracing enabled.
-iorapd_compiler_for_app_trace() {
- local package="$1"
- local activity="$2"
- local inodes="$3" # local path
-
- # remote path calculations
- local input_path="$(_iorapd_path_to_data_file "$package" "$activity" "perfetto_trace.pb")"
- local compiled_path="$(_iorapd_path_to_data_file "$package" "$activity" "compiled_trace.tmp.pb")"
- local compiled_path_final="$(_iorapd_path_to_data_file "$package" "$activity" "compiled_trace.pb")"
-
- if ! adb shell "[[ -f '$input_path' ]]"; then
- echo "Error: Missing perfetto traces; nothing to compile. Expected: '$input_path'" >&2
- return 1
- fi
-
- if ! [[ -f $inodes ]]; then
- # We could compile using 'diskscan' but it's non-deterministic, so refuse instead.
- echo "Error: Missing inodes textcache at '$inodes'; refusing to compile." >&2
- return 1
- fi
-
- # inodes file needs to be on the device for iorap.cmd.compiler to access it
- local remote_inodes=/data/local/tmp/prefetch/inodes.txt
- adb shell "mkdir -p \"$(dirname "$remote_inodes")\"" || return 1
- verbose_print adb push "$inodes" "$remote_inodes"
- adb push "$inodes" "$remote_inodes"
-
- verbose_print 'iorapd-compiler: compile app trace in ' "$input_path"
- verbose_print adb shell "iorap.cmd.compiler '$input_path' --inode-textcache '$remote_inodes' --output-proto '$compiled_path'"
- adb shell "iorap.cmd.compiler '$input_path' --inode-textcache '$remote_inodes' --output-proto '$compiled_path'"
- retcode=$?
-
- # Don't overwrite the true 'compiled_trace.pb' unless the compiler completed without error.
- # TODO: The native compiler code should be handling its own transaction-safety.
- if [[ $retcode -eq 0 ]]; then
- adb shell "mv '$compiled_path' '$compiled_path_final'"
- else
- adb shell "[[ -f '$compiled_path' ]] && rm -f '$compiled_path'"
- fi
-
- # Clean up inodes file we just pushed.
-# adb shell "[[ -f '$remote_inodes' ]] && rm -f '$remote_inodes'"
-
- return $retcode
-}
-
-# Pull the remote compiled trace file into a local file.
-iorapd_compiler_pull_trace_file() {
- local package="$1"
- local activity="$2"
- local output_file="$3" # local path
-
- local compiled_path="$(_iorapd_path_to_data_file "$package" "$activity" "compiled_trace.pb")"
-
- if ! adb shell "[[ -f '$compiled_path' ]]"; then
- echo "Error: Remote path '$compiled_path' invalid" >&2
- return 1
- fi
- if ! mkdir -p "$(dirname "$output_file")"; then
- echo "Error: Fail to make output directory for '$output_file'" >&2
- return 1
- fi
- verbose_print adb pull "$compiled_path" "$output_file"
- adb pull "$compiled_path" "$output_file"
-}
-
-# Install a compiled trace file.
-iorapd_compiler_install_trace_file() {
- local package="$1"
- local activity="$2"
- local input_file="$3" # local path
-
- # remote path calculations
- local compiled_path="$(_iorapd_path_to_data_file "$package" "$activity" "compiled_trace.pb")"
-
- if ! [[ -f $input_file ]]; then
- echo "Error: File '$input_file' does not exist." >&2
- return 1
- fi
-
- adb shell "mkdir -p \"$(dirname "$compiled_path")\"" || return 1
-
- verbose_print adb push "$input_file" "$compiled_path"
- adb push "$input_file" "$compiled_path"
-}
-
-iorapd_compiler_purge_trace_file() {
- local package="$1"
- local activity="$2"
- local input_file="$3" # local path
-
- local remote_path="$(_iorapd_path_to_data_file "$package" "$activity" "compiled_trace.pb")"
-
- adb shell "[[ -f '$remote_path' ]] && rm -f '$remote_path' || exit 0"
-}
-
-# Blocks until the readahead for the requested package/activity has finished.
-# This assumes that the trace file was already installed, and also that
-# the application launched but not completed yet.
-iorapd_readahead_wait_until_finished() {
- local package="$1"
- local activity="$2"
- local timestamp="$3"
- local timeout="$4"
-
- if [[ $# -lt 4 ]]; then
- echo "FATAL: Expected 4 arguments (actual $# $@)" >&2
- exit 1
- fi
-
- local remote_path="$(_iorapd_path_to_data_file "$package" "$activity" "compiled_trace.pb")"
-
- # See 'read_ahead.cc' LOG(INFO).
- local pattern="Description = $remote_path"
- logcat_wait_for_pattern "$timeout" "$timestamp" "$pattern"
-}
diff --git a/startop/scripts/iorap/compile_handcrafted_file.py b/startop/scripts/iorap/compile_handcrafted_file.py
deleted file mode 100755
index 6dbbeaf91571..000000000000
--- a/startop/scripts/iorap/compile_handcrafted_file.py
+++ /dev/null
@@ -1,297 +0,0 @@
-#!/usr/bin/env python3
-#
-# 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.
-
-import argparse
-import asyncio
-import csv
-import itertools
-import os
-import re
-import struct
-import sys
-import tempfile
-import time
-import zipfile
-from typing import Any, Callable, Dict, Generic, Iterable, List, NamedTuple, TextIO, Tuple, TypeVar, Optional, Union
-
-# Include generated protos.
-dir_name = os.path.dirname(os.path.realpath(__file__))
-sys.path.append(dir_name + "/generated")
-
-from TraceFile_pb2 import *
-
-
-def parse_options(argv: List[str] = None):
- """Parse command line arguments and return an argparse Namespace object."""
- parser = argparse.ArgumentParser(description="Compile a TraceFile.proto from a manual text file.")
- # argparse considers args starting with - and -- optional in --help, even though required=True.
- # by using a named argument group --help will clearly say that it's required instead of optional.
- required_named = parser.add_argument_group('required named arguments')
-
- # optional arguments
- # use a group here to get the required arguments to appear 'above' the optional arguments in help.
- optional_named = parser.add_argument_group('optional named arguments')
- optional_named.add_argument('-opb', '--output-proto-binary', dest='output_proto_binary', action='store', help='Write binary proto output to file.')
- optional_named.add_argument('-pm', '--pinlist-meta', dest='pinlist_meta', action='store', help='Path to pinlist.meta (default=none) binary file.')
- optional_named.add_argument('-pmp', '--pinlist-meta-parent', dest='pinlist_meta_parent', action='store', help='Device path that the pinlist.meta applies to (e.g. /data/.../somefile.apk)')
- optional_named.add_argument('-i', '--input', dest='input', action='store', help='Input text file (default stdin).')
- optional_named.add_argument('-zp', '--zip_path', dest='zip_path', action='append', help='Directory containing zip files.')
- optional_named.add_argument('-d', '--debug', dest='debug', action='store_true', help='Add extra debugging output')
- optional_named.add_argument('-ot', '--output-text', dest='output_text', action='store', help='Output text file (default stdout).')
-
- return parser.parse_args(argv)
-
-# TODO: refactor this with a common library file with analyze_metrics.py
-def _debug_print(*args, **kwargs):
- """Print the args to sys.stderr if the --debug/-d flag was passed in."""
- if _debug:
- print(*args, **kwargs, file=sys.stderr)
-
-class BadInputError(Exception):
- pass
-
-InputRecord = NamedTuple('InputRecord', [('filepath', str), ('offset', int), ('length', int), ('remark', str)])
-
-def find_zip_in_paths(original_name, zip_paths):
- # /foo/bar/bax.zip -> bax.zip
- file_basename = os.path.split(original_name)[1]
-
- # the file must be located in one of the --zip-path arguments
- matched = None
- for zip_path in zip_paths:
- for dir_entry in os.listdir(zip_path):
- if dir_entry == file_basename:
- matched = os.path.join(zip_path, dir_entry)
- break
- if matched:
- break
-
- if not matched:
- raise ValueError("%s could not be found in any of the --zip_path specified." %(file_basename))
-
- _debug_print("found zip file ", file_basename, " in ", matched)
-
- if not zipfile.is_zipfile(matched):
- raise ValueError("%s is not a zip file" %(matched))
-
- return matched
-
-def handle_zip_entry(input_record, zip_paths):
-
- res = re.match("([^!]+)[!](.*)", input_record.filepath)
-
- if not res:
- return input_record
-
- # 'foo!bar'
- in_filepath = res[1] # -> 'foo'
- in_zip_entry = res[2] # -> 'bar'
-
- matched = find_zip_in_paths(in_filepath, zip_paths)
-
- zip = zipfile.ZipFile(matched)
-
- try:
- zip_info = zip.getinfo(in_zip_entry)
- except KeyError:
- raise ValueError("%s is not an item in the zip file %s" %(in_zip_entry, matched))
-
- # TODO: do we also need to add header size to this?
- in_offset = zip_info.header_offset
-
- # TODO: if a range is specified, use that instead.
- in_length = zip_info.compress_size
-
- return InputRecord(in_filepath, in_offset, in_length, 'zip entry (%s)' %(in_zip_entry))
-
-def parse_input_file(input: Iterable[str], zip_paths: List[str]) -> Iterable[InputRecord]:
- for line in input:
- line = line.strip()
-
- _debug_print("Line = ", line)
- if not line:
- _debug_print(" skip empty line", line)
- continue
- elif line[0] == "#":
- _debug_print(" skip commented line", line)
- continue
-
- res = re.match("([^\s]+)\s+(\d+)\s+(\d+)", line)
- if not res:
- raise BadInputError("Expected input of form: <str:filepath> <int:offset> <int:length>")
-
- in_filepath = res[1]
- in_offset = int(res[2])
- in_length = int(res[3])
-
- yield handle_zip_entry(InputRecord(in_filepath, in_offset, in_length, 'regular file'), zip_paths)
-
-# format:
-# (<big_endian(i32):file_offset> <big_endian(i32):range_length>)+
-PIN_META_FORMAT = ">ii"
-PIN_META_READ_SIZE = struct.calcsize(PIN_META_FORMAT)
-
-def parse_pin_meta(pin_meta_file, pinlist_meta_parent, zip_paths):
- if not pin_meta_file:
- return ()
-
- global PIN_META_FORMAT
- global PIN_META_READ_SIZE
-
- # '/data/app/com.google.android.GoogleCamera-aNQhzSznf4h_bvJ_MRbweQ==/base.apk'
- # -> 'com.google.android.GoogleCamera'
- package_name_match = re.match('/.*/(.*)-.*=/base.apk', pinlist_meta_parent)
-
- if not package_name_match:
- raise ValueError("%s did not contain the <packagename>.apk" %(pinlist_meta_parent))
-
- package_name = package_name_match[1]
- # "com.google.android.GoogleCamera" -> "GoogleCamera.apk"
- apk_name = package_name.split(".")[-1] + ".apk"
-
- path_to_zip_on_host = find_zip_in_paths(apk_name, zip_paths)
- apk_file_size = os.path.getsize(path_to_zip_on_host)
- _debug_print("APK path '%s' file size '%d'" %(path_to_zip_on_host, apk_file_size))
-
- while True:
- data = pin_meta_file.read(PIN_META_READ_SIZE)
-
- if not data:
- break
-
- (pin_offset, pin_length) = struct.unpack(PIN_META_FORMAT, data) # (offset, length)
-
- remark = 'regular file (pinlist.meta)'
-
- remaining_size = apk_file_size - pin_offset
- if remaining_size < 0:
- print("WARNING: Clamp entry (%d, %d), offset too large (max file size = %d)" %(pin_offset, pin_length, apk_file_size))
-
- pin_length = pin_length + remaining_size
- pin_offset = pin_offset + remaining_size
-
- if pin_offset < 0:
- pin_offset = 0
-
- remark += '[clamped.offset]'
-
- pin_last_offset = pin_offset + pin_length
- remaining_size = apk_file_size - pin_last_offset
-
- if remaining_size < 0:
- print("WARNING: Clamp entry (%d, %d), length too large (max file size = %d)" %(pin_offset, pin_length, apk_file_size))
- pin_length = pin_length + remaining_size
-
- remark += '[clamped.length]'
-
- yield InputRecord(pinlist_meta_parent, pin_offset, pin_length, remark)
-
-def write_text_file_output(input_records: Iterable[InputRecord], output_text_file):
- for rec in input_records:
- output_text_file.write("%s %d %d #%s\n" %(rec.filepath, rec.offset, rec.length, rec.remark))
-
-def build_trace_file(input_records: Iterable[InputRecord]) -> TraceFile:
- trace_file = TraceFile()
- trace_file_index = trace_file.index
-
- file_id_counter = 0
- file_id_map = {} # filename -> id
-
- stats_length_total = 0
- filename_stats = {} # filename -> total size
-
- for rec in input_records:
- filename = rec.filepath
-
- file_id = file_id_map.get(filename)
- if not file_id:
- file_id = file_id_counter
- file_id_map[filename] = file_id_counter
- file_id_counter = file_id_counter + 1
-
- file_index_entry = trace_file_index.entries.add()
- file_index_entry.id = file_id
- file_index_entry.file_name = filename
-
- # already in the file index, add the file entry.
- file_entry = trace_file.list.entries.add()
- file_entry.index_id = file_id
- file_entry.file_length = rec.length
- stats_length_total += file_entry.file_length
- file_entry.file_offset = rec.offset
-
- filename_stats[filename] = filename_stats.get(filename, 0) + file_entry.file_length
-
- return trace_file
-
-def main():
- global _debug
-
- options= parse_options()
- _debug = options.debug
- _debug_print("parsed options: ", options)
-
- if not options.input:
- input_file = sys.stdin
- _debug_print("input = stdin")
- else:
- input_file = open(options.input)
- _debug_print("input = (file)", options.input)
-
- if not options.output_proto_binary:
- output_proto_file = None
- else:
- output_proto_file = open(options.output_proto_binary, 'wb')
- _debug_print("output_proto_binary = ", output_proto_file)
-
- pinlist_meta_parent = options.pinlist_meta_parent
- if options.pinlist_meta:
- pin_meta_file = open(options.pinlist_meta, 'rb')
- else:
- pin_meta_file = None
-
- if (pinlist_meta_parent == None) != (pin_meta_file == None):
- print("Options must be used together: --pinlist-meta and --pinlist-meta-path")
- return 1
-
- if not options.output_text:
- output_text_file = sys.stdout
- _debug_print("output = stdout")
- else:
- output_text_file = open(options.output_text, 'w')
- _debug_print("output = (file)", options.output_text)
-
- zip_paths = options.zip_path or []
-
- input_records = list(parse_pin_meta(pin_meta_file, pinlist_meta_parent, zip_paths))
- input_records = input_records + list(parse_input_file(input_file, zip_paths))
-
- for p in input_records:
- _debug_print(p)
-
- write_text_file_output(input_records, output_text_file)
- output_text_file.close()
-
- out_proto = build_trace_file(input_records)
-
- if output_proto_file:
- output_proto_file.write(out_proto.SerializeToString())
- output_proto_file.close()
-
- return 0
-
-if __name__ == '__main__':
- sys.exit(main())
diff --git a/startop/scripts/iorap/compiler.py b/startop/scripts/iorap/compiler.py
deleted file mode 100644
index 1426d34f325d..000000000000
--- a/startop/scripts/iorap/compiler.py
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/usr/bin/env python3
-#
-# 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.
-
-import importlib
-import os
-import sys
-import tempfile
-from enum import Enum
-from typing import TextIO, List
-
-# local import
-DIR = os.path.abspath(os.path.dirname(__file__))
-sys.path.append(os.path.dirname(DIR))
-import lib.print_utils as print_utils
-
-# Type of compiler.
-class CompilerType(Enum):
- HOST = 1 # iorap.cmd.compiler on host
- DEVICE = 2 # adb shell iorap.cmd.compiler
- RI = 3 # compiler.py
-
-def compile_perfetto_trace_ri(
- argv: List[str],
- compiler) -> TextIO:
- print_utils.debug_print('Compile using RI compiler.')
- compiler_trace_file = tempfile.NamedTemporaryFile()
- argv.extend(['-o', compiler_trace_file.name])
- print_utils.debug_print(argv)
- compiler.main([''] + argv)
- return compiler_trace_file
-
-def compile_perfetto_trace_device(inodes_path: str,
- package: str,
- activity: str,
- compiler) -> TextIO:
- print_utils.debug_print('Compile using on-device compiler.')
- compiler_trace_file = tempfile.NamedTemporaryFile()
- compiler.main(inodes_path, package, activity, compiler_trace_file.name)
- return compiler_trace_file
-
-def compile(compiler_type: CompilerType,
- inodes_path: str,
- ri_compiler_argv,
- package: str,
- activity: str) -> TextIO:
- if compiler_type == CompilerType.RI:
- compiler = importlib.import_module('iorap.compiler_ri')
- compiler_trace_file = compile_perfetto_trace_ri(ri_compiler_argv,
- compiler)
- return compiler_trace_file
- if compiler_type == CompilerType.DEVICE:
- compiler = importlib.import_module('iorap.compiler_device')
- compiler_trace_file = compile_perfetto_trace_device(inodes_path,
- package,
- activity,
- compiler)
- return compiler_trace_file
-
- # Should not arrive here.
- raise ValueError('Unknown compiler type')
diff --git a/startop/scripts/iorap/compiler_device.py b/startop/scripts/iorap/compiler_device.py
deleted file mode 100644
index d941cd913fe1..000000000000
--- a/startop/scripts/iorap/compiler_device.py
+++ /dev/null
@@ -1,68 +0,0 @@
-#!/usr/bin/env python3
-#
-# 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.
-
-import argparse
-import os
-import sys
-from typing import List
-
-DIR = os.path.abspath(os.path.dirname(__file__))
-sys.path.append(os.path.dirname(DIR)) # framework/base/startop/script
-import lib.print_utils as print_utils
-import iorap.lib.iorapd_utils as iorapd_utils
-from app_startup.lib.app_runner import AppRunner
-
-IORAP_COMMON_BASH_SCRIPT = os.path.join(DIR, 'common')
-
-def parse_options(argv: List[str] = None):
- """Parses command line arguments and returns an argparse Namespace object."""
- parser = argparse.ArgumentParser(description="Compile perfetto trace file")
- required_named = parser.add_argument_group('required named arguments')
-
- required_named.add_argument('-i', dest='inodes', metavar='FILE',
- help='Read cached inode data from a file saved '
- 'earlier with pagecache.py -d')
- required_named.add_argument('-p', dest='package',
- help='Package of the app to be compiled')
-
- optional_named = parser.add_argument_group('optional named arguments')
- optional_named.add_argument('-o', dest='output',
- help='The compiled trace is stored into the output file')
- optional_named.add_argument('-a', dest='activity',
- help='Activity of the app to be compiled')
- optional_named.add_argument('-d', dest='debug', action='store_true'
- , help='Activity of the app to be compiled')
-
- return parser.parse_args(argv)
-
-def main(inodes, package, activity, output, **kwargs) -> int:
- """Entries of the program."""
- if not activity:
- activity = AppRunner.get_activity(package)
-
- passed = iorapd_utils.compile_perfetto_trace_on_device(package, activity,
- inodes)
- if passed and output:
- iorapd_utils.get_iorapd_compiler_trace(package, activity, output)
-
- return 0
-
-if __name__ == '__main__':
- opts = parse_options()
- if opts.debug:
- print_utils.DEBUG = opts.debug
- print_utils.debug_print(opts)
- sys.exit(main(**(vars(opts))))
diff --git a/startop/scripts/iorap/compiler_ri.py b/startop/scripts/iorap/compiler_ri.py
deleted file mode 100755
index 90fc8a8123c5..000000000000
--- a/startop/scripts/iorap/compiler_ri.py
+++ /dev/null
@@ -1,325 +0,0 @@
-#!/usr/bin/env python3
-
-#
-# 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.
-#
-
-#
-# Dependencies:
-#
-# $> sudo apt-get install python3-pip
-# $> pip3 install --user protobuf sqlalchemy sqlite3
-#
-
-import optparse
-import os
-import re
-import sys
-import tempfile
-from pathlib import Path
-from datetime import timedelta
-from typing import Iterable, Optional, List
-
-DIR = os.path.abspath(os.path.dirname(__file__))
-sys.path.append(os.path.dirname(DIR))
-from iorap.generated.TraceFile_pb2 import *
-from iorap.lib.inode2filename import Inode2Filename
-
-parent_dir_name = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
-sys.path.append(parent_dir_name)
-from trace_analyzer.lib.trace2db import Trace2Db, MmFilemapAddToPageCache, \
- RawFtraceEntry
-import lib.cmd_utils as cmd_utils
-
-_PAGE_SIZE = 4096 # adb shell getconf PAGESIZE ## size of a memory page in bytes.
-ANDROID_BUILD_TOP = Path(parent_dir_name).parents[3]
-TRACECONV_BIN = ANDROID_BUILD_TOP.joinpath(
- 'external/perfetto/tools/traceconv')
-
-class PageRun:
- """
- Intermediate representation for a run of one or more pages.
- """
- def __init__(self, device_number: int, inode: int, offset: int, length: int):
- self.device_number = device_number
- self.inode = inode
- self.offset = offset
- self.length = length
-
- def __str__(self):
- return "PageRun(device_number=%d, inode=%d, offset=%d, length=%d)" \
- %(self.device_number, self.inode, self.offset, self.length)
-
-def debug_print(msg):
- #print(msg)
- pass
-
-UNDER_LAUNCH = False
-
-def page_cache_entries_to_runs(page_cache_entries: Iterable[MmFilemapAddToPageCache]):
- global _PAGE_SIZE
-
- runs = [
- PageRun(device_number=pg_entry.dev, inode=pg_entry.ino, offset=pg_entry.ofs,
- length=_PAGE_SIZE)
- for pg_entry in page_cache_entries
- ]
-
- for r in runs:
- debug_print(r)
-
- print("Stats: Page runs totaling byte length: %d" %(len(runs) * _PAGE_SIZE))
-
- return runs
-
-def optimize_page_runs(page_runs):
- new_entries = []
- last_entry = None
- for pg_entry in page_runs:
- if last_entry:
- if pg_entry.device_number == last_entry.device_number and pg_entry.inode == last_entry.inode:
- # we are dealing with a run for the same exact file as a previous run.
- if pg_entry.offset == last_entry.offset + last_entry.length:
- # trivially contiguous entries. merge them together.
- last_entry.length += pg_entry.length
- continue
- # Default: Add the run without merging it to a previous run.
- last_entry = pg_entry
- new_entries.append(pg_entry)
- return new_entries
-
-def is_filename_matching_filter(file_name, filters=[]):
- """
- Blacklist-style regular expression filters.
-
- :return: True iff file_name has an RE match in one of the filters.
- """
- for filt in filters:
- res = re.search(filt, file_name)
- if res:
- return True
-
- return False
-
-def build_protobuf(page_runs, inode2filename, filters=[]):
- trace_file = TraceFile()
- trace_file_index = trace_file.index
-
- file_id_counter = 0
- file_id_map = {} # filename -> id
-
- stats_length_total = 0
- filename_stats = {} # filename -> total size
-
- skipped_inode_map = {}
- filtered_entry_map = {} # filename -> count
-
- for pg_entry in page_runs:
- fn = inode2filename.resolve(pg_entry.device_number, pg_entry.inode)
- if not fn:
- skipped_inode_map[pg_entry.inode] = skipped_inode_map.get(pg_entry.inode, 0) + 1
- continue
-
- filename = fn
-
- if filters and not is_filename_matching_filter(filename, filters):
- filtered_entry_map[filename] = filtered_entry_map.get(filename, 0) + 1
- continue
-
- file_id = file_id_map.get(filename)
- # file_id could 0, which satisfies "if file_id" and causes duplicate
- # filename for file id 0.
- if file_id is None:
- file_id = file_id_counter
- file_id_map[filename] = file_id_counter
- file_id_counter = file_id_counter + 1
-
- file_index_entry = trace_file_index.entries.add()
- file_index_entry.id = file_id
- file_index_entry.file_name = filename
-
- # already in the file index, add the file entry.
- file_entry = trace_file.list.entries.add()
- file_entry.index_id = file_id
- file_entry.file_length = pg_entry.length
- stats_length_total += file_entry.file_length
- file_entry.file_offset = pg_entry.offset
-
- filename_stats[filename] = filename_stats.get(filename, 0) + file_entry.file_length
-
- for inode, count in skipped_inode_map.items():
- print("WARNING: Skip inode %s because it's not in inode map (%d entries)" %(inode, count))
-
- print("Stats: Sum of lengths %d" %(stats_length_total))
-
- if filters:
- print("Filter: %d total files removed." %(len(filtered_entry_map)))
-
- for fn, count in filtered_entry_map.items():
- print("Filter: File '%s' removed '%d' entries." %(fn, count))
-
- for filename, file_size in filename_stats.items():
- print("%s,%s" %(filename, file_size))
-
- return trace_file
-
-def calc_trace_end_time(trace2db: Trace2Db,
- trace_duration: Optional[timedelta]) -> float:
- """
- Calculates the end time based on the trace duration.
- The start time is the first receiving mm file map event.
- The end time is the start time plus the trace duration.
- All of them are in milliseconds.
- """
- # If the duration is not set, assume all time is acceptable.
- if trace_duration is None:
- # float('inf')
- return RawFtraceEntry.__table__.c.timestamp.type.python_type('inf')
-
- first_event = trace2db.session.query(MmFilemapAddToPageCache).join(
- MmFilemapAddToPageCache.raw_ftrace_entry).order_by(
- RawFtraceEntry.timestamp).first()
-
- # total_seconds() will return a float number.
- return first_event.raw_ftrace_entry.timestamp + trace_duration.total_seconds()
-
-def query_add_to_page_cache(trace2db: Trace2Db, trace_duration: Optional[timedelta]):
- end_time = calc_trace_end_time(trace2db, trace_duration)
- # SELECT * FROM tbl ORDER BY id;
- return trace2db.session.query(MmFilemapAddToPageCache).join(
- MmFilemapAddToPageCache.raw_ftrace_entry).filter(
- RawFtraceEntry.timestamp <= end_time).order_by(
- MmFilemapAddToPageCache.id).all()
-
-def transform_perfetto_trace_to_systrace(path_to_perfetto_trace: str,
- path_to_tmp_systrace: str) -> None:
- """ Transforms the systrace file from perfetto trace. """
- cmd_utils.run_command_nofail([str(TRACECONV_BIN),
- 'systrace',
- path_to_perfetto_trace,
- path_to_tmp_systrace])
-
-
-def run(sql_db_path:str,
- trace_file:str,
- trace_duration:Optional[timedelta],
- output_file:str,
- inode_table:str,
- filter:List[str]) -> int:
- trace2db = Trace2Db(sql_db_path)
- # Speed optimization: Skip any entries that aren't mm_filemap_add_to_pagecache.
- trace2db.set_raw_ftrace_entry_filter(\
- lambda entry: entry['function'] == 'mm_filemap_add_to_page_cache')
- # TODO: parse multiple trace files here.
- parse_count = trace2db.parse_file_into_db(trace_file)
-
- mm_filemap_add_to_page_cache_rows = query_add_to_page_cache(trace2db,
- trace_duration)
- print("DONE. Parsed %d entries into sql db." %(len(mm_filemap_add_to_page_cache_rows)))
-
- page_runs = page_cache_entries_to_runs(mm_filemap_add_to_page_cache_rows)
- print("DONE. Converted %d entries" %(len(page_runs)))
-
- # TODO: flags to select optimizations.
- optimized_page_runs = optimize_page_runs(page_runs)
- print("DONE. Optimized down to %d entries" %(len(optimized_page_runs)))
-
- print("Build protobuf...")
- trace_file = build_protobuf(optimized_page_runs, inode_table, filter)
-
- print("Write protobuf to file...")
- output_file = open(output_file, 'wb')
- output_file.write(trace_file.SerializeToString())
- output_file.close()
-
- print("DONE")
-
- # TODO: Silent running mode [no output except on error] for build runs.
-
- return 0
-
-def main(argv):
- parser = optparse.OptionParser(usage="Usage: %prog [options]", description="Compile systrace file into TraceFile.pb")
- parser.add_option('-i', dest='inode_data_file', metavar='FILE',
- help='Read cached inode data from a file saved earlier with pagecache.py -d')
- parser.add_option('-t', dest='trace_file', metavar='FILE',
- help='Path to systrace file (trace.html) that will be parsed')
- parser.add_option('--perfetto-trace', dest='perfetto_trace_file',
- metavar='FILE',
- help='Path to perfetto trace that will be parsed')
-
- parser.add_option('--db', dest='sql_db', metavar='FILE',
- help='Path to intermediate sqlite3 database [default: in-memory].')
-
- parser.add_option('-f', dest='filter', action="append", default=[],
- help="Add file filter. All file entries not matching one of the filters are discarded.")
-
- parser.add_option('-l', dest='launch_lock', action="store_true", default=False,
- help="Exclude all events not inside launch_lock")
-
- parser.add_option('-o', dest='output_file', metavar='FILE',
- help='Output protobuf file')
-
- parser.add_option('--duration', dest='trace_duration', action="store",
- type=int, help='The duration of trace in milliseconds.')
-
- options, categories = parser.parse_args(argv[1:])
-
- # TODO: OptionParser should have some flags to make these mandatory.
- if not options.inode_data_file:
- parser.error("-i is required")
- if not options.trace_file and not options.perfetto_trace_file:
- parser.error("one of -t or --perfetto-trace is required")
- if options.trace_file and options.perfetto_trace_file:
- parser.error("please enter either -t or --perfetto-trace, not both")
- if not options.output_file:
- parser.error("-o is required")
-
- if options.launch_lock:
- print("INFO: Launch lock flag (-l) enabled; filtering all events not inside launch_lock.")
-
- inode_table = Inode2Filename.new_from_filename(options.inode_data_file)
-
- sql_db_path = ":memory:"
- if options.sql_db:
- sql_db_path = options.sql_db
-
- trace_duration = timedelta(milliseconds=options.trace_duration) if \
- options.trace_duration is not None else None
-
- # if the input is systrace
- if options.trace_file:
- return run(sql_db_path,
- options.trace_file,
- trace_duration,
- options.output_file,
- inode_table,
- options.filter)
-
- # if the input is perfetto trace
- # TODO python 3.7 switch to using nullcontext
- with tempfile.NamedTemporaryFile() as trace_file:
- transform_perfetto_trace_to_systrace(options.perfetto_trace_file,
- trace_file.name)
- return run(sql_db_path,
- trace_file.name,
- trace_duration,
- options.output_file,
- inode_table,
- options.filter)
-
-if __name__ == '__main__':
- print(sys.argv)
- sys.exit(main(sys.argv))
diff --git a/startop/scripts/iorap/compiler_test.py b/startop/scripts/iorap/compiler_test.py
deleted file mode 100644
index b8de70147565..000000000000
--- a/startop/scripts/iorap/compiler_test.py
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/usr/bin/env python3
-#
-# 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.
-#
-
-"""
-Unit tests for the compiler.py script.
-
-Install:
- $> sudo apt-get install python3-pytest ## OR
- $> pip install -U pytest
-See also https://docs.pytest.org/en/latest/getting-started.html
-
-Usage:
- $> pytest compiler_test.py
-
-See also https://docs.pytest.org/en/latest/usage.html
-"""
-import os
-
-import compiler_ri as compiler
-
-DIR = os.path.abspath(os.path.dirname(__file__))
-TEXTCACHE = os.path.join(DIR, 'test_fixtures/compiler/common_textcache')
-SYSTRACE = os.path.join(DIR, 'test_fixtures/compiler/common_systrace')
-ARGV = [os.path.join(DIR, 'compiler.py'), '-i', TEXTCACHE, '-t', SYSTRACE]
-PERFETTO_TRACE = os.path.join(DIR,
- 'test_fixtures/compiler/common_perfetto_trace.pb')
-
-def assert_compile_result(output, expected, *extra_argv):
- argv = ARGV + ['-o', output] + [args for args in extra_argv]
-
- compiler.main(argv)
-
- with open(output, 'rb') as f1, open(expected, 'rb') as f2:
- assert f1.read() == f2.read()
-
-### Unit tests - testing compiler code directly
-def test_transform_perfetto_trace_to_systrace(tmpdir):
- expected = os.path.join(DIR,
- 'test_fixtures/compiler/test_result_systrace')
- output = tmpdir.mkdir('compiler').join('tmp_systrace')
-
- compiler.transform_perfetto_trace_to_systrace(PERFETTO_TRACE, str(output))
-
- with open(output, 'rb') as f1, open(expected, 'rb') as f2:
- assert f1.read() == f2.read()
-
-### Functional tests - calls 'compiler.py --args...'
-def test_compiler_main(tmpdir):
- output = tmpdir.mkdir('compiler').join('output')
-
- # No duration
- expected = os.path.join(DIR,
- 'test_fixtures/compiler/test_result_without_duration.TraceFile.pb')
- assert_compile_result(output, expected)
-
- # 10ms duration
- expected = os.path.join(DIR,
- 'test_fixtures/compiler/test_result_with_duration.TraceFile.pb')
- assert_compile_result(output, expected, '--duration', '10000')
-
- # 30ms duration
- expected = os.path.join(DIR,
- 'test_fixtures/compiler/test_result_without_duration.TraceFile.pb')
- assert_compile_result(output, expected, '--duration', '30000')
diff --git a/startop/scripts/iorap/dump_compiled_pb b/startop/scripts/iorap/dump_compiled_pb
deleted file mode 100755
index ad26a7d72c53..000000000000
--- a/startop/scripts/iorap/dump_compiled_pb
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/bash
-#
-# 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.
-
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-
-#
-# Dumps an iorap compiler protobuf from iorap.cmd.compiler into text
-# with gqui.
-#
-
-if [[ "$#" -lt 1 ]]; then
- echo "Usage: $0 <compiler_trace_file.pb> [...args]" >&2
- exit 1
-fi
-
-path_to_proto="$DIR/../../../../../system/iorap/src/serialize/TraceFile.proto"
-
-filename="$1"
-shift
-if ! [[ -f $filename ]]; then
- echo "Error: $filename does not exist." >&2
- exit 1
-fi
-
-gqui "rawproto:$filename" proto "$path_to_proto":iorap.serialize.proto.TraceFile "$@"
diff --git a/startop/scripts/iorap/dump_trace_pb b/startop/scripts/iorap/dump_trace_pb
deleted file mode 100755
index bcec4a524994..000000000000
--- a/startop/scripts/iorap/dump_trace_pb
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/bash
-#
-# 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.
-
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-
-#
-# Dumps a perfetto protobuf collected by iorapd (from perfetto) into text
-# with gqui.
-#
-
-if [[ "$#" -lt 1 ]]; then
- echo "Usage: $0 <perfetto_trace.pb> [...args]" >&2
- exit 1
-fi
-
-path_to_perfetto_proto="$DIR/../../../../../external/perfetto/protos/perfetto/trace/perfetto_trace.proto"
-
-filename="$1"
-shift
-if ! [[ -f $filename ]]; then
- echo "Error: $filename does not exist." >&2
- exit 1
-fi
-
-gqui "rawproto:$filename" proto "$path_to_perfetto_proto":perfetto.protos.Trace "$@"
diff --git a/startop/scripts/iorap/generated/TraceFile_pb2.py b/startop/scripts/iorap/generated/TraceFile_pb2.py
deleted file mode 100644
index f005bed427ca..000000000000
--- a/startop/scripts/iorap/generated/TraceFile_pb2.py
+++ /dev/null
@@ -1,259 +0,0 @@
-# Generated by the protocol buffer compiler. DO NOT EDIT!
-# source: TraceFile.proto
-
-import sys
-_b=sys.version_info[0]<3 and (lambda x:x) or (lambda x:x.encode('latin1'))
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import message as _message
-from google.protobuf import reflection as _reflection
-from google.protobuf import symbol_database as _symbol_database
-from google.protobuf import descriptor_pb2
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-
-
-DESCRIPTOR = _descriptor.FileDescriptor(
- name='TraceFile.proto',
- package='iorap.serialize.proto',
- syntax='proto2',
- serialized_pb=_b('\n\x0fTraceFile.proto\x12\x15iorap.serialize.proto\"u\n\tTraceFile\x12\x34\n\x05index\x18\x01 \x02(\x0b\x32%.iorap.serialize.proto.TraceFileIndex\x12\x32\n\x04list\x18\x02 \x02(\x0b\x32$.iorap.serialize.proto.TraceFileList\"M\n\x0eTraceFileIndex\x12;\n\x07\x65ntries\x18\x01 \x03(\x0b\x32*.iorap.serialize.proto.TraceFileIndexEntry\"4\n\x13TraceFileIndexEntry\x12\n\n\x02id\x18\x01 \x02(\x03\x12\x11\n\tfile_name\x18\x02 \x02(\t\"G\n\rTraceFileList\x12\x36\n\x07\x65ntries\x18\x01 \x03(\x0b\x32%.iorap.serialize.proto.TraceFileEntry\"L\n\x0eTraceFileEntry\x12\x10\n\x08index_id\x18\x01 \x02(\x03\x12\x13\n\x0b\x66ile_offset\x18\x02 \x02(\x03\x12\x13\n\x0b\x66ile_length\x18\x03 \x02(\x03\x42\x1c\n\x18\x63om.google.android.iorapH\x03')
-)
-_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-
-
-
-
-_TRACEFILE = _descriptor.Descriptor(
- name='TraceFile',
- full_name='iorap.serialize.proto.TraceFile',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='index', full_name='iorap.serialize.proto.TraceFile.index', index=0,
- number=1, type=11, cpp_type=10, label=2,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='list', full_name='iorap.serialize.proto.TraceFile.list', index=1,
- number=2, type=11, cpp_type=10, label=2,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=42,
- serialized_end=159,
-)
-
-
-_TRACEFILEINDEX = _descriptor.Descriptor(
- name='TraceFileIndex',
- full_name='iorap.serialize.proto.TraceFileIndex',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='entries', full_name='iorap.serialize.proto.TraceFileIndex.entries', index=0,
- number=1, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=161,
- serialized_end=238,
-)
-
-
-_TRACEFILEINDEXENTRY = _descriptor.Descriptor(
- name='TraceFileIndexEntry',
- full_name='iorap.serialize.proto.TraceFileIndexEntry',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='id', full_name='iorap.serialize.proto.TraceFileIndexEntry.id', index=0,
- number=1, type=3, cpp_type=2, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='file_name', full_name='iorap.serialize.proto.TraceFileIndexEntry.file_name', index=1,
- number=2, type=9, cpp_type=9, label=2,
- has_default_value=False, default_value=_b("").decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=240,
- serialized_end=292,
-)
-
-
-_TRACEFILELIST = _descriptor.Descriptor(
- name='TraceFileList',
- full_name='iorap.serialize.proto.TraceFileList',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='entries', full_name='iorap.serialize.proto.TraceFileList.entries', index=0,
- number=1, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=294,
- serialized_end=365,
-)
-
-
-_TRACEFILEENTRY = _descriptor.Descriptor(
- name='TraceFileEntry',
- full_name='iorap.serialize.proto.TraceFileEntry',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- fields=[
- _descriptor.FieldDescriptor(
- name='index_id', full_name='iorap.serialize.proto.TraceFileEntry.index_id', index=0,
- number=1, type=3, cpp_type=2, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='file_offset', full_name='iorap.serialize.proto.TraceFileEntry.file_offset', index=1,
- number=2, type=3, cpp_type=2, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- _descriptor.FieldDescriptor(
- name='file_length', full_name='iorap.serialize.proto.TraceFileEntry.file_length', index=2,
- number=3, type=3, cpp_type=2, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- options=None),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=367,
- serialized_end=443,
-)
-
-_TRACEFILE.fields_by_name['index'].message_type = _TRACEFILEINDEX
-_TRACEFILE.fields_by_name['list'].message_type = _TRACEFILELIST
-_TRACEFILEINDEX.fields_by_name['entries'].message_type = _TRACEFILEINDEXENTRY
-_TRACEFILELIST.fields_by_name['entries'].message_type = _TRACEFILEENTRY
-DESCRIPTOR.message_types_by_name['TraceFile'] = _TRACEFILE
-DESCRIPTOR.message_types_by_name['TraceFileIndex'] = _TRACEFILEINDEX
-DESCRIPTOR.message_types_by_name['TraceFileIndexEntry'] = _TRACEFILEINDEXENTRY
-DESCRIPTOR.message_types_by_name['TraceFileList'] = _TRACEFILELIST
-DESCRIPTOR.message_types_by_name['TraceFileEntry'] = _TRACEFILEENTRY
-
-TraceFile = _reflection.GeneratedProtocolMessageType('TraceFile', (_message.Message,), dict(
- DESCRIPTOR = _TRACEFILE,
- __module__ = 'TraceFile_pb2'
- # @@protoc_insertion_point(class_scope:iorap.serialize.proto.TraceFile)
- ))
-_sym_db.RegisterMessage(TraceFile)
-
-TraceFileIndex = _reflection.GeneratedProtocolMessageType('TraceFileIndex', (_message.Message,), dict(
- DESCRIPTOR = _TRACEFILEINDEX,
- __module__ = 'TraceFile_pb2'
- # @@protoc_insertion_point(class_scope:iorap.serialize.proto.TraceFileIndex)
- ))
-_sym_db.RegisterMessage(TraceFileIndex)
-
-TraceFileIndexEntry = _reflection.GeneratedProtocolMessageType('TraceFileIndexEntry', (_message.Message,), dict(
- DESCRIPTOR = _TRACEFILEINDEXENTRY,
- __module__ = 'TraceFile_pb2'
- # @@protoc_insertion_point(class_scope:iorap.serialize.proto.TraceFileIndexEntry)
- ))
-_sym_db.RegisterMessage(TraceFileIndexEntry)
-
-TraceFileList = _reflection.GeneratedProtocolMessageType('TraceFileList', (_message.Message,), dict(
- DESCRIPTOR = _TRACEFILELIST,
- __module__ = 'TraceFile_pb2'
- # @@protoc_insertion_point(class_scope:iorap.serialize.proto.TraceFileList)
- ))
-_sym_db.RegisterMessage(TraceFileList)
-
-TraceFileEntry = _reflection.GeneratedProtocolMessageType('TraceFileEntry', (_message.Message,), dict(
- DESCRIPTOR = _TRACEFILEENTRY,
- __module__ = 'TraceFile_pb2'
- # @@protoc_insertion_point(class_scope:iorap.serialize.proto.TraceFileEntry)
- ))
-_sym_db.RegisterMessage(TraceFileEntry)
-
-
-DESCRIPTOR.has_options = True
-DESCRIPTOR._options = _descriptor._ParseOptions(descriptor_pb2.FileOptions(), _b('\n\030com.google.android.iorapH\003'))
-# @@protoc_insertion_point(module_scope)
diff --git a/startop/scripts/iorap/generated/codegen_protos b/startop/scripts/iorap/generated/codegen_protos
deleted file mode 100755
index 5688711ec25d..000000000000
--- a/startop/scripts/iorap/generated/codegen_protos
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/bin/bash
-#
-# 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.
-
-DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-APROTOC="$(which aprotoc)"
-
-IORAP_SERIALIZE_DIR="${DIR}/../../../../../../system/iorap/src/serialize"
-IORAP_PROTOS=($IORAP_SERIALIZE_DIR/*.proto)
-
-if [[ $? -ne 0 ]]; then
- echo "Fatal: Missing aprotoc. Set APROTOC=... or lunch build/envsetup.sh?" >&2
- exit 1
-fi
-
-if ! [[ -d $IORAP_SERIALIZE_DIR ]]; then
- echo "Fatal: Directory '$IORAP_SERIALIZE_DIR' does not exist." >&2
- exit 1
-fi
-
-# codegen the .py files into the same directory as this script.
-echo "$APROTOC" --proto_path="$IORAP_SERIALIZE_DIR" --python_out="$DIR" "${IORAP_PROTOS[@]}"
-"$APROTOC" --proto_path="$IORAP_SERIALIZE_DIR" --python_out="$DIR" "${IORAP_PROTOS[@]}"
diff --git a/startop/scripts/iorap/lib/inode2filename.py b/startop/scripts/iorap/lib/inode2filename.py
deleted file mode 100644
index 2e713936319a..000000000000
--- a/startop/scripts/iorap/lib/inode2filename.py
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/usr/bin/env python3
-
-#
-# 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.
-#
-
-from typing import Any, Callable, Dict, Generic, Iterable, List, NamedTuple, TextIO, Tuple, TypeVar, Optional, Union, TextIO
-
-import re
-
-class Inode2Filename:
- """
- Parses a text file of the format
- "uint(dev_t) uint(ino_t) int(file_size) string(filepath)\\n"*
-
- Lines not matching this format are ignored.
- """
-
- def __init__(self, inode_data_file: TextIO):
- """
- Create an Inode2Filename that reads cached inode from a file saved earlier
- (e.g. with pagecache.py -d or with inode2filename --format=textcache)
-
- :param inode_data_file: a file object (e.g. created with open or StringIO).
-
- Lifetime: inode_data_file is only used during the construction of the object.
- """
- self._inode_table = Inode2Filename.build_inode_lookup_table(inode_data_file)
-
- @classmethod
- def new_from_filename(cls, textcache_filename: str) -> 'Inode2Filename':
- """
- Create an Inode2Filename that reads cached inode from a file saved earlier
- (e.g. with pagecache.py -d or with inode2filename --format=textcache)
-
- :param textcache_filename: path to textcache
- """
- with open(textcache_filename) as inode_data_file:
- return cls(inode_data_file)
-
- @staticmethod
- def build_inode_lookup_table(inode_data_file: TextIO) -> Dict[Tuple[int, int], Tuple[str, str]]:
- """
- :return: map { (device_int, inode_int) -> (filename_str, size_str) }
- """
- inode2filename = {}
- for line in inode_data_file:
- # stat -c "%d %i %s %n
- # device number, inode number, total size in bytes, file name
- result = re.match('([0-9]+)d? ([0-9]+) -?([0-9]+) (.*)', line)
- if result:
- inode2filename[(int(result.group(1)), int(result.group(2)))] = \
- (result.group(4), result.group(3))
-
- return inode2filename
-
- def resolve(self, dev_t: int, ino_t: int) -> Optional[str]:
- """
- Return a filename (str) from a (dev_t, ino_t) inode pair.
-
- Returns None if the lookup fails.
- """
- maybe_result = self._inode_table.get((dev_t, ino_t))
-
- if not maybe_result:
- return None
-
- return maybe_result[0] # filename str
-
- def __len__(self) -> int:
- """
- :return: the number of inode entries parsed from the file.
- """
- return len(self._inode_table)
-
- def __repr__(self) -> str:
- """
- :return: string representation for debugging/test failures.
- """
- return "Inode2Filename%s" %(repr(self._inode_table))
-
- # end of class.
diff --git a/startop/scripts/iorap/lib/inode2filename_test.py b/startop/scripts/iorap/lib/inode2filename_test.py
deleted file mode 100755
index 1224c61da641..000000000000
--- a/startop/scripts/iorap/lib/inode2filename_test.py
+++ /dev/null
@@ -1,83 +0,0 @@
-#!/usr/bin/env python3
-#
-# 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.
-#
-
-"""
-Unit tests for inode2filename module.
-
-Install:
- $> sudo apt-get install python3-pytest ## OR
- $> pip install -U pytest
-See also https://docs.pytest.org/en/latest/getting-started.html
-
-Usage:
- $> ./inode2filename_test.py
- $> pytest inode2filename_test.py
- $> python -m pytest inode2filename_test.py
-
-See also https://docs.pytest.org/en/latest/usage.html
-"""
-
-# global imports
-from contextlib import contextmanager
-import io
-import shlex
-import sys
-import typing
-
-# pip imports
-import pytest
-
-# local imports
-from inode2filename import *
-
-def create_inode2filename(*contents):
- buf = io.StringIO()
-
- for c in contents:
- buf.write(c)
- buf.write("\n")
-
- buf.seek(0)
-
- i2f = Inode2Filename(buf)
-
- buf.close()
-
- return i2f
-
-def test_inode2filename():
- a = create_inode2filename("")
- assert len(a) == 0
- assert a.resolve(1, 2) == None
-
- a = create_inode2filename("1 2 3 foo.bar")
- assert len(a) == 1
- assert a.resolve(1, 2) == "foo.bar"
- assert a.resolve(4, 5) == None
-
- a = create_inode2filename("1 2 3 foo.bar", "4 5 6 bar.baz")
- assert len(a) == 2
- assert a.resolve(1, 2) == "foo.bar"
- assert a.resolve(4, 5) == "bar.baz"
-
- a = create_inode2filename("1567d 8910 -1 /a/b/c/", "4 5 6 bar.baz")
- assert len(a) == 2
- assert a.resolve(1567, 8910) == "/a/b/c/"
- assert a.resolve(4, 5) == "bar.baz"
-
-if __name__ == '__main__':
- pytest.main()
diff --git a/startop/scripts/iorap/lib/iorapd_utils.py b/startop/scripts/iorap/lib/iorapd_utils.py
deleted file mode 100644
index f6f21fd70005..000000000000
--- a/startop/scripts/iorap/lib/iorapd_utils.py
+++ /dev/null
@@ -1,175 +0,0 @@
-#!/usr/bin/env python3
-#
-# 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.
-
-"""Helper util libraries for iorapd related operations."""
-
-import os
-import sys
-
-# up to two level
-sys.path.append(os.path.join(os.path.abspath(__file__),'../..'))
-import lib.cmd_utils as cmd_utils
-
-IORAPID_LIB_DIR = os.path.abspath(os.path.dirname(__file__))
-IORAPD_DATA_PATH = '/data/misc/iorapd'
-IORAP_COMMON_BASH_SCRIPT = os.path.realpath(os.path.join(IORAPID_LIB_DIR,
- '../common'))
-
-def _iorapd_path_to_data_file(package: str, activity: str, suffix: str) -> str:
- """Gets conventional data filename.
-
- Returns:
- The path of iorapd data file.
-
- """
- # Match logic of 'AppComponentName' in iorap::compiler C++ code.
- return '{}/{}%2F{}.{}'.format(IORAPD_DATA_PATH, package, activity, suffix)
-
-def compile_perfetto_trace_on_device(package: str, activity: str,
- inodes: str) -> bool:
- """Compiles the perfetto trace using on-device compiler."""
- passed, _ = cmd_utils.run_shell_func(IORAP_COMMON_BASH_SCRIPT,
- 'iorapd_compiler_for_app_trace',
- [package, activity, inodes])
- return passed
-
-def get_iorapd_compiler_trace(package: str, activity: str, dest: str) -> str:
- """Gets compiler trace to dest file."""
- src = _iorapd_path_to_data_file(package, activity, 'compiled_trace.pb')
- passed, _ = cmd_utils.run_shell_command('adb pull "{}" "{}"'.format(src, dest))
- if not passed:
- return False
- return True
-
-def iorapd_compiler_install_trace_file(package: str, activity: str,
- input_file: str) -> bool:
- """Installs a compiled trace file.
-
- Returns:
- Whether the trace file is installed successful or not.
- """
- # remote path calculations
- compiled_path = _iorapd_path_to_data_file(package, activity,
- 'compiled_trace.pb')
-
- if not os.path.exists(input_file):
- print('Error: File {} does not exist'.format(input_file))
- return False
-
- passed, _ = cmd_utils.run_adb_shell_command(
- 'mkdir -p "$(dirname "{}")"'.format(compiled_path))
- if not passed:
- return False
-
- passed, _ = cmd_utils.run_shell_command('adb push "{}" "{}"'.format(
- input_file, compiled_path))
-
- return passed
-
-def wait_for_iorapd_finish(package: str,
- activity: str,
- timeout: int,
- debug: bool,
- logcat_timestamp: str)->bool:
- """Waits for the finish of iorapd.
-
- Returns:
- A bool indicates whether the iorapd is done successfully or not.
- """
- # Set verbose for bash script based on debug flag.
- if debug:
- os.putenv('verbose', 'y')
-
- # Validate that readahead completes.
- # If this fails for some reason, then this will also discard the timing of
- # the run.
- passed, _ = cmd_utils.run_shell_func(IORAP_COMMON_BASH_SCRIPT,
- 'iorapd_readahead_wait_until_finished',
- [package, activity, logcat_timestamp,
- str(timeout)])
- return passed
-
-
-def enable_iorapd_readahead() -> bool:
- """
- Disable readahead. Subsequent launches of an application will be sped up
- by iorapd readahead prefetching.
-
- Returns:
- A bool indicates whether the enabling is done successfully or not.
- """
- passed, _ = cmd_utils.run_shell_func(IORAP_COMMON_BASH_SCRIPT,
- 'iorapd_readahead_enable', [])
- return passed
-
-def disable_iorapd_readahead() -> bool:
- """
- Disable readahead. Subsequent launches of an application will be not be sped
- up by iorapd readahead prefetching.
-
- Returns:
- A bool indicates whether the disabling is done successfully or not.
- """
- passed, _ = cmd_utils.run_shell_func(IORAP_COMMON_BASH_SCRIPT,
- 'iorapd_readahead_disable', [])
- return passed
-
-def enable_iorapd_perfetto() -> bool:
- """
- Enable Perfetto. Subsequent launches of an application will record a perfetto
- trace protobuf.
-
- Returns:
- A bool indicates whether the enabling is done successfully or not.
- """
- passed, _ = cmd_utils.run_shell_func(IORAP_COMMON_BASH_SCRIPT,
- 'iorapd_perfetto_enable', [])
- return passed
-
-def disable_iorapd_perfetto() -> bool:
- """
- Disable Perfetto. Subsequent launches of applications will no longer record
- perfetto trace protobufs.
-
- Returns:
- A bool indicates whether the disabling is done successfully or not.
- """
- passed, _ = cmd_utils.run_shell_func(IORAP_COMMON_BASH_SCRIPT,
- 'iorapd_perfetto_disable', [])
- return passed
-
-def start_iorapd() -> bool:
- """
- Starts iorapd.
-
- Returns:
- A bool indicates whether the starting is done successfully or not.
- """
- passed, _ = cmd_utils.run_shell_func(IORAP_COMMON_BASH_SCRIPT,
- 'iorapd_start', [])
- return passed
-
-def stop_iorapd() -> bool:
- """
- Stops iorapd.
-
- Returns:
- A bool indicates whether the stopping is done successfully or not.
- """
- passed, _ = cmd_utils.run_shell_func(IORAP_COMMON_BASH_SCRIPT,
- 'iorapd_stop', [])
- return passed
-
diff --git a/startop/scripts/iorap/pull_textcache b/startop/scripts/iorap/pull_textcache
deleted file mode 100755
index 05544263957d..000000000000
--- a/startop/scripts/iorap/pull_textcache
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/bash
-#
-# 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.
-
-if [[ $# -lt 1 ]]; then
- echo "Usage: $0 <output-filename>" >&2
- exit 1
-fi
-
-# see compiler/main.cc for list of roots
-adb shell iorap.inode2filename --output-format=textcache --output=/data/local/tmp/dumpcache --all --root=/system --root=/apex --root=/vendor --root=/data --root=/product --root=/metadata
-adb pull /data/local/tmp/dumpcache "$1"
diff --git a/startop/scripts/iorap/test_fixtures/compiler/common_perfetto_trace.pb b/startop/scripts/iorap/test_fixtures/compiler/common_perfetto_trace.pb
deleted file mode 100644
index a47ad3d5d9ec..000000000000
--- a/startop/scripts/iorap/test_fixtures/compiler/common_perfetto_trace.pb
+++ /dev/null
Binary files differ
diff --git a/startop/scripts/iorap/test_fixtures/compiler/common_systrace b/startop/scripts/iorap/test_fixtures/compiler/common_systrace
deleted file mode 100644
index 4573738db5c6..000000000000
--- a/startop/scripts/iorap/test_fixtures/compiler/common_systrace
+++ /dev/null
@@ -1,5 +0,0 @@
-<...>-2965 (-----) [001] .... 10000.746629: mm_filemap_add_to_page_cache: dev 253:6 ino 1 page=00000000679ee1ec pfn=1299913 ofs=192512
-<...>-2965 (-----) [001] .... 10010.746664: mm_filemap_add_to_page_cache: dev 253:6 ino 2 page=0000000006cd2fb7 pfn=1296251 ofs=196608
-<...>-2965 (-----) [001] .... 10020.746677: mm_filemap_add_to_page_cache: dev 253:6 ino 3 page=00000000af82f3d6 pfn=1419330 ofs=200704
-<...>-2965 (-----) [001] .... 10030.746693: mm_filemap_add_to_page_cache: dev 253:6 ino 4 page=000000002840f054 pfn=1304928 ofs=204800
-<...>-2965 (-----) [001] .... 10040.746706: mm_filemap_add_to_page_cache: dev 253:6 ino 5 page=000000004a59da17 pfn=1288069 ofs=208896
diff --git a/startop/scripts/iorap/test_fixtures/compiler/common_textcache b/startop/scripts/iorap/test_fixtures/compiler/common_textcache
deleted file mode 100644
index da03004ec6fb..000000000000
--- a/startop/scripts/iorap/test_fixtures/compiler/common_textcache
+++ /dev/null
@@ -1,2 +0,0 @@
-64774 1 -1 /system/test1
-64774 3 -1 /data/test2
diff --git a/startop/scripts/iorap/test_fixtures/compiler/test_result_systrace b/startop/scripts/iorap/test_fixtures/compiler/test_result_systrace
deleted file mode 100644
index 59ff7537180b..000000000000
--- a/startop/scripts/iorap/test_fixtures/compiler/test_result_systrace
+++ /dev/null
@@ -1,748 +0,0 @@
-TRACE:
-# tracer: nop
-#
-# entries-in-buffer/entries-written: 30624/30624 #P:4
-#
-# _-----=> irqs-off
-# / _----=> need-resched
-# | / _---=> hardirq/softirq
-# || / _--=> preempt-depth
-# ||| / delay
-# TASK-PID TGID CPU# |||| TIMESTAMP FUNCTION
-# | | | | |||| | |
- <unknown>-27388 (-----) [004] .... 1920260.530929: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1461937 ofs=9535488
- <unknown>-27388 (-----) [005] .... 1920260.532161: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1344589 ofs=9474048
- <unknown>-27388 (-----) [005] .... 1920260.532183: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1153671 ofs=9478144
- <unknown>-27388 (-----) [005] .... 1920260.532184: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1219563 ofs=9482240
- <unknown>-27388 (-----) [005] .... 1920260.532185: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1083162 ofs=9486336
- <unknown>-27388 (-----) [005] .... 1920260.532185: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1147318 ofs=9490432
- <unknown>-27388 (-----) [005] .... 1920260.532186: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1333594 ofs=9494528
- <unknown>-27388 (-----) [005] .... 1920260.532186: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1375715 ofs=9498624
- <unknown>-27388 (-----) [005] .... 1920260.532186: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1184831 ofs=9502720
- <unknown>-27388 (-----) [005] .... 1920260.532187: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1241653 ofs=9506816
- <unknown>-27388 (-----) [005] .... 1920260.532187: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1134975 ofs=9510912
- <unknown>-27388 (-----) [005] .... 1920260.532190: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1145772 ofs=9515008
- <unknown>-27388 (-----) [005] .... 1920260.532190: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1090457 ofs=9519104
- <unknown>-27388 (-----) [005] .... 1920260.532190: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1137942 ofs=9523200
- <unknown>-27388 (-----) [005] .... 1920260.532191: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1130123 ofs=9527296
- <unknown>-27388 (-----) [005] .... 1920260.532191: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1208783 ofs=9531392
- <unknown>-27388 (-----) [005] .... 1920260.532192: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1294989 ofs=9539584
- <unknown>-27388 (-----) [005] .... 1920260.532206: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1163979 ofs=9543680
- <unknown>-27388 (-----) [005] .... 1920260.532206: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1350628 ofs=9547776
- <unknown>-27388 (-----) [005] .... 1920260.532206: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1386717 ofs=9551872
- <unknown>-27388 (-----) [005] .... 1920260.532207: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1316148 ofs=9555968
- <unknown>-27388 (-----) [005] .... 1920260.532208: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1316419 ofs=9560064
- <unknown>-27388 (-----) [005] .... 1920260.532208: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1149076 ofs=9564160
- <unknown>-27388 (-----) [005] .... 1920260.532209: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1372772 ofs=9568256
- <unknown>-27388 (-----) [005] .... 1920260.532209: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1116389 ofs=9572352
- <unknown>-27388 (-----) [005] .... 1920260.532211: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1325458 ofs=9576448
- <unknown>-27388 (-----) [005] .... 1920260.532211: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1195423 ofs=9580544
- <unknown>-27388 (-----) [005] .... 1920260.532211: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1250964 ofs=9584640
- <unknown>-27388 (-----) [005] .... 1920260.532212: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1196027 ofs=9588736
- <unknown>-27388 (-----) [005] .... 1920260.532212: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1354059 ofs=9592832
- <unknown>-27388 (-----) [005] .... 1920260.532213: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1264649 ofs=9596928
- <unknown>-27388 (-----) [005] .... 1920260.532213: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1245285 ofs=9601024
- <unknown>-27388 (-----) [005] .... 1920260.535119: mm_filemap_add_to_page_cache: dev 0:64768 ino 588 page=0000000000000000 pfn=1411552 ofs=44244992
- <unknown>-27388 (-----) [005] .... 1920260.535129: mm_filemap_add_to_page_cache: dev 0:3 ino 0 page=0000000000000000 pfn=1483081 ofs=433524736
- <unknown>-27388 (-----) [004] .... 1920260.536144: mm_filemap_add_to_page_cache: dev 0:3 ino 0 page=0000000000000000 pfn=1276173 ofs=438185984
- <unknown>-27388 (-----) [004] .... 1920260.536462: mm_filemap_add_to_page_cache: dev 0:64768 ino 588 page=0000000000000000 pfn=1174575 ofs=44249088
- <unknown>-27388 (-----) [004] .... 1920260.536464: mm_filemap_add_to_page_cache: dev 0:64768 ino 588 page=0000000000000000 pfn=1126294 ofs=44253184
- <unknown>-27388 (-----) [004] .... 1920260.536464: mm_filemap_add_to_page_cache: dev 0:64768 ino 588 page=0000000000000000 pfn=1248232 ofs=44257280
- <unknown>-27388 (-----) [004] .... 1920260.537065: mm_filemap_add_to_page_cache: dev 0:64768 ino 588 page=0000000000000000 pfn=1332993 ofs=44240896
- <unknown>-27388 (-----) [006] .... 1920260.537646: mm_filemap_add_to_page_cache: dev 0:64768 ino 588 page=0000000000000000 pfn=1153343 ofs=44400640
- <unknown>-27388 (-----) [005] .... 1920260.538777: mm_filemap_add_to_page_cache: dev 0:64768 ino 588 page=0000000000000000 pfn=1358397 ofs=44474368
- <unknown>-12683 (-----) [006] .... 1920260.560094: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1426577 ofs=0
- <unknown>-12683 (-----) [006] .... 1920260.560105: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1117587 ofs=1171456
- <unknown>-12683 (-----) [006] .... 1920260.561199: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099987 ofs=4096
- <unknown>-12683 (-----) [006] .... 1920260.561411: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099910 ofs=16384
- <unknown>-12683 (-----) [006] .... 1920260.561598: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099905 ofs=20480
- <unknown>-12683 (-----) [006] .... 1920260.561758: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099883 ofs=32768
- <unknown>-12683 (-----) [006] .... 1920260.562088: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099809 ofs=36864
- <unknown>-12683 (-----) [006] .... 1920260.562325: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099803 ofs=98304
- <unknown>-12683 (-----) [006] .... 1920260.562516: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099795 ofs=102400
- <unknown>-12683 (-----) [006] .... 1920260.563094: mm_filemap_add_to_page_cache: dev 0:64768 ino 5f3 page=0000000000000000 pfn=1107649 ofs=12288
- <unknown>-12683 (-----) [006] .... 1920260.563105: mm_filemap_add_to_page_cache: dev 0:64768 ino 5f3 page=0000000000000000 pfn=1269029 ofs=16384
- <unknown>-12683 (-----) [006] .... 1920260.563785: mm_filemap_add_to_page_cache: dev 0:64768 ino 4da page=0000000000000000 pfn=1451096 ofs=8192
- <unknown>-12683 (-----) [006] .... 1920260.563790: mm_filemap_add_to_page_cache: dev 0:64768 ino 4da page=0000000000000000 pfn=1301480 ofs=12288
- <unknown>-12683 (-----) [006] .... 1920260.563790: mm_filemap_add_to_page_cache: dev 0:64768 ino 4da page=0000000000000000 pfn=1314353 ofs=16384
- <unknown>-12683 (-----) [006] .... 1920260.563791: mm_filemap_add_to_page_cache: dev 0:64768 ino 4da page=0000000000000000 pfn=1216744 ofs=24576
- <unknown>-12683 (-----) [006] .... 1920260.564309: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099787 ofs=49152
- <unknown>-12683 (-----) [006] .... 1920260.564514: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1099778 ofs=53248
- <unknown>-12683 (-----) [005] .... 1920260.564756: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1148849 ofs=114688
- <unknown>-12683 (-----) [005] .... 1920260.564973: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1164731 ofs=118784
- <unknown>-12683 (-----) [005] .... 1920260.565000: mm_filemap_add_to_page_cache: dev 0:2053 ino 1a page=0000000000000000 pfn=1170255 ofs=0
- <unknown>-12683 (-----) [005] .... 1920260.565003: mm_filemap_add_to_page_cache: dev 0:2053 ino 1a page=0000000000000000 pfn=1181043 ofs=4096
- <unknown>-12683 (-----) [005] .... 1920260.565004: mm_filemap_add_to_page_cache: dev 0:2053 ino 1a page=0000000000000000 pfn=1296004 ofs=8192
- <unknown>-12683 (-----) [005] .... 1920260.565004: mm_filemap_add_to_page_cache: dev 0:2053 ino 1a page=0000000000000000 pfn=1102004 ofs=12288
- <unknown>-12683 (-----) [005] .... 1920260.565626: mm_filemap_add_to_page_cache: dev 0:3 ino 0 page=0000000000000000 pfn=1351232 ofs=470597632
- <unknown>-12683 (-----) [005] .... 1920260.565982: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1391336 ofs=40210432
- <unknown>-12683 (-----) [005] .... 1920260.565985: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1267536 ofs=12668928
- <unknown>-27388 (-----) [007] .... 1920260.566082: mm_filemap_add_to_page_cache: dev 0:64768 ino 588 page=0000000000000000 pfn=1256752 ofs=43921408
- <unknown>-12683 (-----) [005] .... 1920260.566516: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1110966 ofs=176226304
- <unknown>-12683 (-----) [005] .... 1920260.566519: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1060586 ofs=12967936
- <unknown>-12683 (-----) [004] .... 1920260.567773: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1117234 ofs=421888
- <unknown>-12683 (-----) [005] .... 1920260.568604: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1210571 ofs=430080
- <unknown>-12683 (-----) [005] .... 1920260.568887: mm_filemap_add_to_page_cache: dev 0:64771 ino 69 page=0000000000000000 pfn=1055640 ofs=0
- <unknown>-12683 (-----) [005] .... 1920260.568908: mm_filemap_add_to_page_cache: dev 0:64771 ino 49 page=0000000000000000 pfn=1142694 ofs=0
- <unknown>-12683 (-----) [005] .... 1920260.568910: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1060788 ofs=299008
- <unknown>-12683 (-----) [005] .... 1920260.569418: mm_filemap_add_to_page_cache: dev 0:64771 ino 49 page=0000000000000000 pfn=1085046 ofs=4096
- <unknown>-12683 (-----) [005] .... 1920260.569640: mm_filemap_add_to_page_cache: dev 0:64771 ino 49 page=0000000000000000 pfn=1057135 ofs=8192
- <unknown>-12683 (-----) [005] .... 1920260.569833: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1058976 ofs=19406848
- <unknown>-12683 (-----) [005] .... 1920260.569835: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1477947 ofs=10526720
- <unknown>-12683 (-----) [005] .... 1920260.572285: mm_filemap_add_to_page_cache: dev 0:64768 ino 61d page=0000000000000000 pfn=1237492 ofs=299008
- <unknown>-12683 (-----) [005] .... 1920260.572297: mm_filemap_add_to_page_cache: dev 0:64768 ino 61d page=0000000000000000 pfn=1264914 ofs=339968
- <unknown>-12683 (-----) [005] .... 1920260.572314: mm_filemap_add_to_page_cache: dev 0:64768 ino 61d page=0000000000000000 pfn=1434748 ofs=348160
- <unknown>-12683 (-----) [005] .... 1920260.572316: mm_filemap_add_to_page_cache: dev 0:64768 ino 61d page=0000000000000000 pfn=1372959 ofs=352256
- <unknown>-12683 (-----) [005] .... 1920260.572317: mm_filemap_add_to_page_cache: dev 0:64768 ino 61d page=0000000000000000 pfn=1258955 ofs=356352
- <unknown>-12683 (-----) [005] .... 1920260.572317: mm_filemap_add_to_page_cache: dev 0:64768 ino 61d page=0000000000000000 pfn=1113420 ofs=360448
- <unknown>-12683 (-----) [005] .... 1920260.572318: mm_filemap_add_to_page_cache: dev 0:64768 ino 61d page=0000000000000000 pfn=1137083 ofs=364544
- <unknown>-12683 (-----) [004] .... 1920260.575490: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1379679 ofs=65536
- <unknown>-12683 (-----) [006] .... 1920260.576194: mm_filemap_add_to_page_cache: dev 0:64771 ino 11e page=0000000000000000 pfn=1323898 ofs=69632
- <unknown>-12683 (-----) [006] .... 1920260.576248: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1323895 ofs=262623232
- <unknown>-12683 (-----) [006] .... 1920260.576251: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1323861 ofs=13156352
- <unknown>-12683 (-----) [005] .... 1920260.576810: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1477585 ofs=262590464
- <unknown>-12683 (-----) [004] .... 1920260.577197: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1267617 ofs=25206784
- <unknown>-12683 (-----) [004] .... 1920260.577200: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1267618 ofs=12636160
- <unknown>-12683 (-----) [005] .... 1920260.577725: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1056225 ofs=228618240
- <unknown>-12683 (-----) [005] .... 1920260.577727: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1164942 ofs=13082624
- <unknown>-12683 (-----) [007] .... 1920260.578411: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1372616 ofs=0
- <unknown>-12683 (-----) [007] .... 1920260.578422: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1307468 ofs=4096
- <unknown>-12683 (-----) [007] .... 1920260.578428: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1120117 ofs=8192
- <unknown>-12683 (-----) [007] .... 1920260.578428: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1217989 ofs=12288
- <unknown>-12683 (-----) [007] .... 1920260.578650: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1475011 ofs=5419008
- <unknown>-12683 (-----) [007] .... 1920260.578653: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1066084 ofs=236453888
- <unknown>-12683 (-----) [007] .... 1920260.578654: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1100271 ofs=13099008
- <unknown>-12683 (-----) [004] .... 1920260.579004: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1485156 ofs=5423104
- <unknown>-12683 (-----) [004] .... 1920260.579005: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1124212 ofs=5427200
- <unknown>-12683 (-----) [004] .... 1920260.579006: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1195377 ofs=5431296
- <unknown>-12683 (-----) [004] .... 1920260.579006: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1265888 ofs=5435392
- <unknown>-12683 (-----) [004] .... 1920260.579007: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1170194 ofs=5439488
- <unknown>-12683 (-----) [004] .... 1920260.579007: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1403742 ofs=5443584
- <unknown>-12683 (-----) [004] .... 1920260.579008: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1123826 ofs=5447680
- <unknown>-12683 (-----) [004] .... 1920260.579008: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1255034 ofs=5451776
- <unknown>-12683 (-----) [004] .... 1920260.579011: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1190447 ofs=5455872
- <unknown>-12683 (-----) [004] .... 1920260.579011: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1286864 ofs=5459968
- <unknown>-12683 (-----) [004] .... 1920260.579012: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1428535 ofs=5464064
- <unknown>-12683 (-----) [004] .... 1920260.579012: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1184092 ofs=5468160
- <unknown>-12683 (-----) [004] .... 1920260.579013: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1411906 ofs=5472256
- <unknown>-12683 (-----) [004] .... 1920260.579013: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1342349 ofs=5476352
- <unknown>-12683 (-----) [004] .... 1920260.579013: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1188185 ofs=5480448
- <unknown>-12683 (-----) [004] .... 1920260.579014: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1158702 ofs=5484544
- <unknown>-12683 (-----) [005] .... 1920260.579430: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1299421 ofs=5230592
- <unknown>-12683 (-----) [005] .... 1920260.579435: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1317097 ofs=5234688
- <unknown>-12683 (-----) [005] .... 1920260.579435: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1441714 ofs=5238784
- <unknown>-12683 (-----) [005] .... 1920260.579438: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1081974 ofs=5242880
- <unknown>-12683 (-----) [005] .... 1920260.579439: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1128684 ofs=5246976
- <unknown>-12683 (-----) [005] .... 1920260.579439: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1447381 ofs=5251072
- <unknown>-12683 (-----) [005] .... 1920260.579440: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1466410 ofs=5255168
- <unknown>-12683 (-----) [005] .... 1920260.579440: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1259909 ofs=5259264
- <unknown>-12683 (-----) [005] .... 1920260.579441: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1125784 ofs=5263360
- <unknown>-12683 (-----) [005] .... 1920260.579441: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1270592 ofs=5267456
- <unknown>-12683 (-----) [005] .... 1920260.579442: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1246070 ofs=5271552
- <unknown>-12683 (-----) [005] .... 1920260.579442: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1472544 ofs=5275648
- <unknown>-12683 (-----) [005] .... 1920260.579442: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1113357 ofs=5279744
- <unknown>-12683 (-----) [005] .... 1920260.579443: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1202021 ofs=5283840
- <unknown>-12683 (-----) [005] .... 1920260.579443: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1078639 ofs=5287936
- <unknown>-12683 (-----) [005] .... 1920260.579449: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1176171 ofs=5292032
- <unknown>-12683 (-----) [005] .... 1920260.579450: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1089516 ofs=5296128
- <unknown>-12683 (-----) [005] .... 1920260.579451: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1400065 ofs=5300224
- <unknown>-12683 (-----) [005] .... 1920260.579452: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1300489 ofs=5304320
- <unknown>-12683 (-----) [005] .... 1920260.579452: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1452081 ofs=5308416
- <unknown>-12683 (-----) [005] .... 1920260.579452: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1161862 ofs=5312512
- <unknown>-12683 (-----) [005] .... 1920260.579453: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1161871 ofs=5316608
- <unknown>-12683 (-----) [005] .... 1920260.579453: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1263798 ofs=5320704
- <unknown>-12683 (-----) [005] .... 1920260.579454: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1126887 ofs=5324800
- <unknown>-12683 (-----) [005] .... 1920260.579454: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1375498 ofs=5328896
- <unknown>-12683 (-----) [005] .... 1920260.579455: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1328067 ofs=5332992
- <unknown>-12683 (-----) [005] .... 1920260.579455: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1420691 ofs=5337088
- <unknown>-12683 (-----) [005] .... 1920260.579456: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1298707 ofs=5341184
- <unknown>-12683 (-----) [005] .... 1920260.579456: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1078670 ofs=5345280
- <unknown>-12683 (-----) [005] .... 1920260.579457: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1430498 ofs=5349376
- <unknown>-12683 (-----) [005] .... 1920260.579458: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1338720 ofs=5353472
- <unknown>-12683 (-----) [005] .... 1920260.579476: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1452611 ofs=5357568
- <unknown>-12683 (-----) [006] .... 1920260.580451: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1241967 ofs=0
- <unknown>-12683 (-----) [006] .... 1920260.580454: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1116541 ofs=4096
- <unknown>-12683 (-----) [006] .... 1920260.580461: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1145049 ofs=8192
- <unknown>-12683 (-----) [006] .... 1920260.580462: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1277255 ofs=12288
- <unknown>-12683 (-----) [006] .... 1920260.580462: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1098037 ofs=16384
- <unknown>-12683 (-----) [006] .... 1920260.580463: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1135986 ofs=20480
- <unknown>-12683 (-----) [006] .... 1920260.580464: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1154455 ofs=24576
- <unknown>-12683 (-----) [006] .... 1920260.580464: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1221822 ofs=28672
- <unknown>-12683 (-----) [006] .... 1920260.580465: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1078684 ofs=32768
- <unknown>-12683 (-----) [006] .... 1920260.580465: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1158876 ofs=36864
- <unknown>-12683 (-----) [006] .... 1920260.580465: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1289644 ofs=40960
- <unknown>-12683 (-----) [006] .... 1920260.580466: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1289386 ofs=45056
- <unknown>-12683 (-----) [006] .... 1920260.580466: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1131002 ofs=49152
- <unknown>-12683 (-----) [006] .... 1920260.580467: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1464335 ofs=53248
- <unknown>-12683 (-----) [006] .... 1920260.580468: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1135789 ofs=57344
- <unknown>-12683 (-----) [006] .... 1920260.580469: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1240897 ofs=61440
- <unknown>-12683 (-----) [006] .... 1920260.580469: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1241770 ofs=65536
- <unknown>-12683 (-----) [006] .... 1920260.580470: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1421959 ofs=69632
- <unknown>-12683 (-----) [006] .... 1920260.580470: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1230007 ofs=73728
- <unknown>-12683 (-----) [006] .... 1920260.580471: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1109271 ofs=77824
- <unknown>-12683 (-----) [006] .... 1920260.580471: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1159974 ofs=81920
- <unknown>-12683 (-----) [006] .... 1920260.580471: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1154528 ofs=86016
- <unknown>-12683 (-----) [006] .... 1920260.580472: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1315790 ofs=90112
- <unknown>-12683 (-----) [006] .... 1920260.580473: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1185583 ofs=94208
- <unknown>-12683 (-----) [006] .... 1920260.580473: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1253153 ofs=98304
- <unknown>-12683 (-----) [006] .... 1920260.580473: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103982 ofs=102400
- <unknown>-12683 (-----) [006] .... 1920260.580474: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1284589 ofs=106496
- <unknown>-12683 (-----) [006] .... 1920260.580474: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1169601 ofs=110592
- <unknown>-12683 (-----) [006] .... 1920260.580476: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1206248 ofs=114688
- <unknown>-12683 (-----) [006] .... 1920260.580476: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1261161 ofs=118784
- <unknown>-12683 (-----) [006] .... 1920260.580477: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1305841 ofs=122880
- <unknown>-12683 (-----) [006] .... 1920260.580477: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1468293 ofs=126976
- <unknown>-12683 (-----) [004] .... 1920260.580646: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1318816 ofs=16384
- <unknown>-12683 (-----) [004] .... 1920260.580649: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1472922 ofs=20480
- <unknown>-12683 (-----) [004] .... 1920260.580650: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1473229 ofs=24576
- <unknown>-12683 (-----) [004] .... 1920260.580650: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1524262 ofs=28672
- <unknown>-12683 (-----) [004] .... 1920260.580656: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1205714 ofs=32768
- <unknown>-12683 (-----) [004] .... 1920260.580657: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1310560 ofs=36864
- <unknown>-12683 (-----) [004] .... 1920260.580658: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1295070 ofs=40960
- <unknown>-12683 (-----) [004] .... 1920260.580659: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1404093 ofs=45056
- <unknown>-12683 (-----) [004] .... 1920260.580659: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1435814 ofs=49152
- <unknown>-12683 (-----) [004] .... 1920260.580660: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1435442 ofs=53248
- <unknown>-12683 (-----) [004] .... 1920260.580660: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1096077 ofs=57344
- <unknown>-12683 (-----) [004] .... 1920260.580661: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1483793 ofs=61440
- <unknown>-12683 (-----) [004] .... 1920260.580661: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1231298 ofs=65536
- <unknown>-12683 (-----) [004] .... 1920260.580661: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1215648 ofs=69632
- <unknown>-12683 (-----) [004] .... 1920260.580662: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1327326 ofs=73728
- <unknown>-12683 (-----) [004] .... 1920260.580662: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1108894 ofs=77824
- <unknown>-12683 (-----) [004] .... 1920260.580663: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1327545 ofs=81920
- <unknown>-12683 (-----) [004] .... 1920260.580663: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1328804 ofs=86016
- <unknown>-12683 (-----) [004] .... 1920260.580664: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1300171 ofs=90112
- <unknown>-12683 (-----) [004] .... 1920260.580664: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1353250 ofs=94208
- <unknown>-12683 (-----) [004] .... 1920260.580668: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1333681 ofs=98304
- <unknown>-12683 (-----) [004] .... 1920260.580668: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1144969 ofs=102400
- <unknown>-12683 (-----) [004] .... 1920260.580669: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1450962 ofs=106496
- <unknown>-12683 (-----) [004] .... 1920260.580669: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1255701 ofs=110592
- <unknown>-12683 (-----) [004] .... 1920260.580670: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1294782 ofs=114688
- <unknown>-12683 (-----) [004] .... 1920260.580670: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1226912 ofs=118784
- <unknown>-12683 (-----) [004] .... 1920260.580671: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1294579 ofs=122880
- <unknown>-12683 (-----) [004] .... 1920260.580671: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1246960 ofs=126976
- <unknown>-12683 (-----) [004] .... 1920260.580671: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1199086 ofs=131072
- <unknown>-12683 (-----) [004] .... 1920260.580672: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1449590 ofs=135168
- <unknown>-12683 (-----) [004] .... 1920260.580672: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1276363 ofs=139264
- <unknown>-12683 (-----) [004] .... 1920260.580675: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1389998 ofs=143360
- <unknown>-12683 (-----) [004] .... 1920260.580739: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1423031 ofs=1249280
- <unknown>-12683 (-----) [004] .... 1920260.580741: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1171032 ofs=1253376
- <unknown>-12683 (-----) [004] .... 1920260.580742: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1320946 ofs=1257472
- <unknown>-12683 (-----) [004] .... 1920260.580743: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1314696 ofs=1261568
- <unknown>-12683 (-----) [004] .... 1920260.580743: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1414864 ofs=1265664
- <unknown>-12683 (-----) [004] .... 1920260.580744: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1334933 ofs=1269760
- <unknown>-12683 (-----) [004] .... 1920260.580744: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1242845 ofs=1273856
- <unknown>-12683 (-----) [004] .... 1920260.580747: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1289488 ofs=1277952
- <unknown>-12683 (-----) [004] .... 1920260.580748: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1335445 ofs=1282048
- <unknown>-12683 (-----) [004] .... 1920260.580748: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1289663 ofs=1286144
- <unknown>-12683 (-----) [004] .... 1920260.580749: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1080462 ofs=1290240
- <unknown>-12683 (-----) [004] .... 1920260.580749: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1286303 ofs=1294336
- <unknown>-12683 (-----) [004] .... 1920260.580750: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1353531 ofs=1298432
- <unknown>-12683 (-----) [004] .... 1920260.580750: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1280701 ofs=1302528
- <unknown>-12683 (-----) [004] .... 1920260.580751: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1107730 ofs=1306624
- <unknown>-12683 (-----) [004] .... 1920260.580752: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1242729 ofs=1310720
- <unknown>-12683 (-----) [004] .... 1920260.580753: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1078336 ofs=1314816
- <unknown>-12683 (-----) [004] .... 1920260.580753: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1372425 ofs=1318912
- <unknown>-12683 (-----) [004] .... 1920260.580754: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1248813 ofs=1323008
- <unknown>-12683 (-----) [004] .... 1920260.580754: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1201155 ofs=1327104
- <unknown>-12683 (-----) [004] .... 1920260.580755: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1250103 ofs=1331200
- <unknown>-12683 (-----) [004] .... 1920260.580755: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1359710 ofs=1335296
- <unknown>-12683 (-----) [004] .... 1920260.580756: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1272462 ofs=1339392
- <unknown>-12683 (-----) [004] .... 1920260.580758: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1097035 ofs=1343488
- <unknown>-12683 (-----) [004] .... 1920260.580759: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1233124 ofs=1347584
- <unknown>-12683 (-----) [004] .... 1920260.580759: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1455812 ofs=1351680
- <unknown>-12683 (-----) [004] .... 1920260.580759: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1355689 ofs=1355776
- <unknown>-12683 (-----) [004] .... 1920260.580760: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1263593 ofs=1359872
- <unknown>-12683 (-----) [004] .... 1920260.580760: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1230789 ofs=1363968
- <unknown>-12683 (-----) [004] .... 1920260.580761: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1143766 ofs=1368064
- <unknown>-12683 (-----) [004] .... 1920260.580762: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1269666 ofs=1372160
- <unknown>-12683 (-----) [004] .... 1920260.580762: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1353022 ofs=1376256
- <unknown>-12683 (-----) [004] .... 1920260.581613: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1355509 ofs=258048
- <unknown>-12683 (-----) [004] .... 1920260.581615: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1178902 ofs=262144
- <unknown>-12683 (-----) [004] .... 1920260.581616: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1193649 ofs=266240
- <unknown>-12683 (-----) [004] .... 1920260.581618: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1225497 ofs=270336
- <unknown>-12683 (-----) [004] .... 1920260.581618: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1228259 ofs=274432
- <unknown>-12683 (-----) [004] .... 1920260.581635: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1309674 ofs=278528
- <unknown>-12683 (-----) [004] .... 1920260.581635: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1239390 ofs=282624
- <unknown>-12683 (-----) [004] .... 1920260.581636: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1468083 ofs=286720
- <unknown>-12683 (-----) [004] .... 1920260.581636: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1292751 ofs=290816
- <unknown>-12683 (-----) [004] .... 1920260.581637: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1318066 ofs=294912
- <unknown>-12683 (-----) [004] .... 1920260.581637: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1489314 ofs=299008
- <unknown>-12683 (-----) [004] .... 1920260.581637: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1169867 ofs=303104
- <unknown>-12683 (-----) [004] .... 1920260.581639: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1314256 ofs=307200
- <unknown>-12683 (-----) [004] .... 1920260.581639: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1310230 ofs=311296
- <unknown>-12683 (-----) [004] .... 1920260.581640: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1356180 ofs=315392
- <unknown>-12683 (-----) [004] .... 1920260.581640: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1419179 ofs=319488
- <unknown>-12683 (-----) [004] .... 1920260.581641: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1307265 ofs=323584
- <unknown>-12683 (-----) [004] .... 1920260.581641: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1218590 ofs=327680
- <unknown>-12683 (-----) [004] .... 1920260.581642: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1447586 ofs=331776
- <unknown>-12683 (-----) [004] .... 1920260.581642: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1209382 ofs=335872
- <unknown>-12683 (-----) [004] .... 1920260.581642: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1072148 ofs=339968
- <unknown>-12683 (-----) [004] .... 1920260.581645: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1227195 ofs=344064
- <unknown>-12683 (-----) [004] .... 1920260.581646: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1246369 ofs=348160
- <unknown>-12683 (-----) [004] .... 1920260.581646: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1193845 ofs=352256
- <unknown>-12683 (-----) [004] .... 1920260.581647: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1137553 ofs=356352
- <unknown>-12683 (-----) [004] .... 1920260.581647: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1475215 ofs=360448
- <unknown>-12683 (-----) [004] .... 1920260.581648: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1258935 ofs=364544
- <unknown>-12683 (-----) [004] .... 1920260.581649: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1448788 ofs=368640
- <unknown>-12683 (-----) [004] .... 1920260.581649: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1447611 ofs=372736
- <unknown>-12683 (-----) [004] .... 1920260.581650: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1290842 ofs=376832
- <unknown>-12683 (-----) [004] .... 1920260.581650: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1447826 ofs=380928
- <unknown>-12683 (-----) [004] .... 1920260.581650: mm_filemap_add_to_page_cache: dev 0:64771 ino da07 page=0000000000000000 pfn=1181016 ofs=385024
- <unknown>-12683 (-----) [005] .... 1920260.582230: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1216810 ofs=1662976
- <unknown>-12683 (-----) [005] .... 1920260.582234: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1175966 ofs=1667072
- <unknown>-12683 (-----) [005] .... 1920260.582235: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1449798 ofs=1671168
- <unknown>-12683 (-----) [005] .... 1920260.582236: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1273480 ofs=1675264
- <unknown>-12683 (-----) [005] .... 1920260.582236: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1152779 ofs=1679360
- <unknown>-12683 (-----) [005] .... 1920260.582237: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1272810 ofs=1683456
- <unknown>-12683 (-----) [005] .... 1920260.582237: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1248634 ofs=1687552
- <unknown>-12683 (-----) [005] .... 1920260.582237: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1203376 ofs=1691648
- <unknown>-12683 (-----) [005] .... 1920260.582238: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1138880 ofs=1695744
- <unknown>-12683 (-----) [005] .... 1920260.582238: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1344591 ofs=1699840
- <unknown>-12683 (-----) [005] .... 1920260.582239: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1416060 ofs=1703936
- <unknown>-12683 (-----) [005] .... 1920260.582246: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1128676 ofs=1708032
- <unknown>-12683 (-----) [005] .... 1920260.582247: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1301921 ofs=1712128
- <unknown>-12683 (-----) [005] .... 1920260.582248: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1384569 ofs=1716224
- <unknown>-12683 (-----) [005] .... 1920260.582248: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1249106 ofs=1720320
- <unknown>-12683 (-----) [005] .... 1920260.582249: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1206596 ofs=1724416
- <unknown>-12683 (-----) [005] .... 1920260.582249: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1429831 ofs=1728512
- <unknown>-12683 (-----) [005] .... 1920260.582252: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1107796 ofs=1732608
- <unknown>-12683 (-----) [005] .... 1920260.582255: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1098336 ofs=1736704
- <unknown>-12683 (-----) [005] .... 1920260.582255: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1230286 ofs=1740800
- <unknown>-12683 (-----) [005] .... 1920260.582256: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1100370 ofs=1744896
- <unknown>-12683 (-----) [005] .... 1920260.582256: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1241930 ofs=1748992
- <unknown>-12683 (-----) [005] .... 1920260.582257: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1366807 ofs=1753088
- <unknown>-12683 (-----) [005] .... 1920260.582257: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1136252 ofs=1757184
- <unknown>-12683 (-----) [005] .... 1920260.582258: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1274291 ofs=1761280
- <unknown>-12683 (-----) [005] .... 1920260.582258: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1254775 ofs=1765376
- <unknown>-12683 (-----) [005] .... 1920260.582259: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1194679 ofs=1769472
- <unknown>-12683 (-----) [005] .... 1920260.582262: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1177090 ofs=1773568
- <unknown>-12683 (-----) [005] .... 1920260.582263: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1343925 ofs=1777664
- <unknown>-12683 (-----) [005] .... 1920260.582263: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1159217 ofs=1781760
- <unknown>-12683 (-----) [005] .... 1920260.582263: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1435471 ofs=1785856
- <unknown>-12683 (-----) [005] .... 1920260.582264: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1435529 ofs=1789952
- <unknown>-12683 (-----) [004] .... 1920260.582524: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1181910 ofs=0
- <unknown>-12683 (-----) [004] .... 1920260.582528: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1212021 ofs=4096
- <unknown>-12683 (-----) [004] .... 1920260.582529: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1162778 ofs=8192
- <unknown>-12683 (-----) [004] .... 1920260.582529: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1107700 ofs=12288
- <unknown>-12683 (-----) [004] .... 1920260.583553: mm_filemap_add_to_page_cache: dev 0:64771 ino df31 page=0000000000000000 pfn=1093394 ofs=3399680
- <unknown>-12683 (-----) [004] .... 1920260.583984: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1121431 ofs=242503680
- <unknown>-12683 (-----) [004] .... 1920260.583986: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1168551 ofs=13115392
- <unknown>-12683 (-----) [004] .... 1920260.584304: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1347409 ofs=0
- <unknown>-12683 (-----) [004] .... 1920260.584307: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1428681 ofs=4096
- <unknown>-12683 (-----) [004] .... 1920260.584307: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1259106 ofs=8192
- <unknown>-12683 (-----) [004] .... 1920260.584308: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1343229 ofs=12288
- <unknown>-12694 (-----) [005] .... 1920260.584622: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1098733 ofs=1531904
- <unknown>-12696 (-----) [006] .... 1920260.584626: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1331319 ofs=1536000
- <unknown>-12694 (-----) [005] .... 1920260.584626: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1278537 ofs=1540096
- <unknown>-12696 (-----) [006] .... 1920260.584631: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1492534 ofs=1544192
- <unknown>-12694 (-----) [005] .... 1920260.584636: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1460878 ofs=1548288
- <unknown>-12694 (-----) [005] .... 1920260.584640: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1092973 ofs=1552384
- <unknown>-12694 (-----) [005] .... 1920260.584641: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1103200 ofs=1556480
- <unknown>-12694 (-----) [005] .... 1920260.584642: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1257426 ofs=1560576
- <unknown>-12694 (-----) [005] .... 1920260.584642: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1219424 ofs=1564672
- <unknown>-12683 (-----) [004] .... 1920260.584660: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1279352 ofs=1568768
- <unknown>-12696 (-----) [006] .... 1920260.584662: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1260572 ofs=1572864
- <unknown>-12683 (-----) [004] .... 1920260.584663: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1225809 ofs=1576960
- <unknown>-12696 (-----) [006] .... 1920260.584665: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1350766 ofs=1585152
- <unknown>-12697 (-----) [007] .... 1920260.584666: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1107173 ofs=1581056
- <unknown>-12683 (-----) [004] .... 1920260.584668: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1305885 ofs=1589248
- <unknown>-12694 (-----) [005] .... 1920260.584669: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1293385 ofs=1593344
- <unknown>-12696 (-----) [006] .... 1920260.584670: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1173841 ofs=1597440
- <unknown>-12697 (-----) [007] .... 1920260.584670: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1080021 ofs=1601536
- <unknown>-12683 (-----) [004] .... 1920260.584673: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1147419 ofs=1605632
- <unknown>-12696 (-----) [006] .... 1920260.584673: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1252762 ofs=1609728
- <unknown>-12694 (-----) [005] .... 1920260.584674: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1323916 ofs=1613824
- <unknown>-12683 (-----) [004] .... 1920260.584675: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1155631 ofs=1617920
- <unknown>-12696 (-----) [006] .... 1920260.584676: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1449815 ofs=1622016
- <unknown>-12694 (-----) [005] .... 1920260.584678: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1227069 ofs=1626112
- <unknown>-12696 (-----) [006] .... 1920260.584680: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1317692 ofs=1630208
- <unknown>-12694 (-----) [005] .... 1920260.584681: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1492244 ofs=1634304
- <unknown>-12683 (-----) [004] .... 1920260.584682: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1241876 ofs=1638400
- <unknown>-12697 (-----) [007] .... 1920260.585446: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1402958 ofs=167936
- <unknown>-12697 (-----) [007] .... 1920260.585449: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1133263 ofs=172032
- <unknown>-12697 (-----) [007] .... 1920260.585450: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1295502 ofs=176128
- <unknown>-12697 (-----) [007] .... 1920260.585450: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1249495 ofs=180224
- <unknown>-12697 (-----) [007] .... 1920260.585451: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1237999 ofs=184320
- <unknown>-12697 (-----) [007] .... 1920260.585451: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1280965 ofs=188416
- <unknown>-12697 (-----) [007] .... 1920260.585454: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1208361 ofs=192512
- <unknown>-12697 (-----) [007] .... 1920260.585454: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1308840 ofs=196608
- <unknown>-12695 (-----) [004] .... 1920260.585455: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1138875 ofs=569344
- <unknown>-12695 (-----) [004] .... 1920260.585458: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1314886 ofs=573440
- <unknown>-12697 (-----) [007] .... 1920260.585458: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1242734 ofs=200704
- <unknown>-12695 (-----) [004] .... 1920260.585458: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1447386 ofs=577536
- <unknown>-12697 (-----) [007] .... 1920260.585459: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1241302 ofs=204800
- <unknown>-12695 (-----) [004] .... 1920260.585459: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1328663 ofs=581632
- <unknown>-12697 (-----) [007] .... 1920260.585459: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1476101 ofs=208896
- <unknown>-12695 (-----) [004] .... 1920260.585460: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1209461 ofs=585728
- <unknown>-12697 (-----) [007] .... 1920260.585460: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1080147 ofs=212992
- <unknown>-12697 (-----) [007] .... 1920260.585461: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1128509 ofs=217088
- <unknown>-12697 (-----) [007] .... 1920260.585461: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1371915 ofs=221184
- <unknown>-12697 (-----) [007] .... 1920260.585461: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1264015 ofs=225280
- <unknown>-12697 (-----) [007] .... 1920260.585462: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1211695 ofs=229376
- <unknown>-12697 (-----) [007] .... 1920260.585462: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1150386 ofs=233472
- <unknown>-12697 (-----) [007] .... 1920260.585463: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1135747 ofs=237568
- <unknown>-12697 (-----) [007] .... 1920260.585463: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1128230 ofs=241664
- <unknown>-12697 (-----) [007] .... 1920260.585464: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1155451 ofs=245760
- <unknown>-12697 (-----) [007] .... 1920260.585465: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1246841 ofs=249856
- <unknown>-12697 (-----) [007] .... 1920260.585465: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1462971 ofs=253952
- <unknown>-12697 (-----) [007] .... 1920260.585466: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1131333 ofs=258048
- <unknown>-12697 (-----) [007] .... 1920260.585466: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1289407 ofs=262144
- <unknown>-12695 (-----) [004] .... 1920260.585467: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1134730 ofs=589824
- <unknown>-12697 (-----) [007] .... 1920260.585467: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1289873 ofs=266240
- <unknown>-12697 (-----) [007] .... 1920260.585468: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1448734 ofs=270336
- <unknown>-12695 (-----) [004] .... 1920260.585468: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1129776 ofs=593920
- <unknown>-12697 (-----) [007] .... 1920260.585468: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1524090 ofs=274432
- <unknown>-12695 (-----) [004] .... 1920260.585468: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1399725 ofs=598016
- <unknown>-12697 (-----) [007] .... 1920260.585469: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1524081 ofs=278528
- <unknown>-12695 (-----) [004] .... 1920260.585469: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1276535 ofs=602112
- <unknown>-12697 (-----) [007] .... 1920260.585469: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1524060 ofs=282624
- <unknown>-12695 (-----) [004] .... 1920260.585470: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1449847 ofs=606208
- <unknown>-12697 (-----) [007] .... 1920260.585470: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1158944 ofs=286720
- <unknown>-12695 (-----) [004] .... 1920260.585470: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1384536 ofs=610304
- <unknown>-12697 (-----) [007] .... 1920260.585470: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1116785 ofs=290816
- <unknown>-12695 (-----) [004] .... 1920260.585471: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1308118 ofs=614400
- <unknown>-12697 (-----) [007] .... 1920260.585471: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1448669 ofs=294912
- <unknown>-12695 (-----) [004] .... 1920260.585471: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1227050 ofs=618496
- <unknown>-12695 (-----) [004] .... 1920260.585473: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1289324 ofs=622592
- <unknown>-12695 (-----) [004] .... 1920260.585473: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1187869 ofs=626688
- <unknown>-12695 (-----) [004] .... 1920260.585474: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1400523 ofs=630784
- <unknown>-12695 (-----) [004] .... 1920260.585474: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1344176 ofs=634880
- <unknown>-12695 (-----) [004] .... 1920260.585475: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1092871 ofs=638976
- <unknown>-12695 (-----) [004] .... 1920260.585475: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1092021 ofs=643072
- <unknown>-12695 (-----) [004] .... 1920260.585476: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1198169 ofs=647168
- <unknown>-12695 (-----) [004] .... 1920260.585476: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1371540 ofs=651264
- <unknown>-12683 (-----) [005] .... 1920260.585476: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1195003 ofs=348160
- <unknown>-12695 (-----) [004] .... 1920260.585477: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1228787 ofs=655360
- <unknown>-12695 (-----) [004] .... 1920260.585477: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1236123 ofs=659456
- <unknown>-12695 (-----) [004] .... 1920260.585477: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1137213 ofs=663552
- <unknown>-12695 (-----) [004] .... 1920260.585478: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1294618 ofs=667648
- <unknown>-12695 (-----) [004] .... 1920260.585478: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1241048 ofs=671744
- <unknown>-12695 (-----) [004] .... 1920260.585479: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1228779 ofs=675840
- <unknown>-12683 (-----) [005] .... 1920260.585479: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1199292 ofs=352256
- <unknown>-12683 (-----) [005] .... 1920260.585480: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1200861 ofs=356352
- <unknown>-12695 (-----) [004] .... 1920260.585480: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1309572 ofs=679936
- <unknown>-12683 (-----) [005] .... 1920260.585480: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1215770 ofs=360448
- <unknown>-12695 (-----) [004] .... 1920260.585481: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1409002 ofs=684032
- <unknown>-12683 (-----) [005] .... 1920260.585481: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1151883 ofs=364544
- <unknown>-12695 (-----) [004] .... 1920260.585481: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1103729 ofs=688128
- <unknown>-12683 (-----) [005] .... 1920260.585482: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1468126 ofs=368640
- <unknown>-12695 (-----) [004] .... 1920260.585482: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1162720 ofs=692224
- <unknown>-12683 (-----) [005] .... 1920260.585482: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1251672 ofs=372736
- <unknown>-12695 (-----) [004] .... 1920260.585482: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1199221 ofs=696320
- <unknown>-12683 (-----) [005] .... 1920260.585483: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1283325 ofs=376832
- <unknown>-12683 (-----) [005] .... 1920260.585483: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1190489 ofs=380928
- <unknown>-12683 (-----) [005] .... 1920260.585484: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1489117 ofs=385024
- <unknown>-12683 (-----) [005] .... 1920260.585484: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1273899 ofs=389120
- <unknown>-12683 (-----) [005] .... 1920260.585485: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1274459 ofs=393216
- <unknown>-12683 (-----) [005] .... 1920260.585486: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1316649 ofs=397312
- <unknown>-12683 (-----) [005] .... 1920260.585491: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1375678 ofs=401408
- <unknown>-12683 (-----) [005] .... 1920260.585491: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1483317 ofs=405504
- <unknown>-12683 (-----) [005] .... 1920260.585492: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1240286 ofs=409600
- <unknown>-12683 (-----) [005] .... 1920260.585492: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1131345 ofs=413696
- <unknown>-12683 (-----) [005] .... 1920260.585493: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1200483 ofs=417792
- <unknown>-12683 (-----) [005] .... 1920260.585493: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1384693 ofs=421888
- <unknown>-12683 (-----) [005] .... 1920260.585493: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1161385 ofs=425984
- <unknown>-12683 (-----) [005] .... 1920260.585494: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1452025 ofs=430080
- <unknown>-12683 (-----) [005] .... 1920260.585495: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1253654 ofs=434176
- <unknown>-12683 (-----) [005] .... 1920260.585495: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1116697 ofs=438272
- <unknown>-12683 (-----) [005] .... 1920260.585495: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1432645 ofs=442368
- <unknown>-12694 (-----) [006] .... 1920260.585495: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1337397 ofs=16384
- <unknown>-12683 (-----) [005] .... 1920260.585496: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1304229 ofs=446464
- <unknown>-12683 (-----) [005] .... 1920260.585496: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1419147 ofs=450560
- <unknown>-12683 (-----) [005] .... 1920260.585498: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1349246 ofs=454656
- <unknown>-12683 (-----) [005] .... 1920260.585499: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1128519 ofs=458752
- <unknown>-12683 (-----) [005] .... 1920260.585499: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1125168 ofs=462848
- <unknown>-12694 (-----) [006] .... 1920260.585509: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1081031 ofs=20480
- <unknown>-12694 (-----) [006] .... 1920260.585509: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1293022 ofs=24576
- <unknown>-12694 (-----) [006] .... 1920260.585510: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1113007 ofs=28672
- <unknown>-12694 (-----) [006] .... 1920260.585510: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1339312 ofs=32768
- <unknown>-12694 (-----) [006] .... 1920260.585511: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1412311 ofs=36864
- <unknown>-12694 (-----) [006] .... 1920260.585511: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1260960 ofs=40960
- <unknown>-12694 (-----) [006] .... 1920260.585512: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1189529 ofs=45056
- <unknown>-12694 (-----) [006] .... 1920260.585512: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1412184 ofs=49152
- <unknown>-12694 (-----) [006] .... 1920260.585513: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1481227 ofs=53248
- <unknown>-12694 (-----) [006] .... 1920260.585513: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1455940 ofs=57344
- <unknown>-12694 (-----) [006] .... 1920260.585514: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1299132 ofs=61440
- <unknown>-12694 (-----) [006] .... 1920260.585514: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1337375 ofs=65536
- <unknown>-12694 (-----) [006] .... 1920260.585529: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1328742 ofs=69632
- <unknown>-12694 (-----) [006] .... 1920260.585529: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1315646 ofs=73728
- <unknown>-12694 (-----) [006] .... 1920260.585531: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1225475 ofs=77824
- <unknown>-12694 (-----) [006] .... 1920260.585531: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1146097 ofs=81920
- <unknown>-12694 (-----) [006] .... 1920260.585532: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1318775 ofs=86016
- <unknown>-12694 (-----) [006] .... 1920260.585532: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1448391 ofs=90112
- <unknown>-12694 (-----) [006] .... 1920260.585532: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1441412 ofs=94208
- <unknown>-12694 (-----) [006] .... 1920260.585533: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1138111 ofs=98304
- <unknown>-12694 (-----) [006] .... 1920260.585533: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1143223 ofs=102400
- <unknown>-12683 (-----) [005] .... 1920260.585534: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1079876 ofs=466944
- <unknown>-12694 (-----) [006] .... 1920260.585534: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1447637 ofs=106496
- <unknown>-12694 (-----) [006] .... 1920260.585534: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1220585 ofs=110592
- <unknown>-12694 (-----) [006] .... 1920260.585535: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1449051 ofs=114688
- <unknown>-12694 (-----) [006] .... 1920260.585535: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1313180 ofs=118784
- <unknown>-12694 (-----) [006] .... 1920260.585535: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1313166 ofs=122880
- <unknown>-12694 (-----) [006] .... 1920260.585536: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1313154 ofs=126976
- <unknown>-12683 (-----) [005] .... 1920260.585536: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1218394 ofs=471040
- <unknown>-12694 (-----) [006] .... 1920260.585536: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1144047 ofs=131072
- <unknown>-12683 (-----) [005] .... 1920260.585537: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1218579 ofs=475136
- <unknown>-12694 (-----) [006] .... 1920260.585543: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1241332 ofs=135168
- <unknown>-12694 (-----) [006] .... 1920260.585543: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1097199 ofs=139264
- <unknown>-12694 (-----) [006] .... 1920260.585545: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1214197 ofs=143360
- <unknown>-12694 (-----) [006] .... 1920260.585645: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1197633 ofs=147456
- <unknown>-12694 (-----) [006] .... 1920260.585647: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1311536 ofs=151552
- <unknown>-12694 (-----) [006] .... 1920260.585647: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1322952 ofs=155648
- <unknown>-12694 (-----) [006] .... 1920260.585647: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1346974 ofs=159744
- <unknown>-12694 (-----) [006] .... 1920260.585648: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1257232 ofs=163840
- <unknown>-12695 (-----) [004] .... 1920260.586355: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1204484 ofs=700416
- <unknown>-12695 (-----) [004] .... 1920260.586357: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1326426 ofs=704512
- <unknown>-12695 (-----) [004] .... 1920260.586358: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1151808 ofs=708608
- <unknown>-12695 (-----) [004] .... 1920260.586358: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1209422 ofs=712704
- <unknown>-12695 (-----) [004] .... 1920260.586359: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1408387 ofs=716800
- <unknown>-12695 (-----) [004] .... 1920260.586359: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1197336 ofs=720896
- <unknown>-12695 (-----) [004] .... 1920260.586363: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1205652 ofs=724992
- <unknown>-12695 (-----) [004] .... 1920260.586363: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1133421 ofs=729088
- <unknown>-12695 (-----) [004] .... 1920260.586364: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1092173 ofs=733184
- <unknown>-12695 (-----) [004] .... 1920260.586365: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1124430 ofs=737280
- <unknown>-12695 (-----) [004] .... 1920260.586365: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1143926 ofs=741376
- <unknown>-12695 (-----) [004] .... 1920260.586366: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1090109 ofs=745472
- <unknown>-12695 (-----) [004] .... 1920260.586366: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1102012 ofs=749568
- <unknown>-12695 (-----) [004] .... 1920260.586367: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1154930 ofs=753664
- <unknown>-12695 (-----) [004] .... 1920260.586368: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1132993 ofs=757760
- <unknown>-12695 (-----) [004] .... 1920260.586369: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1430780 ofs=761856
- <unknown>-12695 (-----) [004] .... 1920260.586369: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1197452 ofs=765952
- <unknown>-12695 (-----) [004] .... 1920260.586369: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1075111 ofs=770048
- <unknown>-12695 (-----) [004] .... 1920260.586370: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1275616 ofs=774144
- <unknown>-12695 (-----) [004] .... 1920260.586370: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1444981 ofs=778240
- <unknown>-12695 (-----) [004] .... 1920260.586371: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1452592 ofs=782336
- <unknown>-12695 (-----) [004] .... 1920260.586374: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1102857 ofs=786432
- <unknown>-12695 (-----) [004] .... 1920260.586376: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1406969 ofs=790528
- <unknown>-12695 (-----) [004] .... 1920260.586378: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1522553 ofs=794624
- <unknown>-12695 (-----) [004] .... 1920260.586378: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1260771 ofs=798720
- <unknown>-12695 (-----) [004] .... 1920260.586379: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1474649 ofs=802816
- <unknown>-12695 (-----) [004] .... 1920260.586379: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1268708 ofs=806912
- <unknown>-12695 (-----) [004] .... 1920260.586379: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1346144 ofs=811008
- <unknown>-12695 (-----) [004] .... 1920260.586380: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1081167 ofs=815104
- <unknown>-12695 (-----) [004] .... 1920260.586380: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1137677 ofs=819200
- <unknown>-12695 (-----) [004] .... 1920260.586381: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1161175 ofs=823296
- <unknown>-12695 (-----) [004] .... 1920260.586381: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1461331 ofs=827392
- <unknown>-12695 (-----) [004] .... 1920260.586492: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1347219 ofs=831488
- <unknown>-12695 (-----) [004] .... 1920260.586494: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1290004 ofs=835584
- <unknown>-12695 (-----) [004] .... 1920260.586494: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1299174 ofs=839680
- <unknown>-12695 (-----) [004] .... 1920260.586496: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1317595 ofs=843776
- <unknown>-12695 (-----) [004] .... 1920260.586496: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1484924 ofs=847872
- <unknown>-12695 (-----) [004] .... 1920260.586497: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1169920 ofs=851968
- <unknown>-12695 (-----) [004] .... 1920260.586501: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1359189 ofs=856064
- <unknown>-12695 (-----) [004] .... 1920260.586501: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1307842 ofs=860160
- <unknown>-12695 (-----) [004] .... 1920260.586502: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1237858 ofs=864256
- <unknown>-12695 (-----) [004] .... 1920260.586502: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1189461 ofs=868352
- <unknown>-12695 (-----) [004] .... 1920260.586503: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1223232 ofs=872448
- <unknown>-12695 (-----) [004] .... 1920260.586503: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1104076 ofs=876544
- <unknown>-12695 (-----) [004] .... 1920260.586504: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1079223 ofs=880640
- <unknown>-12695 (-----) [004] .... 1920260.586504: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1092537 ofs=884736
- <unknown>-12695 (-----) [004] .... 1920260.586505: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1353960 ofs=888832
- <unknown>-12695 (-----) [004] .... 1920260.586505: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1346330 ofs=892928
- <unknown>-12695 (-----) [004] .... 1920260.586506: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1345764 ofs=897024
- <unknown>-12695 (-----) [004] .... 1920260.586507: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1363913 ofs=901120
- <unknown>-12695 (-----) [004] .... 1920260.586508: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1319570 ofs=905216
- <unknown>-12695 (-----) [004] .... 1920260.586508: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1367024 ofs=909312
- <unknown>-12695 (-----) [004] .... 1920260.586508: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1333808 ofs=913408
- <unknown>-12695 (-----) [004] .... 1920260.586509: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1158627 ofs=917504
- <unknown>-12695 (-----) [004] .... 1920260.586509: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1300368 ofs=921600
- <unknown>-12695 (-----) [004] .... 1920260.586510: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1245363 ofs=925696
- <unknown>-12695 (-----) [004] .... 1920260.586510: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1345609 ofs=929792
- <unknown>-12695 (-----) [004] .... 1920260.586510: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1393826 ofs=933888
- <unknown>-12695 (-----) [004] .... 1920260.586511: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1200552 ofs=937984
- <unknown>-12695 (-----) [004] .... 1920260.586511: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1170885 ofs=942080
- <unknown>-12695 (-----) [004] .... 1920260.586512: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1536209 ofs=946176
- <unknown>-12695 (-----) [004] .... 1920260.586512: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1189630 ofs=950272
- <unknown>-12695 (-----) [004] .... 1920260.586513: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1121010 ofs=954368
- <unknown>-12695 (-----) [004] .... 1920260.586514: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1324474 ofs=958464
- <unknown>-12697 (-----) [007] .... 1920260.586578: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1129628 ofs=299008
- <unknown>-12697 (-----) [007] .... 1920260.586579: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1307120 ofs=303104
- <unknown>-12697 (-----) [007] .... 1920260.586580: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1347284 ofs=307200
- <unknown>-12697 (-----) [007] .... 1920260.586580: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1312996 ofs=311296
- <unknown>-12697 (-----) [007] .... 1920260.586581: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1170623 ofs=315392
- <unknown>-12697 (-----) [007] .... 1920260.586581: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1359281 ofs=319488
- <unknown>-12697 (-----) [007] .... 1920260.586582: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1180021 ofs=323584
- <unknown>-12697 (-----) [007] .... 1920260.586582: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1195728 ofs=327680
- <unknown>-12697 (-----) [007] .... 1920260.586582: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1163642 ofs=331776
- <unknown>-12697 (-----) [007] .... 1920260.586587: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1152538 ofs=335872
- <unknown>-12697 (-----) [007] .... 1920260.586589: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1345922 ofs=339968
- <unknown>-12697 (-----) [007] .... 1920260.586589: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1343604 ofs=344064
- <unknown>-12697 (-----) [007] .... 1920260.586721: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1399371 ofs=479232
- <unknown>-12697 (-----) [007] .... 1920260.586723: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1106549 ofs=483328
- <unknown>-12697 (-----) [007] .... 1920260.586724: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1331546 ofs=487424
- <unknown>-12697 (-----) [007] .... 1920260.586724: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1299299 ofs=491520
- <unknown>-12697 (-----) [007] .... 1920260.586725: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1288883 ofs=495616
- <unknown>-12697 (-----) [007] .... 1920260.586725: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1399049 ofs=499712
- <unknown>-12697 (-----) [007] .... 1920260.586726: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1146931 ofs=503808
- <unknown>-12697 (-----) [007] .... 1920260.586726: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1296592 ofs=507904
- <unknown>-12697 (-----) [007] .... 1920260.586727: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1468397 ofs=512000
- <unknown>-12697 (-----) [007] .... 1920260.586727: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1215698 ofs=516096
- <unknown>-12697 (-----) [007] .... 1920260.586727: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1177341 ofs=520192
- <unknown>-12697 (-----) [007] .... 1920260.586731: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1189162 ofs=524288
- <unknown>-12697 (-----) [007] .... 1920260.586732: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1435997 ofs=528384
- <unknown>-12697 (-----) [007] .... 1920260.586732: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1209896 ofs=532480
- <unknown>-12697 (-----) [007] .... 1920260.586733: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1255888 ofs=536576
- <unknown>-12697 (-----) [007] .... 1920260.586734: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1234200 ofs=540672
- <unknown>-12697 (-----) [007] .... 1920260.586734: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1422854 ofs=544768
- <unknown>-12697 (-----) [007] .... 1920260.586735: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1435794 ofs=548864
- <unknown>-12697 (-----) [007] .... 1920260.586735: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1236279 ofs=552960
- <unknown>-12697 (-----) [007] .... 1920260.586736: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1485732 ofs=557056
- <unknown>-12683 (-----) [005] .... 1920260.586743: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1417198 ofs=561152
- <unknown>-12683 (-----) [005] .... 1920260.586746: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1469450 ofs=565248
- <unknown>-12696 (-----) [004] .... 1920260.587465: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1489023 ofs=1040384
- <unknown>-12696 (-----) [004] .... 1920260.587469: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1449498 ofs=1044480
- <unknown>-12696 (-----) [004] .... 1920260.587469: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1447737 ofs=1048576
- <unknown>-12696 (-----) [004] .... 1920260.587470: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1124530 ofs=1052672
- <unknown>-12696 (-----) [004] .... 1920260.587476: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1246743 ofs=1056768
- <unknown>-12696 (-----) [004] .... 1920260.587476: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1441927 ofs=1060864
- <unknown>-12696 (-----) [004] .... 1920260.587477: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1280581 ofs=1064960
- <unknown>-12696 (-----) [004] .... 1920260.587477: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1289438 ofs=1069056
- <unknown>-12696 (-----) [004] .... 1920260.587477: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1464236 ofs=1073152
- <unknown>-12696 (-----) [004] .... 1920260.587478: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1125808 ofs=1077248
- <unknown>-12696 (-----) [004] .... 1920260.587478: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1329385 ofs=1081344
- <unknown>-12696 (-----) [004] .... 1920260.587480: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1314093 ofs=1085440
- <unknown>-12696 (-----) [004] .... 1920260.587480: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1201837 ofs=1089536
- <unknown>-12696 (-----) [004] .... 1920260.587481: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1327734 ofs=1093632
- <unknown>-12696 (-----) [004] .... 1920260.587481: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1406568 ofs=1097728
- <unknown>-12696 (-----) [004] .... 1920260.587481: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1331873 ofs=1101824
- <unknown>-12696 (-----) [004] .... 1920260.587482: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1331898 ofs=1105920
- <unknown>-12696 (-----) [004] .... 1920260.587482: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1331917 ofs=1110016
- <unknown>-12696 (-----) [004] .... 1920260.587483: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1332091 ofs=1114112
- <unknown>-12696 (-----) [004] .... 1920260.587483: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1108186 ofs=1118208
- <unknown>-12696 (-----) [004] .... 1920260.587486: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1182631 ofs=1122304
- <unknown>-12696 (-----) [004] .... 1920260.587486: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1085941 ofs=1126400
- <unknown>-12696 (-----) [004] .... 1920260.587487: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1433982 ofs=1130496
- <unknown>-12696 (-----) [004] .... 1920260.587487: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1387028 ofs=1134592
- <unknown>-12696 (-----) [004] .... 1920260.587488: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1353117 ofs=1138688
- <unknown>-12696 (-----) [004] .... 1920260.587489: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1352364 ofs=1142784
- <unknown>-12696 (-----) [004] .... 1920260.587489: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1144513 ofs=1146880
- <unknown>-12696 (-----) [004] .... 1920260.587490: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1403984 ofs=1150976
- <unknown>-12696 (-----) [004] .... 1920260.587490: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1278970 ofs=1155072
- <unknown>-12696 (-----) [004] .... 1920260.587491: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1326743 ofs=1159168
- <unknown>-12696 (-----) [004] .... 1920260.587491: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1221809 ofs=1163264
- <unknown>-12696 (-----) [004] .... 1920260.587492: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1268668 ofs=1167360
- <unknown>-12695 (-----) [005] .... 1920260.587502: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1074544 ofs=962560
- <unknown>-12695 (-----) [005] .... 1920260.587506: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1074294 ofs=966656
- <unknown>-12695 (-----) [005] .... 1920260.587506: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1075097 ofs=970752
- <unknown>-12695 (-----) [005] .... 1920260.587507: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1162407 ofs=974848
- <unknown>-12695 (-----) [005] .... 1920260.587507: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1141370 ofs=978944
- <unknown>-12695 (-----) [005] .... 1920260.587508: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1306487 ofs=983040
- <unknown>-12695 (-----) [005] .... 1920260.587508: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1306434 ofs=987136
- <unknown>-12695 (-----) [005] .... 1920260.587514: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1306347 ofs=991232
- <unknown>-12695 (-----) [005] .... 1920260.587514: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1306247 ofs=995328
- <unknown>-12695 (-----) [005] .... 1920260.587515: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1306195 ofs=999424
- <unknown>-12695 (-----) [005] .... 1920260.587516: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1306039 ofs=1003520
- <unknown>-12695 (-----) [005] .... 1920260.587516: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1305983 ofs=1007616
- <unknown>-12694 (-----) [006] .... 1920260.587701: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1216391 ofs=1171456
- <unknown>-12694 (-----) [006] .... 1920260.587705: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1262462 ofs=1175552
- <unknown>-12694 (-----) [006] .... 1920260.587706: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1358114 ofs=1179648
- <unknown>-12694 (-----) [006] .... 1920260.587706: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1357898 ofs=1183744
- <unknown>-12694 (-----) [006] .... 1920260.587707: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1237003 ofs=1187840
- <unknown>-12694 (-----) [006] .... 1920260.587707: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1126319 ofs=1191936
- <unknown>-12694 (-----) [006] .... 1920260.587708: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1415489 ofs=1196032
- <unknown>-12694 (-----) [006] .... 1920260.587708: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1279558 ofs=1200128
- <unknown>-12694 (-----) [006] .... 1920260.587708: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1434022 ofs=1204224
- <unknown>-12694 (-----) [006] .... 1920260.587709: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1220130 ofs=1208320
- <unknown>-12694 (-----) [006] .... 1920260.587710: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1163037 ofs=1212416
- <unknown>-12694 (-----) [006] .... 1920260.587711: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1404501 ofs=1216512
- <unknown>-12694 (-----) [006] .... 1920260.587711: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1406287 ofs=1220608
- <unknown>-12697 (-----) [007] .... 1920260.588132: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1355143 ofs=1376256
- <unknown>-12697 (-----) [007] .... 1920260.588136: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1213923 ofs=1380352
- <unknown>-12697 (-----) [007] .... 1920260.588136: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1243190 ofs=1384448
- <unknown>-12697 (-----) [007] .... 1920260.588143: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1300698 ofs=1388544
- <unknown>-12697 (-----) [007] .... 1920260.588144: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1482568 ofs=1392640
- <unknown>-12697 (-----) [007] .... 1920260.588144: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1461789 ofs=1396736
- <unknown>-12697 (-----) [007] .... 1920260.588145: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1242314 ofs=1400832
- <unknown>-12697 (-----) [007] .... 1920260.588145: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1471996 ofs=1404928
- <unknown>-12697 (-----) [007] .... 1920260.588146: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1242742 ofs=1409024
- <unknown>-12697 (-----) [007] .... 1920260.588146: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1242579 ofs=1413120
- <unknown>-12697 (-----) [007] .... 1920260.588148: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1242553 ofs=1417216
- <unknown>-12697 (-----) [007] .... 1920260.588148: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1457332 ofs=1421312
- <unknown>-12697 (-----) [007] .... 1920260.588149: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1315431 ofs=1425408
- <unknown>-12697 (-----) [007] .... 1920260.588149: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1080653 ofs=1429504
- <unknown>-12697 (-----) [007] .... 1920260.588149: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1324174 ofs=1433600
- <unknown>-12697 (-----) [007] .... 1920260.588150: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1324142 ofs=1437696
- <unknown>-12697 (-----) [007] .... 1920260.588150: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1157760 ofs=1441792
- <unknown>-12697 (-----) [007] .... 1920260.588151: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1075059 ofs=1445888
- <unknown>-12683 (-----) [006] .... 1920260.589785: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1279192 ofs=1486848
- <unknown>-12683 (-----) [006] .... 1920260.589790: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1278527 ofs=1490944
- <unknown>-12683 (-----) [006] .... 1920260.589791: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1091778 ofs=1495040
- <unknown>-12683 (-----) [006] .... 1920260.589791: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1339447 ofs=1499136
- <unknown>-12683 (-----) [006] .... 1920260.589792: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1254007 ofs=1503232
- <unknown>-12683 (-----) [006] .... 1920260.589793: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1115173 ofs=1507328
- <unknown>-12683 (-----) [006] .... 1920260.589793: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1393985 ofs=1511424
- <unknown>-12683 (-----) [006] .... 1920260.589794: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1369123 ofs=1515520
- <unknown>-12683 (-----) [006] .... 1920260.589794: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1314257 ofs=1519616
- <unknown>-12683 (-----) [006] .... 1920260.589802: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1404487 ofs=1523712
- <unknown>-12683 (-----) [006] .... 1920260.589803: mm_filemap_add_to_page_cache: dev 0:64771 ino e745 page=0000000000000000 pfn=1354554 ofs=1527808
- <unknown>-12683 (-----) [006] .... 1920260.594312: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1141445 ofs=9801728
- <unknown>-12683 (-----) [006] .... 1920260.594322: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1323774 ofs=231460864
- <unknown>-12683 (-----) [006] .... 1920260.594326: mm_filemap_add_to_page_cache: dev 0:64771 ino 2 page=0000000000000000 pfn=1323772 ofs=10993664
- <unknown>-12683 (-----) [006] .... 1920260.595212: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1481305 ofs=9805824
- <unknown>-12683 (-----) [006] .... 1920260.595214: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1481306 ofs=9809920
- <unknown>-12683 (-----) [006] .... 1920260.595214: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1481316 ofs=9814016
- <unknown>-12683 (-----) [006] .... 1920260.595215: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1481340 ofs=9818112
- <unknown>-12683 (-----) [006] .... 1920260.595216: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1394587 ofs=9822208
- <unknown>-12683 (-----) [006] .... 1920260.595216: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103455 ofs=9826304
- <unknown>-12683 (-----) [006] .... 1920260.595217: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103271 ofs=9830400
- <unknown>-12683 (-----) [006] .... 1920260.595218: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103168 ofs=9834496
- <unknown>-12683 (-----) [006] .... 1920260.595218: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103145 ofs=9838592
- <unknown>-12683 (-----) [006] .... 1920260.595219: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103115 ofs=9842688
- <unknown>-12683 (-----) [006] .... 1920260.595222: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103057 ofs=9846784
- <unknown>-12683 (-----) [006] .... 1920260.595222: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1331958 ofs=9850880
- <unknown>-12683 (-----) [006] .... 1920260.595227: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1356305 ofs=9854976
- <unknown>-12683 (-----) [006] .... 1920260.595228: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103708 ofs=9859072
- <unknown>-12683 (-----) [006] .... 1920260.595228: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1099286 ofs=9863168
- <unknown>-12683 (-----) [006] .... 1920260.595229: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1435190 ofs=9867264
- <unknown>-12683 (-----) [006] .... 1920260.595229: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1395504 ofs=9871360
- <unknown>-12683 (-----) [006] .... 1920260.595230: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1352916 ofs=9875456
- <unknown>-12683 (-----) [006] .... 1920260.595231: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1255529 ofs=9879552
- <unknown>-12683 (-----) [006] .... 1920260.595231: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1336145 ofs=9883648
- <unknown>-12683 (-----) [006] .... 1920260.595232: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1334143 ofs=9887744
- <unknown>-12683 (-----) [006] .... 1920260.595232: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1328548 ofs=9891840
- <unknown>-12683 (-----) [006] .... 1920260.595232: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1222215 ofs=9895936
- <unknown>-12683 (-----) [006] .... 1920260.595233: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1461056 ofs=9900032
- <unknown>-12683 (-----) [006] .... 1920260.595234: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1228276 ofs=9904128
- <unknown>-12683 (-----) [006] .... 1920260.595235: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1151188 ofs=9908224
- <unknown>-12683 (-----) [006] .... 1920260.595236: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1443605 ofs=9912320
- <unknown>-12683 (-----) [006] .... 1920260.595236: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1146821 ofs=9916416
- <unknown>-12683 (-----) [006] .... 1920260.595237: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103669 ofs=9920512
- <unknown>-12683 (-----) [006] .... 1920260.595238: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103744 ofs=9924608
- <unknown>-12683 (-----) [006] .... 1920260.595238: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1103868 ofs=9928704
- <unknown>-12683 (-----) [006] .... 1920260.595789: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1465942 ofs=15855616
- <unknown>-12683 (-----) [006] .... 1920260.595792: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1323712 ofs=261189632
- <unknown>-12683 (-----) [006] .... 1920260.595998: mm_filemap_add_to_page_cache: dev 0:64771 ino 1 page=0000000000000000 pfn=1323701 ofs=262094848
- <unknown>-12683 (-----) [006] .... 1920260.596191: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1222287 ofs=15859712
- <unknown>-12683 (-----) [006] .... 1920260.596192: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1213146 ofs=15863808
- <unknown>-12683 (-----) [006] .... 1920260.596192: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1310396 ofs=15867904
- <unknown>-12683 (-----) [006] .... 1920260.596193: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1310177 ofs=15872000
- <unknown>-12683 (-----) [006] .... 1920260.596194: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1187914 ofs=15876096
- <unknown>-12683 (-----) [006] .... 1920260.596195: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1322409 ofs=15880192
- <unknown>-12683 (-----) [006] .... 1920260.596195: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1282484 ofs=15884288
- <unknown>-12683 (-----) [006] .... 1920260.596200: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1097245 ofs=15888384
- <unknown>-12683 (-----) [006] .... 1920260.596200: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1416816 ofs=15892480
- <unknown>-12683 (-----) [006] .... 1920260.596201: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1257125 ofs=15896576
- <unknown>-12683 (-----) [006] .... 1920260.596201: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1403527 ofs=15900672
- <unknown>-12683 (-----) [006] .... 1920260.596202: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1218006 ofs=15904768
- <unknown>-12683 (-----) [006] .... 1920260.596202: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1153893 ofs=15908864
- <unknown>-12683 (-----) [006] .... 1920260.596202: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1328023 ofs=15912960
- <unknown>-12683 (-----) [006] .... 1920260.596203: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1465412 ofs=15917056
- <unknown>-12683 (-----) [006] .... 1920260.596203: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1092448 ofs=15921152
- <unknown>-12683 (-----) [006] .... 1920260.596204: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1239220 ofs=15925248
- <unknown>-12683 (-----) [006] .... 1920260.596204: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1276491 ofs=15929344
- <unknown>-12683 (-----) [006] .... 1920260.596205: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1262240 ofs=15933440
- <unknown>-12683 (-----) [006] .... 1920260.596206: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1323793 ofs=15937536
- <unknown>-12683 (-----) [006] .... 1920260.596206: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1074937 ofs=15941632
- <unknown>-12683 (-----) [006] .... 1920260.596207: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1311157 ofs=15945728
- <unknown>-12683 (-----) [006] .... 1920260.596207: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1308442 ofs=15949824
- <unknown>-12683 (-----) [006] .... 1920260.596210: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1467709 ofs=15953920
- <unknown>-12683 (-----) [006] .... 1920260.596211: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1394299 ofs=15958016
- <unknown>-12683 (-----) [004] .... 1920260.612586: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1316156 ofs=344064
- <unknown>-12683 (-----) [004] .... 1920260.612591: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1406323 ofs=348160
- <unknown>-12683 (-----) [004] .... 1920260.612601: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1216972 ofs=352256
- <unknown>-12683 (-----) [004] .... 1920260.612605: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1271924 ofs=356352
- <unknown>-12683 (-----) [004] .... 1920260.612605: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1369225 ofs=360448
- <unknown>-12683 (-----) [004] .... 1920260.612608: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1318474 ofs=364544
- <unknown>-12683 (-----) [004] .... 1920260.612609: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1227283 ofs=368640
- <unknown>-12683 (-----) [004] .... 1920260.612613: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1364376 ofs=372736
- <unknown>-12683 (-----) [004] .... 1920260.612613: mm_filemap_add_to_page_cache: dev 0:64771 ino 180a page=0000000000000000 pfn=1073400 ofs=376832
diff --git a/startop/scripts/iorap/test_fixtures/compiler/test_result_with_duration.TraceFile.pb b/startop/scripts/iorap/test_fixtures/compiler/test_result_with_duration.TraceFile.pb
deleted file mode 100644
index ab3df45f8c54..000000000000
--- a/startop/scripts/iorap/test_fixtures/compiler/test_result_with_duration.TraceFile.pb
+++ /dev/null
Binary files differ
diff --git a/startop/scripts/iorap/test_fixtures/compiler/test_result_without_duration.TraceFile.pb b/startop/scripts/iorap/test_fixtures/compiler/test_result_without_duration.TraceFile.pb
deleted file mode 100644
index 17cb11662172..000000000000
--- a/startop/scripts/iorap/test_fixtures/compiler/test_result_without_duration.TraceFile.pb
+++ /dev/null
Binary files differ
diff --git a/startop/scripts/lib/cmd_utils.py b/startop/scripts/lib/cmd_utils.py
deleted file mode 100644
index 6071f145fe1d..000000000000
--- a/startop/scripts/lib/cmd_utils.py
+++ /dev/null
@@ -1,184 +0,0 @@
-#!/usr/bin/env python3
-#
-# 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.
-
-"""Helper util libraries for command line operations."""
-
-import asyncio
-import sys
-import time
-from typing import Tuple, Optional, List
-
-import lib.print_utils as print_utils
-
-TIMEOUT = 50
-SIMULATE = False
-
-def run_command_nofail(cmd: List[str], **kwargs) -> None:
- """Runs cmd list with default timeout.
-
- Throws exception if the execution fails.
- """
- my_kwargs = {"timeout": TIMEOUT, "shell": False, "simulate": False}
- my_kwargs.update(kwargs)
- passed, out = execute_arbitrary_command(cmd, **my_kwargs)
- if not passed:
- raise RuntimeError(
- "Failed to execute %s (kwargs=%s), output=%s" % (cmd, kwargs, out))
-
-def run_adb_shell_command(cmd: str) -> Tuple[bool, str]:
- """Runs command using adb shell.
-
- Returns:
- A tuple of running status (True=succeeded, False=failed or timed out) and
- std output (string contents of stdout with trailing whitespace removed).
- """
- return run_shell_command('adb shell "{}"'.format(cmd))
-
-def run_shell_func(script_path: str,
- func: str,
- args: List[str]) -> Tuple[bool, str]:
- """Runs shell function with default timeout.
-
- Returns:
- A tuple of running status (True=succeeded, False=failed or timed out) and
- std output (string contents of stdout with trailing whitespace removed) .
- """
- if args:
- cmd = 'bash -c "source {script_path}; {func} {args}"'.format(
- script_path=script_path,
- func=func,
- args=' '.join("'{}'".format(arg) for arg in args))
- else:
- cmd = 'bash -c "source {script_path}; {func}"'.format(
- script_path=script_path,
- func=func)
-
- print_utils.debug_print(cmd)
- return run_shell_command(cmd)
-
-def run_shell_command(cmd: str) -> Tuple[bool, str]:
- """Runs shell command with default timeout.
-
- Returns:
- A tuple of running status (True=succeeded, False=failed or timed out) and
- std output (string contents of stdout with trailing whitespace removed) .
- """
- return execute_arbitrary_command([cmd],
- TIMEOUT,
- shell=True,
- simulate=SIMULATE)
-
-def execute_arbitrary_command(cmd: List[str],
- timeout: int,
- shell: bool,
- simulate: bool) -> Tuple[bool, str]:
- """Run arbitrary shell command with default timeout.
-
- Mostly copy from
- frameworks/base/startop/scripts/app_startup/app_startup_runner.py.
-
- Args:
- cmd: list of cmd strings.
- timeout: the time limit of running cmd.
- shell: indicate if the cmd is a shell command.
- simulate: if it's true, do not run the command and assume the running is
- successful.
-
- Returns:
- A tuple of running status (True=succeeded, False=failed or timed out) and
- std output (string contents of stdout with trailing whitespace removed) .
- """
- if simulate:
- print(cmd)
- return True, ''
-
- print_utils.debug_print('[EXECUTE]', cmd)
- # block until either command finishes or the timeout occurs.
- loop = asyncio.get_event_loop()
-
- (return_code, script_output) = loop.run_until_complete(
- _run_command(*cmd, shell=shell, timeout=timeout))
-
- script_output = script_output.decode() # convert bytes to str
-
- passed = (return_code == 0)
- print_utils.debug_print('[$?]', return_code)
- if not passed:
- print('[FAILED, code:%s]' % (return_code), script_output, file=sys.stderr)
-
- return passed, script_output.rstrip()
-
-async def _run_command(*args: List[str],
- shell: bool = False,
- timeout: Optional[int] = None) -> Tuple[int, bytes]:
- if shell:
- process = await asyncio.create_subprocess_shell(
- *args, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.STDOUT)
- else:
- process = await asyncio.create_subprocess_exec(
- *args, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.STDOUT)
-
- script_output = b''
-
- print_utils.debug_print('[PID]', process.pid)
-
- timeout_remaining = timeout
- time_started = time.time()
-
- # read line (sequence of bytes ending with b'\n') asynchronously
- while True:
- try:
- line = await asyncio.wait_for(process.stdout.readline(),
- timeout_remaining)
- print_utils.debug_print('[STDOUT]', line)
- script_output += line
-
- if timeout_remaining:
- time_elapsed = time.time() - time_started
- timeout_remaining = timeout - time_elapsed
- except asyncio.TimeoutError:
- print_utils.debug_print('[TIMEDOUT] Process ', process.pid)
-
- print_utils.debug_print('[TIMEDOUT] Sending SIGTERM.')
- process.terminate()
-
- # 5 second timeout for process to handle SIGTERM nicely.
- try:
- (remaining_stdout,
- remaining_stderr) = await asyncio.wait_for(process.communicate(), 5)
- script_output += remaining_stdout
- except asyncio.TimeoutError:
- print_utils.debug_print('[TIMEDOUT] Sending SIGKILL.')
- process.kill()
-
- # 5 second timeout to finish with SIGKILL.
- try:
- (remaining_stdout,
- remaining_stderr) = await asyncio.wait_for(process.communicate(), 5)
- script_output += remaining_stdout
- except asyncio.TimeoutError:
- # give up, this will leave a zombie process.
- print_utils.debug_print('[TIMEDOUT] SIGKILL failed for process ',
- process.pid)
- time.sleep(100)
-
- return -1, script_output
- else:
- if not line: # EOF
- break
-
- code = await process.wait() # wait for child process to exit
- return code, script_output
diff --git a/startop/scripts/lib/logcat_utils.py b/startop/scripts/lib/logcat_utils.py
deleted file mode 100644
index 8a3d00b46771..000000000000
--- a/startop/scripts/lib/logcat_utils.py
+++ /dev/null
@@ -1,104 +0,0 @@
-#!/usr/bin/env python3
-#
-# 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.
-
-"""Helper util libraries for parsing logcat logs."""
-
-import asyncio
-import re
-from datetime import datetime
-from typing import Optional, Pattern
-
-# local import
-import lib.print_utils as print_utils
-
-def parse_logcat_datetime(timestamp: str) -> Optional[datetime]:
- """Parses the timestamp of logcat.
-
- Params:
- timestamp: for example "2019-07-01 16:13:55.221".
-
- Returns:
- a datetime of timestamp with the year now.
- """
- try:
- # Match the format of logcat. For example: "2019-07-01 16:13:55.221",
- # because it doesn't have year, set current year to it.
- timestamp = datetime.strptime(timestamp,
- '%Y-%m-%d %H:%M:%S.%f')
- return timestamp
- except ValueError as ve:
- print_utils.debug_print('Invalid line: ' + timestamp)
- return None
-
-def _is_time_out(timeout: datetime, line: str) -> bool:
- """Checks if the timestamp of this line exceeds the timeout.
-
- Returns:
- true if the timestamp exceeds the timeout.
- """
- # Get the timestampe string.
- cur_timestamp_str = ' '.join(re.split(r'\s+', line)[0:2])
- timestamp = parse_logcat_datetime(cur_timestamp_str)
- if not timestamp:
- return False
-
- return timestamp > timeout
-
-async def _blocking_wait_for_logcat_pattern(timestamp: datetime,
- pattern: Pattern,
- timeout: datetime) -> Optional[str]:
- # Show the year in the timestampe.
- logcat_cmd = 'adb logcat -v UTC -v year -v threadtime -T'.split()
- logcat_cmd.append(str(timestamp))
- print_utils.debug_print('[LOGCAT]:' + ' '.join(logcat_cmd))
-
- # Create subprocess
- process = await asyncio.create_subprocess_exec(
- *logcat_cmd,
- # stdout must a pipe to be accessible as process.stdout
- stdout=asyncio.subprocess.PIPE)
-
- while (True):
- # Read one line of output.
- data = await process.stdout.readline()
- line = data.decode('utf-8').rstrip()
-
- # 2019-07-01 14:54:21.946 27365 27392 I ActivityTaskManager: Displayed
- # com.android.settings/.Settings: +927ms
- # TODO: Detect timeouts even when there is no logcat output.
- if _is_time_out(timeout, line):
- print_utils.debug_print('DID TIMEOUT BEFORE SEEING ANYTHING ('
- 'timeout={timeout} seconds << {pattern} '
- '>>'.format(timeout=timeout, pattern=pattern))
- return None
-
- if pattern.match(line):
- print_utils.debug_print(
- 'WE DID SEE PATTERN << "{}" >>.'.format(pattern))
- return line
-
-def blocking_wait_for_logcat_pattern(timestamp: datetime,
- pattern: Pattern,
- timeout: datetime) -> Optional[str]:
- """Selects the line that matches the pattern and within the timeout.
-
- Returns:
- the line that matches the pattern and within the timeout.
- """
- loop = asyncio.get_event_loop()
- result = loop.run_until_complete(
- _blocking_wait_for_logcat_pattern(timestamp, pattern, timeout))
- return result
diff --git a/startop/scripts/lib/logcat_utils_test.py b/startop/scripts/lib/logcat_utils_test.py
deleted file mode 100644
index ab82515bc4fa..000000000000
--- a/startop/scripts/lib/logcat_utils_test.py
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/usr/bin/env python3
-#
-# 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.
-#
-"""Unit tests for the logcat_utils.py script."""
-
-import asyncio
-import datetime
-import re
-
-import logcat_utils
-from mock import MagicMock, patch
-
-def test_parse_logcat_datatime():
- # Act
- result = logcat_utils.parse_logcat_datetime('2019-07-01 16:13:55.221')
-
- # Assert
- assert result == datetime.datetime(2019, 7, 1, 16, 13, 55, 221000)
-
-class AsyncMock(MagicMock):
- async def __call__(self, *args, **kwargs):
- return super(AsyncMock, self).__call__(*args, **kwargs)
-
-def _async_return():
- f = asyncio.Future()
- f.set_result(
- b'2019-07-01 15:51:53.290 27365 27392 I ActivityTaskManager: '
- b'Displayed com.google.android.music/com.android.music.activitymanagement.'
- b'TopLevelActivity: +1s7ms')
- return f
-
-def test_parse_displayed_time_succeed():
- # Act
- with patch('asyncio.create_subprocess_exec',
- new_callable=AsyncMock) as asyncio_mock:
- asyncio_mock.return_value.stdout.readline = _async_return
- timestamp = datetime.datetime(datetime.datetime.now().year, 7, 1, 16, 13,
- 55, 221000)
- timeout_dt = timestamp + datetime.timedelta(0, 10)
- pattern = re.compile('.*ActivityTaskManager: Displayed '
- 'com.google.android.music/com.android.music.*')
- result = logcat_utils.blocking_wait_for_logcat_pattern(timestamp,
- pattern,
- timeout_dt)
-
- # Assert
- assert result == '2019-07-01 15:51:53.290 27365 27392 I ' \
- 'ActivityTaskManager: ' \
- 'Displayed com.google.android.music/com.android.music.' \
- 'activitymanagement.TopLevelActivity: +1s7ms'
-
-def _async_timeout_return():
- f = asyncio.Future()
- f.set_result(
- b'2019-07-01 17:51:53.290 27365 27392 I ActivityTaskManager: '
- b'Displayed com.google.android.music/com.android.music.activitymanagement.'
- b'TopLevelActivity: +1s7ms')
- return f
-
-def test_parse_displayed_time_timeout():
- # Act
- with patch('asyncio.create_subprocess_exec',
- new_callable=AsyncMock) as asyncio_mock:
- asyncio_mock.return_value.stdout.readline = _async_timeout_return
- timestamp = datetime.datetime(datetime.datetime.now().year,
- 7, 1, 16, 13, 55, 221000)
- timeout_dt = timestamp + datetime.timedelta(0, 10)
- pattern = re.compile('.*ActivityTaskManager: Displayed '
- 'com.google.android.music/com.android.music.*')
- result = logcat_utils.blocking_wait_for_logcat_pattern(timestamp,
- pattern,
- timeout_dt)
-
- # Assert
- assert result == None
diff --git a/startop/scripts/lib/print_utils.py b/startop/scripts/lib/print_utils.py
deleted file mode 100644
index 8c5999d99d6e..000000000000
--- a/startop/scripts/lib/print_utils.py
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/usr/bin/env python3
-#
-# 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.
-
-"""Helper util libraries for debug printing."""
-
-import sys
-
-DEBUG = False
-
-def debug_print(*args, **kwargs):
- """Prints the args to sys.stderr if the DEBUG is set."""
- if DEBUG:
- print(*args, **kwargs, file=sys.stderr)
-
-def error_print(*args, **kwargs):
- print('[ERROR]:', *args, file=sys.stderr, **kwargs)
-
-def _expand_gen_repr(args):
- """Like repr but any generator-like object has its iterator consumed
- and then called repr on."""
- new_args_list = []
- for i in args:
- # detect iterable objects that do not have their own override of __str__
- if hasattr(i, '__iter__'):
- to_str = getattr(i, '__str__')
- if to_str.__objclass__ == object:
- # the repr for a generator is just type+address, expand it out instead.
- new_args_list.append([_expand_gen_repr([j])[0] for j in i])
- continue
- # normal case: uses the built-in to-string
- new_args_list.append(i)
- return new_args_list
-
-def debug_print_gen(*args, **kwargs):
- """Like _debug_print but will turn any iterable args into a list."""
- if not DEBUG:
- return
-
- new_args_list = _expand_gen_repr(args)
- debug_print(*new_args_list, **kwargs)
-
-def debug_print_nd(*args, **kwargs):
- """Like _debug_print but will turn any NamedTuple-type args into a string."""
- if not DEBUG:
- return
-
- new_args_list = []
- for i in args:
- if hasattr(i, '_field_types'):
- new_args_list.append("%s: %s" % (i.__name__, i._field_types))
- else:
- new_args_list.append(i)
-
- debug_print(*new_args_list, **kwargs)
diff --git a/startop/scripts/trace_analyzer/lib/trace2db.py b/startop/scripts/trace_analyzer/lib/trace2db.py
deleted file mode 100644
index 42a33aff046d..000000000000
--- a/startop/scripts/trace_analyzer/lib/trace2db.py
+++ /dev/null
@@ -1,355 +0,0 @@
-#!/usr/bin/python3
-# 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.
-
-import re
-import sys
-
-from sqlalchemy import create_engine
-from sqlalchemy import Column, Date, Integer, Float, String, ForeignKey
-from sqlalchemy.ext.declarative import declarative_base
-from sqlalchemy.orm import relationship
-
-from sqlalchemy.orm import sessionmaker
-
-import sqlalchemy
-
-from typing import Optional, Tuple
-
-_DEBUG = False # print sql commands to console
-_FLUSH_LIMIT = 10000 # how many entries are parsed before flushing to DB from memory
-
-Base = declarative_base()
-
-class RawFtraceEntry(Base):
- __tablename__ = 'raw_ftrace_entries'
-
- id = Column(Integer, primary_key=True)
- task_name = Column(String, nullable=True) # <...> -> None.
- task_pid = Column(String, nullable=False)
- tgid = Column(Integer, nullable=True) # ----- -> None.
- cpu = Column(Integer, nullable=False)
- timestamp = Column(Float, nullable=False)
- function = Column(String, nullable=False)
- function_args = Column(String, nullable=False)
-
- # 1:1 relation with MmFilemapAddToPageCache.
- mm_filemap_add_to_page_cache = relationship("MmFilemapAddToPageCache",
- back_populates="raw_ftrace_entry")
-
- @staticmethod
- def parse_dict(line):
- # ' <...>-5521 (-----) [003] ...1 17148.446877: tracing_mark_write: trace_event_clock_sync: parent_ts=17148.447266'
- m = re.match('\s*(.*)-(\d+)\s+\(([^\)]+)\)\s+\[(\d+)\]\s+([\w.]{4})\s+(\d+[.]\d+):\s+(\w+):\s+(.*)', line)
- if not m:
- return None
-
- groups = m.groups()
- # groups example:
- # ('<...>',
- # '5521',
- # '-----',
- # '003',
- # '...1',
- # '17148.446877',
- # 'tracing_mark_write',
- # 'trace_event_clock_sync: parent_ts=17148.447266')
- task_name = groups[0]
- if task_name == '<...>':
- task_name = None
-
- task_pid = int(groups[1])
- tgid = groups[2]
- if tgid == '-----':
- tgid = None
-
- cpu = int(groups[3])
- # irq_flags = groups[4]
- timestamp = float(groups[5])
- function = groups[6]
- function_args = groups[7]
-
- return {'task_name': task_name, 'task_pid': task_pid, 'tgid': tgid, 'cpu': cpu, 'timestamp': timestamp, 'function': function, 'function_args': function_args}
-
-class SchedSwitch(Base):
- __tablename__ = 'sched_switches'
-
- id = Column(Integer, ForeignKey('raw_ftrace_entries.id'), primary_key=True)
-
- prev_comm = Column(String, nullable=False)
- prev_pid = Column(Integer, nullable=False)
- prev_prio = Column(Integer, nullable=False)
- prev_state = Column(String, nullable=False)
-
- next_comm = Column(String, nullable=False)
- next_pid = Column(Integer, nullable=False)
- next_prio = Column(Integer, nullable=False)
-
- @staticmethod
- def parse_dict(function_args, id = None):
- # 'prev_comm=kworker/u16:5 prev_pid=13971 prev_prio=120 prev_state=S ==> next_comm=swapper/4 next_pid=0 next_prio=120'
- m = re.match("prev_comm=(.*) prev_pid=(\d+) prev_prio=(\d+) prev_state=(.*) ==> next_comm=(.*) next_pid=(\d+) next_prio=(\d+) ?", function_args)
- if not m:
- return None
-
- groups = m.groups()
- # ('kworker/u16:5', '13971', '120', 'S', 'swapper/4', '0', '120')
- d = {}
- if id is not None:
- d['id'] = id
- d['prev_comm'] = groups[0]
- d['prev_pid'] = int(groups[1])
- d['prev_prio'] = int(groups[2])
- d['prev_state'] = groups[3]
- d['next_comm'] = groups[4]
- d['next_pid'] = int(groups[5])
- d['next_prio'] = int(groups[6])
-
- return d
-
-class SchedBlockedReason(Base):
- __tablename__ = 'sched_blocked_reasons'
-
- id = Column(Integer, ForeignKey('raw_ftrace_entries.id'), primary_key=True)
-
- pid = Column(Integer, nullable=False)
- iowait = Column(Integer, nullable=False)
- caller = Column(String, nullable=False)
-
- @staticmethod
- def parse_dict(function_args, id = None):
- # 'pid=2289 iowait=1 caller=wait_on_page_bit_common+0x2a8/0x5f'
- m = re.match("pid=(\d+) iowait=(\d+) caller=(.*) ?", function_args)
- if not m:
- return None
-
- groups = m.groups()
- # ('2289', '1', 'wait_on_page_bit_common+0x2a8/0x5f8')
- d = {}
- if id is not None:
- d['id'] = id
- d['pid'] = int(groups[0])
- d['iowait'] = int(groups[1])
- d['caller'] = groups[2]
-
- return d
-
-class MmFilemapAddToPageCache(Base):
- __tablename__ = 'mm_filemap_add_to_page_caches'
-
- id = Column(Integer, ForeignKey('raw_ftrace_entries.id'), primary_key=True)
-
- dev = Column(Integer, nullable=False) # decoded from ${major}:${minor} syntax.
- dev_major = Column(Integer, nullable=False) # original ${major} value.
- dev_minor = Column(Integer, nullable=False) # original ${minor} value.
-
- ino = Column(Integer, nullable=False) # decoded from hex to base 10
- page = Column(Integer, nullable=False) # decoded from hex to base 10
-
- pfn = Column(Integer, nullable=False)
- ofs = Column(Integer, nullable=False)
-
- # 1:1 relation with RawFtraceEntry.
- raw_ftrace_entry = relationship("RawFtraceEntry", uselist=False)
-
- @staticmethod
- def parse_dict(function_args, id = None):
- # dev 253:6 ino b2c7 page=00000000ec787cd9 pfn=1478539 ofs=4096
- m = re.match("dev (\d+):(\d+) ino ([0-9a-fA-F]+) page=([0-9a-fA-F]+) pfn=(\d+) ofs=(\d+)", function_args)
- if not m:
- return None
-
- groups = m.groups()
- # ('253', '6', 'b2c7', '00000000ec787cd9', '1478539', '4096')
- d = {}
- if id is not None:
- d['id'] = id
-
- device_major = d['dev_major'] = int(groups[0])
- device_minor = d['dev_minor'] = int(groups[1])
- d['dev'] = device_major << 8 | device_minor
- d['ino'] = int(groups[2], 16)
- d['page'] = int(groups[3], 16)
- d['pfn'] = int(groups[4])
- d['ofs'] = int(groups[5])
-
- return d
-
-class Trace2Db:
- def __init__(self, db_filename: str):
- (s, e) = self._init_sqlalchemy(db_filename)
- self._session = s
- self._engine = e
- self._raw_ftrace_entry_filter = lambda x: True
-
- def set_raw_ftrace_entry_filter(self, flt):
- """
- Install a function dict(RawFtraceEntry) -> bool
-
- If this returns 'false', then we skip adding the RawFtraceEntry to the database.
- """
- self._raw_ftrace_entry_filter = flt
-
- @staticmethod
- def _init_sqlalchemy(db_filename: str) -> Tuple[object, object]:
- global _DEBUG
- engine = create_engine('sqlite:///' + db_filename, echo=_DEBUG)
-
- # CREATE ... (tables)
- Base.metadata.create_all(engine)
-
- Session = sessionmaker(bind=engine)
- session = Session()
- return (session, engine)
-
- def parse_file_into_db(self, filename: str, limit: Optional[int] = None):
- """
- Parse the ftrace/systrace at 'filename',
- inserting the values into the current sqlite database.
-
- :return: number of RawFtraceEntry inserted.
- """
- return parse_file(filename, self._session, self._engine, self._raw_ftrace_entry_filter, limit)
-
- def parse_file_buf_into_db(self, file_buf, limit: Optional[int] = None):
- """
- Parse the ftrace/systrace at 'filename',
- inserting the values into the current sqlite database.
-
- :return: number of RawFtraceEntry inserted.
- """
- return parse_file_buf(file_buf, self._session, self._engine, self._raw_ftrace_entry_filter, limit)
-
-
- @property
- def session(self):
- return self._session
-
-def insert_pending_entries(engine, kls, lst):
- if len(lst) > 0:
- # for some reason, it tries to generate an empty INSERT statement with len=0,
- # which of course violates the first non-null constraint.
- try:
- # Performance-sensitive parsing according to:
- # https://docs.sqlalchemy.org/en/13/faq/performance.html#i-m-inserting-400-000-rows-with-the-orm-and-it-s-really-slow
- engine.execute(kls.__table__.insert(), lst)
- lst.clear()
- except sqlalchemy.exc.IntegrityError as err:
- # possibly violating some SQL constraint, print data here.
- print(err)
- print(lst)
- raise
-
-def parse_file(filename: str, *args, **kwargs) -> int:
- # use explicit encoding to avoid UnicodeDecodeError.
- with open(filename, encoding="ISO-8859-1") as f:
- return parse_file_buf(f, *args, **kwargs)
-
-def parse_file_buf(filebuf, session, engine, raw_ftrace_entry_filter, limit=None) -> int:
- global _FLUSH_LIMIT
- count = 0
- # count and id are not equal, because count still increases for invalid lines.
- id = 0
-
- pending_entries = []
- pending_sched_switch = []
- pending_sched_blocked_reasons = []
- pending_mm_filemap_add_to_pagecaches = []
-
- def insert_all_pending_entries():
- insert_pending_entries(engine, RawFtraceEntry, pending_entries)
- insert_pending_entries(engine, SchedSwitch, pending_sched_switch)
- insert_pending_entries(engine, SchedBlockedReason, pending_sched_blocked_reasons)
- insert_pending_entries(engine, MmFilemapAddToPageCache, pending_mm_filemap_add_to_pagecaches)
-
- # for trace.html files produced by systrace,
- # the actual ftrace is in the 'second' trace-data script class.
- parsing_trace_data = 0
- parsing_systrace_file = False
-
- f = filebuf
- for l in f:
- if parsing_trace_data == 0 and l == "<!DOCTYPE html>\n":
- parsing_systrace_file = True
- continue
- if parsing_trace_data != 2 and parsing_systrace_file:
- if l == ' <script class="trace-data" type="application/text">\n':
- parsing_trace_data = parsing_trace_data + 1
- continue
-
- if parsing_systrace_file and parsing_trace_data != 2:
- continue
- elif parsing_systrace_file and parsing_trace_data == 2 and l == " </script>\n":
- # the rest of this file is just random html
- break
-
- # now parsing the ftrace data.
- if len(l) > 1 and l[0] == '#':
- continue
-
- count = count + 1
-
- if limit and count >= limit:
- break
-
- raw_ftrace_entry = RawFtraceEntry.parse_dict(l)
- if not raw_ftrace_entry:
- print("WARNING: Failed to parse raw ftrace entry: " + l)
- continue
-
- if not raw_ftrace_entry_filter(raw_ftrace_entry):
- # Skip processing raw ftrace entries that don't match a filter.
- # This is an optimization for when Trace2Db is used programatically
- # to avoid having an overly large database.
- continue
-
- pending_entries.append(raw_ftrace_entry)
- id = id + 1
-
- if raw_ftrace_entry['function'] == 'sched_switch':
- sched_switch = SchedSwitch.parse_dict(raw_ftrace_entry['function_args'], id)
-
- if not sched_switch:
- print("WARNING: Failed to parse sched_switch: " + l)
- else:
- pending_sched_switch.append(sched_switch)
-
- elif raw_ftrace_entry['function'] == 'sched_blocked_reason':
- sbr = SchedBlockedReason.parse_dict(raw_ftrace_entry['function_args'], id)
-
- if not sbr:
- print("WARNING: Failed to parse sched_blocked_reason: " + l)
- else:
- pending_sched_blocked_reasons.append(sbr)
-
- elif raw_ftrace_entry['function'] == 'mm_filemap_add_to_page_cache':
- d = MmFilemapAddToPageCache.parse_dict(raw_ftrace_entry['function_args'],
- id)
- if not d:
- print("WARNING: Failed to parse mm_filemap_add_to_page_cache: " + l)
- else:
- pending_mm_filemap_add_to_pagecaches.append(d)
-
- # Objects are cached in python memory, not yet sent to SQL database.
-
- # Send INSERT/UPDATE/etc statements to the underlying SQL database.
- if count % _FLUSH_LIMIT == 0:
- insert_all_pending_entries()
-
- insert_all_pending_entries()
-
- # Ensure underlying database commits changes from memory to disk.
- session.commit()
-
- return count
diff --git a/startop/scripts/trace_analyzer/lib/trace2db_test.py b/startop/scripts/trace_analyzer/lib/trace2db_test.py
deleted file mode 100755
index 3b326f000a7d..000000000000
--- a/startop/scripts/trace_analyzer/lib/trace2db_test.py
+++ /dev/null
@@ -1,222 +0,0 @@
-#!/usr/bin/env python3
-#
-# 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.
-#
-
-"""
-Unit tests for inode2filename module.
-
-Install:
- $> sudo apt-get install python3-pytest ## OR
- $> pip install -U pytest
-See also https://docs.pytest.org/en/latest/getting-started.html
-
-Usage:
- $> ./inode2filename_test.py
- $> pytest inode2filename_test.py
- $> python -m pytest inode2filename_test.py
-
-See also https://docs.pytest.org/en/latest/usage.html
-"""
-
-# global imports
-import io
-from copy import deepcopy
-
-# pip imports
-# local imports
-from trace2db import *
-
-# This pretty-prints the raw dictionary of the sqlalchemy object if it fails.
-class EqualsSqlAlchemyObject:
- # For convenience to write shorter tests, we also add 'ignore_fields' which allow us to specify
- # which fields to ignore when doing the comparison.
- def __init__(self_, self, ignore_fields=[]):
- self_.self = self
- self_.ignore_fields = ignore_fields
-
- # Do field-by-field comparison.
- # It seems that SQLAlchemy does not implement __eq__ itself so we have to do it ourselves.
- def __eq__(self_, other):
- if isinstance(other, EqualsSqlAlchemyObject):
- other = other.self
-
- self = self_.self
-
- classes_match = isinstance(other, self.__class__)
- a, b = deepcopy(self.__dict__), deepcopy(other.__dict__)
-
- #compare based on equality our attributes, ignoring SQLAlchemy internal stuff
-
- a.pop('_sa_instance_state', None)
- b.pop('_sa_instance_state', None)
-
- for f in self_.ignore_fields:
- a.pop(f, None)
- b.pop(f, None)
-
- attrs_match = (a == b)
- return classes_match and attrs_match
-
- def __repr__(self):
- return repr(self.self.__dict__)
-
-
-def assert_eq_ignore_id(left, right):
- # This pretty-prints the raw dictionary of the sqlalchemy object if it fails.
- # It does field-by-field comparison, but ignores the 'id' field.
- assert EqualsSqlAlchemyObject(left, ignore_fields=['id']) == EqualsSqlAlchemyObject(right)
-
-def parse_trace_file_to_db(*contents):
- """
- Make temporary in-memory sqlite3 database by parsing the string contents as a trace.
-
- :return: Trace2Db instance
- """
- buf = io.StringIO()
-
- for c in contents:
- buf.write(c)
- buf.write("\n")
-
- buf.seek(0)
-
- t2d = Trace2Db(":memory:")
- t2d.parse_file_buf_into_db(buf)
-
- buf.close()
-
- return t2d
-
-def test_ftrace_mm_filemap_add_to_pagecache():
- test_contents = """
-MediaStoreImpor-27212 (27176) [000] .... 16136.595194: mm_filemap_add_to_page_cache: dev 253:6 ino 7580 page=0000000060e990c7 pfn=677646 ofs=159744
-MediaStoreImpor-27212 (27176) [000] .... 16136.595920: mm_filemap_add_to_page_cache: dev 253:6 ino 7580 page=0000000048e2e156 pfn=677645 ofs=126976
-MediaStoreImpor-27212 (27176) [000] .... 16136.597793: mm_filemap_add_to_page_cache: dev 253:6 ino 7580 page=0000000051eabfb2 pfn=677644 ofs=122880
-MediaStoreImpor-27212 (27176) [000] .... 16136.597815: mm_filemap_add_to_page_cache: dev 253:6 ino 7580 page=00000000ce7cd606 pfn=677643 ofs=131072
-MediaStoreImpor-27212 (27176) [000] .... 16136.603732: mm_filemap_add_to_page_cache: dev 253:6 ino 1 page=000000008ffd3030 pfn=730119 ofs=186482688
-MediaStoreImpor-27212 (27176) [000] .... 16136.604126: mm_filemap_add_to_page_cache: dev 253:6 ino b1d8 page=0000000098d4d2e2 pfn=829676 ofs=0
- <...>-27197 (-----) [002] .... 16136.613471: mm_filemap_add_to_page_cache: dev 253:6 ino 7580 page=00000000aca88a97 pfn=743346 ofs=241664
- <...>-27197 (-----) [002] .... 16136.615979: mm_filemap_add_to_page_cache: dev 253:6 ino 7580 page=00000000351f2bc1 pfn=777799 ofs=106496
- <...>-27224 (-----) [006] .... 16137.400090: mm_filemap_add_to_page_cache: dev 253:6 ino 712d page=000000006ff7ffdb pfn=754861 ofs=0
- <...>-1396 (-----) [000] .... 16137.451660: mm_filemap_add_to_page_cache: dev 253:6 ino 1 page=00000000ba0cbb34 pfn=769173 ofs=187191296
- <...>-1396 (-----) [000] .... 16137.453020: mm_filemap_add_to_page_cache: dev 253:6 ino b285 page=00000000f6ef038e pfn=820291 ofs=0
- <...>-1396 (-----) [000] .... 16137.453067: mm_filemap_add_to_page_cache: dev 253:6 ino b285 page=0000000083ebc446 pfn=956463 ofs=4096
- <...>-1396 (-----) [000] .... 16137.453101: mm_filemap_add_to_page_cache: dev 253:6 ino b285 page=000000009dc2cd25 pfn=822813 ofs=8192
- <...>-1396 (-----) [000] .... 16137.453113: mm_filemap_add_to_page_cache: dev 253:6 ino b285 page=00000000a11167fb pfn=928650 ofs=12288
- <...>-1396 (-----) [000] .... 16137.453126: mm_filemap_add_to_page_cache: dev 253:6 ino b285 page=00000000c1c3311b pfn=621110 ofs=16384
- <...>-1396 (-----) [000] .... 16137.453139: mm_filemap_add_to_page_cache: dev 253:6 ino b285 page=000000009aa78342 pfn=689370 ofs=20480
- <...>-1396 (-----) [000] .... 16137.453151: mm_filemap_add_to_page_cache: dev 253:6 ino b285 page=0000000082cddcd6 pfn=755584 ofs=24576
- <...>-1396 (-----) [000] .... 16137.453162: mm_filemap_add_to_page_cache: dev 253:6 ino b285 page=00000000b0249bc7 pfn=691431 ofs=28672
- <...>-1396 (-----) [000] .... 16137.453183: mm_filemap_add_to_page_cache: dev 253:6 ino b285 page=000000006a776ff0 pfn=795084 ofs=32768
- <...>-1396 (-----) [000] .... 16137.453203: mm_filemap_add_to_page_cache: dev 253:6 ino b285 page=000000001a4918a7 pfn=806998 ofs=36864
- <...>-2578 (-----) [002] .... 16137.561871: mm_filemap_add_to_page_cache: dev 253:6 ino 1 page=00000000d65af9d2 pfn=719246 ofs=187015168
- <...>-2578 (-----) [002] .... 16137.562846: mm_filemap_add_to_page_cache: dev 253:6 ino b25a page=000000002f6ba74f pfn=864982 ofs=0
- <...>-2578 (-----) [000] .... 16138.104500: mm_filemap_add_to_page_cache: dev 253:6 ino 1 page=00000000f888d0f6 pfn=805812 ofs=192794624
- <...>-2578 (-----) [000] .... 16138.105836: mm_filemap_add_to_page_cache: dev 253:6 ino b7dd page=000000003749523b pfn=977196 ofs=0
- <...>-27215 (-----) [001] .... 16138.256881: mm_filemap_add_to_page_cache: dev 253:6 ino 758f page=000000001b375de1 pfn=755928 ofs=0
- <...>-27215 (-----) [001] .... 16138.257526: mm_filemap_add_to_page_cache: dev 253:6 ino 7591 page=000000004e039481 pfn=841534 ofs=0
- NonUserFacing6-5246 ( 1322) [005] .... 16138.356491: mm_filemap_add_to_page_cache: dev 253:6 ino 1 page=00000000d65af9d2 pfn=719246 ofs=161890304
- NonUserFacing6-5246 ( 1322) [005] .... 16138.357538: mm_filemap_add_to_page_cache: dev 253:6 ino 9a64 page=000000002f6ba74f pfn=864982 ofs=0
- NonUserFacing6-5246 ( 1322) [005] .... 16138.357581: mm_filemap_add_to_page_cache: dev 253:6 ino 9a64 page=000000006e0f8322 pfn=797894 ofs=4096
- <...>-27197 (-----) [005] .... 16140.143224: mm_filemap_add_to_page_cache: dev 253:6 ino 7580 page=00000000a42527c6 pfn=1076669 ofs=32768
- """
-
- t2d = parse_trace_file_to_db(test_contents)
- session = t2d.session
-
- first_row = session.query(MmFilemapAddToPageCache).order_by(MmFilemapAddToPageCache.id).first()
-
- #dev 253:6 ino 7580 page=0000000060e990c7 pfn=677646 ofs=159744
- assert_eq_ignore_id(MmFilemapAddToPageCache(dev=64774, dev_major=253, dev_minor=6,
- ino=0x7580, page=0x0000000060e990c7, pfn=677646, ofs=159744), first_row)
-
- second_to_last_row = session.query(MmFilemapAddToPageCache).filter(MmFilemapAddToPageCache.page.in_([0x000000006e0f8322])).first()
-
- # dev 253:6 ino 9a64 page=000000006e0f8322 pfn=797894 ofs=4096
- assert_eq_ignore_id(MmFilemapAddToPageCache(dev=64774, dev_major=253, dev_minor=6,
- ino=0x9a64, page=0x000000006e0f8322, pfn=797894, ofs=4096), second_to_last_row)
-
-def test_systrace_mm_filemap_add_to_pagecache():
- test_contents = """
-<!DOCTYPE html>
-<html>
-<head i18n-values="dir:textdirection;">
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<meta charset="utf-8"/>
-<title>Android System Trace</title>
- <script class="trace-data" type="application/text">
-PROCESS DUMP
-USER PID PPID VSZ RSS WCHAN PC S NAME COMM
-root 1 0 62148 5976 0 0 S init [init]
-root 2 0 0 0 0 0 S [kthreadd] [kthreadd]
- </script>
-
- <script class="trace-data" type="application/text">
-MediaStoreImpor-27212 (27176) [000] .... 16136.595194: mm_filemap_add_to_page_cache: dev 253:6 ino 7580 page=0000000060e990c7 pfn=677646 ofs=159744
-NonUserFacing6-5246 ( 1322) [005] .... 16138.357581: mm_filemap_add_to_page_cache: dev 253:6 ino 9a64 page=000000006e0f8322 pfn=797894 ofs=4096
- </script>
-
- <script class="trace-data" type="application/text">
-{"traceEvents": [{"category": "process_argv", "name": "process_argv", "args": {"argv": ["/mnt/ssd3/workspace/master/external/chromium-trace/systrace.py", "-t", "5", "pagecache"]}, "pid": 160383, "ts": 1037300940509.7991, "tid": 139628672526080, "ph": "M"}, {"category": "python", "name": "clock_sync", "args": {"issue_ts": 1037307346185.212, "sync_id": "9a7e4fe3-89ad-441f-8226-8fe533fe973e"}, "pid": 160383, "ts": 1037307351643.906, "tid": 139628726089536, "ph": "c"}], "metadata": {"clock-domain": "SYSTRACE"}}
- </script>
-<!-- END TRACE -->
- """
-
- t2d = parse_trace_file_to_db(test_contents)
- session = t2d.session
-
- first_row = session.query(MmFilemapAddToPageCache).order_by(MmFilemapAddToPageCache.id).first()
-
- #dev 253:6 ino 7580 page=0000000060e990c7 pfn=677646 ofs=159744
- assert_eq_ignore_id(MmFilemapAddToPageCache(dev=64774, dev_major=253, dev_minor=6,
- ino=0x7580, page=0x0000000060e990c7, pfn=677646, ofs=159744), first_row)
-
- second_to_last_row = session.query(MmFilemapAddToPageCache).filter(MmFilemapAddToPageCache.page.in_([0x000000006e0f8322])).first()
-
- # dev 253:6 ino 9a64 page=000000006e0f8322 pfn=797894 ofs=4096
- assert_eq_ignore_id(MmFilemapAddToPageCache(dev=64774, dev_major=253, dev_minor=6,
- ino=0x9a64, page=0x000000006e0f8322, pfn=797894, ofs=4096), second_to_last_row)
-
-def test_timestamp_filter():
- test_contents = """
- MediaStoreImpor-27212 (27176) [000] .... 16136.595194: mm_filemap_add_to_page_cache: dev 253:6 ino 7580 page=0000000060e990c7 pfn=677646 ofs=159744
- NonUserFacing6-5246 ( 1322) [005] .... 16139.357581: mm_filemap_add_to_page_cache: dev 253:6 ino 9a64 page=000000006e0f8322 pfn=797894 ofs=4096
- MediaStoreImpor-27212 (27176) [000] .... 16136.604126: mm_filemap_add_to_page_cache: dev 253:6 ino b1d8 page=0000000098d4d2e2 pfn=829676 ofs=0
- """
-
- t2d = parse_trace_file_to_db(test_contents)
- session = t2d.session
-
- end_time = 16137.0
-
- results = session.query(MmFilemapAddToPageCache).join(
- MmFilemapAddToPageCache.raw_ftrace_entry).filter(
- RawFtraceEntry.timestamp <= end_time).order_by(
- MmFilemapAddToPageCache.id).all()
-
- assert len(results) == 2
- assert_eq_ignore_id(
- MmFilemapAddToPageCache(dev=64774, dev_major=253, dev_minor=6,
- ino=0x7580, page=0x0000000060e990c7, pfn=677646,
- ofs=159744), results[0])
- assert_eq_ignore_id(
- MmFilemapAddToPageCache(dev=64774, dev_major=253, dev_minor=6,
- ino=0xb1d8, page=0x0000000098d4d2e2, pfn=829676,
- ofs=0), results[1])
-
-
-if __name__ == '__main__':
- pytest.main()
diff --git a/startop/scripts/trace_analyzer/queries_all.sql b/startop/scripts/trace_analyzer/queries_all.sql
deleted file mode 100644
index 41d1c0804a7f..000000000000
--- a/startop/scripts/trace_analyzer/queries_all.sql
+++ /dev/null
@@ -1,57 +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.
- */
-
--- filter for atrace writes
-CREATE VIEW IF NOT EXISTS tracing_mark_writes AS
- SELECT *
- FROM raw_ftrace_entries
- WHERE function = 'tracing_mark_write';
-
--- split the tracing_mark_write function args by ||s
-DROP TABLE IF exists tracing_mark_write_split_array;
-
-CREATE TABLE tracing_mark_write_split_array (
- predictorset_id INT REFERENCES raw_ftrace_entries (id),
- predictor_name,
- rest,
- gen,
-
- UNIQUE(predictorset_id, gen) -- drops redundant inserts into table
-);
-
-CREATE INDEX "tracing_mark_write_split_array_id" ON tracing_mark_write_split_array (
- predictorset_id COLLATE BINARY COLLATE BINARY
-);
-
-INSERT INTO tracing_mark_write_split_array
- WITH
- split(predictorset_id, predictor_name, rest, gen) AS (
- -- split by |
- SELECT id, '', function_args || '|', 0 FROM tracing_mark_writes WHERE id
- UNION ALL
- SELECT predictorset_id,
- substr(rest, 0, instr(rest, '|')),
- substr(rest, instr(rest, '|')+1),
- gen + 1
- FROM split
- WHERE rest <> ''),
- split_results AS (
- SELECT * FROM split WHERE predictor_name <> ''
- )
- SELECT * from split_results
-;
-
-
diff --git a/startop/scripts/trace_analyzer/queries_app_launch_spans_with_name.sql b/startop/scripts/trace_analyzer/queries_app_launch_spans_with_name.sql
deleted file mode 100644
index c28475eec73d..000000000000
--- a/startop/scripts/trace_analyzer/queries_app_launch_spans_with_name.sql
+++ /dev/null
@@ -1,44 +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.
- */
-
--- use the 'launching: $process_name' async slice to figure out launch duration.
-DROP VIEW IF EXISTS launch_durations_named;
-
-CREATE VIEW launch_durations_named AS
-WITH
- launch_traces_raw AS (
- SELECT *
- FROM tracing_mark_write_split AS tmw,
- raw_ftrace_entries AS rfe
- WHERE atrace_message LIKE 'launching: %' AND rfe.id = tmw.raw_ftrace_entry_id
- ),
- launch_traces_joined AS (
- SELECT started.timestamp AS started_timestamp,
- finished.timestamp AS finished_timestamp,
- started.id AS started_id,
- finished.id AS finished_id,
- SUBSTR(started.atrace_message, 12) AS proc_name -- crop out "launching: " from the string.
- FROM launch_traces_raw AS started,
- launch_traces_raw AS finished
- -- async slices ('S' -> 'F') have matching counters given the same PID.
- WHERE started.atrace_type == 'S'
- AND finished.atrace_type == 'F'
- AND started.atrace_count == finished.atrace_count
- AND started.atrace_pid == finished.atrace_pid
- )
-SELECT * from launch_traces_joined;
-
-SELECT * FROM launch_durations_named;
diff --git a/startop/scripts/trace_analyzer/queries_block_launch.sql b/startop/scripts/trace_analyzer/queries_block_launch.sql
deleted file mode 100644
index 34e5f03d0c48..000000000000
--- a/startop/scripts/trace_analyzer/queries_block_launch.sql
+++ /dev/null
@@ -1,52 +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.
- */
-
-DROP VIEW IF EXISTS blocked_iowait_for_app_launches;
-
-CREATE VIEW blocked_iowait_for_app_launches AS
-WITH
- block_launch_join AS (
- SELECT *
- FROM blocking_durations AS bd,
- launch_durations_named AS ld
- WHERE bd.block_timestamp >= ld.started_timestamp
- AND bd.unblock_timestamp <= ld.finished_timestamp
- ),
- blocked_ui_threads AS (
- SELECT *
- FROM start_process_ui_threads AS sp,
- block_launch_join AS blj
- WHERE sp.atm_ui_thread_tid == unblock_pid
- AND sp.process_name = blj.proc_name
- ),
- summed_raw AS (
- SELECT SUM(unblock_timestamp-block_timestamp)*1000 AS sum_block_duration_ms,
- *
- FROM blocked_ui_threads
- GROUP BY unblock_pid
- ),
- summed_neat AS (
- SELECT sum_block_duration_ms AS blocked_iowait_duration_ms,
- process_name,
- (finished_timestamp - started_timestamp) * 1000 AS launching_duration_ms,
- started_timestamp * 1000 AS launching_started_timestamp_ms,
- finished_timestamp * 1000 AS launching_finished_timestamp_ms
- -- filter out the rest because its just selecting 1 arbitrary row (due to the SUM aggregate).,
- FROM summed_raw
- )
-SELECT * FROM summed_neat;
-
-SELECT * FROM blocked_iowait_for_app_launches;
diff --git a/startop/scripts/trace_analyzer/queries_find_sched_switch_unblocked.sql b/startop/scripts/trace_analyzer/queries_find_sched_switch_unblocked.sql
deleted file mode 100644
index 788d0dae47d3..000000000000
--- a/startop/scripts/trace_analyzer/queries_find_sched_switch_unblocked.sql
+++ /dev/null
@@ -1,101 +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.
- */
-
-DROP VIEW IF EXISTS sched_switch_iowaits_pre;
-
--- scan for the closest pair such that:
--- sched_block_reason pid=$PID iowait=1 ...
--- ...
--- sched_switch next_pid=$PID
-CREATE VIEW sched_switch_iowaits_pre AS
- SELECT MAX(sbr.id) AS blocked_id,
- ss.id AS sched_switch_id,
- pid, -- iow.pid
- iowait, -- iowait=0 or iowait=1
- caller,
- sbr_f.timestamp AS blocked_timestamp,
- ss_f.timestamp AS sched_switch_timestamp,
- next_comm, -- name of next_pid
- next_pid -- same as iow.pid
- FROM sched_blocked_reasons AS sbr,
- raw_ftrace_entries AS sbr_f,
- sched_switches AS ss,
- raw_ftrace_entries AS ss_f
- WHERE sbr_f.id == sbr.id
- AND ss_f.id == ss.id
- AND sbr.pid == ss.next_pid
- AND sbr.iowait = 1
- AND sbr_f.timestamp < ss_f.timestamp -- ensures the 'closest' sched_blocked_reason is selected.
- GROUP BY ss.id
-;
-
-DROP VIEW IF EXISTS sched_switch_iowaits;
-
-CREATE VIEW sched_switch_iowaits AS
- SELECT *, MIN(sched_switch_timestamp) AS ss_timestamp -- drop all of the 'too large' sched_switch entries except the closest one.
- FROM sched_switch_iowaits_pre
- GROUP BY blocked_id;
-
-SELECT * FROM sched_switch_iowaits;
-
--- use a real table here instead of a view, otherwise SQLiteStudio segfaults for some reason.
-DROP TABLE IF EXISTS blocking_durations;
-
-CREATE TABLE blocking_durations AS
-WITH
- blocking_durations_raw AS (
- SELECT MAX(ss.id) AS block_id,
- ssf.timestamp AS block_timestamp,
- iow.sched_switch_timestamp AS unblock_timestamp,
- ss.prev_comm as block_prev_comm,
- iow.next_comm AS unblock_next_comm,
- ss.prev_state AS block_prev_state,
- iow.sched_switch_id AS unblock_id,
- iow.pid AS unblock_pid,
- iow.caller AS unblock_caller
- FROM sched_switches AS ss, -- this is the sched_switch that caused a block (in the future when it unblocks, the reason is iowait=1).
- sched_switch_iowaits AS iow, -- this is the sched_switch that removes the block (it is now running again).
- raw_ftrace_entries AS ssf
- WHERE ssf.id = ss.id AND ss.prev_pid == iow.next_pid AND ssf.timestamp < iow.sched_switch_timestamp
- GROUP BY unblock_timestamp
- ),
- blocking_durations_tmp AS (
- SELECT block_id,
- unblock_timestamp,
- block_timestamp,
- block_prev_comm as comm,
- block_prev_state as block_state,
- unblock_id,
- unblock_pid,
- unblock_caller
- FROM blocking_durations_raw
- )
- SELECT * FROM blocking_durations_tmp;-- ORDER BY block_id ASC;
- --SELECT SUM(block_duration_ms) AS sum, * FROM blocking_durations GROUP BY unblock_pid ORDER BY sum DESC;
-
-DROP INDEX IF EXISTS "blocking_durations_block_timestamp";
-
-CREATE INDEX "blocking_durations_block_timestamp" ON blocking_durations (
- block_timestamp COLLATE BINARY COLLATE BINARY
-);
-
-DROP INDEX IF EXISTS "blocking_durations_unblock_timestamp";
-
-CREATE INDEX "blocking_durations_unblock_timestamp" ON blocking_durations (
- unblock_timestamp COLLATE BINARY COLLATE BINARY
-);
-
-SELECT * FROM blocking_durations;
diff --git a/startop/scripts/trace_analyzer/queries_get_comm_and_pids.sql b/startop/scripts/trace_analyzer/queries_get_comm_and_pids.sql
deleted file mode 100644
index 0c166b09784c..000000000000
--- a/startop/scripts/trace_analyzer/queries_get_comm_and_pids.sql
+++ /dev/null
@@ -1,42 +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.
- */
-
-DROP VIEW IF EXISTS sched_switch_next_comm_pids;
-
-CREATE VIEW IF NOT EXISTS sched_switch_next_comm_pids AS
-
--- TODO: switch to using sched_switches table.
-
-WITH
- sched_switchs AS (
- SELECT * FROM raw_ftrace_entries WHERE function = 'sched_switch' AND function_args LIKE '% next_pid=%' AND function_args NOT LIKE '% next_comm=main %'
- ),
- comm_and_pids_raws AS (
- SELECT id,
- SUBSTR(function_args, instr(function_args, "next_comm="), instr(function_args, "next_pid=") - instr(function_args, "next_comm=")) AS next_comm_raw,
- SUBSTR(function_args, instr(function_args, "next_pid="), instr(function_args, "next_prio=") - instr(function_args, "next_pid=")) AS next_pid_raw
- FROM sched_switchs
- ),
- comm_and_pids AS (
- SELECT id,
- id AS raw_ftrace_entry_id,
- TRIM(SUBSTR(next_pid_raw, 10)) AS next_pid, -- len("next_pid=") is 10
- TRIM(SUBSTR(next_comm_raw, 11)) AS next_comm -- len("next_comm=") is 11
- FROM comm_and_pids_raws
- )
-SELECT * from comm_and_pids;
-
-SELECT * from sched_switch_next_comm_pids;
diff --git a/startop/scripts/trace_analyzer/queries_get_procs.sql b/startop/scripts/trace_analyzer/queries_get_procs.sql
deleted file mode 100644
index 06871c6e16b6..000000000000
--- a/startop/scripts/trace_analyzer/queries_get_procs.sql
+++ /dev/null
@@ -1,30 +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.
- */
-
-DROP VIEW IF EXISTS start_procs;
-
-CREATE VIEW IF NOT EXISTS start_procs AS
-WITH
- start_procs_raw AS (
- SELECT * from tracing_mark_write_split WHERE atrace_message LIKE 'Start proc: %'
- ),
- start_procs_substr AS (
- -- note: "12" is len("Start proc: ")+1. sqlite indices start at 1.
- SELECT raw_ftrace_entry_id, atrace_pid, SUBSTR(atrace_message, 13) AS process_name FROM start_procs_raw
- )
-SELECT * from start_procs_substr;
-
-SELECT * from start_procs;
diff --git a/startop/scripts/trace_analyzer/queries_get_ui_threads.sql b/startop/scripts/trace_analyzer/queries_get_ui_threads.sql
deleted file mode 100644
index 876e50e9880a..000000000000
--- a/startop/scripts/trace_analyzer/queries_get_ui_threads.sql
+++ /dev/null
@@ -1,88 +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.
- */
-
--- note: These queries do comparisons based on raw_ftrace_entries.id by treating it as if it was equivalent to the temporal timestamp.
--- in practice, the ID of raw_ftrace_entries is based on its order in the ftrace buffer [and on the same cpu its equivalent].
--- we can always resort raw_ftrace_entries to ensure id order matches timestamp order. We should rarely need to compare by timestamp directly.
--- accessing 'floats' is inferior as they are harder to index, and will result in slower queries.
---
--- Naming convention note: '_fid' corresponds to 'raw_ftrace_entry.id'.
-DROP VIEW IF EXISTS start_process_ui_threads;
-
--- Map of started process names to their UI thread's TID (as returned by gettid).
-CREATE VIEW IF NOT EXISTS start_process_ui_threads AS
-WITH
- start_proc_tids AS (
- SELECT sp.raw_ftrace_entry_id AS start_proc_fid,
- sp.atrace_pid AS atrace_pid,
- sp.process_name AS process_name,
- --MIN(nc.raw_ftrace_entry_id) as next_comm_fid,
- nc.raw_ftrace_entry_id AS next_comm_fid,
- nc.next_pid as next_pid,
- nc.next_comm as next_comm,
- SUBSTR(sp.process_name, -15) AS cut -- why -15? See TASK_MAX in kernel, the sched_switch name is truncated to 16 bytes.
- FROM start_procs AS sp,
- sched_switch_next_comm_pids AS nc
- WHERE sp.process_name LIKE '%' || nc.next_comm -- kernel truncates the sched_switch::next_comm event, so we must match the prefix of the full name.
- --WHERE SUBSTR(sp.process_name, -16) == nc.next_comm
- --WHERE cut == nc.next_comm
- ),
- start_proc_tids_filtered AS (
- SELECT *
- FROM start_proc_tids
- WHERE next_comm_fid > start_proc_fid -- safeguard that avoids choosing "earlier" sched_switch before process was even started.
- --ORDER BY start_proc_fid, next_comm_fid
- ),
- start_proc_all_threads AS (
- SELECT DISTINCT
- start_proc_fid, -- this is the ftrace entry of the system server 'Start proc: $process_name'. only need this to join for timestamp.
- process_name, -- this is the '$process_name' from the system server entry.
- -- next up we have all the possible thread IDs as parsed from sched_switch that corresponds most closest to the start proc.
- next_pid AS ui_thread_tpid, -- sched_switch.next_pid. This can be any of the threads in that process, it's not necessarily the main UI thread yet.
- next_comm,
- MIN(next_comm_fid) AS next_comm_fid -- don't pick the 'later' next_comm_fid because it could correspond to another app start.
- FROM start_proc_tids_filtered
- GROUP BY start_proc_fid, ui_thread_tpid
- ),
- activity_thread_mains AS (
- SELECT * FROM tracing_mark_write_split WHERE atrace_message = 'ActivityThreadMain'
- ),
- start_proc_ui_threads AS (
- SELECT start_proc_fid,
- process_name,
- ui_thread_tpid,
- next_comm,
- next_comm_fid,
- atm.raw_ftrace_entry_id as atm_fid,
- atm.atrace_pid as atm_ui_thread_tid
- FROM start_proc_all_threads AS spt,
- activity_thread_mains AS atm
- WHERE atm.atrace_pid == spt.ui_thread_tpid AND atm.raw_ftrace_entry_id > spt.start_proc_fid -- Ensure we ignore earlier ActivityThreadMains prior to their Start proc.
- ),
- start_proc_ui_threads_filtered AS (
- SELECT start_proc_fid,
- process_name, -- e.g. 'com.android.settings'
- --ui_thread_tpid,
- --next_comm,
- --next_comm_fid,
- MIN(atm_fid) AS atm_fid,
- atm_ui_thread_tid -- equivalent to gettid() for the process's UI thread.
- FROM start_proc_ui_threads
- GROUP BY start_proc_fid, atm_ui_thread_tid -- find the temporally closest ActivityTaskMain to a "Start proc: $process_name"
- )
-SELECT * FROM start_proc_ui_threads_filtered;
-
-SELECT * FROM start_process_ui_threads;
diff --git a/startop/scripts/trace_analyzer/queries_mark_write_join.sql b/startop/scripts/trace_analyzer/queries_mark_write_join.sql
deleted file mode 100644
index 100f07403423..000000000000
--- a/startop/scripts/trace_analyzer/queries_mark_write_join.sql
+++ /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.
- */
-
-DROP TABLE IF EXISTS tracing_mark_write_split;
-
-CREATE TABLE tracing_mark_write_split (
- raw_ftrace_entry_id INT REFERENCES raw_ftrace_entries (id),
- atrace_type CHAR(1), -- only null for the first 2 sync timers. usually 'B', 'C', E', ...
- atrace_pid INT, -- only null for first 2 sync timers
- atrace_message, -- usually null for type='E' etc.
- atrace_count, -- usually non-null only for 'C'
-
- UNIQUE(raw_ftrace_entry_id) -- drops redundant inserts into table
-);
-
-INSERT INTO tracing_mark_write_split
-WITH
- pivoted AS (
- SELECT tx.predictorset_id,
- --ty.predictorset_id,
- --tz.predictorset_id,
- --tzz.predictorset_id,
- tx.predictor_name AS atrace_type,
- CAST(ty.predictor_name AS integer) AS atrace_pid,
- tz.predictor_name AS atrace_message,
- CAST(tzz.predictor_name AS integer) AS atrace_count
- FROM (SELECT * from tracing_mark_write_split_array WHERE gen = 1) AS tx
- LEFT JOIN
- (SELECT * FROM tracing_mark_write_split_array WHERE gen = 2) AS ty
- ON tx.predictorset_id = ty.predictorset_id
- LEFT JOIN
- (SELECT * FROM tracing_mark_write_split_array WHERE gen = 3) AS tz
- ON tx.predictorset_id = tz.predictorset_id
- LEFT JOIN
- (SELECT * FROM tracing_mark_write_split_array WHERE gen = 4) AS tzz
- ON tx.predictorset_id = tzz.predictorset_id
- )
-SELECT * from pivoted ORDER BY predictorset_id;-- LIMIT 100;
-
-SELECT * FROM tracing_mark_write_split;
diff --git a/startop/scripts/trace_analyzer/run-sql-queries b/startop/scripts/trace_analyzer/run-sql-queries
deleted file mode 100755
index 61a0ad42a339..000000000000
--- a/startop/scripts/trace_analyzer/run-sql-queries
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/bin/bash
-# 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.
-
-DIR="$( cd "$(dirname "$0")" ; pwd -P )"
-
-if [[ $# -lt 1 ]]; then
- echo "Usage: $0 <db-file>"
-fi
-
-DB_TARGET=$1
-
-if ! [[ -f $DB_TARGET ]]; then
- echo "ERROR: File '$DB_TARGET' does not exist." >&2
- exit 1
-fi
-
-exec_sql_file() {
- local filename="$1"
- if ! [[ -f $filename ]]; then
- echo "ERROR: Can't exec SQL file, '$filename' does not exist." >&2
- return 1
- fi
-
- sqlite3 "$DB_TARGET" < "$DIR"/"$filename"
-}
-
-exec_sql_file_quiet() {
- exec_sql_file "$@" > /dev/null
-}
-
-# Some views/tables need other views already created, so order does matter.
-# x -> y , means x depends on y.
-
-# View: tracing_mark_writes
-# Table: tracing_mark_write_split_array -> tracing_mark_writes
-exec_sql_file_quiet "queries_all.sql"
-
-# Table: tracing_mark_write_split -> tracing_mark_write_split_array
-exec_sql_file_quiet "queries_mark_write_join.sql"
-
-# View: start_procs -> tracing_mark_write_split
-exec_sql_file_quiet "queries_get_procs.sql"
-
-# View: sched_switch_next_comm_pids
-exec_sql_file_quiet "queries_get_comm_and_pids.sql"
-
-# View: start_process_ui_threads -> start_procs, sched_switch_next_comm_pids
-exec_sql_file_quiet "queries_get_ui_threads.sql"
-
-# View: launch_durations_named -> tracing_mark_write_split
-exec_sql_file_quiet "queries_app_launch_spans_with_name.sql"
-
-# View: sched_switch_iowaits_pre
-# View: sched_switch_iowaits -> sched_switch_iowaits_pre
-# Table: blocking_durations -> sched_switch_iowaits
-exec_sql_file_quiet "queries_find_sched_switch_unblocked.sql"
-
-# View: blocked_iowait_for_app_launches -> launch_durations_named, blocking_durations
-exec_sql_file_quiet "queries_block_launch.sql"
-
-#####
-#####
-#####
-
-# Final queries
-
-exec_sql_file "queries_pretty_print_block_launch.sql"
diff --git a/startop/scripts/trace_analyzer/test_fixtures/common_systrace b/startop/scripts/trace_analyzer/test_fixtures/common_systrace
deleted file mode 100644
index 802cb5562593..000000000000
--- a/startop/scripts/trace_analyzer/test_fixtures/common_systrace
+++ /dev/null
@@ -1,518 +0,0 @@
-# tracer: nop
-#
-# entries-in-buffer/entries-written: 411983/411983 #P:8
-#
-# _-----=> irqs-off
-# / _----=> need-resched
-# | / _---=> hardirq/softirq
-# || / _--=> preempt-depth
-# ||| / delay
-# TASK-PID TGID CPU# |||| TIMESTAMP FUNCTION
-# | | | | |||| | |
- <...>-14603 (-----) [000] ...1 14592.893157: tracing_mark_write: trace_event_clock_sync: parent_ts=14592.892578
- <...>-14603 (-----) [000] ...1 14592.893172: tracing_mark_write: trace_event_clock_sync: realtime_ts=1557129597951
- <...>-18150 (-----) [004] d..2 14594.182110: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=D ==> next_comm=kworker/u16:16 next_pid=23269 next_prio=120
- kworker/u16:16-23269 (23269) [004] d.h3 14594.182228: sched_blocked_reason: pid=18150 iowait=0 caller=a6xx_oob_set+0x194/0x3dc
- kworker/u16:16-23269 (23269) [004] d..2 14594.182248: sched_switch: prev_comm=kworker/u16:16 prev_pid=23269 prev_prio=120 prev_state=D ==> next_comm=kworker/u16:18 next_pid=18150 next_prio=120
- <...>-18150 (-----) [004] d..2 14594.182312: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=D ==> next_comm=swapper/4 next_pid=0 next_prio=120
- <...>-18150 (-----) [004] d..2 14594.182488: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=D ==> next_comm=swapper/4 next_pid=0 next_prio=120
- kworker/u16:16-23269 (23269) [005] d..2 14594.182610: sched_switch: prev_comm=kworker/u16:16 prev_pid=23269 prev_prio=120 prev_state=S ==> next_comm=swapper/5 next_pid=0 next_prio=120
- <...>-18150 (-----) [004] d..2 14594.182626: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=D ==> next_comm=swapper/4 next_pid=0 next_prio=120
- <...>-18150 (-----) [004] d..2 14594.182755: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=D ==> next_comm=swapper/4 next_pid=0 next_prio=120
- <...>-18150 (-----) [004] d..2 14594.182975: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=D ==> next_comm=swapper/4 next_pid=0 next_prio=120
- <...>-18150 (-----) [004] d..2 14594.183209: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=D ==> next_comm=swapper/4 next_pid=0 next_prio=120
- <...>-18150 (-----) [004] d..2 14594.183371: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=D ==> next_comm=swapper/4 next_pid=0 next_prio=120
- <...>-18150 (-----) [004] d..2 14594.184286: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=S ==> next_comm=swapper/4 next_pid=0 next_prio=120
- kworker/u16:16-23269 (23269) [005] d..2 14594.184495: sched_switch: prev_comm=kworker/u16:16 prev_pid=23269 prev_prio=120 prev_state=S ==> next_comm=swapper/5 next_pid=0 next_prio=120
- <...>-18150 (-----) [004] d..2 14594.184498: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=S ==> next_comm=swapper/4 next_pid=0 next_prio=120
- ksoftirqd/4-47 ( 47) [004] d..2 14594.185678: sched_switch: prev_comm=ksoftirqd/4 prev_pid=47 prev_prio=120 prev_state=S ==> next_comm=swapper/4 next_pid=0 next_prio=120
- kworker/6:2-10610 (10610) [006] d..2 14594.186012: sched_switch: prev_comm=kworker/6:2 prev_pid=10610 prev_prio=120 prev_state=S ==> next_comm=swapper/6 next_pid=0 next_prio=120
- <...>-656 (-----) [001] .... 14594.219464: binder_set_priority: proc=625 thread=656 old=110 => new=120 desired=120
- <...>-1803 (-----) [000] d..2 14594.219595: sched_switch: prev_comm=ndroid.systemui prev_pid=1803 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <...>-3359 (-----) [001] ...1 14594.219856: tracing_mark_write: S|1368|launching: com.google.android.dialer|0
- <...>-3359 (-----) [001] ...1 14594.219863: tracing_mark_write: B|1368|MetricsLogger:launchObserverNotifyActivityLaunched
- <...>-3359 (-----) [001] ...1 14594.219869: tracing_mark_write: B|1368|MetricsLogger:convertActivityRecordToProto
- <...>-1398 (-----) [006] ...1 14594.220160: tracing_mark_write: B|1368|updateInputWindows
- <...>-3359 (-----) [001] .... 14594.220230: binder_set_priority: proc=1368 thread=3359 old=110 => new=120 desired=120
- <...>-1398 (-----) [006] ...1 14594.220588: tracing_mark_write: B|1368|android.os.Handler: com.android.server.wm.AppWindowToken$1
- <...>-1398 (-----) [006] ...1 14594.220722: tracing_mark_write: B|1368|ResourcesManager#getResources
- <...>-1052 (-----) [002] d..2 14594.220884: sched_switch: prev_comm=statsd.writer prev_pid=1052 prev_prio=120 prev_state=S ==> next_comm=UiThreadHelper next_pid=2045 next_prio=118
- <...>-1398 (-----) [006] ...1 14594.220926: tracing_mark_write: B|1368|Theme::ApplyStyle
- <...>-1398 (-----) [006] ...1 14594.220929: tracing_mark_write: B|1368|AssetManager::GetBag
- <...>-2007 (-----) [007] ...1 14594.220996: tracing_mark_write: B|2007|Choreographer#doFrame
- <...>-2007 (-----) [007] ...1 14594.221005: tracing_mark_write: B|2007|animation
- <...>-1398 (-----) [006] ...1 14594.221015: tracing_mark_write: B|1368|ResourcesManager#getResources
- <...>-2045 (-----) [002] ...2 14594.221035: binder_set_priority: proc=1368 thread=1903 old=120 => new=118 desired=118
- <...>-2045 (-----) [002] d..2 14594.221065: sched_switch: prev_comm=UiThreadHelper prev_pid=2045 prev_prio=118 prev_state=S ==> next_comm=Binder:1368_4 next_pid=1903 next_prio=118
- <...>-1398 (-----) [006] ...1 14594.221080: tracing_mark_write: B|1368|AssetManager::SetApkAssets
- <...>-2007 (-----) [007] ...1 14594.221110: tracing_mark_write: B|2007|traversal
- <...>-656 (-----) [000] ...1 14594.221137: tracing_mark_write: B|625|requestNextVsync
- <...>-656 (-----) [000] ...1 14594.221141: tracing_mark_write: B|625|resetIdleTimer
- <...>-2007 (-----) [007] ...1 14594.221146: tracing_mark_write: B|2007|draw
- <...>-2007 (-----) [007] ...1 14594.221160: tracing_mark_write: B|2007|Record View#draw()
- <...>-660 (-----) [005] d..2 14594.221285: sched_switch: prev_comm=app prev_pid=660 prev_prio=97 prev_state=S ==> next_comm=RenderThread next_pid=2738 next_prio=110
- <...>-658 (-----) [004] d..2 14594.221327: sched_switch: prev_comm=DispSync prev_pid=658 prev_prio=97 prev_state=S ==> next_comm=android.display next_pid=1397 next_prio=117
- <...>-2738 (-----) [005] ...1 14594.221342: tracing_mark_write: B|2007|notifyFramePending
- <...>-2738 (-----) [005] ...1 14594.221362: tracing_mark_write: B|2007|DrawFrame
- <...>-2738 (-----) [005] ...1 14594.221369: tracing_mark_write: B|2007|query
- <...>-2007 (-----) [007] d..2 14594.221369: sched_switch: prev_comm=s.nexuslauncher prev_pid=2007 prev_prio=110 prev_state=S ==> next_comm=swapper/7 next_pid=0 next_prio=120
- <...>-1903 (-----) [002] .... 14594.221397: binder_set_priority: proc=1368 thread=1903 old=118 => new=120 desired=120
- <...>-2738 (-----) [005] ...2 14594.221400: binder_set_priority: proc=625 thread=656 old=120 => new=110 desired=110
- <...>-2738 (-----) [005] d..2 14594.221430: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=S ==> next_comm=Binder:625_1 next_pid=656 next_prio=110
- <...>-1368 (-----) [003] ...1 14594.221431: tracing_mark_write: B|1368|Lock contention on GC thread flip lock (owner tid: 0)
- <...>-656 (-----) [005] ...1 14594.221460: tracing_mark_write: B|625|query
- <...>-656 (-----) [005] .... 14594.221528: binder_set_priority: proc=625 thread=656 old=110 => new=120 desired=120
- <...>-2738 (-----) [007] ...1 14594.221552: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [007] ...2 14594.221563: binder_set_priority: proc=625 thread=656 old=120 => new=110 desired=110
- <...>-2738 (-----) [007] d..2 14594.221600: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=S ==> next_comm=Binder:625_1 next_pid=656 next_prio=110
- <...>-1368 (-----) [003] d..2 14594.221623: sched_switch: prev_comm=system_server prev_pid=1368 prev_prio=118 prev_state=S ==> next_comm=swapper/3 next_pid=0 next_prio=120
- <...>-656 (-----) [007] ...1 14594.221628: tracing_mark_write: B|625|query
- <...>-23031 (-----) [001] d..2 14594.221643: sched_switch: prev_comm=UiAutomation prev_pid=23031 prev_prio=120 prev_state=S ==> next_comm=swapper/1 next_pid=0 next_prio=120
- <...>-2738 (-----) [007] ...1 14594.221664: tracing_mark_write: B|2007|syncFrameState
- <...>-2738 (-----) [007] ...1 14594.221697: tracing_mark_write: B|2007|prepareTree
- <...>-23008 (-----) [005] d..2 14594.221706: sched_switch: prev_comm=hub.uiautomator prev_pid=23008 prev_prio=120 prev_state=S ==> next_comm=swapper/5 next_pid=0 next_prio=120
- <...>-656 (-----) [000] .... 14594.221737: binder_set_priority: proc=625 thread=656 old=110 => new=120 desired=120
- <...>-1803 (-----) [003] d..2 14594.221747: sched_switch: prev_comm=ndroid.systemui prev_pid=1803 prev_prio=120 prev_state=S ==> next_comm=swapper/3 next_pid=0 next_prio=120
- <...>-1397 (-----) [004] d..2 14594.221806: sched_switch: prev_comm=android.display prev_pid=1397 prev_prio=117 prev_state=S ==> next_comm=Binder:2007_A next_pid=4180 next_prio=120
- <...>-1398 (-----) [006] d..2 14594.221816: sched_switch: prev_comm=android.anim prev_pid=1398 prev_prio=110 prev_state=R ==> next_comm=s.nexuslauncher next_pid=2007 next_prio=110
- <...>-2738 (-----) [007] ...1 14594.221824: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [007] ...1 14594.221830: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [007] ...1 14594.221834: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [007] ...1 14594.221841: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [007] ...1 14594.221843: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [007] ...1 14594.221846: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [007] ...1 14594.221850: tracing_mark_write: B|2007|dequeueBuffer
- <...>-2738 (-----) [007] ...2 14594.221864: binder_set_priority: proc=625 thread=656 old=120 => new=110 desired=110
- <...>-2738 (-----) [007] d..2 14594.221985: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=R+ ==> next_comm=crtc_event:97 next_pid=303 next_prio=83
- <...>-2007 (-----) [006] ...1 14594.221989: tracing_mark_write: B|2007|topResumedActivityChangeItem
- <...>-303 (-----) [007] d..2 14594.222016: sched_switch: prev_comm=crtc_event:97 prev_pid=303 prev_prio=83 prev_state=S ==> next_comm=rcu_preempt next_pid=7 next_prio=120
- rcu_preempt-7 ( 7) [007] d..2 14594.222035: sched_switch: prev_comm=rcu_preempt prev_pid=7 prev_prio=120 prev_state=S ==> next_comm=RenderThread next_pid=2738 next_prio=110
- migration/4-46 ( 46) [004] d..2 14594.222037: sched_switch: prev_comm=migration/4 prev_pid=46 prev_prio=0 prev_state=S ==> next_comm=Binder:625_1 next_pid=656 next_prio=110
- <...>-2738 (-----) [007] d..2 14594.222039: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=S ==> next_comm=kworker/u16:18 next_pid=18150 next_prio=120
- <...>-656 (-----) [004] ...1 14594.222100: tracing_mark_write: B|625|dequeueBuffer
- <...>-656 (-----) [004] ...1 14594.222114: tracing_mark_write: B|625|com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#1: 2
- <...>-2007 (-----) [006] ...2 14594.222131: binder_set_priority: proc=1368 thread=1903 old=120 => new=110 desired=110
- <...>-2007 (-----) [006] d..2 14594.222143: sched_switch: prev_comm=s.nexuslauncher prev_pid=2007 prev_prio=110 prev_state=S ==> next_comm=UiThreadHelper next_pid=2045 next_prio=118
- <...>-2613 (-----) [001] d..2 14594.222158: sched_switch: prev_comm=ogle.android.as prev_pid=2613 prev_prio=120 prev_state=S ==> next_comm=swapper/1 next_pid=0 next_prio=120
- <...>-18150 (-----) [007] d..2 14594.222193: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=S ==> next_comm=swapper/7 next_pid=0 next_prio=120
- <...>-656 (-----) [004] .... 14594.222220: binder_set_priority: proc=625 thread=656 old=110 => new=120 desired=120
- <...>-2738 (-----) [007] ...1 14594.222267: tracing_mark_write: B|2007|HWC release fence 36027 has signaled
- <...>-656 (-----) [007] ...1 14594.223842: tracing_mark_write: B|625|queueBuffer
- <...>-656 (-----) [007] ...1 14594.223845: tracing_mark_write: B|625|com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#1: 2
- <...>-656 (-----) [007] ...1 14594.223871: tracing_mark_write: B|625|requestNextVsync
- <...>-656 (-----) [007] ...1 14594.223873: tracing_mark_write: B|625|resetIdleTimer
- <...>-656 (-----) [007] ...1 14594.223881: tracing_mark_write: B|625|addAndGetFrameTimestamps
- <...>-1395 (-----) [001] d..2 14594.223909: sched_switch: prev_comm=android.ui prev_pid=1395 prev_prio=118 prev_state=S ==> next_comm=swapper/1 next_pid=0 next_prio=120
- <...>-2738 (-----) [007] ...1 14594.223959: tracing_mark_write: B|2007|Trace GPU completion fence 36027
- <...>-11799 (-----) [006] ...1 14594.224006: tracing_mark_write: B|2007|waiting for GPU completion 36027
- <...>-11799 (-----) [006] ...1 14594.224009: tracing_mark_write: B|2007|waitForever
- <...>-2613 (-----) [004] d..2 14594.224014: sched_switch: prev_comm=ogle.android.as prev_pid=2613 prev_prio=120 prev_state=S ==> next_comm=Binder:1803_6 next_pid=2173 next_prio=120
- <...>-11799 (-----) [006] d..1 14594.224014: fence_enable_signal: driver=kgsl-timeline timeline=kgsl-3d0_13-s.nexuslauncher(200 context=27 seqno=78002
- <...>-11799 (-----) [006] d..2 14594.224021: sched_switch: prev_comm=GPU completion prev_pid=11799 prev_prio=110 prev_state=S ==> next_comm=rcuop/6 next_pid=68 next_prio=120
- rcuop/6-68 ( 68) [006] d..2 14594.224044: sched_switch: prev_comm=rcuop/6 prev_pid=68 prev_prio=120 prev_state=S ==> next_comm=swapper/6 next_pid=0 next_prio=120
- <...>-259 (-----) [006] d..2 14594.224132: sched_switch: prev_comm=kgsl_worker_thr prev_pid=259 prev_prio=97 prev_state=S ==> next_comm=Binder:2007_A next_pid=4180 next_prio=120
- <...>-3206 (-----) [001] d..2 14594.224167: sched_switch: prev_comm=aiai-vc-0 prev_pid=3206 prev_prio=139 prev_state=R ==> next_comm=ndroid.systemui next_pid=1803 next_prio=120
- lowpool[847]-14589 ( 2446) [005] d..1 14594.224300: mm_filemap_delete_from_page_cache: dev 0:1 ino 3d0034 page=000000008247d586 pfn=676904 ofs=0
- <...>-1803 (-----) [001] d..2 14594.224302: sched_switch: prev_comm=ndroid.systemui prev_pid=1803 prev_prio=120 prev_state=S ==> next_comm=aiai-vc-0 next_pid=3206 next_prio=139
- <...>-3206 (-----) [001] d..2 14594.224433: sched_switch: prev_comm=aiai-vc-0 prev_pid=3206 prev_prio=139 prev_state=S ==> next_comm=swapper/1 next_pid=0 next_prio=120
- <...>-1903 (-----) [003] ...1 14594.224490: tracing_mark_write: B|1368|dispatchingStartProcess:com.google.android.dialer
- <...>-1903 (-----) [003] ...1 14594.224659: tracing_mark_write: B|1368|wmLayout
- <...>-1903 (-----) [003] ...1 14594.224666: tracing_mark_write: B|1368|performSurfacePlacement
- <...>-1903 (-----) [003] ...1 14594.224683: tracing_mark_write: B|1368|applySurfaceChanges
- <...>-1903 (-----) [003] ...1 14594.224688: tracing_mark_write: B|1368|openSurfaceTransaction
- <...>-2738 (-----) [007] ...1 14594.224711: tracing_mark_write: B|2007|query
- <...>-1903 (-----) [003] ...1 14594.224714: tracing_mark_write: B|1368|performLayout
- <...>-2738 (-----) [007] ...1 14594.224714: tracing_mark_write: B|2007|query
- <...>-1903 (-----) [003] ...1 14594.224723: tracing_mark_write: B|1368|applyPostLayoutPolicy
- <...>-2738 (-----) [007] d..2 14594.224752: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=S ==> next_comm=Binder:625_1 next_pid=656 next_prio=110
- <...>-656 (-----) [007] .... 14594.224766: binder_set_priority: proc=625 thread=656 old=110 => new=120 desired=120
- <...>-1398 (-----) [002] ...1 14594.224801: tracing_mark_write: B|1368|Theme::ApplyStyle
- <...>-1398 (-----) [002] ...1 14594.224805: tracing_mark_write: B|1368|AssetManager::GetBag
- <...>-1398 (-----) [002] ...1 14594.224820: tracing_mark_write: B|1368|AssetManager::GetBag
- <...>-1398 (-----) [002] ...1 14594.224826: tracing_mark_write: B|1368|AssetManager::GetBag
- <...>-1398 (-----) [002] ...1 14594.224833: tracing_mark_write: B|1368|AssetManager::GetBag
- <...>-1398 (-----) [002] ...1 14594.224838: tracing_mark_write: B|1368|AssetManager::GetBag
- <...>-1398 (-----) [002] ...1 14594.224846: tracing_mark_write: B|1368|AssetManager::GetBag
- <...>-1398 (-----) [002] ...1 14594.224853: tracing_mark_write: B|1368|AssetManager::GetBag
- <...>-1398 (-----) [002] ...1 14594.224859: tracing_mark_write: B|1368|AssetManager::GetBag
- <...>-1398 (-----) [002] ...1 14594.224864: tracing_mark_write: B|1368|AssetManager::GetBag
- <...>-18150 (-----) [006] d..2 14594.228407: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=R+ ==> next_comm=mmc-cmdqd/0 next_pid=440 next_prio=98
- <...>-2738 (-----) [007] d..2 14594.228411: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=R+ ==> next_comm=kworker/7:0H next_pid=76 next_prio=100
- <...>-1409 (-----) [004] ...1 14594.228417: tracing_mark_write: B|1368|Start proc: com.google.android.dialer
- <...>-440 (-----) [006] d..2 14594.228418: sched_switch: prev_comm=mmc-cmdqd/0 prev_pid=440 prev_prio=98 prev_state=D ==> next_comm=kworker/u16:18 next_pid=18150 next_prio=120
- <...>-76 (-----) [007] d..2 14594.228430: sched_switch: prev_comm=kworker/7:0H prev_pid=76 prev_prio=100 prev_state=R+ ==> next_comm=mmc-cmdqd/0 next_pid=440 next_prio=98
- <...>-440 (-----) [007] d..2 14594.228434: sched_switch: prev_comm=mmc-cmdqd/0 prev_pid=440 prev_prio=98 prev_state=D ==> next_comm=kworker/7:0H next_pid=76 next_prio=100
- <...>-18150 (-----) [006] d..3 14594.228442: sched_blocked_reason: pid=1398 iowait=1 caller=wait_on_page_bit_common+0x2a8/0x5f8
- <...>-76 (-----) [007] d..2 14594.228442: sched_switch: prev_comm=kworker/7:0H prev_pid=76 prev_prio=100 prev_state=S ==> next_comm=RenderThread next_pid=2738 next_prio=110
- <...>-2738 (-----) [007] ...2 14594.228446: binder_set_priority: proc=625 thread=656 old=120 => new=110 desired=110
- <...>-18150 (-----) [006] d..2 14594.228447: sched_switch: prev_comm=kworker/u16:18 prev_pid=18150 prev_prio=120 prev_state=R+ ==> next_comm=android.anim next_pid=1398 next_prio=110
- <...>-2738 (-----) [007] d..2 14594.228479: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=S ==> next_comm=Binder:625_1 next_pid=656 next_prio=110
- <...>-1409 (-----) [004] d..2 14594.228499: sched_switch: prev_comm=ActivityManager prev_pid=1409 prev_prio=118 prev_state=D ==> next_comm=Binder:965_2 next_pid=1041 next_prio=120
- <...>-625 (-----) [003] ...1 14594.229271: tracing_mark_write: B|625|handleTransaction
- <...>-1773 (-----) [004] .... 14594.229285: binder_set_priority: proc=625 thread=1773 old=110 => new=120 desired=120
- <...>-440 (-----) [007] d..2 14594.229301: sched_switch: prev_comm=mmc-cmdqd/0 prev_pid=440 prev_prio=98 prev_state=D ==> next_comm=RenderThread next_pid=2738 next_prio=110
- <...>-2738 (-----) [007] ...1 14594.229318: tracing_mark_write: B|2007|HWC release fence 36028 has signaled
- <...>-2738 (-----) [007] ...1 14594.229331: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [007] ...1 14594.229337: tracing_mark_write: B|2007|eglBeginFrame
- <...>-2738 (-----) [007] ...1 14594.229352: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [007] ...1 14594.229354: tracing_mark_write: B|2007|query
- <...>-791 (-----) [000] d..2 14594.229357: sched_switch: prev_comm=main prev_pid=791 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <...>-625 (-----) [003] ...1 14594.229440: tracing_mark_write: B|625|doTransaction
- <...>-13916 (-----) [002] d..2 14594.229482: sched_switch: prev_comm=HeapTaskDaemon prev_pid=13916 prev_prio=124 prev_state=D|K ==> next_comm=swapper/2 next_pid=0 next_prio=120
- <...>-13917 (-----) [001] d..2 14594.229492: sched_blocked_reason: pid=13916 iowait=0 caller=__rwsem_down_write_failed_common+0x3e8/0x754
- <...>-625 (-----) [003] ...1 14594.229492: tracing_mark_write: B|625|doTransaction
- <...>-625 (-----) [003] ...1 14594.229507: tracing_mark_write: B|625|doTransaction
- <...>-13917 (-----) [001] d..2 14594.229523: sched_switch: prev_comm=ReferenceQueueD prev_pid=13917 prev_prio=124 prev_state=D ==> next_comm=swapper/1 next_pid=0 next_prio=120
- <...>-13916 (-----) [002] d..2 14594.229535: sched_blocked_reason: pid=13917 iowait=0 caller=do_page_fault+0x550/0x5fc
- <...>-625 (-----) [003] ...1 14594.229538: tracing_mark_write: B|625|doTransaction
- <...>-2738 (-----) [007] ...1 14594.229543: tracing_mark_write: B|2007|flush commands
- <...>-13916 (-----) [002] .... 14594.229562: sched_process_exit: comm=HeapTaskDaemon pid=13916 prio=124
- <...>-625 (-----) [003] ...1 14594.229567: tracing_mark_write: B|625|doTransaction
- <...>-625 (-----) [003] ...1 14594.229588: tracing_mark_write: B|625|doTransaction
- <...>-625 (-----) [003] ...1 14594.229628: tracing_mark_write: B|625|doTransaction
- <...>-625 (-----) [003] ...1 14594.229652: tracing_mark_write: B|625|doTransaction
- <...>-13916 (-----) [002] d..2 14594.229676: sched_switch: prev_comm=HeapTaskDaemon prev_pid=13916 prev_prio=124 prev_state=x ==> next_comm=swapper/2 next_pid=0 next_prio=120
- <...>-625 (-----) [003] ...1 14594.229676: tracing_mark_write: B|625|doTransaction
- <...>-2007 (-----) [006] d..2 14594.229688: sched_switch: prev_comm=s.nexuslauncher prev_pid=2007 prev_prio=110 prev_state=S ==> next_comm=swapper/6 next_pid=0 next_prio=120
- <...>-625 (-----) [003] ...1 14594.229703: tracing_mark_write: B|625|doTransaction
- <...>-625 (-----) [003] ...1 14594.229725: tracing_mark_write: B|625|doTransaction
- <...>-625 (-----) [003] ...1 14594.229750: tracing_mark_write: B|625|doTransaction
- <...>-625 (-----) [003] ...1 14594.229772: tracing_mark_write: B|625|doTransaction
- <...>-625 (-----) [003] ...1 14594.229792: tracing_mark_write: B|625|doTransaction
- <...>-791 (-----) [000] d..2 14594.229811: sched_switch: prev_comm=main prev_pid=791 prev_prio=120 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <...>-625 (-----) [003] ...1 14594.229824: tracing_mark_write: B|625|doTransaction
- <...>-2738 (-----) [007] ...1 14594.229827: tracing_mark_write: B|2007|eglSwapBuffersWithDamageKHR
- <...>-13917 (-----) [001] d..2 14594.229836: sched_switch: prev_comm=ReferenceQueueD prev_pid=13917 prev_prio=124 prev_state=D ==> next_comm=swapper/1 next_pid=0 next_prio=120
- <...>-2738 (-----) [007] ...1 14594.229837: tracing_mark_write: B|2007|setSurfaceDamage
- <...>-625 (-----) [003] ...1 14594.229850: tracing_mark_write: B|625|doTransaction
- <...>-13918 (-----) [002] d..2 14594.229856: sched_blocked_reason: pid=13917 iowait=0 caller=SyS_madvise+0xd34/0xd3c
- <...>-5281 (-----) [001] d..2 14594.229932: sched_switch: prev_comm=writer prev_pid=5281 prev_prio=96 prev_state=D ==> next_comm=swapper/1 next_pid=0 next_prio=120
- <...>-89 (-----) [006] d..2 14594.229951: sched_switch: prev_comm=lpass_smem_glin prev_pid=89 prev_prio=98 prev_state=S ==> next_comm=swapper/6 next_pid=0 next_prio=120
- <...>-625 (-----) [003] ...1 14594.229982: tracing_mark_write: B|625|handleMessageInvalidate
- <...>-625 (-----) [003] ...1 14594.229984: tracing_mark_write: B|625|handlePageFlip
- <...>-625 (-----) [003] ...1 14594.230013: tracing_mark_write: B|625|latchBuffer
- <...>-13917 (-----) [000] .... 14594.230015: sched_process_exit: comm=ReferenceQueueD pid=13917 prio=124
- <...>-625 (-----) [003] ...1 14594.230020: tracing_mark_write: B|625|query
- <...>-625 (-----) [003] ...1 14594.230028: tracing_mark_write: B|625|updateTexImage
- <...>-625 (-----) [003] ...1 14594.230035: tracing_mark_write: B|625|acquireBuffer
- <...>-625 (-----) [003] ...1 14594.230044: tracing_mark_write: B|625|com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#1: 2
- <...>-2738 (-----) [007] d..2 14594.230057: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=D ==> next_comm=smem_native_lpa next_pid=88 next_prio=120
- <...>-14607 (-----) [000] d..2 14594.259609: sched_blocked_reason: pid=14624 iowait=0 caller=__rwsem_down_write_failed_common+0x3e8/0x754
- <...>-2738 (-----) [005] d..2 14594.259620: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=120 prev_state=S ==> next_comm=Binder:625_4 next_pid=1773 next_prio=120
- <...>-1773 (-----) [005] ...1 14594.259649: tracing_mark_write: B|625|query
- <...>-2738 (-----) [005] ...1 14594.259714: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [005] d..2 14594.259743: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=120 prev_state=S ==> next_comm=Binder:625_4 next_pid=1773 next_prio=120
- <...>-1773 (-----) [005] ...1 14594.259757: tracing_mark_write: B|625|query
- <...>-2738 (-----) [005] ...1 14594.259810: tracing_mark_write: B|2007|syncFrameState
- <...>-2738 (-----) [005] ...1 14594.259856: tracing_mark_write: B|2007|prepareTree
- Binder:14607_1-14624 (14607) [002] ...1 14594.259863: tracing_mark_write: B|14607|AttachCurrentThread
- Binder:14607_1-14624 (14607) [002] ...1 14594.259869: tracing_mark_write: B|14607|Thread::Attach
- Binder:14607_1-14624 (14607) [002] ...1 14594.259873: tracing_mark_write: B|14607|Thread birth
- Binder:14607_1-14624 (14607) [002] ...1 14594.259916: tracing_mark_write: B|14607|Thread::Init
- Binder:14607_1-14624 (14607) [002] ...1 14594.259920: tracing_mark_write: B|14607|InitStackHwm
- <...>-14607 (-----) [000] d..2 14594.259932: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- Binder:14607_1-14624 (14607) [002] d..2 14594.259941: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- <...>-3198 (-----) [001] ...1 14594.259942: tracing_mark_write: B|2007|Update SurfaceView position
- Binder:14607_1-14624 (14607) [002] ...1 14594.259963: tracing_mark_write: B|14607|InitTlsEntryPoints
- Binder:14607_1-14624 (14607) [002] ...1 14594.259974: tracing_mark_write: B|14607|InitInterpreterTls
- <...>-14607 (-----) [000] d..2 14594.260005: sched_blocked_reason: pid=14624 iowait=0 caller=__rwsem_down_write_failed_common+0x3e8/0x754
- <...>-3198 (-----) [001] d..2 14594.260007: sched_switch: prev_comm=hwuiTask1 prev_pid=3198 prev_prio=118 prev_state=S ==> next_comm=swapper/1 next_pid=0 next_prio=120
- <...>-14607 (-----) [000] d..2 14594.260024: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- Binder:14607_1-14624 (14607) [002] d..2 14594.260038: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- <...>-14607 (-----) [000] d..2 14594.260064: sched_blocked_reason: pid=14624 iowait=0 caller=__rwsem_down_write_failed_common+0x3e8/0x754
- Binder:14607_1-14624 (14607) [002] ...1 14594.260101: tracing_mark_write: B|14607|ThreadList::Register
- <...>-2738 (-----) [005] ...1 14594.260128: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [005] ...1 14594.260140: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [005] ...1 14594.260148: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [005] ...1 14594.260155: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [005] ...1 14594.260161: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [005] ...1 14594.260167: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [005] ...1 14594.260173: tracing_mark_write: B|2007|dequeueBuffer
- <...>-2007 (-----) [001] d..2 14594.260201: sched_switch: prev_comm=s.nexuslauncher prev_pid=2007 prev_prio=120 prev_state=S ==> next_comm=swapper/1 next_pid=0 next_prio=120
- <...>-2738 (-----) [005] d..2 14594.260214: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=120 prev_state=S ==> next_comm=Binder:625_4 next_pid=1773 next_prio=120
- <...>-1773 (-----) [005] ...1 14594.260236: tracing_mark_write: B|625|dequeueBuffer
- <...>-1773 (-----) [005] ...1 14594.260249: tracing_mark_write: B|625|com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#1: 2
- <...>-14607 (-----) [000] d..2 14594.260334: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- Binder:14607_1-14624 (14607) [002] d..2 14594.260343: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- <...>-14607 (-----) [000] d..2 14594.260376: sched_blocked_reason: pid=14624 iowait=0 caller=__rwsem_down_write_failed_common+0x3e8/0x754
- <...>-14607 (-----) [000] d..2 14594.260387: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <...>-2738 (-----) [005] ...1 14594.260401: tracing_mark_write: B|2007|HWC release fence 36030 has signaled
- Binder:14607_1-14624 (14607) [002] d..2 14594.260407: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- <...>-2738 (-----) [005] ...1 14594.260419: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [005] ...1 14594.260427: tracing_mark_write: B|2007|eglBeginFrame
- <...>-2738 (-----) [005] ...1 14594.260445: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [005] ...1 14594.260450: tracing_mark_write: B|2007|query
- Binder:14607_1-14624 (14607) [002] .... 14594.260472: task_newtask: pid=14625 comm=Binder:14607_1 clone_flags=3d0f00 oom_score_adj=-1000
- <...>-14607 (-----) [000] d..2 14594.260517: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- Binder:14607_2-14625 (14607) [001] d..2 14594.260525: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- <...>-14607 (-----) [000] d..2 14594.260555: sched_blocked_reason: pid=14625 iowait=0 caller=__rwsem_down_write_failed_common+0x3e8/0x754
- <...>-14607 (-----) [000] ...1 14594.260569: tracing_mark_write: B|14607|ActivityThreadMain
- <...>-14607 (-----) [000] d..2 14594.260581: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- Binder:14607_2-14625 (14607) [001] d..2 14594.260588: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- <...>-14607 (-----) [000] d..2 14594.260611: sched_blocked_reason: pid=14625 iowait=0 caller=__rwsem_down_write_failed_common+0x3e8/0x754
- <...>-14607 (-----) [000] d..2 14594.260623: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- Binder:14607_2-14625 (14607) [001] d..2 14594.260636: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- <...>-14607 (-----) [000] d..2 14594.260663: sched_blocked_reason: pid=14625 iowait=0 caller=__rwsem_down_write_failed_common+0x3e8/0x754
- <...>-14607 (-----) [000] d..2 14594.260674: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- Binder:14607_2-14625 (14607) [001] d..2 14594.260694: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- <...>-14607 (-----) [000] d..2 14594.260724: sched_blocked_reason: pid=14625 iowait=0 caller=__rwsem_down_write_failed_common+0x3e8/0x754
- <...>-2738 (-----) [005] ...1 14594.260734: tracing_mark_write: B|2007|flush commands
- <...>-14607 (-----) [000] d..2 14594.260735: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- Binder:14607_2-14625 (14607) [001] d..2 14594.260753: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- Binder:14607_2-14625 (14607) [001] ...1 14594.260925: tracing_mark_write: B|14607|AttachCurrentThread
- Binder:14607_2-14625 (14607) [001] ...1 14594.260930: tracing_mark_write: B|14607|Thread::Attach
- Binder:14607_2-14625 (14607) [001] ...1 14594.260933: tracing_mark_write: B|14607|Thread birth
- Binder:14607_2-14625 (14607) [001] ...1 14594.260973: tracing_mark_write: B|14607|Thread::Init
- Binder:14607_2-14625 (14607) [001] ...1 14594.260977: tracing_mark_write: B|14607|InitStackHwm
- <...>-14607 (-----) [000] d..2 14594.260990: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- Binder:14607_2-14625 (14607) [001] d..2 14594.260998: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- Binder:14607_2-14625 (14607) [001] ...1 14594.261023: tracing_mark_write: B|14607|InitTlsEntryPoints
- Binder:14607_2-14625 (14607) [001] ...1 14594.261034: tracing_mark_write: B|14607|InitInterpreterTls
- <...>-14607 (-----) [000] d..2 14594.261064: sched_blocked_reason: pid=14625 iowait=0 caller=__rwsem_down_write_failed_common+0x3e8/0x754
- <...>-14607 (-----) [000] d..2 14594.261075: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- Binder:14607_2-14625 (14607) [001] d..2 14594.261094: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- <...>-14607 (-----) [000] d..2 14594.261120: sched_blocked_reason: pid=14625 iowait=0 caller=__rwsem_down_write_failed_common+0x3e8/0x754
- <...>-14607 (-----) [000] d..2 14594.261132: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- Binder:14607_2-14625 (14607) [001] d..2 14594.261146: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- Binder:14607_2-14625 (14607) [001] ...1 14594.261167: tracing_mark_write: B|14607|ThreadList::Register
- <...>-14607 (-----) [000] d..2 14594.261209: sched_blocked_reason: pid=14625 iowait=0 caller=__rwsem_down_write_failed_common+0x3e8/0x754
- <...>-2738 (-----) [005] ...1 14594.261212: tracing_mark_write: B|2007|waitOnFences
- <...>-14607 (-----) [000] d..2 14594.261220: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=120 prev_state=D ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <...>-2738 (-----) [005] ...1 14594.261232: tracing_mark_write: B|2007|eglSwapBuffersWithDamageKHR
- <...>-2738 (-----) [005] ...1 14594.261244: tracing_mark_write: B|2007|setSurfaceDamage
- Binder:14607_2-14625 (14607) [001] d..2 14594.261246: sched_blocked_reason: pid=14607 iowait=0 caller=do_page_fault+0x550/0x5fc
- <...>-14607 (-----) [000] ...1 14594.261326: tracing_mark_write: B|14607|VerifyClass com.android.org.conscrypt.TrustedCertificateStore$PreloadHolder
- <...>-2738 (-----) [005] .... 14594.261621: fence_init: driver=kgsl-timeline timeline=kgsl-3d0_13-s.nexuslauncher(200 context=27 seqno=78005
- <...>-625 (-----) [003] ...1 14594.263903: tracing_mark_write: B|625|resetIdleTimer
- <...>-625 (-----) [003] ...1 14594.263912: tracing_mark_write: B|625|rebuildLayerStacks
- <...>-625 (-----) [003] ...1 14594.263915: tracing_mark_write: B|625|rebuildLayerStacks VR Dirty
- <...>-625 (-----) [003] ...1 14594.263919: tracing_mark_write: B|625|computeVisibleRegions
- <...>-1398 (-----) [006] d..2 14594.263966: sched_switch: prev_comm=android.anim prev_pid=1398 prev_prio=110 prev_state=S ==> next_comm=Binder:625_4 next_pid=1773 next_prio=120
- <...>-1695 (-----) [001] d..2 14594.264086: sched_switch: prev_comm=InputDispatcher prev_pid=1695 prev_prio=112 prev_state=S ==> next_comm=Binder:1368_14 next_pid=3253 next_prio=120
- <...>-625 (-----) [003] ...1 14594.264293: tracing_mark_write: B|625|calculateWorkingSet
- <...>-625 (-----) [003] ...1 14594.264500: tracing_mark_write: B|625|prepare
- <...>-625 (-----) [003] ...1 14594.264513: tracing_mark_write: B|625|HIDL::IComposerClient::executeCommands_2_2::client
- <...>-625 (-----) [003] ...2 14594.264584: binder_set_priority: proc=627 thread=627 old=97 => new=98 desired=98
- <...>-625 (-----) [003] d..2 14594.264617: sched_switch: prev_comm=surfaceflinger prev_pid=625 prev_prio=98 prev_state=S ==> next_comm=logd.writer next_pid=588 next_prio=130
- <...>-588 (-----) [003] d..2 14594.264851: sched_switch: prev_comm=logd.writer prev_pid=588 prev_prio=130 prev_state=S ==> next_comm=swapper/3 next_pid=0 next_prio=120
- rcu_preempt-7 ( 7) [007] d..2 14594.265273: sched_switch: prev_comm=rcu_preempt prev_pid=7 prev_prio=120 prev_state=S ==> next_comm=kworker/u16:3 next_pid=18008 next_prio=120
- <...>-18008 (-----) [007] d..2 14594.265404: sched_switch: prev_comm=kworker/u16:3 prev_pid=18008 prev_prio=120 prev_state=D ==> next_comm=swapper/7 next_pid=0 next_prio=120
- <...>-18008 (-----) [007] d..2 14594.265471: sched_switch: prev_comm=kworker/u16:3 prev_pid=18008 prev_prio=120 prev_state=S ==> next_comm=swapper/7 next_pid=0 next_prio=120
- <...>-625 (-----) [003] ...1 14594.265496: tracing_mark_write: B|625|doComposition
- <...>-625 (-----) [003] ...1 14594.265507: tracing_mark_write: B|625|doComposeSurfaces
- <...>-625 (-----) [003] ...1 14594.265552: tracing_mark_write: B|625|acquireBuffer
- <...>-625 (-----) [003] ...1 14594.265563: tracing_mark_write: B|625|postFramebuffer
- <...>-625 (-----) [003] ...1 14594.265567: tracing_mark_write: B|625|presentAndGetReleaseFences
- <...>-625 (-----) [003] d..1 14594.265601: fence_enable_signal: driver=sde_fence:crtc97:91650 timeline=crtc97 context=3 seqno=91650
- <...>-625 (-----) [003] ...1 14594.265735: tracing_mark_write: B|625|logLayerStats
- <...>-625 (-----) [003] ...1 14594.265744: tracing_mark_write: B|625|postComposition
- <...>-625 (-----) [003] ...1 14594.265749: tracing_mark_write: B|625|releaseBuffer
- <...>-625 (-----) [003] ...1 14594.265753: tracing_mark_write: B|625|com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#1: 1
- <...>-625 (-----) [003] ...1 14594.265791: tracing_mark_write: B|625|releaseBuffer
- <...>-440 (-----) [007] d..2 14594.342366: sched_switch: prev_comm=mmc-cmdqd/0 prev_pid=440 prev_prio=98 prev_state=D ==> next_comm=kworker/u17:2 next_pid=1778 next_prio=100
- <...>-2007 (-----) [006] ...1 14594.342375: tracing_mark_write: B|2007|input
- <...>-2007 (-----) [006] ...1 14594.342399: tracing_mark_write: B|2007|animation
- <...>-625 (-----) [003] ...1 14594.342447: tracing_mark_write: B|625|doTransaction
- <...>-625 (-----) [003] ...1 14594.342489: tracing_mark_write: B|625|doTransaction
- kworker/u17:2-1778 ( 1778) [007] d..3 14594.342532: sched_blocked_reason: pid=14607 iowait=1 caller=wait_on_page_bit_common+0x2a8/0x5f8
- kworker/u17:2-1778 ( 1778) [007] d..2 14594.342544: sched_switch: prev_comm=kworker/u17:2 prev_pid=1778 prev_prio=100 prev_state=S ==> next_comm=kworker/u16:2 next_pid=27544 next_prio=120
- <...>-1773 (-----) [000] ...1 14594.342575: tracing_mark_write: B|625|requestNextVsync
- <...>-1773 (-----) [000] ...1 14594.342579: tracing_mark_write: B|625|resetIdleTimer
- <...>-27544 (-----) [007] d..2 14594.342589: sched_switch: prev_comm=kworker/u16:2 prev_pid=27544 prev_prio=120 prev_state=S ==> next_comm=swapper/7 next_pid=0 next_prio=120
- <...>-656 (-----) [002] d.h3 14594.342604: sched_blocked_reason: pid=1233 iowait=0 caller=geni_i2c_xfer+0x4d8/0x1398
- <...>-1803 (-----) [001] d..2 14594.342605: sched_switch: prev_comm=ndroid.systemui prev_pid=1803 prev_prio=120 prev_state=S ==> next_comm=swapper/1 next_pid=0 next_prio=120
- <...>-625 (-----) [003] ...1 14594.342632: tracing_mark_write: B|625|handleMessageInvalidate
- <...>-625 (-----) [003] ...1 14594.342634: tracing_mark_write: B|625|handlePageFlip
- <...>-2738 (-----) [007] ...1 14594.342641: tracing_mark_write: B|2007|notifyFramePending
- <...>-658 (-----) [002] d..2 14594.342653: sched_switch: prev_comm=DispSync prev_pid=658 prev_prio=97 prev_state=S ==> next_comm=Binder:625_1 next_pid=656 next_prio=120
- <...>-656 (-----) [002] ...1 14594.342656: tracing_mark_write: B|625|requestNextVsync
- <...>-2738 (-----) [007] d..2 14594.342658: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=S ==> next_comm=swapper/7 next_pid=0 next_prio=120
- <...>-656 (-----) [002] ...1 14594.342660: tracing_mark_write: B|625|resetIdleTimer
- <...>-660 (-----) [005] d..2 14594.342663: sched_switch: prev_comm=app prev_pid=660 prev_prio=97 prev_state=S ==> next_comm=swapper/5 next_pid=0 next_prio=120
- <...>-625 (-----) [003] ...1 14594.342665: tracing_mark_write: B|625|latchBuffer
- <...>-625 (-----) [003] ...1 14594.342673: tracing_mark_write: B|625|query
- <...>-625 (-----) [003] ...1 14594.342682: tracing_mark_write: B|625|updateTexImage
- <...>-625 (-----) [003] ...1 14594.342693: tracing_mark_write: B|625|acquireBuffer
- <...>-625 (-----) [003] ...1 14594.342703: tracing_mark_write: B|625|com.google.android.apps.nexuslauncher/com.google.android.apps.nexuslauncher.NexusLauncherActivity#1: 1
- <...>-660 (-----) [005] d..2 14594.342709: sched_switch: prev_comm=app prev_pid=660 prev_prio=97 prev_state=S ==> next_comm=swapper/5 next_pid=0 next_prio=120
- <...>-2007 (-----) [006] ...1 14594.342733: tracing_mark_write: B|2007|traversal
- <...>-2007 (-----) [006] ...1 14594.342776: tracing_mark_write: B|2007|draw
- <...>-2007 (-----) [006] ...1 14594.342791: tracing_mark_write: B|2007|Record View#draw()
- <...>-625 (-----) [003] ...1 14594.342849: tracing_mark_write: B|625|updateInputFlinger
- <...>-2007 (-----) [006] d..2 14594.342903: sched_switch: prev_comm=s.nexuslauncher prev_pid=2007 prev_prio=110 prev_state=S ==> next_comm=kworker/6:2H next_pid=24261 next_prio=100
- <...>-2738 (-----) [007] ...1 14594.342910: tracing_mark_write: B|2007|DrawFrame
- <...>-2738 (-----) [007] d..2 14594.342917: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=R+ ==> next_comm=mmc-cmdqd/0 next_pid=440 next_prio=98
- <...>-24261 (-----) [006] d..2 14594.342918: sched_switch: prev_comm=kworker/6:2H prev_pid=24261 prev_prio=100 prev_state=S ==> next_comm=.android.dialer next_pid=14607 next_prio=110
- <...>-440 (-----) [007] d..2 14594.342926: sched_switch: prev_comm=mmc-cmdqd/0 prev_pid=440 prev_prio=98 prev_state=D ==> next_comm=RenderThread next_pid=2738 next_prio=110
- <...>-2738 (-----) [007] ...1 14594.342927: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [007] ...2 14594.342959: binder_set_priority: proc=625 thread=656 old=120 => new=110 desired=110
- <...>-2738 (-----) [007] d..2 14594.342975: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=R+ ==> next_comm=Binder:625_1 next_pid=656 next_prio=110
- <...>-656 (-----) [007] ...1 14594.343021: tracing_mark_write: B|625|query
- <...>-656 (-----) [007] .... 14594.343033: binder_set_priority: proc=625 thread=656 old=110 => new=120 desired=120
- <...>-2738 (-----) [007] ...1 14594.343070: tracing_mark_write: B|2007|query
- <...>-1233 (-----) [004] d..2 14594.343074: sched_switch: prev_comm=sound trigger c prev_pid=1233 prev_prio=120 prev_state=R+ ==> next_comm=irq/144-1436400 next_pid=2522 next_prio=49
- <...>-2738 (-----) [007] ...2 14594.343078: binder_set_priority: proc=625 thread=656 old=120 => new=110 desired=110
- <...>-625 (-----) [003] ...1 14594.343084: tracing_mark_write: B|625|onMessageReceived
- <...>-625 (-----) [003] ...1 14594.343087: tracing_mark_write: B|625|handleMessageRefresh
- <...>-625 (-----) [003] ...1 14594.343090: tracing_mark_write: B|625|preComposition
- <...>-2738 (-----) [007] d..2 14594.343090: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=R+ ==> next_comm=Binder:625_1 next_pid=656 next_prio=110
- <...>-625 (-----) [003] ...1 14594.343122: tracing_mark_write: B|625|rebuildLayerStacks
- <...>-625 (-----) [003] ...1 14594.343124: tracing_mark_write: B|625|rebuildLayerStacks VR Dirty
- <...>-89 (-----) [007] d..2 14594.343126: sched_switch: prev_comm=lpass_smem_glin prev_pid=89 prev_prio=98 prev_state=S ==> next_comm=Binder:625_1 next_pid=656 next_prio=110
- <...>-625 (-----) [003] ...1 14594.343129: tracing_mark_write: B|625|computeVisibleRegions
- <...>-656 (-----) [007] ...1 14594.343136: tracing_mark_write: B|625|query
- <...>-14607 (-----) [006] ...2 14594.343141: binder_set_priority: proc=1368 thread=3253 old=120 => new=110 desired=110
- <...>-2965 (-----) [001] .... 14596.746610: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=000000002ae8fcff pfn=1522884 ofs=188416
- <idle>-0 (-----) [002] d..2 14596.746619: sched_switch: prev_comm=swapper/2 prev_pid=0 prev_prio=120 prev_state=R ==> next_comm=mmc-cmdqd/0 next_pid=440 next_prio=98
- <...>-2965 (-----) [001] .... 14596.746629: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=00000000679ee1ec pfn=1299913 ofs=192512
- <...>-2965 (-----) [001] .... 14596.746664: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=0000000006cd2fb7 pfn=1296251 ofs=196608
- <...>-2965 (-----) [001] .... 14596.746677: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=00000000af82f3d6 pfn=1419330 ofs=200704
- <...>-2965 (-----) [001] .... 14596.746693: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=000000002840f054 pfn=1304928 ofs=204800
- <...>-2965 (-----) [001] .... 14596.746706: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=000000004a59da17 pfn=1288069 ofs=208896
- <...>-2965 (-----) [001] .... 14596.746717: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=0000000023a80dca pfn=1419686 ofs=212992
- <...>-2965 (-----) [001] .... 14596.746730: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=000000001cf89eab pfn=1315372 ofs=217088
- <...>-2965 (-----) [001] .... 14596.746743: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=000000005b4c6cb6 pfn=1380698 ofs=221184
- <...>-2965 (-----) [001] .... 14596.746760: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=00000000f8304ae7 pfn=1206753 ofs=225280
- <...>-2965 (-----) [001] .... 14596.746773: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=00000000cb912305 pfn=1325465 ofs=229376
- <...>-2965 (-----) [001] .... 14596.746785: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=00000000f16f3774 pfn=1408056 ofs=233472
- <...>-2965 (-----) [001] .... 14596.746801: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=0000000056d4c926 pfn=1418352 ofs=237568
- <...>-2965 (-----) [001] .... 14596.746815: mm_filemap_add_to_page_cache: dev 253:6 ino a359 page=00000000f3eeb42c pfn=1320957 ofs=241664
- <...>-440 (-----) [002] d..2 14596.746916: sched_switch: prev_comm=mmc-cmdqd/0 prev_pid=440 prev_prio=98 prev_state=D ==> next_comm=swapper/2 next_pid=0 next_prio=120
-
- <...>-656 (-----) [007] .... 14594.343145: binder_set_priority: proc=625 thread=656 old=110 => new=120 desired=120
- <...>-14607 (-----) [006] d..2 14594.343164: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=110 prev_state=S ==> next_comm=swapper/6 next_pid=0 next_prio=120
- <...>-5281 (-----) [002] d..2 14594.343177: sched_switch: prev_comm=writer prev_pid=5281 prev_prio=96 prev_state=S ==> next_comm=RenderThread next_pid=2738 next_prio=110
- irq/144-1436400-2522 ( 2522) [004] d..2 14594.343223: sched_switch: prev_comm=irq/144-1436400 prev_pid=2522 prev_prio=49 prev_state=D ==> next_comm=sound trigger c next_pid=1233 next_prio=120
- <...>-88 (-----) [006] d..2 14594.343240: sched_switch: prev_comm=smem_native_lpa prev_pid=88 prev_prio=98 prev_state=S ==> next_comm=swapper/6 next_pid=0 next_prio=120
- <...>-1238 (-----) [001] d..2 14594.343243: sched_switch: prev_comm=FastMixer prev_pid=1238 prev_prio=96 prev_state=S ==> next_comm=swapper/1 next_pid=0 next_prio=120
- <...>-2738 (-----) [002] ...1 14594.343244: tracing_mark_write: B|2007|syncFrameState
- <...>-2738 (-----) [002] ...1 14594.343293: tracing_mark_write: B|2007|prepareTree
- <...>-1695 (-----) [001] d..2 14594.343318: sched_switch: prev_comm=InputDispatcher prev_pid=1695 prev_prio=112 prev_state=R+ ==> next_comm=FastMixer next_pid=1238 next_prio=96
- <...>-5281 (-----) [005] d..2 14594.343322: sched_switch: prev_comm=writer prev_pid=5281 prev_prio=96 prev_state=S ==> next_comm=Binder:1368_14 next_pid=3253 next_prio=110
- <...>-1238 (-----) [001] d..2 14594.343442: sched_switch: prev_comm=FastMixer prev_pid=1238 prev_prio=96 prev_state=S ==> next_comm=InputDispatcher next_pid=1695 next_prio=112
- <...>-1695 (-----) [001] d..2 14594.343467: sched_switch: prev_comm=InputDispatcher prev_pid=1695 prev_prio=112 prev_state=S ==> next_comm=swapper/1 next_pid=0 next_prio=120
- <...>-5281 (-----) [000] d..2 14594.343484: sched_switch: prev_comm=writer prev_pid=5281 prev_prio=96 prev_state=S ==> next_comm=swapper/0 next_pid=0 next_prio=120
- <...>-625 (-----) [003] ...1 14594.343519: tracing_mark_write: B|625|calculateWorkingSet
- <...>-2738 (-----) [002] ...1 14594.343568: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [002] ...1 14594.343577: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [002] ...1 14594.343586: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [002] ...1 14594.343591: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [002] ...1 14594.343597: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [002] ...1 14594.343602: tracing_mark_write: B|2007|query
- <...>-2738 (-----) [002] ...1 14594.343609: tracing_mark_write: B|2007|dequeueBuffer
- <...>-2007 (-----) [006] d..2 14594.343612: sched_switch: prev_comm=s.nexuslauncher prev_pid=2007 prev_prio=110 prev_state=S ==> next_comm=swapper/6 next_pid=0 next_prio=120
- <...>-2738 (-----) [002] ...2 14594.343633: binder_set_priority: proc=625 thread=656 old=120 => new=110 desired=110
- <...>-2738 (-----) [002] d..2 14594.343683: sched_switch: prev_comm=RenderThread prev_pid=2738 prev_prio=110 prev_state=R+ ==> next_comm=Binder:625_1 next_pid=656 next_prio=110
- <...>-625 (-----) [003] ...1 14594.343704: tracing_mark_write: B|625|prepare
- <...>-656 (-----) [002] ...1 14594.343707: tracing_mark_write: B|625|dequeueBuffer
- <...>-625 (-----) [004] ...1 14594.812869: tracing_mark_write: B|625|com.google.android.dialer/com.google.android.dialer.extensions.GoogleDialtactsActivity#0: 2
- <...>-2048 (-----) [000] d..2 14594.812895: sched_switch: prev_comm=RenderThread prev_pid=2048 prev_prio=120 prev_state=R+ ==> next_comm=Binder:625_3 next_pid=1431 next_prio=120
- <...>-1431 (-----) [000] ...1 14594.812911: tracing_mark_write: B|625|query
- <...>-625 (-----) [004] ...1 14594.812914: tracing_mark_write: B|625|latchBuffer
- <...>-625 (-----) [004] ...1 14594.812919: tracing_mark_write: B|625|query
- <...>-625 (-----) [004] ...1 14594.812925: tracing_mark_write: B|625|updateTexImage
- <...>-625 (-----) [004] ...1 14594.812928: tracing_mark_write: B|625|acquireBuffer
- <...>-625 (-----) [004] ...1 14594.812934: tracing_mark_write: B|625|StatusBar#0: 1
- <...>-2048 (-----) [000] ...1 14594.812962: tracing_mark_write: B|1803|syncFrameState
- <...>-656 (-----) [002] ...1 14594.813044: tracing_mark_write: B|625|setTransactionState
- <...>-14607 (-----) [007] ...2 14594.813083: binder_set_priority: proc=10691 thread=18733 old=120 => new=110 desired=110
- <...>-14607 (-----) [007] d..2 14594.813114: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=110 prev_state=S ==> next_comm=kworker/7:1 next_pid=7092 next_prio=120
- <...>-14655 (-----) [006] d..2 14594.813128: sched_switch: prev_comm=DialerExecutors prev_pid=14655 prev_prio=130 prev_state=R ==> next_comm=lpass_smem_glin next_pid=89 next_prio=98
- <...>-89 (-----) [006] d..2 14594.813163: sched_switch: prev_comm=lpass_smem_glin prev_pid=89 prev_prio=98 prev_state=S ==> next_comm=DialerExecutors next_pid=14655 next_prio=130
- <...>-656 (-----) [002] ...1 14594.813218: tracing_mark_write: B|625|requestNextVsync
- <...>-656 (-----) [002] ...1 14594.813222: tracing_mark_write: B|625|resetIdleTimer
- kworker/7:1-7092 ( 7092) [007] d..2 14594.813239: sched_switch: prev_comm=kworker/7:1 prev_pid=7092 prev_prio=120 prev_state=R+ ==> next_comm=smem_native_lpa next_pid=88 next_prio=98
- <...>-5281 (-----) [001] d..2 14594.813245: sched_switch: prev_comm=writer prev_pid=5281 prev_prio=96 prev_state=S ==> next_comm=Binder:10691_B next_pid=18733 next_prio=110
- <...>-88 (-----) [007] d..2 14594.813248: sched_switch: prev_comm=smem_native_lpa prev_pid=88 prev_prio=98 prev_state=R ==> next_comm=kgsl_worker_thr next_pid=259 next_prio=97
- <...>-2048 (-----) [000] d..2 14594.813249: sched_switch: prev_comm=RenderThread prev_pid=2048 prev_prio=120 prev_state=R+ ==> next_comm=FastMixer next_pid=1238 next_prio=96
- <...>-14655 (-----) [006] d..2 14594.813263: sched_switch: prev_comm=DialerExecutors prev_pid=14655 prev_prio=130 prev_state=R+ ==> next_comm=smem_native_lpa next_pid=88 next_prio=98
- <...>-661 (-----) [002] d..2 14594.813265: sched_switch: prev_comm=sf prev_pid=661 prev_prio=97 prev_state=S ==> next_comm=Binder:625_1 next_pid=656 next_prio=116
- <...>-259 (-----) [007] d..2 14594.813265: sched_switch: prev_comm=kgsl_worker_thr prev_pid=259 prev_prio=97 prev_state=S ==> next_comm=kworker/7:1 next_pid=7092 next_prio=120
- kworker/7:1-7092 ( 7092) [007] d..2 14594.813271: sched_switch: prev_comm=kworker/7:1 prev_pid=7092 prev_prio=120 prev_state=S ==> next_comm=system next_pid=108 next_prio=120
- <...>-108 (-----) [007] .... 14594.813275: ion_heap_shrink: heap_name=system, len=9469952, total_allocated=189620224
- <...>-88 (-----) [006] d..2 14594.813294: sched_switch: prev_comm=smem_native_lpa prev_pid=88 prev_prio=98 prev_state=S ==> next_comm=DialerExecutors next_pid=14655 next_prio=130
- <...>-625 (-----) [004] ...1 14594.813310: tracing_mark_write: B|625|updateInputFlinger
- <...>-1238 (-----) [000] d..2 14594.813312: sched_switch: prev_comm=FastMixer prev_pid=1238 prev_prio=96 prev_state=S ==> next_comm=RenderThread next_pid=2048 next_prio=120
- <...>-661 (-----) [002] d..2 14594.813317: sched_switch: prev_comm=sf prev_pid=661 prev_prio=97 prev_state=S ==> next_comm=Binder:625_1 next_pid=656 next_prio=116
- <...>-14640 (-----) [005] d..2 14594.813319: sched_switch: prev_comm=DialerExecutors prev_pid=14640 prev_prio=130 prev_state=R ==> next_comm=DispSync next_pid=658 next_prio=97
- <...>-656 (-----) [002] ...1 14594.813336: tracing_mark_write: B|625|~GraphicBuffer
- <...>-658 (-----) [005] d..2 14594.813345: sched_switch: prev_comm=DispSync prev_pid=658 prev_prio=97 prev_state=S ==> next_comm=DialerExecutors next_pid=14640 next_prio=130
- <...>-656 (-----) [002] ...1 14594.813345: tracing_mark_write: B|625|~GraphicBuffer
- <...>-656 (-----) [002] ...1 14594.813353: tracing_mark_write: B|625|~GraphicBuffer
- <...>-2048 (-----) [000] d..2 14594.813358: sched_switch: prev_comm=RenderThread prev_pid=2048 prev_prio=120 prev_state=R+ ==> next_comm=FastMixer next_pid=1238 next_prio=96
- <...>-656 (-----) [002] ...1 14594.813364: tracing_mark_write: B|625|~GraphicBuffer
- <...>-5281 (-----) [001] d..2 14594.813369: sched_switch: prev_comm=writer prev_pid=5281 prev_prio=96 prev_state=S ==> next_comm=Binder:10691_B next_pid=18733 next_prio=110
- <...>-656 (-----) [002] ...1 14594.813372: tracing_mark_write: B|625|~GraphicBuffer
- <...>-656 (-----) [002] ...1 14594.813380: tracing_mark_write: B|625|~GraphicBuffer
- <...>-656 (-----) [002] ...1 14594.813391: tracing_mark_write: B|625|~GraphicBuffer
- <...>-656 (-----) [002] ...1 14594.813398: tracing_mark_write: B|625|~GraphicBuffer
- <...>-656 (-----) [002] ...1 14594.813408: tracing_mark_write: B|625|~GraphicBuffer
- <...>-656 (-----) [002] ...1 14594.813416: tracing_mark_write: B|625|~GraphicBuffer
- <...>-656 (-----) [002] ...1 14594.813424: tracing_mark_write: B|625|~GraphicBuffer
- <...>-656 (-----) [002] ...1 14594.813432: tracing_mark_write: B|625|~GraphicBuffer
- <...>-656 (-----) [002] .n.1 14594.813443: tracing_mark_write: B|625|~GraphicBuffer
- <...>-1238 (-----) [000] d..2 14594.813464: sched_switch: prev_comm=FastMixer prev_pid=1238 prev_prio=96 prev_state=S ==> next_comm=RenderThread next_pid=2048 next_prio=120
- <...>-5281 (-----) [002] d..2 14594.813525: sched_switch: prev_comm=writer prev_pid=5281 prev_prio=96 prev_state=S ==> next_comm=Binder:625_1 next_pid=656 next_prio=116
- <...>-656 (-----) [002] ...1 14594.813544: tracing_mark_write: B|625|~GraphicBuffer
- <...>-656 (-----) [002] ...1 14594.813557: tracing_mark_write: B|625|~GraphicBuffer
- <...>-2048 (-----) [000] d..2 14594.813594: sched_switch: prev_comm=RenderThread prev_pid=2048 prev_prio=120 prev_state=R+ ==> next_comm=Binder:1368_15 next_pid=3359 next_prio=120
- <...>-18733 (-----) [001] ...2 14594.813635: binder_set_priority: proc=1368 thread=3514 old=120 => new=110 desired=110
- <...>-656 (-----) [002] .... 14594.813637: binder_set_priority: proc=625 thread=656 old=116 => new=120 desired=120
- <...>-108 (-----) [007] d..2 14594.813646: sched_switch: prev_comm=system prev_pid=108 prev_prio=120 prev_state=R+ ==> next_comm=android.anim next_pid=1398 next_prio=116
- <...>-625 (-----) [004] ...1 14594.813646: tracing_mark_write: B|625|onMessageReceived
- <...>-625 (-----) [004] ...1 14594.813649: tracing_mark_write: B|625|handleMessageRefresh
- <...>-625 (-----) [004] ...1 14594.813651: tracing_mark_write: B|625|preComposition
- <...>-625 (-----) [004] ...1 14594.813693: tracing_mark_write: B|625|rebuildLayerStacks
- <...>-625 (-----) [004] ...1 14594.813696: tracing_mark_write: B|625|rebuildLayerStacks VR Dirty
- <...>-625 (-----) [004] ...1 14594.813701: tracing_mark_write: B|625|computeVisibleRegions
- <...>-1398 (-----) [007] d..2 14594.813718: sched_switch: prev_comm=android.anim prev_pid=1398 prev_prio=116 prev_state=S ==> next_comm=system next_pid=108 next_prio=120
- <...>-108 (-----) [007] d..2 14594.813739: sched_switch: prev_comm=system prev_pid=108 prev_prio=120 prev_state=R+ ==> next_comm=android.anim next_pid=1398 next_prio=116
- <...>-1695 (-----) [002] d..2 14594.813970: sched_switch: prev_comm=InputDispatcher prev_pid=1695 prev_prio=112 prev_state=S ==> next_comm=system next_pid=108 next_prio=120
- <...>-1398 (-----) [007] ...1 14594.814029: tracing_mark_write: B|1368|wmLayout
- <...>-1398 (-----) [007] ...1 14594.814033: tracing_mark_write: B|1368|performSurfacePlacement
- <...>-1398 (-----) [007] ...1 14594.814040: tracing_mark_write: B|1368|applySurfaceChanges
- <...>-1398 (-----) [007] ...1 14594.814043: tracing_mark_write: B|1368|openSurfaceTransaction
- <...>-1398 (-----) [007] ...1 14594.814063: tracing_mark_write: B|1368|performLayout
- <...>-625 (-----) [004] ...1 14594.814119: tracing_mark_write: B|625|calculateWorkingSet
- <...>-1398 (-----) [007] ...1 14594.814241: tracing_mark_write: B|1368|layoutInputConsumer
- <...>-2048 (-----) [000] ...1 14594.814260: tracing_mark_write: B|1803|prepareTree
- <...>-1398 (-----) [007] ...1 14594.814263: tracing_mark_write: B|1368|applyPostLayoutPolicy
- <...>-2048 (-----) [000] d..2 14594.814408: sched_switch: prev_comm=RenderThread prev_pid=2048 prev_prio=120 prev_state=R ==> next_comm=Binder:1368_15 next_pid=3359 next_prio=120
- <...>-625 (-----) [004] ...1 14594.814411: tracing_mark_write: B|625|prepare
- <...>-625 (-----) [004] ...1 14594.814428: tracing_mark_write: B|625|HIDL::IComposerClient::executeCommands_2_2::client
- <...>-2048 (-----) [000] d..2 14594.814533: sched_switch: prev_comm=RenderThread prev_pid=2048 prev_prio=120 prev_state=R+ ==> next_comm=ndroid.systemui next_pid=1803 next_prio=120
- <...>-1803 (-----) [000] d..2 14594.814558: sched_switch: prev_comm=ndroid.systemui prev_pid=1803 prev_prio=120 prev_state=S ==> next_comm=RenderThread next_pid=2048 next_prio=120
- <...>-2048 (-----) [000] d..2 14594.814572: sched_switch: prev_comm=RenderThread prev_pid=2048 prev_prio=120 prev_state=R+ ==> next_comm=ndroid.systemui next_pid=1803 next_prio=120
- <...>-625 (-----) [004] ...2 14594.814589: binder_set_priority: proc=627 thread=627 old=97 => new=98 desired=98
- <...>-108 (-----) [002] d..2 14594.814650: sched_switch: prev_comm=system prev_pid=108 prev_prio=120 prev_state=R+ ==> next_comm=composer@2.2-se next_pid=627 next_prio=98
- <...>-625 (-----) [004] d..2 14594.814664: sched_switch: prev_comm=surfaceflinger prev_pid=625 prev_prio=98 prev_state=S ==> next_comm=ashmemd next_pid=854 next_prio=129
- <...>-1398 (-----) [007] ...1 14594.814723: tracing_mark_write: B|1368|applyWindowSurfaceChanges
- <...>-854 (-----) [004] .... 14594.814746: binder_set_priority: proc=854 thread=854 old=129 => new=120 desired=120
- <...>-854 (-----) [004] d..2 14594.814757: sched_switch: prev_comm=ashmemd prev_pid=854 prev_prio=120 prev_state=R+ ==> next_comm=highpool[0] next_pid=3493 next_prio=129
- <...>-1803 (-----) [000] d..2 14594.814763: sched_switch: prev_comm=ndroid.systemui prev_pid=1803 prev_prio=120 prev_state=S ==> next_comm=RenderThread next_pid=2048 next_prio=120
- <...>-18733 (-----) [001] d..1 14594.814819: mm_filemap_delete_from_page_cache: dev 0:1 ino 3ce5e7 page=0000000083f10c7a pfn=1298474 ofs=0
- <...>-2048 (-----) [000] ...1 14594.814842: tracing_mark_write: B|1803|dequeueBuffer
- <...>-1398 (-----) [007] ...1 14594.814850: tracing_mark_write: F|1368|launching: com.google.android.dialer|0
- <...>-1398 (-----) [007] ...1 14594.814855: tracing_mark_write: B|1368|MetricsLogger:launchObserverNotifyActivityLaunchFinished
- <...>-1398 (-----) [007] ...1 14594.814857: tracing_mark_write: B|1368|MetricsLogger:convertActivityRecordToProto
- <...>-2048 (-----) [000] d..2 14594.814905: sched_switch: prev_comm=RenderThread prev_pid=2048 prev_prio=120 prev_state=R+ ==> next_comm=Binder:625_1 next_pid=656 next_prio=120
- <...>-1410 (-----) [006] .... 14592.997816: mm_filemap_add_to_page_cache: dev 253:6 ino b785 page=00000000615a8f24 pfn=1134764 ofs=0
- <...>-1410 (-----) [006] .... 14592.997831: mm_filemap_add_to_page_cache: dev 253:6 ino b785 page=000000008768a58f pfn=1134751 ofs=4096
-
- <...>-18733 (-----) [001] .... 14594.814914: binder_set_priority: proc=10691 thread=18733 old=110 => new=120 desired=120
- <...>-14655 (-----) [006] d..2 14594.814932: sched_switch: prev_comm=DialerExecutors prev_pid=14655 prev_prio=130 prev_state=R ==> next_comm=.android.dialer next_pid=14607 next_prio=110
- <...>-656 (-----) [000] ...1 14594.814948: tracing_mark_write: B|625|dequeueBuffer
- <...>-3514 (-----) [001] .... 14594.814954: binder_set_priority: proc=1368 thread=3514 old=110 => new=120 desired=120
- <...>-656 (-----) [000] ...1 14594.814963: tracing_mark_write: B|625|NavigationBar0#0: 2
- <...>-14607 (-----) [006] ...2 14594.815022: binder_set_priority: proc=1368 thread=3514 old=120 => new=110 desired=110
- <...>-1398 (-----) [007] ...1 14594.815039: tracing_mark_write: B|1368|prepareSurfaces
- <...>-14607 (-----) [006] d..2 14594.815041: sched_switch: prev_comm=.android.dialer prev_pid=14607 prev_prio=110 prev_state=S ==> next_comm=DialerExecutors next_pid=14655 next_prio=130
- <...>-3493 (-----) [004] d..2 14594.815057: sched_switch: prev_comm=highpool[0] prev_pid=3493 prev_prio=129 prev_state=R ==> next_comm=Binder:1368_18 next_pid=3514 next_prio=110
- <...>-2048 (-----) [000] ...1 14594.815088: tracing_mark_write: B|1803|HWC release fence 45750 has signaled
- <...>-2048 (-----) [000] ...1 14594.815119: tracing_mark_write: B|1803|eglBeginFrame
- <...>-14655 (-----) [006] d..2 14594.815190: sched_switch: prev_comm=DialerExecutors prev_pid=14655 prev_prio=130 prev_state=R ==> next_comm=crtc_commit:97 next_pid=301 next_prio=83
- <...>-3514 (-----) [004] .... 14594.815193: binder_set_priority: proc=1368 thread=3514 old=110 => new=120 desired=120
- <...>-1398 (-----) [007] ...1 14594.815322: tracing_mark_write: B|1368|closeSurfaceTransaction
- <...>-3493 (-----) [004] .... 14594.815353: mm_filemap_add_to_page_cache: dev 253:6 ino 113b page=0000000069e2b98a pfn=628464 ofs=2723840
- <...>-1398 (-----) [007] ...2 14594.815393: binder_set_priority: proc=625 thread=656 old=120 => new=116 desired=116
- rcu_sched-8 ( 8) [007] d..2 14594.815449: sched_switch: prev_comm=rcu_sched prev_pid=8 prev_prio=120 prev_state=S ==> next_comm=Binder:625_1 next_pid=656 next_prio=116
diff --git a/startop/scripts/trace_analyzer/trace_analyzer b/startop/scripts/trace_analyzer/trace_analyzer
deleted file mode 100755
index 8c0396430c40..000000000000
--- a/startop/scripts/trace_analyzer/trace_analyzer
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/bin/bash
-# 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.
-
-DIR="$( cd "$(dirname "$0")" ; pwd -P )"
-
-if [[ "$#" -lt 2 ]]; then
- echo "Usage: $0 <filename.trace> <sqlite-filename.db>" >&2
- exit 1
-fi
-
-TRACE_FILENAME="$1"
-SQLITE_FILENAME="$2"
-
-#echo "Trace filename: $TRACE_FILENAME"
-#echo "SQLite filename: $SQLITE_FILENAME"
-
-if ! [[ -f "$TRACE_FILENAME" ]]; then
- echo "Error: Trace '$TRACE_FILENAME' does not exist." >&2
- exit 1
-fi
-
-if ! "$DIR/trace_analyzer.py" "$SQLITE_FILENAME" "$TRACE_FILENAME" > /dev/null; then
- echo "Fatal: trace_analyzer.py failed, aborting." >&2
- exit 1
-fi
-
-if ! "$DIR/run-sql-queries" "$SQLITE_FILENAME"; then
- echo "Fatal: Failed to run sql queries, aborting." >&2
- exit 1
-fi
diff --git a/startop/scripts/trace_analyzer/trace_analyzer.py b/startop/scripts/trace_analyzer/trace_analyzer.py
deleted file mode 100755
index 62ae018a9986..000000000000
--- a/startop/scripts/trace_analyzer/trace_analyzer.py
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/usr/bin/python3
-# 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.
-
-import re
-import sys
-import argparse
-
-from lib.trace2db import Trace2Db
-
-# This script requires 'sqlalchemy' to access the sqlite3 database.
-#
-# $> sudo apt-get install python3-pip
-# $> pip3 install --user sqlalchemy
-#
-
-def main(argv):
- parser = argparse.ArgumentParser(description='Convert ftrace/systrace file into sqlite3 db.')
- parser.add_argument('db_filename', metavar='sql_filename.db', type=str,
- help='path to sqlite3 db filename')
- parser.add_argument('trace_filename', metavar='systrace.ftrace', type=str,
- help='path to ftrace/systrace filename')
- parser.add_argument('--limit', type=int, help='limit the number of entries parsed [for debugging]')
-
- args = parser.parse_args()
-
- db_filename = args.db_filename
- trace_filename = args.trace_filename
-
- trace2db = Trace2Db(db_filename)
- print("SQL Alchemy db initialized")
-
- # parse 'raw_ftrace_entries' table
- count = trace2db.parse_file_into_db(trace_filename, limit=args.limit)
- print("Count was ", count)
-
- return 0
-
-if __name__ == '__main__':
- main(sys.argv)
diff --git a/startop/scripts/trace_analyzer/trace_analyzer_recursive b/startop/scripts/trace_analyzer/trace_analyzer_recursive
deleted file mode 100755
index 4d9ee0eec9b0..000000000000
--- a/startop/scripts/trace_analyzer/trace_analyzer_recursive
+++ /dev/null
@@ -1,78 +0,0 @@
-#!/bin/bash
-# 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.
-
-DIR="$( cd "$(dirname "$0")" ; pwd -P )"
-
-if [[ "$#" -lt 3 ]]; then
- echo "Usage: $0 <trace-dir> <db-dir> <output.csv>" >&2
- exit 1
-fi
-
-simulate="n"
-
-TRACE_DIRNAME="$1"
-SQLITE_DIRNAME="$2"
-OUTPUT_FILENAME="$3"
-
-echo "Trace filename: $TRACE_DIRNAME"
-echo "SQLite filename: $SQLITE_DIRNAME"
-
-if ! [[ -d "$TRACE_DIRNAME" ]]; then
- echo "Error: Trace '$TRACE_DIRNAME' does not exist." >&2
- exit 1
-fi
-
-process_trace_file() {
- local trace_filename="$1"
- local db_dirname="$2"
- local output_file="$3"
-
- local db_filename="$db_dirname/$(basename "$trace_filename").db"
-
- if [[ $simulate == y ]]; then
- echo "$DIR/trace_analyzer.py" "$db_filename" "$trace_filename" "> /dev/null"
- else
- if ! "$DIR/trace_analyzer.py" "$db_filename" "$trace_filename" > /dev/null; then
- echo "Fatal: trace_analyzer.py failed, aborting." >&2
- return 1
- fi
- fi
-
- if [[ $simulate == y ]]; then
- echo "$DIR/run-sql-queries" "$db_filename" ">> '$output_file'"
- else
- # append name of trace to CSV, so we can see where data came from
- echo "; $trace_filename" >> "$output_file"
- if ! "$DIR/run-sql-queries" "$db_filename" >> "$output_file"; then
- echo "Fatal: Failed to run sql queries, aborting." >&2
- return 1
- fi
- fi
-
- return 0
-}
-
-find "$TRACE_DIRNAME" -type f -name '*.trace' -print0 |
-while IFS= read -r -d '' file; do
- if [[ $file == *#*.trace && $file != *#1.trace ]]; then
- echo "Skip $file"
- continue
- fi
-
- printf '%s\n' "$file"
- process_trace_file "$file" "$SQLITE_DIRNAME" "$OUTPUT_FILENAME"
-done
-
-echo "Done"
diff --git a/startop/scripts/trace_analyzer/trace_analyzer_test.py b/startop/scripts/trace_analyzer/trace_analyzer_test.py
deleted file mode 100644
index 579529c6f6d5..000000000000
--- a/startop/scripts/trace_analyzer/trace_analyzer_test.py
+++ /dev/null
@@ -1,66 +0,0 @@
-#!/usr/bin/env python3
-#
-# 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.
-#
-
-"""
-Unit tests for trace_analyzer module.
-
-Install:
- $> sudo apt-get install python3-pytest ## OR
- $> pip install -U pytest
-See also https://docs.pytest.org/en/latest/getting-started.html
-
-Usage:
- $> pytest trace_analyzer_test.py
-
-See also https://docs.pytest.org/en/latest/usage.html
-"""
-
-# global imports
-import os
-import sys
-
-DIR = os.path.abspath(os.path.dirname(__file__))
-
-sys.path.append(os.path.dirname(DIR))
-import lib.cmd_utils as cmd_utils
-
-def test_trace_analyzer(tmpdir):
- # Setup
- bin = os.path.join(DIR, 'trace_analyzer')
- systrace = os.path.join(DIR, 'test_fixtures/common_systrace')
- db_file = tmpdir.mkdir('trace_analyzer').join('test.db')
-
- # Act
- passed, output = cmd_utils.execute_arbitrary_command([bin, systrace,
- str(db_file)],
- timeout=300,
- shell=False,
- simulate=False)
-
- # Assert
- assert passed
- assert output == """\
-'blocked_iowait_duration_ms',\
-'process_name',\
-'launching_duration_ms',\
-'launching_started_timestamp_ms',\
-'launching_finished_timestamp_ms'
-81.697999999960302375,\
-'com.google.android.dialer',\
-594.99400000095192808,\
-14594219.85600000061,\
-14594814.85000000149"""
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index c5fc4365df7a..27d423b3bc1e 100755
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -18,6 +18,7 @@ package android.telecom;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.annotation.TestApi;
@@ -3156,15 +3157,27 @@ public abstract class ConnectionService extends Service {
}
/**
- * Create a {@code Connection} for a new unknown call. An unknown call is a call originating
- * from the ConnectionService that was neither a user-initiated outgoing call, nor an incoming
- * call created using
- * {@code TelecomManager#addNewIncomingCall(PhoneAccountHandle, android.os.Bundle)}.
+ * Calls of this type are created using
+ * {@link TelecomManager#addNewUnknownCall(PhoneAccountHandle, Bundle)}. Unknown calls
+ * are used for representing calls which become known to the {@link ConnectionService}
+ * midway through the call.
+ *
+ * For example, a call transferred from one device to answer would surface as an active
+ * call in Telecom instead of going through a typical Ringing to Active transition, or
+ * Dialing to Active transition.
+ *
+ * A {@link ConnectionService} can return {@code null} (the default behavior)
+ * if it is not able to handle a request for the requested unknown connection.
+ *
+ * {@link TelecomManager#addNewIncomingCall(PhoneAccountHandle, android.os.Bundle)}.
*
* @hide
*/
- public Connection onCreateUnknownConnection(PhoneAccountHandle connectionManagerPhoneAccount,
- ConnectionRequest request) {
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
+ public @Nullable Connection onCreateUnknownConnection(
+ @NonNull PhoneAccountHandle connectionManagerPhoneAccount,
+ @NonNull ConnectionRequest request) {
return null;
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index a74930b0da12..e0e791321819 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -8920,7 +8920,7 @@ public class CarrierConfigManager {
sDefaults.putBoolean(KEY_STORE_SIM_PIN_FOR_UNATTENDED_REBOOT_BOOL, true);
sDefaults.putBoolean(KEY_HIDE_ENABLE_2G, false);
sDefaults.putStringArray(KEY_ALLOWED_INITIAL_ATTACH_APN_TYPES_STRING_ARRAY,
- new String[]{"ia", "default", "mms", "dun"});
+ new String[]{"ia", "default"});
sDefaults.putBoolean(KEY_CARRIER_PROVISIONS_WIFI_MERGED_NETWORKS_BOOL, false);
sDefaults.putBoolean(KEY_USE_IP_FOR_CALLING_INDICATOR_BOOL, false);
sDefaults.putBoolean(KEY_DISPLAY_CALL_STRENGTH_INDICATOR_BOOL, true);
diff --git a/tools/lint/README.md b/tools/lint/README.md
index 2b6d65b318e5..b534b62cb395 100644
--- a/tools/lint/README.md
+++ b/tools/lint/README.md
@@ -40,6 +40,9 @@ m out/soong/.intermediates/frameworks/base/services/autofill/services.autofill/a
- If you want to build lint reports for more than 1 module and they include a common module in their
`defaults` field, e.g. `platform_service_defaults`, you can add the `lint` property to that common
module instead of adding it in every module.
+- If you want to run a single lint type, use the `ANDROID_LINT_CHECK`
+ environment variable with the id of the lint. For example:
+ `ANDROID_LINT_CHECK=UnusedTokenOfOriginalCallingIdentity m out/[...]/lint-report.html`
## Create or update a baseline