summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java43
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java42
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java11
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java13
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/ContentObserverController.java8
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java25
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java8
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java94
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java59
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/StorageController.java7
-rw-r--r--apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java6
-rw-r--r--cmds/screencap/screencap.cpp1
-rw-r--r--core/api/current.txt30
-rw-r--r--core/api/system-current.txt15
-rw-r--r--core/api/test-current.txt1
-rw-r--r--core/java/android/app/ActivityThread.java8
-rw-r--r--core/java/android/app/AppOpsManager.java20
-rw-r--r--core/java/android/app/time/ExternalTimeSuggestion.java69
-rw-r--r--core/java/android/app/time/TimeManager.java23
-rw-r--r--core/java/android/app/timedetector/TimeDetector.java9
-rw-r--r--core/java/android/app/timedetector/TimeDetectorImpl.java13
-rw-r--r--core/java/android/content/pm/ApplicationInfo.java6
-rw-r--r--core/java/android/content/pm/dex/DexMetadataHelper.java16
-rw-r--r--core/java/android/hardware/SystemSensorManager.java5
-rw-r--r--core/java/android/hardware/display/DeviceProductInfo.java99
-rw-r--r--core/java/android/os/PowerManager.java5
-rw-r--r--core/java/android/os/Process.java6
-rw-r--r--core/java/android/os/storage/StorageManager.java1
-rw-r--r--core/java/android/provider/Settings.java23
-rw-r--r--core/java/android/view/Display.java13
-rw-r--r--core/java/android/view/InsetsState.java61
-rw-r--r--core/java/android/view/RoundedCorners.java2
-rw-r--r--core/java/android/view/SurfaceControl.java148
-rw-r--r--core/java/android/view/SurfaceControlViewHost.java22
-rw-r--r--core/java/android/view/SurfaceView.java8
-rw-r--r--core/java/android/view/autofill/AutofillManager.java5
-rw-r--r--core/java/android/widget/AbsListView.java194
-rw-r--r--core/java/android/widget/RemoteViews.java142
-rw-r--r--core/java/com/android/internal/app/IAppOpsNotedCallback.aidl2
-rw-r--r--core/java/com/android/internal/app/IAppOpsStartedCallback.aidl2
-rw-r--r--core/java/com/android/internal/listeners/ListenerTransportManager.java56
-rw-r--r--core/java/com/android/internal/os/KernelCpuBpfTracking.java70
-rw-r--r--core/java/com/android/internal/os/KernelCpuTotalBpfMapReader.java26
-rw-r--r--core/java/com/android/internal/os/KernelCpuUidBpfMapReader.java11
-rw-r--r--core/jni/android_hardware_SensorManager.cpp38
-rw-r--r--core/jni/android_media_AudioTrack.cpp25
-rw-r--r--core/jni/android_view_SurfaceControl.cpp272
-rw-r--r--core/jni/com_android_internal_os_KernelCpuBpfTracking.cpp40
-rw-r--r--core/jni/com_android_internal_os_KernelCpuTotalBpfMapReader.cpp32
-rw-r--r--core/jni/com_android_internal_os_KernelCpuUidBpfMapReader.cpp26
-rw-r--r--core/res/AndroidManifest.xml7
-rw-r--r--core/res/res/drawable/toast_frame.xml5
-rw-r--r--core/res/res/layout/transient_notification.xml33
-rw-r--r--core/res/res/values-af/strings.xml8
-rw-r--r--core/res/res/values-am/strings.xml8
-rw-r--r--core/res/res/values-ar/strings.xml8
-rw-r--r--core/res/res/values-as/strings.xml7
-rw-r--r--core/res/res/values-az/strings.xml8
-rw-r--r--core/res/res/values-b+sr+Latn/strings.xml7
-rw-r--r--core/res/res/values-be/strings.xml8
-rw-r--r--core/res/res/values-bg/strings.xml7
-rw-r--r--core/res/res/values-bn/strings.xml8
-rw-r--r--core/res/res/values-bs/strings.xml7
-rw-r--r--core/res/res/values-ca/strings.xml7
-rw-r--r--core/res/res/values-cs/strings.xml8
-rw-r--r--core/res/res/values-da/strings.xml8
-rw-r--r--core/res/res/values-de/strings.xml7
-rw-r--r--core/res/res/values-el/strings.xml8
-rw-r--r--core/res/res/values-en-rAU/strings.xml1
-rw-r--r--core/res/res/values-en-rCA/strings.xml1
-rw-r--r--core/res/res/values-en-rGB/strings.xml1
-rw-r--r--core/res/res/values-en-rIN/strings.xml1
-rw-r--r--core/res/res/values-en-rXC/strings.xml1
-rw-r--r--core/res/res/values-es-rUS/strings.xml2
-rw-r--r--core/res/res/values-es/strings.xml8
-rw-r--r--core/res/res/values-et/strings.xml8
-rw-r--r--core/res/res/values-eu/strings.xml27
-rw-r--r--core/res/res/values-fa/strings.xml8
-rw-r--r--core/res/res/values-fi/strings.xml8
-rw-r--r--core/res/res/values-fr-rCA/strings.xml2
-rw-r--r--core/res/res/values-fr/strings.xml8
-rw-r--r--core/res/res/values-gl/strings.xml8
-rw-r--r--core/res/res/values-gu/strings.xml8
-rw-r--r--core/res/res/values-hi/strings.xml7
-rw-r--r--core/res/res/values-hr/strings.xml7
-rw-r--r--core/res/res/values-hu/strings.xml8
-rw-r--r--core/res/res/values-hy/strings.xml8
-rw-r--r--core/res/res/values-in/strings.xml8
-rw-r--r--core/res/res/values-is/strings.xml8
-rw-r--r--core/res/res/values-it/strings.xml8
-rw-r--r--core/res/res/values-iw/strings.xml8
-rw-r--r--core/res/res/values-ja/strings.xml1
-rw-r--r--core/res/res/values-ka/strings.xml2
-rw-r--r--core/res/res/values-kk/strings.xml8
-rw-r--r--core/res/res/values-km/strings.xml7
-rw-r--r--core/res/res/values-kn/strings.xml8
-rw-r--r--core/res/res/values-ko/strings.xml8
-rw-r--r--core/res/res/values-ky/strings.xml8
-rw-r--r--core/res/res/values-land/dimens.xml1
-rw-r--r--core/res/res/values-lo/strings.xml1
-rw-r--r--core/res/res/values-lt/strings.xml8
-rw-r--r--core/res/res/values-lv/strings.xml8
-rw-r--r--core/res/res/values-mk/strings.xml8
-rw-r--r--core/res/res/values-ml/strings.xml2
-rw-r--r--core/res/res/values-mn/strings.xml2
-rw-r--r--core/res/res/values-mr/strings.xml2
-rw-r--r--core/res/res/values-ms/strings.xml7
-rw-r--r--core/res/res/values-my/strings.xml11
-rw-r--r--core/res/res/values-nb/strings.xml8
-rw-r--r--core/res/res/values-ne/strings.xml2
-rw-r--r--core/res/res/values-nl/strings.xml7
-rw-r--r--core/res/res/values-or/strings.xml8
-rw-r--r--core/res/res/values-pa/strings.xml2
-rw-r--r--core/res/res/values-pl/strings.xml8
-rw-r--r--core/res/res/values-pt-rBR/strings.xml1
-rw-r--r--core/res/res/values-pt-rPT/strings.xml8
-rw-r--r--core/res/res/values-pt/strings.xml2
-rw-r--r--core/res/res/values-ro/strings.xml7
-rw-r--r--core/res/res/values-ru/strings.xml8
-rw-r--r--core/res/res/values-si/strings.xml1
-rw-r--r--core/res/res/values-sk/strings.xml8
-rw-r--r--core/res/res/values-sl/strings.xml7
-rw-r--r--core/res/res/values-sq/strings.xml2
-rw-r--r--core/res/res/values-sr/strings.xml7
-rw-r--r--core/res/res/values-sv/strings.xml8
-rw-r--r--core/res/res/values-sw/strings.xml1
-rw-r--r--core/res/res/values-ta/strings.xml7
-rw-r--r--core/res/res/values-te/strings.xml1
-rw-r--r--core/res/res/values-th/strings.xml7
-rw-r--r--core/res/res/values-tl/strings.xml2
-rw-r--r--core/res/res/values-tr/strings.xml2
-rw-r--r--core/res/res/values-uk/strings.xml8
-rw-r--r--core/res/res/values-ur/strings.xml7
-rw-r--r--core/res/res/values-uz/strings.xml8
-rw-r--r--core/res/res/values-vi/strings.xml8
-rw-r--r--core/res/res/values-zh-rCN/strings.xml7
-rw-r--r--core/res/res/values-zh-rHK/strings.xml7
-rw-r--r--core/res/res/values-zh-rTW/strings.xml7
-rw-r--r--core/res/res/values-zu/strings.xml8
-rw-r--r--core/res/res/values/dimens.xml8
-rw-r--r--core/res/res/values/styles.xml3
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/tests/coretests/src/android/app/time/ExternalTimeSuggestionTest.java15
-rw-r--r--data/etc/car/com.android.car.bugreport.xml1
-rw-r--r--data/etc/services.core.protolog.json6
-rw-r--r--graphics/java/android/graphics/BlurShader.java89
-rw-r--r--graphics/java/android/graphics/RenderNode.java20
-rw-r--r--libs/WindowManager/Shell/res/layout/size_compat_mode_hint.xml73
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipUiEventLogger.java11
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java19
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatHintPopup.java71
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatRestartButton.java87
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java16
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java149
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIWindowManager.java33
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt12
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenDockActivity.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenLaunchToSide.kt5
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenNonResizableNotDock.kt11
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottom.kt12
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitPrimarySplitScreenShowSecondaryFullscreen.kt14
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncher.kt5
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenTransition.kt32
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableDismissInLegacySplitScreen.kt14
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableLaunchInLegacySplitScreen.kt8
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreen.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt2
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt5
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt5
-rw-r--r--libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt2
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatHintPopupTest.java85
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatRestartButtonTest.java34
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUILayoutTest.java77
-rw-r--r--libs/hwui/DamageAccumulator.cpp15
-rw-r--r--libs/hwui/DamageAccumulator.h3
-rw-r--r--libs/hwui/JankTracker.cpp1
-rw-r--r--libs/hwui/RecordingCanvas.cpp21
-rw-r--r--libs/hwui/RenderNode.cpp6
-rw-r--r--libs/hwui/RenderProperties.cpp1
-rw-r--r--libs/hwui/TreeInfo.h2
-rw-r--r--libs/hwui/hwui/Canvas.cpp3
-rw-r--r--libs/hwui/hwui/Canvas.h8
-rw-r--r--libs/hwui/jni/android_graphics_RenderNode.cpp37
-rw-r--r--libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp31
-rw-r--r--libs/hwui/pipeline/skia/SkiaRecordingCanvas.h17
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp5
-rw-r--r--libs/hwui/tests/common/TestContext.cpp8
-rw-r--r--libs/hwui/tests/common/TestContext.h4
-rw-r--r--libs/input/MouseCursorController.h1
-rw-r--r--libs/input/PointerController.h1
-rw-r--r--libs/input/PointerControllerContext.h1
-rw-r--r--location/java/android/location/GnssMeasurement.java11
-rw-r--r--location/java/android/location/GnssStatus.java7
-rw-r--r--location/java/android/location/LocationManager.java51
-rw-r--r--media/java/android/media/AudioDeviceInfo.java22
-rw-r--r--media/java/android/media/AudioManager.java71
-rw-r--r--media/java/android/media/AudioTrack.java38
-rwxr-xr-xmedia/java/android/media/IAudioService.aidl4
-rw-r--r--media/java/android/media/PlayerBase.java2
-rw-r--r--media/java/android/media/tv/tuner/Tuner.java10
-rw-r--r--media/java/android/media/tv/tuner/filter/DownloadEvent.java2
-rw-r--r--media/java/android/media/tv/tuner/filter/Filter.java8
-rw-r--r--media/java/android/media/tv/tuner/filter/MediaEvent.java2
-rw-r--r--media/java/android/media/tv/tuner/filter/MmtpRecordEvent.java2
-rw-r--r--media/java/android/media/tv/tuner/filter/PesEvent.java2
-rw-r--r--media/jni/android_media_MediaDrm.cpp2
-rw-r--r--media/jni/tuner/DemuxClient.cpp2
-rw-r--r--media/jni/tuner/FilterClient.h3
-rw-r--r--media/jni/tuner/FrontendClient.cpp15
-rw-r--r--media/jni/tuner/FrontendClient.h3
-rw-r--r--media/jni/tuner/LnbClient.cpp9
-rw-r--r--media/jni/tuner/LnbClient.h3
-rw-r--r--media/jni/tuner/TunerClient.cpp2
-rw-r--r--native/android/surface_control.cpp12
-rw-r--r--packages/SettingsLib/res/values/strings.xml3
-rw-r--r--packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java5
-rw-r--r--packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java1
-rw-r--r--packages/Shell/AndroidManifest.xml1
-rw-r--r--packages/SystemUI/AndroidManifest.xml5
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_bouncer.xml2
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml4
-rw-r--r--packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml5
-rw-r--r--packages/SystemUI/res-keyguard/values-sw600dp-land/bools.xml (renamed from packages/SystemUI/res/drawable/toast_background.xml)9
-rw-r--r--packages/SystemUI/res-keyguard/values/config.xml1
-rw-r--r--packages/SystemUI/res-keyguard/values/dimens.xml13
-rw-r--r--packages/SystemUI/res-keyguard/values/styles.xml2
-rw-r--r--packages/SystemUI/res/layout/status_bar_expanded.xml2
-rw-r--r--packages/SystemUI/res/layout/text_toast.xml30
-rw-r--r--packages/SystemUI/res/values-land/dimens.xml2
-rw-r--r--packages/SystemUI/res/values/dimens.xml7
-rw-r--r--packages/SystemUI/res/values/strings.xml3
-rw-r--r--packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java7
-rw-r--r--packages/SystemUI/src/com/android/keyguard/DisabledUdfpsController.java26
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java7
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java18
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java13
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java223
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java1
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java9
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java18
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimation.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationKeyguard.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/doze/DozeUi.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt20
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java201
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java186
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java99
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerService.java81
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java52
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java96
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java31
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java9
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/glwallpaper/EglHelperTest.java1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/glwallpaper/ImageWallpaperRendererTest.java2
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt131
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java52
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java35
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java35
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java149
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeTunerService.java8
-rw-r--r--services/core/java/com/android/server/SensorPrivacyService.java15
-rw-r--r--services/core/java/com/android/server/am/ActiveServices.java6
-rw-r--r--services/core/java/com/android/server/am/OomAdjuster.java129
-rw-r--r--services/core/java/com/android/server/appop/AppOpsService.java46
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java10
-rw-r--r--services/core/java/com/android/server/audio/SoundEffectsHelper.java30
-rw-r--r--services/core/java/com/android/server/display/ColorFade.java2
-rw-r--r--services/core/java/com/android/server/display/DisplayDeviceInfo.java2
-rw-r--r--services/core/java/com/android/server/display/LocalDisplayAdapter.java180
-rw-r--r--services/core/java/com/android/server/location/LocationManagerService.java17
-rw-r--r--services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java89
-rw-r--r--services/core/java/com/android/server/location/contexthub/ContextHubService.java4
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java87
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java111
-rw-r--r--services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java3
-rw-r--r--services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java42
-rw-r--r--services/core/java/com/android/server/pm/verify/domain/DomainVerificationShell.java8
-rw-r--r--services/core/java/com/android/server/power/FaceDownDetector.java456
-rw-r--r--services/core/java/com/android/server/power/Notifier.java6
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java56
-rw-r--r--services/core/java/com/android/server/rotationresolver/RotationResolverManagerPerUserService.java44
-rw-r--r--services/core/java/com/android/server/rotationresolver/RotationResolverShellCommand.java39
-rw-r--r--services/core/java/com/android/server/stats/pull/StatsPullAtomService.java116
-rw-r--r--services/core/java/com/android/server/utils/WatchedLongSparseArray.java418
-rw-r--r--services/core/java/com/android/server/wm/ActivityClientController.java5
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java14
-rw-r--r--services/core/java/com/android/server/wm/ActivityTaskSupervisor.java13
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java43
-rw-r--r--services/core/java/com/android/server/wm/DisplayFrames.java25
-rw-r--r--services/core/java/com/android/server/wm/InsetsStateController.java73
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java38
-rw-r--r--services/core/jni/Android.bp2
-rw-r--r--services/core/jni/com_android_server_SystemServer.cpp35
-rw-r--r--services/incremental/Android.bp5
-rw-r--r--services/incremental/IncrementalService.cpp68
-rw-r--r--services/incremental/ServiceWrappers.cpp22
-rw-r--r--services/incremental/ServiceWrappers.h15
-rw-r--r--services/incremental/TEST_MAPPING32
-rw-r--r--services/incremental/test/IncrementalServiceTest.cpp18
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java162
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java134
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java221
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java5
-rw-r--r--services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java9
-rw-r--r--services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java9
-rw-r--r--services/tests/servicestests/src/com/android/server/power/FaceDownDetectorTest.java165
-rw-r--r--services/tests/servicestests/src/com/android/server/power/NotifierTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java5
-rw-r--r--services/tests/servicestests/src/com/android/server/utils/WatcherTest.java163
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java91
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java15
-rw-r--r--telephony/java/android/telephony/ims/ImsCallProfile.java13
-rw-r--r--telephony/java/android/telephony/ims/RtpHeaderExtension.java15
-rw-r--r--telephony/java/android/telephony/ims/RtpHeaderExtensionType.java12
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl5
-rw-r--r--tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java147
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt2
-rw-r--r--tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt2
-rw-r--r--tests/HwAccelerationTest/AndroidManifest.xml9
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java77
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/StretchySurfaceViewActivity.java157
353 files changed, 6673 insertions, 2758 deletions
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index ac6eb3229a25..c5d3b7a726b9 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -53,6 +53,7 @@ import android.net.Uri;
import android.os.BatteryStats;
import android.os.BatteryStatsInternal;
import android.os.Binder;
+import android.os.Build;
import android.os.Handler;
import android.os.LimitExceededException;
import android.os.Looper;
@@ -151,6 +152,9 @@ public class JobSchedulerService extends com.android.server.SystemService
private static final boolean ENFORCE_MAX_JOBS = true;
/** The maximum number of jobs that we allow an unprivileged app to schedule */
private static final int MAX_JOBS_PER_APP = 100;
+ /** The number of the most recently completed jobs to keep track of for debugging purposes. */
+ private static final int NUM_COMPLETED_JOB_HISTORY =
+ Build.IS_USERDEBUG || Build.IS_ENG ? 25 : 0;
@VisibleForTesting
public static Clock sSystemClock = Clock.systemUTC();
@@ -297,6 +301,10 @@ public class JobSchedulerService extends com.android.server.SystemService
*/
boolean mReportedActive;
+ private int mLastCompletedJobIndex = 0;
+ private final JobStatus[] mLastCompletedJobs = new JobStatus[NUM_COMPLETED_JOB_HISTORY];
+ private final long[] mLastCompletedJobTimeElapsed = new long[NUM_COMPLETED_JOB_HISTORY];
+
/**
* A mapping of which uids are currently in the foreground to their effective priority.
*/
@@ -1752,6 +1760,10 @@ public class JobSchedulerService extends com.android.server.SystemService
Slog.d(TAG, "Completed " + jobStatus + ", reschedule=" + needsReschedule);
}
+ mLastCompletedJobs[mLastCompletedJobIndex] = jobStatus;
+ mLastCompletedJobTimeElapsed[mLastCompletedJobIndex] = sElapsedRealtimeClock.millis();
+ mLastCompletedJobIndex = (mLastCompletedJobIndex + 1) % NUM_COMPLETED_JOB_HISTORY;
+
// Intentionally not checking expedited job quota here. An app can't find out if it's run
// out of quota when it asks JS to reschedule an expedited job. Instead, the rescheduled
// EJ will just be demoted to a regular job if the app has no EJ quota left.
@@ -3298,6 +3310,37 @@ public class JobSchedulerService extends com.android.server.SystemService
}
}
pw.decreaseIndent();
+
+ pw.println();
+ boolean recentPrinted = false;
+ pw.println("Recently completed jobs:");
+ pw.increaseIndent();
+ for (int r = 1; r <= NUM_COMPLETED_JOB_HISTORY; ++r) {
+ // Print most recent first
+ final int idx = (mLastCompletedJobIndex + NUM_COMPLETED_JOB_HISTORY - r)
+ % NUM_COMPLETED_JOB_HISTORY;
+ final JobStatus job = mLastCompletedJobs[idx];
+ if (job != null) {
+ if (!predicate.test(job)) {
+ continue;
+ }
+ recentPrinted = true;
+ TimeUtils.formatDuration(mLastCompletedJobTimeElapsed[idx], nowElapsed, pw);
+ pw.println();
+ // Double indent for readability
+ pw.increaseIndent();
+ pw.increaseIndent();
+ job.dump(pw, true, nowElapsed);
+ pw.decreaseIndent();
+ pw.decreaseIndent();
+ }
+ }
+ if (!recentPrinted) {
+ pw.println("None");
+ }
+ pw.decreaseIndent();
+ pw.println();
+
if (filterUid == -1) {
pw.println();
pw.print("mReadyToRock="); pw.println(mReadyToRock);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
index 58396eb69d14..a230b23f03a4 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/BackgroundJobsController.java
@@ -17,6 +17,7 @@
package com.android.server.job.controllers;
import static com.android.server.job.JobSchedulerService.NEVER_INDEX;
+import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -59,6 +60,8 @@ public final class BackgroundJobsController extends StateController {
private final AppStateTrackerImpl mAppStateTracker;
+ private final UpdateJobFunctor mUpdateJobFunctor = new UpdateJobFunctor();
+
public BackgroundJobsController(JobSchedulerService service) {
super(service);
@@ -69,7 +72,7 @@ public final class BackgroundJobsController extends StateController {
@Override
public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
- updateSingleJobRestrictionLocked(jobStatus, UNKNOWN);
+ updateSingleJobRestrictionLocked(jobStatus, sElapsedRealtimeClock.millis(), UNKNOWN);
}
@Override
@@ -79,7 +82,7 @@ public final class BackgroundJobsController extends StateController {
@Override
public void evaluateStateLocked(JobStatus jobStatus) {
- updateSingleJobRestrictionLocked(jobStatus, UNKNOWN);
+ updateSingleJobRestrictionLocked(jobStatus, sElapsedRealtimeClock.millis(), UNKNOWN);
}
@Override
@@ -163,33 +166,34 @@ public final class BackgroundJobsController extends StateController {
}
private void updateJobRestrictionsLocked(int filterUid, int newActiveState) {
- final UpdateJobFunctor updateTrackedJobs = new UpdateJobFunctor(newActiveState);
+ mUpdateJobFunctor.prepare(newActiveState);
final long start = DEBUG ? SystemClock.elapsedRealtimeNanos() : 0;
final JobStore store = mService.getJobStore();
if (filterUid > 0) {
- store.forEachJobForSourceUid(filterUid, updateTrackedJobs);
+ store.forEachJobForSourceUid(filterUid, mUpdateJobFunctor);
} else {
- store.forEachJob(updateTrackedJobs);
+ store.forEachJob(mUpdateJobFunctor);
}
final long time = DEBUG ? (SystemClock.elapsedRealtimeNanos() - start) : 0;
if (DEBUG) {
Slog.d(TAG, String.format(
"Job status updated: %d/%d checked/total jobs, %d us",
- updateTrackedJobs.mCheckedCount,
- updateTrackedJobs.mTotalCount,
+ mUpdateJobFunctor.mCheckedCount,
+ mUpdateJobFunctor.mTotalCount,
(time / 1000)
- ));
+ ));
}
- if (updateTrackedJobs.mChanged) {
+ if (mUpdateJobFunctor.mChanged) {
mStateChangedListener.onControllerStateChanged();
}
}
- boolean updateSingleJobRestrictionLocked(JobStatus jobStatus, int activeState) {
+ boolean updateSingleJobRestrictionLocked(JobStatus jobStatus, final long nowElapsed,
+ int activeState) {
final int uid = jobStatus.getSourceUid();
final String packageName = jobStatus.getSourcePackageName();
@@ -205,26 +209,32 @@ public final class BackgroundJobsController extends StateController {
if (isActive && jobStatus.getStandbyBucket() == NEVER_INDEX) {
jobStatus.maybeLogBucketMismatch();
}
- boolean didChange = jobStatus.setBackgroundNotRestrictedConstraintSatisfied(canRun);
+ boolean didChange =
+ jobStatus.setBackgroundNotRestrictedConstraintSatisfied(nowElapsed, canRun);
didChange |= jobStatus.setUidActive(isActive);
return didChange;
}
private final class UpdateJobFunctor implements Consumer<JobStatus> {
- final int activeState;
+ int mActiveState;
boolean mChanged = false;
int mTotalCount = 0;
int mCheckedCount = 0;
-
- public UpdateJobFunctor(int newActiveState) {
- activeState = newActiveState;
+ long mUpdateTimeElapsed = 0;
+
+ void prepare(int newActiveState) {
+ mActiveState = newActiveState;
+ mUpdateTimeElapsed = sElapsedRealtimeClock.millis();
+ mChanged = false;
+ mTotalCount = 0;
+ mCheckedCount = 0;
}
@Override
public void accept(JobStatus jobStatus) {
mTotalCount++;
mCheckedCount++;
- if (updateSingleJobRestrictionLocked(jobStatus, activeState)) {
+ if (updateSingleJobRestrictionLocked(jobStatus, mUpdateTimeElapsed, mActiveState)) {
mChanged = true;
}
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java
index 28269c89d13b..6fd094844cd6 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/BatteryController.java
@@ -65,10 +65,12 @@ public final class BatteryController extends RestrictingController {
@Override
public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
if (taskStatus.hasPowerConstraint()) {
+ final long nowElapsed = sElapsedRealtimeClock.millis();
mTrackedTasks.add(taskStatus);
taskStatus.setTrackingController(JobStatus.TRACKING_BATTERY);
- taskStatus.setChargingConstraintSatisfied(mChargeTracker.isOnStablePower());
- taskStatus.setBatteryNotLowConstraintSatisfied(mChargeTracker.isBatteryNotLow());
+ taskStatus.setChargingConstraintSatisfied(nowElapsed, mChargeTracker.isOnStablePower());
+ taskStatus.setBatteryNotLowConstraintSatisfied(
+ nowElapsed, mChargeTracker.isBatteryNotLow());
}
}
@@ -97,14 +99,15 @@ public final class BatteryController extends RestrictingController {
if (DEBUG) {
Slog.d(TAG, "maybeReportNewChargingStateLocked: " + stablePower);
}
+ final long nowElapsed = sElapsedRealtimeClock.millis();
boolean reportChange = false;
for (int i = mTrackedTasks.size() - 1; i >= 0; i--) {
final JobStatus ts = mTrackedTasks.valueAt(i);
- boolean previous = ts.setChargingConstraintSatisfied(stablePower);
+ boolean previous = ts.setChargingConstraintSatisfied(nowElapsed, stablePower);
if (previous != stablePower) {
reportChange = true;
}
- previous = ts.setBatteryNotLowConstraintSatisfied(batteryNotLow);
+ previous = ts.setBatteryNotLowConstraintSatisfied(nowElapsed, batteryNotLow);
if (previous != batteryNotLow) {
reportChange = true;
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
index 14484ff441ca..6e542f346f81 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java
@@ -20,6 +20,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
+import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
import android.annotation.Nullable;
import android.app.job.JobInfo;
@@ -461,11 +462,12 @@ public final class ConnectivityController extends RestrictingController implemen
final Network network = mConnManager.getActiveNetworkForUid(
jobStatus.getSourceUid(), jobStatus.shouldIgnoreNetworkBlocking());
final NetworkCapabilities capabilities = getNetworkCapabilities(network);
- return updateConstraintsSatisfied(jobStatus, network, capabilities);
+ return updateConstraintsSatisfied(jobStatus, sElapsedRealtimeClock.millis(),
+ network, capabilities);
}
- private boolean updateConstraintsSatisfied(JobStatus jobStatus, Network network,
- NetworkCapabilities capabilities) {
+ private boolean updateConstraintsSatisfied(JobStatus jobStatus, final long nowElapsed,
+ Network network, NetworkCapabilities capabilities) {
// TODO: consider matching against non-active networks
final boolean ignoreBlocked = jobStatus.shouldIgnoreNetworkBlocking();
@@ -476,7 +478,7 @@ public final class ConnectivityController extends RestrictingController implemen
final boolean satisfied = isSatisfied(jobStatus, network, capabilities, mConstants);
final boolean changed = jobStatus
- .setConnectivityConstraintSatisfied(connected && satisfied);
+ .setConnectivityConstraintSatisfied(nowElapsed, connected && satisfied);
// Pass along the evaluated network for job to use; prevents race
// conditions as default routes change over time, and opens the door to
@@ -530,6 +532,7 @@ public final class ConnectivityController extends RestrictingController implemen
NetworkCapabilities exemptedNetworkCapabilities = null;
boolean exemptedNetworkMatch = false;
+ final long nowElapsed = sElapsedRealtimeClock.millis();
boolean changed = false;
for (int i = jobs.size() - 1; i >= 0; i--) {
final JobStatus js = jobs.valueAt(i);
@@ -555,7 +558,7 @@ public final class ConnectivityController extends RestrictingController implemen
// job hasn't yet been evaluated against the currently
// active network; typically when we just lost a network.
if (match || !Objects.equals(js.network, net)) {
- changed |= updateConstraintsSatisfied(js, net, netCap);
+ changed |= updateConstraintsSatisfied(js, nowElapsed, net, netCap);
}
}
return changed;
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/ContentObserverController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/ContentObserverController.java
index 131a6d4f4791..8b0da3471781 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/ContentObserverController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/ContentObserverController.java
@@ -16,6 +16,8 @@
package com.android.server.job.controllers;
+import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+
import android.annotation.UserIdInt;
import android.app.job.JobInfo;
import android.database.ContentObserver;
@@ -74,6 +76,7 @@ public final class ContentObserverController extends StateController {
@Override
public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
if (taskStatus.hasContentTriggerConstraint()) {
+ final long nowElapsed = sElapsedRealtimeClock.millis();
if (taskStatus.contentObserverJobInstance == null) {
taskStatus.contentObserverJobInstance = new JobInstance(taskStatus);
}
@@ -110,7 +113,7 @@ public final class ContentObserverController extends StateController {
}
taskStatus.changedAuthorities = null;
taskStatus.changedUris = null;
- taskStatus.setContentTriggerConstraintSatisfied(havePendingUris);
+ taskStatus.setContentTriggerConstraintSatisfied(nowElapsed, havePendingUris);
}
if (lastJob != null && lastJob.contentObserverJobInstance != null) {
// And now we can detach the instance state from the last job.
@@ -295,7 +298,8 @@ public final class ContentObserverController extends StateController {
boolean reportChange = false;
synchronized (mLock) {
if (mTriggerPending) {
- if (mJobStatus.setContentTriggerConstraintSatisfied(true)) {
+ final long nowElapsed = sElapsedRealtimeClock.millis();
+ if (mJobStatus.setContentTriggerConstraintSatisfied(nowElapsed, true)) {
reportChange = true;
}
unscheduleLocked();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java
index 04b41646b48b..192f5e66255d 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java
@@ -16,6 +16,8 @@
package com.android.server.job.controllers;
+import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+
import android.app.job.JobInfo;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -104,8 +106,10 @@ public final class DeviceIdleJobsController extends StateController {
+ Arrays.toString(mPowerSaveTempWhitelistAppIds));
}
boolean changed = false;
+ final long nowElapsed = sElapsedRealtimeClock.millis();
for (int i = 0; i < mAllowInIdleJobs.size(); i++) {
- changed |= updateTaskStateLocked(mAllowInIdleJobs.valueAt(i));
+ changed |=
+ updateTaskStateLocked(mAllowInIdleJobs.valueAt(i), nowElapsed);
}
if (changed) {
mStateChangedListener.onControllerStateChanged();
@@ -147,6 +151,7 @@ public final class DeviceIdleJobsController extends StateController {
}
mDeviceIdleMode = enabled;
if (DEBUG) Slog.d(TAG, "mDeviceIdleMode=" + mDeviceIdleMode);
+ mDeviceIdleUpdateFunctor.prepare();
if (enabled) {
mHandler.removeMessages(PROCESS_BACKGROUND_JOBS);
mService.getJobStore().forEachJob(mDeviceIdleUpdateFunctor);
@@ -180,7 +185,7 @@ public final class DeviceIdleJobsController extends StateController {
Slog.d(TAG, "uid " + uid + " going " + (active ? "active" : "inactive"));
}
mForegroundUids.put(uid, active);
- mDeviceIdleUpdateFunctor.mChanged = false;
+ mDeviceIdleUpdateFunctor.prepare();
mService.getJobStore().forEachJobForSourceUid(uid, mDeviceIdleUpdateFunctor);
if (mDeviceIdleUpdateFunctor.mChanged) {
mStateChangedListener.onControllerStateChanged();
@@ -203,12 +208,12 @@ public final class DeviceIdleJobsController extends StateController {
UserHandle.getAppId(job.getSourceUid()));
}
- private boolean updateTaskStateLocked(JobStatus task) {
+ private boolean updateTaskStateLocked(JobStatus task, final long nowElapsed) {
final boolean allowInIdle = ((task.getFlags()&JobInfo.FLAG_IMPORTANT_WHILE_FOREGROUND) != 0)
&& (mForegroundUids.get(task.getSourceUid()) || isTempWhitelistedLocked(task));
final boolean whitelisted = isWhitelistedLocked(task);
final boolean enableTask = !mDeviceIdleMode || whitelisted || allowInIdle;
- return task.setDeviceNotDozingConstraintSatisfied(enableTask, whitelisted);
+ return task.setDeviceNotDozingConstraintSatisfied(nowElapsed, enableTask, whitelisted);
}
@Override
@@ -216,7 +221,7 @@ public final class DeviceIdleJobsController extends StateController {
if ((jobStatus.getFlags()&JobInfo.FLAG_IMPORTANT_WHILE_FOREGROUND) != 0) {
mAllowInIdleJobs.add(jobStatus);
}
- updateTaskStateLocked(jobStatus);
+ updateTaskStateLocked(jobStatus, sElapsedRealtimeClock.millis());
}
@Override
@@ -282,10 +287,16 @@ public final class DeviceIdleJobsController extends StateController {
final class DeviceIdleUpdateFunctor implements Consumer<JobStatus> {
boolean mChanged;
+ long mUpdateTimeElapsed = 0;
+
+ void prepare() {
+ mChanged = false;
+ mUpdateTimeElapsed = sElapsedRealtimeClock.millis();
+ }
@Override
public void accept(JobStatus jobStatus) {
- mChanged |= updateTaskStateLocked(jobStatus);
+ mChanged |= updateTaskStateLocked(jobStatus, mUpdateTimeElapsed);
}
}
@@ -300,7 +311,7 @@ public final class DeviceIdleJobsController extends StateController {
case PROCESS_BACKGROUND_JOBS:
// Just process all the jobs, the ones in foreground should already be running.
synchronized (mLock) {
- mDeviceIdleUpdateFunctor.mChanged = false;
+ mDeviceIdleUpdateFunctor.prepare();
mService.getJobStore().forEachJob(mDeviceIdleUpdateFunctor);
if (mDeviceIdleUpdateFunctor.mChanged) {
mStateChangedListener.onControllerStateChanged();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java
index 2fe827e338e9..e26a3c6962d5 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/IdleController.java
@@ -16,6 +16,8 @@
package com.android.server.job.controllers;
+import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
+
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.UserHandle;
@@ -58,9 +60,10 @@ public final class IdleController extends RestrictingController implements Idlen
@Override
public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
if (taskStatus.hasIdleConstraint()) {
+ final long nowElapsed = sElapsedRealtimeClock.millis();
mTrackedTasks.add(taskStatus);
taskStatus.setTrackingController(JobStatus.TRACKING_IDLE);
- taskStatus.setIdleConstraintSatisfied(mIdleTracker.isIdle());
+ taskStatus.setIdleConstraintSatisfied(nowElapsed, mIdleTracker.isIdle());
}
}
@@ -90,8 +93,9 @@ public final class IdleController extends RestrictingController implements Idlen
@Override
public void reportNewIdleState(boolean isIdle) {
synchronized (mLock) {
+ final long nowElapsed = sElapsedRealtimeClock.millis();
for (int i = mTrackedTasks.size()-1; i >= 0; i--) {
- mTrackedTasks.valueAt(i).setIdleConstraintSatisfied(isIdle);
+ mTrackedTasks.valueAt(i).setIdleConstraintSatisfied(nowElapsed, isIdle);
}
}
mStateChangedListener.onControllerStateChanged();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index 6917fb531ac4..5bdeb38a1424 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -73,6 +73,8 @@ public final class JobStatus {
private static final String TAG = "JobScheduler.JobStatus";
static final boolean DEBUG = JobSchedulerService.DEBUG;
+ private static final int NUM_CONSTRAINT_CHANGE_HISTORY = 10;
+
public static final long NO_LATEST_RUNTIME = Long.MAX_VALUE;
public static final long NO_EARLIEST_RUNTIME = 0L;
@@ -350,6 +352,10 @@ public final class JobStatus {
*/
private Pair<Long, Long> mPersistedUtcTimes;
+ private int mConstraintChangeHistoryIndex = 0;
+ private final long[] mConstraintUpdatedTimesElapsed = new long[NUM_CONSTRAINT_CHANGE_HISTORY];
+ private final int[] mConstraintStatusHistory = new int[NUM_CONSTRAINT_CHANGE_HISTORY];
+
/**
* For use only by ContentObserverController: state it is maintaining about content URIs
* being observed.
@@ -1090,28 +1096,28 @@ public final class JobStatus {
}
/** @return true if the constraint was changed, false otherwise. */
- boolean setChargingConstraintSatisfied(boolean state) {
- return setConstraintSatisfied(CONSTRAINT_CHARGING, state);
+ boolean setChargingConstraintSatisfied(final long nowElapsed, boolean state) {
+ return setConstraintSatisfied(CONSTRAINT_CHARGING, nowElapsed, state);
}
/** @return true if the constraint was changed, false otherwise. */
- boolean setBatteryNotLowConstraintSatisfied(boolean state) {
- return setConstraintSatisfied(CONSTRAINT_BATTERY_NOT_LOW, state);
+ boolean setBatteryNotLowConstraintSatisfied(final long nowElapsed, boolean state) {
+ return setConstraintSatisfied(CONSTRAINT_BATTERY_NOT_LOW, nowElapsed, state);
}
/** @return true if the constraint was changed, false otherwise. */
- boolean setStorageNotLowConstraintSatisfied(boolean state) {
- return setConstraintSatisfied(CONSTRAINT_STORAGE_NOT_LOW, state);
+ boolean setStorageNotLowConstraintSatisfied(final long nowElapsed, boolean state) {
+ return setConstraintSatisfied(CONSTRAINT_STORAGE_NOT_LOW, nowElapsed, state);
}
/** @return true if the constraint was changed, false otherwise. */
- boolean setTimingDelayConstraintSatisfied(boolean state) {
- return setConstraintSatisfied(CONSTRAINT_TIMING_DELAY, state);
+ boolean setTimingDelayConstraintSatisfied(final long nowElapsed, boolean state) {
+ return setConstraintSatisfied(CONSTRAINT_TIMING_DELAY, nowElapsed, state);
}
/** @return true if the constraint was changed, false otherwise. */
- boolean setDeadlineConstraintSatisfied(boolean state) {
- if (setConstraintSatisfied(CONSTRAINT_DEADLINE, state)) {
+ boolean setDeadlineConstraintSatisfied(final long nowElapsed, boolean state) {
+ if (setConstraintSatisfied(CONSTRAINT_DEADLINE, nowElapsed, state)) {
// The constraint was changed. Update the ready flag.
mReadyDeadlineSatisfied = !job.isPeriodic() && hasDeadlineConstraint() && state;
return true;
@@ -1120,24 +1126,25 @@ public final class JobStatus {
}
/** @return true if the constraint was changed, false otherwise. */
- boolean setIdleConstraintSatisfied(boolean state) {
- return setConstraintSatisfied(CONSTRAINT_IDLE, state);
+ boolean setIdleConstraintSatisfied(final long nowElapsed, boolean state) {
+ return setConstraintSatisfied(CONSTRAINT_IDLE, nowElapsed, state);
}
/** @return true if the constraint was changed, false otherwise. */
- boolean setConnectivityConstraintSatisfied(boolean state) {
- return setConstraintSatisfied(CONSTRAINT_CONNECTIVITY, state);
+ boolean setConnectivityConstraintSatisfied(final long nowElapsed, boolean state) {
+ return setConstraintSatisfied(CONSTRAINT_CONNECTIVITY, nowElapsed, state);
}
/** @return true if the constraint was changed, false otherwise. */
- boolean setContentTriggerConstraintSatisfied(boolean state) {
- return setConstraintSatisfied(CONSTRAINT_CONTENT_TRIGGER, state);
+ boolean setContentTriggerConstraintSatisfied(final long nowElapsed, boolean state) {
+ return setConstraintSatisfied(CONSTRAINT_CONTENT_TRIGGER, nowElapsed, state);
}
/** @return true if the constraint was changed, false otherwise. */
- boolean setDeviceNotDozingConstraintSatisfied(boolean state, boolean whitelisted) {
+ boolean setDeviceNotDozingConstraintSatisfied(final long nowElapsed,
+ boolean state, boolean whitelisted) {
dozeWhitelisted = whitelisted;
- if (setConstraintSatisfied(CONSTRAINT_DEVICE_NOT_DOZING, state)) {
+ if (setConstraintSatisfied(CONSTRAINT_DEVICE_NOT_DOZING, nowElapsed, state)) {
// The constraint was changed. Update the ready flag.
mReadyNotDozing = state || canRunInDoze();
return true;
@@ -1146,8 +1153,8 @@ public final class JobStatus {
}
/** @return true if the constraint was changed, false otherwise. */
- boolean setBackgroundNotRestrictedConstraintSatisfied(boolean state) {
- if (setConstraintSatisfied(CONSTRAINT_BACKGROUND_NOT_RESTRICTED, state)) {
+ boolean setBackgroundNotRestrictedConstraintSatisfied(final long nowElapsed, boolean state) {
+ if (setConstraintSatisfied(CONSTRAINT_BACKGROUND_NOT_RESTRICTED, nowElapsed, state)) {
// The constraint was changed. Update the ready flag.
mReadyNotRestrictedInBg = state;
return true;
@@ -1156,8 +1163,8 @@ public final class JobStatus {
}
/** @return true if the constraint was changed, false otherwise. */
- boolean setQuotaConstraintSatisfied(boolean state) {
- if (setConstraintSatisfied(CONSTRAINT_WITHIN_QUOTA, state)) {
+ boolean setQuotaConstraintSatisfied(final long nowElapsed, boolean state) {
+ if (setConstraintSatisfied(CONSTRAINT_WITHIN_QUOTA, nowElapsed, state)) {
// The constraint was changed. Update the ready flag.
mReadyWithinQuota = state;
return true;
@@ -1166,8 +1173,8 @@ public final class JobStatus {
}
/** @return true if the constraint was changed, false otherwise. */
- boolean setExpeditedJobQuotaConstraintSatisfied(boolean state) {
- if (setConstraintSatisfied(CONSTRAINT_WITHIN_EXPEDITED_QUOTA, state)) {
+ boolean setExpeditedJobQuotaConstraintSatisfied(final long nowElapsed, boolean state) {
+ if (setConstraintSatisfied(CONSTRAINT_WITHIN_EXPEDITED_QUOTA, nowElapsed, state)) {
// The constraint was changed. Update the ready flag.
mReadyWithinExpeditedQuota = state;
// DeviceIdleJobsController currently only tracks jobs with the WILL_BE_FOREGROUND flag.
@@ -1190,7 +1197,7 @@ public final class JobStatus {
}
/** @return true if the constraint was changed, false otherwise. */
- boolean setConstraintSatisfied(int constraint, boolean state) {
+ boolean setConstraintSatisfied(int constraint, final long nowElapsed, boolean state) {
boolean old = (satisfiedConstraints&constraint) != 0;
if (old == state) {
return false;
@@ -1212,6 +1219,12 @@ public final class JobStatus {
: FrameworkStatsLog
.SCHEDULED_JOB_CONSTRAINT_CHANGED__STATE__UNSATISFIED);
}
+
+ mConstraintUpdatedTimesElapsed[mConstraintChangeHistoryIndex] = nowElapsed;
+ mConstraintStatusHistory[mConstraintChangeHistoryIndex] = satisfiedConstraints;
+ mConstraintChangeHistoryIndex =
+ (mConstraintChangeHistoryIndex + 1) % NUM_CONSTRAINT_CHANGE_HISTORY;
+
return true;
}
@@ -1700,7 +1713,7 @@ public final class JobStatus {
}
// Dumpsys infrastructure
- public void dump(IndentingPrintWriter pw, boolean full, long elapsedRealtimeMillis) {
+ public void dump(IndentingPrintWriter pw, boolean full, long nowElapsed) {
UserHandle.formatUid(pw, callingUid);
pw.print(" tag="); pw.println(tag);
@@ -1830,6 +1843,22 @@ public final class JobStatus {
dumpConstraints(pw,
((requiredConstraints | CONSTRAINT_WITHIN_QUOTA) & ~satisfiedConstraints));
pw.println();
+
+ pw.println("Constraint history:");
+ pw.increaseIndent();
+ for (int h = 0; h < NUM_CONSTRAINT_CHANGE_HISTORY; ++h) {
+ final int idx = (h + mConstraintChangeHistoryIndex) % NUM_CONSTRAINT_CHANGE_HISTORY;
+ if (mConstraintUpdatedTimesElapsed[idx] == 0) {
+ continue;
+ }
+ TimeUtils.formatDuration(mConstraintUpdatedTimesElapsed[idx], nowElapsed, pw);
+ // dumpConstraints prepends with a space, so no need to add a space after the =
+ pw.print(" =");
+ dumpConstraints(pw, mConstraintStatusHistory[idx]);
+ pw.println();
+ }
+ pw.decreaseIndent();
+
if (dozeWhitelisted) {
pw.println("Doze whitelisted: true");
}
@@ -1910,26 +1939,25 @@ public final class JobStatus {
pw.increaseIndent();
if (whenStandbyDeferred != 0) {
pw.print("Deferred since: ");
- TimeUtils.formatDuration(whenStandbyDeferred, elapsedRealtimeMillis, pw);
+ TimeUtils.formatDuration(whenStandbyDeferred, nowElapsed, pw);
pw.println();
}
if (mFirstForceBatchedTimeElapsed != 0) {
pw.print("Time since first force batch attempt: ");
- TimeUtils.formatDuration(mFirstForceBatchedTimeElapsed, elapsedRealtimeMillis, pw);
+ TimeUtils.formatDuration(mFirstForceBatchedTimeElapsed, nowElapsed, pw);
pw.println();
}
pw.decreaseIndent();
pw.print("Enqueue time: ");
- TimeUtils.formatDuration(enqueueTime, elapsedRealtimeMillis, pw);
+ TimeUtils.formatDuration(enqueueTime, nowElapsed, pw);
pw.println();
pw.print("Run time: earliest=");
- formatRunTime(pw, earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME, elapsedRealtimeMillis);
+ formatRunTime(pw, earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME, nowElapsed);
pw.print(", latest=");
- formatRunTime(pw, latestRunTimeElapsedMillis, NO_LATEST_RUNTIME, elapsedRealtimeMillis);
+ formatRunTime(pw, latestRunTimeElapsedMillis, NO_LATEST_RUNTIME, nowElapsed);
pw.print(", original latest=");
- formatRunTime(pw, mOriginalLatestRunTimeElapsedMillis,
- NO_LATEST_RUNTIME, elapsedRealtimeMillis);
+ formatRunTime(pw, mOriginalLatestRunTimeElapsedMillis, NO_LATEST_RUNTIME, nowElapsed);
pw.println();
if (numFailures != 0) {
pw.print("Num failures: "); pw.println(numFailures);
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
index 2196b16e0846..824fa7fc1659 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java
@@ -626,6 +626,7 @@ public final class QuotaController extends StateController {
@Override
public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
+ final long nowElapsed = sElapsedRealtimeClock.millis();
final int userId = jobStatus.getSourceUserId();
final String pkgName = jobStatus.getSourcePackageName();
ArraySet<JobStatus> jobs = mTrackedJobs.get(userId, pkgName);
@@ -636,11 +637,11 @@ public final class QuotaController extends StateController {
jobs.add(jobStatus);
jobStatus.setTrackingController(JobStatus.TRACKING_QUOTA);
final boolean isWithinQuota = isWithinQuotaLocked(jobStatus);
- setConstraintSatisfied(jobStatus, isWithinQuota);
+ setConstraintSatisfied(jobStatus, nowElapsed, isWithinQuota);
final boolean outOfEJQuota;
if (jobStatus.isRequestedExpeditedJob()) {
final boolean isWithinEJQuota = isWithinEJQuotaLocked(jobStatus);
- setExpeditedConstraintSatisfied(jobStatus, isWithinEJQuota);
+ setExpeditedConstraintSatisfied(jobStatus, nowElapsed, isWithinEJQuota);
outOfEJQuota = !isWithinEJQuota;
} else {
outOfEJQuota = false;
@@ -1397,7 +1398,8 @@ public final class QuotaController extends StateController {
synchronized (mLock) {
final ShrinkableDebits quota = getEJQuotaLocked(userId, packageName);
quota.transactOnDebitsLocked(-credit);
- if (maybeUpdateConstraintForPkgLocked(userId, packageName)) {
+ if (maybeUpdateConstraintForPkgLocked(sElapsedRealtimeClock.millis(),
+ userId, packageName)) {
mStateChangedListener.onControllerStateChanged();
}
}
@@ -1499,11 +1501,12 @@ public final class QuotaController extends StateController {
private void maybeUpdateAllConstraintsLocked() {
boolean changed = false;
+ final long nowElapsed = sElapsedRealtimeClock.millis();
for (int u = 0; u < mTrackedJobs.numMaps(); ++u) {
final int userId = mTrackedJobs.keyAt(u);
for (int p = 0; p < mTrackedJobs.numElementsForKey(userId); ++p) {
final String packageName = mTrackedJobs.keyAt(u, p);
- changed |= maybeUpdateConstraintForPkgLocked(userId, packageName);
+ changed |= maybeUpdateConstraintForPkgLocked(nowElapsed, userId, packageName);
}
}
if (changed) {
@@ -1516,7 +1519,7 @@ public final class QuotaController extends StateController {
*
* @return true if at least one job had its bit changed
*/
- private boolean maybeUpdateConstraintForPkgLocked(final int userId,
+ private boolean maybeUpdateConstraintForPkgLocked(final long nowElapsed, final int userId,
@NonNull final String packageName) {
ArraySet<JobStatus> jobs = mTrackedJobs.get(userId, packageName);
if (jobs == null || jobs.size() == 0) {
@@ -1533,21 +1536,21 @@ public final class QuotaController extends StateController {
if (isTopStartedJobLocked(js)) {
// Job was started while the app was in the TOP state so we should allow it to
// finish.
- changed |= js.setQuotaConstraintSatisfied(true);
+ changed |= js.setQuotaConstraintSatisfied(nowElapsed, true);
} else if (realStandbyBucket != ACTIVE_INDEX
&& realStandbyBucket == js.getEffectiveStandbyBucket()) {
// An app in the ACTIVE bucket may be out of quota while the job could be in quota
// for some reason. Therefore, avoid setting the real value here and check each job
// individually.
- changed |= setConstraintSatisfied(js, realInQuota);
+ changed |= setConstraintSatisfied(js, nowElapsed, realInQuota);
} else {
// This job is somehow exempted. Need to determine its own quota status.
- changed |= setConstraintSatisfied(js, isWithinQuotaLocked(js));
+ changed |= setConstraintSatisfied(js, nowElapsed, isWithinQuotaLocked(js));
}
if (js.isRequestedExpeditedJob()) {
boolean isWithinEJQuota = isWithinEJQuotaLocked(js);
- changed |= setExpeditedConstraintSatisfied(js, isWithinEJQuota);
+ changed |= setExpeditedConstraintSatisfied(js, nowElapsed, isWithinEJQuota);
outOfEJQuota |= !isWithinEJQuota;
}
}
@@ -1566,14 +1569,21 @@ public final class QuotaController extends StateController {
private final SparseArrayMap<String, Integer> mToScheduleStartAlarms =
new SparseArrayMap<>();
public boolean wasJobChanged;
+ long mUpdateTimeElapsed = 0;
+
+ void prepare() {
+ mUpdateTimeElapsed = sElapsedRealtimeClock.millis();
+ }
@Override
public void accept(JobStatus jobStatus) {
- wasJobChanged |= setConstraintSatisfied(jobStatus, isWithinQuotaLocked(jobStatus));
+ wasJobChanged |= setConstraintSatisfied(
+ jobStatus, mUpdateTimeElapsed, isWithinQuotaLocked(jobStatus));
final boolean outOfEJQuota;
if (jobStatus.isRequestedExpeditedJob()) {
final boolean isWithinEJQuota = isWithinEJQuotaLocked(jobStatus);
- wasJobChanged |= setExpeditedConstraintSatisfied(jobStatus, isWithinEJQuota);
+ wasJobChanged |= setExpeditedConstraintSatisfied(
+ jobStatus, mUpdateTimeElapsed, isWithinEJQuota);
outOfEJQuota = !isWithinEJQuota;
} else {
outOfEJQuota = false;
@@ -1611,6 +1621,7 @@ public final class QuotaController extends StateController {
private final UidConstraintUpdater mUpdateUidConstraints = new UidConstraintUpdater();
private boolean maybeUpdateConstraintForUidLocked(final int uid) {
+ mUpdateUidConstraints.prepare();
mService.getJobStore().forEachJobForSourceUid(uid, mUpdateUidConstraints);
mUpdateUidConstraints.postProcess();
@@ -1716,21 +1727,22 @@ public final class QuotaController extends StateController {
mInQuotaAlarmListener.addAlarmLocked(userId, packageName, inQuotaTimeElapsed);
}
- private boolean setConstraintSatisfied(@NonNull JobStatus jobStatus, boolean isWithinQuota) {
+ private boolean setConstraintSatisfied(@NonNull JobStatus jobStatus, long nowElapsed,
+ boolean isWithinQuota) {
if (!isWithinQuota && jobStatus.getWhenStandbyDeferred() == 0) {
// Mark that the job is being deferred due to buckets.
- jobStatus.setWhenStandbyDeferred(sElapsedRealtimeClock.millis());
+ jobStatus.setWhenStandbyDeferred(nowElapsed);
}
- return jobStatus.setQuotaConstraintSatisfied(isWithinQuota);
+ return jobStatus.setQuotaConstraintSatisfied(nowElapsed, isWithinQuota);
}
/**
* If the satisfaction changes, this will tell connectivity & background jobs controller to
* also re-evaluate their state.
*/
- private boolean setExpeditedConstraintSatisfied(@NonNull JobStatus jobStatus,
+ private boolean setExpeditedConstraintSatisfied(@NonNull JobStatus jobStatus, long nowElapsed,
boolean isWithinQuota) {
- if (jobStatus.setExpeditedJobQuotaConstraintSatisfied(isWithinQuota)) {
+ if (jobStatus.setExpeditedJobQuotaConstraintSatisfied(nowElapsed, isWithinQuota)) {
mBackgroundJobsController.evaluateStateLocked(jobStatus);
mConnectivityController.evaluateStateLocked(jobStatus);
if (isWithinQuota && jobStatus.isReady()) {
@@ -2188,7 +2200,8 @@ public final class QuotaController extends StateController {
final ShrinkableDebits quota =
getEJQuotaLocked(mPkg.userId, mPkg.packageName);
quota.transactOnDebitsLocked(-mEJRewardTopAppMs * numTimeChunks);
- if (maybeUpdateConstraintForPkgLocked(mPkg.userId, mPkg.packageName)) {
+ if (maybeUpdateConstraintForPkgLocked(nowElapsed,
+ mPkg.userId, mPkg.packageName)) {
mStateChangedListener.onControllerStateChanged();
}
}
@@ -2292,7 +2305,8 @@ public final class QuotaController extends StateController {
if (timer != null && timer.isActive()) {
timer.rescheduleCutoff();
}
- if (maybeUpdateConstraintForPkgLocked(userId, packageName)) {
+ if (maybeUpdateConstraintForPkgLocked(sElapsedRealtimeClock.millis(),
+ userId, packageName)) {
mStateChangedListener.onControllerStateChanged();
}
}
@@ -2417,7 +2431,8 @@ public final class QuotaController extends StateController {
if (timeRemainingMs <= 50) {
// Less than 50 milliseconds left. Start process of shutting down jobs.
if (DEBUG) Slog.d(TAG, pkg + " has reached its quota.");
- if (maybeUpdateConstraintForPkgLocked(pkg.userId, pkg.packageName)) {
+ if (maybeUpdateConstraintForPkgLocked(sElapsedRealtimeClock.millis(),
+ pkg.userId, pkg.packageName)) {
mStateChangedListener.onControllerStateChanged();
}
} else {
@@ -2444,7 +2459,8 @@ public final class QuotaController extends StateController {
pkg.userId, pkg.packageName);
if (timeRemainingMs <= 0) {
if (DEBUG) Slog.d(TAG, pkg + " has reached its EJ quota.");
- if (maybeUpdateConstraintForPkgLocked(pkg.userId, pkg.packageName)) {
+ if (maybeUpdateConstraintForPkgLocked(sElapsedRealtimeClock.millis(),
+ pkg.userId, pkg.packageName)) {
mStateChangedListener.onControllerStateChanged();
}
} else {
@@ -2475,7 +2491,8 @@ public final class QuotaController extends StateController {
if (DEBUG) {
Slog.d(TAG, "Checking pkg " + string(userId, packageName));
}
- if (maybeUpdateConstraintForPkgLocked(userId, packageName)) {
+ if (maybeUpdateConstraintForPkgLocked(sElapsedRealtimeClock.millis(),
+ userId, packageName)) {
mStateChangedListener.onControllerStateChanged();
}
break;
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/StorageController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/StorageController.java
index 0731918d83a1..867891363912 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/StorageController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/StorageController.java
@@ -61,9 +61,11 @@ public final class StorageController extends StateController {
@Override
public void maybeStartTrackingJobLocked(JobStatus taskStatus, JobStatus lastJob) {
if (taskStatus.hasStorageNotLowConstraint()) {
+ final long nowElapsed = sElapsedRealtimeClock.millis();
mTrackedTasks.add(taskStatus);
taskStatus.setTrackingController(JobStatus.TRACKING_STORAGE);
- taskStatus.setStorageNotLowConstraintSatisfied(mStorageTracker.isStorageNotLow());
+ taskStatus.setStorageNotLowConstraintSatisfied(
+ nowElapsed, mStorageTracker.isStorageNotLow());
}
}
@@ -76,12 +78,13 @@ public final class StorageController extends StateController {
}
private void maybeReportNewStorageState() {
+ final long nowElapsed = sElapsedRealtimeClock.millis();
final boolean storageNotLow = mStorageTracker.isStorageNotLow();
boolean reportChange = false;
synchronized (mLock) {
for (int i = mTrackedTasks.size() - 1; i >= 0; i--) {
final JobStatus ts = mTrackedTasks.valueAt(i);
- reportChange |= ts.setStorageNotLowConstraintSatisfied(storageNotLow);
+ reportChange |= ts.setStorageNotLowConstraintSatisfied(nowElapsed, storageNotLow);
}
}
if (storageNotLow) {
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
index ede14ec06c71..e8ebfb53fde8 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/TimeController.java
@@ -258,9 +258,9 @@ public final class TimeController extends StateController {
if (jobDeadline <= nowElapsedMillis) {
if (job.hasTimingDelayConstraint()) {
- job.setTimingDelayConstraintSatisfied(true);
+ job.setTimingDelayConstraintSatisfied(nowElapsedMillis, true);
}
- job.setDeadlineConstraintSatisfied(true);
+ job.setDeadlineConstraintSatisfied(nowElapsedMillis, true);
return true;
}
return false;
@@ -332,7 +332,7 @@ public final class TimeController extends StateController {
private boolean evaluateTimingDelayConstraint(JobStatus job, long nowElapsedMillis) {
final long jobDelayTime = job.getEarliestRunTime();
if (jobDelayTime <= nowElapsedMillis) {
- job.setTimingDelayConstraintSatisfied(true);
+ job.setTimingDelayConstraintSatisfied(nowElapsedMillis, true);
return true;
}
return false;
diff --git a/cmds/screencap/screencap.cpp b/cmds/screencap/screencap.cpp
index 5c08704a6623..d4da5e554591 100644
--- a/cmds/screencap/screencap.cpp
+++ b/cmds/screencap/screencap.cpp
@@ -34,7 +34,6 @@
#include <gui/SurfaceComposerClient.h>
#include <gui/SyncScreenCaptureListener.h>
-#include <ui/DisplayInfo.h>
#include <ui/GraphicTypes.h>
#include <ui/PixelFormat.h>
diff --git a/core/api/current.txt b/core/api/current.txt
index d6c783dc71b0..b0375b69553d 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -11786,6 +11786,8 @@ package android.content.pm {
field public int category;
field public String className;
field public int compatibleWidthLimitDp;
+ field public int compileSdkVersion;
+ field @Nullable public String compileSdkVersionCodename;
field public String dataDir;
field public int descriptionRes;
field public String deviceProtectedDataDir;
@@ -14615,11 +14617,6 @@ package android.graphics {
enum_constant public static final android.graphics.BlurMaskFilter.Blur SOLID;
}
- public final class BlurShader extends android.graphics.Shader {
- ctor public BlurShader(float, float, @Nullable android.graphics.Shader);
- ctor public BlurShader(float, float, @Nullable android.graphics.Shader, @NonNull android.graphics.Shader.TileMode);
- }
-
public class Camera {
ctor public Camera();
method public void applyToCanvas(android.graphics.Canvas);
@@ -18537,6 +18534,23 @@ package android.hardware.camera2.params {
package android.hardware.display {
+ public final class DeviceProductInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method public int getConnectionToSinkType();
+ method public int getManufactureWeek();
+ method public int getManufactureYear();
+ method @NonNull public String getManufacturerPnpId();
+ method public int getModelYear();
+ method @Nullable public String getName();
+ method @NonNull public String getProductId();
+ method public void writeToParcel(@NonNull android.os.Parcel, int);
+ field public static final int CONNECTION_TO_SINK_BUILT_IN = 1; // 0x1
+ field public static final int CONNECTION_TO_SINK_DIRECT = 2; // 0x2
+ field public static final int CONNECTION_TO_SINK_TRANSITIVE = 3; // 0x3
+ field public static final int CONNECTION_TO_SINK_UNKNOWN = 0; // 0x0
+ field @NonNull public static final android.os.Parcelable.Creator<android.hardware.display.DeviceProductInfo> CREATOR;
+ }
+
public final class DisplayManager {
method public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, int, int, int, @Nullable android.view.Surface, int);
method public android.hardware.display.VirtualDisplay createVirtualDisplay(@NonNull String, int, int, int, @Nullable android.view.Surface, int, @Nullable android.hardware.display.VirtualDisplay.Callback, @Nullable android.os.Handler);
@@ -42465,7 +42479,7 @@ package android.telephony {
method @Deprecated public int getPhoneCount();
method public int getPhoneType();
method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PHONE_STATE}) public int getPreferredOpportunisticDataSubscription();
- method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.telephony.ServiceState getServiceState();
+ method @Nullable @RequiresPermission(allOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.ACCESS_COARSE_LOCATION}) public android.telephony.ServiceState getServiceState();
method @Nullable public android.telephony.SignalStrength getSignalStrength();
method public int getSimCarrierId();
method @Nullable public CharSequence getSimCarrierIdName();
@@ -46613,6 +46627,7 @@ package android.view {
method public long getAppVsyncOffsetNanos();
method public void getCurrentSizeRange(android.graphics.Point, android.graphics.Point);
method @Nullable public android.view.DisplayCutout getCutout();
+ method @Nullable public android.hardware.display.DeviceProductInfo getDeviceProductInfo();
method public int getDisplayId();
method public int getFlags();
method public android.view.Display.HdrCapabilities getHdrCapabilities();
@@ -55055,6 +55070,8 @@ package android.widget {
method public void setChronometer(@IdRes int, long, String, boolean);
method public void setChronometerCountDown(@IdRes int, boolean);
method public void setColor(@IdRes int, @NonNull String, @ColorRes int);
+ method public void setColorInt(@IdRes int, @NonNull String, @ColorInt int, @ColorInt int);
+ method public void setColorStateList(@IdRes int, @NonNull String, @Nullable android.content.res.ColorStateList, @Nullable android.content.res.ColorStateList);
method public void setColorStateList(@IdRes int, @NonNull String, @ColorRes int);
method public void setCompoundButtonChecked(@IdRes int, boolean);
method public void setContentDescription(@IdRes int, CharSequence);
@@ -55065,6 +55082,7 @@ package android.widget {
method public void setFloatDimen(@IdRes int, @NonNull String, @DimenRes int);
method public void setFloatDimen(@IdRes int, @NonNull String, float, int);
method public void setIcon(@IdRes int, String, android.graphics.drawable.Icon);
+ method public void setIcon(@IdRes int, @NonNull String, @Nullable android.graphics.drawable.Icon, @Nullable android.graphics.drawable.Icon);
method public void setImageViewBitmap(@IdRes int, android.graphics.Bitmap);
method public void setImageViewIcon(@IdRes int, android.graphics.drawable.Icon);
method public void setImageViewResource(@IdRes int, @DrawableRes int);
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 7b7518d05345..d79c11db9d09 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -5704,7 +5704,7 @@ package android.media.tv.tuner {
method public void updateResourcePriority(int, int);
field public static final int INVALID_AV_SYNC_ID = -1; // 0xffffffff
field public static final int INVALID_FILTER_ID = -1; // 0xffffffff
- field public static final long INVALID_FILTER_ID_64BIT = -1L; // 0xffffffffffffffffL
+ field public static final long INVALID_FILTER_ID_LONG = -1L; // 0xffffffffffffffffL
field public static final int INVALID_FIRST_MACROBLOCK_IN_SLICE = -1; // 0xffffffff
field public static final int INVALID_FRONTEND_ID = -1; // 0xffffffff
field public static final int INVALID_FRONTEND_SETTING_FREQUENCY = -1; // 0xffffffff
@@ -5885,7 +5885,7 @@ package android.media.tv.tuner.filter {
method public int getItemFragmentIndex();
method public int getItemId();
method public int getLastItemFragmentIndex();
- method public int getMpuSequenceNumber();
+ method @IntRange(from=0) public int getMpuSequenceNumber();
}
public class DownloadSettings extends android.media.tv.tuner.filter.Settings {
@@ -5903,7 +5903,7 @@ package android.media.tv.tuner.filter {
method public int configure(@NonNull android.media.tv.tuner.filter.FilterConfiguration);
method public int flush();
method public int getId();
- method public long getId64Bit();
+ method public long getIdLong();
method public int read(@NonNull byte[], long, long);
method public int setDataSource(@Nullable android.media.tv.tuner.filter.Filter);
method public int setMonitorEventMask(int);
@@ -5994,7 +5994,7 @@ package android.media.tv.tuner.filter {
method public long getDataLength();
method @Nullable public android.media.tv.tuner.filter.AudioDescriptor getExtraMetaData();
method @Nullable public android.media.MediaCodec.LinearBlock getLinearBlock();
- method public int getMpuSequenceNumber();
+ method @IntRange(from=0) public int getMpuSequenceNumber();
method public long getOffset();
method public long getPts();
method public int getStreamId();
@@ -6019,7 +6019,7 @@ package android.media.tv.tuner.filter {
public class MmtpRecordEvent extends android.media.tv.tuner.filter.FilterEvent {
method public long getDataLength();
method public int getFirstMacroblockInSlice();
- method public int getMpuSequenceNumber();
+ method @IntRange(from=0) public int getMpuSequenceNumber();
method public long getPts();
method public int getScHevcIndexMask();
method public int getTsIndexMask();
@@ -6027,7 +6027,7 @@ package android.media.tv.tuner.filter {
public class PesEvent extends android.media.tv.tuner.filter.FilterEvent {
method public int getDataLength();
- method public int getMpuSequenceNumber();
+ method @IntRange(from=0) public int getMpuSequenceNumber();
method public int getStreamId();
}
@@ -8580,7 +8580,7 @@ package android.os {
method @RequiresPermission(allOf={android.Manifest.permission.READ_DREAM_STATE, android.Manifest.permission.WRITE_DREAM_STATE}) public void dream(long);
method @RequiresPermission(android.Manifest.permission.DEVICE_POWER) public boolean forceSuspend();
method @NonNull public android.os.BatterySaverPolicyConfig getFullPowerSavePolicy();
- method @RequiresPermission(android.Manifest.permission.POWER_SAVER) public int getPowerSaveModeTrigger();
+ method public int getPowerSaveModeTrigger();
method @RequiresPermission(android.Manifest.permission.READ_DREAM_STATE) public boolean isAmbientDisplayAvailable();
method @RequiresPermission(android.Manifest.permission.READ_DREAM_STATE) public boolean isAmbientDisplaySuppressed();
method @RequiresPermission(android.Manifest.permission.READ_DREAM_STATE) public boolean isAmbientDisplaySuppressedForToken(@NonNull String);
@@ -12904,6 +12904,7 @@ package android.telephony.ims {
field public static final String EXTRA_EMERGENCY_CALL = "e_call";
field public static final String EXTRA_EXTENDING_TO_CONFERENCE_SUPPORTED = "android.telephony.ims.extra.EXTENDING_TO_CONFERENCE_SUPPORTED";
field public static final String EXTRA_FORWARDED_NUMBER = "android.telephony.ims.extra.FORWARDED_NUMBER";
+ field public static final String EXTRA_IS_BUSINESS_CALL = "android.telephony.ims.extra.IS_BUSINESS_CALL";
field public static final String EXTRA_IS_CALL_PULL = "CallPull";
field public static final String EXTRA_IS_CROSS_SIM_CALL = "android.telephony.ims.extra.IS_CROSS_SIM_CALL";
field public static final String EXTRA_LOCATION = "android.telephony.ims.extra.LOCATION";
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index e0e84537368f..d7b43c0bc48e 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -1640,6 +1640,7 @@ package android.os.storage {
public class StorageManager {
method @NonNull public static java.util.UUID convert(@NonNull String);
method @NonNull public static String convert(@NonNull java.util.UUID);
+ method public static boolean isUserKeyUnlocked(int);
}
public final class StorageVolume implements android.os.Parcelable {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3d9f6123963f..47d2e7cee65a 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -5141,7 +5141,7 @@ public final class ActivityThread extends ClientTransactionHandler {
private void onCoreSettingsChange() {
if (updateDebugViewAttributeState()) {
// request all activities to relaunch for the changes to take place
- relaunchAllActivities(false /* preserveWindows */);
+ relaunchAllActivities(false /* preserveWindows */, "onCoreSettingsChange");
}
}
@@ -5160,7 +5160,8 @@ public final class ActivityThread extends ClientTransactionHandler {
return previousState != View.sDebugViewAttributes;
}
- private void relaunchAllActivities(boolean preserveWindows) {
+ private void relaunchAllActivities(boolean preserveWindows, String reason) {
+ Log.i(TAG, "Relaunch all activities: " + reason);
for (int i = mActivities.size() - 1; i >= 0; i--) {
scheduleRelaunchActivityIfPossible(mActivities.valueAt(i), preserveWindows);
}
@@ -5535,6 +5536,7 @@ public final class ActivityThread extends ClientTransactionHandler {
void scheduleRelaunchActivity(IBinder token) {
final ActivityClientRecord r = mActivities.get(token);
if (r != null) {
+ Log.i(TAG, "Schedule relaunch activity: " + r.activityInfo.name);
scheduleRelaunchActivityIfPossible(r, !r.stopped /* preserveWindow */);
}
}
@@ -6079,7 +6081,7 @@ public final class ActivityThread extends ClientTransactionHandler {
handleConfigurationChanged(newConfig, null);
// Preserve windows to avoid black flickers when overlays change.
- relaunchAllActivities(true /* preserveWindows */);
+ relaunchAllActivities(true /* preserveWindows */, "handleApplicationInfoChanged");
}
static void freeTextLayoutCachesIfNeeded(int configDiff) {
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 1906ee4d85d2..b8735c731817 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -6553,14 +6553,15 @@ public class AppOpsManager {
public interface OnOpNotedListener {
/**
* Called when an op was noted.
- *
* @param code The op code.
* @param uid The UID performing the operation.
* @param packageName The package performing the operation.
+ * @param attributionTag The attribution tag performing the operation.
* @param flags The flags of this op
* @param result The result of the note.
*/
- void onOpNoted(int code, int uid, String packageName, @OpFlags int flags, @Mode int result);
+ void onOpNoted(int code, int uid, String packageName, String attributionTag,
+ @OpFlags int flags, @Mode int result);
}
/**
@@ -6593,14 +6594,15 @@ public class AppOpsManager {
* Called when an op was started.
*
* Note: This is only for op starts. It is not called when an op is noted or stopped.
- *
* @param op The op code.
* @param uid The UID performing the operation.
* @param packageName The package performing the operation.
+ * @param attributionTag The attribution tag performing the operation.
* @param flags The flags of this op
* @param result The result of the start.
*/
- void onOpStarted(int op, int uid, String packageName, @OpFlags int flags, @Mode int result);
+ void onOpStarted(int op, int uid, String packageName, String attributionTag,
+ @OpFlags int flags, @Mode int result);
}
AppOpsManager(Context context, IAppOpsService service) {
@@ -7183,8 +7185,9 @@ public class AppOpsManager {
}
cb = new IAppOpsStartedCallback.Stub() {
@Override
- public void opStarted(int op, int uid, String packageName, int flags, int mode) {
- callback.onOpStarted(op, uid, packageName, flags, mode);
+ public void opStarted(int op, int uid, String packageName, String attributionTag,
+ int flags, int mode) {
+ callback.onOpStarted(op, uid, packageName, attributionTag, flags, mode);
}
};
mStartedWatchers.put(callback, cb);
@@ -7250,8 +7253,9 @@ public class AppOpsManager {
}
cb = new IAppOpsNotedCallback.Stub() {
@Override
- public void opNoted(int op, int uid, String packageName, int flags, int mode) {
- callback.onOpNoted(op, uid, packageName, flags, mode);
+ public void opNoted(int op, int uid, String packageName, String attributionTag,
+ int flags, int mode) {
+ callback.onOpNoted(op, uid, packageName, attributionTag, flags, mode);
}
};
mNotedWatchers.put(callback, cb);
diff --git a/core/java/android/app/time/ExternalTimeSuggestion.java b/core/java/android/app/time/ExternalTimeSuggestion.java
index b566eab9867d..61defb588170 100644
--- a/core/java/android/app/time/ExternalTimeSuggestion.java
+++ b/core/java/android/app/time/ExternalTimeSuggestion.java
@@ -16,6 +16,8 @@
package android.app.time;
+import android.annotation.CurrentTimeMillisLong;
+import android.annotation.ElapsedRealtimeLong;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
@@ -31,9 +33,9 @@ import java.util.Objects;
/**
* A time signal from an External source.
*
- * External time suggestions are for use in situations where the Android device is part of a wider
- * network of devices that are required to use a single time source, and where authority for the
- * time is external to the Android device. For example, for the Android Auto use case where the
+ * <p>External time suggestions are for use in situations where the Android device is part of a
+ * wider network of devices that are required to use a single time source, and where authority for
+ * the time is external to the Android device. For example, for the Android Auto use case where the
* Android device is part of a wider in-car network of devices that should display the same time.
*
* <p>Android allows for a single external source for time. If there are several external sources
@@ -49,19 +51,19 @@ import java.util.Objects;
* capture the elapsed realtime reference clock, e.g. via {@link SystemClock#elapsedRealtime()},
* when the UTC time is first obtained (usually under a wakelock). This enables Android to adjust
* for latency introduced between suggestion creation and eventual use. Adjustments for other
- * sources of latency, i.e. those before the external time suggestion is created, must be handled
- * by the creator.
+ * sources of latency, i.e. those before the external time suggestion is created, must be handled by
+ * the creator.
*
- * <p>{@code utcTime} is the suggested time. The {@code utcTime.value} is the number of milliseconds
- * elapsed since 1/1/1970 00:00:00 UTC. The {@code utcTime.referenceTimeMillis} is the value of the
- * elapsed realtime clock when the {@code utcTime.value} was established.
- * Note that the elapsed realtime clock is considered accurate but it is volatile, so time
- * suggestions cannot be persisted across device resets.
+ * <p>{@code elapsedRealtimeMillis} and {@code suggestionMillis} represent the suggested time.
+ * {@code suggestionMillis} is the number of milliseconds elapsed since 1/1/1970 00:00:00 UTC.
+ * {@code elapsedRealtimeMillis} is the value of the elapsed realtime clock when {@code
+ * suggestionMillis} was established. Note that the elapsed realtime clock is considered accurate
+ * but it is volatile, so time suggestions cannot be persisted across device resets.
*
* <p>{@code debugInfo} contains debugging metadata associated with the suggestion. This is used to
* record why the suggestion exists and how it was entered. This information exists only to aid in
- * debugging and therefore is used by {@link #toString()}, but it is not for use in detection
- * logic and is not considered in {@link #hashCode()} or {@link #equals(Object)}.
+ * debugging and therefore is used by {@link #toString()}, but it is not for use in detection logic
+ * and is not considered in {@link #hashCode()} or {@link #equals(Object)}.
*
* @hide
*/
@@ -78,17 +80,28 @@ public final class ExternalTimeSuggestion implements Parcelable {
}
};
- @NonNull private final TimestampedValue<Long> mUtcTime;
- @Nullable private ArrayList<String> mDebugInfo;
+ @NonNull
+ private final TimestampedValue<Long> mUtcTime;
+ @Nullable
+ private ArrayList<String> mDebugInfo;
- public ExternalTimeSuggestion(@NonNull TimestampedValue<Long> utcTime) {
- mUtcTime = Objects.requireNonNull(utcTime);
- Objects.requireNonNull(utcTime.getValue());
+ /**
+ * Creates a time suggestion cross-referenced to the elapsed realtime clock. See {@link
+ * ExternalTimeSuggestion} for more details.
+ *
+ * @param elapsedRealtimeMillis the elapsed realtime clock reference for the suggestion
+ * @param suggestionMillis the suggested UTC time in milliseconds since the start of the
+ * Unix epoch
+ */
+ public ExternalTimeSuggestion(@ElapsedRealtimeLong long elapsedRealtimeMillis,
+ @CurrentTimeMillisLong long suggestionMillis) {
+ mUtcTime = new TimestampedValue(elapsedRealtimeMillis, suggestionMillis);
}
private static ExternalTimeSuggestion createFromParcel(Parcel in) {
TimestampedValue<Long> utcTime = in.readParcelable(null /* classLoader */);
- ExternalTimeSuggestion suggestion = new ExternalTimeSuggestion(utcTime);
+ ExternalTimeSuggestion suggestion =
+ new ExternalTimeSuggestion(utcTime.getReferenceTimeMillis(), utcTime.getValue());
@SuppressWarnings("unchecked")
ArrayList<String> debugInfo = (ArrayList<String>) in.readArrayList(null /* classLoader */);
suggestion.mDebugInfo = debugInfo;
@@ -106,23 +119,31 @@ public final class ExternalTimeSuggestion implements Parcelable {
dest.writeList(mDebugInfo);
}
+ /**
+ * {@hide}
+ */
@NonNull
public TimestampedValue<Long> getUtcTime() {
return mUtcTime;
}
+ /**
+ * Returns information that can be useful for debugging / logging. See {@link #addDebugInfo}.
+ * {@hide}
+ */
@NonNull
public List<String> getDebugInfo() {
return mDebugInfo == null
- ? Collections.emptyList() : Collections.unmodifiableList(mDebugInfo);
+ ? Collections.emptyList()
+ : Collections.unmodifiableList(mDebugInfo);
}
/**
* Associates information with the instance that can be useful for debugging / logging. The
- * information is present in {@link #toString()} but is not considered for
- * {@link #equals(Object)} and {@link #hashCode()}.
+ * information is present in {@link #toString()} but is not considered for {@link
+ * #equals(Object)} and {@link #hashCode()}.
*/
- public void addDebugInfo(String... debugInfos) {
+ public void addDebugInfo(@NonNull String... debugInfos) {
if (mDebugInfo == null) {
mDebugInfo = new ArrayList<>();
}
@@ -148,9 +169,7 @@ public final class ExternalTimeSuggestion implements Parcelable {
@Override
public String toString() {
- return "ExternalTimeSuggestion{"
- + "mUtcTime=" + mUtcTime
- + ", mDebugInfo=" + mDebugInfo
+ return "ExternalTimeSuggestion{" + "mUtcTime=" + mUtcTime + ", mDebugInfo=" + mDebugInfo
+ '}';
}
}
diff --git a/core/java/android/app/time/TimeManager.java b/core/java/android/app/time/TimeManager.java
index 262d244c5b1c..430960fb11a8 100644
--- a/core/java/android/app/time/TimeManager.java
+++ b/core/java/android/app/time/TimeManager.java
@@ -20,6 +20,7 @@ import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
+import android.app.timedetector.ITimeDetectorService;
import android.app.timezonedetector.ITimeZoneDetectorService;
import android.content.Context;
import android.os.RemoteException;
@@ -45,6 +46,7 @@ public final class TimeManager {
private final Object mLock = new Object();
private final ITimeZoneDetectorService mITimeZoneDetectorService;
+ private final ITimeDetectorService mITimeDetectorService;
@GuardedBy("mLock")
private ITimeZoneDetectorListener mTimeZoneDetectorReceiver;
@@ -62,6 +64,8 @@ public final class TimeManager {
// internal refactoring.
mITimeZoneDetectorService = ITimeZoneDetectorService.Stub.asInterface(
ServiceManager.getServiceOrThrow(Context.TIME_ZONE_DETECTOR_SERVICE));
+ mITimeDetectorService = ITimeDetectorService.Stub.asInterface(
+ ServiceManager.getServiceOrThrow(Context.TIME_DETECTOR_SERVICE));
}
/**
@@ -214,4 +218,23 @@ public final class TimeManager {
}
}
}
+
+ /**
+ * Suggests the current time from an external time source. For example, a form factor-specific
+ * HAL. This time <em>may</em> be used to set the device system clock, depending on the device
+ * configuration and user settings. This method call is processed asynchronously.
+ * See {@link ExternalTimeSuggestion} for more details.
+ * {@hide}
+ */
+ @RequiresPermission(android.Manifest.permission.SET_TIME)
+ public void suggestExternalTime(@NonNull ExternalTimeSuggestion timeSuggestion) {
+ if (DEBUG) {
+ Log.d(TAG, "suggestExternalTime called: " + timeSuggestion);
+ }
+ try {
+ mITimeDetectorService.suggestExternalTime(timeSuggestion);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
diff --git a/core/java/android/app/timedetector/TimeDetector.java b/core/java/android/app/timedetector/TimeDetector.java
index 76f378590ae2..52016b65688b 100644
--- a/core/java/android/app/timedetector/TimeDetector.java
+++ b/core/java/android/app/timedetector/TimeDetector.java
@@ -19,7 +19,6 @@ package android.app.timedetector;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemService;
-import android.app.time.ExternalTimeSuggestion;
import android.content.Context;
import android.os.SystemClock;
import android.os.TimestampedValue;
@@ -80,12 +79,4 @@ public interface TimeDetector {
*/
@RequiresPermission(android.Manifest.permission.SET_TIME)
void suggestGnssTime(GnssTimeSuggestion timeSuggestion);
-
- /**
- * Suggests the time according to an external time source (form factor specific HAL, etc).
- *
- * @hide
- */
- @RequiresPermission(android.Manifest.permission.SET_TIME)
- void suggestExternalTime(ExternalTimeSuggestion timeSuggestion);
}
diff --git a/core/java/android/app/timedetector/TimeDetectorImpl.java b/core/java/android/app/timedetector/TimeDetectorImpl.java
index ef818ef647d6..b0aa3c8d4575 100644
--- a/core/java/android/app/timedetector/TimeDetectorImpl.java
+++ b/core/java/android/app/timedetector/TimeDetectorImpl.java
@@ -17,7 +17,6 @@
package android.app.timedetector;
import android.annotation.NonNull;
-import android.app.time.ExternalTimeSuggestion;
import android.content.Context;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -87,16 +86,4 @@ public final class TimeDetectorImpl implements TimeDetector {
throw e.rethrowFromSystemServer();
}
}
-
- @Override
- public void suggestExternalTime(ExternalTimeSuggestion timeSuggestion) {
- if (DEBUG) {
- Log.d(TAG, "suggestExternalTime called: " + timeSuggestion);
- }
- try {
- mITimeDetectorService.suggestExternalTime(timeSuggestion);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
- }
}
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 01ff4326a800..dec2c3d7fe48 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -1105,19 +1105,15 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
* <p>
* This property is the compile-time equivalent of
* {@link android.os.Build.VERSION#CODENAME Build.VERSION.SDK_INT}.
- *
- * @hide For platform use only; we don't expect developers to need to read this value.
*/
public int compileSdkVersion;
/**
- * The development codename (ex. "O", "REL") of the framework against which the application
+ * The development codename (ex. "S", "REL") of the framework against which the application
* claims to have been compiled, or {@code null} if not specified.
* <p>
* This property is the compile-time equivalent of
* {@link android.os.Build.VERSION#CODENAME Build.VERSION.CODENAME}.
- *
- * @hide For platform use only; we don't expect developers to need to read this value.
*/
@Nullable
public String compileSdkVersionCodename;
diff --git a/core/java/android/content/pm/dex/DexMetadataHelper.java b/core/java/android/content/pm/dex/DexMetadataHelper.java
index bc5d14a533e2..0d5b33cd8672 100644
--- a/core/java/android/content/pm/dex/DexMetadataHelper.java
+++ b/core/java/android/content/pm/dex/DexMetadataHelper.java
@@ -24,16 +24,16 @@ import android.content.pm.parsing.ApkLiteParseUtils;
import android.content.pm.parsing.PackageLite;
import android.os.SystemProperties;
import android.util.ArrayMap;
-import android.util.jar.StrictJarFile;
import android.util.JsonReader;
import android.util.Log;
+import android.util.jar.StrictJarFile;
import com.android.internal.annotations.VisibleForTesting;
import java.io.File;
+import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.nio.file.Paths;
@@ -53,7 +53,10 @@ public class DexMetadataHelper {
/** $> adb shell 'setprop log.tag.DexMetadataHelper VERBOSE' */
public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
/** $> adb shell 'setprop pm.dexopt.dm.require_manifest true' */
- private static String PROPERTY_DM_JSON_MANIFEST_REQUIRED = "pm.dexopt.dm.require_manifest";
+ private static final String PROPERTY_DM_JSON_MANIFEST_REQUIRED =
+ "pm.dexopt.dm.require_manifest";
+ /** $> adb shell 'setprop pm.dexopt.dm.require_fsverity true' */
+ private static final String PROPERTY_DM_FSVERITY_REQUIRED = "pm.dexopt.dm.require_fsverity";
private static final String DEX_METADATA_FILE_EXTENSION = ".dm";
@@ -70,6 +73,13 @@ public class DexMetadataHelper {
}
/**
+ * Returns whether fs-verity is required to install a dex metadata
+ */
+ public static boolean isFsVerityRequired() {
+ return SystemProperties.getBoolean(PROPERTY_DM_FSVERITY_REQUIRED, false);
+ }
+
+ /**
* Return the size (in bytes) of all dex metadata files associated with the given package.
*/
public static long getPackageDexMetadataSize(PackageLite pkg) {
diff --git a/core/java/android/hardware/SystemSensorManager.java b/core/java/android/hardware/SystemSensorManager.java
index 1ffd18fc1ac8..788afe3bdb8e 100644
--- a/core/java/android/hardware/SystemSensorManager.java
+++ b/core/java/android/hardware/SystemSensorManager.java
@@ -667,7 +667,7 @@ public class SystemSensorManager extends SensorManager {
private abstract static class BaseEventQueue {
private static native long nativeInitBaseEventQueue(long nativeManager,
WeakReference<BaseEventQueue> eventQWeak, MessageQueue msgQ,
- String packageName, int mode, String opPackageName);
+ String packageName, int mode, String opPackageName, String attributionTag);
private static native int nativeEnableSensor(long eventQ, int handle, int rateUs,
int maxBatchReportLatencyUs);
private static native int nativeDisableSensor(long eventQ, int handle);
@@ -689,7 +689,8 @@ public class SystemSensorManager extends SensorManager {
if (packageName == null) packageName = "";
mNativeSensorEventQueue = nativeInitBaseEventQueue(manager.mNativeInstance,
new WeakReference<>(this), looper.getQueue(),
- packageName, mode, manager.mContext.getOpPackageName());
+ packageName, mode, manager.mContext.getOpPackageName(),
+ manager.mContext.getAttributionTag());
mCloseGuard.open("dispose");
mManager = manager;
}
diff --git a/core/java/android/hardware/display/DeviceProductInfo.java b/core/java/android/hardware/display/DeviceProductInfo.java
index 41126b70c89f..9457d8f1aac4 100644
--- a/core/java/android/hardware/display/DeviceProductInfo.java
+++ b/core/java/android/hardware/display/DeviceProductInfo.java
@@ -16,40 +16,69 @@
package android.hardware.display;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.os.Parcel;
import android.os.Parcelable;
-import java.util.Arrays;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.Objects;
/**
* Product-specific information about the display or the directly connected device on the
* display chain. For example, if the display is transitively connected, this field may contain
* product information about the intermediate device.
- * @hide
*/
public final class DeviceProductInfo implements Parcelable {
+ /** @hide */
+ @IntDef(prefix = {"CONNECTION_TO_SINK_"}, value = {
+ CONNECTION_TO_SINK_UNKNOWN,
+ CONNECTION_TO_SINK_BUILT_IN,
+ CONNECTION_TO_SINK_DIRECT,
+ CONNECTION_TO_SINK_TRANSITIVE
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ConnectionToSinkType { }
+
+ /** The device connection to the display sink is unknown. */
+ public static final int CONNECTION_TO_SINK_UNKNOWN =
+ IDeviceProductInfoConstants.CONNECTION_TO_SINK_UNKNOWN;
+
+ /** The display sink is built-in to the device */
+ public static final int CONNECTION_TO_SINK_BUILT_IN =
+ IDeviceProductInfoConstants.CONNECTION_TO_SINK_BUILT_IN;
+
+ /** The device is directly connected to the display sink. */
+ public static final int CONNECTION_TO_SINK_DIRECT =
+ IDeviceProductInfoConstants.CONNECTION_TO_SINK_DIRECT;
+
+ /** The device is transitively connected to the display sink. */
+ public static final int CONNECTION_TO_SINK_TRANSITIVE =
+ IDeviceProductInfoConstants.CONNECTION_TO_SINK_TRANSITIVE;
+
private final String mName;
private final String mManufacturerPnpId;
private final String mProductId;
private final Integer mModelYear;
private final ManufactureDate mManufactureDate;
- private final int[] mRelativeAddress;
+ private final @ConnectionToSinkType int mConnectionToSinkType;
+ /** @hide */
public DeviceProductInfo(
String name,
String manufacturerPnpId,
String productId,
Integer modelYear,
ManufactureDate manufactureDate,
- int[] relativeAddress) {
+ int connectionToSinkType) {
this.mName = name;
this.mManufacturerPnpId = manufacturerPnpId;
this.mProductId = productId;
this.mModelYear = modelYear;
this.mManufactureDate = manufactureDate;
- this.mRelativeAddress = relativeAddress;
+ this.mConnectionToSinkType = connectionToSinkType;
}
private DeviceProductInfo(Parcel in) {
@@ -58,12 +87,13 @@ public final class DeviceProductInfo implements Parcelable {
mProductId = (String) in.readValue(null);
mModelYear = (Integer) in.readValue(null);
mManufactureDate = (ManufactureDate) in.readValue(null);
- mRelativeAddress = in.createIntArray();
+ mConnectionToSinkType = in.readInt();
}
/**
* @return Display name.
*/
+ @Nullable
public String getName() {
return mName;
}
@@ -71,6 +101,7 @@ public final class DeviceProductInfo implements Parcelable {
/**
* @return Manufacturer Plug and Play ID.
*/
+ @NonNull
public String getManufacturerPnpId() {
return mManufacturerPnpId;
}
@@ -78,32 +109,58 @@ public final class DeviceProductInfo implements Parcelable {
/**
* @return Manufacturer product ID.
*/
+ @NonNull
public String getProductId() {
return mProductId;
}
/**
- * @return Model year of the device. Typically exactly one of model year or
- * manufacture date will be present.
+ * @return Model year of the device. Return -1 if not available. Typically,
+ * one of model year or manufacture year is available.
*/
- public Integer getModelYear() {
- return mModelYear;
+ public int getModelYear() {
+ return mModelYear != null ? mModelYear : -1;
+ }
+
+ /**
+ * @return The year of manufacture, or -1 it is not available. Typically,
+ * one of model year or manufacture year is available.
+ */
+ public int getManufactureYear() {
+ if (mManufactureDate == null) {
+ return -1;
+ }
+ return mManufactureDate.mYear != null ? mManufactureDate.mYear : -1;
+ }
+
+ /**
+ * @return The week of manufacture, or -1 it is not available. Typically,
+ * not present if model year is available.
+ */
+ public int getManufactureWeek() {
+ if (mManufactureDate == null) {
+ return -1;
+ }
+ return mManufactureDate.mWeek != null ? mManufactureDate.mWeek : -1;
}
/**
* @return Manufacture date. Typically exactly one of model year or manufacture
* date will be present.
+ *
+ * @hide
*/
public ManufactureDate getManufactureDate() {
return mManufactureDate;
}
/**
- * @return Relative address in the display network. For example, for HDMI connected devices this
- * can be its physical address. Each component of the address is in the range [0, 255].
+ * @return How the current device is connected to the display sink. For example, the display
+ * can be connected immediately to the device or there can be a receiver in between.
*/
- public int[] getRelativeAddress() {
- return mRelativeAddress;
+ @ConnectionToSinkType
+ public int getConnectionToSinkType() {
+ return mConnectionToSinkType;
}
@Override
@@ -119,8 +176,8 @@ public final class DeviceProductInfo implements Parcelable {
+ mModelYear
+ ", manufactureDate="
+ mManufactureDate
- + ", relativeAddress="
- + Arrays.toString(mRelativeAddress)
+ + ", connectionToSinkType="
+ + mConnectionToSinkType
+ '}';
}
@@ -134,16 +191,16 @@ public final class DeviceProductInfo implements Parcelable {
&& Objects.equals(mProductId, that.mProductId)
&& Objects.equals(mModelYear, that.mModelYear)
&& Objects.equals(mManufactureDate, that.mManufactureDate)
- && Arrays.equals(mRelativeAddress, that.mRelativeAddress);
+ && mConnectionToSinkType == that.mConnectionToSinkType;
}
@Override
public int hashCode() {
return Objects.hash(mName, mManufacturerPnpId, mProductId, mModelYear, mManufactureDate,
- Arrays.hashCode(mRelativeAddress));
+ mConnectionToSinkType);
}
- public static final Creator<DeviceProductInfo> CREATOR =
+ @NonNull public static final Creator<DeviceProductInfo> CREATOR =
new Creator<DeviceProductInfo>() {
@Override
public DeviceProductInfo createFromParcel(Parcel in) {
@@ -162,13 +219,13 @@ public final class DeviceProductInfo implements Parcelable {
}
@Override
- public void writeToParcel(Parcel dest, int flags) {
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeString(mName);
dest.writeString(mManufacturerPnpId);
dest.writeValue(mProductId);
dest.writeValue(mModelYear);
dest.writeValue(mManufactureDate);
- dest.writeIntArray(mRelativeAddress);
+ dest.writeInt(mConnectionToSinkType);
}
/**
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index ff9b4f41ef3b..e5163d83de69 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -1881,6 +1881,10 @@ public final class PowerManager {
* Returns the current battery saver control mode. Values it may return are defined in
* AutoPowerSaveModeTriggers. Note that this is a global device state, not a per user setting.
*
+ * <p>Note: Prior to Android version {@link Build.VERSION_CODES#S}, any app calling this method
+ * was required to hold the {@link android.Manifest.permission#POWER_SAVER} permission. Starting
+ * from Android version {@link Build.VERSION_CODES#S}, that permission is no longer required.
+ *
* @return The current value power saver mode for the system.
*
* @see AutoPowerSaveModeTriggers
@@ -1889,7 +1893,6 @@ public final class PowerManager {
*/
@AutoPowerSaveModeTriggers
@SystemApi
- @RequiresPermission(android.Manifest.permission.POWER_SAVER)
public int getPowerSaveModeTrigger() {
try {
return mService.getPowerSaveModeTrigger();
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 54d2df865c39..136dc388022f 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -207,6 +207,12 @@ public class Process {
public static final int SE_UID = 1068;
/**
+ * Defines the UID/GID for the iorapd.
+ * @hide
+ */
+ public static final int IORAPD_UID = 1071;
+
+ /**
* Defines the UID/GID for the NetworkStack app.
* @hide
*/
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index a5d3c2acc577..3a5426c60b24 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -1536,6 +1536,7 @@ public class StorageManager {
}
/** {@hide} */
+ @TestApi
public static boolean isUserKeyUnlocked(int userId) {
if (sStorageManager == null) {
sStorageManager = IStorageManager.Stub
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e979e13d89c5..6ee7eb25eb2f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -14614,6 +14614,29 @@ public final class Settings {
public static final String POWER_BUTTON_VERY_LONG_PRESS =
"power_button_very_long_press";
+
+ /**
+ * Keyguard should be on the left hand side of the screen, for wide screen layouts.
+ *
+ * @hide
+ */
+ public static final int ONE_HANDED_KEYGUARD_SIDE_LEFT = 0;
+
+ /**
+ * Keyguard should be on the right hand side of the screen, for wide screen layouts.
+ *
+ * @hide
+ */
+ public static final int ONE_HANDED_KEYGUARD_SIDE_RIGHT = 1;
+ /**
+ * In one handed mode, which side the keyguard should be on. Allowable values are one of
+ * the ONE_HANDED_KEYGUARD_SIDE_* constants.
+ *
+ * @hide
+ */
+ @Readable
+ public static final String ONE_HANDED_KEYGUARD_SIDE = "one_handed_keyguard_side";
+
/**
* Keys we no longer back up under the current schema, but want to continue to
* process when restoring historical backup datasets.
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 0ba1dfee16f3..8117c963b959 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -34,6 +34,7 @@ import android.graphics.ColorSpace;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
+import android.hardware.display.DeviceProductInfo;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerGlobal;
import android.os.Build;
@@ -1181,6 +1182,18 @@ public final class Display {
}
/**
+ * Returns the product-specific information about the display or the directly connected
+ * device on the display chain.
+ * For example, if the display is transitively connected, this field may contain product
+ * information about the intermediate device.
+ * Returns {@code null} if product information is not available.
+ */
+ @Nullable
+ public DeviceProductInfo getDeviceProductInfo() {
+ return mDisplayInfo.deviceProductInfo;
+ }
+
+ /**
* Gets display metrics that describe the size and density of this display.
* The size returned by this method does not necessarily represent the
* actual raw size (native resolution) of the display.
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 219190f554ea..21dd1fb05615 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -20,8 +20,6 @@ import static android.view.InsetsStateProto.DISPLAY_CUTOUT;
import static android.view.InsetsStateProto.DISPLAY_FRAME;
import static android.view.InsetsStateProto.SOURCES;
import static android.view.View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
-import static android.view.WindowInsets.Type.MANDATORY_SYSTEM_GESTURES;
-import static android.view.WindowInsets.Type.SYSTEM_GESTURES;
import static android.view.WindowInsets.Type.displayCutout;
import static android.view.WindowInsets.Type.ime;
import static android.view.WindowInsets.Type.indexOf;
@@ -106,14 +104,11 @@ public class InsetsState implements Parcelable {
public static final int ITYPE_NAVIGATION_BAR = 1;
public static final int ITYPE_CAPTION_BAR = 2;
- // The always visible types are visible to all windows regardless of the z-order.
- public static final int FIRST_ALWAYS_VISIBLE_TYPE = 3;
- public static final int ITYPE_TOP_GESTURES = FIRST_ALWAYS_VISIBLE_TYPE;
+ public static final int ITYPE_TOP_GESTURES = 3;
public static final int ITYPE_BOTTOM_GESTURES = 4;
public static final int ITYPE_LEFT_GESTURES = 5;
public static final int ITYPE_RIGHT_GESTURES = 6;
- /** Additional gesture inset types that map into {@link Type.MANDATORY_SYSTEM_GESTURES}. */
public static final int ITYPE_TOP_MANDATORY_GESTURES = 7;
public static final int ITYPE_BOTTOM_MANDATORY_GESTURES = 8;
public static final int ITYPE_LEFT_MANDATORY_GESTURES = 9;
@@ -123,7 +118,6 @@ public class InsetsState implements Parcelable {
public static final int ITYPE_TOP_DISPLAY_CUTOUT = 12;
public static final int ITYPE_RIGHT_DISPLAY_CUTOUT = 13;
public static final int ITYPE_BOTTOM_DISPLAY_CUTOUT = 14;
- public static final int LAST_ALWAYS_VISIBLE_TYPE = ITYPE_BOTTOM_DISPLAY_CUTOUT;
public static final int ITYPE_LEFT_TAPPABLE_ELEMENT = 15;
public static final int ITYPE_TOP_TAPPABLE_ELEMENT = 16;
@@ -188,18 +182,6 @@ public class InsetsState implements Parcelable {
}
/**
- * Mirror the always visible sources from the other state. They will share the same object for
- * the always visible types.
- *
- * @param other the state to mirror the mirrored sources from.
- */
- public void mirrorAlwaysVisibleInsetsSources(InsetsState other) {
- for (int type = FIRST_ALWAYS_VISIBLE_TYPE; type <= LAST_ALWAYS_VISIBLE_TYPE; type++) {
- mSources[type] = other.mSources[type];
- }
- }
-
- /**
* Calculates {@link WindowInsets} based on the current source configuration.
*
* @param frame The frame to calculate the insets relative to.
@@ -380,14 +362,14 @@ public class InsetsState implements Parcelable {
processSourceAsPublicType(source, typeInsetsMap, typeSideMap, typeVisibilityMap,
insets, type);
- if (type == MANDATORY_SYSTEM_GESTURES) {
+ if (type == Type.MANDATORY_SYSTEM_GESTURES) {
// Mandatory system gestures are also system gestures.
// TODO: find a way to express this more generally. One option would be to define
// Type.systemGestureInsets() as NORMAL | MANDATORY, but then we lose the
// ability to set systemGestureInsets() independently from
// mandatorySystemGestureInsets() in the Builder.
processSourceAsPublicType(source, typeInsetsMap, typeSideMap, typeVisibilityMap,
- insets, SYSTEM_GESTURES);
+ insets, Type.SYSTEM_GESTURES);
}
}
@@ -493,9 +475,14 @@ public class InsetsState implements Parcelable {
* to the client.
*
* @param type The {@link InternalInsetsType} of the source to remove
+ * @return {@code true} if this InsetsState was modified; {@code false} otherwise.
*/
- public void removeSource(@InternalInsetsType int type) {
+ public boolean removeSource(@InternalInsetsType int type) {
+ if (mSources[type] == null) {
+ return false;
+ }
mSources[type] = null;
+ return true;
}
/**
@@ -552,6 +539,24 @@ public class InsetsState implements Parcelable {
}
}
+ /**
+ * Sets the values from the other InsetsState. But for sources, only specific types of source
+ * would be set.
+ *
+ * @param other the other InsetsState.
+ * @param types the only types of sources would be set.
+ */
+ public void set(InsetsState other, @InsetsType int types) {
+ mDisplayFrame.set(other.mDisplayFrame);
+ mDisplayCutout.set(other.mDisplayCutout);
+ mRoundedCorners = other.getRoundedCorners();
+ final ArraySet<Integer> t = toInternalType(types);
+ for (int i = t.size() - 1; i >= 0; i--) {
+ final int type = t.valueAt(i);
+ mSources[type] = other.mSources[type];
+ }
+ }
+
public void addSource(InsetsSource source) {
mSources[source.getType()] = source;
}
@@ -575,6 +580,18 @@ public class InsetsState implements Parcelable {
if ((types & Type.CAPTION_BAR) != 0) {
result.add(ITYPE_CAPTION_BAR);
}
+ if ((types & Type.SYSTEM_GESTURES) != 0) {
+ result.add(ITYPE_LEFT_GESTURES);
+ result.add(ITYPE_TOP_GESTURES);
+ result.add(ITYPE_RIGHT_GESTURES);
+ result.add(ITYPE_BOTTOM_GESTURES);
+ }
+ if ((types & Type.MANDATORY_SYSTEM_GESTURES) != 0) {
+ result.add(ITYPE_LEFT_MANDATORY_GESTURES);
+ result.add(ITYPE_TOP_MANDATORY_GESTURES);
+ result.add(ITYPE_RIGHT_MANDATORY_GESTURES);
+ result.add(ITYPE_BOTTOM_MANDATORY_GESTURES);
+ }
if ((types & Type.DISPLAY_CUTOUT) != 0) {
result.add(ITYPE_LEFT_DISPLAY_CUTOUT);
result.add(ITYPE_TOP_DISPLAY_CUTOUT);
diff --git a/core/java/android/view/RoundedCorners.java b/core/java/android/view/RoundedCorners.java
index 015e804da2f6..569c287901c7 100644
--- a/core/java/android/view/RoundedCorners.java
+++ b/core/java/android/view/RoundedCorners.java
@@ -335,7 +335,7 @@ public class RoundedCorners implements Parcelable {
}
if (o instanceof RoundedCorners) {
RoundedCorners r = (RoundedCorners) o;
- return Arrays.deepEquals(mRoundedCorners, ((RoundedCorners) o).mRoundedCorners);
+ return Arrays.deepEquals(mRoundedCorners, r.mRoundedCorners);
}
return false;
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 66b9617714a6..2bd32acc6c2c 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -68,6 +68,7 @@ import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Objects;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -141,6 +142,9 @@ public final class SurfaceControl implements Parcelable {
int layerStack);
private static native void nativeSetBlurRegions(long transactionObj, long nativeObj,
float[][] regions, int length);
+ private static native void nativeSetStretchEffect(long transactionObj, long nativeObj,
+ float left, float top, float right, float bottom, float vecX, float vecY,
+ float maxStretchAmount);
private static native boolean nativeClearContentFrameStats(long nativeObject);
private static native boolean nativeGetContentFrameStats(long nativeObject, WindowContentFrameStats outStats);
@@ -161,25 +165,21 @@ public final class SurfaceControl implements Parcelable {
int L, int T, int R, int B);
private static native void nativeSetDisplaySize(long transactionObj, IBinder displayToken,
int width, int height);
- private static native DisplayInfo nativeGetDisplayInfo(IBinder displayToken);
- private static native DisplayMode[] nativeGetDisplayModes(
- IBinder displayToken);
+ private static native StaticDisplayInfo nativeGetStaticDisplayInfo(IBinder displayToken);
+ private static native DynamicDisplayInfo nativeGetDynamicDisplayInfo(IBinder displayToken);
private static native DisplayedContentSamplingAttributes
nativeGetDisplayedContentSamplingAttributes(IBinder displayToken);
private static native boolean nativeSetDisplayedContentSamplingEnabled(IBinder displayToken,
boolean enable, int componentMask, int maxFrames);
private static native DisplayedContentSample nativeGetDisplayedContentSample(
IBinder displayToken, long numFrames, long timestamp);
- private static native int nativeGetActiveDisplayMode(IBinder displayToken);
private static native boolean nativeSetDesiredDisplayModeSpecs(IBinder displayToken,
DesiredDisplayModeSpecs desiredDisplayModeSpecs);
private static native DesiredDisplayModeSpecs
nativeGetDesiredDisplayModeSpecs(IBinder displayToken);
- private static native int[] nativeGetDisplayColorModes(IBinder displayToken);
private static native DisplayPrimaries nativeGetDisplayNativePrimaries(
IBinder displayToken);
private static native int[] nativeGetCompositionDataspaces();
- private static native int nativeGetActiveColorMode(IBinder displayToken);
private static native boolean nativeSetActiveColorMode(IBinder displayToken,
int colorMode);
private static native void nativeSetAutoLowLatencyMode(IBinder displayToken, boolean on);
@@ -191,8 +191,6 @@ public final class SurfaceControl implements Parcelable {
private static native void nativeReparent(long transactionObj, long nativeObject,
long newParentNativeObject);
- private static native Display.HdrCapabilities nativeGetHdrCapabilities(IBinder displayToken);
-
private static native boolean nativeGetAutoLowLatencyModeSupport(IBinder displayToken);
private static native boolean nativeGetGameContentTypeSupport(IBinder displayToken);
@@ -1707,7 +1705,7 @@ public final class SurfaceControl implements Parcelable {
*
* @hide
*/
- public static final class DisplayInfo {
+ public static final class StaticDisplayInfo {
public boolean isInternal;
public float density;
public boolean secure;
@@ -1715,7 +1713,7 @@ public final class SurfaceControl implements Parcelable {
@Override
public String toString() {
- return "DisplayInfo{isInternal=" + isInternal
+ return "StaticDisplayInfo{isInternal=" + isInternal
+ ", density=" + density
+ ", secure=" + secure
+ ", deviceProductInfo=" + deviceProductInfo + "}";
@@ -1725,7 +1723,7 @@ public final class SurfaceControl implements Parcelable {
public boolean equals(@Nullable Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
- DisplayInfo that = (DisplayInfo) o;
+ StaticDisplayInfo that = (StaticDisplayInfo) o;
return isInternal == that.isInternal
&& density == that.density
&& secure == that.secure
@@ -1739,6 +1737,49 @@ public final class SurfaceControl implements Parcelable {
}
/**
+ * Dynamic information about physical display.
+ *
+ * @hide
+ */
+ public static final class DynamicDisplayInfo {
+ public DisplayMode[] supportedDisplayModes;
+ public int activeDisplayModeId;
+
+ public int[] supportedColorModes;
+ public int activeColorMode;
+
+ public Display.HdrCapabilities hdrCapabilities;
+
+ @Override
+ public String toString() {
+ return "DynamicDisplayInfo{"
+ + "supportedDisplayModes=" + Arrays.toString(supportedDisplayModes)
+ + ", activeDisplayModeId=" + activeDisplayModeId
+ + ", supportedColorModes=" + Arrays.toString(supportedColorModes)
+ + ", activeColorMode=" + activeColorMode
+ + ", hdrCapabilities=" + hdrCapabilities + "}";
+ }
+
+ @Override
+ public boolean equals(@Nullable Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ DynamicDisplayInfo that = (DynamicDisplayInfo) o;
+ return Arrays.equals(supportedDisplayModes, that.supportedDisplayModes)
+ && activeDisplayModeId == that.activeDisplayModeId
+ && Arrays.equals(supportedColorModes, that.supportedColorModes)
+ && activeColorMode == that.activeColorMode
+ && Objects.equals(hdrCapabilities, that.hdrCapabilities);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(supportedDisplayModes, activeDisplayModeId, activeDisplayModeId,
+ activeColorMode, hdrCapabilities);
+ }
+ }
+
+ /**
* Configuration supported by physical display.
*
* @hide
@@ -1749,6 +1790,7 @@ public final class SurfaceControl implements Parcelable {
*/
public static final int INVALID_DISPLAY_MODE_ID = -1;
+ public int id;
public int width;
public int height;
public float xDpi;
@@ -1768,7 +1810,8 @@ public final class SurfaceControl implements Parcelable {
@Override
public String toString() {
- return "DisplayConfig{width=" + width
+ return "DisplayMode{id=" + id
+ + ", width=" + width
+ ", height=" + height
+ ", xDpi=" + xDpi
+ ", yDpi=" + yDpi
@@ -1777,46 +1820,58 @@ public final class SurfaceControl implements Parcelable {
+ ", presentationDeadlineNanos=" + presentationDeadlineNanos
+ ", group=" + group + "}";
}
- }
- /**
- * @hide
- */
- public static void setDisplayPowerMode(IBinder displayToken, int mode) {
- if (displayToken == null) {
- throw new IllegalArgumentException("displayToken must not be null");
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ DisplayMode that = (DisplayMode) o;
+ return id == that.id
+ && width == that.width
+ && height == that.height
+ && Float.compare(that.xDpi, xDpi) == 0
+ && Float.compare(that.yDpi, yDpi) == 0
+ && Float.compare(that.refreshRate, refreshRate) == 0
+ && appVsyncOffsetNanos == that.appVsyncOffsetNanos
+ && presentationDeadlineNanos == that.presentationDeadlineNanos
+ && group == that.group;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(id, width, height, xDpi, yDpi, refreshRate, appVsyncOffsetNanos,
+ presentationDeadlineNanos, group);
}
- nativeSetDisplayPowerMode(displayToken, mode);
}
/**
* @hide
*/
- public static SurfaceControl.DisplayInfo getDisplayInfo(IBinder displayToken) {
+ public static void setDisplayPowerMode(IBinder displayToken, int mode) {
if (displayToken == null) {
throw new IllegalArgumentException("displayToken must not be null");
}
- return nativeGetDisplayInfo(displayToken);
+ nativeSetDisplayPowerMode(displayToken, mode);
}
/**
* @hide
*/
- public static DisplayMode[] getDisplayModes(IBinder displayToken) {
+ public static StaticDisplayInfo getStaticDisplayInfo(IBinder displayToken) {
if (displayToken == null) {
throw new IllegalArgumentException("displayToken must not be null");
}
- return nativeGetDisplayModes(displayToken);
+ return nativeGetStaticDisplayInfo(displayToken);
}
/**
* @hide
*/
- public static int getActiveDisplayMode(IBinder displayToken) {
+ public static DynamicDisplayInfo getDynamicDisplayInfo(IBinder displayToken) {
if (displayToken == null) {
throw new IllegalArgumentException("displayToken must not be null");
}
- return nativeGetActiveDisplayMode(displayToken);
+ return nativeGetDynamicDisplayInfo(displayToken);
}
/**
@@ -1978,16 +2033,6 @@ public final class SurfaceControl implements Parcelable {
}
/**
- * @hide
- */
- public static int[] getDisplayColorModes(IBinder displayToken) {
- if (displayToken == null) {
- throw new IllegalArgumentException("displayToken must not be null");
- }
- return nativeGetDisplayColorModes(displayToken);
- }
-
- /**
* Color coordinates in CIE1931 XYZ color space
*
* @hide
@@ -2057,16 +2102,6 @@ public final class SurfaceControl implements Parcelable {
/**
* @hide
*/
- public static int getActiveColorMode(IBinder displayToken) {
- if (displayToken == null) {
- throw new IllegalArgumentException("displayToken must not be null");
- }
- return nativeGetActiveColorMode(displayToken);
- }
-
- /**
- * @hide
- */
public static boolean setActiveColorMode(IBinder displayToken, int colorMode) {
if (displayToken == null) {
throw new IllegalArgumentException("displayToken must not be null");
@@ -2169,16 +2204,6 @@ public final class SurfaceControl implements Parcelable {
/**
* @hide
*/
- public static Display.HdrCapabilities getHdrCapabilities(IBinder displayToken) {
- if (displayToken == null) {
- throw new IllegalArgumentException("displayToken must not be null");
- }
- return nativeGetHdrCapabilities(displayToken);
- }
-
- /**
- * @hide
- */
public static boolean getAutoLowLatencyModeSupport(IBinder displayToken) {
if (displayToken == null) {
throw new IllegalArgumentException("displayToken must not be null");
@@ -2951,6 +2976,17 @@ public final class SurfaceControl implements Parcelable {
/**
* @hide
*/
+ public Transaction setStretchEffect(SurfaceControl sc, float left, float top, float right,
+ float bottom, float vecX, float vecY, float maxStretchAmount) {
+ checkPreconditions(sc);
+ nativeSetStretchEffect(mNativeObject, sc.mNativeObject, left, top, right, bottom,
+ vecX, vecY, maxStretchAmount);
+ return this;
+ }
+
+ /**
+ * @hide
+ */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.O)
public Transaction setLayerStack(SurfaceControl sc, int layerStack) {
checkPreconditions(sc);
diff --git a/core/java/android/view/SurfaceControlViewHost.java b/core/java/android/view/SurfaceControlViewHost.java
index 18029af6a85e..870fd8cc4f5d 100644
--- a/core/java/android/view/SurfaceControlViewHost.java
+++ b/core/java/android/view/SurfaceControlViewHost.java
@@ -218,16 +218,6 @@ public class SurfaceControlViewHost {
}
/**
- * @hide
- */
- @TestApi
- public void setView(@NonNull View view, @NonNull WindowManager.LayoutParams attrs) {
- Objects.requireNonNull(view);
- view.setLayoutParams(attrs);
- mViewRoot.setView(view, attrs, null);
- }
-
- /**
* Set the root view of the SurfaceControlViewHost. This view will render in to
* the SurfaceControl, and receive input based on the SurfaceControls positioning on
* screen. It will be laid as if it were in a window of the passed in width and height.
@@ -240,11 +230,21 @@ public class SurfaceControlViewHost {
final WindowManager.LayoutParams lp =
new WindowManager.LayoutParams(width, height,
WindowManager.LayoutParams.TYPE_APPLICATION, 0, PixelFormat.TRANSPARENT);
- lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
setView(view, lp);
}
/**
+ * @hide
+ */
+ @TestApi
+ public void setView(@NonNull View view, @NonNull WindowManager.LayoutParams attrs) {
+ Objects.requireNonNull(view);
+ attrs.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+ view.setLayoutParams(attrs);
+ mViewRoot.setView(view, attrs, null);
+ }
+
+ /**
* @return The view passed to setView, or null if none has been passed.
*/
public @Nullable View getView() {
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 6eba83fee48c..ec7e4c1f6a8e 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -1444,6 +1444,14 @@ public class SurfaceView extends View implements ViewRootImpl.SurfaceChangedCall
}
@Override
+ public void applyStretch(long frameNumber, float left, float top, float right,
+ float bottom, float vecX, float vecY, float maxStretch) {
+ mRtTransaction.setStretchEffect(mSurfaceControl, left, top, right, bottom, vecX, vecY,
+ maxStretch);
+ applyRtTransaction(frameNumber);
+ }
+
+ @Override
public void positionLost(long frameNumber) {
if (DEBUG) {
Log.d(TAG, String.format("%d windowPositionLost, frameNr = %d",
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index decbf8c0c59e..4f0c568989de 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -1975,7 +1975,10 @@ public final class AutofillManager {
if (client == null) {
return false;
}
-
+ if (mService == null) {
+ Log.w(TAG, "Autofill service is null!");
+ return false;
+ }
if (mServiceClient == null) {
mServiceClient = new AutofillManagerClient(this);
try {
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index d5f97743c257..05b177ebbb45 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -715,7 +715,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
*/
@NonNull
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769408)
- private EdgeEffect mEdgeGlowTop = new EdgeEffect(mContext);
+ private EdgeEffect mEdgeGlowTop;
/**
* Tracks the state of the bottom edge glow.
@@ -725,7 +725,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
*/
@NonNull
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768444)
- private EdgeEffect mEdgeGlowBottom = new EdgeEffect(mContext);
+ private EdgeEffect mEdgeGlowBottom;
/**
* An estimate of how many pixels are between the top of the list and
@@ -847,6 +847,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
public AbsListView(Context context) {
super(context);
+ mEdgeGlowBottom = new EdgeEffect(context);
+ mEdgeGlowTop = new EdgeEffect(context);
initAbsListView();
mOwnerThread = Thread.currentThread();
@@ -867,6 +869,8 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
public AbsListView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
+ mEdgeGlowBottom = new EdgeEffect(context, attrs);
+ mEdgeGlowTop = new EdgeEffect(context, attrs);
initAbsListView();
mOwnerThread = Thread.currentThread();
@@ -3584,6 +3588,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mLastY != Integer.MIN_VALUE ? y - mLastY + scrollConsumedCorrection : deltaY;
int lastYCorrection = 0;
+ // First allow releasing existing overscroll effect:
+ incrementalDeltaY = releaseGlow(incrementalDeltaY, x);
+
if (mTouchMode == TOUCH_MODE_SCROLL) {
if (PROFILE_SCROLLING) {
if (!mScrollProfilingStarted) {
@@ -3666,14 +3673,14 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mTouchMode = TOUCH_MODE_OVERSCROLL;
}
if (incrementalDeltaY > 0) {
- mEdgeGlowTop.onPull((float) -overscroll / getHeight(),
+ mEdgeGlowTop.onPullDistance((float) -overscroll / getHeight(),
(float) x / getWidth());
if (!mEdgeGlowBottom.isFinished()) {
mEdgeGlowBottom.onRelease();
}
invalidateTopGlow();
} else if (incrementalDeltaY < 0) {
- mEdgeGlowBottom.onPull((float) overscroll / getHeight(),
+ mEdgeGlowBottom.onPullDistance((float) overscroll / getHeight(),
1.f - (float) x / getWidth());
if (!mEdgeGlowTop.isFinished()) {
mEdgeGlowTop.onRelease();
@@ -3713,14 +3720,15 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
(overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS &&
!contentFits())) {
if (rawDeltaY > 0) {
- mEdgeGlowTop.onPull((float) overScrollDistance / getHeight(),
+ mEdgeGlowTop.onPullDistance((float) overScrollDistance / getHeight(),
(float) x / getWidth());
if (!mEdgeGlowBottom.isFinished()) {
mEdgeGlowBottom.onRelease();
}
invalidateTopGlow();
} else if (rawDeltaY < 0) {
- mEdgeGlowBottom.onPull((float) overScrollDistance / getHeight(),
+ mEdgeGlowBottom.onPullDistance(
+ (float) -overScrollDistance / getHeight(),
1.f - (float) x / getWidth());
if (!mEdgeGlowTop.isFinished()) {
mEdgeGlowTop.onRelease();
@@ -3757,6 +3765,44 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
}
+ /**
+ * If the edge glow is currently active, this consumes part or all of deltaY
+ * on the edge glow.
+ *
+ * @param deltaY The pointer motion, in pixels, in the vertical direction, positive
+ * for moving down and negative for moving up.
+ * @param x The horizontal position of the pointer.
+ * @return The remainder of <code>deltaY</code> that has not been consumed by the
+ * edge glow.
+ */
+ private int releaseGlow(int deltaY, int x) {
+ // First allow releasing existing overscroll effect:
+ float consumed = 0;
+ if (mEdgeGlowTop.getDistance() != 0) {
+ consumed = mEdgeGlowTop.onPullDistance((float) deltaY / getHeight(),
+ (float) x / getWidth());
+ if (consumed != 0f) {
+ invalidateTopGlow();
+ }
+ } else if (mEdgeGlowBottom.getDistance() != 0) {
+ consumed = -mEdgeGlowBottom.onPullDistance((float) -deltaY / getHeight(),
+ 1f - (float) x / getWidth());
+ if (consumed != 0f) {
+ invalidateBottomGlow();
+ }
+ }
+ int pixelsConsumed = Math.round(consumed * getHeight());
+ return deltaY - pixelsConsumed;
+ }
+
+ /**
+ * @return <code>true</code> if either the top or bottom edge glow is currently active or
+ * <code>false</code> if it has no value to release.
+ */
+ private boolean isGlowActive() {
+ return mEdgeGlowBottom.getDistance() != 0 || mEdgeGlowTop.getDistance() != 0;
+ }
+
private void invalidateTopGlow() {
if (!shouldDisplayEdgeEffects()) {
return;
@@ -3926,7 +3972,9 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
if (mTouchMode == TOUCH_MODE_OVERFLING) {
// Stopped the fling. It is a scroll.
- mFlingRunnable.endFling();
+ if (mFlingRunnable != null) {
+ mFlingRunnable.endFling();
+ }
if (mPositionScroller != null) {
mPositionScroller.stop();
}
@@ -3936,6 +3984,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mLastY = mMotionY;
mMotionCorrection = 0;
mDirection = 0;
+ stopEdgeGlowRecede(ev.getX());
} else {
final int x = (int) ev.getX();
final int y = (int) ev.getY();
@@ -3948,7 +3997,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mTouchMode = TOUCH_MODE_SCROLL;
mMotionCorrection = 0;
motionPosition = findMotionRow(y);
- mFlingRunnable.flywheelTouch();
+ if (mFlingRunnable != null) {
+ mFlingRunnable.flywheelTouch();
+ }
+ stopEdgeGlowRecede(x);
} else if ((motionPosition >= 0) && getAdapter().isEnabled(motionPosition)) {
// User clicked on an actual view (and was not stopping a
// fling). It might be a click or a scroll. Assume it is a
@@ -3984,6 +4036,15 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
}
+ private void stopEdgeGlowRecede(float x) {
+ if (mEdgeGlowTop.getDistance() != 0) {
+ mEdgeGlowTop.onPullDistance(0, x / getWidth());
+ }
+ if (mEdgeGlowBottom.getDistance() != 0) {
+ mEdgeGlowBottom.onPullDistance(0, x / getWidth());
+ }
+ }
+
private void onTouchMove(MotionEvent ev, MotionEvent vtev) {
if (mHasPerformedLongPress) {
// Consume all move events following a successful long press.
@@ -4489,73 +4550,76 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
switch (actionMasked) {
- case MotionEvent.ACTION_DOWN: {
- int touchMode = mTouchMode;
- if (touchMode == TOUCH_MODE_OVERFLING || touchMode == TOUCH_MODE_OVERSCROLL) {
- mMotionCorrection = 0;
- return true;
- }
-
- final int x = (int) ev.getX();
- final int y = (int) ev.getY();
- mActivePointerId = ev.getPointerId(0);
+ case MotionEvent.ACTION_DOWN: {
+ int touchMode = mTouchMode;
+ if (touchMode == TOUCH_MODE_OVERFLING || touchMode == TOUCH_MODE_OVERSCROLL) {
+ mMotionCorrection = 0;
+ return true;
+ }
- int motionPosition = findMotionRow(y);
- if (touchMode != TOUCH_MODE_FLING && motionPosition >= 0) {
- // User clicked on an actual view (and was not stopping a fling).
- // Remember where the motion event started
- v = getChildAt(motionPosition - mFirstPosition);
- mMotionViewOriginalTop = v.getTop();
- mMotionX = x;
- mMotionY = y;
- mMotionPosition = motionPosition;
- mTouchMode = TOUCH_MODE_DOWN;
- clearScrollingCache();
- }
- mLastY = Integer.MIN_VALUE;
- initOrResetVelocityTracker();
- mVelocityTracker.addMovement(ev);
- mNestedYOffset = 0;
- startNestedScroll(SCROLL_AXIS_VERTICAL);
- if (touchMode == TOUCH_MODE_FLING) {
- return true;
- }
- break;
- }
+ final int x = (int) ev.getX();
+ final int y = (int) ev.getY();
+ mActivePointerId = ev.getPointerId(0);
- case MotionEvent.ACTION_MOVE: {
- switch (mTouchMode) {
- case TOUCH_MODE_DOWN:
- int pointerIndex = ev.findPointerIndex(mActivePointerId);
- if (pointerIndex == -1) {
- pointerIndex = 0;
- mActivePointerId = ev.getPointerId(pointerIndex);
+ int motionPosition = findMotionRow(y);
+ if (isGlowActive()) {
+ // Pressed during edge effect, so this is considered the same as a fling catch.
+ mTouchMode = TOUCH_MODE_FLING;
+ } else if (touchMode != TOUCH_MODE_FLING && motionPosition >= 0) {
+ // User clicked on an actual view (and was not stopping a fling).
+ // Remember where the motion event started
+ v = getChildAt(motionPosition - mFirstPosition);
+ mMotionViewOriginalTop = v.getTop();
+ mMotionX = x;
+ mMotionY = y;
+ mMotionPosition = motionPosition;
+ mTouchMode = TOUCH_MODE_DOWN;
+ clearScrollingCache();
}
- final int y = (int) ev.getY(pointerIndex);
- initVelocityTrackerIfNotExists();
+ mLastY = Integer.MIN_VALUE;
+ initOrResetVelocityTracker();
mVelocityTracker.addMovement(ev);
- if (startScrollIfNeeded((int) ev.getX(pointerIndex), y, null)) {
+ mNestedYOffset = 0;
+ startNestedScroll(SCROLL_AXIS_VERTICAL);
+ if (touchMode == TOUCH_MODE_FLING) {
return true;
}
break;
}
- break;
- }
- case MotionEvent.ACTION_CANCEL:
- case MotionEvent.ACTION_UP: {
- mTouchMode = TOUCH_MODE_REST;
- mActivePointerId = INVALID_POINTER;
- recycleVelocityTracker();
- reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
- stopNestedScroll();
- break;
- }
+ case MotionEvent.ACTION_MOVE: {
+ switch (mTouchMode) {
+ case TOUCH_MODE_DOWN:
+ int pointerIndex = ev.findPointerIndex(mActivePointerId);
+ if (pointerIndex == -1) {
+ pointerIndex = 0;
+ mActivePointerId = ev.getPointerId(pointerIndex);
+ }
+ final int y = (int) ev.getY(pointerIndex);
+ initVelocityTrackerIfNotExists();
+ mVelocityTracker.addMovement(ev);
+ if (startScrollIfNeeded((int) ev.getX(pointerIndex), y, null)) {
+ return true;
+ }
+ break;
+ }
+ break;
+ }
- case MotionEvent.ACTION_POINTER_UP: {
- onSecondaryPointerUp(ev);
- break;
- }
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP: {
+ mTouchMode = TOUCH_MODE_REST;
+ mActivePointerId = INVALID_POINTER;
+ recycleVelocityTracker();
+ reportScrollStateChange(OnScrollListener.SCROLL_STATE_IDLE);
+ stopNestedScroll();
+ break;
+ }
+
+ case MotionEvent.ACTION_POINTER_UP: {
+ onSecondaryPointerUp(ev);
+ break;
+ }
}
return false;
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 2112fb1de63f..30bf546eb83e 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -211,6 +211,7 @@ public class RemoteViews implements Parcelable, Filter {
private static final int SET_RADIO_GROUP_CHECKED = 27;
private static final int SET_VIEW_OUTLINE_RADIUS_TAG = 28;
private static final int SET_ON_CHECKED_CHANGE_RESPONSE_TAG = 29;
+ private static final int NIGHT_MODE_REFLECTION_ACTION_TAG = 30;
/** @hide **/
@IntDef(prefix = "MARGIN_", value = {
@@ -1877,6 +1878,73 @@ public class RemoteViews implements Parcelable, Filter {
}
}
+ private final class NightModeReflectionAction extends BaseReflectionAction {
+
+ private final Object mLightValue;
+ private final Object mDarkValue;
+
+ NightModeReflectionAction(
+ @IdRes int viewId,
+ String methodName,
+ int type,
+ Object lightValue,
+ Object darkValue) {
+ super(viewId, methodName, type);
+ mLightValue = lightValue;
+ mDarkValue = darkValue;
+ }
+
+ NightModeReflectionAction(Parcel in) {
+ super(in);
+ switch (this.type) {
+ case ICON:
+ mLightValue = in.readTypedObject(Icon.CREATOR);
+ mDarkValue = in.readTypedObject(Icon.CREATOR);
+ break;
+ case COLOR_STATE_LIST:
+ mLightValue = in.readTypedObject(ColorStateList.CREATOR);
+ mDarkValue = in.readTypedObject(ColorStateList.CREATOR);
+ break;
+ case INT:
+ mLightValue = in.readInt();
+ mDarkValue = in.readInt();
+ break;
+ default:
+ throw new ActionException("Unexpected night mode action type: " + this.type);
+ }
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ super.writeToParcel(out, flags);
+ switch (this.type) {
+ case ICON:
+ case COLOR_STATE_LIST:
+ out.writeTypedObject((Parcelable) mLightValue, flags);
+ out.writeTypedObject((Parcelable) mDarkValue, flags);
+ break;
+ case INT:
+ out.writeInt((int) mLightValue);
+ out.writeInt((int) mDarkValue);
+ break;
+ }
+ }
+
+ @Nullable
+ @Override
+ protected Object getParameterValue(@Nullable View view) throws ActionException {
+ if (view == null) return null;
+
+ Configuration configuration = view.getResources().getConfiguration();
+ return configuration.isNightModeActive() ? mDarkValue : mLightValue;
+ }
+
+ @Override
+ public int getActionTag() {
+ return NIGHT_MODE_REFLECTION_ACTION_TAG;
+ }
+ }
+
/**
* This is only used for async execution of actions and it not parcelable.
*/
@@ -3243,6 +3311,8 @@ public class RemoteViews implements Parcelable, Filter {
return new SetViewOutlinePreferredRadiusAction(parcel);
case SET_ON_CHECKED_CHANGE_RESPONSE_TAG:
return new SetOnCheckedChangeResponse(parcel);
+ case NIGHT_MODE_REFLECTION_ACTION_TAG:
+ return new NightModeReflectionAction(parcel);
default:
throw new ActionException("Tag " + tag + " not found");
}
@@ -4130,6 +4200,30 @@ public class RemoteViews implements Parcelable, Filter {
ResourceReflectionAction.COLOR_RESOURCE, colorResource));
}
+ /**
+ * Call a method taking one int, a color, on a view in the layout for this RemoteViews.
+ *
+ * @param viewId The id of the view on which to call the method.
+ * @param methodName The name of the method to call.
+ * @param notNight The value to pass to the method when the view's configuration is set to
+ * {@link Configuration#UI_MODE_NIGHT_NO}
+ * @param night The value to pass to the method when the view's configuration is set to
+ * {@link Configuration#UI_MODE_NIGHT_YES}
+ */
+ public void setColorInt(
+ @IdRes int viewId,
+ @NonNull String methodName,
+ @ColorInt int notNight,
+ @ColorInt int night) {
+ addAction(
+ new NightModeReflectionAction(
+ viewId,
+ methodName,
+ BaseReflectionAction.INT,
+ notNight,
+ night));
+ }
+
/**
* Call a method taking one ColorStateList on a view in the layout for this RemoteViews.
@@ -4148,6 +4242,30 @@ public class RemoteViews implements Parcelable, Filter {
/**
* Call a method taking one ColorStateList on a view in the layout for this RemoteViews.
*
+ * @param viewId The id of the view on which to call the method.
+ * @param methodName The name of the method to call.
+ * @param notNight The value to pass to the method when the view's configuration is set to
+ * {@link Configuration#UI_MODE_NIGHT_NO}
+ * @param night The value to pass to the method when the view's configuration is set to
+ * {@link Configuration#UI_MODE_NIGHT_YES}
+ */
+ public void setColorStateList(
+ @IdRes int viewId,
+ @NonNull String methodName,
+ @Nullable ColorStateList notNight,
+ @Nullable ColorStateList night) {
+ addAction(
+ new NightModeReflectionAction(
+ viewId,
+ methodName,
+ BaseReflectionAction.COLOR_STATE_LIST,
+ notNight,
+ night));
+ }
+
+ /**
+ * Call a method taking one ColorStateList on a view in the layout for this RemoteViews.
+ *
* The ColorStateList will be resolved from the resources at the time of inflation.
*
* @param viewId The id of the view on which to call the method.
@@ -4356,6 +4474,30 @@ public class RemoteViews implements Parcelable, Filter {
}
/**
+ * Call a method taking one Icon on a view in the layout for this RemoteViews.
+ *
+ * @param viewId The id of the view on which to call the method.
+ * @param methodName The name of the method to call.
+ * @param notNight The value to pass to the method when the view's configuration is set to
+ * {@link Configuration#UI_MODE_NIGHT_NO}
+ * @param night The value to pass to the method when the view's configuration is set to
+ * {@link Configuration#UI_MODE_NIGHT_YES}
+ */
+ public void setIcon(
+ @IdRes int viewId,
+ @NonNull String methodName,
+ @Nullable Icon notNight,
+ @Nullable Icon night) {
+ addAction(
+ new NightModeReflectionAction(
+ viewId,
+ methodName,
+ BaseReflectionAction.ICON,
+ notNight,
+ night));
+ }
+
+ /**
* Equivalent to calling View.setContentDescription(CharSequence).
*
* @param viewId The id of the view whose content description should change.
diff --git a/core/java/com/android/internal/app/IAppOpsNotedCallback.aidl b/core/java/com/android/internal/app/IAppOpsNotedCallback.aidl
index cb280cd14180..f3759e091ed6 100644
--- a/core/java/com/android/internal/app/IAppOpsNotedCallback.aidl
+++ b/core/java/com/android/internal/app/IAppOpsNotedCallback.aidl
@@ -18,5 +18,5 @@ package com.android.internal.app;
// Iterface to observe op note/checks of ops
oneway interface IAppOpsNotedCallback {
- void opNoted(int op, int uid, String packageName, int flags, int mode);
+ void opNoted(int op, int uid, String packageName, String attributionTag, int flags, int mode);
}
diff --git a/core/java/com/android/internal/app/IAppOpsStartedCallback.aidl b/core/java/com/android/internal/app/IAppOpsStartedCallback.aidl
index b0cb2a8ceb64..3a108e7e1d94 100644
--- a/core/java/com/android/internal/app/IAppOpsStartedCallback.aidl
+++ b/core/java/com/android/internal/app/IAppOpsStartedCallback.aidl
@@ -18,5 +18,5 @@ package com.android.internal.app;
// Iterface to observe op starts
oneway interface IAppOpsStartedCallback {
- void opStarted(int op, int uid, String packageName, int flags, int mode);
+ void opStarted(int op, int uid, String packageName, String attributionTag, int flags, int mode);
}
diff --git a/core/java/com/android/internal/listeners/ListenerTransportManager.java b/core/java/com/android/internal/listeners/ListenerTransportManager.java
index 0d5d1b7b53ff..d5b561939836 100644
--- a/core/java/com/android/internal/listeners/ListenerTransportManager.java
+++ b/core/java/com/android/internal/listeners/ListenerTransportManager.java
@@ -17,6 +17,7 @@
package com.android.internal.listeners;
import android.os.RemoteException;
+import android.util.ArrayMap;
import com.android.internal.annotations.GuardedBy;
@@ -36,13 +37,17 @@ public abstract class ListenerTransportManager<TTransport extends ListenerTransp
@GuardedBy("mRegistrations")
private final Map<Object, WeakReference<TTransport>> mRegistrations;
- protected ListenerTransportManager() {
+ protected ListenerTransportManager(boolean allowServerSideTransportRemoval) {
// using weakhashmap means that the transport may be GCed if the server drops its reference,
// and thus the listener may be GCed as well if the client drops that reference. if the
// server will never drop a reference without warning (ie, transport removal may only be
// initiated from the client side), then arraymap or similar may be used without fear of
// memory leaks.
- mRegistrations = new WeakHashMap<>();
+ if (allowServerSideTransportRemoval) {
+ mRegistrations = new WeakHashMap<>();
+ } else {
+ mRegistrations = new ArrayMap<>();
+ }
}
/**
@@ -53,16 +58,21 @@ public abstract class ListenerTransportManager<TTransport extends ListenerTransp
synchronized (mRegistrations) {
// ordering of operations is important so that if an error occurs at any point we
// are left in a reasonable state
- registerTransport(transport);
- WeakReference<TTransport> oldTransportRef = mRegistrations.put(key,
- new WeakReference<>(transport));
+ TTransport oldTransport;
+ WeakReference<TTransport> oldTransportRef = mRegistrations.get(key);
if (oldTransportRef != null) {
- TTransport oldTransport = oldTransportRef.get();
- if (oldTransport != null) {
- oldTransport.unregister();
- unregisterTransport(oldTransport);
- }
+ oldTransport = oldTransportRef.get();
+ } else {
+ oldTransport = null;
+ }
+
+ if (oldTransport == null) {
+ registerTransport(transport);
+ } else {
+ registerTransport(transport, oldTransport);
+ oldTransport.unregister();
}
+ mRegistrations.put(key, new WeakReference<>(transport));
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -91,7 +101,33 @@ public abstract class ListenerTransportManager<TTransport extends ListenerTransp
}
}
+ /**
+ * Registers a new transport.
+ */
protected abstract void registerTransport(TTransport transport) throws RemoteException;
+ /**
+ * Registers a new transport that is replacing the given old transport. Implementations must
+ * ensure that if they throw a remote exception, the call does not have any side effects.
+ */
+ protected void registerTransport(TTransport transport, TTransport oldTransport)
+ throws RemoteException {
+ registerTransport(transport);
+ try {
+ unregisterTransport(oldTransport);
+ } catch (RemoteException e) {
+ try {
+ // best effort to ensure there are no side effects
+ unregisterTransport(transport);
+ } catch (RemoteException suppressed) {
+ e.addSuppressed(suppressed);
+ }
+ throw e;
+ }
+ }
+
+ /**
+ * Unregisters an existing transport.
+ */
protected abstract void unregisterTransport(TTransport transport) throws RemoteException;
}
diff --git a/core/java/com/android/internal/os/KernelCpuBpfTracking.java b/core/java/com/android/internal/os/KernelCpuBpfTracking.java
index 28525478be05..387d3270f5e4 100644
--- a/core/java/com/android/internal/os/KernelCpuBpfTracking.java
+++ b/core/java/com/android/internal/os/KernelCpuBpfTracking.java
@@ -16,11 +16,79 @@
package com.android.internal.os;
-/** CPU tracking using eBPF. */
+import android.annotation.Nullable;
+
+/**
+ * CPU tracking using eBPF.
+ *
+ * The tracking state and data about available frequencies are cached to avoid JNI calls and
+ * creating temporary arrays. The data is stored in a format that is convenient for metrics
+ * computation.
+ *
+ * Synchronization is not needed because the underlying native library can be invoked concurrently
+ * and getters are idempotent.
+ */
public final class KernelCpuBpfTracking {
+ private static boolean sTracking = false;
+
+ /** Cached mapping from frequency index to frequency in kHz. */
+ private static long[] sFreqs = null;
+
+ /** Cached mapping from frequency index to CPU cluster / policy. */
+ private static int[] sFreqsClusters = null;
+
private KernelCpuBpfTracking() {
}
/** Returns whether CPU tracking using eBPF is supported. */
public static native boolean isSupported();
+
+ /** Starts CPU tracking using eBPF. */
+ public static boolean startTracking() {
+ if (!sTracking) {
+ sTracking = startTrackingInternal();
+ }
+ return sTracking;
+ }
+
+ private static native boolean startTrackingInternal();
+
+ /** Returns frequencies in kHz on which CPU is tracked. Empty if not supported. */
+ public static long[] getFreqs() {
+ if (sFreqs == null) {
+ long[] freqs = getFreqsInternal();
+ if (freqs == null) {
+ return new long[0];
+ }
+ sFreqs = freqs;
+ }
+ return sFreqs;
+ }
+
+ @Nullable
+ static native long[] getFreqsInternal();
+
+ /**
+ * Returns the cluster (policy) number for each frequency on which CPU is tracked. Empty if
+ * not supported.
+ */
+ public static int[] getFreqsClusters() {
+ if (sFreqsClusters == null) {
+ int[] freqsClusters = getFreqsClustersInternal();
+ if (freqsClusters == null) {
+ return new int[0];
+ }
+ sFreqsClusters = freqsClusters;
+ }
+ return sFreqsClusters;
+ }
+
+ @Nullable
+ private static native int[] getFreqsClustersInternal();
+
+ /** Returns the number of clusters (policies). */
+ public static int getClusters() {
+ int[] freqClusters = getFreqsClusters();
+ return freqClusters.length > 0 ? freqClusters[freqClusters.length - 1] + 1 : 0;
+ }
}
diff --git a/core/java/com/android/internal/os/KernelCpuTotalBpfMapReader.java b/core/java/com/android/internal/os/KernelCpuTotalBpfMapReader.java
index 06760e140de1..553eda48e61d 100644
--- a/core/java/com/android/internal/os/KernelCpuTotalBpfMapReader.java
+++ b/core/java/com/android/internal/os/KernelCpuTotalBpfMapReader.java
@@ -16,22 +16,22 @@
package com.android.internal.os;
-/**
- * Reads total CPU time bpf map.
- */
+import android.annotation.Nullable;
+
+/** Reads total CPU time bpf map. */
public final class KernelCpuTotalBpfMapReader {
private KernelCpuTotalBpfMapReader() {
}
- /** Reads total CPU time from bpf map. */
- public static native boolean read(Callback callback);
-
- /** Callback accepting values read from bpf map. */
- public interface Callback {
- /**
- * Accepts values read from bpf map: cluster index, frequency in kilohertz and time in
- * milliseconds that the cpu cluster spent at the frequency (excluding sleep).
- */
- void accept(int cluster, int freqKhz, long timeMs);
+ /** Reads total CPU times (excluding sleep) per frequency in milliseconds from bpf map. */
+ @Nullable
+ public static long[] read() {
+ if (!KernelCpuBpfTracking.startTracking()) {
+ return null;
+ }
+ return readInternal();
}
+
+ @Nullable
+ private static native long[] readInternal();
}
diff --git a/core/java/com/android/internal/os/KernelCpuUidBpfMapReader.java b/core/java/com/android/internal/os/KernelCpuUidBpfMapReader.java
index dafb924f37bd..52c0c3fa93df 100644
--- a/core/java/com/android/internal/os/KernelCpuUidBpfMapReader.java
+++ b/core/java/com/android/internal/os/KernelCpuUidBpfMapReader.java
@@ -68,14 +68,15 @@ public abstract class KernelCpuUidBpfMapReader {
final String mTag = this.getClass().getSimpleName();
private int mErrors = 0;
- private boolean mTracking = false;
protected SparseArray<long[]> mData = new SparseArray<>();
private long mLastReadTime = 0;
protected final ReentrantReadWriteLock mLock = new ReentrantReadWriteLock();
protected final ReentrantReadWriteLock.ReadLock mReadLock = mLock.readLock();
protected final ReentrantReadWriteLock.WriteLock mWriteLock = mLock.writeLock();
- public native boolean startTrackingBpfTimes();
+ public boolean startTrackingBpfTimes() {
+ return KernelCpuBpfTracking.startTracking();
+ }
protected abstract boolean readBpfData();
@@ -116,7 +117,7 @@ public abstract class KernelCpuUidBpfMapReader {
if (mErrors > ERROR_THRESHOLD) {
return null;
}
- if (!mTracking && !startTrackingBpfTimes()) {
+ if (!startTrackingBpfTimes()) {
Slog.w(mTag, "Failed to start tracking");
mErrors++;
return null;
@@ -182,7 +183,9 @@ public abstract class KernelCpuUidBpfMapReader {
protected final native boolean readBpfData();
@Override
- public final native long[] getDataDimensions();
+ public final long[] getDataDimensions() {
+ return KernelCpuBpfTracking.getFreqsInternal();
+ }
@Override
public void removeUidsInRange(int startUid, int endUid) {
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 5b327d40ac69..d0504fb481ca 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -421,11 +421,18 @@ private:
};
static jlong nativeInitSensorEventQueue(JNIEnv *env, jclass clazz, jlong sensorManager,
- jobject eventQWeak, jobject msgQ, jstring packageName, jint mode) {
+ jobject eventQWeak, jobject msgQ, jstring packageName,
+ jint mode, jstring opPackageName, jstring attributionTag) {
SensorManager* mgr = reinterpret_cast<SensorManager*>(sensorManager);
ScopedUtfChars packageUtf(env, packageName);
String8 clientName(packageUtf.c_str());
- sp<SensorEventQueue> queue(mgr->createEventQueue(clientName, mode));
+
+ String16 attributionTagName("");
+ if (attributionTag != nullptr) {
+ ScopedUtfChars attrUtf(env, attributionTag);
+ attributionTagName = String16(attrUtf.c_str());
+ }
+ sp<SensorEventQueue> queue(mgr->createEventQueue(clientName, mode, attributionTagName));
if (queue == NULL) {
jniThrowRuntimeException(env, "Cannot construct native SensorEventQueue.");
@@ -517,29 +524,20 @@ static const JNINativeMethod gSystemSensorManagerMethods[] = {
};
static const JNINativeMethod gBaseEventQueueMethods[] = {
- {"nativeInitBaseEventQueue",
- "(JLjava/lang/ref/WeakReference;Landroid/os/MessageQueue;Ljava/lang/String;ILjava/lang/String;)J",
- (void*)nativeInitSensorEventQueue },
+ {"nativeInitBaseEventQueue",
+ "(JLjava/lang/ref/WeakReference;Landroid/os/MessageQueue;Ljava/lang/String;ILjava/lang/"
+ "String;Ljava/lang/String;)J",
+ (void *)nativeInitSensorEventQueue},
- {"nativeEnableSensor",
- "(JIII)I",
- (void*)nativeEnableSensor },
+ {"nativeEnableSensor", "(JIII)I", (void *)nativeEnableSensor},
- {"nativeDisableSensor",
- "(JI)I",
- (void*)nativeDisableSensor },
+ {"nativeDisableSensor", "(JI)I", (void *)nativeDisableSensor},
- {"nativeDestroySensorEventQueue",
- "(J)V",
- (void*)nativeDestroySensorEventQueue },
+ {"nativeDestroySensorEventQueue", "(J)V", (void *)nativeDestroySensorEventQueue},
- {"nativeFlushSensor",
- "(J)I",
- (void*)nativeFlushSensor },
+ {"nativeFlushSensor", "(J)I", (void *)nativeFlushSensor},
- {"nativeInjectSensorData",
- "(JI[FIJ)I",
- (void*)nativeInjectSensorData },
+ {"nativeInjectSensorData", "(JI[FIJ)I", (void *)nativeInjectSensorData},
};
} //unnamed namespace
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 065c79b8601f..da60a75ba900 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -1419,6 +1419,28 @@ static jint android_media_AudioTrack_getDualMonoMode(JNIEnv *env, jobject thiz,
return nativeToJavaStatus(status);
}
+static void android_media_AudioTrack_setLogSessionId(JNIEnv *env, jobject thiz,
+ jstring jlogSessionId) {
+ sp<AudioTrack> track = getAudioTrack(env, thiz);
+ if (track == nullptr) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Unable to retrieve AudioTrack pointer for setLogSessionId()");
+ }
+ ScopedUtfChars logSessionId(env, jlogSessionId);
+ ALOGV("%s: logSessionId %s", __func__, logSessionId.c_str());
+ track->setLogSessionId(logSessionId.c_str());
+}
+
+static void android_media_AudioTrack_setPlayerIId(JNIEnv *env, jobject thiz, jint playerIId) {
+ sp<AudioTrack> track = getAudioTrack(env, thiz);
+ if (track == nullptr) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Unable to retrieve AudioTrack pointer for setPlayerIId()");
+ }
+ ALOGV("%s: playerIId %d", __func__, playerIId);
+ track->setPlayerIId(playerIId);
+}
+
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
static const JNINativeMethod gMethods[] = {
@@ -1496,6 +1518,9 @@ static const JNINativeMethod gMethods[] = {
(void *)android_media_AudioTrack_getAudioDescriptionMixLeveldB},
{"native_set_dual_mono_mode", "(I)I", (void *)android_media_AudioTrack_setDualMonoMode},
{"native_get_dual_mono_mode", "([I)I", (void *)android_media_AudioTrack_getDualMonoMode},
+ {"native_setLogSessionId", "(Ljava/lang/String;)V",
+ (void *)android_media_AudioTrack_setLogSessionId},
+ {"native_setPlayerIId", "(I)V", (void *)android_media_AudioTrack_setPlayerIId},
};
// field names found in android/media/AudioTrack.java
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 7a3366acce27..d11ee3a875aa 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -27,6 +27,7 @@
#include <android-base/chrono_utils.h>
#include <android/graphics/region.h>
#include <android/gui/BnScreenCaptureListener.h>
+#include <android/hardware/display/IDeviceProductInfoConstants.h>
#include <android/os/IInputConstants.h>
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/android_hardware_HardwareBuffer.h>
@@ -44,14 +45,15 @@
#include <ui/BlurRegion.h>
#include <ui/ConfigStoreTypes.h>
#include <ui/DeviceProductInfo.h>
-#include <ui/DisplayInfo.h>
#include <ui/DisplayMode.h>
#include <ui/DisplayedFrameStats.h>
+#include <ui/DynamicDisplayInfo.h>
#include <ui/FrameStats.h>
#include <ui/GraphicTypes.h>
#include <ui/HdrCapabilities.h>
#include <ui/Rect.h>
#include <ui/Region.h>
+#include <ui/StaticDisplayInfo.h>
#include <utils/LightRefBase.h>
#include <utils/Log.h>
@@ -86,11 +88,22 @@ static struct {
jfieldID density;
jfieldID secure;
jfieldID deviceProductInfo;
-} gDisplayInfoClassInfo;
+} gStaticDisplayInfoClassInfo;
static struct {
jclass clazz;
jmethodID ctor;
+ jfieldID supportedDisplayModes;
+ jfieldID activeDisplayModeId;
+ jfieldID supportedColorModes;
+ jfieldID activeColorMode;
+ jfieldID hdrCapabilities;
+} gDynamicDisplayInfoClassInfo;
+
+static struct {
+ jclass clazz;
+ jmethodID ctor;
+ jfieldID id;
jfieldID width;
jfieldID height;
jfieldID xDpi;
@@ -580,6 +593,15 @@ static void nativeSetBlurRegions(JNIEnv* env, jclass clazz, jlong transactionObj
transaction->setBlurRegions(ctrl, blurRegionVector);
}
+static void nativeSetStretchEffect(JNIEnv* env, jclass clazz, jlong transactionObj,
+ jlong nativeObject, jfloat left, jfloat top, jfloat right,
+ jfloat bottom, jfloat vecX, jfloat vecY,
+ jfloat maxStretchAmount) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
+ transaction->setStretchEffect(ctrl, left, top, right, bottom, vecX, vecY, maxStretchAmount);
+}
+
static void nativeSetSize(JNIEnv* env, jclass clazz, jlong transactionObj,
jlong nativeObject, jint w, jint h) {
auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
@@ -999,63 +1021,120 @@ static jobject convertDeviceProductInfoToJavaObject(
} else {
LOG_FATAL("Unknown alternative for variant DeviceProductInfo::ManufactureOrModelDate");
}
- auto relativeAddress = env->NewIntArray(info->relativeAddress.size());
- auto relativeAddressData = env->GetIntArrayElements(relativeAddress, nullptr);
- for (int i = 0; i < info->relativeAddress.size(); i++) {
- relativeAddressData[i] = info->relativeAddress[i];
+ jint connectionToSinkType;
+ // Relative address maps to HDMI physical address. All addresses are 4 digits long allowing
+ // for a 5–device-deep hierarchy. For more information, refer:
+ // Section 8.7 - Physical Address of HDMI Specification Version 1.3a
+ using android::hardware::display::IDeviceProductInfoConstants;
+ if (info->relativeAddress.size() != 4) {
+ connectionToSinkType = IDeviceProductInfoConstants::CONNECTION_TO_SINK_UNKNOWN;
+ } else if (info->relativeAddress[0] == 0) {
+ connectionToSinkType = IDeviceProductInfoConstants::CONNECTION_TO_SINK_BUILT_IN;
+ } else if (info->relativeAddress[1] == 0) {
+ connectionToSinkType = IDeviceProductInfoConstants::CONNECTION_TO_SINK_DIRECT;
+ } else {
+ connectionToSinkType = IDeviceProductInfoConstants::CONNECTION_TO_SINK_TRANSITIVE;
}
- env->ReleaseIntArrayElements(relativeAddress, relativeAddressData, 0);
return env->NewObject(gDeviceProductInfoClassInfo.clazz, gDeviceProductInfoClassInfo.ctor, name,
manufacturerPnpId, productId, modelYear, manufactureDate,
- relativeAddress);
+ connectionToSinkType);
}
-static jobject nativeGetDisplayInfo(JNIEnv* env, jclass clazz, jobject tokenObj) {
- DisplayInfo info;
+static jobject nativeGetStaticDisplayInfo(JNIEnv* env, jclass clazz, jobject tokenObj) {
+ ui::StaticDisplayInfo info;
if (const auto token = ibinderForJavaObject(env, tokenObj);
- !token || SurfaceComposerClient::getDisplayInfo(token, &info) != NO_ERROR) {
+ !token || SurfaceComposerClient::getStaticDisplayInfo(token, &info) != NO_ERROR) {
return nullptr;
}
- jobject object = env->NewObject(gDisplayInfoClassInfo.clazz, gDisplayInfoClassInfo.ctor);
- env->SetBooleanField(object, gDisplayInfoClassInfo.isInternal,
- info.connectionType == DisplayConnectionType::Internal);
- env->SetFloatField(object, gDisplayInfoClassInfo.density, info.density);
- env->SetBooleanField(object, gDisplayInfoClassInfo.secure, info.secure);
- env->SetObjectField(object, gDisplayInfoClassInfo.deviceProductInfo,
+ jobject object =
+ env->NewObject(gStaticDisplayInfoClassInfo.clazz, gStaticDisplayInfoClassInfo.ctor);
+ env->SetBooleanField(object, gStaticDisplayInfoClassInfo.isInternal,
+ info.connectionType == ui::DisplayConnectionType::Internal);
+ env->SetFloatField(object, gStaticDisplayInfoClassInfo.density, info.density);
+ env->SetBooleanField(object, gStaticDisplayInfoClassInfo.secure, info.secure);
+ env->SetObjectField(object, gStaticDisplayInfoClassInfo.deviceProductInfo,
convertDeviceProductInfoToJavaObject(env, info.deviceProductInfo));
return object;
}
-static jobjectArray nativeGetDisplayModes(JNIEnv* env, jclass clazz, jobject tokenObj) {
- Vector<ui::DisplayMode> modes;
- if (const auto token = ibinderForJavaObject(env, tokenObj); !token ||
- SurfaceComposerClient::getDisplayModes(token, &modes) != NO_ERROR || modes.isEmpty()) {
+static jobject convertDisplayModeToJavaObject(JNIEnv* env, const ui::DisplayMode& config) {
+ jobject object = env->NewObject(gDisplayModeClassInfo.clazz, gDisplayModeClassInfo.ctor);
+ env->SetIntField(object, gDisplayModeClassInfo.id, config.id);
+ env->SetIntField(object, gDisplayModeClassInfo.width, config.resolution.getWidth());
+ env->SetIntField(object, gDisplayModeClassInfo.height, config.resolution.getHeight());
+ env->SetFloatField(object, gDisplayModeClassInfo.xDpi, config.xDpi);
+ env->SetFloatField(object, gDisplayModeClassInfo.yDpi, config.yDpi);
+
+ env->SetFloatField(object, gDisplayModeClassInfo.refreshRate, config.refreshRate);
+ env->SetLongField(object, gDisplayModeClassInfo.appVsyncOffsetNanos, config.appVsyncOffset);
+ env->SetLongField(object, gDisplayModeClassInfo.presentationDeadlineNanos,
+ config.presentationDeadline);
+ env->SetIntField(object, gDisplayModeClassInfo.group, config.group);
+ return object;
+}
+
+jobject convertDeviceProductInfoToJavaObject(JNIEnv* env, const HdrCapabilities& capabilities) {
+ const auto& types = capabilities.getSupportedHdrTypes();
+ std::vector<int32_t> intTypes;
+ for (auto type : types) {
+ intTypes.push_back(static_cast<int32_t>(type));
+ }
+ auto typesArray = env->NewIntArray(types.size());
+ env->SetIntArrayRegion(typesArray, 0, intTypes.size(), intTypes.data());
+
+ return env->NewObject(gHdrCapabilitiesClassInfo.clazz, gHdrCapabilitiesClassInfo.ctor,
+ typesArray, capabilities.getDesiredMaxLuminance(),
+ capabilities.getDesiredMaxAverageLuminance(),
+ capabilities.getDesiredMinLuminance());
+}
+
+static jobject nativeGetDynamicDisplayInfo(JNIEnv* env, jclass clazz, jobject tokenObj) {
+ ui::DynamicDisplayInfo info;
+ if (const auto token = ibinderForJavaObject(env, tokenObj);
+ !token || SurfaceComposerClient::getDynamicDisplayInfo(token, &info) != NO_ERROR) {
return nullptr;
}
- jobjectArray modesArray =
- env->NewObjectArray(modes.size(), gDisplayModeClassInfo.clazz, nullptr);
+ jobject object =
+ env->NewObject(gDynamicDisplayInfoClassInfo.clazz, gDynamicDisplayInfoClassInfo.ctor);
+ if (object == NULL) {
+ jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ return NULL;
+ }
- for (size_t c = 0; c < modes.size(); ++c) {
- const ui::DisplayMode& mode = modes[c];
- jobject object = env->NewObject(gDisplayModeClassInfo.clazz, gDisplayModeClassInfo.ctor);
- env->SetIntField(object, gDisplayModeClassInfo.width, mode.resolution.getWidth());
- env->SetIntField(object, gDisplayModeClassInfo.height, mode.resolution.getHeight());
- env->SetFloatField(object, gDisplayModeClassInfo.xDpi, mode.xDpi);
- env->SetFloatField(object, gDisplayModeClassInfo.yDpi, mode.yDpi);
+ const auto numModes = info.supportedDisplayModes.size();
+ jobjectArray modesArray = env->NewObjectArray(numModes, gDisplayModeClassInfo.clazz, nullptr);
+ for (size_t i = 0; i < numModes; i++) {
+ const ui::DisplayMode& mode = info.supportedDisplayModes[i];
+ jobject displayModeObj = convertDisplayModeToJavaObject(env, mode);
+ env->SetObjectArrayElement(modesArray, static_cast<jsize>(i), displayModeObj);
+ env->DeleteLocalRef(displayModeObj);
+ }
+ env->SetObjectField(object, gDynamicDisplayInfoClassInfo.supportedDisplayModes, modesArray);
+ env->SetIntField(object, gDynamicDisplayInfoClassInfo.activeDisplayModeId,
+ info.activeDisplayModeId);
- env->SetFloatField(object, gDisplayModeClassInfo.refreshRate, mode.refreshRate);
- env->SetLongField(object, gDisplayModeClassInfo.appVsyncOffsetNanos, mode.appVsyncOffset);
- env->SetLongField(object, gDisplayModeClassInfo.presentationDeadlineNanos,
- mode.presentationDeadline);
- env->SetIntField(object, gDisplayModeClassInfo.group, mode.group);
- env->SetObjectArrayElement(modesArray, static_cast<jsize>(c), object);
- env->DeleteLocalRef(object);
+ jintArray colorModesArray = env->NewIntArray(info.supportedColorModes.size());
+ if (colorModesArray == NULL) {
+ jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+ return NULL;
}
+ jint* colorModesArrayValues = env->GetIntArrayElements(colorModesArray, 0);
+ for (size_t i = 0; i < info.supportedColorModes.size(); i++) {
+ colorModesArrayValues[i] = static_cast<jint>(info.supportedColorModes[i]);
+ }
+ env->ReleaseIntArrayElements(colorModesArray, colorModesArrayValues, 0);
+ env->SetObjectField(object, gDynamicDisplayInfoClassInfo.supportedColorModes, colorModesArray);
+
+ env->SetIntField(object, gDynamicDisplayInfoClassInfo.activeColorMode,
+ static_cast<jint>(info.activeColorMode));
+
+ env->SetObjectField(object, gDynamicDisplayInfoClassInfo.hdrCapabilities,
+ convertDeviceProductInfoToJavaObject(env, info.hdrCapabilities));
- return modesArray;
+ return object;
}
static jboolean nativeSetDesiredDisplayModeSpecs(JNIEnv* env, jclass clazz, jobject tokenObj,
@@ -1063,9 +1142,8 @@ static jboolean nativeSetDesiredDisplayModeSpecs(JNIEnv* env, jclass clazz, jobj
sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
if (token == nullptr) return JNI_FALSE;
- size_t defaultMode =
- static_cast<size_t>(env->GetIntField(DesiredDisplayModeSpecs,
- gDesiredDisplayModeSpecsClassInfo.defaultMode));
+ ui::DisplayModeId defaultMode = env->GetIntField(DesiredDisplayModeSpecs,
+ gDesiredDisplayModeSpecsClassInfo.defaultMode);
jboolean allowGroupSwitching =
env->GetBooleanField(DesiredDisplayModeSpecs,
gDesiredDisplayModeSpecsClassInfo.allowGroupSwitching);
@@ -1095,7 +1173,7 @@ static jobject nativeGetDesiredDisplayModeSpecs(JNIEnv* env, jclass clazz, jobje
sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
if (token == nullptr) return nullptr;
- size_t defaultMode;
+ ui::DisplayModeId defaultMode;
bool allowGroupSwitching;
float primaryRefreshRateMin;
float primaryRefreshRateMax;
@@ -1115,34 +1193,6 @@ static jobject nativeGetDesiredDisplayModeSpecs(JNIEnv* env, jclass clazz, jobje
appRequestRefreshRateMax);
}
-static jint nativeGetActiveDisplayMode(JNIEnv* env, jclass clazz, jobject tokenObj) {
- sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
- if (token == NULL) return -1;
- return static_cast<jint>(SurfaceComposerClient::getActiveDisplayModeId(token));
-}
-
-static jintArray nativeGetDisplayColorModes(JNIEnv* env, jclass, jobject tokenObj) {
- sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
- if (token == NULL) return NULL;
- Vector<ui::ColorMode> colorModes;
- if (SurfaceComposerClient::getDisplayColorModes(token, &colorModes) != NO_ERROR ||
- colorModes.isEmpty()) {
- return NULL;
- }
-
- jintArray colorModesArray = env->NewIntArray(colorModes.size());
- if (colorModesArray == NULL) {
- jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
- return NULL;
- }
- jint* colorModesArrayValues = env->GetIntArrayElements(colorModesArray, 0);
- for (size_t i = 0; i < colorModes.size(); i++) {
- colorModesArrayValues[i] = static_cast<jint>(colorModes[i]);
- }
- env->ReleaseIntArrayElements(colorModesArray, colorModesArrayValues, 0);
- return colorModesArray;
-}
-
static jobject nativeGetDisplayNativePrimaries(JNIEnv* env, jclass, jobject tokenObj) {
sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
if (token == NULL) return NULL;
@@ -1203,12 +1253,6 @@ static jobject nativeGetDisplayNativePrimaries(JNIEnv* env, jclass, jobject toke
return jprimaries;
}
-static jint nativeGetActiveColorMode(JNIEnv* env, jclass, jobject tokenObj) {
- sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
- if (token == NULL) return -1;
- return static_cast<jint>(SurfaceComposerClient::getActiveColorMode(token));
-}
-
static jintArray nativeGetCompositionDataspaces(JNIEnv* env, jclass) {
ui::Dataspace defaultDataspace, wcgDataspace;
ui::PixelFormat defaultPixelFormat, wcgPixelFormat;
@@ -1414,26 +1458,6 @@ static void nativeReparent(JNIEnv* env, jclass clazz, jlong transactionObj,
transaction->reparent(ctrl, newParent);
}
-static jobject nativeGetHdrCapabilities(JNIEnv* env, jclass clazz, jobject tokenObject) {
- sp<IBinder> token(ibinderForJavaObject(env, tokenObject));
- if (token == NULL) return NULL;
-
- HdrCapabilities capabilities;
- SurfaceComposerClient::getHdrCapabilities(token, &capabilities);
-
- const auto& types = capabilities.getSupportedHdrTypes();
- std::vector<int32_t> intTypes;
- for (auto type : types) {
- intTypes.push_back(static_cast<int32_t>(type));
- }
- auto typesArray = env->NewIntArray(types.size());
- env->SetIntArrayRegion(typesArray, 0, intTypes.size(), intTypes.data());
-
- return env->NewObject(gHdrCapabilitiesClassInfo.clazz, gHdrCapabilitiesClassInfo.ctor,
- typesArray, capabilities.getDesiredMaxLuminance(),
- capabilities.getDesiredMaxAverageLuminance(), capabilities.getDesiredMinLuminance());
-}
-
static jboolean nativeGetAutoLowLatencyModeSupport(JNIEnv* env, jclass clazz, jobject tokenObject) {
sp<IBinder> token(ibinderForJavaObject(env, tokenObject));
if (token == NULL) return NULL;
@@ -1754,6 +1778,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeSetLayerStack },
{"nativeSetBlurRegions", "(JJ[[FI)V",
(void*)nativeSetBlurRegions },
+ {"nativeSetStretchEffect", "(JJFFFFFFF)V",
+ (void*) nativeSetStretchEffect },
{"nativeSetShadowRadius", "(JJF)V",
(void*)nativeSetShadowRadius },
{"nativeSetFrameRate", "(JJFIZ)V",
@@ -1778,24 +1804,21 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeSetDisplayProjection },
{"nativeSetDisplaySize", "(JLandroid/os/IBinder;II)V",
(void*)nativeSetDisplaySize },
- {"nativeGetDisplayInfo", "(Landroid/os/IBinder;)Landroid/view/SurfaceControl$DisplayInfo;",
- (void*)nativeGetDisplayInfo },
- {"nativeGetDisplayModes", "(Landroid/os/IBinder;)[Landroid/view/SurfaceControl$DisplayMode;",
- (void*)nativeGetDisplayModes },
- {"nativeGetActiveDisplayMode", "(Landroid/os/IBinder;)I",
- (void*)nativeGetActiveDisplayMode },
+ {"nativeGetStaticDisplayInfo",
+ "(Landroid/os/IBinder;)Landroid/view/SurfaceControl$StaticDisplayInfo;",
+ (void*)nativeGetStaticDisplayInfo },
+ {"nativeGetDynamicDisplayInfo",
+ "(Landroid/os/IBinder;)Landroid/view/SurfaceControl$DynamicDisplayInfo;",
+ (void*)nativeGetDynamicDisplayInfo },
{"nativeSetDesiredDisplayModeSpecs",
"(Landroid/os/IBinder;Landroid/view/SurfaceControl$DesiredDisplayModeSpecs;)Z",
(void*)nativeSetDesiredDisplayModeSpecs },
{"nativeGetDesiredDisplayModeSpecs",
"(Landroid/os/IBinder;)Landroid/view/SurfaceControl$DesiredDisplayModeSpecs;",
(void*)nativeGetDesiredDisplayModeSpecs },
- {"nativeGetDisplayColorModes", "(Landroid/os/IBinder;)[I",
- (void*)nativeGetDisplayColorModes},
- {"nativeGetDisplayNativePrimaries", "(Landroid/os/IBinder;)Landroid/view/SurfaceControl$DisplayPrimaries;",
+ {"nativeGetDisplayNativePrimaries",
+ "(Landroid/os/IBinder;)Landroid/view/SurfaceControl$DisplayPrimaries;",
(void*)nativeGetDisplayNativePrimaries },
- {"nativeGetActiveColorMode", "(Landroid/os/IBinder;)I",
- (void*)nativeGetActiveColorMode},
{"nativeSetActiveColorMode", "(Landroid/os/IBinder;I)Z",
(void*)nativeSetActiveColorMode},
{"nativeGetAutoLowLatencyModeSupport", "(Landroid/os/IBinder;)Z",
@@ -1808,8 +1831,6 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeSetGameContentType },
{"nativeGetCompositionDataspaces", "()[I",
(void*)nativeGetCompositionDataspaces},
- {"nativeGetHdrCapabilities", "(Landroid/os/IBinder;)Landroid/view/Display$HdrCapabilities;",
- (void*)nativeGetHdrCapabilities },
{"nativeClearContentFrameStats", "(J)Z",
(void*)nativeClearContentFrameStats },
{"nativeGetContentFrameStats", "(JLandroid/view/WindowContentFrameStats;)Z",
@@ -1888,19 +1909,36 @@ int register_android_view_SurfaceControl(JNIEnv* env)
gIntegerClassInfo.clazz = MakeGlobalRefOrDie(env, integerClass);
gIntegerClassInfo.ctor = GetMethodIDOrDie(env, gIntegerClassInfo.clazz, "<init>", "(I)V");
- jclass infoClazz = FindClassOrDie(env, "android/view/SurfaceControl$DisplayInfo");
- gDisplayInfoClassInfo.clazz = MakeGlobalRefOrDie(env, infoClazz);
- gDisplayInfoClassInfo.ctor = GetMethodIDOrDie(env, infoClazz, "<init>", "()V");
- gDisplayInfoClassInfo.isInternal = GetFieldIDOrDie(env, infoClazz, "isInternal", "Z");
- gDisplayInfoClassInfo.density = GetFieldIDOrDie(env, infoClazz, "density", "F");
- gDisplayInfoClassInfo.secure = GetFieldIDOrDie(env, infoClazz, "secure", "Z");
- gDisplayInfoClassInfo.deviceProductInfo =
+ jclass infoClazz = FindClassOrDie(env, "android/view/SurfaceControl$StaticDisplayInfo");
+ gStaticDisplayInfoClassInfo.clazz = MakeGlobalRefOrDie(env, infoClazz);
+ gStaticDisplayInfoClassInfo.ctor = GetMethodIDOrDie(env, infoClazz, "<init>", "()V");
+ gStaticDisplayInfoClassInfo.isInternal = GetFieldIDOrDie(env, infoClazz, "isInternal", "Z");
+ gStaticDisplayInfoClassInfo.density = GetFieldIDOrDie(env, infoClazz, "density", "F");
+ gStaticDisplayInfoClassInfo.secure = GetFieldIDOrDie(env, infoClazz, "secure", "Z");
+ gStaticDisplayInfoClassInfo.deviceProductInfo =
GetFieldIDOrDie(env, infoClazz, "deviceProductInfo",
"Landroid/hardware/display/DeviceProductInfo;");
+ jclass dynamicInfoClazz = FindClassOrDie(env, "android/view/SurfaceControl$DynamicDisplayInfo");
+ gDynamicDisplayInfoClassInfo.clazz = MakeGlobalRefOrDie(env, dynamicInfoClazz);
+ gDynamicDisplayInfoClassInfo.ctor = GetMethodIDOrDie(env, dynamicInfoClazz, "<init>", "()V");
+ gDynamicDisplayInfoClassInfo.supportedDisplayModes =
+ GetFieldIDOrDie(env, dynamicInfoClazz, "supportedDisplayModes",
+ "[Landroid/view/SurfaceControl$DisplayMode;");
+ gDynamicDisplayInfoClassInfo.activeDisplayModeId =
+ GetFieldIDOrDie(env, dynamicInfoClazz, "activeDisplayModeId", "I");
+ gDynamicDisplayInfoClassInfo.supportedColorModes =
+ GetFieldIDOrDie(env, dynamicInfoClazz, "supportedColorModes", "[I");
+ gDynamicDisplayInfoClassInfo.activeColorMode =
+ GetFieldIDOrDie(env, dynamicInfoClazz, "activeColorMode", "I");
+ gDynamicDisplayInfoClassInfo.hdrCapabilities =
+ GetFieldIDOrDie(env, dynamicInfoClazz, "hdrCapabilities",
+ "Landroid/view/Display$HdrCapabilities;");
+
jclass modeClazz = FindClassOrDie(env, "android/view/SurfaceControl$DisplayMode");
gDisplayModeClassInfo.clazz = MakeGlobalRefOrDie(env, modeClazz);
gDisplayModeClassInfo.ctor = GetMethodIDOrDie(env, modeClazz, "<init>", "()V");
+ gDisplayModeClassInfo.id = GetFieldIDOrDie(env, modeClazz, "id", "I");
gDisplayModeClassInfo.width = GetFieldIDOrDie(env, modeClazz, "width", "I");
gDisplayModeClassInfo.height = GetFieldIDOrDie(env, modeClazz, "height", "I");
gDisplayModeClassInfo.xDpi = GetFieldIDOrDie(env, modeClazz, "xDpi", "F");
@@ -1948,7 +1986,7 @@ int register_android_view_SurfaceControl(JNIEnv* env)
"Ljava/lang/String;"
"Ljava/lang/Integer;"
"Landroid/hardware/display/DeviceProductInfo$ManufactureDate;"
- "[I)V");
+ "I)V");
jclass deviceProductInfoManufactureDateClazz =
FindClassOrDie(env, "android/hardware/display/DeviceProductInfo$ManufactureDate");
diff --git a/core/jni/com_android_internal_os_KernelCpuBpfTracking.cpp b/core/jni/com_android_internal_os_KernelCpuBpfTracking.cpp
index e6a82f6d0cb5..6b41b2ec8f93 100644
--- a/core/jni/com_android_internal_os_KernelCpuBpfTracking.cpp
+++ b/core/jni/com_android_internal_os_KernelCpuBpfTracking.cpp
@@ -24,8 +24,48 @@ static jboolean KernelCpuBpfTracking_isSupported(JNIEnv *, jobject) {
return android::bpf::isTrackingUidTimesSupported() ? JNI_TRUE : JNI_FALSE;
}
+static jboolean KernelCpuBpfTracking_startTrackingInternal(JNIEnv *, jobject) {
+ return android::bpf::startTrackingUidTimes();
+}
+
+static jlongArray KernelCpuBpfTracking_getFreqsInternal(JNIEnv *env, jobject) {
+ auto freqs = android::bpf::getCpuFreqs();
+ if (!freqs) return NULL;
+
+ std::vector<uint64_t> allFreqs;
+ for (const auto &vec : *freqs) std::copy(vec.begin(), vec.end(), std::back_inserter(allFreqs));
+
+ auto ar = env->NewLongArray(allFreqs.size());
+ if (ar != NULL) {
+ env->SetLongArrayRegion(ar, 0, allFreqs.size(),
+ reinterpret_cast<const jlong *>(allFreqs.data()));
+ }
+ return ar;
+}
+
+static jintArray KernelCpuBpfTracking_getFreqsClustersInternal(JNIEnv *env, jobject) {
+ auto freqs = android::bpf::getCpuFreqs();
+ if (!freqs) return NULL;
+
+ std::vector<uint32_t> freqsClusters;
+ uint32_t clusters = freqs->size();
+ for (uint32_t c = 0; c < clusters; ++c) {
+ freqsClusters.insert(freqsClusters.end(), (*freqs)[c].size(), c);
+ }
+
+ auto ar = env->NewIntArray(freqsClusters.size());
+ if (ar != NULL) {
+ env->SetIntArrayRegion(ar, 0, freqsClusters.size(),
+ reinterpret_cast<const jint *>(freqsClusters.data()));
+ }
+ return ar;
+}
+
static const JNINativeMethod methods[] = {
{"isSupported", "()Z", (void *)KernelCpuBpfTracking_isSupported},
+ {"startTrackingInternal", "()Z", (void *)KernelCpuBpfTracking_startTrackingInternal},
+ {"getFreqsInternal", "()[J", (void *)KernelCpuBpfTracking_getFreqsInternal},
+ {"getFreqsClustersInternal", "()[I", (void *)KernelCpuBpfTracking_getFreqsClustersInternal},
};
int register_com_android_internal_os_KernelCpuBpfTracking(JNIEnv *env) {
diff --git a/core/jni/com_android_internal_os_KernelCpuTotalBpfMapReader.cpp b/core/jni/com_android_internal_os_KernelCpuTotalBpfMapReader.cpp
index 72492381e31a..ad43014d321f 100644
--- a/core/jni/com_android_internal_os_KernelCpuTotalBpfMapReader.cpp
+++ b/core/jni/com_android_internal_os_KernelCpuTotalBpfMapReader.cpp
@@ -20,33 +20,27 @@
namespace android {
-static jboolean KernelCpuTotalBpfMapReader_read(JNIEnv *env, jobject, jobject callback) {
- jclass callbackClass = env->GetObjectClass(callback);
- jmethodID callbackMethod = env->GetMethodID(callbackClass, "accept", "(IIJ)V");
- if (callbackMethod == 0) {
- return JNI_FALSE;
- }
-
- auto freqs = android::bpf::getCpuFreqs();
- if (!freqs) return JNI_FALSE;
+static jlongArray KernelCpuTotalBpfMapReader_readInternal(JNIEnv *env, jobject) {
auto freqTimes = android::bpf::getTotalCpuFreqTimes();
if (!freqTimes) return JNI_FALSE;
- auto freqsClusterSize = (*freqs).size();
- for (uint32_t clusterIndex = 0; clusterIndex < freqsClusterSize; ++clusterIndex) {
- auto freqsSize = (*freqs)[clusterIndex].size();
- for (uint32_t freqIndex = 0; freqIndex < freqsSize; ++freqIndex) {
- env->CallVoidMethod(callback, callbackMethod, clusterIndex,
- (*freqs)[clusterIndex][freqIndex],
- (*freqTimes)[clusterIndex][freqIndex] / 1000000);
+ std::vector<uint64_t> allTimes;
+ for (const auto &vec : *freqTimes) {
+ for (const auto &timeNs : vec) {
+ allTimes.push_back(timeNs / 1000000);
}
}
- return JNI_TRUE;
+
+ auto ar = env->NewLongArray(allTimes.size());
+ if (ar != NULL) {
+ env->SetLongArrayRegion(ar, 0, allTimes.size(),
+ reinterpret_cast<const jlong *>(allTimes.data()));
+ }
+ return ar;
}
static const JNINativeMethod methods[] = {
- {"read", "(Lcom/android/internal/os/KernelCpuTotalBpfMapReader$Callback;)Z",
- (void *)KernelCpuTotalBpfMapReader_read},
+ {"readInternal", "()[J", (void *)KernelCpuTotalBpfMapReader_readInternal},
};
int register_com_android_internal_os_KernelCpuTotalBpfMapReader(JNIEnv *env) {
diff --git a/core/jni/com_android_internal_os_KernelCpuUidBpfMapReader.cpp b/core/jni/com_android_internal_os_KernelCpuUidBpfMapReader.cpp
index 7c68de504417..7900d301dbb0 100644
--- a/core/jni/com_android_internal_os_KernelCpuUidBpfMapReader.cpp
+++ b/core/jni/com_android_internal_os_KernelCpuUidBpfMapReader.cpp
@@ -82,25 +82,9 @@ static jboolean KernelCpuUidFreqTimeBpfMapReader_readBpfData(JNIEnv *env, jobjec
return true;
}
-static jlongArray KernelCpuUidFreqTimeBpfMapReader_getDataDimensions(JNIEnv *env, jobject) {
- auto freqs = android::bpf::getCpuFreqs();
- if (!freqs) return NULL;
-
- std::vector<uint64_t> allFreqs;
- for (const auto &vec : *freqs) std::copy(vec.begin(), vec.end(), std::back_inserter(allFreqs));
-
- auto ar = env->NewLongArray(allFreqs.size());
- if (ar != NULL) {
- env->SetLongArrayRegion(ar, 0, allFreqs.size(),
- reinterpret_cast<const jlong *>(allFreqs.data()));
- }
- return ar;
-}
-
static const JNINativeMethod gFreqTimeMethods[] = {
{"removeUidRange", "(II)Z", (void *)KernelCpuUidFreqTimeBpfMapReader_removeUidRange},
{"readBpfData", "()Z", (void *)KernelCpuUidFreqTimeBpfMapReader_readBpfData},
- {"getDataDimensions", "()[J", (void *)KernelCpuUidFreqTimeBpfMapReader_getDataDimensions},
};
static jboolean KernelCpuUidActiveTimeBpfMapReader_readBpfData(JNIEnv *env, jobject thiz) {
@@ -186,10 +170,6 @@ static const readerMethods gAllMethods[] = {
{"KernelCpuUidClusterTimeBpfMapReader", gClusterTimeMethods, NELEM(gClusterTimeMethods)},
};
-static jboolean KernelCpuUidBpfMapReader_startTrackingBpfTimes(JNIEnv *, jobject) {
- return android::bpf::startTrackingUidTimes();
-}
-
int register_com_android_internal_os_KernelCpuUidBpfMapReader(JNIEnv *env) {
gSparseArrayClassInfo.clazz = FindClassOrDie(env, "android/util/SparseArray");
gSparseArrayClassInfo.clazz = MakeGlobalRefOrDie(env, gSparseArrayClassInfo.clazz);
@@ -198,14 +178,10 @@ int register_com_android_internal_os_KernelCpuUidBpfMapReader(JNIEnv *env) {
gSparseArrayClassInfo.get =
GetMethodIDOrDie(env, gSparseArrayClassInfo.clazz, "get", "(I)Ljava/lang/Object;");
constexpr auto readerName = "com/android/internal/os/KernelCpuUidBpfMapReader";
- constexpr JNINativeMethod method = {"startTrackingBpfTimes", "()Z",
- (void *)KernelCpuUidBpfMapReader_startTrackingBpfTimes};
-
- int ret = RegisterMethodsOrDie(env, readerName, &method, 1);
- if (ret < 0) return ret;
auto c = FindClassOrDie(env, readerName);
gmData = GetFieldIDOrDie(env, c, "mData", "Landroid/util/SparseArray;");
+ int ret = 0;
for (const auto &m : gAllMethods) {
auto fullName = android::base::StringPrintf("%s$%s", readerName, m.name);
ret = RegisterMethodsOrDie(env, fullName.c_str(), m.methods, m.numMethods);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index a85996afa900..5dd85805cfc1 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3983,6 +3983,13 @@
<permission android:name="com.android.permission.USE_INSTALLER_V2"
android:protectionLevel="signature|verifier" />
+ <!-- Allows an application to use System Data Loaders.
+ <p>Not for use by third-party applications.
+ @hide
+ -->
+ <permission android:name="com.android.permission.USE_SYSTEM_DATA_LOADERS"
+ android:protectionLevel="signature" />
+
<!-- @SystemApi @TestApi Allows an application to clear user data.
<p>Not for use by third-party applications
@hide
diff --git a/core/res/res/drawable/toast_frame.xml b/core/res/res/drawable/toast_frame.xml
index d57bd6a554e1..44c00c0521b4 100644
--- a/core/res/res/drawable/toast_frame.xml
+++ b/core/res/res/drawable/toast_frame.xml
@@ -17,8 +17,7 @@
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
- <!-- background is material_grey_200 with .9 alpha -->
- <solid android:color="#E6EEEEEE" />
- <corners android:radius="22dp" />
+ <solid android:color="?android:attr/colorBackground" />
+ <corners android:radius="28dp" />
</shape>
diff --git a/core/res/res/layout/transient_notification.xml b/core/res/res/layout/transient_notification.xml
index db586ec37cf1..8fcb77ff4ebd 100644
--- a/core/res/res/layout/transient_notification.xml
+++ b/core/res/res/layout/transient_notification.xml
@@ -18,24 +18,27 @@
*/
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:background="?android:attr/toastFrameBackground">
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:gravity="center_vertical"
+ android:maxWidth="@dimen/toast_width"
+ android:background="?android:attr/toastFrameBackground"
+ android:layout_marginEnd="16dp"
+ android:layout_marginStart="16dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp">
<TextView
android:id="@android:id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_weight="1"
- android:layout_marginHorizontal="24dp"
- android:layout_marginVertical="15dp"
- android:layout_gravity="center_horizontal"
- android:textAppearance="@style/TextAppearance.Toast"
- android:textColor="@color/primary_text_default_material_light"
- />
-
+ android:ellipsize="end"
+ android:maxLines="2"
+ android:paddingTop="12dp"
+ android:paddingBottom="12dp"
+ android:lineHeight="20sp"
+ android:textAppearance="@style/TextAppearance.Toast"/>
</LinearLayout>
-
-
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index d7474d050399..aa4baf3c94c0 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Laat die program toe om Moenie Steur Nie-opstelling te lees en skryf."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"begin kyk van toestemminggebruik"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Laat die houer toe om die toestemminggebruik vir \'n program te begin. Behoort nooit vir normale programme nodig te wees nie."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"kry toegang tot sensordata teen \'n hoë monsternemingkoers"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Laat die program toe om monsters van sensordata teen \'n hoër koers as 200 Hz te neem"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Stel wagwoordreëls"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Beheer die lengte en die karakters wat in skermslotwagwoorde en -PIN\'e toegelaat word."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Monitor pogings om skerm te ontsluit"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS-versoek is na video-oproep toe verander"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS-versoek is na USSD-versoek toe verander"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Na nuwe SS-versoek toe verander"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Werkprofiel"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Kennisgewing gegee"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Vou uit"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 8283584758cc..9b11350ba686 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"መተግበሪያው የአትረብሽ ውቅረትን እንዲያነብብ እና እንዲጸፍ ይፈቅዳል።"</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"የእይታ ፈቃድ መጠቀምን መጀመር"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"ያዢው ለአንድ መተግበሪያ የፈቃድ አጠቃቀሙን እንዲያስጀምር ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ ሊያስፈልግ አይገባም።"</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"የዳሳሽ ውሂቡን በከፍተኛ የናሙና ብዛት ላይ ይድረሱበት"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"መተግበሪያው የዳሳሽ ውሂቡን ከ200 ኸ በሚበልጥ ፍጥነት ናሙና እንዲያደርግ ይፈቅድለታል"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"የይለፍ ቃል ደንቦች አዘጋጅ"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"በማያ ገጽ መቆለፊያ የይለፍ ቃሎች እና ፒኖች ውስጥ የሚፈቀዱ ቁምፊዎችን እና ርዝመታቸውን ተቆጣጠር።"</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"የማሳያ-ክፈት ሙከራዎችን ክትትል ያድርጉባቸው"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"የSS ጥያቄ ወደ የቪዲዮ ጥሪ ተለውጧል"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"የSS ጥያቄ ወደ የUSSD ጥያቄ ተለውጧል"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"ወደ አዲስ የSS ጥያቄ ተለውጧል"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"የስራ መገለጫ"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"ነቅተዋል"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"ዘርጋ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index d0dd5fb52ecf..bbf30fe42104 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -697,10 +697,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"للسماح للتطبيق بقراءة إعداد \"عدم الإزعاج\" وكتابتها."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"بدء استخدام إذن العرض"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"للسماح للمالك ببدء استخدام الإذن لأحد التطبيقات. ولن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"الوصول إلى بيانات جهاز الاستشعار بمعدّل مرتفع للبيانات في الملف الصوتي"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"يسمح هذا الأذن للتطبيق بزيادة بيانات جهاز الاستشعار بمعدّل بيانات في الملف الصوتي أكبر من 200 هرتز."</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"تعيين قواعد كلمة المرور"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"للتحكم في الطول والأحرف المسموح بها في كلمات المرور وأرقام التعريف الشخصي في قفل الشاشة."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"مراقبة محاولات فتح قفل الشاشة"</string>
@@ -1997,6 +1995,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"‏تم تغيير طلب SS إلى مكالمة فيديو."</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"‏تم تغيير طلب SS إلى طلب USSD."</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"‏تم التغيير إلى طلب SS الجديد."</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"الملف الشخصي للعمل"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"تمّ تفعيل التنبيه"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"توسيع"</string>
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index f6fc09f8d5e7..e4f657fb5aec 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"অসুবিধা নিদিবৰ কনফিগাৰেশ্বনক পঢ়িবলৈ আৰু সালসলনি কৰিবলৈ এপটোক অনুমতি দিয়ে।"</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"চোৱাৰ অনুমতিৰ ব্যৱহাৰ আৰম্ভ কৰক"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"ধাৰকক কোনো এপৰ বাবে অনুমতিৰ ব্যৱহাৰ আৰম্ভ কৰিবলৈ দিয়ে। সাধাৰণ এপ্‌সমূহৰ বাবে কেতিয়াও প্ৰয়োজন হ’ব নালাগে।"</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"এটা উচ্চ ছেম্পলিঙৰ হাৰত ছেন্সৰৰ ডেটা এক্সেছ কৰে"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"এপ্‌টোক ২০০ হাৰ্টজতকৈ অধিক হাৰত ছেন্সৰৰ ডেটাৰ নমুনা ল’বলৈ অনুমতি দিয়ে"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"পাছৱর্ডৰ নিয়ম ছেট কৰক"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"স্ক্ৰীণ লক পাছৱৰ্ড আৰু পিনৰ দৈর্ঘ্য আৰু কি কি আখৰ ব্যৱহাৰ কৰিব পাৰে তাক নিয়ন্ত্ৰণ কৰক।"</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"স্ক্ৰীণ আনলক কৰা প্ৰয়াসবোৰ পৰ্যবেক্ষণ কৰিব পাৰে"</string>
@@ -1873,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS অনুৰোধ ভিডিঅ\' কললৈ সলনি কৰা হ’ল"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS অনুৰোধ USSD অনুৰোধলৈ সলনি কৰা হ’ল"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"নতুন SS অনুৰোধলৈ সলনি কৰা হ’ল"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"ফিশ্বিঙৰ সতৰ্কবাৰ্তা"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"কৰ্মস্থানৰ প্ৰ\'ফাইল"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"সতৰ্ক কৰা হ’ল"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"বিস্তাৰ কৰক"</string>
diff --git a/core/res/res/values-az/strings.xml b/core/res/res/values-az/strings.xml
index 58d225d4d854..549784d95765 100644
--- a/core/res/res/values-az/strings.xml
+++ b/core/res/res/values-az/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Tətbiqə \"Narahat Etməyin\" konfiqurasiyasını oxumağa və yazmağa icazə verin."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"Baxış icazəsinin istifadəsinə başlayın"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Sahibinə tətbiqin icazədən istifadəsinə başlamağa imkan verir. Adi tətbiqlər üçün heç vaxt tələb edilmir."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"sensor datasına yüksək ölçmə sürəti ilə giriş etmək"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Tətbiqə sensor datasını 200 Hz-dən yüksək sürətlə ölçməyə imkan verir"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Parol qaydalarını təyin edin"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Ekran kilidinin parolu və PINlərində icazə verilən uzunluq və simvollara nəzarət edin."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Ekranı kiliddən çıxarmaq üçün edilən cəhdlərə nəzarət edin"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS sorğusu video zəngə dəyişdirildi"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS sorğusu USSD sorğusuna dəyişdirildi"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Yeni SS sorğusuna dəyişdirildi"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"İş profili"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Xəbərdarlıq edildi"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Genişləndirin"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 1569bd13797c..5709e3d5f445 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -688,10 +688,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Dozvoljava aplikaciji da čita i upisuje konfiguraciju podešavanja Ne uznemiravaj."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"početak korišćenja dozvole za pregled"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Dozvoljava vlasniku da započne korišćenje dozvole za aplikaciju. Nikada ne bi trebalo da bude potrebna za uobičajene aplikacije."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"pristup podacima senzora pri velikoj brzini uzorkovanja"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Dozvoljava aplikaciji da uzima uzorak podataka senzora pri brzini većoj od 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Podešavanje pravila za lozinku"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Kontroliše dužinu i znakove dozvoljene u lozinkama i PIN-ovima za zaključavanje ekrana."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Nadgledajte pokušaje otključavanja ekrana"</string>
@@ -1904,6 +1902,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS zahtev je promenjen u video poziv"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS zahtev je promenjen u USSD zahtev"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Promenjeno je u novi SS zahtev"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Upozorenje o „pecanju“"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Poslovni profil"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Obavešteno"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Proširi"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index f1f7e0cc2313..880c9860b244 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -691,10 +691,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Дазваляе праграме чытаць і выконваць запіс у канфігурацыю рэжыму «Не турбаваць»."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"запусціць выкарыстанне дазволаў на прагляд"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Дазваляе трымальніку запусціць выкарыстанне дазволаў праграмай. Не патрэбна для звычайных праграм."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"атрымліваць даныя датчыка з высокай частатой дыскрэтызацыі"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Праграма зможа распазнаваць даныя датчыка з частатой звыш 200 Гц"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Устанавіць правілы паролю"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Кіраваць даўжынёй і сімваламі, дазволенымі пры ўводзе пароляў і PIN-кодаў блакіроўкі экрана."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Сачыць за спробамі разблакіроўкі экрана"</string>
@@ -1935,6 +1933,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS-запыт заменены на відэавыклік"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS-запыт заменены на USSD-запыт"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Зроблена замена на новы SS-запыт"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Працоўны профіль"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"З гукам"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Разгарнуць"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 076df22cbe7b..2ed363fca997 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Предоставя на приложението достъп за четене и запис до конфигурацията на „Не безпокойте“."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"стартиране на прегледа на използваните разрешения"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Разрешава на притежателя да стартира прегледа на използваните разрешения за дадено приложение. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"осъществяване на достъп до данните от сензорите при висока скорост на семплиране"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Разрешава на приложението да семплира данните от сензорите със скорост, по-висока от 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Задаване на правила за паролата"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Контролира дължината и разрешените знаци за паролите и ПИН кодовете за заключване на екрана."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Наблюдаване на опитите за отключване на екрана"</string>
@@ -1873,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS заявката е променена на видеообаждане"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS заявката е променена на USSD заявка"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Променено на нова SS заявка"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Сигнал за фишинг"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Служебен потребителски профил"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Сигналът е изпратен"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Разгъване"</string>
diff --git a/core/res/res/values-bn/strings.xml b/core/res/res/values-bn/strings.xml
index c7fb8bd21e33..dd38e9aac67f 100644
--- a/core/res/res/values-bn/strings.xml
+++ b/core/res/res/values-bn/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"অ্যাপটিকে \'বিরক্ত করবে না\' কনফিগারেশন পড়া এবং লেখার অনুমতি দেয়।"</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"দেখার অনুমতি কাজে লাগানো শুরু করুন"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"কোনও অ্যাপের কোনও নির্দিষ্ট অনুমতির ব্যবহার শুরু করার ক্ষেত্রে হোল্ডারকে সাহায্য করে। সাধারণ অ্যাপের জন্য এটির পরিবর্তন হওয়ার কথা নয়।"</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"হাই স্যাম্পলিং রেটে সেন্সর ডেটা অ্যাক্সেস করুন"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"200 Hz-এর বেশি রেটে অ্যাপকে স্যাম্পল সেন্সর ডেটার জন্য অনুমতি দিন"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"পাসওয়ার্ড নিয়মগুলি সেট করে"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"স্ক্রিন লক করার পাসওয়ার্ডগুলিতে অনুমতিপ্রাপ্ত অক্ষর এবং দৈর্ঘ্য নিয়ন্ত্রণ করে৷"</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"স্ক্রিন আনলক করার প্রচেষ্টাগুলির উপরে নজর রাখুন"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS অনুরোধ ভিডিও কলে পরিবর্তন করা হয়েছে"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS অনুরোধ USSD অনুরোধে পরিবর্তন করা হয়েছে"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"নতুন SS অনুরোধে পরিবর্তন করা হয়েছে"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"কর্মস্থলের প্রোফাইল"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"সতর্ক করা হয়েছে"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"বড় করুন"</string>
diff --git a/core/res/res/values-bs/strings.xml b/core/res/res/values-bs/strings.xml
index 393e70224b9c..d5b10d52db2d 100644
--- a/core/res/res/values-bs/strings.xml
+++ b/core/res/res/values-bs/strings.xml
@@ -688,10 +688,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Omogućava aplikaciji da čita i upisuje konfiguraciju načina rada Ne ometaj."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"pokrenuti korištenje odobrenja za pregled"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Dozvoljava vlasniku da pokrene korištenje odobrenja za aplikaciju. Ne bi trebalo biti potrebno za obične aplikacije."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"pristup podacima senzora velikom brzinom uzorkovanja"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Dozvoljava aplikaciji da uzorkuje podatke senzora većom brzinom od 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Postavljanje pravila za lozinke"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Kontrolira dužinu i znakove koji su dozvoljeni u lozinkama za zaključavanje ekrana i PIN-ovima."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Prati pokušaje otključavanja ekrana"</string>
@@ -1904,6 +1902,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS zahtjev je promijenjen u video poziv"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS zahtjev je promijenjen u USSD zahtjev"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Promijenjeno u novi SS zahtjev"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Upozorenje o krađi identiteta"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Profil za posao"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Upozoreni"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Proširi"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 56131e3e4386..280fe1ab030f 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Permet que l\'aplicació llegeixi la configuració No molestis i hi escrigui."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"comença a utilitzar el permís de visualització"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Permet que un propietari comenci a utilitzar el permís amb una aplicació. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"accedir a les dades del sensor a una freqüència de mostratge alta"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Permet que l\'aplicació dugui a terme un mostratge de les dades del sensor a una freqüència superior a 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Definir les normes de contrasenya"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Permet controlar la longitud i el nombre de caràcters permesos a les contrasenyes i als PIN del bloqueig de pantalla."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Supervisar els intents de desbloqueig de la pantalla"</string>
@@ -1873,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"La sol·licitud SS s\'ha canviat per una videotrucada"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"La sol·licitud SS s\'ha canviat per una sol·licitud USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"S\'ha canviat a una nova sol·licitud SS"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Alerta de pesca de credencials"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Perfil de treball"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"S\'ha enviat una alerta"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Desplega"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 7f20d3f0511c..091ed836a37c 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -691,10 +691,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Umožňuje aplikaci číst a zapisovat konfiguraci režimu Nerušit."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"zahájení zobrazení využití oprávnění"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Umožňuje přístup zahájit využití oprávnění jiné aplikace. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"přístup k datům ze senzorů s vyšší vzorkovací frekvencí"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Umožňuje aplikaci vzorkovat data ze senzorů s frekvencí vyšší než 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Nastavit pravidla pro heslo"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Ovládání délky a znaků povolených v heslech a kódech PIN zámku obrazovky."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Sledovat pokusy o odemknutí obrazovky"</string>
@@ -1935,6 +1933,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Požadavek SS byl změněn na videohovor"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Požadavek SS byl změněn na požadavek USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Změněno na nový požadavek SS"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Pracovní profil"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Upozorněno"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Rozbalit"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index d0effa6628e5..8e191003ca9d 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -687,10 +687,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Giver appen tilladelse til at læse og redigere konfigurationen af Forstyr ikke."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"start brugen at tilladelsesvisning"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Tillader, at brugeren kan bruge en tilladelse for en app. Dette bør aldrig være nødvendigt for almindelige apps."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"få adgang til sensordata ved høj samplingfrekvens"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Tillader, at appen kan sample sensordata ved en højere frekvens end 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Angiv regler for adgangskoder"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Tjek længden samt tilladte tegn i adgangskoder og pinkoder til skærmlåsen."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Overvåg forsøg på oplåsning af skærm"</string>
@@ -1875,6 +1873,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS-anmodningen blev ændret til et videoopkald"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS-anmodningen blev ændret til en USSD-anmodning"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Ændret til en SS-anmodning"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Arbejdsprofil"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Underrettet"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Udvid"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 70459411bf1d..d9710e6eee64 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Ermöglicht der App Lese- und Schreibzugriff auf die \"Bitte nicht stören\"-Konfiguration"</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"Mit der Verwendung der Anzeigeberechtigung beginnen"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Ermöglicht dem Inhaber, die Berechtigungsnutzung für eine App zu beginnen. Sollte für normale Apps nie benötigt werden."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"Sensordaten mit hoher Frequenz auslesen"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Erlaubt der App, Sensordaten mit einer Frequenz von mehr als 200 Hz auszulesen"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Passwortregeln festlegen"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Zulässige Länge und Zeichen für Passwörter für die Displaysperre festlegen"</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Versuche zum Entsperren des Displays überwachen"</string>
@@ -1873,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS-Anfrage wurde in Videoanruf geändert"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS-Anfrage wurde in USSD-Anfrage geändert"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"In neue SS-Anfrage geändert"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Phishing-Warnung"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Arbeitsprofil"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Gewarnt"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Maximieren"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 8d14b3bbe710..358a1f192cd0 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Επιτρέπει στην εφαρμογή την εγγραφή και τη σύνταξη διαμόρφωσης για τη λειτουργία \"Μην ενοχλείτε\"."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"έναρξη χρήσης άδειας προβολής"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Επιτρέπει στον κάτοχο να ξεκινήσει τη χρήση της άδειας για μια εφαρμογή. Δεν απαιτείται ποτέ για κανονικές εφαρμογές."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"πρόσβαση σε δεδομένα αισθητήρα με υψηλό ρυθμό δειγματοληψίας"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Επιτρέπει στην εφαρμογή τη δειγματοληψία των δεδομένων αισθητήρα με ρυθμό μεγαλύτερο από 200 Hz."</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Ορισμός κανόνων κωδικού πρόσβασης"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Ελέγξτε την έκταση και τους επιτρεπόμενους χαρακτήρες σε κωδικούς πρόσβασης κλειδώματος οθόνης και PIN."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Παρακολούθηση προσπαθειών ξεκλειδώματος οθόνης"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Το αίτημα SS τροποποιήθηκε σε βιντεοκλήση"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Το αίτημα SS τροποποιήθηκε σε αίτημα USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Τροποποιήθηκε σε νέο αίτημα SS"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Προφίλ εργασίας"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Ειδοποιήθηκε"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Ανάπτυξη"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 51e4ef79ddba..058ae7748dab 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1871,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS request changed to video call"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS request changed to USSD request"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Changed to new SS request"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Phishing alert"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Work profile"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Alerted"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Expand"</string>
diff --git a/core/res/res/values-en-rCA/strings.xml b/core/res/res/values-en-rCA/strings.xml
index 3e99738a8900..d91b3d0ed4ed 100644
--- a/core/res/res/values-en-rCA/strings.xml
+++ b/core/res/res/values-en-rCA/strings.xml
@@ -1871,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS request changed to video call"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS request changed to USSD request"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Changed to new SS request"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Phishing alert"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Work profile"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Alerted"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Expand"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 464a44ba3df4..60950ee208b4 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1871,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS request changed to video call"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS request changed to USSD request"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Changed to new SS request"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Phishing alert"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Work profile"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Alerted"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Expand"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 2b8cd8681a57..1915d45370f8 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1871,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS request changed to video call"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS request changed to USSD request"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Changed to new SS request"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Phishing alert"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Work profile"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Alerted"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Expand"</string>
diff --git a/core/res/res/values-en-rXC/strings.xml b/core/res/res/values-en-rXC/strings.xml
index 9d073b9edf86..0a90aeacfd77 100644
--- a/core/res/res/values-en-rXC/strings.xml
+++ b/core/res/res/values-en-rXC/strings.xml
@@ -1871,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‎‏‏‎‎‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‏‏‏‎‏‎‎‎‏‎‏‎‎‏‎‏‎‏‎‏‏‎‎‎‎SS request changed to video call‎‏‎‎‏‎"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‏‎‎‏‏‎‏‎‎‏‎‎‏‏‎‏‎‎‎‎‎‏‎‏‏‎‎‎‏‎‏‎‏‎‎‎‏‏‎‏‎‎‏‏‏‎‎‎‎‎‎‎‏‏‏‏‎‎‎‎SS request changed to USSD request‎‏‎‎‏‎"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‎‏‏‏‏‎‏‎‏‎‏‎‎‎‏‏‎‏‎‎‏‎‎‎‏‎‎‎‏‏‎‏‎‎‏‎‏‏‏‎‎‏‎‏‎‎‏‏‎‏‏‎‎‎‏‎‎‏‎‎Changed to new SS request‎‏‎‎‏‎"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‏‎‏‏‎‏‏‏‏‎‏‏‎‎‏‎‎‎‏‏‏‎‏‏‎‎‏‏‏‏‎‎‎‎‎‏‎‏‎‎‏‎‏‏‎‏‎‎‎‎‎‎‏‏‎‎Phishing alert‎‏‎‎‏‎"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‎‎‎‎‎‎‏‏‎‏‏‏‏‎‏‎‏‎‎‎‏‏‏‎‎‎‎‏‎‎‏‏‎‏‏‎‏‏‏‎‏‎‎‏‎‎‎‏‏‎‎‏‏‏‎Work profile‎‏‎‎‏‎"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‏‎‏‎‎‏‎‎‏‎‎‎‎‏‎‏‎‏‎‏‎‎‏‏‎‏‎‏‎‎‎‎‏‎‎‏‎‎‏‏‏‏‏‏‏‏‏‎‎‏‎‎‎‎Alerted‎‏‎‎‏‎"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‏‏‏‎‎‎‎‎‎‏‏‏‏‏‎‎‎‏‎‎‎‎‏‏‎‎‏‏‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‏‏‎‎‎‏‏‏‎‎‏‏‏‎Expand‎‏‎‎‏‎"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index 333bdc804369..e81d6d158fe6 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -1871,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Se cambió la solicitud SS por una videollamada"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Se cambió la solicitud SS por una solicitud USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Se cambió a una nueva solicitud SS"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Perfil de trabajo"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Alerta enviada"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Expandir"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 476193e3102f..70cac4a58781 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Permite que la aplicación lea y modifique la configuración de No molestar."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"iniciar uso de permiso de visualización"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Permite que el titular inicie el uso de permisos de una aplicación. Las aplicaciones normales no deberían necesitar nunca este permiso."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"acceder a datos de sensores a una frecuencia de muestreo alta"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Permite que la aplicación consulte datos de sensores a una frecuencia superior a 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Establecimiento de reglas de contraseña"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Controla la longitud y los caracteres permitidos en los PIN y en las contraseñas de bloqueo de pantalla."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Supervisar los intentos de desbloqueo de pantalla"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Se ha cambiado la solicitud de SS a una videollamada"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Se ha cambiado la solicitud de SS a una solicitud de USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Se ha cambiado a una nueva solicitud de SS"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Perfil de trabajo"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Con sonido"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Mostrar"</string>
diff --git a/core/res/res/values-et/strings.xml b/core/res/res/values-et/strings.xml
index c32cf73bf2ca..2a2db3af8f43 100644
--- a/core/res/res/values-et/strings.xml
+++ b/core/res/res/values-et/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Võimaldab rakendusel lugeda ja kirjutada funktsiooni Mitte segada seadistusi."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"vaatamisloa kasutamise alustamine"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Võimaldab omanikul rakenduse puhul alustada loa kasutamist. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"juurdepääs anduri andmetele kõrgel diskreetimissagedusel"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Võimaldab rakendusel anduri andmeid diskreetida sagedusel, mis on suurem kui 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Parooli reeglite määramine"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Juhitakse ekraaniluku paroolide ja PIN-koodide pikkusi ning lubatud tähemärkide seadeid."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Ekraani avamiskatsete jälgimine"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS-taotlus muudeti videokõneks"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS-taotlus muudeti USSD-taotluseks"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Muudeti uueks SS-taotluseks"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Tööprofiil"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Teavitatud"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Laienda"</string>
diff --git a/core/res/res/values-eu/strings.xml b/core/res/res/values-eu/strings.xml
index 86546e0baac0..901d8661e411 100644
--- a/core/res/res/values-eu/strings.xml
+++ b/core/res/res/values-eu/strings.xml
@@ -251,7 +251,7 @@
<string name="global_action_logout" msgid="6093581310002476511">"Amaitu saioa"</string>
<string name="global_action_screenshot" msgid="2610053466156478564">"Pantaila-argazkia"</string>
<string name="bugreport_title" msgid="8549990811777373050">"Akatsen txostena"</string>
- <string name="bugreport_message" msgid="5212529146119624326">"Gailuaren uneko egoerari buruzko informazioa bilduko da, mezu elektroniko gisa bidaltzeko. Minutu batzuk igaroko dira akatsen txostena sortzen hasten denetik bidaltzeko prest egon arte. Itxaron, mesedez."</string>
+ <string name="bugreport_message" msgid="5212529146119624326">"Gailuaren oraingo egoerari buruzko informazioa bilduko da, mezu elektroniko gisa bidaltzeko. Minutu batzuk igaroko dira akatsen txostena sortzen hasten denetik bidaltzeko prest egon arte. Itxaron, mesedez."</string>
<string name="bugreport_option_interactive_title" msgid="7968287837902871289">"Txosten dinamikoa"</string>
<string name="bugreport_option_interactive_summary" msgid="8493795476325339542">"Aukera hau erabili beharko zenuke ia beti. Txostenaren jarraipena egin ahal izango duzu eta arazoari buruzko xehetasunak eman ahal izango dituzu. Baliteke gutxitan erabili behar izaten diren atalak ez agertzea, denbora aurrezteko."</string>
<string name="bugreport_option_full_title" msgid="7681035745950045690">"Txosten osoa"</string>
@@ -674,7 +674,7 @@
<string name="permlab_accessDrmCertificates" msgid="6473765454472436597">"atzitu DRM ziurtagiriak"</string>
<string name="permdesc_accessDrmCertificates" msgid="6983139753493781941">"DRM ziurtagiriak hornitzea eta erabiltzeko baimena ematen die aplikazioei. Aplikazio normalek ez lukete beharko."</string>
<string name="permlab_handoverStatus" msgid="7620438488137057281">"Jaso Android Beam transferentzien egoera"</string>
- <string name="permdesc_handoverStatus" msgid="3842269451732571070">"Uneko Android Beam transferentziei buruzko informazioa jasotzeko baimena ematen die aplikazioei"</string>
+ <string name="permdesc_handoverStatus" msgid="3842269451732571070">"Oraingo Android Beam transferentziei buruzko informazioa jasotzeko baimena ematen die aplikazioei"</string>
<string name="permlab_removeDrmCertificates" msgid="710576248717404416">"kendu DRM ziurtagiriak"</string>
<string name="permdesc_removeDrmCertificates" msgid="4068445390318355716">"DRM ziurtagiriak kentzea baimentzen die aplikazioei. Aplikazio normalek ez lukete beharko."</string>
<string name="permlab_bindCarrierMessagingService" msgid="3363450860593096967">"lotu operadorearen mezularitza-zerbitzuari"</string>
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Ez molestatzeko moduaren konfigurazioa irakurtzeko eta bertan idazteko baimena ematen die aplikazioei."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"hasi ikusteko baimena erabiltzen"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Aplikazioaren baimena erabiltzen hasteko baimena ematen die titularrei. Aplikazio normalek ez lukete beharko."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"atzitu sentsoreen datuen laginak abiadura handian"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Aplikazioak 200 Hz-tik gorako abiaduran hartu ahal izango ditu sentsoreen datuen laginak"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Ezarri pasahitzen arauak"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Kontrolatu pantaila blokeoaren pasahitzen eta PINen luzera eta onartutako karaktereak."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Gainbegiratu pantaila desblokeatzeko saiakerak"</string>
@@ -1201,7 +1199,7 @@
<string name="screen_compat_mode_scale" msgid="8627359598437527726">"Eskala"</string>
<string name="screen_compat_mode_show" msgid="5080361367584709857">"Erakutsi beti"</string>
<string name="screen_compat_mode_hint" msgid="4032272159093750908">"Gaitu hori berriro Sistemaren ezarpenak &gt; Aplikazioak &gt; Deskargatutakoak."</string>
- <string name="unsupported_display_size_message" msgid="7265211375269394699">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioak ez du onartzen uneko pantailaren tamaina eta espero ez bezala joka lezake."</string>
+ <string name="unsupported_display_size_message" msgid="7265211375269394699">"<xliff:g id="APP_NAME">%1$s</xliff:g> aplikazioak ez du onartzen pantailaren tamaina, eta baliteke espero ez bezala jokatzea."</string>
<string name="unsupported_display_size_show" msgid="980129850974919375">"Erakutsi beti"</string>
<string name="unsupported_compile_sdk_message" msgid="7326293500707890537">"Android sistema eragilearen bertsio bateraezin baterako dago egina <xliff:g id="APP_NAME">%1$s</xliff:g>; beraz, espero ez bezala funtziona lezake. Baliteke aplikazioaren bertsio eguneratuago bat eskuragarri egotea."</string>
<string name="unsupported_compile_sdk_show" msgid="1601210057960312248">"Erakutsi beti"</string>
@@ -1231,9 +1229,9 @@
<string name="new_app_description" msgid="1958903080400806644">"Gorde gabe itxiko da <xliff:g id="OLD_APP">%1$s</xliff:g>"</string>
<string name="dump_heap_notification" msgid="5316644945404825032">"<xliff:g id="PROC">%1$s</xliff:g> prozesuak memoria-muga gainditu du"</string>
<string name="dump_heap_ready_notification" msgid="2302452262927390268">"Prest dago <xliff:g id="PROC">%1$s</xliff:g> memoria-iraulketaren txostena"</string>
- <string name="dump_heap_notification_detail" msgid="8431586843001054050">"Sortu da uneko memoria-iraulketaren txostena. Sakatu partekatzeko."</string>
- <string name="dump_heap_title" msgid="4367128917229233901">"Uneko memoria-iraulketaren txostena partekatu nahi duzu?"</string>
- <string name="dump_heap_text" msgid="1692649033835719336">"<xliff:g id="PROC">%1$s</xliff:g> prozesuak memoria-muga (<xliff:g id="SIZE">%2$s</xliff:g>) gainditu du. Uneko memoria-iraulketaren txostena sortu da, garatzailearekin parteka dezazun. Kontuz: baliteke txosten horrek aplikazioak atzi dezakeen informazio pertsonala izatea."</string>
+ <string name="dump_heap_notification_detail" msgid="8431586843001054050">"Sortu da memoria-iraulketaren txostena. Sakatu partekatzeko."</string>
+ <string name="dump_heap_title" msgid="4367128917229233901">"Memoria-iraulketaren txostena partekatu nahi duzu?"</string>
+ <string name="dump_heap_text" msgid="1692649033835719336">"<xliff:g id="PROC">%1$s</xliff:g> prozesuak memoria-muga (<xliff:g id="SIZE">%2$s</xliff:g>) gainditu du. Memoria-iraulketaren txostena sortu da, garatzailearekin parteka dezazun. Kontuz: baliteke txosten horrek aplikazioak atzi dezakeen informazio pertsonala izatea."</string>
<string name="dump_heap_system_text" msgid="6805155514925350849">"<xliff:g id="PROC">%1$s</xliff:g> prozesuak bere memoria-muga (<xliff:g id="SIZE">%2$s</xliff:g>) gainditu du. Memoria-iraulketaren txosten bat duzu erabilgarri, hura partekatu nahi baduzu ere. Kontuz: baliteke txosten horrek prozesuak atzi dezakeen kontuzko informazio pertsonala izatea eta datu horien barnean zuk idatzitakoak egotea, besteak beste."</string>
<string name="dump_heap_ready_text" msgid="5849618132123045516">"<xliff:g id="PROC">%1$s</xliff:g> prozesuaren memoria-iraulketaren txosten bat duzu erabilgarri, hura partekatu nahi baduzu ere. Kontuz: baliteke txosten horrek prozesuak atzi dezakeen kontuzko informazio pertsonala izatea eta datu horien barnean zuk idatzitakoak egotea, besteak beste."</string>
<string name="sendText" msgid="493003724401350724">"Aukeratu testurako ekintza"</string>
@@ -1361,7 +1359,7 @@
<string name="alert_windows_notification_message" msgid="6538171456970725333">"Ez baduzu nahi <xliff:g id="NAME">%s</xliff:g> zerbitzuak eginbide hori erabiltzea, sakatu hau ezarpenak ireki eta aukera desaktibatzeko."</string>
<string name="alert_windows_notification_turn_off_action" msgid="7805857234839123780">"Desaktibatu"</string>
<string name="ext_media_checking_notification_title" msgid="8299199995416510094">"<xliff:g id="NAME">%s</xliff:g> egiaztatzen…"</string>
- <string name="ext_media_checking_notification_message" msgid="2231566971425375542">"Uneko edukia berrikusten"</string>
+ <string name="ext_media_checking_notification_message" msgid="2231566971425375542">"Edukia berrikusten"</string>
<string name="ext_media_new_notification_title" msgid="3517407571407687677">"Euskarri berria: <xliff:g id="NAME">%s</xliff:g>"</string>
<string name="ext_media_new_notification_title" product="automotive" msgid="9085349544984742727">"<xliff:g id="NAME">%s</xliff:g> ez da funtzionatzen ari"</string>
<string name="ext_media_new_notification_message" msgid="6095403121990786986">"Sakatu konfiguratzeko"</string>
@@ -1642,7 +1640,7 @@
<string name="accessibility_shortcut_warning_dialog_title" msgid="4017995837692622933">"Erabilerraztasun-lasterbidea erabili nahi duzu?"</string>
<string name="accessibility_shortcut_toogle_warning" msgid="4161716521310929544">"Lasterbidea aktibatuta dagoenean, bi bolumen-botoiak hiru segundoz sakatuta abiaraziko da erabilerraztasun-eginbidea."</string>
<string name="accessibility_shortcut_multiple_service_warning_title" msgid="3135860819356676426">"Erabilerraztasun-eginbideetarako lasterbidea aktibatu nahi duzu?"</string>
- <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Eduki sakatuta bolumen-botoiak segundo batzuez erabilerraztasun-eginbideak aktibatzeko. Hori eginez gero, baliteke zure mugikorraren funtzionamendua aldatzea.\n\nUneko eginbideak:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nHautatutako eginbideak aldatzeko, joan Ezarpenak &gt; Erabilerraztasuna atalera."</string>
+ <string name="accessibility_shortcut_multiple_service_warning" msgid="3740723309483706911">"Eduki sakatuta bolumen-botoiak segundo batzuez erabilerraztasun-eginbideak aktibatzeko. Hori eginez gero, baliteke zure mugikorraren funtzionamendua aldatzea.\n\nEginbideak:\n<xliff:g id="SERVICE">%1$s</xliff:g>\nHautatutako eginbideak aldatzeko, joan Ezarpenak &gt; Erabilerraztasuna atalera."</string>
<string name="accessibility_shortcut_multiple_service_list" msgid="6935581470716541531">" • <xliff:g id="SERVICE">%1$s</xliff:g>\n"</string>
<string name="accessibility_shortcut_single_service_warning_title" msgid="1909518473488345266">"<xliff:g id="SERVICE">%1$s</xliff:g> zerbitzuaren lasterbidea aktibatu nahi duzu?"</string>
<string name="accessibility_shortcut_single_service_warning" msgid="6363127705112844257">"Eduki sakatuta bolumen-botoiak segundo batzuez <xliff:g id="SERVICE">%1$s</xliff:g> izeneko erabilerraztasun-eginbidea aktibatzeko. Honen bidez, baliteke zure mugikorraren funtzionamendua aldatzea.\n\nLasterbide hau beste eginbide batengatik aldatzeko, joan Ezarpenak &gt; Erabilerraztasuna atalera."</string>
@@ -1680,7 +1678,7 @@
<string name="accessibility_gesture_instructional_text" msgid="9196230728837090497">"Eginbide batetik bestera aldatzeko, pasatu bi hatz pantailaren behealdetik gora eta eduki sakatuta une batez."</string>
<string name="accessibility_gesture_3finger_instructional_text" msgid="3425123684990193765">"Eginbide batetik bestera aldatzeko, pasatu hiru hatz pantailaren behealdetik gora eta eduki sakatuta une batez."</string>
<string name="accessibility_magnification_chooser_text" msgid="1502075582164931596">"Lupa"</string>
- <string name="user_switched" msgid="7249833311585228097">"Uneko erabiltzailea: <xliff:g id="NAME">%1$s</xliff:g>."</string>
+ <string name="user_switched" msgid="7249833311585228097">"Erabiltzailea: <xliff:g id="NAME">%1$s</xliff:g>."</string>
<string name="user_switching_message" msgid="1912993630661332336">"<xliff:g id="NAME">%1$s</xliff:g> erabiltzailera aldatzen…"</string>
<string name="user_logging_out_message" msgid="7216437629179710359">"<xliff:g id="NAME">%1$s</xliff:g> erabiltzailearen saioa amaitzen…"</string>
<string name="owner_name" msgid="8713560351570795743">"Jabea"</string>
@@ -1780,7 +1778,7 @@
<string name="restr_pin_enter_admin_pin" msgid="1199419462726962697">"Idatzi administratzailearen PIN kodea"</string>
<string name="restr_pin_enter_pin" msgid="373139384161304555">"Idatzi PINa"</string>
<string name="restr_pin_incorrect" msgid="3861383632940852496">"Okerra"</string>
- <string name="restr_pin_enter_old_pin" msgid="7537079094090650967">"Uneko PINa"</string>
+ <string name="restr_pin_enter_old_pin" msgid="7537079094090650967">"Oraingo PINa"</string>
<string name="restr_pin_enter_new_pin" msgid="3267614461844565431">"PIN berria"</string>
<string name="restr_pin_confirm_pin" msgid="7143161971614944989">"Berretsi PIN berria"</string>
<string name="restr_pin_create_pin" msgid="917067613896366033">"Konfiguratu debekuak aldatu ahal izateko idatzi beharko den PIN kodea"</string>
@@ -1873,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS eskaera bideo-deira aldatu da"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS eskaera USSD eskaerara aldatu da"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"SS eskaera berrira aldatu da"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Phishing-alerta"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Work profila"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Egin du soinua"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Zabaldu"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index b1ec1f6e7483..ec195e53364b 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"به برنامه امکان می‌دهد پیکربندی «مزاحم نشوید» را بخواند و بنویسد."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"شروع مشاهده استفاده از مجوز"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"به دارنده اجازه شروع استفاده از مجوز را برای برنامه می‌دهد. هرگز برای برنامه‌های معمول نیاز نیست."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"دسترسی به داده‌های حسگر با نرخ نمونه‌برداری بالا"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"به برنامه اجازه می‌دهد داده‌های حسگر را با نرخ بیش‌از ۲۰۰ هرتز نمونه‌برداری کند"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"تنظیم قوانین گذرواژه"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"کنترل طول و نوع نویسه‌هایی که در گذرواژه و پین قفل صفحه مجاز است."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"پایش تلاش‌های باز کردن قفل صفحه"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"‏درخواست SS به تماس تصویری تغییر کرد"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"‏درخواست SS به‌ درخواست USSD تغییر کرد"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"‏به‌ درخواست SS جدید تغییر کرد"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"نمایه کاری"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"هشدار ارسال شد"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"بزرگ کردن"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 55c6d92f1136..6773dde66de5 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Sallii sovelluksen lukea ja muokata Älä häiritse -tilan asetuksia."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"aloita katseluoikeuksien käyttö"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Antaa luvanhaltijan käynnistää sovelluksen käyttöoikeuksien käytön. Ei tavallisten sovelluksien käyttöön."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"saada pääsyn anturidataan suuremmalla näytteenottotaajuudella"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Sallii sovelluksen ottaa anturidatasta näytteitä yli 200 Hz:n taajuudella"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Asentaa salasanasäännöt"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Hallinnoida ruudun lukituksen salasanoissa ja PIN-koodeissa sallittuja merkkejä ja niiden pituutta."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Tarkkailla näytön avaamisyrityksiä"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS-pyyntö vaihdettu videopuheluksi"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS-pyyntö vaihdettu USSD-pyynnöksi"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Vaihdettu uudeksi SS-pyynnöksi"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Työprofiili"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Hälytti"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Laajenna"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 15351bcef7ba..9c4f92a0bc44 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -1871,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"La demande SS a été remplacée par une demande d\'appel vidéo"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"La demande SS a été remplacée par une demande USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"La demande a été remplacée par une nouvelle demande SS"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Profil professionnel"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Alerté"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Développer"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 8cb86143b5f5..78af86f06b34 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Permet à l\'application de consulter et de modifier la configuration du mode Ne pas déranger."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"activer l\'utilisation de l\'autorisation d\'affichage"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Permet à l\'application autorisée d\'activer l\'utilisation de l\'autorisation pour une application. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"accéder aux données des capteurs à un taux d\'échantillonnage élevé"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Autorise l\'appli à échantillonner les données des capteurs à un taux supérieur à 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Définir les règles du mot de passe"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Gérer le nombre et le type de caractères autorisés dans les mots de passe et les codes d\'accès de verrouillage de l\'écran"</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Gérer les tentatives de déverrouillage de l\'écran"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Requête SS transformée en appel vidéo"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Requête SS transformée en requête USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Remplacement par une nouvelle requête SS"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Profil professionnel"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Alerte envoyée"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Développer"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index f99d02c01996..949e48629d4f 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Permite á aplicación ler e escribir a configuración do modo Non molestar."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"iniciar uso de permiso de vista"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Permite ao propietario iniciar o uso de permisos dunha aplicación. As aplicacións normais non deberían precisalo nunca."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"acceder aos datos dos sensores usando unha taxa de mostraxe alta"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Permite que a aplicación recompile mostras dos datos dos sensores cunha taxa superior a 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Establecer as normas de contrasinal"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Controla a lonxitude e os caracteres permitidos nos contrasinais e nos PIN de bloqueo da pantalla."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Controlar os intentos de desbloqueo da pantalla"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"A solicitude SS transformouse nunha videochamada"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"A solicitude SS transformouse nunha solicitude USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Transformouse nunha nova solicitude SS"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Perfil de traballo"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Con son"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Despregar"</string>
diff --git a/core/res/res/values-gu/strings.xml b/core/res/res/values-gu/strings.xml
index 84ee732e0d16..29ce76bd8e7c 100644
--- a/core/res/res/values-gu/strings.xml
+++ b/core/res/res/values-gu/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"એપ્લિકેશનને ખલેલ પાડશો નહીં ગોઠવણી વાંચવા અને લખવાની મંજૂરી આપે છે."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"પરવાનગી વપરાશ જુઓને શરૂ કરો"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"કોઈ ઍપ માટે પરવાનગી વપરાશ શરૂ કરવાની ધારકને મંજૂરી આપે છે. સામાન્ય ઍપ માટે ક્યારેય જરૂર પડી ન શકે."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"ઉચ્ચ સેમ્પ્લિંગ રેટ પર સેન્સરનો ડેટા ઍક્સેસ કરો"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"ઍપને 200 Hzથી વધુના દરે સેન્સરના ડેટાના નમૂનાની મંજૂરી આપે છે"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"પાસવર્ડ નિયમો સેટ કરો"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"સ્ક્રીન લૉક પાસવર્ડ અને પિનમાં મંજૂર લંબાઈ અને અક્ષરોને નિયંત્રિત કરો."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"સ્ક્રીનને અનલૉક કરવાના પ્રયત્નોનું નિયમન કરો"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS વિનંતીને વીડિઓ કૉલમાં બદલવામાં આવી છે"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS વિનંતીને USSD વિનંતીમાં બદલવામાં આવી છે"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"નવી SS વિનંતીમાં બદલવામાં આવી છે"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"ઑફિસની પ્રોફાઇલ"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"અલર્ટ કરેલ"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"વિસ્તૃત કરો"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 93408be6a5e3..15bb461fbb66 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"ऐप को परेशान न करें कॉन्फ़िगरेशन पढ़ने और लिखने देती है."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"देखने की अनुमतियां चालू करें"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"इस्तेमाल करने वाले को किसी ऐप्लिकेशन के लिए अनुमतियों का इस्तेमाल शुरू करने देता है. सामान्य ऐप्लिकेशन के लिए इसकी ज़रूरत कभी नहीं पड़ती."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"सेंसर डेटा को नमूने लेने की तेज़ दर पर ऐक्सेस करें"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"यह अनुमति मिलने पर ऐप्लिकेशन, 200 हर्ट्ज़ से ज़्यादा की दर पर सेंसर डेटा का नमूना ले पाएगा"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"पासवर्ड नियम सेट करना"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"स्‍क्रीन लॉक पासवर्ड और पिन की लंबाई और उनमें स्वीकृत वर्णों को नियंत्रित करना."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"स्‍क्रीन अनलॉक करने के की कोशिशों पर नज़र रखना"</string>
@@ -1873,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"एसएस कोड चलाने के अनुरोध को वीडियो कॉल में बदला गया"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"एसएस कोड चलाने के अनुरोध को यूएसएसडी कोड चलाने के अनुरोध में बदला गया"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"एसएस कोड चलाने के नए अनुरोध में बदला गया"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"फ़िशिंग से जुड़ी चेतावनी"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"वर्क प्रोफ़ाइल"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"अलर्ट किया गया"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"विस्तार करें"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 7fa4fe32ede5..6e7c3300becd 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -688,10 +688,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Omogućuje aplikaciji čitanje i pisanje konfiguracije opcije Ne ometaj."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"pokrenuti upotrebu dopuštenja za pregled"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Dopušta nositelju pokretanje upotrebe dopuštenja za aplikaciju. Ne bi smjelo biti potrebno za uobičajene aplikacije."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"pristup podacima senzora pri višoj brzini uzorkovanja"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Aplikaciji omogućuje uzorkovanje podataka senzora pri brzini većoj od 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Postavi pravila zaporke"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Upravlja duljinom i znakovima koji su dopušteni u zaporkama i PIN-ovima zaključavanja zaslona."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Nadziri pokušaje otključavanja zaslona"</string>
@@ -1904,6 +1902,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS zahtjev promijenjen je u videopoziv"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS zahtjev promijenjen je u USSD zahtjev"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Promijenjeno u novi SS zahtjev"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Upozorenje o krađi identiteta"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Radni profil"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Upozoreni"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Proširivanje"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index d71c5620d44d..d966249f7fb4 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Az alkalmazás olvashatja és szerkesztheti a „Ne zavarjanak” funkció beállításait."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"engedélyhasználat megtekintésének elindítása"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Lehetővé teszi a felhasználó számára, hogy elindítsa az alkalmazás engedélyhasználatát. A normál alkalmazásoknak erre soha nincs szükségük."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"hozzáférés a szenzoradatokhoz nagy mintavételezési gyakorisággal"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Lehetővé teszi az alkalmazás számára, hogy 200 Hz-nél magasabb gyakorisággal vegyen mintát a szenzoradatokból"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Jelszavakkal kapcsolatos szabályok beállítása"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"A képernyőzár jelszavaiban és PIN kódjaiban engedélyezett karakterek és hosszúság vezérlése."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Képernyőzár-feloldási kísérletek figyelése"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Az SS-kérés módosítva videohívásra"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Az SS-kérés módosítva USSD-kérésre"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Új SS-kérésre módosítva"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Munkaprofil"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Értesítve"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Kibontás"</string>
diff --git a/core/res/res/values-hy/strings.xml b/core/res/res/values-hy/strings.xml
index e5267d95a959..6110be3b91d9 100644
--- a/core/res/res/values-hy/strings.xml
+++ b/core/res/res/values-hy/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Թույլ է տալիս հավելվածին փոփոխել «Չանհանգստացնել» գործառույթի կազմաձևումը:"</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"թույլտվությունների մասին տվյալների հասանելիություն"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Հավելվածին հասանելի կդառնան թույլտվությունների մասին տվյալները։ Այս թույլտվությունն անհրաժեշտ չէ սովորական հավելվածներին։"</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"օգտագործել սենսորների տվյալները բարձր հաճախականության վրա"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Թույլ է տալիս հավելվածին փորձել սենսորների տվյալները 200 Հց-ից ավել հաճախականության վրա"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Սահմանել գաղտնաբառի կանոնները"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Կառավարել էկրանի ապակողպման գաղտնաբառերի և PIN կոդերի թույլատրելի երկարությունն ու գրանշանները:"</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Վերահսկել էկրանի ապակողպման փորձերը"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS հարցումը փոխվել է տեսազանգի"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS հարցումը փոխվել է USSD հարցման"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Փոխվել է նոր SS հարցման"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Աշխատանքային պրոֆիլ"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Ուղարկվել է զգուշացում"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Ընդարձակել"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 636bb04c3473..3335f599b50a 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Mengizinkan aplikasi membaca dan menulis konfigurasi status Jangan Ganggu."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"mulai melihat penggunaan izin"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Memungkinkan pemegang memulai penggunaan izin untuk aplikasi. Tidak diperlukan untuk aplikasi normal."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"mengakses data sensor pada frekuensi pengambilan sampel yang tinggi"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Mengizinkan aplikasi mengambil sampel data sensor pada frekuensi yang lebih besar dari 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Setel aturan sandi"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Mengontrol panjang dan karakter yang diizinkan dalam sandi dan PIN kunci layar."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Pantau upaya pembukaan kunci layar"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Permintaan SS diubah ke panggilan video"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Permintaan SS diubah ke permintaan USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Diubah ke permintaan SS baru"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Profil kerja"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Diingatkan"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Luaskan"</string>
diff --git a/core/res/res/values-is/strings.xml b/core/res/res/values-is/strings.xml
index b359e7d3a28e..86a4638a6633 100644
--- a/core/res/res/values-is/strings.xml
+++ b/core/res/res/values-is/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Leyfir forriti að lesa og skrifa í grunnstillingu „Ónáðið ekki“."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"heimildanotkun upphafsyfirlits"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Leyfir handhafa að byrja heimildanotkun fyrir forrit. Ætti aldrei að þurfa fyrir venjuleg forrit."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"aðgangur að skynjaragögnum með hárri upptökutíðni"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Leyfir forritinu að nota upptökutíðni yfir 200 Hz fyrir skynjaragögn"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Setja reglur um aðgangsorð"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Stjórna lengd og fjölda stafa í aðgangsorðum og PIN-númerum skjáláss."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Fylgjast með tilraunum til að taka skjáinn úr lás"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS-beiðni breytt í myndsímtal"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS-beiðni breytt í USSD-beiðni"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Breytt í nýja SS-beiðni"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Vinnusnið"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Tilkynnt"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Stækka"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index d4c6ae0540c9..fa6b46110d4c 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Consente all\'app di leggere e modificare la configurazione della funzione Non disturbare."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"avvio dell\'uso dell\'autorizzazione di visualizzazione"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Consente al titolare di avviare l\'uso delle autorizzazioni per un\'app. Non dovrebbe essere mai necessaria per le normali applicazioni."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"Accesso ai dati dei sensori a una frequenza di campionamento elevata"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Consente all\'app di campionare i dati dei sensori a una frequenza maggiore di 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Impostare regole per le password"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Controlla la lunghezza e i caratteri ammessi nelle password e nei PIN del blocco schermo."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Monitorare tentativi di sblocco dello schermo"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Richiesta SS modificata in videochiamata"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Richiesta SS modificata in richiesta USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Modificata in nuova richiesta SS"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Profilo di lavoro"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Avviso inviato"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Espandi"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 33f43af259e8..d9b889ebe436 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -691,10 +691,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"מאפשר לאפליקציה לקרוא ולכתוב את התצורה של \'נא לא להפריע\'."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"התחלת צפייה בהרשאות השימוש"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"מאפשרת לבעלים להפעיל את השימוש בהרשאות עבור אפליקציה מסוימת. הרשאה זו אף פעם לא נדרשת עבור אפליקציות רגילות."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"גישה לנתוני חיישנים בתדירות דגימה גבוהה"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"האפליקציה תוכל לדגום נתוני חיישנים בתדירות של מעל 200 הרץ"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"הגדר כללי סיסמה"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"קביעת האורך הנדרש והתווים המותרים בסיסמאות ובקודי הגישה של מסך הנעילה."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"מעקב אחר ניסיונות לביטול של נעילת המסך"</string>
@@ -1935,6 +1933,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"‏בקשת SS שונתה לשיחת וידאו"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"‏בקשת SS שונתה לבקשת USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"‏היה שינוי לבקשת SS חדשה"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"פרופיל עבודה"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"נשלחה התראה"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"הרחב"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 2482c7e8a5e2..68213defda29 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1871,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS リクエストはビデオ通話に変更されました"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS リクエストは USSD リクエストに変更されました"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"新しい SS リクエストに変更されました"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"フィッシングに関する警告"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"仕事用プロファイル"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"アラートとして送信済み"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"展開"</string>
diff --git a/core/res/res/values-ka/strings.xml b/core/res/res/values-ka/strings.xml
index e45b18a6170b..3c764544a5c4 100644
--- a/core/res/res/values-ka/strings.xml
+++ b/core/res/res/values-ka/strings.xml
@@ -1871,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS მოთხოვნა შეიცვალა ვიდეოზარის მოთხოვნით"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS მოთხოვნა შეიცვალა USSD მოთხოვნით"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"შეიცვალა ახალი SS მოთხოვნით"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"სამსახურის პროფილი"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"გაფრთხილებით"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"გაშლა"</string>
diff --git a/core/res/res/values-kk/strings.xml b/core/res/res/values-kk/strings.xml
index 08a2e6773c90..38f947524edc 100644
--- a/core/res/res/values-kk/strings.xml
+++ b/core/res/res/values-kk/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Қолданбаға «Мазаламау» конфигурациясын оқу және жазу мүмкіндігін береді."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"рұқсаттарды пайдалану туралы деректерді көру"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Пайдаланушы қолданбаға берілетін рұқсаттарды басқара алады. Ондай рұқсаттар әдеттегі қолданбаларға керек емес."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"жоғары дискретизация жиілігіндегі датчик деректерін пайдалану"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Қолданбаға жиілігі 200 Гц-тен жоғары датчик деректерінің үлгісін таңдауға рұқсат береді."</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Құпия сөз ережелерін тағайындау"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Экран бекітпесінің құпия сөздерінің және PIN кодтарының ұзындығын және оларда рұқсат етілген таңбаларды басқару."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Экран құлпын ашу әркеттерін бақылау"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS сұрауы бейне қоңырауға өзгертілді"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS сұрауы USSD сұрауына өзгертілді"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Жаңа SS сұрауына өзгертілді"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Жұмыс профилі"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Ескертілді"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Жаю"</string>
diff --git a/core/res/res/values-km/strings.xml b/core/res/res/values-km/strings.xml
index 34e249e550ee..5bde7332aad7 100644
--- a/core/res/res/values-km/strings.xml
+++ b/core/res/res/values-km/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"អនុញ្ញាតឲ្យកម្មវិធីអាន និងសរសេរការកំណត់រចនាសម្ព័ន្ធមុខងារ កុំរំខាន។"</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"ចាប់ផ្ដើម​មើល​ការប្រើប្រាស់​ការអនុញ្ញាត"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"អនុញ្ញាត​ឱ្យម្ចាស់​ចាប់ផ្ដើម​ការប្រើប្រាស់​ការអនុញ្ញាត​សម្រាប់កម្មវិធី។ មិនគួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"ចូលប្រើទិន្នន័យ​ឧបករណ៍ចាប់សញ្ញា​នៅអត្រាសំណាកខ្ពស់"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"អនុញ្ញាតឱ្យកម្មវិធី​ធ្វើសំណាកទិន្នន័យ​ឧបករណ៍ចាប់សញ្ញា​នៅអត្រាលើសពី 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"កំណត់​ក្បួន​ពាក្យ​សម្ងាត់"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"គ្រប់គ្រងប្រវែង និងតួអក្សរដែលអនុញ្ញាតឲ្យប្រើក្នុងពាក្យសម្ងាត់ និងលេខសម្ងាត់ចាក់សោអេក្រង់។"</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"តាមដាន​ការ​ព្យាយាម​ដោះ​សោ​អេក្រង់"</string>
@@ -1873,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"សំណើ SS ត្រូវបាន​ប្ដូរ​ទៅ​ការហៅ​ជា​វីដេអូ"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"សំណើ SS ត្រូវបាន​ប្ដូរ​ទៅ​សំណើ USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"បាន​ប្ដូរ​ទៅ​សំណើ SS ថ្មី"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"ការជូនដំណឹង​អំពីការ​ដាក់នុយ"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"ប្រវត្តិរូបការងារ"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"បាន​ជូនដំណឹង"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"ពង្រីក"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 9a33f06b61fc..cf0f644cb27b 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"ಅಡಚಣೆ ಮಾಡಬೇಡಿ ಕಾನ್ಫಿಗರೇಶನ್ ಅನ್ನು ಓದಲು ಮತ್ತು ಬರೆಯಲು ಅಪ್ಲಿಕೇಶನ್‌ಗೆ ಅನುಮತಿಸುತ್ತದೆ."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"ವೀಕ್ಷಣಾ ಅನುಮತಿಯ ಬಳಕೆಯನ್ನು ಪ್ರಾರಂಭಿಸಿ"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"ಆ್ಯಪ್‌ಗಾಗಿ ಅನುಮತಿ ಬಳಕೆಯನ್ನು ಪ್ರಾರಂಭಿಸಲು ಹೊಂದಿರುವವರಿಗೆ ಅನುಮತಿಸುತ್ತದೆ. ಸಾಮಾನ್ಯ ಆ್ಯಪ್‌ಗಳಿಗೆ ಎಂದಿಗೂ ಅಗತ್ಯವಿರುವುದಿಲ್ಲ."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"ಹೆಚ್ಚಿನ ನಮೂನೆ ದರದಲ್ಲಿ ಸೆನ್ಸಾರ್ ಡೇಟಾ ಪ್ರವೇಶಿಸಿ"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"200 Hz ಗಿಂತಲೂ ಹೆಚ್ಚಿನ ವೇಗದಲ್ಲಿ ಸೆನ್ಸಾರ್ ಡೇಟಾದ ಮಾದರಿ ಪರೀಕ್ಷಿಸಲು ಆ್ಯಪ್‌ಗೆ ಅನುಮತಿಸಿ"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"ಪಾಸ್‌ವರ್ಡ್ ನಿಮಯಗಳನ್ನು ಹೊಂದಿಸಿ"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"ಪರದೆ ಲಾಕ್‌ನಲ್ಲಿನ ಪಾಸ್‌ವರ್ಡ್‌ಗಳು ಮತ್ತು ಪಿನ್‌ಗಳ ಅನುಮತಿಸಲಾದ ಅಕ್ಷರಗಳ ಪ್ರಮಾಣವನ್ನು ನಿಯಂತ್ರಿಸಿ."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"ಪರದೆಯ ಅನ್‌ಲಾಕ್ ಪ್ರಯತ್ನಗಳನ್ನು ಮೇಲ್ವಿಚಾರಣೆ ಮಾಡಿ"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS ವಿನಂತಿಯನ್ನು ವೀಡಿಯೊ ಕರೆಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS ವಿನಂತಿಯನ್ನು USSD ವಿನಂತಿಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"ಹೊಸ SS ವಿನಂತಿಗೆ ಬದಲಾಯಿಸಲಾಗಿದೆ"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"ಉದ್ಯೋಗ ಪ್ರೊಫೈಲ್"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"ಎಚ್ಚರಿಕೆ ನೀಡಲಾಗಿದೆ"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"ವಿಸ್ತೃತಗೊಳಿಸಿ"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index a395c892dcfa..8fde34c190a3 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"앱에서 방해 금지 모드 설정을 읽고 작성하도록 허용합니다."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"권한 사용 보기 시작"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"앱의 권한 사용을 시작하려면 보유자를 허용하세요. 일반 앱에는 필요하지 않습니다."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"더 높은 샘플링 레이트로 센서 데이터 액세스"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"앱에서 200Hz보다 빠른 속도로 센서 데이터를 샘플링하도록 허용합니다."</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"비밀번호 규칙 설정"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"화면 잠금 비밀번호와 PIN에 허용되는 길이와 문자 수를 제어합니다."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"화면 잠금 해제 시도 모니터링"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS 요청이 화상 통화로 변경됨"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS 요청이 USSD 요청으로 변경됨"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"새 SS 요청으로 변경됨"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"직장 프로필"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"알림 전송됨"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"펼치기"</string>
diff --git a/core/res/res/values-ky/strings.xml b/core/res/res/values-ky/strings.xml
index f8a800db2ba2..aa5d01c1a946 100644
--- a/core/res/res/values-ky/strings.xml
+++ b/core/res/res/values-ky/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Колдонмого \"Тынчымды алба\" режиминин конфигурациясын окуу жана жазуу мүмкүнчүлүгүн берет."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"уруксаттын колдонулушун көрүп баштоо"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Колдонмонун пайдаланылышына уруксат берүүгө мүмкүнчүлүк берет. Кадимки колдонмолорго эч качан талап кылынбашы керек."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"үлгүнү жаздыруу ылдамдыгы жогору болгон сенсор дайындарынын үлгүсүнө мүмкүнчүлүк алуу"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Колдонмолорго сенсор дайындарынын үлгүсү 200 Герцтен жогору болгон үлгүлөрдү алууга уруксат берет"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Сырсөз эрежелерин коюу"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Экран кулпусунун сырсөздөрү менен PIN\'дерине уруксат берилген узундук менен белгилерди көзөмөлдөө."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Экран кулпусун ачуу аракеттерин көзөмөлдөө"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS сурамы видео чалууга өзгөртүлдү"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS сурамы USSD сурамына өзгөртүлдү"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Жаңы SS сурамына өзгөртүлдү"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Жумуш профили"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Эскертилди"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Жайып көрсөтүү"</string>
diff --git a/core/res/res/values-land/dimens.xml b/core/res/res/values-land/dimens.xml
index 9e87a47219f3..42c2c6912d81 100644
--- a/core/res/res/values-land/dimens.xml
+++ b/core/res/res/values-land/dimens.xml
@@ -78,4 +78,5 @@
<dimen name="chooser_preview_width">480dp</dimen>
+ <dimen name="toast_y_offset">24dp</dimen>
</resources>
diff --git a/core/res/res/values-lo/strings.xml b/core/res/res/values-lo/strings.xml
index 93f38890326f..806a5e2922c5 100644
--- a/core/res/res/values-lo/strings.xml
+++ b/core/res/res/values-lo/strings.xml
@@ -1871,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"ປ່ຽນການຮ້ອງຂໍ SS ເປັນການໂທວິດີໂອແລ້ວ"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"ປ່ຽນຄຳຂໍ SS ເປັນຄຳຂໍ USSD ແລ້ວ"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"ປ່ຽນຄຳຂໍ SS ໃໝ່ແລ້ວ"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"ການແຈ້ງເຕືອນການຫຼອກເອົາຂໍ້ມູນ"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"​ໂປຣ​ໄຟລ໌​ບ່ອນ​ເຮັດ​ວຽກ"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"ເຕືອນແລ້ວ"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"ຂະຫຍາຍ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 9c1e09de02b6..8f64bddc6bf0 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -691,10 +691,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Leidžiama programai skaityti ir rašyti „Do Not Disturb“ konfigūraciją."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"pradėti peržiūrėti leidimo naudojimą"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Leidžia savininkui pradėti naudoti programos leidimą. Įprastoms programoms to neturėtų prireikti."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"pasiekti jutiklių duomenis dideliu skaitmeninimo dažniu"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Programai leidžiama skaitmeninti jutiklių duomenis didesniu nei 200 Hz dažniu"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Nustatyti slaptažodžio taisykles"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Valdykite, kokio ilgio ekrano užrakto slaptažodžius ir PIN kodus galima naudoti."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Stebėti bandymus atrakinti ekraną"</string>
@@ -1935,6 +1933,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS užklausa pakeista į vaizdo skambutį"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS užklausa pakeista į USSD užklausą"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Pakeista į naują SS užklausą"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Darbo profilis"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Įspėjimas išsiųstas"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Išskleisti"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index d77cfd4c5bad..346ade469828 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -688,10 +688,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Ļauj lietotnei lasīt un rakstīt režīma “Netraucēt” konfigurāciju."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"Datu skatīšana par izmantojamajām atļaujām"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Ļauj atļaujas īpašniekam sākt lietotnes atļauju izmantošanu. Parastām lietotnēm tas nekad nav nepieciešams."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"piekļuve sensoru datiem, izmantojot augstu iztveršanas frekvenci"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Ļauj lietotnei iztvert sensoru datus, izmantojot frekvenci, kas ir augstāka par 200 Hz."</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Paroles kārtulu iestatīšana"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Kontrolēt ekrāna bloķēšanas paroļu un PIN garumu un tajos atļautās rakstzīmes."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Ekrāna atbloķēšanas mēģinājumu pārraudzīšana"</string>
@@ -1904,6 +1902,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS pieprasījums mainīts uz videozvanu"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS pieprasījums mainīts uz USSD pieprasījumu"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Mainīts uz jaunu SS pieprasījumu"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Darba profils"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Brīdināts"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Izvērst"</string>
diff --git a/core/res/res/values-mk/strings.xml b/core/res/res/values-mk/strings.xml
index 54ac67b0c3b6..8d176ad552a3 100644
--- a/core/res/res/values-mk/strings.xml
+++ b/core/res/res/values-mk/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Дозволува апликацијата да чита и пишува конфигурација Не вознемирувај."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"започнете со користење на дозволата за приказ"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Дозволува сопственикот да почне со користење на дозволата за апликација. Не треба да се користи за стандардни апликации."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"пристапува до податоците со висока фреквенција на семпл"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Дозволува апликацијата да пристапува до податоците од сензорите со фреквенција на семпл поголема од 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Постави правила за лозинката"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Контролирај ги должината и знаците што се дозволени за лозинки и PIN-броеви за отклучување екран."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Следи ги обидите за отклучување на екранот"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Барањето SS е изменето во видео повик"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Барањето SS е изменето во барање USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Променето на ново барање SS"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Работен профил"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Предупредено"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Прошири"</string>
diff --git a/core/res/res/values-ml/strings.xml b/core/res/res/values-ml/strings.xml
index 1329fb096836..fd61768347d3 100644
--- a/core/res/res/values-ml/strings.xml
+++ b/core/res/res/values-ml/strings.xml
@@ -1873,6 +1873,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS അഭ്യർത്ഥന, വീഡിയോ കോളിലേക്ക് മാറ്റി"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS അഭ്യർത്ഥന, USSD അഭ്യർത്ഥനയിലേക്ക് മാറ്റി"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"പുതിയ SS അഭ്യർത്ഥനയിലേക്ക് മാറ്റി"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"ഔദ്യോഗിക പ്രൊഫൈൽ"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"മുന്നറിയിപ്പ് നൽകി"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"വികസിപ്പിക്കുക"</string>
diff --git a/core/res/res/values-mn/strings.xml b/core/res/res/values-mn/strings.xml
index 4b1dbb358adf..d5937d364788 100644
--- a/core/res/res/values-mn/strings.xml
+++ b/core/res/res/values-mn/strings.xml
@@ -1871,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS хүсэлтийг видео дуудлага болгон өөрчилсөн"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS хүсэлтийг USSD хүсэлт болгон өөрчилсөн"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Шинэ SS хүсэлт болгон өөрчилсөн"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Ажлын профайл"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Мэдэгдсэн"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Дэлгэх"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index ea222907eee8..5f4d5fd916f6 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -1873,6 +1873,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS विनंती व्हिडिओ कॉलवर बदलली"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS विनंती USSD विनंतीवर बदलली"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"नवीन SS विनंतीवर बदलली"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"कार्य प्रोफाईल"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"सूचना दिल्या"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"विस्तृत करा"</string>
diff --git a/core/res/res/values-ms/strings.xml b/core/res/res/values-ms/strings.xml
index 0a1205fe608b..27b1d60ba652 100644
--- a/core/res/res/values-ms/strings.xml
+++ b/core/res/res/values-ms/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Membenarkan apl membaca dan menulis konfigurasi Jangan Ganggu."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"mulakan lihat penggunaan kebenaran"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Membenarkan pemegang memulakan penggunaan kebenaran untuk apl. Tidak sekali-kali diperlukan untuk apl biasa."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"akses data penderia pada data pensampelan yang tinggi"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Membenarkan apl mengambil sampel data penderia pada kadar yang lebih besar daripada 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Tetapkan peraturan kata laluan"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Mengawal panjang dan aksara yang dibenarkan dalam kata laluan dan PIN kunci skrin."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Pantau percubaan buka kunci skrin"</string>
@@ -1873,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Permintaan SS ditukar kepada panggilan video"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Permintaan SS ditukar kepada permintaan USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Bertukar kepada permintaan SS baharu"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Amaran pancingan data"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Profil kerja"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Dimaklumkan"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Kembangkan"</string>
diff --git a/core/res/res/values-my/strings.xml b/core/res/res/values-my/strings.xml
index 845c24f97ce2..9e1bd7394d41 100644
--- a/core/res/res/values-my/strings.xml
+++ b/core/res/res/values-my/strings.xml
@@ -649,8 +649,8 @@
<string name="permdesc_bind_incall_service" msgid="4124917526967765162">"အက်ပ်အား အသုံးပြုသူက ခေါ်ဆိုမှုအဝင် မျက်နှာပြင် ဘယ်အချိန်မှာ ဘယ်လို မြင်ရမှာကို ထိန်းချုပ်ခွင့်ပေးရန်"</string>
<string name="permlab_bind_connection_service" msgid="5409268245525024736">"တယ်လီဖုန်း ဝန်ဆောင်မှုများနှင့် အပြန်အလှန် တုံ့ပြန်မှု"</string>
<string name="permdesc_bind_connection_service" msgid="6261796725253264518">"အက်ပ်အား ခေါ်ဆိုမှုများ လုပ်ခြင်း/လက်ခံခြင်း ပြုလုပ်နိုင်ရန် တယ်လီဖုန်း ဝန်ဆောင်မှုများနှင့် အပြန်အလှန် တုံ့ပြန်မှုကို ခွင့်ပြုသည်။"</string>
- <string name="permlab_control_incall_experience" msgid="6436863486094352987">"အသုံးပြုသူ အတွက် ခေါ်ဆိုမှုအဝင် လုပ်ကိုင်ပုံကို စီစဉ်ပေးခြင်း"</string>
- <string name="permdesc_control_incall_experience" msgid="5896723643771737534">"အက်ပ်အား အသုံးပြုသူ အတွက် ခေါ်ဆိုမှုအဝင် လုပ်ကိုင်ပုံကို စီစဉ်ခွင့် ပြုသည်။"</string>
+ <string name="permlab_control_incall_experience" msgid="6436863486094352987">"အဝင်ခေါ်ဆိုမှုအတွက် အသုံးပြုသူ၏ နှစ်သက်မှုကို ခွင့်ပြုခြင်း"</string>
+ <string name="permdesc_control_incall_experience" msgid="5896723643771737534">"အဝင်ခေါ်ဆိုမှုအတွက် အသုံးပြုသူ၏ နှစ်သက်မှုကို ပံ့ပိုးပေးရန် အက်ပ်အား ခွင့်ပြုသည်။"</string>
<string name="permlab_readNetworkUsageHistory" msgid="8470402862501573795">"ရာဇဝင်အလိုက် ကွန်ယက်သုံစွဲမှုအား ဖတ်ခြင်း"</string>
<string name="permdesc_readNetworkUsageHistory" msgid="1112962304941637102">"အက်ပ်အား အထူး ကွန်ရက်များ နှင့် အက်ပ်များ အတွက် ကွန်ရက် အသုံးပြုမှု မှတ်တမ်းကို ဖတ်ကြားခွင့် ပြုသည်။"</string>
<string name="permlab_manageNetworkPolicy" msgid="6872549423152175378">"ကွန်ယက်မူဝါဒအား စီမံခြင်း"</string>
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"မနှောင့်ယှက်ရန် ချိန်ညှိမှုကို အပ်ဖ်များ ဖတ်ခြင်း ပြင်ခြင်းပြုလုပ်နိုင်ရန် ခွင့်ပြုမည်။"</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"အစမြင်ကွင်း ခွင့်ပြုချက် အသုံးပြုမှု"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"အက်ပ်တစ်ခုအတွက် ခွင့်ပြုချက်စတင်အသုံးပြုမှုကို ကိုင်ဆောင်သူအား ခွင့်ပြုသည်။ ပုံမှန်အက်ပ်များအတွက် ဘယ်သောအခါမျှ မလိုအပ်ပါ။"</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"နမူနာနှုန်းမြင့်သော အာရုံခံစနစ်ဒေတာကို သုံးပါ"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"၂၀၀ Hz နှုန်းထက်ပိုများသော အာရုံခံစနစ်ဒေတာကို နမူနာယူရန် အက်ပ်အား ခွင့်ပြုပါ"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"စကားဝှက်စည်းမျဥ်းကိုသတ်မှတ်ရန်"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"မျက်နှာပြင်သော့ခတ်သည့် စကားဝှက်များနှင့် PINများရှိ ခွင့်ပြုထားသည့် စာလုံးအရေအတွက်နှင့် အက္ခရာများအား ထိန်းချုပ်ရန်။"</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"မျက်နှာပြင်လော့ခ်ဖွင့်ရန် ကြိုးပမ်းမှုများကို စောင့်ကြည့်ပါ"</string>
@@ -1873,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS တောင်းဆိုမှုကို ဗီဒီယိုခေါ်ဆိုမှုသို့ ပြောင်းထားသည်"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS တောင်းဆိုမှုကို USSD တောင်းဆိုမှုအဖြစ် ပြောင်းထားသည်"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"SS တောင်းဆိုမှုအသစ်သို့ ပြောင်းထားသည်"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"အယောင်ဆောင်ဖြားယောင်းခြင်း သတိပေးချက်"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"အလုပ်ကိုယ်ရေးအချက်အလက်"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"သတိပေးထားသည်"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"ချဲ့ရန်"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 4e05659a0732..c84670154549 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Lar appen lese og skrive konfigurasjon av Ikke forstyrr."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"start visning av bruk av tillatelser"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Lar innehaveren starte bruk av tillatelser for en app. Dette skal aldri være nødvendig for vanlige apper."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"tilgang til sensordata ved høy samplingfrekvens"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Lar appen samle inn sensordata ved en hastighet som er høyere enn 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Angi passordregler"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Kontrollerer tillatt lengde og tillatte tegn i passord og PIN-koder for opplåsing av skjermen."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Overvåk forsøk på å låse opp skjermen"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS-forespørsel endret til videoanrop"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS-forespørsel endret til USSD-forespørsel"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Endret til ny SS-forespørsel"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Arbeidsprofil"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Varslet"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Vis"</string>
diff --git a/core/res/res/values-ne/strings.xml b/core/res/res/values-ne/strings.xml
index f76011ae439c..9af472aa3322 100644
--- a/core/res/res/values-ne/strings.xml
+++ b/core/res/res/values-ne/strings.xml
@@ -1873,6 +1873,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS अनुरोधलाई भिडियो कलमा परिवर्तन गरियो"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS अनुरोधलाई USSD अनुरोधमा परिवर्तन गरियो"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"नयाँ SS अनुरोधमा परिवर्तन गरियो"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"कार्य प्रोफाइल"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"सतर्कता गरियो"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"विस्तृत गर्नुहोस्"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 01d4a70bd958..d76d32a8d6b2 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Hiermee kan de app configuratie voor Niet storen lezen en schrijven."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"rechtengebruik starten"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Hiermee kan de houder het rechtengebruik voor een app starten. Nooit vereist voor normale apps."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"toegang krijgen tot sensorgegevens met een hoge samplingsnelheid"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Hiermee kan de app sensorgegevens samplen met een snelheid die hoger is dan 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Wachtwoordregels instellen"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"De lengte en het aantal tekens beheren die zijn toegestaan in wachtwoorden en pincodes voor schermvergrendeling."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Pogingen voor schermontgrendeling bijhouden"</string>
@@ -1873,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS-verzoek gewijzigd in videogesprek"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS-verzoek gewijzigd in USSD-verzoek"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Gewijzigd in nieuw SS-verzoek"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Phishingmelding"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Werkprofiel"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Gemeld"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Uitvouwen"</string>
diff --git a/core/res/res/values-or/strings.xml b/core/res/res/values-or/strings.xml
index e14578758c49..f42d8abbcee2 100644
--- a/core/res/res/values-or/strings.xml
+++ b/core/res/res/values-or/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"\"ବିରକ୍ତ କରନ୍ତୁ ନାହିଁ\" କନଫିଗରେଶନ୍‍ ପଢ଼ିବା ତଥା ଲେଖିବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦେଇଥାଏ।"</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"ଅନୁମତି ବ୍ୟବହାର ଦେଖିବା ଆରମ୍ଭ କରନ୍ତୁ"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"ଏକ ଆପ୍ ପାଇଁ ଅନୁମତିର ବ୍ୟବହାର ଆରମ୍ଭ କରିବାକୁ ଧାରକକୁ ଅନୁମତି ଦେଇଥାଏ। ସାଧାରଣ ଆପ୍‌ଗୁଡ଼ିକ ପାଇଁ ଏହା ଆବଶ୍ୟକ ନୁହେଁ।"</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"ଏକ ଉଚ୍ଚ ନମୁନାକରଣ ରେଟରେ ସେନ୍ସର୍ ଡାଟାକୁ ଆକ୍ସେସ୍ କରନ୍ତୁ"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"200 Hz ଠାରୁ ଅଧିକ ଏକ ରେଟରେ ସେନ୍ସର୍ ଡାଟାର ନମୁନା ନେବା ପାଇଁ ଆପକୁ ଅନୁମତି ଦିଏ"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"ପାସ୍‌ୱର୍ଡ ନିୟମାବଳୀ ସେଟ୍ କରନ୍ତୁ"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"ଲକ୍‍ ସ୍କ୍ରୀନ୍‍ ପାସ୍‌ୱର୍ଡ ଓ PINରେ ଅନୁମୋଦିତ ଦୀର୍ଘତା ଓ ବର୍ଣ୍ଣ ନିୟନ୍ତ୍ରଣ କରନ୍ତୁ।"</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"ସ୍କ୍ରୀନ୍-ଅନଲକ୍ କରିବା ଉଦ୍ୟମ ନୀରିକ୍ଷଣ କରନ୍ତୁ"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SSଙ୍କ ଅନୁରୋଧକୁ ଭିଡିଓ କଲ୍‌ରେ ପରିବର୍ତ୍ତନ କରାଗଲା"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS ଅନୁରୋଧ, USSD ଅନୁରୋଧକୁ ପରିବର୍ତ୍ତନ ହେଲା"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"ନୂତନ SS ଅନୁରୋଧରେ ପରିବର୍ତ୍ତନ ହେଲା"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"ୱର୍କ ପ୍ରୋଫାଇଲ୍‌"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"ଆଲର୍ଟ କରାଯାଇଛି"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"ବଢ଼ାନ୍ତୁ"</string>
diff --git a/core/res/res/values-pa/strings.xml b/core/res/res/values-pa/strings.xml
index c51845b82563..17a4944c1b14 100644
--- a/core/res/res/values-pa/strings.xml
+++ b/core/res/res/values-pa/strings.xml
@@ -1873,6 +1873,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS ਬੇਨਤੀ ਨੂੰ ਵੀਡੀਓ ਕਾਲ ਵਿੱਚ ਬਦਲਿਆ ਗਿਆ"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS ਬੇਨਤੀ ਨੂੰ USSD ਬੇਨਤੀ ਵਿੱਚ ਬਦਲਿਆ ਗਿਆ"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"ਨਵੀਂ SS ਬੇਨਤੀ ਵਿੱਚ ਬਦਲਿਆ ਗਿਆ"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"ਕਾਰਜ ਪ੍ਰੋਫਾਈਲ"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"ਸੁਚੇਤਨਾਵਾਂ"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"ਵਿਸਤਾਰ ਕਰੋ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 6f54b413af03..14ca2b9d8a18 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -691,10 +691,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Pozwala aplikacji na odczyt i zmianę konfiguracji trybu Nie przeszkadzać."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"rozpocząć wyświetlanie użycia uprawnień"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Umożliwia rozpoczęcie korzystania z uprawnienia dotyczącego danej aplikacji jego posiadaczowi. Zwykłe aplikacje nie powinny potrzebować tego uprawnienia."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"dostęp do danych czujnika z wysoką częstotliwością"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Zezwala aplikacji na pobieranie próbek danych z czujnika z częstotliwością wyższą niż 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Określ reguły hasła"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Kontrolowanie długości haseł blokady ekranu i kodów PIN oraz dozwolonych w nich znaków."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Monitorowanie prób odblokowania ekranu"</string>
@@ -1935,6 +1933,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Żądanie SS zmienione na rozmowę wideo"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Żądanie SS zmienione na żądanie USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Zmieniono na nowe żądanie SS"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Profil służbowy"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Alert"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Rozwiń"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index bfab1f39a06e..3fbfd7ebc075 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -1871,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Solicitação SS alterada para videochamada"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Solicitação SS alterada para solicitação USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Alterada para uma nova solicitação SS"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Alerta de phishing"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Perfil de trabalho"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Alertado"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Expandir"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index ee18a2f632b3..eb09af88f69a 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Permite à app ler e alterar a configuração de Não incomodar"</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"iniciar utilização da autorização de visualização"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Permite que o titular inicie a utilização de autorizações para uma app. Nunca deverá ser necessário para aplicações normais."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"aceder aos dados de sensores a uma taxa de amostragem elevada"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Permite que a app obtenha uma amostra dos dados de sensores a uma taxa superior a 200 Hz."</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Definir regras de palavra-passe"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Controlar o comprimento e os carateres permitidos nos PINs e nas palavras-passe do bloqueio de ecrã."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Monitorizar tentativas de desbloqueio do ecrã"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"O pedido SS foi alterado para uma videochamada."</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"O pedido SS foi alterado para um novo pedido USSD."</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Foi alterado para um novo pedido SS."</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Perfil de trabalho"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Alertado"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Expandir"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index bfab1f39a06e..bad102e5e0b8 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -1871,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Solicitação SS alterada para videochamada"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Solicitação SS alterada para solicitação USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Alterada para uma nova solicitação SS"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Perfil de trabalho"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Alertado"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Expandir"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 9e6b3f9b9309..1e789e448955 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -688,10 +688,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Permite aplicației să citească și să scrie configurația Nu deranja."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"porniți folosirea permisiunii de vizualizare"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Permite proprietarului să pornească folosirea permisiunii pentru o aplicație. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"să acceseze date de la senzori la o rată de eșantionare mare"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Permite aplicației să colecteze date de la senzori la o rată de eșantionare de peste 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Să seteze reguli pentru parolă"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Stabiliți lungimea și tipul de caractere permise pentru parolele și codurile PIN de blocare a ecranului."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Să monitorizeze încercările de deblocare a ecranului"</string>
@@ -1904,6 +1902,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Solicitarea SS a fost schimbată cu un apel video"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Solicitarea SS a fost schimbată cu o solicitare USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Schimbat cu o solicitare SS nouă"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Alertă privind phishingul"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Profil de serviciu"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Notificat"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Extindeți"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index c2377099d409..5cb8a5087321 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -691,10 +691,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Открывает приложению доступ к настройкам режима \"Не беспокоить\" и позволяет изменять их."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"Просмотр данных об используемых разрешениях"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Приложение получит доступ к данным об используемых разрешениях. Это разрешение не требуется обычным приложениям."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"Доступ к данным датчиков при высокой частоте дискретизации"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Приложение сможет считывать данные датчиков на частоте более 200 Гц."</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Настройка правил для паролей"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Контролировать длину и символы при вводе пароля и PIN-кода."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Отслеживание попыток разблокировать экран"</string>
@@ -1935,6 +1933,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS-запрос преобразован в видеовызов"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS-запрос преобразован в USSD-запрос"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Преобразовано в SS-запрос"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Рабочий профиль"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Отправлено оповещение"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Развернуть"</string>
diff --git a/core/res/res/values-si/strings.xml b/core/res/res/values-si/strings.xml
index 5a00e9265166..bd311fb958e0 100644
--- a/core/res/res/values-si/strings.xml
+++ b/core/res/res/values-si/strings.xml
@@ -1871,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS ඉල්ලීම වීඩියෝ ඇමතුමට වෙනස් කරන ලදී"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS ඉල්ලීම USSD ඉල්ලීමට වෙනස් කරන ලදී"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"නව SS ඉල්ලීමට වෙනස් කරන ලදී"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"තතුබෑම් ඇඟවීම"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"කාර්යාල පැතිකඩ"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"අනතුරු අඟවන ලදී"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"දිග හරින්න"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index de7a2a4f65ac..825215b1fae1 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -691,10 +691,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Umožňuje aplikácii čítať a zapisovať konfiguráciu režimu bez vyrušení."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"spustenie používania povolenia na zobrazenie"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Umožňuje držiteľovi spustiť používanie povolenia aplikáciou. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"prístup k dátam senzorom s vysokou vzorkovacou frekvenciou"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Umožňuje aplikácii vzorkovať dáta senzorov s frekvenciou vyššou ako 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Nastaviť pravidlá pre heslo"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Nastavte dĺžku hesiel na odomknutie obrazovky aj kódov PIN a v nich používané znaky."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Sledovanie pokusov o odomknutie obrazovky"</string>
@@ -1935,6 +1933,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Žiadosť SS bola zmenená na videohovor"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Žiadosť SS bola zmenená na žiadosť USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Zmenené na novú žiadosť SS"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Pracovný profil"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Upozornené"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Rozbaliť"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index 3575131884d3..a27b805c21db 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -691,10 +691,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Aplikaciji omogoča branje in pisanje konfiguracije načina »ne moti«."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"začetek uporabe dovoljenja za ogledovanje"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Imetniku omogoča začetek uporabe dovoljenj za aplikacijo. Nikoli ni potrebno za navadne aplikacije."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"dostop do podatkov tipal z večjo hitrostjo vzorčenja"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Aplikaciji dovoljuje, da vzorči podatke tipal s hitrostjo, večjo od 200 Hz."</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Nastavitev pravil za geslo"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Nadzor nad dolžino in znaki, ki so dovoljeni v geslih in kodah PIN za odklepanje zaslona."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Nadzor nad poskusi odklepanja zaslona"</string>
@@ -1935,6 +1933,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Zahteva SS je spremenjena v videoklic"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Zahteva SS je spremenjena v zahtevo USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Spremenjeno v novo zahtevo SS"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Opozorilo o lažnem predstavljanju"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Delovni profil"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Opozorilo prikazano"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Razširi"</string>
diff --git a/core/res/res/values-sq/strings.xml b/core/res/res/values-sq/strings.xml
index 8857e08002ad..823b963c8b62 100644
--- a/core/res/res/values-sq/strings.xml
+++ b/core/res/res/values-sq/strings.xml
@@ -1871,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Kërkesa SS u ndryshua në telefonatë me video"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Kërkesa SS u ndryshua në kërkesë USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"U ndryshua në kërkesë të re SS"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Profili i punës"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Sinjalizuar"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Zgjero"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index 4aca2009b567..74589a85d700 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -688,10 +688,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Дозвољава апликацији да чита и уписује конфигурацију подешавања Не узнемиравај."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"почетак коришћења дозволе за преглед"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Дозвољава власнику да започне коришћење дозволе за апликацију. Никада не би требало да буде потребна за уобичајене апликације."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"приступ подацима сензора при великој брзини узорковања"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Дозвољава апликацији да узима узорак података сензора при брзини већој од 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Подешавање правила за лозинку"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Контролише дужину и знакове дозвољене у лозинкама и PIN-овима за закључавање екрана."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Надгледајте покушаје откључавања екрана"</string>
@@ -1904,6 +1902,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS захтев је промењен у видео позив"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS захтев је промењен у USSD захтев"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Промењено је у нови SS захтев"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Упозорење о „пецању“"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Пословни профил"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Обавештено"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Прошири"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index fb6d4ce3828c..47bfe0a00360 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Ger appen läs- och skrivbehörighet till konfigurationen för Stör ej."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"börja visa behörighetsanvändningen"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Gör att innehavaren kan öppna behörighetsanvändning för en app. Ska inte behövas för vanliga appar."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"åtkomst till sensordata med en hög samplingsfrekvens"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Tillåter att appen får åtkomst till sensordata med en högre samplingsfrekvens än 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Ange lösenordsregler"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Styr tillåten längd och tillåtna tecken i lösenord och pinkoder för skärmlåset."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Övervaka försök att låsa upp skärmen"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS-begäran har ändrats till videosamtal"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS-begäran har ändrats till en USSD-begäran"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Har ändrats till ny SS-begäran"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Jobbprofil"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Aviserad"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Utöka"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 93dc3b922d3f..fcc9c9dca038 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -1871,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Imebadilisha ombi la SS kuwa simu ya video"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Imebadilisha ombi la SS kuwa ombi la USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Imebadilisha kuwa ombi jipya la SS"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"Arifa ya wizi wa data binafsi"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Wasifu wa kazini"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Imearifu"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Panua"</string>
diff --git a/core/res/res/values-ta/strings.xml b/core/res/res/values-ta/strings.xml
index e70ffecc33bb..535fb6c45e10 100644
--- a/core/res/res/values-ta/strings.xml
+++ b/core/res/res/values-ta/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"தொந்தரவு செய்ய வேண்டாம் உள்ளமைவைப் படிக்கவும் எழுதவும், ஆப்ஸை அனுமதிக்கிறது."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"அனுமதி உபயோகத்தை அணுகுதல்"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"ஆப்ஸிற்கான அனுமதி உபயோகத்தை ஹோல்டருக்கு வழங்கும். இயல்பான ஆப்ஸிற்கு இது எப்போதுமே தேவைப்படாது."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"அதிகளவிலான சாம்பிளிங் ரேட்டில் சென்சார் தரவை அணுகுதல்"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"200 ஹெர்ட்ஸ்க்கும் அதிகமான வீதத்தில் சென்சார் தரவை மாதிரியாக்க ஆப்ஸை அனுமதிக்கும்"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"கடவுச்சொல் விதிகளை அமைக்கவும்"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"திரைப் பூட்டின் கடவுச்சொற்கள் மற்றும் பின்களில் அனுமதிக்கப்படும் நீளத்தையும் எழுத்துக்குறிகளையும் கட்டுப்படுத்தும்."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"திரையைத் திறப்பதற்கான முயற்சிகளைக் கண்காணி"</string>
@@ -1873,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS கோரிக்கை, வீடியோ அழைப்பிற்கு மாற்றப்பட்டது"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS கோரிக்கை, USSD கோரிக்கைக்கு மாற்றப்பட்டது"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"புதிய SS கோரிக்கைக்கு மாற்றப்பட்டது"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"ஃபிஷிங் எச்சரிக்கை"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"பணிக் கணக்கு"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"விழிப்பூட்டல் ஐகான்"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"விரிவாக்கும்"</string>
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 365e6d748710..59d451abae2d 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -1873,6 +1873,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS అభ్యర్థన వీడియో కాల్‌కి మార్చబడింది"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS అభ్యర్థన USSD అభ్యర్థనకు మార్చబడింది"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"కొత్త SS అభ్యర్థనకు మార్చబడింది"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"ఫిషింగ్ అలర్ట్"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"కార్యాలయ ప్రొఫైల్‌"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"హెచ్చరించబడింది"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"విస్తరింపజేయి"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index b41e892180cb..cb21c725574b 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"อนุญาตให้แอปอ่านและเขียนการกำหนดค่าโหมดห้ามรบกวน"</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"เริ่มการใช้สิทธิ์การดู"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"อนุญาตให้เจ้าของเริ่มการใช้สิทธิ์ของแอป ไม่จำเป็นสำหรับแอปทั่วไป"</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"เข้าถึงข้อมูลเซ็นเซอร์ที่อัตราการสุ่มตัวอย่างสูง"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"อนุญาตให้แอปสุ่มตัวอย่างข้อมูลเซ็นเซอร์ที่อัตราสูงกว่า 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"ตั้งค่ากฎรหัสผ่าน"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"ควบคุมความยาวและอักขระที่สามารถใช้ในรหัสผ่านของการล็อกหน้าจอและ PIN"</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"ตรวจสอบความพยายามในการปลดล็อกหน้าจอ"</string>
@@ -1873,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"คำขอ SS เปลี่ยนเป็นวิดีโอคอลแล้ว"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"คำขอ SS เปลี่ยนเป็นคำขอ USSD แล้ว"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"เปลี่ยนเป็นคำขอ SS ใหม่แล้ว"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"การแจ้งเตือนฟิชชิง"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"โปรไฟล์งาน"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"แจ้งเตือนแล้ว"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"ขยาย"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index c617ccf67068..6f00ba8d3e5c 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1871,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Ginawang video call ang SS na kahilingan"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Ginawang USSD na kahilingan ang SS na kahilingan"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Ginawang bagong SS na kahilingan"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Profile sa trabaho"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Naalertuhan"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Palawakin"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 5724bcf2cc39..67086d2e1fdc 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -1871,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS isteği görüntülü görüşme olarak değişti"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS isteği USSD isteği olarak değişti"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Yeni SS isteği olarak değişti"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"İş profili"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Sesli uyarıldı"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Genişlet"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index ff1936f2a2f7..d6a3677b844b 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -691,10 +691,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Додаток зможе переглядати та змінювати конфігурацію режиму \"Не турбувати\"."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"перегляньте дані про використання дозволів"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Власник зможе використовувати дозволи для цього додатка. Цей дозвіл не потрібен для звичайних додатків."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"доступ до даних датчиків із високою частотою дикретизації"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Додаток зможе дискретизувати дані даних датчиків із частотою понад 200 Гц"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Устан. правила пароля"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Укажіть максимальну довжину та кількість символів для паролів розблокування екрана та PIN-кодів."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Відстежувати спроби розблокування екрана"</string>
@@ -1935,6 +1933,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Запит SS змінено на відеовиклик"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Запит SS змінено на запит USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Змінено на новий запит SS"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Робочий профіль"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Зі звуком"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Розгорнути"</string>
diff --git a/core/res/res/values-ur/strings.xml b/core/res/res/values-ur/strings.xml
index e1fb04cc0abe..9a7cb8764670 100644
--- a/core/res/res/values-ur/strings.xml
+++ b/core/res/res/values-ur/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"ایپ کو ڈسٹرب نہ کریں کنفیگریشن لکھنے اور پڑھنے کے قابل کرتا ہے۔"</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"اجازت کی استعمال کا ملاحظہ شروع کریں"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"حامل کو ایپ کی اجازت کے استعمال کو شروع کرنے کی اجازت دیتا ہے۔ عام ایپس کے لیے کبھی بھی درکار نہیں ہونا چاہیے۔"</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"نمونہ کاری کی اعلی شرح پر سینسر کے ڈیٹا تک رسائی حاصل کریں"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"‏ایپ کو Hz‏200 سے زیادہ شرح پر سینسر ڈیٹا کا نمونہ لینے کی اجازت دیتی ہے"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"پاس ورڈ کے اصول سیٹ کریں"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"‏اسکرین لاک پاس ورڈز اور PINs میں اجازت یافتہ لمبائی اور حروف کو کنٹرول کریں۔"</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"اسکرین غیر مقفل کرنے کی کوششیں مانیٹر کریں"</string>
@@ -1873,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"‏SS درخواست کو ویڈیو کال میں تبدیل کر دیا گیا"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"‏SS درخواست کو USSD درخواست میں تبدیل کر دیا گیا"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"‏نئی SS درخواست میں تبدیل کر دیا گیا"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"فریب دہی کا الرٹ"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"دفتری پروفائل"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"الرٹ کیا گیا"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"پھیلائیں"</string>
diff --git a/core/res/res/values-uz/strings.xml b/core/res/res/values-uz/strings.xml
index ddb5b1cc0710..60134a477b66 100644
--- a/core/res/res/values-uz/strings.xml
+++ b/core/res/res/values-uz/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"“Bezovta qilinmasin” rejimi sozlamalarini ko‘rish va o‘zgartirish."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"foydalaniladigan ruxsatlar axborotini ochish"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Ilova foydalanadigan ruxsatlar axborotini ishga tushirishga ruxsat beradi. Oddiy ilovalar uchun talab qilinmaydi."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"yuqori diskretlash chastotali sensor axborotiga ruxsat"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Ilova sensor axborotini 200 Hz dan yuqori tezlikda hisoblashi mumkin"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Parol qoidalarini o‘rnatish"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Ekran qulfi paroli va PIN kodlari uchun qo‘yiladigan talablarni (belgilar soni va uzunligi) nazorat qiladi."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Ekranni qulfdan chiqarishga urinishlarni nazorat qilish"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS talabi video chaqiruvga almashtirildi"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS talabi USSD talabiga almashtirildi"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Yangi SS talabiga almashtirildi"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Ish profili"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Ogohlantirildi"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Yoyish"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 13ffe3021c12..25f0644903b5 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Cho phép ứng dụng đọc và ghi cấu hình Không làm phiền."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"cấp quyền xem"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Cho phép chủ sở hữu cấp quyền cho một ứng dụng. Các ứng dụng thông thường sẽ không bao giờ cần quyền này."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"truy cập vào dữ liệu cảm biến ở tốc độ lấy mẫu cao"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Cho phép ứng dụng lấy mẫu dữ liệu cảm biến ở tốc độ lớn hơn 200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Đặt quy tắc mật khẩu"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Kiểm soát độ dài và ký tự được phép trong mật khẩu khóa màn hình và mã PIN."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Giám sát những lần thử mở khóa màn hình"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Yêu cầu SS đã thay đổi thành cuộc gọi video"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Yêu cầu SS đã thay đổi thành yêu cầu USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Đã thay đổi thành yêu cầu SS mới"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Hồ sơ công việc"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Đã phát âm báo"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Mở rộng"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 13fa62aec28d..358367ed2d8b 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"允许此应用读取和写入“勿扰”模式配置。"</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"授权使用“查看权限”"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"允许该应用开始查看应用的权限使用情况(普通应用绝不需要此权限)。"</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"以高采样率访问传感器数据"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"允许应用以高于 200 Hz 的频率对传感器数据进行采样"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"设置密码规则"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"控制锁屏密码和 PIN 码所允许的长度和字符。"</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"监控屏幕解锁尝试次数"</string>
@@ -1873,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS 请求已更改为视频通话"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS 请求已更改为 USSD 请求"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"已更改为新的 SS 请求"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"网上诱骗警报"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"工作资料"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"已提醒"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"展开"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index dd5eada00c37..e4fa2e0c9488 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"允許應用程式讀取和寫入「請勿騷擾」設定。"</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"開始查看權限使用情況"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"允許應用程式開始查看應用程式的權限使用情況 (一般應用程式並不需要)。"</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"以高取樣率存取感應器資料"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"允許應用程式以大於 200 Hz 的頻率對感應器資料進行取樣"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"設定密碼規則"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"控制螢幕鎖定密碼和 PIN 所允許的長度和字元。"</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"監控螢幕解鎖嘗試次數"</string>
@@ -1873,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS 要求已變更為視像通話"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS 要求已變更為 USSD 要求"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"已變更為新的 SS 要求"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"仿冒詐騙警示"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"工作設定檔"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"已提醒"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"展開"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index a2573440f9bb..49e57b3261dc 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"允許應用程式讀取及寫入「零打擾」設定。"</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"啟動檢視權限用途"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"允許應用程式開始使用其他應用程式 (一般應用程式並不需要)。"</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"以高取樣率存取感應器資料"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"允許應用程式以高於 200 Hz 的頻率對感應器資料進行取樣"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"設定密碼規則"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"管理螢幕鎖定密碼和 PIN 碼支援的字元和長度上限。"</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"監控螢幕解鎖嘗試次數"</string>
@@ -1873,6 +1871,7 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"SS 要求已變更為視訊通話"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"SS 要求已變更為 USSD 要求"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"已變更為新的 SS 要求"</string>
+ <string name="notification_phishing_alert_content_description" msgid="494227305355958790">"網路詐騙警示"</string>
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"工作資料夾"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"已提醒"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"展開"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 712e57823a38..9a21e78361a4 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -685,10 +685,8 @@
<string name="permdesc_access_notification_policy" msgid="8538374112403845013">"Ivumela izinhlelo zokusebenza ukufunda nokubhala ukulungiswa kokuthi Ungaphazamisi."</string>
<string name="permlab_startViewPermissionUsage" msgid="1504564328641112341">"qala ukusetshenziswa kokubuka imvume"</string>
<string name="permdesc_startViewPermissionUsage" msgid="2820325605959586538">"Ivumela umphathi ukuthi aqale ukusetshenziswa kwemvume kohlelo lokusebenza. Akumele idingelwe izinhlelo zokusebenza ezijwayelekile."</string>
- <!-- no translation found for permlab_highSamplingRateSensors (3941068435726317070) -->
- <skip />
- <!-- no translation found for permdesc_highSamplingRateSensors (8430061978931155995) -->
- <skip />
+ <string name="permlab_highSamplingRateSensors" msgid="3941068435726317070">"finyelela idatha yenzwa ngenani eliphezulu lokwenza isampuli"</string>
+ <string name="permdesc_highSamplingRateSensors" msgid="8430061978931155995">"Ivumela uhlelo lokusebenza lusampule idatha yenzwa ngenani elikhulu kuno-200 Hz"</string>
<string name="policylab_limitPassword" msgid="4851829918814422199">"Misa imithetho yephasiwedi"</string>
<string name="policydesc_limitPassword" msgid="4105491021115793793">"Lawula ubude nezinhlamvu ezivunyelwe kumaphasiwedi wokukhiya isikrini nama-PIN."</string>
<string name="policylab_watchLogin" msgid="7599669460083719504">"Qapha imizamo yokuvula isikrini sakho"</string>
@@ -1873,6 +1871,8 @@
<string name="stk_cc_ss_to_dial_video" msgid="1324194624384312664">"Isicelo se-SS sishintshele kukholi yevidiyo"</string>
<string name="stk_cc_ss_to_ussd" msgid="8417905193112944760">"Isicelo se-SS sishintshele kusicelo se-USSD"</string>
<string name="stk_cc_ss_to_ss" msgid="132040645206514450">"Ishintshele kusicelo esisha se-SS"</string>
+ <!-- no translation found for notification_phishing_alert_content_description (494227305355958790) -->
+ <skip />
<string name="notification_work_profile_content_description" msgid="5296477955677725799">"Iphrofayela yomsebenzi"</string>
<string name="notification_alerted_content_description" msgid="6139691253611265992">"Kuxwayisiwe"</string>
<string name="expand_button_content_description_collapsed" msgid="3873368935659010279">"Nweba"</string>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 3c712edffa63..1ca54985dfbc 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -30,7 +30,13 @@
will be displayed in the app launcher and elsewhere. -->
<dimen name="app_icon_size">48dip</dimen>
- <dimen name="toast_y_offset">24dp</dimen>
+ <!-- Offset from the bottom of the device a toast shows -->
+ <dimen name="toast_y_offset">48dp</dimen>
+ <!-- Max width of a toast -->
+ <dimen name="toast_width">300dp</dimen>
+ <!-- Text size of the message within a toast -->
+ <dimen name="toast_text_size">14sp</dimen>
+
<!-- Height of the status bar -->
<dimen name="status_bar_height">@dimen/status_bar_height_portrait</dimen>
<!-- Height of the status bar in portrait. The height should be
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 24afe07b57cf..c7ded0cfa3a2 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -964,8 +964,9 @@ please see styles_device_defaults.xml.
</style>
<style name="TextAppearance.Toast">
- <item name="fontFamily">sans-serif</item>
+ <item name="fontFamily">@*android:string/config_headlineFontFamily</item>
<item name="textSize">14sp</item>
+ <item name="textColor">?android:attr/textColorPrimary</item>
</style>
<style name="TextAppearance.Tooltip">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index b5af5240b843..e73d6e3af3cb 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4203,4 +4203,6 @@
<java-symbol type="bool" name="config_telephony5gNonStandalone" />
<java-symbol type="bool" name="config_voice_data_sms_auto_fallback" />
+
+ <java-symbol type="bool" name="config_enableOneHandedKeyguard" />
</resources>
diff --git a/core/tests/coretests/src/android/app/time/ExternalTimeSuggestionTest.java b/core/tests/coretests/src/android/app/time/ExternalTimeSuggestionTest.java
index 266ff3dd09f6..1c6b3cc47a45 100644
--- a/core/tests/coretests/src/android/app/time/ExternalTimeSuggestionTest.java
+++ b/core/tests/coretests/src/android/app/time/ExternalTimeSuggestionTest.java
@@ -33,17 +33,20 @@ public class ExternalTimeSuggestionTest {
@Test
public void testEquals() {
- ExternalTimeSuggestion one = new ExternalTimeSuggestion(ARBITRARY_TIME);
+ ExternalTimeSuggestion one = new ExternalTimeSuggestion(
+ ARBITRARY_TIME.getReferenceTimeMillis(),
+ ARBITRARY_TIME.getValue());
assertEquals(one, one);
- ExternalTimeSuggestion two = new ExternalTimeSuggestion(ARBITRARY_TIME);
+ ExternalTimeSuggestion two = new ExternalTimeSuggestion(
+ ARBITRARY_TIME.getReferenceTimeMillis(),
+ ARBITRARY_TIME.getValue());
assertEquals(one, two);
assertEquals(two, one);
- TimestampedValue<Long> differentTime = new TimestampedValue<>(
+ ExternalTimeSuggestion three = new ExternalTimeSuggestion(
ARBITRARY_TIME.getReferenceTimeMillis() + 1,
ARBITRARY_TIME.getValue());
- ExternalTimeSuggestion three = new ExternalTimeSuggestion(differentTime);
assertNotEquals(one, three);
assertNotEquals(three, one);
@@ -55,7 +58,9 @@ public class ExternalTimeSuggestionTest {
@Test
public void testParcelable() {
- ExternalTimeSuggestion suggestion = new ExternalTimeSuggestion(ARBITRARY_TIME);
+ ExternalTimeSuggestion suggestion = new ExternalTimeSuggestion(
+ ARBITRARY_TIME.getReferenceTimeMillis(),
+ ARBITRARY_TIME.getValue());
assertRoundTripParcelable(suggestion);
// DebugInfo should also be stored (but is not checked by equals())
diff --git a/data/etc/car/com.android.car.bugreport.xml b/data/etc/car/com.android.car.bugreport.xml
index 432a838a90e8..c3642d886180 100644
--- a/data/etc/car/com.android.car.bugreport.xml
+++ b/data/etc/car/com.android.car.bugreport.xml
@@ -20,5 +20,6 @@
<permission name="android.permission.INTERACT_ACROSS_USERS"/>
<permission name="android.permission.READ_LOGS"/>
<permission name="android.permission.MANAGE_USERS"/>
+ <permission name="android.permission.BROADCAST_CLOSE_SYSTEM_DIALOGS"/>
</privapp-permissions>
</permissions>
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 5633de348433..cabfad44cfb9 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -1321,6 +1321,12 @@
"group": "WM_DEBUG_ORIENTATION",
"at": "com\/android\/server\/wm\/DisplayRotation.java"
},
+ "-567946587": {
+ "message": "Requested redraw for orientation change: %s",
+ "level": "VERBOSE",
+ "group": "WM_DEBUG_ORIENTATION",
+ "at": "com\/android\/server\/wm\/WindowState.java"
+ },
"-561092364": {
"message": "onPointerDownOutsideFocusLocked called on %s",
"level": "INFO",
diff --git a/graphics/java/android/graphics/BlurShader.java b/graphics/java/android/graphics/BlurShader.java
deleted file mode 100644
index 2e4bd7d9be43..000000000000
--- a/graphics/java/android/graphics/BlurShader.java
+++ /dev/null
@@ -1,89 +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 android.graphics;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-
-/**
- * A subclass of shader that blurs input from another {@link android.graphics.Shader} instance
- * or all the drawing commands with the {@link android.graphics.Paint} that this shader is
- * attached to.
- */
-public final class BlurShader extends Shader {
-
- private final float mRadiusX;
- private final float mRadiusY;
- private final Shader mInputShader;
- private final TileMode mEdgeTreatment;
-
- private long mNativeInputShader = 0;
-
- /**
- * Create a {@link BlurShader} that blurs the contents of the optional input shader
- * with the specified radius along the x and y axis. If no input shader is provided
- * then all drawing commands issued with a {@link android.graphics.Paint} that this
- * shader is installed in will be blurred.
- *
- * This uses a default {@link TileMode#DECAL} for edge treatment
- *
- * @param radiusX Radius of blur along the X axis
- * @param radiusY Radius of blur along the Y axis
- * @param inputShader Input shader that provides the content to be blurred
- */
- public BlurShader(float radiusX, float radiusY, @Nullable Shader inputShader) {
- this(radiusX, radiusY, inputShader, TileMode.DECAL);
- }
-
- /**
- * Create a {@link BlurShader} that blurs the contents of the optional input shader
- * with the specified radius along the x and y axis. If no input shader is provided
- * then all drawing commands issued with a {@link android.graphics.Paint} that this
- * shader is installed in will be blurred
- * @param radiusX Radius of blur along the X axis
- * @param radiusY Radius of blur along the Y axis
- * @param inputShader Input shader that provides the content to be blurred
- * @param edgeTreatment Policy for how to blur content near edges of the blur shader
- */
- public BlurShader(float radiusX, float radiusY, @Nullable Shader inputShader,
- @NonNull TileMode edgeTreatment) {
- mRadiusX = radiusX;
- mRadiusY = radiusY;
- mInputShader = inputShader;
- mEdgeTreatment = edgeTreatment;
- }
-
- /** @hide **/
- @Override
- protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
- mNativeInputShader = mInputShader != null
- ? mInputShader.getNativeInstance(filterFromPaint) : 0;
- return nativeCreate(nativeMatrix, mRadiusX, mRadiusY, mNativeInputShader,
- mEdgeTreatment.nativeInt);
- }
-
- /** @hide **/
- @Override
- protected boolean shouldDiscardNativeInstance(boolean filterFromPaint) {
- long currentNativeInstance = mInputShader != null
- ? mInputShader.getNativeInstance(filterFromPaint) : 0;
- return mNativeInputShader != currentNativeInstance;
- }
-
- private static native long nativeCreate(long nativeMatrix, float radiusX, float radiusY,
- long inputShader, int edgeTreatment);
-}
diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java
index 4a92cf11fa5c..f6f770be3de8 100644
--- a/graphics/java/android/graphics/RenderNode.java
+++ b/graphics/java/android/graphics/RenderNode.java
@@ -272,6 +272,16 @@ public final class RenderNode {
void positionChanged(long frameNumber, int left, int top, int right, int bottom);
/**
+ * Call to apply a stretch effect to any child SurfaceControl layers
+ *
+ * TODO: Fold this into positionChanged & have HWUI do the ASurfaceControl calls?
+ *
+ * @hide
+ */
+ default void applyStretch(long frameNumber, float left, float top, float right,
+ float bottom, float vecX, float vecY, float maxStretch) { }
+
+ /**
* Called by native on RenderThread to notify that the view is no longer in the
* draw tree. UI thread is blocked at this point.
*
@@ -312,6 +322,14 @@ public final class RenderNode {
pul.positionLost(frameNumber);
}
}
+
+ @Override
+ public void applyStretch(long frameNumber, float left, float top, float right, float bottom,
+ float vecX, float vecY, float maxStretch) {
+ for (PositionUpdateListener pul : mListeners) {
+ pul.applyStretch(frameNumber, left, top, right, bottom, vecX, vecY, maxStretch);
+ }
+ }
}
/**
@@ -707,7 +725,7 @@ public final class RenderNode {
if (1.0 < vecY || vecY < -1.0) {
throw new IllegalArgumentException("vecY must be in the range [-1, 1], was " + vecY);
}
- if (top <= bottom || right <= left) {
+ if (top >= bottom || left >= right) {
throw new IllegalArgumentException(
"Stretch region must not be empty, got "
+ new RectF(left, top, right, bottom).toString());
diff --git a/libs/WindowManager/Shell/res/layout/size_compat_mode_hint.xml b/libs/WindowManager/Shell/res/layout/size_compat_mode_hint.xml
index 347c2b47767e..0dea87c6b7fc 100644
--- a/libs/WindowManager/Shell/res/layout/size_compat_mode_hint.xml
+++ b/libs/WindowManager/Shell/res/layout/size_compat_mode_hint.xml
@@ -14,35 +14,52 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<com.android.wm.shell.sizecompatui.SizeCompatHintPopup
+ xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@android:color/background_light"
- android:orientation="vertical">
+ android:layout_height="wrap_content">
- <TextView
- android:layout_width="180dp"
- android:layout_height="wrap_content"
- android:paddingLeft="10dp"
- android:paddingRight="10dp"
- android:paddingTop="10dp"
- android:text="@string/restart_button_description"
- android:textAlignment="viewStart"
- android:textColor="@android:color/primary_text_light"
- android:textSize="16sp" />
-
- <Button
- android:id="@+id/got_it"
+ <FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:includeFontPadding="false"
- android:layout_gravity="end"
- android:minHeight="36dp"
- android:background="?android:attr/selectableItemBackground"
- android:text="@string/got_it"
- android:textAllCaps="true"
- android:textColor="#3c78d8"
- android:textSize="16sp"
- android:textStyle="bold" />
-
-</LinearLayout>
+ android:gravity="center"
+ android:clipToPadding="false"
+ android:padding="@dimen/bubble_elevation">
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="@android:color/background_light"
+ android:elevation="@dimen/bubble_elevation"
+ android:orientation="vertical">
+
+ <TextView
+ android:layout_width="180dp"
+ android:layout_height="wrap_content"
+ android:paddingLeft="10dp"
+ android:paddingRight="10dp"
+ android:paddingTop="10dp"
+ android:text="@string/restart_button_description"
+ android:textAlignment="viewStart"
+ android:textColor="@android:color/primary_text_light"
+ android:textSize="16sp"/>
+
+ <Button
+ android:id="@+id/got_it"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:includeFontPadding="false"
+ android:layout_gravity="end"
+ android:minHeight="36dp"
+ android:background="?android:attr/selectableItemBackground"
+ android:text="@string/got_it"
+ android:textAllCaps="true"
+ android:textColor="#3c78d8"
+ android:textSize="16sp"
+ android:textStyle="bold"/>
+
+ </LinearLayout>
+
+ </FrameLayout>
+
+</com.android.wm.shell.sizecompatui.SizeCompatHintPopup>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipUiEventLogger.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipUiEventLogger.java
index f8b4dd9bc621..a0a76d801cf4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipUiEventLogger.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipUiEventLogger.java
@@ -98,7 +98,16 @@ public class PipUiEventLogger {
PICTURE_IN_PICTURE_CHANGE_ASPECT_RATIO(609),
@UiEvent(doc = "User resize of the picture-in-picture window")
- PICTURE_IN_PICTURE_RESIZE(610);
+ PICTURE_IN_PICTURE_RESIZE(610),
+
+ @UiEvent(doc = "User unstashed picture-in-picture")
+ PICTURE_IN_PICTURE_STASH_UNSTASHED(709),
+
+ @UiEvent(doc = "User stashed picture-in-picture to the left side")
+ PICTURE_IN_PICTURE_STASH_LEFT(710),
+
+ @UiEvent(doc = "User stashed picture-in-picture to the right side")
+ PICTURE_IN_PICTURE_STASH_RIGHT(711);
private final int mId;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
index afc7b5294a2f..5e23281b3438 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipTouchHandler.java
@@ -170,6 +170,7 @@ public class PipTouchHandler {
mPipBoundsAlgorithm = pipBoundsAlgorithm;
mPipBoundsState = pipBoundsState;
mMenuController = menuController;
+ mPipUiEventLogger = pipUiEventLogger;
mMenuController.addListener(new PipMenuListener());
mGesture = new DefaultPipTouchGesture();
mMotionHelper = new PipMotionHelper(mContext, pipBoundsState, pipTaskOrganizer,
@@ -186,6 +187,8 @@ public class PipTouchHandler {
() -> {
if (mPipBoundsState.isStashed()) {
animateToUnStashedState();
+ mPipUiEventLogger.log(
+ PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_STASH_UNSTASHED);
mPipBoundsState.setStashed(STASH_TYPE_NONE);
} else {
mMenuController.showMenuWithPossibleDelay(MENU_STATE_FULL,
@@ -206,8 +209,6 @@ public class PipTouchHandler {
mMotionHelper, pipTaskOrganizer, mPipBoundsAlgorithm.getSnapAlgorithm(),
this::onAccessibilityShowMenu, this::updateMovementBounds, mainExecutor);
- mPipUiEventLogger = pipUiEventLogger;
-
mEnableStash = DeviceConfig.getBoolean(
DeviceConfig.NAMESPACE_SYSTEMUI,
PIP_STASHING,
@@ -867,6 +868,8 @@ public class PipTouchHandler {
if (mEnableStash && shouldStash(vel, getPossiblyMotionBounds())) {
mMotionHelper.stashToEdge(vel.x, vel.y, this::stashEndAction /* endAction */);
} else {
+ mPipUiEventLogger.log(
+ PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_STASH_UNSTASHED);
mPipBoundsState.setStashed(STASH_TYPE_NONE);
mMotionHelper.flingToSnapTarget(vel.x, vel.y,
this::flingEndAction /* endAction */);
@@ -897,6 +900,8 @@ public class PipTouchHandler {
if (!mTouchState.isWaitingForDoubleTap()) {
if (mPipBoundsState.isStashed()) {
animateToUnStashedState();
+ mPipUiEventLogger.log(
+ PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_STASH_UNSTASHED);
mPipBoundsState.setStashed(STASH_TYPE_NONE);
} else {
// User has stalled long enough for this not to be a drag or a double tap,
@@ -921,9 +926,15 @@ public class PipTouchHandler {
&& mPipExclusionBoundsChangeListener.get() != null) {
mPipExclusionBoundsChangeListener.get().accept(mPipBoundsState.getBounds());
}
- if (mPipBoundsState.getBounds().left < 0) {
+ if (mPipBoundsState.getBounds().left < 0
+ && mPipBoundsState.getStashedState() != STASH_TYPE_LEFT) {
+ mPipUiEventLogger.log(
+ PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_STASH_LEFT);
mPipBoundsState.setStashed(STASH_TYPE_LEFT);
- } else {
+ } else if (mPipBoundsState.getBounds().left >= 0
+ && mPipBoundsState.getStashedState() != STASH_TYPE_RIGHT) {
+ mPipUiEventLogger.log(
+ PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_STASH_RIGHT);
mPipBoundsState.setStashed(STASH_TYPE_RIGHT);
}
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatHintPopup.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatHintPopup.java
new file mode 100644
index 000000000000..78af9df30e6a
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatHintPopup.java
@@ -0,0 +1,71 @@
+/*
+ * 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.wm.shell.sizecompatui;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.Color;
+import android.graphics.drawable.RippleDrawable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.Button;
+import android.widget.FrameLayout;
+
+import androidx.annotation.Nullable;
+
+import com.android.wm.shell.R;
+
+/** Popup to show the hint about the {@link SizeCompatRestartButton}. */
+public class SizeCompatHintPopup extends FrameLayout implements View.OnClickListener {
+
+ private SizeCompatUILayout mLayout;
+
+ public SizeCompatHintPopup(Context context) {
+ super(context);
+ }
+
+ public SizeCompatHintPopup(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public SizeCompatHintPopup(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public SizeCompatHintPopup(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ void inject(SizeCompatUILayout layout) {
+ mLayout = layout;
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ final Button gotItButton = findViewById(R.id.got_it);
+ gotItButton.setBackground(new RippleDrawable(ColorStateList.valueOf(Color.LTGRAY),
+ null /* content */, null /* mask */));
+ gotItButton.setOnClickListener(this);
+ }
+
+ @Override
+ public void onClick(View v) {
+ mLayout.dismissHint();
+ }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatRestartButton.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatRestartButton.java
index 9094d7de8d63..08a840297df1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatRestartButton.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatRestartButton.java
@@ -22,19 +22,13 @@ import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.RippleDrawable;
import android.util.AttributeSet;
-import android.view.LayoutInflater;
import android.view.View;
-import android.view.WindowManager;
-import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.ImageButton;
-import android.widget.LinearLayout;
-import android.widget.PopupWindow;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.wm.shell.R;
/** Button to restart the size compat activity. */
@@ -42,10 +36,6 @@ public class SizeCompatRestartButton extends FrameLayout implements View.OnClick
View.OnLongClickListener {
private SizeCompatUILayout mLayout;
- private ImageButton mRestartButton;
- @VisibleForTesting
- PopupWindow mShowingHint;
- private WindowManager.LayoutParams mWinParams;
public SizeCompatRestartButton(@NonNull Context context) {
super(context);
@@ -67,24 +57,19 @@ public class SizeCompatRestartButton extends FrameLayout implements View.OnClick
void inject(SizeCompatUILayout layout) {
mLayout = layout;
- mWinParams = layout.getWindowLayoutParams();
- }
-
- void remove() {
- dismissHint();
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
- mRestartButton = findViewById(R.id.size_compat_restart_button);
+ final ImageButton restartButton = findViewById(R.id.size_compat_restart_button);
final ColorStateList color = ColorStateList.valueOf(Color.LTGRAY);
final GradientDrawable mask = new GradientDrawable();
mask.setShape(GradientDrawable.OVAL);
mask.setColor(color);
- mRestartButton.setBackground(new RippleDrawable(color, null /* content */, mask));
- mRestartButton.setOnClickListener(this);
- mRestartButton.setOnLongClickListener(this);
+ restartButton.setBackground(new RippleDrawable(color, null /* content */, mask));
+ restartButton.setOnClickListener(this);
+ restartButton.setOnLongClickListener(this);
}
@Override
@@ -94,69 +79,7 @@ public class SizeCompatRestartButton extends FrameLayout implements View.OnClick
@Override
public boolean onLongClick(View v) {
- showHint();
+ mLayout.onRestartButtonLongClicked();
return true;
}
-
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- if (mLayout.mShouldShowHint) {
- mLayout.mShouldShowHint = false;
- showHint();
- }
- }
-
- @Override
- public void setVisibility(@Visibility int visibility) {
- if (visibility == View.GONE && mShowingHint != null) {
- // Also dismiss the popup.
- dismissHint();
- }
- super.setVisibility(visibility);
- }
-
- @Override
- public void setLayoutDirection(int layoutDirection) {
- final int gravity = SizeCompatUILayout.getGravity(layoutDirection);
- if (mWinParams.gravity != gravity) {
- mWinParams.gravity = gravity;
- getContext().getSystemService(WindowManager.class).updateViewLayout(this,
- mWinParams);
- }
- super.setLayoutDirection(layoutDirection);
- }
-
- void showHint() {
- if (mShowingHint != null) {
- return;
- }
-
- // TODO: popup is not attached to the button surface. Need to handle this differently for
- // non-fullscreen task.
- final View popupView = LayoutInflater.from(getContext()).inflate(
- R.layout.size_compat_mode_hint, null);
- final PopupWindow popupWindow = new PopupWindow(popupView,
- LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
- popupWindow.setWindowLayoutType(mWinParams.type);
- popupWindow.setElevation(getResources().getDimension(R.dimen.bubble_elevation));
- popupWindow.setAnimationStyle(android.R.style.Animation_InputMethod);
- popupWindow.setClippingEnabled(false);
- popupWindow.setOnDismissListener(() -> mShowingHint = null);
- mShowingHint = popupWindow;
-
- final Button gotItButton = popupView.findViewById(R.id.got_it);
- gotItButton.setBackground(new RippleDrawable(ColorStateList.valueOf(Color.LTGRAY),
- null /* content */, null /* mask */));
- gotItButton.setOnClickListener(view -> dismissHint());
- popupWindow.showAtLocation(mRestartButton, mWinParams.gravity, mLayout.mPopupOffsetX,
- mLayout.mPopupOffsetY);
- }
-
- void dismissHint() {
- if (mShowingHint != null) {
- mShowingHint.dismiss();
- mShowingHint = null;
- }
- }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java
index a3880f497ff3..c981adee9b5c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java
@@ -50,7 +50,7 @@ public class SizeCompatUIController implements DisplayController.OnDisplaysChang
/** Whether the IME is shown on display id. */
private final Set<Integer> mDisplaysWithIme = new ArraySet<>(1);
- /** The showing buttons by task id. */
+ /** The showing UIs by task id. */
private final SparseArray<SizeCompatUILayout> mActiveLayouts = new SparseArray<>(0);
/** Avoid creating display context frequently for non-default display. */
@@ -77,12 +77,12 @@ public class SizeCompatUIController implements DisplayController.OnDisplaysChang
}
/**
- * Called when the Task info changed. Creates and updates the restart button if there is an
- * activity in size compat, or removes the restart button if there is no size compat activity.
+ * Called when the Task info changed. Creates and updates the size compat UI if there is an
+ * activity in size compat, or removes the UI if there is no size compat activity.
*
* @param displayId display the task and activity are in.
* @param taskId task the activity is in.
- * @param taskConfig task config to place the restart button with.
+ * @param taskConfig task config to place the size compat UI with.
* @param sizeCompatActivity the size compat activity in the task. Can be {@code null} if the
* top activity in this Task is not in size compat.
* @param taskListener listener to handle the Task Surface placement.
@@ -94,10 +94,10 @@ public class SizeCompatUIController implements DisplayController.OnDisplaysChang
// Null token means the current foreground activity is not in size compatibility mode.
removeLayout(taskId);
} else if (mActiveLayouts.contains(taskId)) {
- // Button already exists, update the button layout.
+ // UI already exists, update the UI layout.
updateLayout(taskId, taskConfig, sizeCompatActivity, taskListener);
} else {
- // Create a new restart button.
+ // Create a new size compat UI.
createLayout(displayId, taskId, taskConfig, sizeCompatActivity, taskListener);
}
}
@@ -106,7 +106,7 @@ public class SizeCompatUIController implements DisplayController.OnDisplaysChang
public void onDisplayRemoved(int displayId) {
mDisplayContextCache.remove(displayId);
- // Remove all buttons on the removed display.
+ // Remove all size compat UIs on the removed display.
final List<Integer> toRemoveTaskIds = new ArrayList<>();
forAllLayoutsOnDisplay(displayId, layout -> toRemoveTaskIds.add(layout.getTaskId()));
for (int i = toRemoveTaskIds.size() - 1; i >= 0; i--) {
@@ -128,7 +128,7 @@ public class SizeCompatUIController implements DisplayController.OnDisplaysChang
mDisplaysWithIme.remove(displayId);
}
- // Hide the button when input method is showing.
+ // Hide the size compat UIs when input method is showing.
forAllLayoutsOnDisplay(displayId, layout -> layout.updateImeVisibility(isShowing));
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java
index 5924b53f822c..32f3648be19a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java
@@ -30,7 +30,6 @@ import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.Binder;
import android.os.IBinder;
-import android.view.Gravity;
import android.view.SurfaceControl;
import android.view.View;
import android.view.WindowManager;
@@ -43,7 +42,7 @@ import com.android.wm.shell.common.SyncTransactionQueue;
/**
* Records and handles layout of size compat UI on a task with size compat activity. Helps to
- * calculate proper bounds when configuration or button position changes.
+ * calculate proper bounds when configuration or UI position changes.
*/
class SizeCompatUILayout {
private static final String TAG = "SizeCompatUILayout";
@@ -56,12 +55,18 @@ class SizeCompatUILayout {
private IBinder mActivityToken;
private ShellTaskOrganizer.TaskListener mTaskListener;
private DisplayLayout mDisplayLayout;
- @VisibleForTesting
- final SizeCompatUIWindowManager mWindowManager;
@VisibleForTesting
+ final SizeCompatUIWindowManager mButtonWindowManager;
+ @VisibleForTesting
+ @Nullable
+ SizeCompatUIWindowManager mHintWindowManager;
+ @VisibleForTesting
@Nullable
SizeCompatRestartButton mButton;
+ @VisibleForTesting
+ @Nullable
+ SizeCompatHintPopup mHint;
final int mButtonSize;
final int mPopupOffsetX;
final int mPopupOffsetY;
@@ -79,7 +84,7 @@ class SizeCompatUILayout {
mTaskListener = taskListener;
mDisplayLayout = displayLayout;
mShouldShowHint = !hasShownHint;
- mWindowManager = new SizeCompatUIWindowManager(mContext, taskConfig, this);
+ mButtonWindowManager = new SizeCompatUIWindowManager(mContext, taskConfig, this);
mButtonSize =
mContext.getResources().getDimensionPixelSize(R.dimen.size_compat_button_size);
@@ -87,21 +92,52 @@ class SizeCompatUILayout {
mPopupOffsetY = mButtonSize;
}
- /** Creates the button window. */
+ /** Creates the activity restart button window. */
void createSizeCompatButton(boolean isImeShowing) {
if (isImeShowing || mButton != null) {
// When ime is showing, wait until ime is dismiss to create UI.
return;
}
- mButton = mWindowManager.createSizeCompatUI();
- updateSurfacePosition();
+ mButton = mButtonWindowManager.createSizeCompatButton();
+ updateButtonSurfacePosition();
+
+ if (mShouldShowHint) {
+ // Only show by default for the first time.
+ mShouldShowHint = false;
+ createSizeCompatHint();
+ }
+ }
+
+ /** Creates the restart button hint window. */
+ private void createSizeCompatHint() {
+ if (mHint != null) {
+ // Hint already shown.
+ return;
+ }
+ mHintWindowManager = createHintWindowManager();
+ mHint = mHintWindowManager.createSizeCompatHint();
+ updateHintSurfacePosition();
}
- /** Releases the button window. */
+ @VisibleForTesting
+ SizeCompatUIWindowManager createHintWindowManager() {
+ return new SizeCompatUIWindowManager(mContext, mTaskConfig, this);
+ }
+
+ /** Dismisses the hint window. */
+ void dismissHint() {
+ mHint = null;
+ if (mHintWindowManager != null) {
+ mHintWindowManager.release();
+ mHintWindowManager = null;
+ }
+ }
+
+ /** Releases the UI windows. */
void release() {
- mButton.remove();
+ dismissHint();
mButton = null;
- mWindowManager.release();
+ mButtonWindowManager.release();
}
/** Called when size compat info changed. */
@@ -115,7 +151,10 @@ class SizeCompatUILayout {
// Update configuration.
mContext = mContext.createConfigurationContext(taskConfig);
- mWindowManager.setConfiguration(taskConfig);
+ mButtonWindowManager.setConfiguration(taskConfig);
+ if (mHintWindowManager != null) {
+ mHintWindowManager.setConfiguration(taskConfig);
+ }
if (mButton == null || prevTaskListener != taskListener) {
// TaskListener changed, recreate the button for new surface parent.
@@ -126,14 +165,19 @@ class SizeCompatUILayout {
if (!taskConfig.windowConfiguration.getBounds()
.equals(prevTaskConfig.windowConfiguration.getBounds())) {
- // Reposition the button surface.
- updateSurfacePosition();
+ // Reposition the UI surfaces.
+ updateButtonSurfacePosition();
+ updateHintSurfacePosition();
}
if (taskConfig.getLayoutDirection() != prevTaskConfig.getLayoutDirection()) {
// Update layout for RTL.
mButton.setLayoutDirection(taskConfig.getLayoutDirection());
- updateSurfacePosition();
+ updateButtonSurfacePosition();
+ if (mHint != null) {
+ mHint.setLayoutDirection(taskConfig.getLayoutDirection());
+ updateHintSurfacePosition();
+ }
}
}
@@ -149,8 +193,9 @@ class SizeCompatUILayout {
displayLayout.getStableBounds(curStableBounds);
mDisplayLayout = displayLayout;
if (!prevStableBounds.equals(curStableBounds)) {
- // Stable bounds changed, update button surface position.
- updateSurfacePosition();
+ // Stable bounds changed, update UI surface positions.
+ updateButtonSurfacePosition();
+ updateHintSurfacePosition();
}
}
@@ -162,27 +207,46 @@ class SizeCompatUILayout {
return;
}
+ // Hide size compat UIs when IME is showing.
final int newVisibility = isImeShowing ? View.GONE : View.VISIBLE;
if (mButton.getVisibility() != newVisibility) {
mButton.setVisibility(newVisibility);
}
+ if (mHint != null && mHint.getVisibility() != newVisibility) {
+ mHint.setVisibility(newVisibility);
+ }
}
/** Gets the layout params for restart button. */
- WindowManager.LayoutParams getWindowLayoutParams() {
+ WindowManager.LayoutParams getButtonWindowLayoutParams() {
final WindowManager.LayoutParams winParams = new WindowManager.LayoutParams(
+ // Cannot be wrap_content as this determines the actual window size
mButtonSize, mButtonSize,
TYPE_APPLICATION_OVERLAY,
FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL,
PixelFormat.TRANSLUCENT);
- winParams.gravity = getGravity(getLayoutDirection());
winParams.token = new Binder();
- winParams.setTitle(SizeCompatRestartButton.class.getSimpleName() + mContext.getDisplayId());
+ winParams.setTitle(SizeCompatRestartButton.class.getSimpleName() + getTaskId());
winParams.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
return winParams;
}
- /** Called when it is ready to be placed button surface button. */
+ /** Gets the layout params for hint popup. */
+ WindowManager.LayoutParams getHintWindowLayoutParams(SizeCompatHintPopup hint) {
+ final WindowManager.LayoutParams winParams = new WindowManager.LayoutParams(
+ // Cannot be wrap_content as this determines the actual window size
+ hint.getMeasuredWidth(), hint.getMeasuredHeight(),
+ TYPE_APPLICATION_OVERLAY,
+ FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL,
+ PixelFormat.TRANSLUCENT);
+ winParams.token = new Binder();
+ winParams.setTitle(SizeCompatHintPopup.class.getSimpleName() + getTaskId());
+ winParams.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
+ winParams.windowAnimations = android.R.style.Animation_InputMethod;
+ return winParams;
+ }
+
+ /** Called when it is ready to be placed size compat UI surface. */
void attachToParentSurface(SurfaceControl.Builder b) {
mTaskListener.attachChildSurfaceToTask(mTaskId, b);
}
@@ -192,13 +256,17 @@ class SizeCompatUILayout {
ActivityClient.getInstance().restartActivityProcessIfVisible(mActivityToken);
}
+ /** Called when the restart button is long clicked. */
+ void onRestartButtonLongClicked() {
+ createSizeCompatHint();
+ }
+
@VisibleForTesting
- void updateSurfacePosition() {
- if (mButton == null || mWindowManager.getSurfaceControl() == null) {
+ void updateButtonSurfacePosition() {
+ if (mButton == null || mButtonWindowManager.getSurfaceControl() == null) {
return;
}
- // The hint popup won't be at the correct position.
- mButton.dismissHint();
+ final SurfaceControl leash = mButtonWindowManager.getSurfaceControl();
// Use stable bounds to prevent the button from overlapping with system bars.
final Rect taskBounds = mTaskConfig.windowConfiguration.getBounds();
@@ -212,8 +280,30 @@ class SizeCompatUILayout {
: stableBounds.right - taskBounds.left - mButtonSize;
final int positionY = stableBounds.bottom - taskBounds.top - mButtonSize;
- mSyncQueue.runInSync(t ->
- t.setPosition(mWindowManager.getSurfaceControl(), positionX, positionY));
+ mSyncQueue.runInSync(t -> t.setPosition(leash, positionX, positionY));
+ }
+
+ void updateHintSurfacePosition() {
+ if (mHint == null || mHintWindowManager == null
+ || mHintWindowManager.getSurfaceControl() == null) {
+ return;
+ }
+ final SurfaceControl leash = mHintWindowManager.getSurfaceControl();
+
+ // Use stable bounds to prevent the hint from overlapping with system bars.
+ final Rect taskBounds = mTaskConfig.windowConfiguration.getBounds();
+ final Rect stableBounds = new Rect();
+ mDisplayLayout.getStableBounds(stableBounds);
+ stableBounds.intersect(taskBounds);
+
+ // Position of the hint in the container coordinate.
+ final int positionX = getLayoutDirection() == View.LAYOUT_DIRECTION_RTL
+ ? stableBounds.left - taskBounds.left + mPopupOffsetX
+ : stableBounds.right - taskBounds.left - mPopupOffsetX - mHint.getMeasuredWidth();
+ final int positionY =
+ stableBounds.bottom - taskBounds.top - mPopupOffsetY - mHint.getMeasuredHeight();
+
+ mSyncQueue.runInSync(t -> t.setPosition(leash, positionX, positionY));
}
int getDisplayId() {
@@ -227,9 +317,4 @@ class SizeCompatUILayout {
private int getLayoutDirection() {
return mContext.getResources().getConfiguration().getLayoutDirection();
}
-
- static int getGravity(int layoutDirection) {
- return Gravity.BOTTOM
- | (layoutDirection == View.LAYOUT_DIRECTION_RTL ? Gravity.START : Gravity.END);
- }
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIWindowManager.java
index a7ad982a4736..f634c4586e39 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIWindowManager.java
@@ -24,12 +24,14 @@ import android.view.LayoutInflater;
import android.view.SurfaceControl;
import android.view.SurfaceControlViewHost;
import android.view.SurfaceSession;
+import android.view.View;
import android.view.WindowlessWindowManager;
import com.android.wm.shell.R;
/**
- * Holds view hierarchy of a root surface and helps to inflate {@link SizeCompatRestartButton}.
+ * Holds view hierarchy of a root surface and helps to inflate {@link SizeCompatRestartButton} or
+ * {@link SizeCompatHintPopup}.
*/
class SizeCompatUIWindowManager extends WindowlessWindowManager {
@@ -67,18 +69,39 @@ class SizeCompatUIWindowManager extends WindowlessWindowManager {
}
/** Inflates {@link SizeCompatRestartButton} on to the root surface. */
- SizeCompatRestartButton createSizeCompatUI() {
- if (mViewHost == null) {
- mViewHost = new SurfaceControlViewHost(mContext, mContext.getDisplay(), this);
+ SizeCompatRestartButton createSizeCompatButton() {
+ if (mViewHost != null) {
+ throw new IllegalStateException(
+ "A UI has already been created with this window manager.");
}
+ mViewHost = new SurfaceControlViewHost(mContext, mContext.getDisplay(), this);
+
final SizeCompatRestartButton button = (SizeCompatRestartButton)
LayoutInflater.from(mContext).inflate(R.layout.size_compat_ui, null);
button.inject(mLayout);
- mViewHost.setView(button, mLayout.getWindowLayoutParams());
+ mViewHost.setView(button, mLayout.getButtonWindowLayoutParams());
return button;
}
+ /** Inflates {@link SizeCompatHintPopup} on to the root surface. */
+ SizeCompatHintPopup createSizeCompatHint() {
+ if (mViewHost != null) {
+ throw new IllegalStateException(
+ "A UI has already been created with this window manager.");
+ }
+
+ mViewHost = new SurfaceControlViewHost(mContext, mContext.getDisplay(), this);
+
+ final SizeCompatHintPopup hint = (SizeCompatHintPopup)
+ LayoutInflater.from(mContext).inflate(R.layout.size_compat_mode_hint, null);
+ // Measure how big the hint is.
+ hint.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
+ hint.inject(mLayout);
+ mViewHost.setView(hint, mLayout.getHintWindowLayoutParams(hint));
+ return hint;
+ }
+
/** Releases the surface control and tears down the view hierarchy. */
void release() {
if (mViewHost != null) {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt
index 9f2087fc91d6..901b7a393291 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/helpers/SplitScreenHelper.kt
@@ -18,7 +18,6 @@ package com.android.wm.shell.flicker.helpers
import android.app.Instrumentation
import android.content.ComponentName
-import android.os.SystemClock
import com.android.wm.shell.flicker.testapp.Components
class SplitScreenHelper(
@@ -27,17 +26,6 @@ class SplitScreenHelper(
componentsInfo: ComponentName
) : BaseAppHelper(instrumentation, activityLabel, componentsInfo) {
- /**
- * Reopens the first device window from the list of recent apps (overview)
- */
- fun reopenAppFromOverview() {
- val x = uiDevice.displayWidth / 2
- val y = uiDevice.displayHeight / 2
- uiDevice.click(x, y)
- // Wait for animation to complete.
- SystemClock.sleep(TIMEOUT_MS)
- }
-
companion object {
const val TEST_REPETITIONS = 1
const val TIMEOUT_MS = 3_000L
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenDockActivity.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenDockActivity.kt
index 2c29220bf20e..0d9edd29d259 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenDockActivity.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenDockActivity.kt
@@ -62,7 +62,7 @@ class EnterSplitScreenDockActivity(
}
repeat { SplitScreenHelper.TEST_REPETITIONS }
transitions {
- device.launchSplitScreen()
+ device.launchSplitScreen(wmHelper)
}
assertions {
layersTrace {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenLaunchToSide.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenLaunchToSide.kt
index 903971ea084f..a513ee1e91f1 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenLaunchToSide.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenLaunchToSide.kt
@@ -27,6 +27,7 @@ import com.android.server.wm.flicker.appWindowBecomesVisible
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.buildTestTag
import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.reopenAppFromOverview
import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
import com.android.server.wm.flicker.startRotation
import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
@@ -62,8 +63,8 @@ class EnterSplitScreenLaunchToSide(
}
repeat { SplitScreenHelper.TEST_REPETITIONS }
transitions {
- device.launchSplitScreen()
- secondaryApp.reopenAppFromOverview()
+ device.launchSplitScreen(wmHelper)
+ device.reopenAppFromOverview(wmHelper)
}
assertions {
layersTrace {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenNonResizableNotDock.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenNonResizableNotDock.kt
index e3619235ee77..78ed773f2409 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenNonResizableNotDock.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/EnterSplitScreenNonResizableNotDock.kt
@@ -60,10 +60,15 @@ class EnterSplitScreenNonResizableNotDock(
buildTestTag("testLegacySplitScreenNonResizeableActivityNotDock", configuration)
}
repeat { SplitScreenHelper.TEST_REPETITIONS }
+ teardown {
+ eachRun {
+ nonResizeableApp.exit(wmHelper)
+ }
+ }
transitions {
nonResizeableApp.launchViaIntent(wmHelper)
- device.openQuickstep()
- if (device.canSplitScreen()) {
+ device.openQuickstep(wmHelper)
+ if (device.canSplitScreen(wmHelper)) {
Assert.fail("Non-resizeable app should not enter split screen")
}
}
@@ -93,7 +98,7 @@ class EnterSplitScreenNonResizableNotDock(
}
}
return FlickerTestRunnerFactory.getInstance().buildTest(
- instrumentation, defaultTransitionSetup, testSpec,
+ instrumentation, cleanSetup, testSpec,
repetitions = SplitScreenHelper.TEST_REPETITIONS,
supportedRotations = listOf(Surface.ROTATION_0 /* bugId = 178685668 */))
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottom.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottom.kt
index 493366553623..f4e5ba7877da 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottom.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitLegacySplitScreenFromBottom.kt
@@ -60,8 +60,18 @@ class ExitLegacySplitScreenFromBottom(
buildTestTag("testExitLegacySplitScreenFromBottom", configuration)
}
repeat { SplitScreenHelper.TEST_REPETITIONS }
+ setup {
+ eachRun {
+ splitScreenApp.launchViaIntent(wmHelper)
+ device.launchSplitScreen(wmHelper)
+ }
+ }
+ teardown {
+ eachRun {
+ splitScreenApp.exit(wmHelper)
+ }
+ }
transitions {
- device.launchSplitScreen()
device.exitSplitScreenFromBottom()
}
assertions {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitPrimarySplitScreenShowSecondaryFullscreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitPrimarySplitScreenShowSecondaryFullscreen.kt
index ff3a979717f2..8737fc5f8430 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitPrimarySplitScreenShowSecondaryFullscreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ExitPrimarySplitScreenShowSecondaryFullscreen.kt
@@ -26,6 +26,7 @@ import com.android.server.wm.flicker.appWindowBecomesInVisible
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.buildTestTag
import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.reopenAppFromOverview
import com.android.server.wm.flicker.layerBecomesInvisible
import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
import com.android.server.wm.flicker.statusBarWindowIsAlwaysVisible
@@ -58,11 +59,18 @@ class ExitPrimarySplitScreenShowSecondaryFullscreen(
buildTestTag("testExitPrimarySplitScreenShowSecondaryFullscreen", configuration)
}
repeat { SplitScreenHelper.TEST_REPETITIONS }
+ teardown {
+ eachRun {
+ secondaryApp.exit(wmHelper)
+ }
+ }
transitions {
- device.launchSplitScreen()
- secondaryApp.reopenAppFromOverview()
+ splitScreenApp.launchViaIntent(wmHelper)
+ secondaryApp.launchViaIntent(wmHelper)
+ device.launchSplitScreen(wmHelper)
+ device.reopenAppFromOverview(wmHelper)
// TODO(b/175687842) Can not find Split screen divider, use exit() instead
- splitScreenApp.exit()
+ splitScreenApp.exit(wmHelper)
}
assertions {
layersTrace {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncher.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncher.kt
index 03b6edf0ff2a..c0feaee73d9a 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncher.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenToLauncher.kt
@@ -80,13 +80,12 @@ class LegacySplitScreenToLauncher(
setup {
test {
device.wakeUpAndGoToHomeScreen()
- device.openQuickStepAndClearRecentAppsFromOverview()
+ device.openQuickStepAndClearRecentAppsFromOverview(wmHelper)
}
eachRun {
testApp.launchViaIntent(wmHelper)
this.setRotation(configuration.endRotation)
- device.launchSplitScreen()
- device.waitForIdle()
+ device.launchSplitScreen(wmHelper)
}
}
teardown {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenTransition.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenTransition.kt
index 328ff88cd41b..f9d2f49186a7 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenTransition.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/LegacySplitScreenTransition.kt
@@ -21,7 +21,10 @@ import android.os.Bundle
import android.support.test.launcherhelper.LauncherStrategyFactory
import android.view.Surface
import com.android.server.wm.flicker.dsl.FlickerBuilder
+import com.android.server.wm.flicker.helpers.exitSplitScreen
+import com.android.server.wm.flicker.helpers.isInSplitScreen
import com.android.server.wm.flicker.helpers.openQuickStepAndClearRecentAppsFromOverview
+import com.android.server.wm.flicker.helpers.openQuickstep
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.helpers.wakeUpAndGoToHomeScreen
import com.android.server.wm.flicker.startRotation
@@ -46,7 +49,7 @@ abstract class LegacySplitScreenTransition(
setup {
eachRun {
device.wakeUpAndGoToHomeScreen()
- device.openQuickStepAndClearRecentAppsFromOverview()
+ device.openQuickStepAndClearRecentAppsFromOverview(wmHelper)
secondaryApp.launchViaIntent(wmHelper)
splitScreenApp.launchViaIntent(wmHelper)
this.setRotation(configuration.startRotation)
@@ -54,8 +57,12 @@ abstract class LegacySplitScreenTransition(
}
teardown {
eachRun {
- splitScreenApp.exit()
- secondaryApp.exit()
+ // TODO(b/175687842) Workaround for exit legacy split screen
+ device.openQuickstep(wmHelper)
+ if (device.isInSplitScreen()) {
+ device.exitSplitScreen()
+ }
+ device.pressHome()
this.setRotation(Surface.ROTATION_0)
}
}
@@ -66,13 +73,18 @@ abstract class LegacySplitScreenTransition(
setup {
eachRun {
device.wakeUpAndGoToHomeScreen()
- device.openQuickStepAndClearRecentAppsFromOverview()
+ device.openQuickStepAndClearRecentAppsFromOverview(wmHelper)
this.setRotation(configuration.startRotation)
}
}
teardown {
eachRun {
- nonResizeableApp.exit()
+ // TODO(b/175687842) Workaround for exit legacy split screen
+ device.openQuickstep(wmHelper)
+ if (device.isInSplitScreen()) {
+ device.exitSplitScreen()
+ }
+ device.pressHome()
this.setRotation(Surface.ROTATION_0)
}
}
@@ -83,15 +95,19 @@ abstract class LegacySplitScreenTransition(
setup {
eachRun {
device.wakeUpAndGoToHomeScreen()
- device.openQuickStepAndClearRecentAppsFromOverview()
+ device.openQuickStepAndClearRecentAppsFromOverview(wmHelper)
secondaryApp.launchViaIntent(wmHelper)
splitScreenApp.launchViaIntent(wmHelper)
}
}
teardown {
eachRun {
- splitScreenApp.exit()
- secondaryApp.exit()
+ // TODO(b/175687842) Workaround for exit legacy split screen
+ device.openQuickstep(wmHelper)
+ if (device.isInSplitScreen()) {
+ device.exitSplitScreen()
+ }
+ device.pressHome()
this.setRotation(Surface.ROTATION_0)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableDismissInLegacySplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableDismissInLegacySplitScreen.kt
index f2a7cda3b42d..a8de8db719a8 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableDismissInLegacySplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableDismissInLegacySplitScreen.kt
@@ -29,6 +29,7 @@ import com.android.server.wm.flicker.appWindowBecomesVisible
import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.helpers.buildTestTag
import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.reopenAppFromOverview
import com.android.server.wm.flicker.layerBecomesInvisible
import com.android.server.wm.flicker.layerBecomesVisible
import com.android.server.wm.flicker.visibleLayersShownMoreThanOneConsecutiveEntry
@@ -60,12 +61,15 @@ class NonResizableDismissInLegacySplitScreen(
buildTestTag("testNonResizableDismissInLegacySplitScreen", configuration)
}
repeat { SplitScreenHelper.TEST_REPETITIONS }
+ setup {
+ eachRun {
+ nonResizeableApp.launchViaIntent(wmHelper)
+ splitScreenApp.launchViaIntent(wmHelper)
+ device.launchSplitScreen(wmHelper)
+ }
+ }
transitions {
- nonResizeableApp.launchViaIntent(wmHelper)
- splitScreenApp.launchViaIntent(wmHelper)
- device.launchSplitScreen()
- nonResizeableApp.reopenAppFromOverview()
- wmHelper.waitForAppTransitionIdle()
+ device.reopenAppFromOverview(wmHelper)
}
assertions {
layersTrace {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableLaunchInLegacySplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableLaunchInLegacySplitScreen.kt
index 421ecffc97d8..c82c80237912 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableLaunchInLegacySplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/NonResizableLaunchInLegacySplitScreen.kt
@@ -60,9 +60,13 @@ class NonResizableLaunchInLegacySplitScreen(
buildTestTag("testNonResizableLaunchInLegacySplitScreen", configuration)
}
repeat { SplitScreenHelper.TEST_REPETITIONS }
+ setup {
+ eachRun {
+ splitScreenApp.launchViaIntent(wmHelper)
+ device.launchSplitScreen(wmHelper)
+ }
+ }
transitions {
- splitScreenApp.launchViaIntent(wmHelper)
- device.launchSplitScreen()
nonResizeableApp.launchViaIntent(wmHelper)
wmHelper.waitForAppTransitionIdle()
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreen.kt
index 7edef9314941..9199c39535ac 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/OpenAppToLegacySplitScreen.kt
@@ -64,7 +64,7 @@ class OpenAppToLegacySplitScreen(
}
repeat { SplitScreenHelper.TEST_REPETITIONS }
transitions {
- device.launchSplitScreen()
+ device.launchSplitScreen(wmHelper)
wmHelper.waitForAppTransitionIdle()
}
assertions {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt
index 54a37d71868d..c305bd856f58 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/ResizeLegacySplitScreen.kt
@@ -100,7 +100,7 @@ class ResizeLegacySplitScreen(
device.pressHome()
testAppTop.launchViaIntent(wmHelper)
device.waitForIdle()
- device.launchSplitScreen()
+ device.launchSplitScreen(wmHelper)
val snapshot =
device.findObject(By.res(device.launcherPackageName, "snapshot"))
snapshot.click()
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt
index 214269e13203..40bdaf3df5e8 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppAndEnterSplitScreen.kt
@@ -63,7 +63,7 @@ class RotateOneLaunchedAppAndEnterSplitScreen(
}
repeat { SplitScreenHelper.TEST_REPETITIONS }
transitions {
- device.launchSplitScreen()
+ device.launchSplitScreen(wmHelper)
this.setRotation(configuration.startRotation)
}
assertions {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt
index 4290c923b38d..ae2c2d8f1bf2 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateOneLaunchedAppInSplitScreenMode.kt
@@ -64,7 +64,7 @@ class RotateOneLaunchedAppInSplitScreenMode(
repeat { SplitScreenHelper.TEST_REPETITIONS }
transitions {
this.setRotation(configuration.startRotation)
- device.launchSplitScreen()
+ device.launchSplitScreen(wmHelper)
}
assertions {
layersTrace {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt
index 4095b9a2e61e..aa9ac8f9782f 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppAndEnterSplitScreen.kt
@@ -28,6 +28,7 @@ import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.endRotation
import com.android.server.wm.flicker.helpers.buildTestTag
import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.reopenAppFromOverview
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
@@ -65,8 +66,8 @@ class RotateTwoLaunchedAppAndEnterSplitScreen(
repeat { SplitScreenHelper.TEST_REPETITIONS }
transitions {
this.setRotation(configuration.startRotation)
- device.launchSplitScreen()
- secondaryApp.reopenAppFromOverview()
+ device.launchSplitScreen(wmHelper)
+ device.reopenAppFromOverview(wmHelper)
}
assertions {
layersTrace {
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt
index aebf6067615e..0e864dbbb75d 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/legacysplitscreen/RotateTwoLaunchedAppInSplitScreenMode.kt
@@ -28,6 +28,7 @@ import com.android.server.wm.flicker.dsl.FlickerBuilder
import com.android.server.wm.flicker.endRotation
import com.android.server.wm.flicker.helpers.buildTestTag
import com.android.server.wm.flicker.helpers.launchSplitScreen
+import com.android.server.wm.flicker.helpers.reopenAppFromOverview
import com.android.server.wm.flicker.helpers.setRotation
import com.android.server.wm.flicker.navBarLayerRotatesAndScales
import com.android.server.wm.flicker.navBarWindowIsAlwaysVisible
@@ -65,8 +66,8 @@ class RotateTwoLaunchedAppInSplitScreenMode(
repeat { SplitScreenHelper.TEST_REPETITIONS }
setup {
eachRun {
- device.launchSplitScreen()
- splitScreenApp.reopenAppFromOverview()
+ device.launchSplitScreen(wmHelper)
+ device.reopenAppFromOverview(wmHelper)
this.setRotation(configuration.startRotation)
}
}
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
index f10bd7f1e45a..5a1e5a1fe7c5 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipLegacySplitScreenTest.kt
@@ -71,7 +71,7 @@ class PipLegacySplitScreenTest(
}
transitions {
testApp.launchViaIntent()
- device.launchSplitScreen()
+ device.launchSplitScreen(wmHelper)
imeApp.launchViaIntent()
waitForAnimationComplete()
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatHintPopupTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatHintPopupTest.java
new file mode 100644
index 000000000000..9845d4650d20
--- /dev/null
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatHintPopupTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.wm.shell.sizecompatui;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.verify;
+
+import android.content.res.Configuration;
+import android.os.IBinder;
+import android.testing.AndroidTestingRunner;
+import android.view.LayoutInflater;
+import android.widget.Button;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.wm.shell.R;
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.ShellTestCase;
+import com.android.wm.shell.common.DisplayLayout;
+import com.android.wm.shell.common.SyncTransactionQueue;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+/**
+ * Tests for {@link SizeCompatHintPopup}.
+ *
+ * Build/Install/Run:
+ * atest WMShellUnitTests:SizeCompatHintPopupTest
+ */
+@RunWith(AndroidTestingRunner.class)
+@SmallTest
+public class SizeCompatHintPopupTest extends ShellTestCase {
+
+ @Mock private SyncTransactionQueue mSyncTransactionQueue;
+ @Mock private IBinder mActivityToken;
+ @Mock private ShellTaskOrganizer.TaskListener mTaskListener;
+ @Mock private DisplayLayout mDisplayLayout;
+
+ private SizeCompatUILayout mLayout;
+ private SizeCompatHintPopup mHint;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ final int taskId = 1;
+ mLayout = new SizeCompatUILayout(mSyncTransactionQueue, mContext, new Configuration(),
+ taskId, mActivityToken, mTaskListener, mDisplayLayout, false /* hasShownHint*/);
+ mHint = (SizeCompatHintPopup)
+ LayoutInflater.from(mContext).inflate(R.layout.size_compat_mode_hint, null);
+ mHint.inject(mLayout);
+
+ spyOn(mLayout);
+ }
+
+ @Test
+ public void testOnClick() {
+ doNothing().when(mLayout).dismissHint();
+
+ final Button button = mHint.findViewById(R.id.got_it);
+ button.performClick();
+
+ verify(mLayout).dismissHint();
+ }
+}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatRestartButtonTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatRestartButtonTest.java
index d9086a6ccdc1..5a43925a5677 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatRestartButtonTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatRestartButtonTest.java
@@ -19,13 +19,13 @@ package com.android.wm.shell.sizecompatui;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import android.content.res.Configuration;
import android.os.IBinder;
import android.testing.AndroidTestingRunner;
import android.view.LayoutInflater;
+import android.widget.ImageButton;
import androidx.test.filters.SmallTest;
@@ -71,45 +71,25 @@ public class SizeCompatRestartButtonTest extends ShellTestCase {
mButton.inject(mLayout);
spyOn(mLayout);
- spyOn(mButton);
- doNothing().when(mButton).showHint();
}
@Test
public void testOnClick() {
doNothing().when(mLayout).onRestartButtonClicked();
- mButton.onClick(mButton);
+ final ImageButton button = mButton.findViewById(R.id.size_compat_restart_button);
+ button.performClick();
verify(mLayout).onRestartButtonClicked();
}
@Test
public void testOnLongClick() {
- verify(mButton, never()).showHint();
+ doNothing().when(mLayout).onRestartButtonLongClicked();
- mButton.onLongClick(mButton);
+ final ImageButton button = mButton.findViewById(R.id.size_compat_restart_button);
+ button.performLongClick();
- verify(mButton).showHint();
- }
-
- @Test
- public void testOnAttachedToWindow_showHint() {
- mLayout.mShouldShowHint = false;
- mButton.onAttachedToWindow();
-
- verify(mButton, never()).showHint();
-
- mLayout.mShouldShowHint = true;
- mButton.onAttachedToWindow();
-
- verify(mButton).showHint();
- }
-
- @Test
- public void testRemove() {
- mButton.remove();
-
- verify(mButton).dismissHint();
+ verify(mLayout).onRestartButtonLongClicked();
}
}
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUILayoutTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUILayoutTest.java
index 236db44bdce0..f33cfe86224f 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUILayoutTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUILayoutTest.java
@@ -18,6 +18,7 @@ package com.android.wm.shell.sizecompatui;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.mockito.ArgumentMatchers.any;
@@ -27,6 +28,7 @@ import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import android.app.ActivityClient;
@@ -68,6 +70,7 @@ public class SizeCompatUILayoutTest extends ShellTestCase {
@Mock private ShellTaskOrganizer.TaskListener mTaskListener;
@Mock private DisplayLayout mDisplayLayout;
@Mock private SizeCompatRestartButton mButton;
+ @Mock private SizeCompatHintPopup mHint;
private Configuration mTaskConfig;
private SizeCompatUILayout mLayout;
@@ -81,8 +84,13 @@ public class SizeCompatUILayoutTest extends ShellTestCase {
TASK_ID, mActivityToken, mTaskListener, mDisplayLayout, false /* hasShownHint*/);
spyOn(mLayout);
- spyOn(mLayout.mWindowManager);
- doReturn(mButton).when(mLayout.mWindowManager).createSizeCompatUI();
+ spyOn(mLayout.mButtonWindowManager);
+ doReturn(mButton).when(mLayout.mButtonWindowManager).createSizeCompatButton();
+
+ final SizeCompatUIWindowManager hintWindowManager = mLayout.createHintWindowManager();
+ spyOn(hintWindowManager);
+ doReturn(mHint).when(hintWindowManager).createSizeCompatHint();
+ doReturn(hintWindowManager).when(mLayout).createHintWindowManager();
}
@Test
@@ -90,24 +98,45 @@ public class SizeCompatUILayoutTest extends ShellTestCase {
// Not create button if IME is showing.
mLayout.createSizeCompatButton(true /* isImeShowing */);
- verify(mLayout.mWindowManager, never()).createSizeCompatUI();
+ verify(mLayout.mButtonWindowManager, never()).createSizeCompatButton();
assertNull(mLayout.mButton);
+ assertNull(mLayout.mHintWindowManager);
+ assertNull(mLayout.mHint);
+ // Not create hint popup.
+ mLayout.mShouldShowHint = false;
mLayout.createSizeCompatButton(false /* isImeShowing */);
- verify(mLayout.mWindowManager).createSizeCompatUI();
+ verify(mLayout.mButtonWindowManager).createSizeCompatButton();
assertNotNull(mLayout.mButton);
+ assertNull(mLayout.mHintWindowManager);
+ assertNull(mLayout.mHint);
+
+ // Create hint popup.
+ mLayout.release();
+ mLayout.mShouldShowHint = true;
+ mLayout.createSizeCompatButton(false /* isImeShowing */);
+
+ verify(mLayout.mButtonWindowManager, times(2)).createSizeCompatButton();
+ assertNotNull(mLayout.mButton);
+ assertNotNull(mLayout.mHintWindowManager);
+ verify(mLayout.mHintWindowManager).createSizeCompatHint();
+ assertNotNull(mLayout.mHint);
+ assertFalse(mLayout.mShouldShowHint);
}
@Test
public void testRelease() {
mLayout.createSizeCompatButton(false /* isImeShowing */);
+ final SizeCompatUIWindowManager hintWindowManager = mLayout.mHintWindowManager;
mLayout.release();
assertNull(mLayout.mButton);
- verify(mButton).remove();
- verify(mLayout.mWindowManager).release();
+ assertNull(mLayout.mHint);
+ verify(hintWindowManager).release();
+ assertNull(mLayout.mHintWindowManager);
+ verify(mLayout.mButtonWindowManager).release();
}
@Test
@@ -119,7 +148,7 @@ public class SizeCompatUILayoutTest extends ShellTestCase {
mLayout.updateSizeCompatInfo(mTaskConfig, mActivityToken, mTaskListener,
false /* isImeShowing */);
- verify(mLayout, never()).updateSurfacePosition();
+ verify(mLayout, never()).updateButtonSurfacePosition();
verify(mLayout, never()).release();
verify(mLayout, never()).createSizeCompatButton(anyBoolean());
@@ -140,7 +169,8 @@ public class SizeCompatUILayoutTest extends ShellTestCase {
mLayout.updateSizeCompatInfo(newTaskConfiguration, mActivityToken, newTaskListener,
false /* isImeShowing */);
- verify(mLayout).updateSurfacePosition();
+ verify(mLayout).updateButtonSurfacePosition();
+ verify(mLayout).updateHintSurfacePosition();
}
@Test
@@ -152,14 +182,16 @@ public class SizeCompatUILayoutTest extends ShellTestCase {
mContext.getResources(), false, false);
mLayout.updateDisplayLayout(displayLayout1);
- verify(mLayout).updateSurfacePosition();
+ verify(mLayout).updateButtonSurfacePosition();
+ verify(mLayout).updateHintSurfacePosition();
// No update if the display bounds is the same.
clearInvocations(mLayout);
final DisplayLayout displayLayout2 = new DisplayLayout(displayInfo,
mContext.getResources(), false, false);
mLayout.updateDisplayLayout(displayLayout2);
- verify(mLayout, never()).updateSurfacePosition();
+ verify(mLayout, never()).updateButtonSurfacePosition();
+ verify(mLayout, never()).updateHintSurfacePosition();
}
@Test
@@ -203,4 +235,29 @@ public class SizeCompatUILayoutTest extends ShellTestCase {
verify(ActivityClient.getInstance()).restartActivityProcessIfVisible(mActivityToken);
}
+
+ @Test
+ public void testOnRestartButtonLongClicked_showHint() {
+ mLayout.dismissHint();
+
+ assertNull(mLayout.mHint);
+
+ mLayout.onRestartButtonLongClicked();
+
+ assertNotNull(mLayout.mHint);
+ }
+
+ @Test
+ public void testDismissHint() {
+ mLayout.onRestartButtonLongClicked();
+ final SizeCompatUIWindowManager hintWindowManager = mLayout.mHintWindowManager;
+ assertNotNull(mLayout.mHint);
+ assertNotNull(hintWindowManager);
+
+ mLayout.dismissHint();
+
+ assertNull(mLayout.mHint);
+ assertNull(mLayout.mHintWindowManager);
+ verify(hintWindowManager).release();
+ }
}
diff --git a/libs/hwui/DamageAccumulator.cpp b/libs/hwui/DamageAccumulator.cpp
index b39f4f20dc0d..0bf948006ea0 100644
--- a/libs/hwui/DamageAccumulator.cpp
+++ b/libs/hwui/DamageAccumulator.cpp
@@ -249,5 +249,20 @@ void DamageAccumulator::finish(SkRect* totalDirty) {
mHead->pendingDirty.setEmpty();
}
+const StretchEffect* DamageAccumulator::findNearestStretchEffect() const {
+ DirtyStack* frame = mHead;
+ while (frame->prev != frame) {
+ frame = frame->prev;
+ if (frame->type == TransformRenderNode) {
+ const auto& effect =
+ frame->renderNode->properties().layerProperties().getStretchEffect();
+ if (!effect.isEmpty()) {
+ return &effect;
+ }
+ }
+ }
+ return nullptr;
+}
+
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/DamageAccumulator.h b/libs/hwui/DamageAccumulator.h
index 2faa9d012d66..89ee0e34055b 100644
--- a/libs/hwui/DamageAccumulator.h
+++ b/libs/hwui/DamageAccumulator.h
@@ -35,6 +35,7 @@ namespace uirenderer {
struct DirtyStack;
class RenderNode;
class Matrix4;
+class StretchEffect;
class DamageAccumulator {
PREVENT_COPY_AND_ASSIGN(DamageAccumulator);
@@ -62,6 +63,8 @@ public:
void finish(SkRect* totalDirty);
+ const StretchEffect* findNearestStretchEffect() const;
+
private:
void pushCommon();
void applyMatrix4Transform(DirtyStack* frame);
diff --git a/libs/hwui/JankTracker.cpp b/libs/hwui/JankTracker.cpp
index 4a2e30dd38f2..2cd9b7b39174 100644
--- a/libs/hwui/JankTracker.cpp
+++ b/libs/hwui/JankTracker.cpp
@@ -236,7 +236,6 @@ void JankTracker::dumpFrames(int fd) {
}
void JankTracker::reset() {
- std::lock_guard lock(mDataMutex);
mFrames.clear();
mData->reset();
(*mGlobalData)->reset();
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 64b8b711f0a8..170f73120414 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -384,10 +384,11 @@ struct DrawImageLattice final : Op {
struct DrawTextBlob final : Op {
static const auto kType = Type::DrawTextBlob;
DrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint)
- : blob(sk_ref_sp(blob)), x(x), y(y), paint(paint) {}
+ : blob(sk_ref_sp(blob)), x(x), y(y), paint(paint), drawTextBlobMode(gDrawTextBlobMode) {}
sk_sp<const SkTextBlob> blob;
SkScalar x, y;
SkPaint paint;
+ DrawTextBlobMode drawTextBlobMode;
void draw(SkCanvas* c, const SkMatrix&) const { c->drawTextBlob(blob.get(), x, y, paint); }
};
@@ -832,6 +833,24 @@ constexpr color_transform_fn colorTransformForOp() {
}
}
+template<>
+constexpr color_transform_fn colorTransformForOp<DrawTextBlob>() {
+ return [](const void *opRaw, ColorTransform transform) {
+ const DrawTextBlob *op = reinterpret_cast<const DrawTextBlob*>(opRaw);
+ switch (op->drawTextBlobMode) {
+ case DrawTextBlobMode::HctOutline:
+ const_cast<SkPaint&>(op->paint).setColor(SK_ColorBLACK);
+ break;
+ case DrawTextBlobMode::HctInner:
+ const_cast<SkPaint&>(op->paint).setColor(SK_ColorWHITE);
+ break;
+ default:
+ transformPaint(transform, const_cast<SkPaint*>(&(op->paint)));
+ break;
+ }
+ };
+}
+
#define X(T) colorTransformForOp<T>(),
static const color_transform_fn color_transform_fns[] = {
#include "DisplayListOps.in"
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 44f54eef458f..f5b2675c7fe6 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -226,6 +226,9 @@ void RenderNode::prepareTreeImpl(TreeObserver& observer, TreeInfo& info, bool fu
if (!mProperties.getAllowForceDark()) {
info.disableForceDark++;
}
+ if (!mProperties.layerProperties().getStretchEffect().isEmpty()) {
+ info.stretchEffectCount++;
+ }
uint32_t animatorDirtyMask = 0;
if (CC_LIKELY(info.runAnimations)) {
@@ -267,6 +270,9 @@ void RenderNode::prepareTreeImpl(TreeObserver& observer, TreeInfo& info, bool fu
if (!mProperties.getAllowForceDark()) {
info.disableForceDark--;
}
+ if (!mProperties.layerProperties().getStretchEffect().isEmpty()) {
+ info.stretchEffectCount--;
+ }
info.damageAccumulator->popTransform();
}
diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp
index 8fba9cf21df1..0589f136b666 100644
--- a/libs/hwui/RenderProperties.cpp
+++ b/libs/hwui/RenderProperties.cpp
@@ -70,6 +70,7 @@ LayerProperties& LayerProperties::operator=(const LayerProperties& other) {
setXferMode(other.xferMode());
setColorFilter(other.getColorFilter());
setImageFilter(other.getImageFilter());
+ mStretchEffect = other.mStretchEffect;
return *this;
}
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index f2481f83767d..cc9094c8afe9 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -98,6 +98,8 @@ public:
const SkISize screenSize;
+ int stretchEffectCount = 0;
+
struct Out {
bool hasFunctors = false;
// This is only updated if evaluateAnimations is true
diff --git a/libs/hwui/hwui/Canvas.cpp b/libs/hwui/hwui/Canvas.cpp
index 146bf283c58a..b046f45d9c57 100644
--- a/libs/hwui/hwui/Canvas.cpp
+++ b/libs/hwui/hwui/Canvas.cpp
@@ -110,16 +110,19 @@ public:
bool darken = channelSum < (128 * 3);
// outline
+ gDrawTextBlobMode = DrawTextBlobMode::HctOutline;
Paint outlinePaint(paint);
simplifyPaint(darken ? SK_ColorWHITE : SK_ColorBLACK, &outlinePaint);
outlinePaint.setStyle(SkPaint::kStrokeAndFill_Style);
canvas->drawGlyphs(glyphFunc, glyphCount, outlinePaint, x, y, totalAdvance);
// inner
+ gDrawTextBlobMode = DrawTextBlobMode::HctInner;
Paint innerPaint(paint);
simplifyPaint(darken ? SK_ColorBLACK : SK_ColorWHITE, &innerPaint);
innerPaint.setStyle(SkPaint::kFill_Style);
canvas->drawGlyphs(glyphFunc, glyphCount, innerPaint, x, y, totalAdvance);
+ gDrawTextBlobMode = DrawTextBlobMode::Normal;
} else {
// standard draw path
canvas->drawGlyphs(glyphFunc, glyphCount, paint, x, y, totalAdvance);
diff --git a/libs/hwui/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index fdfa2883c33f..d1bdb712e911 100644
--- a/libs/hwui/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -61,6 +61,14 @@ class Bitmap;
class Paint;
struct Typeface;
+enum class DrawTextBlobMode {
+ Normal,
+ HctOutline,
+ HctInner,
+};
+
+inline DrawTextBlobMode gDrawTextBlobMode = DrawTextBlobMode::Normal;
+
class ANDROID_API Canvas {
public:
virtual ~Canvas(){};
diff --git a/libs/hwui/jni/android_graphics_RenderNode.cpp b/libs/hwui/jni/android_graphics_RenderNode.cpp
index 80239687a7fb..5f60437b5cc7 100644
--- a/libs/hwui/jni/android_graphics_RenderNode.cpp
+++ b/libs/hwui/jni/android_graphics_RenderNode.cpp
@@ -25,6 +25,7 @@
#include <renderthread/CanvasContext.h>
#endif
#include <TreeInfo.h>
+#include <effects/StretchEffect.h>
#include <hwui/Paint.h>
#include <utils/TraceUtils.h>
@@ -549,6 +550,7 @@ static void android_view_RenderNode_endAllAnimators(JNIEnv* env, jobject clazz,
// ----------------------------------------------------------------------------
jmethodID gPositionListener_PositionChangedMethod;
+jmethodID gPositionListener_ApplyStretchMethod;
jmethodID gPositionListener_PositionLostMethod;
static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
@@ -571,6 +573,11 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
Matrix4 transform;
info.damageAccumulator->computeCurrentTransform(&transform);
const RenderProperties& props = node.properties();
+
+ if (info.stretchEffectCount) {
+ handleStretchEffect(info, transform);
+ }
+
uirenderer::Rect bounds(props.getWidth(), props.getHeight());
transform.mapRect(bounds);
@@ -613,7 +620,7 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
JNIEnv* env = jnienv();
jobject localref = env->NewLocalRef(mWeakRef);
if (CC_UNLIKELY(!localref)) {
- jnienv()->DeleteWeakGlobalRef(mWeakRef);
+ env->DeleteWeakGlobalRef(mWeakRef);
mWeakRef = nullptr;
return;
}
@@ -634,6 +641,32 @@ static void android_view_RenderNode_requestPositionUpdates(JNIEnv* env, jobject,
return env;
}
+ void handleStretchEffect(const TreeInfo& info, const Matrix4& transform) {
+ // Search up to find the nearest stretcheffect parent
+ const StretchEffect* effect = info.damageAccumulator->findNearestStretchEffect();
+ if (!effect) {
+ return;
+ }
+
+ uirenderer::Rect area = effect->stretchArea;
+ transform.mapRect(area);
+ JNIEnv* env = jnienv();
+
+ jobject localref = env->NewLocalRef(mWeakRef);
+ if (CC_UNLIKELY(!localref)) {
+ env->DeleteWeakGlobalRef(mWeakRef);
+ mWeakRef = nullptr;
+ return;
+ }
+#ifdef __ANDROID__ // Layoutlib does not support CanvasContext
+ env->CallVoidMethod(localref, gPositionListener_ApplyStretchMethod,
+ info.canvasContext.getFrameNumber(), area.left, area.top,
+ area.right, area.bottom, effect->stretchDirection.fX,
+ effect->stretchDirection.fY, effect->maxStretchAmount);
+#endif
+ env->DeleteLocalRef(localref);
+ }
+
void doUpdatePositionAsync(jlong frameNumber, jint left, jint top,
jint right, jint bottom) {
ATRACE_NAME("Update SurfaceView position");
@@ -775,6 +808,8 @@ int register_android_view_RenderNode(JNIEnv* env) {
jclass clazz = FindClassOrDie(env, "android/graphics/RenderNode$PositionUpdateListener");
gPositionListener_PositionChangedMethod = GetMethodIDOrDie(env, clazz,
"positionChanged", "(JIIII)V");
+ gPositionListener_ApplyStretchMethod =
+ GetMethodIDOrDie(env, clazz, "applyStretch", "(JFFFFFFF)V");
gPositionListener_PositionLostMethod = GetMethodIDOrDie(env, clazz,
"positionLost", "(J)V");
return RegisterMethodsOrDie(env, kClassPathName, gMethods, NELEM(gMethods));
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index b2884023a83d..04e3a1cb887e 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -194,25 +194,6 @@ SkiaCanvas::PaintCoW&& SkiaRecordingCanvas::filterBitmap(PaintCoW&& paint) {
return filterPaint(std::move(paint));
}
-static BlurDrawLooper* get_looper(const Paint* paint) {
- return paint ? paint->getLooper() : nullptr;
-}
-
-template <typename Proc>
-void applyLooper(BlurDrawLooper* looper, const SkPaint* paint, Proc proc) {
- if (looper) {
- SkPaint p;
- if (paint) {
- p = *paint;
- }
- looper->apply(p, [&](SkPoint offset, const SkPaint& modifiedPaint) {
- proc(offset.fX, offset.fY, &modifiedPaint);
- });
- } else {
- proc(0, 0, paint);
- }
-}
-
static SkFilterMode Paint_to_filter(const SkPaint* paint) {
return paint && paint->getFilterQuality() != kNone_SkFilterQuality ? SkFilterMode::kLinear
: SkFilterMode::kNearest;
@@ -226,8 +207,7 @@ static SkSamplingOptions Paint_to_sampling(const SkPaint* paint) {
void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float left, float top, const Paint* paint) {
sk_sp<SkImage> image = bitmap.makeImage();
- applyLooper(get_looper(paint), filterBitmap(paint), [&](SkScalar x, SkScalar y,
- const SkPaint* p) {
+ applyLooper(paint, [&](SkScalar x, SkScalar y, const SkPaint* p) {
mRecorder.drawImage(image, left + x, top + y, Paint_to_sampling(p), p, bitmap.palette());
});
@@ -245,8 +225,7 @@ void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, const SkMatrix& matrix, con
sk_sp<SkImage> image = bitmap.makeImage();
- applyLooper(get_looper(paint), filterBitmap(paint), [&](SkScalar x, SkScalar y,
- const SkPaint* p) {
+ applyLooper(paint, [&](SkScalar x, SkScalar y, const SkPaint* p) {
mRecorder.drawImage(image, x, y, Paint_to_sampling(p), p, bitmap.palette());
});
@@ -263,8 +242,7 @@ void SkiaRecordingCanvas::drawBitmap(Bitmap& bitmap, float srcLeft, float srcTop
sk_sp<SkImage> image = bitmap.makeImage();
- applyLooper(get_looper(paint), filterBitmap(paint), [&](SkScalar x, SkScalar y,
- const SkPaint* p) {
+ applyLooper(paint, [&](SkScalar x, SkScalar y, const SkPaint* p) {
mRecorder.drawImageRect(image, srcRect, dstRect.makeOffset(x, y), Paint_to_sampling(p),
p, SkCanvas::kFast_SrcRectConstraint, bitmap.palette());
});
@@ -303,8 +281,7 @@ void SkiaRecordingCanvas::drawNinePatch(Bitmap& bitmap, const Res_png_9patch& ch
// HWUI always draws 9-patches with linear filtering, regardless of the Paint.
const SkFilterMode filter = SkFilterMode::kLinear;
- applyLooper(get_looper(paint), filterBitmap(paint), [&](SkScalar x, SkScalar y,
- const SkPaint* p) {
+ applyLooper(paint, [&](SkScalar x, SkScalar y, const SkPaint* p) {
mRecorder.drawImageLattice(image, lattice, dst.makeOffset(x, y), filter, p,
bitmap.palette());
});
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
index 8d7a21a732dd..1e404b845084 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
@@ -87,6 +87,23 @@ private:
std::unique_ptr<SkiaDisplayList> mDisplayList;
StartReorderBarrierDrawable* mCurrentBarrier;
+ template <typename Proc>
+ void applyLooper(const Paint* paint, Proc proc) {
+ SkPaint skp;
+ BlurDrawLooper* looper = nullptr;
+ if (paint) {
+ skp = *filterBitmap(paint);
+ looper = paint->getLooper();
+ }
+ if (looper) {
+ looper->apply(skp, [&](SkPoint offset, const SkPaint& modifiedPaint) {
+ proc(offset.fX, offset.fY, &modifiedPaint);
+ });
+ } else {
+ proc(0, 0, &skp);
+ }
+ }
+
/**
* A new SkiaDisplayList is created or recycled if available.
*
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index b9568fcf8e66..423cc08189ca 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -230,7 +230,10 @@ void RenderProxy::dumpProfileInfo(int fd, int dumpFlags) {
}
void RenderProxy::resetProfileInfo() {
- mRenderThread.queue().runSync([=]() { mContext->resetFrameStats(); });
+ mRenderThread.queue().runSync([=]() {
+ std::lock_guard lock(mRenderThread.getJankDataMutex());
+ mContext->resetFrameStats();
+ });
}
uint32_t RenderProxy::frameTimePercentile(int percentile) {
diff --git a/libs/hwui/tests/common/TestContext.cpp b/libs/hwui/tests/common/TestContext.cpp
index 6a9a98d6743b..898c64bd4159 100644
--- a/libs/hwui/tests/common/TestContext.cpp
+++ b/libs/hwui/tests/common/TestContext.cpp
@@ -22,16 +22,16 @@ namespace android {
namespace uirenderer {
namespace test {
-const DisplayInfo& getDisplayInfo() {
- static DisplayInfo info = [] {
- DisplayInfo info;
+const ui::StaticDisplayInfo& getDisplayInfo() {
+ static ui::StaticDisplayInfo info = [] {
+ ui::StaticDisplayInfo info;
#if HWUI_NULL_GPU
info.density = 2.f;
#else
const sp<IBinder> token = SurfaceComposerClient::getInternalDisplayToken();
LOG_ALWAYS_FATAL_IF(!token, "%s: No internal display", __FUNCTION__);
- const status_t status = SurfaceComposerClient::getDisplayInfo(token, &info);
+ const status_t status = SurfaceComposerClient::getStaticDisplayInfo(token, &info);
LOG_ALWAYS_FATAL_IF(status, "%s: Failed to get display info", __FUNCTION__);
#endif
return info;
diff --git a/libs/hwui/tests/common/TestContext.h b/libs/hwui/tests/common/TestContext.h
index 7d2f6d8ea731..9d00366daffe 100644
--- a/libs/hwui/tests/common/TestContext.h
+++ b/libs/hwui/tests/common/TestContext.h
@@ -23,8 +23,8 @@
#include <gui/Surface.h>
#include <gui/SurfaceComposerClient.h>
#include <gui/SurfaceControl.h>
-#include <ui/DisplayInfo.h>
#include <ui/DisplayMode.h>
+#include <ui/StaticDisplayInfo.h>
#include <utils/Looper.h>
#include <atomic>
@@ -36,7 +36,7 @@ namespace android {
namespace uirenderer {
namespace test {
-const DisplayInfo& getDisplayInfo();
+const ui::StaticDisplayInfo& getDisplayInfo();
const ui::DisplayMode& getActiveDisplayMode();
inline const ui::Size& getActiveDisplayResolution() {
diff --git a/libs/input/MouseCursorController.h b/libs/input/MouseCursorController.h
index e6dfc4c6f99a..c0ab58bd2e7e 100644
--- a/libs/input/MouseCursorController.h
+++ b/libs/input/MouseCursorController.h
@@ -20,7 +20,6 @@
#include <gui/DisplayEventReceiver.h>
#include <input/DisplayViewport.h>
#include <input/Input.h>
-#include <ui/DisplayInfo.h>
#include <utils/BitSet.h>
#include <utils/Looper.h>
#include <utils/RefBase.h>
diff --git a/libs/input/PointerController.h b/libs/input/PointerController.h
index 827fcf1e1bc1..97567bab202b 100644
--- a/libs/input/PointerController.h
+++ b/libs/input/PointerController.h
@@ -21,7 +21,6 @@
#include <gui/DisplayEventReceiver.h>
#include <input/DisplayViewport.h>
#include <input/Input.h>
-#include <ui/DisplayInfo.h>
#include <utils/BitSet.h>
#include <utils/Looper.h>
#include <utils/RefBase.h>
diff --git a/libs/input/PointerControllerContext.h b/libs/input/PointerControllerContext.h
index 98073fea323e..26a65a47471d 100644
--- a/libs/input/PointerControllerContext.h
+++ b/libs/input/PointerControllerContext.h
@@ -21,7 +21,6 @@
#include <gui/DisplayEventReceiver.h>
#include <input/DisplayViewport.h>
#include <input/Input.h>
-#include <ui/DisplayInfo.h>
#include <utils/BitSet.h>
#include <utils/Looper.h>
#include <utils/RefBase.h>
diff --git a/location/java/android/location/GnssMeasurement.java b/location/java/android/location/GnssMeasurement.java
index 3dcaffbd2712..242d9a3627db 100644
--- a/location/java/android/location/GnssMeasurement.java
+++ b/location/java/android/location/GnssMeasurement.java
@@ -1096,13 +1096,7 @@ public final class GnssMeasurement implements Parcelable {
* Gets the carrier frequency of the tracked signal.
*
* <p>For example it can be the GPS central frequency for L1 = 1575.45 MHz, or L2 = 1227.60 MHz,
- * L5 = 1176.45 MHz, varying GLO channels, etc. If the field is not set, it is the primary
- * common use central frequency, e.g. L1 = 1575.45 MHz for GPS.
- *
- * <p> For an L1, L5 receiver tracking a satellite on L1 and L5 at the same time, two raw
- * measurement objects will be reported for this same satellite, in one of the measurement
- * objects, all the values related to L1 will be filled, and in the other all of the values
- * related to L5 will be filled.
+ * L5 = 1176.45 MHz, varying GLO channels, etc.
*
* <p>The value is only available if {@link #hasCarrierFrequencyHz()} is {@code true}.
*
@@ -1382,7 +1376,8 @@ public final class GnssMeasurement implements Parcelable {
* <p> AGC acts as a variable gain amplifier adjusting the power of the incoming signal. The AGC
* level may be used to indicate potential interference. Higher gain (and/or lower input power)
* shall be output as a positive number. Hence in cases of strong jamming, in the band of this
- * signal, this value will go more negative.
+ * signal, this value will go more negative. This value must be consistent given the same level
+ * of the incoming signal power.
*
* <p> Note: Different hardware designs (e.g. antenna, pre-amplification, or other RF HW
* components) may also affect the typical output of of this value on any given hardware design
diff --git a/location/java/android/location/GnssStatus.java b/location/java/android/location/GnssStatus.java
index b46e8ce2f605..23390fce1a5f 100644
--- a/location/java/android/location/GnssStatus.java
+++ b/location/java/android/location/GnssStatus.java
@@ -284,12 +284,7 @@ public final class GnssStatus implements Parcelable {
* Gets the carrier frequency of the signal tracked.
*
* <p>For example it can be the GPS central frequency for L1 = 1575.45 MHz, or L2 = 1227.60
- * MHz, L5 = 1176.45 MHz, varying GLO channels, etc. If the field is not set, it is the primary
- * common use central frequency, e.g. L1 = 1575.45 MHz for GPS.
- *
- * For an L1, L5 receiver tracking a satellite on L1 and L5 at the same time, two measurements
- * will be reported for this same satellite, in one all the values related to L1 will be
- * filled, and in the other all of the values related to L5 will be filled.
+ * MHz, L5 = 1176.45 MHz, varying GLO channels, etc.
*
* <p>The value is only available if {@link #hasCarrierFrequencyHz(int satelliteIndex)} is
* {@code true}.
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 088b789ea690..b7823400695d 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -20,7 +20,6 @@ import static android.Manifest.permission.ACCESS_COARSE_LOCATION;
import static android.Manifest.permission.ACCESS_FINE_LOCATION;
import static android.Manifest.permission.LOCATION_HARDWARE;
import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
-import static android.location.GpsStatus.GPS_EVENT_STARTED;
import static android.location.LocationRequest.createFromDeprecatedCriteria;
import static android.location.LocationRequest.createFromDeprecatedProvider;
@@ -412,7 +411,7 @@ public class LocationManager {
private static final String CACHE_KEY_LOCATION_ENABLED_PROPERTY =
"cache_key.location_enabled";
- private static ILocationManager getService() throws RemoteException {
+ static ILocationManager getService() throws RemoteException {
try {
return ILocationManager.Stub.asInterface(
ServiceManager.getServiceOrThrow(Context.LOCATION_SERVICE));
@@ -439,11 +438,13 @@ public class LocationManager {
new GnssNavigationTransportManager();
}
- private static final ProviderRequestTransportManager sProviderRequestListeners =
- new ProviderRequestTransportManager();
+ private static class ProviderRequestLazyLoader {
+ static final ProviderRequestTransportManager sProviderRequestListeners =
+ new ProviderRequestTransportManager();
+ }
- private final Context mContext;
- private final ILocationManager mService;
+ final Context mContext;
+ final ILocationManager mService;
private volatile PropertyInvalidatedCache<Integer, Boolean> mLocationEnabledCache =
new PropertyInvalidatedCache<Integer, Boolean>(
@@ -2790,7 +2791,7 @@ public class LocationManager {
public boolean registerProviderRequestListener(
@NonNull @CallbackExecutor Executor executor,
@NonNull Listener listener) {
- sProviderRequestListeners.addListener(listener,
+ ProviderRequestLazyLoader.sProviderRequestListeners.addListener(listener,
new ProviderRequestTransport(executor, listener));
return true;
}
@@ -2805,7 +2806,7 @@ public class LocationManager {
@RequiresPermission(Manifest.permission.LOCATION_HARDWARE)
public void unregisterProviderRequestListener(
@NonNull Listener listener) {
- sProviderRequestListeners.removeListener(listener);
+ ProviderRequestLazyLoader.sProviderRequestListeners.removeListener(listener);
}
/**
@@ -2917,6 +2918,10 @@ public class LocationManager {
private static class GnssStatusTransportManager extends
ListenerTransportManager<GnssStatusTransport> {
+ GnssStatusTransportManager() {
+ super(false);
+ }
+
@Override
protected void registerTransport(GnssStatusTransport transport)
throws RemoteException {
@@ -2934,6 +2939,10 @@ public class LocationManager {
private static class GnssNmeaTransportManager extends
ListenerTransportManager<GnssNmeaTransport> {
+ GnssNmeaTransportManager() {
+ super(false);
+ }
+
@Override
protected void registerTransport(GnssNmeaTransport transport)
throws RemoteException {
@@ -2951,6 +2960,10 @@ public class LocationManager {
private static class GnssMeasurementsTransportManager extends
ListenerTransportManager<GnssMeasurementsTransport> {
+ GnssMeasurementsTransportManager() {
+ super(false);
+ }
+
@Override
protected void registerTransport(GnssMeasurementsTransport transport)
throws RemoteException {
@@ -2968,6 +2981,10 @@ public class LocationManager {
private static class GnssAntennaTransportManager extends
ListenerTransportManager<GnssAntennaInfoTransport> {
+ GnssAntennaTransportManager() {
+ super(false);
+ }
+
@Override
protected void registerTransport(GnssAntennaInfoTransport transport) {
transport.getContext().registerReceiver(transport,
@@ -2983,6 +3000,10 @@ public class LocationManager {
private static class GnssNavigationTransportManager extends
ListenerTransportManager<GnssNavigationTransport> {
+ GnssNavigationTransportManager() {
+ super(false);
+ }
+
@Override
protected void registerTransport(GnssNavigationTransport transport)
throws RemoteException {
@@ -3000,6 +3021,10 @@ public class LocationManager {
private static class ProviderRequestTransportManager extends
ListenerTransportManager<ProviderRequestTransport> {
+ ProviderRequestTransportManager() {
+ super(false);
+ }
+
@Override
protected void registerTransport(ProviderRequestTransport transport)
throws RemoteException {
@@ -3117,6 +3142,8 @@ public class LocationManager {
}
}
+ /** @deprecated */
+ @Deprecated
private static class GpsAdapter extends GnssStatus.Callback {
private final GpsStatus.Listener mGpsListener;
@@ -3127,7 +3154,7 @@ public class LocationManager {
@Override
public void onStarted() {
- mGpsListener.onGpsStatusChanged(GPS_EVENT_STARTED);
+ mGpsListener.onGpsStatusChanged(GpsStatus.GPS_EVENT_STARTED);
}
@Override
@@ -3204,6 +3231,8 @@ public class LocationManager {
}
}
+ /** @deprecated */
+ @Deprecated
private static class GpsStatusTransport extends GnssStatusTransport {
static volatile int sTtff;
@@ -3442,6 +3471,8 @@ public class LocationManager {
}
}
+ /** @deprecated */
+ @Deprecated
private static class BatchedLocationCallbackWrapper implements LocationListener {
private final BatchedLocationCallback mCallback;
@@ -3461,6 +3492,8 @@ public class LocationManager {
}
}
+ /** @deprecated */
+ @Deprecated
private static class BatchedLocationCallbackTransport extends LocationListenerTransport {
BatchedLocationCallbackTransport(BatchedLocationCallback callback, Handler handler) {
diff --git a/media/java/android/media/AudioDeviceInfo.java b/media/java/android/media/AudioDeviceInfo.java
index 205c1f4b4057..383c93d7716d 100644
--- a/media/java/android/media/AudioDeviceInfo.java
+++ b/media/java/android/media/AudioDeviceInfo.java
@@ -16,8 +16,10 @@
package android.media;
+import android.Manifest;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
import android.util.SparseIntArray;
import java.lang.annotation.Retention;
@@ -161,6 +163,14 @@ public final class AudioDeviceInfo {
*/
public static final int TYPE_BLE_SPEAKER = 27;
+ /**
+ * A device type describing an Echo Canceller loopback Reference.
+ * This device is only used when capturing with MediaRecorder.AudioSource.ECHO_REFERENCE,
+ * which requires privileged permission
+ * {@link android.Manifest.permission#CAPTURE_AUDIO_OUTPUT}.
+ * @hide */
+ @RequiresPermission(Manifest.permission.CAPTURE_AUDIO_OUTPUT)
+ public static final int TYPE_ECHO_REFERENCE = 28;
/** @hide */
@IntDef(flag = false, prefix = "TYPE", value = {
@@ -188,7 +198,8 @@ public final class AudioDeviceInfo {
TYPE_FM_TUNER,
TYPE_TV_TUNER,
TYPE_BLE_HEADSET,
- TYPE_BLE_SPEAKER}
+ TYPE_BLE_SPEAKER,
+ TYPE_ECHO_REFERENCE}
)
@Retention(RetentionPolicy.SOURCE)
public @interface AudioDeviceType {}
@@ -211,7 +222,8 @@ public final class AudioDeviceInfo {
TYPE_LINE_DIGITAL,
TYPE_IP,
TYPE_BUS,
- TYPE_BLE_HEADSET}
+ TYPE_BLE_HEADSET,
+ TYPE_ECHO_REFERENCE}
)
@Retention(RetentionPolicy.SOURCE)
public @interface AudioDeviceTypeIn {}
@@ -297,6 +309,7 @@ public final class AudioDeviceInfo {
case TYPE_BUS:
case TYPE_REMOTE_SUBMIX:
case TYPE_BLE_HEADSET:
+ case TYPE_ECHO_REFERENCE:
return true;
default:
return false;
@@ -621,6 +634,8 @@ public final class AudioDeviceInfo {
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BUS, TYPE_BUS);
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_REMOTE_SUBMIX, TYPE_REMOTE_SUBMIX);
INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_BLE_HEADSET, TYPE_BLE_HEADSET);
+ INT_TO_EXT_DEVICE_MAPPING.put(AudioSystem.DEVICE_IN_ECHO_REFERENCE, TYPE_ECHO_REFERENCE);
+
// privileges mapping to output device
EXT_TO_INT_DEVICE_MAPPING = new SparseIntArray();
@@ -678,6 +693,9 @@ public final class AudioDeviceInfo {
EXT_TO_INT_INPUT_DEVICE_MAPPING.put(
TYPE_REMOTE_SUBMIX, AudioSystem.DEVICE_IN_REMOTE_SUBMIX);
EXT_TO_INT_INPUT_DEVICE_MAPPING.put(TYPE_BLE_HEADSET, AudioSystem.DEVICE_IN_BLE_HEADSET);
+ EXT_TO_INT_INPUT_DEVICE_MAPPING.put(
+ TYPE_ECHO_REFERENCE, AudioSystem.DEVICE_IN_ECHO_REFERENCE);
+
}
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index d896c1fc82b5..f87f90d8e0a2 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3123,52 +3123,57 @@ public class AudioManager {
/**
* @hide Home sound
- * Played by the framework when the home app becomes active if config_enableHomeSound is set to
- * true. This is currently only used on TV devices.
+ * <p>
+ * To be played by the framework when the home app becomes active if config_enableHomeSound is
+ * set to true. This is currently only used on TV devices.
* Note that this sound is only available if a sound file is specified in audio_assets.xml.
* @see #playSoundEffect(int)
*/
public static final int FX_HOME = 11;
/**
- * @hide Fast scroll sound 1
- * To be by the framework when a fast-scrolling is performed and
- * {@link #areFastScrollSoundEffectsEnabled()} is true.
+ * @hide Navigation repeat sound 1
+ * <p>
+ * To be played by the framework when a focus navigation is repeatedly triggered
+ * (e.g. due to long-pressing) and {@link #areNavigationRepeatSoundEffectsEnabled()} is true.
* This is currently only used on TV devices.
* Note that this sound is only available if a sound file is specified in audio_assets.xml
* @see #playSoundEffect(int)
*/
- public static final int FX_FAST_SCROLL_1 = 12;
+ public static final int FX_FOCUS_NAVIGATION_REPEAT_1 = 12;
/**
- * @hide Fast scroll sound 2
- * To be by the framework when a fast-scrolling is performed and
- * {@link #areFastScrollSoundEffectsEnabled()} is true.
+ * @hide Navigation repeat sound 2
+ * <p>
+ * To be played by the framework when a focus navigation is repeatedly triggered
+ * (e.g. due to long-pressing) and {@link #areNavigationRepeatSoundEffectsEnabled()} is true.
* This is currently only used on TV devices.
* Note that this sound is only available if a sound file is specified in audio_assets.xml
* @see #playSoundEffect(int)
*/
- public static final int FX_FAST_SCROLL_2 = 13;
+ public static final int FX_FOCUS_NAVIGATION_REPEAT_2 = 13;
/**
- * @hide Fast scroll sound 3
- * To be by the framework when a fast-scrolling is performed and
- * {@link #areFastScrollSoundEffectsEnabled()} is true.
+ * @hide Navigation repeat sound 3
+ * <p>
+ * To be played by the framework when a focus navigation is repeatedly triggered
+ * (e.g. due to long-pressing) and {@link #areNavigationRepeatSoundEffectsEnabled()} is true.
* This is currently only used on TV devices.
* Note that this sound is only available if a sound file is specified in audio_assets.xml
* @see #playSoundEffect(int)
*/
- public static final int FX_FAST_SCROLL_3 = 14;
+ public static final int FX_FOCUS_NAVIGATION_REPEAT_3 = 14;
/**
- * @hide Fast scroll sound 4
- * To be by the framework when a fast-scrolling is performed and
- * {@link #areFastScrollSoundEffectsEnabled()} is true.
+ * @hide Navigation repeat sound 4
+ * <p>
+ * To be played by the framework when a focus navigation is repeatedly triggered
+ * (e.g. due to long-pressing) and {@link #areNavigationRepeatSoundEffectsEnabled()} is true.
* This is currently only used on TV devices.
* Note that this sound is only available if a sound file is specified in audio_assets.xml
* @see #playSoundEffect(int)
*/
- public static final int FX_FAST_SCROLL_4 = 15;
+ public static final int FX_FOCUS_NAVIGATION_REPEAT_4 = 15;
/**
* @hide Number of sound effects
@@ -3177,27 +3182,27 @@ public class AudioManager {
public static final int NUM_SOUND_EFFECTS = 16;
/**
- * @hide Number of fast scroll sound effects
+ * @hide Number of FX_FOCUS_NAVIGATION_REPEAT_* sound effects
*/
- public static final int NUM_FAST_SCROLL_SOUND_EFFECTS = 4;
+ public static final int NUM_NAVIGATION_REPEAT_SOUND_EFFECTS = 4;
/**
* @hide
- * @param n a value in [0, {@link #NUM_FAST_SCROLL_SOUND_EFFECTS}[
- * @return The id of a fast scroll sound effect or -1 if out of bounds
+ * @param n a value in [0, {@link #NUM_NAVIGATION_REPEAT_SOUND_EFFECTS}[
+ * @return The id of a navigation repeat sound effect or -1 if out of bounds
*/
- public static int getNthFastScrollSoundEffectId(int n) {
+ public static int getNthNavigationRepeatSoundEffect(int n) {
switch (n) {
case 0:
- return FX_FAST_SCROLL_1;
+ return FX_FOCUS_NAVIGATION_REPEAT_1;
case 1:
- return FX_FAST_SCROLL_2;
+ return FX_FOCUS_NAVIGATION_REPEAT_2;
case 2:
- return FX_FAST_SCROLL_3;
+ return FX_FOCUS_NAVIGATION_REPEAT_3;
case 3:
- return FX_FAST_SCROLL_4;
+ return FX_FOCUS_NAVIGATION_REPEAT_4;
default:
- Log.w(TAG, "Invalid fast-scroll sound effect id: " + n);
+ Log.w(TAG, "Invalid navigation repeat sound effect id: " + n);
return -1;
}
}
@@ -3205,9 +3210,9 @@ public class AudioManager {
/**
* @hide
*/
- public void setFastScrollSoundEffectsEnabled(boolean enabled) {
+ public void setNavigationRepeatSoundEffectsEnabled(boolean enabled) {
try {
- getService().setFastScrollSoundEffectsEnabled(enabled);
+ getService().setNavigationRepeatSoundEffectsEnabled(enabled);
} catch (RemoteException e) {
}
@@ -3215,11 +3220,11 @@ public class AudioManager {
/**
* @hide
- * @return true if the fast scroll sound effects are enabled
+ * @return true if the navigation repeat sound effects are enabled
*/
- public boolean areFastScrollSoundEffectsEnabled() {
+ public boolean areNavigationRepeatSoundEffectsEnabled() {
try {
- return getService().areFastScrollSoundEffectsEnabled();
+ return getService().areNavigationRepeatSoundEffectsEnabled();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 7fb83f17a9d4..6fcb75616f0d 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -565,6 +565,11 @@ public class AudioTrack extends PlayerBase
*/
private int mOffloadPaddingFrames = 0;
+ /**
+ * The log session id used for metrics.
+ */
+ private String mLogSessionId;
+
//--------------------------------
// Used exclusively by native code
//--------------------
@@ -837,6 +842,7 @@ public class AudioTrack extends PlayerBase
}
baseRegisterPlayer(mSessionId);
+ native_setPlayerIId(mPlayerIId); // mPlayerIId now ready to send to native AudioTrack.
}
/**
@@ -3967,6 +3973,23 @@ public class AudioTrack extends PlayerBase
}
}
+ /**
+ * Sets a string handle to this AudioTrack for metrics collection.
+ *
+ * @param logSessionId a string which is used to identify this object
+ * to the metrics service.
+ * @throws IllegalStateException if AudioTrack not initialized.
+ *
+ * @hide
+ */
+ public void setLogSessionId(@NonNull String logSessionId) {
+ if (mState == STATE_UNINITIALIZED) {
+ throw new IllegalStateException("track not initialized");
+ }
+ native_setLogSessionId(logSessionId);
+ mLogSessionId = logSessionId;
+ }
+
//---------------------------------------------------------
// Inner classes
//--------------------
@@ -4202,6 +4225,21 @@ public class AudioTrack extends PlayerBase
private native int native_get_audio_description_mix_level_db(float[] level);
private native int native_set_dual_mono_mode(int dualMonoMode);
private native int native_get_dual_mono_mode(int[] dualMonoMode);
+ private native void native_setLogSessionId(@NonNull String logSessionId);
+
+ /**
+ * Sets the audio service Player Interface Id.
+ *
+ * The playerIId does not change over the lifetime of the client
+ * Java AudioTrack and is set automatically on creation.
+ *
+ * This call informs the native AudioTrack for metrics logging purposes.
+ *
+ * @param id the value reported by AudioManager when registering the track.
+ * A value of -1 indicates invalid - the playerIId was never set.
+ * @throws IllegalStateException if AudioTrack not initialized.
+ */
+ private native void native_setPlayerIId(int playerIId);
//---------------------------------------------------------
// Utility methods
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 71ee57e3d471..0073b5cc93b9 100755
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -351,9 +351,9 @@ interface IAudioService {
oneway void unregisterCommunicationDeviceDispatcher(
ICommunicationDeviceDispatcher dispatcher);
- boolean areFastScrollSoundEffectsEnabled();
+ boolean areNavigationRepeatSoundEffectsEnabled();
- oneway void setFastScrollSoundEffectsEnabled(boolean enabled);
+ oneway void setNavigationRepeatSoundEffectsEnabled(boolean enabled);
boolean isHomeSoundEffectEnabled();
diff --git a/media/java/android/media/PlayerBase.java b/media/java/android/media/PlayerBase.java
index 4407efad6052..5d0f0aa8a921 100644
--- a/media/java/android/media/PlayerBase.java
+++ b/media/java/android/media/PlayerBase.java
@@ -78,7 +78,7 @@ public abstract class PlayerBase {
private final int mImplType;
// uniquely identifies the Player Interface throughout the system (P I Id)
- private int mPlayerIId = AudioPlaybackConfiguration.PLAYER_PIID_INVALID;
+ protected int mPlayerIId = AudioPlaybackConfiguration.PLAYER_PIID_INVALID;
@GuardedBy("mLock")
private int mState;
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index ee0be010c233..952bbf56d5fa 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -149,7 +149,7 @@ public class Tuner implements AutoCloseable {
/**
* Invalid 64-bit filter ID.
*/
- public static final long INVALID_FILTER_ID_64BIT =
+ public static final long INVALID_FILTER_ID_LONG =
android.hardware.tv.tuner.V1_1.Constants.Constant64Bit.INVALID_FILTER_ID_64BIT;
/**
* Invalid frequency that is used as the default frontend frequency setting.
@@ -932,8 +932,8 @@ public class Tuner implements AutoCloseable {
public int connectFrontendToCiCam(int ciCamId) {
if (TunerVersionChecker.checkHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1,
"linkFrontendToCiCam")) {
- if (checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND)
- && checkCiCamResource(ciCamId)) {
+ if (checkCiCamResource(ciCamId)
+ && checkResource(TunerResourceManager.TUNER_RESOURCE_TYPE_FRONTEND)) {
return nativeLinkCiCam(ciCamId);
}
}
@@ -978,7 +978,8 @@ public class Tuner implements AutoCloseable {
public int disconnectFrontendToCiCam(int ciCamId) {
if (TunerVersionChecker.checkHigherOrEqualVersionTo(TunerVersionChecker.TUNER_VERSION_1_1,
"unlinkFrontendToCiCam")) {
- if (mFrontendCiCamHandle != null && mFrontendCiCamId == ciCamId) {
+ if (mFrontendCiCamHandle != null && mFrontendCiCamId != null
+ && mFrontendCiCamId == ciCamId) {
int result = nativeUnlinkCiCam(ciCamId);
if (result == RESULT_SUCCESS) {
mTunerResourceManager.releaseCiCam(mFrontendCiCamHandle, mClientId);
@@ -1409,6 +1410,7 @@ public class Tuner implements AutoCloseable {
boolean granted = mTunerResourceManager.requestCiCam(request, ciCamHandle);
if (granted) {
mFrontendCiCamHandle = ciCamHandle[0];
+ mFrontendCiCamId = ciCamId;
}
return granted;
}
diff --git a/media/java/android/media/tv/tuner/filter/DownloadEvent.java b/media/java/android/media/tv/tuner/filter/DownloadEvent.java
index 9f97b6141de0..394211be646b 100644
--- a/media/java/android/media/tv/tuner/filter/DownloadEvent.java
+++ b/media/java/android/media/tv/tuner/filter/DownloadEvent.java
@@ -16,6 +16,7 @@
package android.media.tv.tuner.filter;
+import android.annotation.IntRange;
import android.annotation.SystemApi;
/**
@@ -51,6 +52,7 @@ public class DownloadEvent extends FilterEvent {
/**
* Gets MPU sequence number of filtered data.
*/
+ @IntRange(from = 0)
public int getMpuSequenceNumber() {
return mMpuSequenceNumber;
}
diff --git a/media/java/android/media/tv/tuner/filter/Filter.java b/media/java/android/media/tv/tuner/filter/Filter.java
index 51b685aeb8be..2f3e2d8d5dd9 100644
--- a/media/java/android/media/tv/tuner/filter/Filter.java
+++ b/media/java/android/media/tv/tuner/filter/Filter.java
@@ -309,7 +309,8 @@ public class Filter implements AutoCloseable {
}
/**
- * Gets the filter Id.
+ * Gets the filter Id in 32-bit. For any Tuner SoC that supports 64-bit filter architecture,
+ * use {@link #getIdLong()}.
*/
public int getId() {
synchronized (mLock) {
@@ -319,9 +320,10 @@ public class Filter implements AutoCloseable {
}
/**
- * Gets the 64-bit filter Id.
+ * Gets the 64-bit filter Id. For any Tuner SoC that supports 32-bit filter architecture,
+ * use {@link #getId()}.
*/
- public long getId64Bit() {
+ public long getIdLong() {
synchronized (mLock) {
TunerUtils.checkResourceState(TAG, mIsClosed);
return nativeGetId64Bit();
diff --git a/media/java/android/media/tv/tuner/filter/MediaEvent.java b/media/java/android/media/tv/tuner/filter/MediaEvent.java
index 91be5c38d693..dbd85e9997d8 100644
--- a/media/java/android/media/tv/tuner/filter/MediaEvent.java
+++ b/media/java/android/media/tv/tuner/filter/MediaEvent.java
@@ -17,6 +17,7 @@
package android.media.tv.tuner.filter;
import android.annotation.BytesLong;
+import android.annotation.IntRange;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.media.MediaCodec.LinearBlock;
@@ -154,6 +155,7 @@ public class MediaEvent extends FilterEvent {
/**
* Gets MPU sequence number of filtered data.
*/
+ @IntRange(from = 0)
public int getMpuSequenceNumber() {
return mMpuSequenceNumber;
}
diff --git a/media/java/android/media/tv/tuner/filter/MmtpRecordEvent.java b/media/java/android/media/tv/tuner/filter/MmtpRecordEvent.java
index 6a41c74ef73a..58a81d99ff99 100644
--- a/media/java/android/media/tv/tuner/filter/MmtpRecordEvent.java
+++ b/media/java/android/media/tv/tuner/filter/MmtpRecordEvent.java
@@ -17,6 +17,7 @@
package android.media.tv.tuner.filter;
import android.annotation.BytesLong;
+import android.annotation.IntRange;
import android.annotation.SystemApi;
import android.media.tv.tuner.filter.RecordSettings.ScHevcIndex;
@@ -69,6 +70,7 @@ public class MmtpRecordEvent extends FilterEvent {
* {@link android.media.tv.tuner.TunerVersionChecker#getTunerVersion()} to get the version
* information.
*/
+ @IntRange(from = 0)
public int getMpuSequenceNumber() {
return mMpuSequenceNumber;
}
diff --git a/media/java/android/media/tv/tuner/filter/PesEvent.java b/media/java/android/media/tv/tuner/filter/PesEvent.java
index 695e596c98b7..bfb7460d9c7b 100644
--- a/media/java/android/media/tv/tuner/filter/PesEvent.java
+++ b/media/java/android/media/tv/tuner/filter/PesEvent.java
@@ -16,6 +16,7 @@
package android.media.tv.tuner.filter;
+import android.annotation.IntRange;
import android.annotation.SystemApi;
/**
@@ -53,6 +54,7 @@ public class PesEvent extends FilterEvent {
/**
* Gets MPU sequence number of filtered data.
*/
+ @IntRange(from = 0)
public int getMpuSequenceNumber() {
return mMpuSequenceNumber;
}
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 73e1f7df89a1..56f6c45bb50e 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -424,7 +424,7 @@ static bool isSessionException(status_t err) {
static bool throwExceptionAsNecessary(
JNIEnv *env, const sp<IDrm> &drm, status_t err, const char *msg = NULL) {
std::string msgStr;
- if (drm != NULL) {
+ if (drm != NULL && err != OK) {
msgStr = DrmUtils::GetExceptionMessage(err, msg, drm);
msg = msgStr.c_str();
}
diff --git a/media/jni/tuner/DemuxClient.cpp b/media/jni/tuner/DemuxClient.cpp
index 359ef364083c..78cb5b003a38 100644
--- a/media/jni/tuner/DemuxClient.cpp
+++ b/media/jni/tuner/DemuxClient.cpp
@@ -216,7 +216,7 @@ Result DemuxClient::disconnectCiCam() {
Result DemuxClient::close() {
if (mTunerDemux != NULL) {
Status s = mTunerDemux->close();
- mDemux = NULL;
+ mTunerDemux = NULL;
return ClientHelper::getServiceSpecificErrorCode(s);
}
diff --git a/media/jni/tuner/FilterClient.h b/media/jni/tuner/FilterClient.h
index bbabc282464a..736b8f9cd4b4 100644
--- a/media/jni/tuner/FilterClient.h
+++ b/media/jni/tuner/FilterClient.h
@@ -267,9 +267,6 @@ private:
AidlMQ* mFilterMQ;
EventFlag* mFilterMQEventFlag;
- sp<FilterClientCallback> mCallback;
- sp<HidlFilterCallback> mHidlCallback;
-
native_handle_t* mAvSharedHandle;
uint64_t mAvSharedMemSize;
bool mIsMediaFilter;
diff --git a/media/jni/tuner/FrontendClient.cpp b/media/jni/tuner/FrontendClient.cpp
index 9e3664275dac..f400a7157051 100644
--- a/media/jni/tuner/FrontendClient.cpp
+++ b/media/jni/tuner/FrontendClient.cpp
@@ -78,8 +78,6 @@ namespace android {
FrontendClient::FrontendClient(shared_ptr<ITunerFrontend> tunerFrontend, int type) {
mTunerFrontend = tunerFrontend;
- mAidlCallback = NULL;
- mHidlCallback = NULL;
mType = type;
}
@@ -87,22 +85,21 @@ FrontendClient::~FrontendClient() {
mTunerFrontend = NULL;
mFrontend = NULL;
mFrontend_1_1 = NULL;
- mAidlCallback = NULL;
- mHidlCallback = NULL;
mId = -1;
mType = -1;
}
Result FrontendClient::setCallback(sp<FrontendClientCallback> frontendClientCallback) {
if (mTunerFrontend != NULL) {
- mAidlCallback = ::ndk::SharedRefBase::make<TunerFrontendCallback>(frontendClientCallback);
- mAidlCallback->setFrontendType(mType);
- Status s = mTunerFrontend->setCallback(mAidlCallback);
+ shared_ptr<TunerFrontendCallback> aidlCallback =
+ ::ndk::SharedRefBase::make<TunerFrontendCallback>(frontendClientCallback);
+ aidlCallback->setFrontendType(mType);
+ Status s = mTunerFrontend->setCallback(aidlCallback);
return ClientHelper::getServiceSpecificErrorCode(s);
}
- mHidlCallback = new HidlFrontendCallback(frontendClientCallback);
- return mFrontend->setCallback(mHidlCallback);
+ sp<HidlFrontendCallback> hidlCallback = new HidlFrontendCallback(frontendClientCallback);
+ return mFrontend->setCallback(hidlCallback);
}
void FrontendClient::setHidlFrontend(sp<IFrontend> frontend) {
diff --git a/media/jni/tuner/FrontendClient.h b/media/jni/tuner/FrontendClient.h
index f71616cb32b7..1dd950eee9e1 100644
--- a/media/jni/tuner/FrontendClient.h
+++ b/media/jni/tuner/FrontendClient.h
@@ -226,9 +226,6 @@ private:
*/
sp<::android::hardware::tv::tuner::V1_1::IFrontend> mFrontend_1_1;
- shared_ptr<TunerFrontendCallback> mAidlCallback;
- sp<HidlFrontendCallback> mHidlCallback;
-
int mId;
int mType;
};
diff --git a/media/jni/tuner/LnbClient.cpp b/media/jni/tuner/LnbClient.cpp
index 5b6e46eba418..073c49a2d6ac 100644
--- a/media/jni/tuner/LnbClient.cpp
+++ b/media/jni/tuner/LnbClient.cpp
@@ -45,14 +45,15 @@ void LnbClient::setHidlLnb(sp<ILnb> lnb) {
Result LnbClient::setCallback(sp<LnbClientCallback> cb) {
if (mTunerLnb != NULL) {
- mAidlCallback = ::ndk::SharedRefBase::make<TunerLnbCallback>(cb);
- Status s = mTunerLnb->setCallback(mAidlCallback);
+ shared_ptr<TunerLnbCallback> aidlCallback =
+ ::ndk::SharedRefBase::make<TunerLnbCallback>(cb);
+ Status s = mTunerLnb->setCallback(aidlCallback);
return ClientHelper::getServiceSpecificErrorCode(s);
}
if (mLnb != NULL) {
- mHidlCallback = new HidlLnbCallback(cb);
- return mLnb->setCallback(mHidlCallback);
+ sp<HidlLnbCallback> hidlCallback = new HidlLnbCallback(cb);
+ return mLnb->setCallback(hidlCallback);
}
return Result::INVALID_STATE;
diff --git a/media/jni/tuner/LnbClient.h b/media/jni/tuner/LnbClient.h
index 465dc2331ecf..7c6118c98eb5 100644
--- a/media/jni/tuner/LnbClient.h
+++ b/media/jni/tuner/LnbClient.h
@@ -126,9 +126,6 @@ private:
*/
sp<ILnb> mLnb;
- shared_ptr<TunerLnbCallback> mAidlCallback;
- sp<HidlLnbCallback> mHidlCallback;
-
LnbId mId;
};
} // namespace android
diff --git a/media/jni/tuner/TunerClient.cpp b/media/jni/tuner/TunerClient.cpp
index cf17ed6f4383..c9a7e8340dda 100644
--- a/media/jni/tuner/TunerClient.cpp
+++ b/media/jni/tuner/TunerClient.cpp
@@ -49,8 +49,6 @@ TunerClient::TunerClient() {
if (mTunerService == NULL) {
ALOGE("Failed to get tuner service");
} else {
- // TODO: b/178124017 update TRM in TunerService independently.
- mTunerService->updateTunerResources();
mTunerService->getTunerHalVersion(&mTunerVersion);
}
}
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
index e51add276647..e8cf63f64572 100644
--- a/native/android/surface_control.cpp
+++ b/native/android/surface_control.cpp
@@ -27,14 +27,13 @@
#include <gui/SurfaceComposerClient.h>
#include <gui/SurfaceControl.h>
-#include <ui/HdrCapabilities.h>
+#include <ui/DynamicDisplayInfo.h>
#include <utils/Timers.h>
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
using namespace android;
-using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
using Transaction = SurfaceComposerClient::Transaction;
@@ -72,14 +71,13 @@ static bool getHdrSupport(const sp<SurfaceControl>& surfaceControl) {
return false;
}
- HdrCapabilities hdrCapabilities;
- status_t err = client->getHdrCapabilities(display, &hdrCapabilities);
- if (err) {
+ ui::DynamicDisplayInfo info;
+ if (status_t err = client->getDynamicDisplayInfo(display, &info); err != NO_ERROR) {
ALOGE("unable to get hdr capabilities");
- return false;
+ return err;
}
- return !hdrCapabilities.getSupportedHdrTypes().empty();
+ return !info.hdrCapabilities.getSupportedHdrTypes().empty();
}
static bool isDataSpaceValid(const sp<SurfaceControl>& surfaceControl, ADataSpace dataSpace) {
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 3866151982a4..79fbcc376b3c 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1007,6 +1007,9 @@
<!-- Settings item title to select the default behavior for transcoding if an encodig is not supported by an app. [CHAR LIMIT=85] -->
<string name="transcode_default">Assume apps support modern formats</string>
+ <!-- Settings item title to select whether to show transcoding notifications. [CHAR LIMIT=85] -->
+ <string name="transcode_notification">Show transcoding notifications</string>
+
<!-- Services settings screen, setting option name for the user to go to the screen to view running services -->
<string name="runningservices_settings_title">Running services</string>
<!-- Services settings screen, setting option summary for the user to go to the screen to view running services -->
diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
index 66165b6d1ff2..ad6a5312f156 100644
--- a/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
+++ b/packages/SettingsProvider/src/android/provider/settings/validators/GlobalSettingsValidators.java
@@ -147,5 +147,10 @@ public class GlobalSettingsValidators {
VALIDATORS.put(Global.DEVELOPMENT_SETTINGS_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Global.NOTIFICATION_FEEDBACK_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Global.RESTRICTED_NETWORKING_MODE, BOOLEAN_VALIDATOR);
+ VALIDATORS.put(
+ Global.ONE_HANDED_KEYGUARD_SIDE,
+ new InclusiveIntegerRangeValidator(
+ /* first= */Global.ONE_HANDED_KEYGUARD_SIDE_LEFT,
+ /* last= */Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT));
}
}
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index 6719f179ef86..d715832dfca0 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -283,6 +283,7 @@ public class SettingsBackupTest {
Settings.Global.EUICC_REMOVING_INVISIBLE_PROFILES_TIMEOUT_MILLIS,
Settings.Global.EUICC_SWITCH_SLOT_TIMEOUT_MILLIS,
Settings.Global.FANCY_IME_ANIMATIONS,
+ Settings.Global.ONE_HANDED_KEYGUARD_SIDE,
Settings.Global.FORCE_ALLOW_ON_EXTERNAL,
Settings.Global.FORCED_APP_STANDBY_ENABLED,
Settings.Global.FORCED_APP_STANDBY_FOR_SMALL_BATTERY_ENABLED,
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index a15ceb6d8811..259484073162 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -86,6 +86,7 @@
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
<!-- TODO(b/152310230): remove once APIs are confirmed to be sufficient -->
<uses-permission android:name="com.android.permission.USE_INSTALLER_V2" />
+ <uses-permission android:name="com.android.permission.USE_SYSTEM_DATA_LOADERS" />
<uses-permission android:name="android.permission.MOVE_PACKAGE" />
<uses-permission android:name="android.permission.KEEP_UNINSTALLED_PACKAGES" />
<uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" />
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 2faca8dbdcbf..fbe58c505662 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -334,6 +334,11 @@
</intent-filter>
</receiver>
+ <activity android:name=".screenshot.LongScreenshotActivity"
+ android:theme="@android:style/Theme.DeviceDefault.NoActionBar"
+ android:process=":screenshot"
+ android:finishOnTaskLaunch="true" />
+
<activity android:name=".screenrecord.ScreenRecordDialog"
android:theme="@style/ScreenRecord"
android:showForAllUsers="true"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_bouncer.xml b/packages/SystemUI/res-keyguard/layout/keyguard_bouncer.xml
index 79868093fb12..71cdaf5c7091 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_bouncer.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_bouncer.xml
@@ -24,7 +24,7 @@
<include
style="@style/BouncerSecurityContainer"
layout="@layout/keyguard_host_view"
- android:layout_width="wrap_content"
+ android:layout_width="match_parent"
android:layout_height="wrap_content" />
</FrameLayout>
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
index f3ec39d2b1fb..b6a41c20a607 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_clock_switch.xml
@@ -64,7 +64,7 @@
android:id="@+id/new_lockscreen_clock_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_alignParentEnd="true"
+ android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:visibility="gone">
<com.android.keyguard.AnimatableClockView
@@ -73,7 +73,7 @@
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center_horizontal"
- android:textSize="100dp"
+ android:textSize="60dp"
android:fontFamily="@font/clock"
android:typeface="monospace"
android:elegantTextHeight="false"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml
index 04e645bd0a32..c75ee51517d1 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_host_view.xml
@@ -41,13 +41,14 @@
android:layout_gravity="center">
<com.android.keyguard.KeyguardSecurityViewFlipper
android:id="@+id/view_flipper"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:clipChildren="false"
android:clipToPadding="false"
android:paddingTop="@dimen/keyguard_security_view_top_margin"
android:paddingStart="@dimen/keyguard_security_view_lateral_margin"
android:paddingEnd="@dimen/keyguard_security_view_lateral_margin"
+ android:layout_gravity="center"
android:gravity="center">
</com.android.keyguard.KeyguardSecurityViewFlipper>
</com.android.keyguard.KeyguardSecurityContainer>
diff --git a/packages/SystemUI/res/drawable/toast_background.xml b/packages/SystemUI/res-keyguard/values-sw600dp-land/bools.xml
index 5c45e8346e3c..e09bf7e37ed0 100644
--- a/packages/SystemUI/res/drawable/toast_background.xml
+++ b/packages/SystemUI/res-keyguard/values-sw600dp-land/bools.xml
@@ -14,8 +14,7 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
- android:shape="rectangle">
- <solid android:color="#FFFFFFFF" />
- <corners android:radius="@dimen/toast_bg_radius" />
-</shape>
+
+<resources>
+ <bool name="can_use_one_handed_bouncer">true</bool>
+</resources>
diff --git a/packages/SystemUI/res-keyguard/values/config.xml b/packages/SystemUI/res-keyguard/values/config.xml
index 8d9d6ee68c67..6176f7c1dd0a 100644
--- a/packages/SystemUI/res-keyguard/values/config.xml
+++ b/packages/SystemUI/res-keyguard/values/config.xml
@@ -22,4 +22,5 @@
<!-- Allow the menu hard key to be disabled in LockScreen on some devices [DO NOT TRANSLATE] -->
<bool name="config_disableMenuKeyInLockScreen">false</bool>
+ <bool name="can_use_one_handed_bouncer">false</bool>
</resources>
diff --git a/packages/SystemUI/res-keyguard/values/dimens.xml b/packages/SystemUI/res-keyguard/values/dimens.xml
index 2a5784a1e6e9..115a156b65e7 100644
--- a/packages/SystemUI/res-keyguard/values/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values/dimens.xml
@@ -47,26 +47,25 @@
<dimen name="eca_overlap">-10dip</dimen>
<!-- Slice header -->
- <dimen name="widget_title_font_size">24dp</dimen>
- <dimen name="header_subtitle_padding">12dp</dimen>
+ <dimen name="widget_title_font_size">20dp</dimen>
+ <dimen name="widget_title_line_height">24dp</dimen>
<dimen name="header_icon_size">16dp</dimen>
<!-- Slice subtitle -->
- <dimen name="widget_label_font_size">18dp</dimen>
+ <dimen name="widget_label_font_size">16dp</dimen>
+ <dimen name="widget_label_line_height">20dp</dimen>
<!-- Clock without header -->
<dimen name="widget_big_font_size">54dp</dimen>
<dimen name="bottom_text_spacing_digital">0dp</dimen>
<dimen name="title_clock_padding">4dp</dimen>
<!-- Clock with header -->
<dimen name="widget_small_font_size">@dimen/widget_title_font_size</dimen>
- <dimen name="widget_vertical_padding">17dp</dimen>
+ <dimen name="widget_vertical_padding">5dp</dimen>
<dimen name="widget_vertical_padding_with_header">25dp</dimen>
<dimen name="widget_vertical_padding_clock">12dp</dimen>
<!-- Subtitle paddings -->
<dimen name="widget_horizontal_padding">8dp</dimen>
- <dimen name="widget_icon_size">20dp</dimen>
+ <dimen name="widget_icon_size">18dp</dimen>
<dimen name="widget_icon_padding">8dp</dimen>
- <dimen name="subtitle_clock_padding">0dp</dimen>
- <dimen name="header_row_font_size">14dp</dimen>
<!-- Notification shelf padding when dark -->
<dimen name="widget_bottom_separator_padding">-6dp</dimen>
diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml
index 2391803957e5..8f42cbe31646 100644
--- a/packages/SystemUI/res-keyguard/values/styles.xml
+++ b/packages/SystemUI/res-keyguard/values/styles.xml
@@ -120,6 +120,7 @@
<style name="TextAppearance.Keyguard">
<item name="android:textSize">@dimen/widget_title_font_size</item>
+ <item name="android:lineHeight">@dimen/widget_title_line_height</item>
<item name="android:gravity">center</item>
<item name="android:ellipsize">end</item>
<item name="android:maxLines">2</item>
@@ -133,6 +134,7 @@
<item name="android:layout_height">wrap_content</item>
<item name="android:lines">1</item>
<item name="android:textSize">@dimen/widget_label_font_size</item>
+ <item name="android:lineHeight">@dimen/widget_label_line_height</item>
</style>
<style name="TextAppearance.Keyguard.BottomArea">
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index a8ef7c346b95..23f34251b812 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -73,7 +73,7 @@
android:id="@+id/qs_edge_guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- systemui:layout_constraintGuide_percent="0.5"
+ systemui:layout_constraintGuide_percent="0.4"
android:orientation="vertical"/>
<com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
diff --git a/packages/SystemUI/res/layout/text_toast.xml b/packages/SystemUI/res/layout/text_toast.xml
index de4e062805fe..ad558d8053fb 100644
--- a/packages/SystemUI/res/layout/text_toast.xml
+++ b/packages/SystemUI/res/layout/text_toast.xml
@@ -20,32 +20,30 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:maxWidth="@dimen/toast_width"
android:orientation="horizontal"
- android:background="@drawable/toast_background"
- android:backgroundTint="?android:attr/colorBackground"
+ android:gravity="center_vertical"
+ android:maxWidth="@*android:dimen/toast_width"
+ android:background="@android:drawable/toast_frame"
android:layout_marginEnd="16dp"
android:layout_marginStart="16dp"
- android:gravity="center_vertical">
+ android:paddingStart="16dp"
+ android:paddingEnd="16dp">
- <!-- Icon should be 24x24, make slightly larger to allow for shadowing, adjust via padding -->
<ImageView
android:id="@+id/icon"
- android:alpha="@dimen/toast_icon_alpha"
- android:padding="11.5dp"
- android:layout_width="@dimen/toast_icon_size"
- android:layout_height="@dimen/toast_icon_size"/>
+ android:layout_width="24dp"
+ android:layout_height="24dp"
+ android:layout_marginTop="10dp"
+ android:layout_marginBottom="10dp"
+ android:layout_marginEnd="10dp"/>
<TextView
android:id="@+id/text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="2"
android:paddingTop="12dp"
android:paddingBottom="12dp"
- android:paddingStart="0dp"
- android:paddingEnd="22dp"
- android:textSize="@dimen/toast_text_size"
- android:textColor="?android:attr/textColorPrimary"
- android:fontFamily="@*android:string/config_headlineFontFamily"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
+ android:lineHeight="20sp"
+ android:textAppearance="@*android:style/TextAppearance.Toast"/>
</LinearLayout>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index 24c7655e5ae4..51d7b8eff5fc 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -52,6 +52,4 @@
<!-- (footer_height -48dp)/2 -->
<dimen name="controls_management_footer_top_margin">4dp</dimen>
<dimen name="controls_management_favorites_top_margin">8dp</dimen>
-
- <dimen name="toast_y_offset">24dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index b07df9caa95b..4bc5a300e833 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1359,11 +1359,4 @@
<dimen name="rounded_slider_icon_size">24dp</dimen>
<!-- rounded_slider_icon_size / 2 -->
<dimen name="rounded_slider_icon_inset">12dp</dimen>
-
- <dimen name="toast_width">296dp</dimen>
- <item name="toast_icon_alpha" format="float" type="dimen">1</item>
- <dimen name="toast_text_size">14sp</dimen>
- <dimen name="toast_y_offset">48dp</dimen>
- <dimen name="toast_icon_size">48dp</dimen>
- <dimen name="toast_bg_radius">28dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 3b42600076ac..70e8b8946ae6 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2717,6 +2717,9 @@
<!-- Controls dialog confirmation [CHAR LIMIT=30] -->
<string name="controls_dialog_confirmation">Controls updated</string>
+ <!-- Controls tile secondary label when device is locked and user does not want access to controls from lockscreen [CHAR LIMIT=20] -->
+ <string name="controls_tile_locked">Device locked</string>
+
<!-- Controls PIN entry dialog, switch to alphanumeric keyboard [CHAR LIMIT=100] -->
<string name="controls_pin_use_alphanumeric">PIN contains letters or symbols</string>
<!-- Controls PIN entry dialog, title [CHAR LIMIT=30] -->
diff --git a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
index 0a117c17a354..1569fff63453 100644
--- a/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/AnimatableClockController.java
@@ -21,9 +21,7 @@ import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
-import android.graphics.Paint;
import android.icu.text.NumberFormat;
-import android.util.MathUtils;
import com.android.settingslib.Utils;
import com.android.systemui.R;
@@ -94,11 +92,6 @@ public class AnimatableClockController extends ViewController<AnimatableClockVie
mStatusBarStateController.removeCallback(mStatusBarStateListener);
}
- float getClockTextTopPadding() {
- Paint.FontMetrics fm = mView.getPaint().getFontMetrics();
- return MathUtils.abs(fm.ascent - fm.top);
- }
-
/**
* Updates the time for the view.
*/
diff --git a/packages/SystemUI/src/com/android/keyguard/DisabledUdfpsController.java b/packages/SystemUI/src/com/android/keyguard/DisabledUdfpsController.java
index f01b67b7b5c2..945c9c499401 100644
--- a/packages/SystemUI/src/com/android/keyguard/DisabledUdfpsController.java
+++ b/packages/SystemUI/src/com/android/keyguard/DisabledUdfpsController.java
@@ -20,6 +20,7 @@ import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
import android.hardware.biometrics.BiometricSourceType;
import android.view.View;
+import android.view.ViewGroup;
import androidx.annotation.NonNull;
@@ -73,13 +74,15 @@ public class DisabledUdfpsController extends ViewController<DisabledUdfpsView> i
@Override
protected void onViewAttached() {
- mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
mIsBouncerShowing = mKeyguardViewController.isBouncerShowing();
-
- mStatusBarStateController.addCallback(mStatusBarStateListener);
mIsKeyguardShowing = mStatusBarStateController.getState() == StatusBarState.KEYGUARD;
mIsDozing = mStatusBarStateController.isDozing();
+ mRunningFPS = mKeyguardUpdateMonitor.isFingerprintDetectionRunning();
mAuthenticated = false;
+ updateButtonVisibility();
+
+ mKeyguardUpdateMonitor.registerCallback(mKeyguardUpdateMonitorCallback);
+ mStatusBarStateController.addCallback(mStatusBarStateListener);
}
@Override
@@ -88,6 +91,15 @@ public class DisabledUdfpsController extends ViewController<DisabledUdfpsView> i
mStatusBarStateController.removeCallback(mStatusBarStateListener);
}
+ /**
+ * Call when this controller is no longer needed. This will remove the view from its parent.
+ */
+ public void destroy() {
+ if (mView != null && mView.getParent() != null) {
+ ((ViewGroup) mView.getParent()).removeView(mView);
+ }
+ }
+
private void updateButtonVisibility() {
mShowButton = !mAuthenticated && !mIsDozing && mIsKeyguardShowing
&& !mIsBouncerShowing && !mRunningFPS;
@@ -143,6 +155,14 @@ public class DisabledUdfpsController extends ViewController<DisabledUdfpsView> i
public void onBiometricRunningStateChanged(boolean running,
BiometricSourceType biometricSourceType) {
mRunningFPS = running && biometricSourceType == FINGERPRINT;
+ mAuthenticated &= !mRunningFPS;
+ updateButtonVisibility();
+ }
+
+ @Override
+ public void onBiometricAuthenticated(int userId,
+ BiometricSourceType biometricSourceType, boolean isStrongBiometric) {
+ mAuthenticated = true;
updateButtonVisibility();
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 6eb54c25a440..93ed0eaa3fba 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -179,20 +179,15 @@ public class KeyguardClockSwitch extends RelativeLayout {
setPaddingRelative(startEndPadding, 0, startEndPadding, 0);
mSmallClockFrame.setVisibility(GONE);
mNewLockscreenClockFrame.setVisibility(VISIBLE);
-
- statusAreaLP.removeRule(RelativeLayout.BELOW);
+ statusAreaLP.addRule(RelativeLayout.BELOW, R.id.new_lockscreen_clock_view);
statusAreaLP.addRule(RelativeLayout.ALIGN_PARENT_START);
- statusAreaLP.addRule(RelativeLayout.START_OF, R.id.new_lockscreen_clock_view);
- statusAreaLP.width = 0;
} else {
setPaddingRelative(0, 0, 0, 0);
mSmallClockFrame.setVisibility(VISIBLE);
mNewLockscreenClockFrame.setVisibility(GONE);
statusAreaLP.removeRule(RelativeLayout.ALIGN_PARENT_START);
- statusAreaLP.removeRule(RelativeLayout.START_OF);
statusAreaLP.addRule(RelativeLayout.BELOW, R.id.clock_view);
- statusAreaLP.width = ViewGroup.LayoutParams.MATCH_PARENT;
}
requestLayout();
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index e375877ed6cf..0675200f81e2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -20,6 +20,7 @@ import android.app.WallpaperManager;
import android.content.ContentResolver;
import android.content.res.Resources;
import android.provider.Settings;
+import android.text.TextUtils;
import android.text.format.DateFormat;
import android.view.View;
import android.view.ViewGroup;
@@ -212,10 +213,10 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
* keep the clock centered.
*/
void updatePosition(int x, float scale, AnimationProperties props, boolean animate) {
- x = Math.abs(x);
+ x = getCurrentLayoutDirection() == View.LAYOUT_DIRECTION_RTL ? -x : x;
if (mNewLockScreenClockFrame != null) {
PropertyAnimator.setProperty(mNewLockScreenClockFrame, AnimatableProperty.TRANSLATION_X,
- -x, props, animate);
+ x, props, animate);
PropertyAnimator.setProperty(mNewLockScreenLargeClockFrame, AnimatableProperty.SCALE_X,
scale, props, animate);
PropertyAnimator.setProperty(mNewLockScreenLargeClockFrame, AnimatableProperty.SCALE_Y,
@@ -277,15 +278,6 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
refreshFormat(mTimeFormat);
}
- float getClockTextTopPadding() {
- if (mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1
- && mNewLockScreenClockViewController != null) {
- return mNewLockScreenClockViewController.getClockTextTopPadding();
- }
-
- return mView.getClockTextTopPadding();
- }
-
private void updateAodIcons() {
NotificationIconContainer nic = (NotificationIconContainer)
mView.findViewById(
@@ -337,4 +329,8 @@ public class KeyguardClockSwitchController extends ViewController<KeyguardClockS
sCacheKey = key;
}
}
+
+ private int getCurrentLayoutDirection() {
+ return TextUtils.getLayoutDirectionFromLocale(Locale.getDefault());
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
index 92b65b242b0e..533bec14f60a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardPasswordView.java
@@ -136,14 +136,23 @@ public class KeyguardPasswordView extends KeyguardAbsKeyInputView {
@Override
public void startAppearAnimation() {
- // Reset state, and let IME animation reveal the view as it slides in
+ // Reset state, and let IME animation reveal the view as it slides in, if one exists.
+ // It is possible for an IME to have no view, so provide a default animation since no
+ // calls to animateForIme would occur
setAlpha(0f);
+ animate()
+ .alpha(1f)
+ .setDuration(500)
+ .setStartDelay(300)
+ .start();
+
setTranslationY(0f);
}
@Override
public void animateForIme(float interpolatedFraction) {
- setAlpha(interpolatedFraction);
+ animate().cancel();
+ setAlpha(Math.max(interpolatedFraction, getAlpha()));
}
@Override
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
index 5f6fd30ffa1b..f511ed1c69c4 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -29,12 +29,17 @@ import android.app.AlertDialog;
import android.content.Context;
import android.graphics.Insets;
import android.graphics.Rect;
+import android.provider.Settings;
import android.util.AttributeSet;
import android.util.MathUtils;
import android.util.TypedValue;
+import android.view.Gravity;
import android.view.MotionEvent;
+import android.view.OrientationEventListener;
import android.view.VelocityTracker;
+import android.view.View;
import android.view.ViewConfiguration;
+import android.view.ViewPropertyAnimator;
import android.view.WindowInsets;
import android.view.WindowInsetsAnimation;
import android.view.WindowInsetsAnimationControlListener;
@@ -55,6 +60,7 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.stack.StackStateAnimator;
import java.util.List;
@@ -99,6 +105,12 @@ public class KeyguardSecurityContainer extends FrameLayout {
private boolean mDisappearAnimRunning;
private SwipeListener mSwipeListener;
+ private boolean mIsSecurityViewLeftAligned = true;
+ private boolean mOneHandedMode = false;
+ private SecurityMode mSecurityMode = SecurityMode.Invalid;
+ private ViewPropertyAnimator mRunningOneHandedAnimator;
+ private final OrientationEventListener mOrientationEventListener;
+
private final WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback =
new WindowInsetsAnimation.Callback(DISPATCH_MODE_STOP) {
@@ -157,16 +169,20 @@ public class KeyguardSecurityContainer extends FrameLayout {
// Used to notify the container when something interesting happens.
public interface SecurityCallback {
boolean dismiss(boolean authenticated, int targetUserId, boolean bypassSecondaryLockScreen);
+
void userActivity();
+
void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput);
/**
- * @param strongAuth wheher the user has authenticated with strong authentication like
- * pattern, password or PIN but not by trust agents or fingerprint
+ * @param strongAuth wheher the user has authenticated with strong authentication like
+ * pattern, password or PIN but not by trust agents or fingerprint
* @param targetUserId a user that needs to be the foreground user at the finish completion.
*/
void finish(boolean strongAuth, int targetUserId);
+
void reset();
+
void onCancelClicked();
}
@@ -224,12 +240,136 @@ public class KeyguardSecurityContainer extends FrameLayout {
super(context, attrs, defStyle);
mSpringAnimation = new SpringAnimation(this, DynamicAnimation.Y);
mViewConfiguration = ViewConfiguration.get(context);
+
+ mOrientationEventListener = new OrientationEventListener(context) {
+ @Override
+ public void onOrientationChanged(int orientation) {
+ updateLayoutForSecurityMode(mSecurityMode);
+ }
+ };
}
void onResume(SecurityMode securityMode, boolean faceAuthEnabled) {
+ mSecurityMode = securityMode;
mSecurityViewFlipper.setWindowInsetsAnimationCallback(mWindowInsetsAnimationCallback);
updateBiometricRetry(securityMode, faceAuthEnabled);
+ updateLayoutForSecurityMode(securityMode);
+ mOrientationEventListener.enable();
+ }
+
+ void updateLayoutForSecurityMode(SecurityMode securityMode) {
+ mSecurityMode = securityMode;
+ mOneHandedMode = canUseOneHandedBouncer();
+
+ if (mOneHandedMode) {
+ mIsSecurityViewLeftAligned = isOneHandedKeyguardLeftAligned(mContext);
+ }
+
+ updateSecurityViewGravity();
+ updateSecurityViewLocation(false);
+ }
+
+ /** Return whether the one-handed keyguard should be enabled. */
+ private boolean canUseOneHandedBouncer() {
+ // Is it enabled?
+ if (!getResources().getBoolean(
+ com.android.internal.R.bool.config_enableOneHandedKeyguard)) {
+ return false;
+ }
+
+ if (!KeyguardSecurityModel.isSecurityViewOneHanded(mSecurityMode)) {
+ return false;
+ }
+
+ return getResources().getBoolean(R.bool.can_use_one_handed_bouncer);
+ }
+
+ /** Read whether the one-handed keyguard should be on the left/right from settings. */
+ private boolean isOneHandedKeyguardLeftAligned(Context context) {
+ try {
+ return Settings.Global.getInt(context.getContentResolver(),
+ Settings.Global.ONE_HANDED_KEYGUARD_SIDE)
+ == Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT;
+ } catch (Settings.SettingNotFoundException ex) {
+ return true;
+ }
+ }
+
+ private void updateSecurityViewGravity() {
+ View securityView = findKeyguardSecurityView();
+
+ if (securityView == null) {
+ return;
+ }
+
+ FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) securityView.getLayoutParams();
+
+ if (mOneHandedMode) {
+ lp.gravity = Gravity.LEFT | Gravity.BOTTOM;
+ } else {
+ lp.gravity = Gravity.CENTER_HORIZONTAL;
+ }
+
+ securityView.setLayoutParams(lp);
+ }
+
+ /**
+ * Moves the inner security view to the correct location (in one handed mode) with animation.
+ * This is triggered when the user taps on the side of the screen that is not currently occupied
+ * by the security view .
+ */
+ private void updateSecurityViewLocation(boolean animate) {
+ View securityView = findKeyguardSecurityView();
+
+ if (securityView == null) {
+ return;
+ }
+
+ if (!mOneHandedMode) {
+ securityView.setTranslationX(0);
+ return;
+ }
+
+ if (mRunningOneHandedAnimator != null) {
+ mRunningOneHandedAnimator.cancel();
+ mRunningOneHandedAnimator = null;
+ }
+
+ int targetTranslation = mIsSecurityViewLeftAligned ? 0 : (int) (getMeasuredWidth() / 2f);
+
+ if (animate) {
+ mRunningOneHandedAnimator = securityView.animate().translationX(targetTranslation);
+ mRunningOneHandedAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+ mRunningOneHandedAnimator.setListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mRunningOneHandedAnimator = null;
+ }
+ });
+
+ mRunningOneHandedAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
+ mRunningOneHandedAnimator.start();
+ } else {
+ securityView.setTranslationX(targetTranslation);
+ }
+ }
+
+ @Nullable
+ private KeyguardSecurityViewFlipper findKeyguardSecurityView() {
+ for (int i = 0; i < getChildCount(); i++) {
+ View child = getChildAt(i);
+
+ if (isKeyguardSecurityView(child)) {
+ return (KeyguardSecurityViewFlipper) child;
+ }
+ }
+
+ return null;
+ }
+
+ private boolean isKeyguardSecurityView(View view) {
+ return view instanceof KeyguardSecurityViewFlipper;
}
public void onPause() {
@@ -238,6 +378,7 @@ public class KeyguardSecurityContainer extends FrameLayout {
mAlertDialog = null;
}
mSecurityViewFlipper.setWindowInsetsAnimationCallback(null);
+ mOrientationEventListener.disable();
}
@Override
@@ -319,19 +460,44 @@ public class KeyguardSecurityContainer extends FrameLayout {
if (mSwipeListener != null) {
mSwipeListener.onSwipeUp();
}
+ } else {
+ if (!mIsDragging) {
+ handleTap(event);
+ }
}
}
return true;
}
+ private void handleTap(MotionEvent event) {
+ // If we're using a fullscreen security mode, skip
+ if (!mOneHandedMode) {
+ return;
+ }
+
+ // Did the tap hit the "other" side of the bouncer?
+ if ((mIsSecurityViewLeftAligned && (event.getX() > getWidth() / 2f))
+ || (!mIsSecurityViewLeftAligned && (event.getX() < getWidth() / 2f))) {
+ mIsSecurityViewLeftAligned = !mIsSecurityViewLeftAligned;
+
+ Settings.Global.putInt(
+ mContext.getContentResolver(),
+ Settings.Global.ONE_HANDED_KEYGUARD_SIDE,
+ mIsSecurityViewLeftAligned ? Settings.Global.ONE_HANDED_KEYGUARD_SIDE_LEFT
+ : Settings.Global.ONE_HANDED_KEYGUARD_SIDE_RIGHT);
+
+ updateSecurityViewLocation(true);
+ }
+ }
+
void setSwipeListener(SwipeListener swipeListener) {
mSwipeListener = swipeListener;
}
private void startSpringAnimation(float startVelocity) {
mSpringAnimation
- .setStartVelocity(startVelocity)
- .animateToFinalPosition(0);
+ .setStartVelocity(startVelocity)
+ .animateToFinalPosition(0);
}
public void startDisappearAnimation(SecurityMode securitySelection) {
@@ -441,18 +607,17 @@ public class KeyguardSecurityContainer extends FrameLayout {
return insets.inset(0, 0, 0, inset);
}
-
private void showDialog(String title, String message) {
if (mAlertDialog != null) {
mAlertDialog.dismiss();
}
mAlertDialog = new AlertDialog.Builder(mContext)
- .setTitle(title)
- .setMessage(message)
- .setCancelable(false)
- .setNeutralButton(R.string.ok, null)
- .create();
+ .setTitle(title)
+ .setMessage(message)
+ .setCancelable(false)
+ .setNeutralButton(R.string.ok, null)
+ .create();
if (!(mContext instanceof Activity)) {
mAlertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
}
@@ -490,6 +655,44 @@ public class KeyguardSecurityContainer extends FrameLayout {
}
}
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int maxHeight = 0;
+ int maxWidth = 0;
+ int childState = 0;
+
+ int halfWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
+ MeasureSpec.getSize(widthMeasureSpec) / 2,
+ MeasureSpec.getMode(widthMeasureSpec));
+
+ for (int i = 0; i < getChildCount(); i++) {
+ final View view = getChildAt(i);
+ if (view.getVisibility() != GONE) {
+ if (mOneHandedMode && isKeyguardSecurityView(view)) {
+ measureChildWithMargins(view, halfWidthMeasureSpec, 0,
+ heightMeasureSpec, 0);
+ } else {
+ measureChildWithMargins(view, widthMeasureSpec, 0,
+ heightMeasureSpec, 0);
+ }
+ final LayoutParams lp = (LayoutParams) view.getLayoutParams();
+ maxWidth = Math.max(maxWidth,
+ view.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
+ maxHeight = Math.max(maxHeight,
+ view.getMeasuredHeight() + lp.topMargin + lp.bottomMargin);
+ childState = combineMeasuredStates(childState, view.getMeasuredState());
+ }
+ }
+
+ // Check against our minimum height and width
+ maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
+ maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
+
+ setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
+ resolveSizeAndState(maxHeight, heightMeasureSpec,
+ childState << MEASURED_HEIGHT_STATE_SHIFT));
+ }
+
void showAlmostAtWipeDialog(int attempts, int remaining, int userType) {
String message = null;
switch (userType) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index 1a8d420fb394..fdab8db67431 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -404,6 +404,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
if (newView != null) {
newView.onResume(KeyguardSecurityView.VIEW_REVEALED);
mSecurityViewFlipperController.show(newView);
+ mView.updateLayoutForSecurityMode(securityMode);
}
mSecurityCallback.onSecurityModeChanged(
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
index c77c86711abf..631c24844417 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityModel.java
@@ -92,4 +92,13 @@ public class KeyguardSecurityModel {
throw new IllegalStateException("Unknown security quality:" + security);
}
}
+
+ /**
+ * Returns whether the given security view should be used in a "one handed" way. This can be
+ * used to change how the security view is drawn (e.g. take up less of the screen, and align to
+ * one side).
+ */
+ public static boolean isSecurityViewOneHanded(SecurityMode securityMode) {
+ return securityMode == SecurityMode.Pattern || securityMode == SecurityMode.PIN;
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index fb97a30f93fb..2373d75cd4ea 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -85,10 +85,6 @@ public class KeyguardSliceView extends LinearLayout {
*/
private Runnable mContentChangeListener;
private boolean mHasHeader;
- private final int mRowWithHeaderPadding;
- private final int mRowPadding;
- private float mRowTextSize;
- private float mRowWithHeaderTextSize;
private View.OnClickListener mOnClickListener;
private int mLockScreenMode = KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL;
@@ -97,9 +93,6 @@ public class KeyguardSliceView extends LinearLayout {
super(context, attrs);
Resources resources = context.getResources();
- mRowPadding = resources.getDimensionPixelSize(R.dimen.subtitle_clock_padding);
- mRowWithHeaderPadding = resources.getDimensionPixelSize(R.dimen.header_subtitle_padding);
-
mLayoutTransition = new LayoutTransition();
mLayoutTransition.setStagger(LayoutTransition.CHANGE_APPEARING, DEFAULT_ANIM_DURATION / 2);
mLayoutTransition.setDuration(LayoutTransition.APPEARING, DEFAULT_ANIM_DURATION);
@@ -120,10 +113,6 @@ public class KeyguardSliceView extends LinearLayout {
mTextColor = Utils.getColorAttrDefaultColor(mContext, R.attr.wallpaperTextColor);
mIconSize = (int) mContext.getResources().getDimension(R.dimen.widget_icon_size);
mIconSizeWithHeader = (int) mContext.getResources().getDimension(R.dimen.header_icon_size);
- mRowTextSize = mContext.getResources().getDimensionPixelSize(
- R.dimen.widget_label_font_size);
- mRowWithHeaderTextSize = mContext.getResources().getDimensionPixelSize(
- R.dimen.header_row_font_size);
mTitle.setBreakStrategy(LineBreaker.BREAK_STRATEGY_BALANCED);
}
@@ -204,7 +193,6 @@ public class KeyguardSliceView extends LinearLayout {
LinearLayout.LayoutParams layoutParams = (LayoutParams) mRow.getLayoutParams();
layoutParams.gravity = mLockScreenMode != KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL
? Gravity.START : Gravity.CENTER;
- layoutParams.topMargin = mHasHeader ? mRowWithHeaderPadding : mRowPadding;
mRow.setLayoutParams(layoutParams);
for (int i = startIndex; i < subItemsCount; i++) {
@@ -230,8 +218,6 @@ public class KeyguardSliceView extends LinearLayout {
final SliceItem titleItem = rc.getTitleItem();
button.setText(titleItem == null ? null : titleItem.getText());
button.setContentDescription(rc.getContentDescription());
- button.setTextSize(TypedValue.COMPLEX_UNIT_PX,
- mHasHeader ? mRowWithHeaderTextSize : mRowTextSize);
Drawable iconDrawable = null;
SliceItem icon = SliceQuery.find(item.getSlice(),
@@ -313,10 +299,6 @@ public class KeyguardSliceView extends LinearLayout {
void onDensityOrFontScaleChanged() {
mIconSize = mContext.getResources().getDimensionPixelSize(R.dimen.widget_icon_size);
mIconSizeWithHeader = (int) mContext.getResources().getDimension(R.dimen.header_icon_size);
- mRowTextSize = mContext.getResources().getDimensionPixelSize(
- R.dimen.widget_label_font_size);
- mRowWithHeaderTextSize = mContext.getResources().getDimensionPixelSize(
- R.dimen.header_row_font_size);
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index 6fb6760be653..934e768f9ba8 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -266,15 +266,9 @@ public class KeyguardStatusViewController extends ViewController<KeyguardStatusV
mKeyguardClockSwitchController.updateLockScreenMode(mode);
mKeyguardSliceViewController.updateLockScreenMode(mode);
if (mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_LAYOUT_1) {
- // align the top of keyguard_status_area with the top of the clock text instead
- // of the top of the view
- mKeyguardSliceViewController.updateTopMargin(
- mKeyguardClockSwitchController.getClockTextTopPadding());
mView.setCanShowOwnerInfo(false);
mView.setCanShowLogout(false);
} else {
- // reset margin
- mKeyguardSliceViewController.updateTopMargin(0);
mView.setCanShowOwnerInfo(true);
mView.setCanShowLogout(false);
}
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
index d8ca63960b30..9686c91f2c31 100644
--- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
@@ -473,7 +473,8 @@ public class AppOpsControllerImpl extends BroadcastReceiver implements AppOpsCon
@Override
public void onOpNoted(int code, int uid, String packageName,
- @AppOpsManager.OpFlags int flags, @AppOpsManager.Mode int result) {
+ String attributionTag, @AppOpsManager.OpFlags int flags,
+ @AppOpsManager.Mode int result) {
if (DEBUG) {
Log.w(TAG, "Noted op: " + code + " with result "
+ AppOpsManager.MODE_NAMES[result] + " for package " + packageName);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimation.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimation.java
index 3ea8140427cb..3bf75d105b9f 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimation.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimation.java
@@ -19,8 +19,10 @@ package com.android.systemui.biometrics;
import android.content.Context;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
+import android.view.View;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import com.android.systemui.R;
@@ -33,6 +35,7 @@ public abstract class UdfpsAnimation extends Drawable {
@NonNull protected final Context mContext;
@NonNull protected final Drawable mFingerprintDrawable;
+ @Nullable private View mView;
public UdfpsAnimation(@NonNull Context context) {
mContext = context;
@@ -53,6 +56,10 @@ public abstract class UdfpsAnimation extends Drawable {
mFingerprintDrawable.setAlpha(alpha);
}
+ public void setAnimationView(UdfpsAnimationView view) {
+ mView = view;
+ }
+
/**
* @return The amount of padding that's needed on each side of the sensor, in pixels.
*/
@@ -66,4 +73,10 @@ public abstract class UdfpsAnimation extends Drawable {
public int getPaddingY() {
return 0;
}
+
+ protected void postInvalidateView() {
+ if (mView != null) {
+ mView.postInvalidate();
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationKeyguard.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationKeyguard.java
index 501de9df575b..8664e44c9ad2 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationKeyguard.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationKeyguard.java
@@ -23,7 +23,6 @@ import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.util.MathUtils;
-import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@@ -42,7 +41,6 @@ public class UdfpsAnimationKeyguard extends UdfpsAnimation implements DozeReceiv
private static final String TAG = "UdfpsAnimationKeyguard";
- @NonNull private final View mParent;
@NonNull private final Context mContext;
private final int mMaxBurnInOffsetX;
private final int mMaxBurnInOffsetY;
@@ -52,10 +50,9 @@ public class UdfpsAnimationKeyguard extends UdfpsAnimation implements DozeReceiv
private float mBurnInOffsetX;
private float mBurnInOffsetY;
- UdfpsAnimationKeyguard(@NonNull View parent, @NonNull Context context,
+ UdfpsAnimationKeyguard(@NonNull Context context,
@NonNull StatusBarStateController statusBarStateController) {
super(context);
- mParent = parent;
mContext = context;
mMaxBurnInOffsetX = context.getResources()
@@ -73,10 +70,10 @@ public class UdfpsAnimationKeyguard extends UdfpsAnimation implements DozeReceiv
mInterpolatedDarkAmount);
mBurnInOffsetY = MathUtils.lerp(0f,
getBurnInOffset(mMaxBurnInOffsetY * 2, false /* xAxis */)
- - 0.5f * mMaxBurnInOffsetY,
+ - mMaxBurnInOffsetY,
mInterpolatedDarkAmount);
updateColor();
- mParent.postInvalidate();
+ postInvalidateView();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationView.java
index 41ea4d66f575..44122cba8716 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationView.java
@@ -74,7 +74,14 @@ public class UdfpsAnimationView extends View implements DozeReceiver,
}
void setAnimation(@Nullable UdfpsAnimation animation) {
+ if (mUdfpsAnimation != null) {
+ mUdfpsAnimation.setAnimationView(null);
+ }
+
mUdfpsAnimation = animation;
+ if (mUdfpsAnimation != null) {
+ mUdfpsAnimation.setAnimationView(this);
+ }
}
void onSensorRectUpdated(@NonNull RectF sensorRect) {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index e7b08e72877d..6451ad9fd5d2 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -44,7 +44,6 @@ import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.DozeReceiver;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.util.concurrency.DelayableExecutor;
@@ -324,7 +323,7 @@ public class UdfpsController implements DozeReceiver, HbmCallback {
case IUdfpsOverlayController.REASON_ENROLL_ENROLLING:
return new UdfpsAnimationEnroll(mContext);
case IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD:
- return new UdfpsAnimationKeyguard(mView, mContext, mStatusBarStateController);
+ return new UdfpsAnimationKeyguard(mContext, mStatusBarStateController);
case IUdfpsOverlayController.REASON_AUTH_FPM_OTHER:
return new UdfpsAnimationFpmOther(mContext);
default:
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
index 00cb28b8b8fb..6ffecdba883b 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsView.java
@@ -113,6 +113,7 @@ public class UdfpsView extends FrameLayout implements DozeReceiver, UdfpsIllumin
void setExtras(@Nullable UdfpsAnimation animation, @Nullable UdfpsEnrollHelper enrollHelper) {
mAnimationView.setAnimation(animation);
+
mEnrollHelper = enrollHelper;
if (enrollHelper != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
index 36937d622b5b..6b7a1ac8cb7e 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/dagger/ControlsComponent.kt
@@ -91,7 +91,7 @@ class ControlsComponent @Inject constructor(
}
/**
- * @return true if controls are feature-enabled and have available services to serve controls
+ * @return true if controls are feature-enabled and the user has the setting enabled
*/
fun isEnabled() = featureEnabled && lazyControlsController.get().available
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java b/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
index 2b362b94d1f5..8d2639d4cdd0 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/DefaultActivityBinder.java
@@ -22,6 +22,7 @@ import com.android.systemui.ForegroundServicesDialog;
import com.android.systemui.keyguard.WorkLockActivity;
import com.android.systemui.people.PeopleSpaceActivity;
import com.android.systemui.screenrecord.ScreenRecordDialog;
+import com.android.systemui.screenshot.LongScreenshotActivity;
import com.android.systemui.settings.brightness.BrightnessDialog;
import com.android.systemui.statusbar.tv.notifications.TvNotificationPanelActivity;
import com.android.systemui.tuner.TunerActivity;
@@ -99,4 +100,10 @@ public abstract class DefaultActivityBinder {
@IntoMap
@ClassKey(PeopleSpaceActivity.class)
public abstract Activity bindPeopleSpaceActivity(PeopleSpaceActivity activity);
+
+ /** Inject into LongScreenshotActivity. */
+ @Binds
+ @IntoMap
+ @ClassKey(LongScreenshotActivity.class)
+ public abstract Activity bindLongScreenshotActivity(LongScreenshotActivity activity);
}
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 8ab135ced97e..4418696bfc9b 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -32,6 +32,7 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.doze.dagger.DozeScope;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.AlarmTimeout;
@@ -41,12 +42,15 @@ import java.util.Calendar;
import javax.inject.Inject;
+import dagger.Lazy;
+
/**
* The policy controlling doze.
*/
@DozeScope
public class DozeUi implements DozeMachine.Part, TunerService.Tunable {
-
+ // if enabled, calls dozeTimeTick() whenever the time changes:
+ private static final boolean BURN_IN_TESTING_ENABLED = false;
private static final long TIME_TICK_DEADLINE_MILLIS = 90 * 1000; // 1.5min
private final Context mContext;
private final DozeHost mHost;
@@ -57,16 +61,28 @@ public class DozeUi implements DozeMachine.Part, TunerService.Tunable {
private final boolean mCanAnimateTransition;
private final DozeParameters mDozeParameters;
private final DozeLog mDozeLog;
+ private final Lazy<StatusBarStateController> mStatusBarStateController;
private boolean mKeyguardShowing;
private final KeyguardUpdateMonitorCallback mKeyguardVisibilityCallback =
new KeyguardUpdateMonitorCallback() {
-
@Override
public void onKeyguardVisibilityChanged(boolean showing) {
mKeyguardShowing = showing;
updateAnimateScreenOff();
}
+
+ @Override
+ public void onTimeChanged() {
+ if (BURN_IN_TESTING_ENABLED && mStatusBarStateController != null
+ && mStatusBarStateController.get().isDozing()) {
+ // update whenever the time changes for manual burn in testing
+ mHost.dozeTimeTick();
+
+ // Keep wakelock until a frame has been pushed.
+ mHandler.post(mWakeLock.wrap(() -> {}));
+ }
+ }
};
private long mLastTimeTickElapsed = 0;
@@ -75,7 +91,8 @@ public class DozeUi implements DozeMachine.Part, TunerService.Tunable {
public DozeUi(Context context, AlarmManager alarmManager,
WakeLock wakeLock, DozeHost host, @Main Handler handler,
DozeParameters params, KeyguardUpdateMonitor keyguardUpdateMonitor,
- DozeLog dozeLog, TunerService tunerService) {
+ DozeLog dozeLog, TunerService tunerService,
+ Lazy<StatusBarStateController> statusBarStateController) {
mContext = context;
mWakeLock = wakeLock;
mHost = host;
@@ -85,8 +102,8 @@ public class DozeUi implements DozeMachine.Part, TunerService.Tunable {
mTimeTicker = new AlarmTimeout(alarmManager, this::onTimeTick, "doze_time_tick", handler);
keyguardUpdateMonitor.registerCallback(mKeyguardVisibilityCallback);
mDozeLog = dozeLog;
-
tunerService.addTunable(this, Settings.Secure.DOZE_ALWAYS_ON);
+ mStatusBarStateController = statusBarStateController;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
index 8110fda1330c..16e519657a41 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterViewController.java
@@ -95,7 +95,6 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme
mActivityStarter.postQSRunnableDismissingKeyguard(() -> {
if (isTunerEnabled()) {
mTunerService.showResetRequest(
- mUserTracker.getUserHandle(),
() -> {
// Relaunch settings so that the tuner disappears.
startSettingsActivity();
@@ -103,7 +102,7 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme
} else {
Toast.makeText(getContext(), R.string.tuner_toast,
Toast.LENGTH_LONG).show();
- mTunerService.setTunerEnabled(mUserTracker.getUserHandle(), true);
+ mTunerService.setTunerEnabled(true);
}
startSettingsActivity();
@@ -238,6 +237,6 @@ public class QSFooterViewController extends ViewController<QSFooterView> impleme
}
private boolean isTunerEnabled() {
- return mTunerService.isTunerEnabled(mUserTracker.getUserHandle());
+ return mTunerService.isTunerEnabled();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
index 41445917a011..3b9f5dc8ea03 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
@@ -25,7 +25,7 @@ import com.android.internal.logging.MetricsLogger
import com.android.systemui.R
import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.controls.dagger.ControlsComponent
-import com.android.systemui.controls.dagger.ControlsComponent.Visibility.UNAVAILABLE
+import com.android.systemui.controls.dagger.ControlsComponent.Visibility.AVAILABLE
import com.android.systemui.controls.management.ControlsListingController
import com.android.systemui.controls.ui.ControlsDialog
import com.android.systemui.dagger.qualifiers.Background
@@ -92,7 +92,7 @@ class DeviceControlsTile @Inject constructor(
override fun isAvailable(): Boolean {
return featureFlags.isKeyguardLayoutEnabled &&
controlsLockscreen &&
- controlsComponent.getVisibility() != UNAVAILABLE
+ controlsComponent.getControlsController().isPresent
}
override fun newTileState(): QSTile.State {
@@ -119,7 +119,7 @@ class DeviceControlsTile @Inject constructor(
}
override fun handleClick() {
- if (state.state != Tile.STATE_UNAVAILABLE) {
+ if (state.state == Tile.STATE_ACTIVE) {
mUiHandler.post {
createDialog()
controlsDialog?.show(controlsComponent.getControlsUiController().get())
@@ -129,15 +129,21 @@ class DeviceControlsTile @Inject constructor(
override fun handleUpdateState(state: QSTile.State, arg: Any?) {
state.label = tileLabel
- state.secondaryLabel = ""
- state.stateDescription = ""
+
state.contentDescription = state.label
state.icon = icon
- if (hasControlsApps.get()) {
- state.state = Tile.STATE_ACTIVE
+ if (controlsComponent.isEnabled() && hasControlsApps.get()) {
if (controlsDialog == null) {
mUiHandler.post(this::createDialog)
}
+ if (controlsComponent.getVisibility() == AVAILABLE) {
+ state.state = Tile.STATE_ACTIVE
+ state.secondaryLabel = ""
+ } else {
+ state.state = Tile.STATE_INACTIVE
+ state.secondaryLabel = mContext.getText(R.string.controls_tile_locked)
+ }
+ state.stateDescription = state.secondaryLabel
} else {
state.state = Tile.STATE_UNAVAILABLE
dismissDialog()
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
new file mode 100644
index 000000000000..a6433ae94b2b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/LongScreenshotActivity.java
@@ -0,0 +1,201 @@
+/*
+ * 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.screenshot;
+
+import android.app.Activity;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.widget.ImageView;
+
+import com.android.internal.logging.UiEventLogger;
+import com.android.systemui.R;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.dagger.qualifiers.Main;
+
+import java.util.concurrent.Executor;
+
+import javax.inject.Inject;
+
+/**
+ * LongScreenshotActivity acquires bitmap data for a long screenshot and lets the user trim the top
+ * and bottom before saving/sharing/editing.
+ */
+public class LongScreenshotActivity extends Activity {
+ private static final String TAG = "LongScreenshotActivity";
+
+ private final UiEventLogger mUiEventLogger;
+ private final ScrollCaptureController mScrollCaptureController;
+
+ private ImageView mPreview;
+ private View mSave;
+ private View mCancel;
+ private View mEdit;
+ private View mShare;
+ private CropView mCropView;
+ private MagnifierView mMagnifierView;
+
+ private enum PendingAction {
+ SHARE,
+ EDIT,
+ SAVE
+ }
+
+ @Inject
+ public LongScreenshotActivity(UiEventLogger uiEventLogger,
+ ImageExporter imageExporter,
+ @Main Executor mainExecutor,
+ @Background Executor bgExecutor,
+ Context context) {
+ mUiEventLogger = uiEventLogger;
+
+ mScrollCaptureController = new ScrollCaptureController(context,
+ ScreenshotController.sScrollConnection, mainExecutor, bgExecutor, imageExporter);
+ }
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.long_screenshot);
+
+ mPreview = findViewById(R.id.preview);
+ mSave = findViewById(R.id.save);
+ mCancel = findViewById(R.id.cancel);
+ mEdit = findViewById(R.id.edit);
+ mShare = findViewById(R.id.share);
+ mCropView = findViewById(R.id.crop_view);
+ mMagnifierView = findViewById(R.id.magnifier);
+ mCropView.setCropInteractionListener(mMagnifierView);
+
+ mSave.setOnClickListener(this::onClicked);
+ mCancel.setOnClickListener(this::onClicked);
+ mEdit.setOnClickListener(this::onClicked);
+ mShare.setOnClickListener(this::onClicked);
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ if (mPreview.getDrawable() == null) {
+ doCapture();
+ }
+ }
+
+ private void disableButtons() {
+ mSave.setEnabled(false);
+ mCancel.setEnabled(false);
+ mEdit.setEnabled(false);
+ mShare.setEnabled(false);
+ }
+
+ private void doEdit(Uri uri) {
+ String editorPackage = getString(R.string.config_screenshotEditor);
+ Intent intent = new Intent(Intent.ACTION_EDIT);
+ if (!TextUtils.isEmpty(editorPackage)) {
+ intent.setComponent(ComponentName.unflattenFromString(editorPackage));
+ }
+ intent.setType("image/png");
+ intent.setData(uri);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
+ | Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
+ startActivityAsUser(intent, UserHandle.CURRENT);
+ finishAndRemoveTask();
+ }
+
+ private void doShare(Uri uri) {
+ Intent intent = new Intent(Intent.ACTION_SEND);
+ intent.setType("image/png");
+ intent.setData(uri);
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
+ | Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ Intent sharingChooserIntent = Intent.createChooser(intent, null)
+ .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ startActivityAsUser(sharingChooserIntent, UserHandle.CURRENT);
+ }
+
+ private void onClicked(View v) {
+ int id = v.getId();
+ v.setPressed(true);
+ disableButtons();
+ if (id == R.id.save) {
+ startExport(PendingAction.SAVE);
+ } else if (id == R.id.cancel) {
+ finishAndRemoveTask();
+ } else if (id == R.id.edit) {
+ mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_EDIT);
+ startExport(PendingAction.EDIT);
+ } else if (id == R.id.share) {
+ mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_SHARE);
+ startExport(PendingAction.SHARE);
+ }
+ }
+
+ private void startExport(PendingAction action) {
+ mScrollCaptureController.startExport(mCropView.getTopBoundary(),
+ mCropView.getBottomBoundary(), new ScrollCaptureController.ExportCallback() {
+ @Override
+ public void onError() {
+ Log.e(TAG, "Error exporting image data.");
+ }
+
+ @Override
+ public void onExportComplete(Uri outputUri) {
+ switch (action) {
+ case EDIT:
+ doEdit(outputUri);
+ break;
+ case SHARE:
+ doShare(outputUri);
+ break;
+ case SAVE:
+ // Nothing more to do
+ finishAndRemoveTask();
+ break;
+ }
+ }
+ });
+ }
+
+ private void doCapture() {
+ mScrollCaptureController.start(new ScrollCaptureController.ScrollCaptureCallback() {
+ @Override
+ public void onError() {
+ Log.e(TAG, "Error!");
+ finishAndRemoveTask();
+ }
+
+ @Override
+ public void onComplete(ImageTileSet imageTileSet) {
+ Log.i(TAG, "Got tiles " + imageTileSet.getWidth() + " x "
+ + imageTileSet.getHeight());
+ mPreview.setImageDrawable(imageTileSet.getDrawable());
+ mMagnifierView.setImageTileset(imageTileSet);
+ mCropView.animateBoundaryTo(CropView.CropBoundary.BOTTOM, 0.5f);
+ }
+ });
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
index 953b40b6e17b..31c693bdde1f 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScreenshotController.java
@@ -41,6 +41,7 @@ import android.app.Notification;
import android.app.WindowContext;
import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.Insets;
@@ -100,6 +101,8 @@ import javax.inject.Inject;
public class ScreenshotController {
private static final String TAG = logTag(ScreenshotController.class);
+ public static ScrollCaptureClient.Connection sScrollConnection;
+
/**
* POD used in the AsyncTask which saves an image in the background.
*/
@@ -597,21 +600,12 @@ public class ScreenshotController {
}
private void runScrollCapture(ScrollCaptureClient.Connection connection) {
- cancelTimeout();
- ScrollCaptureController controller = new ScrollCaptureController(mContext, connection,
- mMainExecutor, mBgExecutor, mImageExporter, mUiEventLogger);
- controller.attach(mWindow);
- controller.start(new TakeScreenshotService.RequestCallback() {
- @Override
- public void reportError() {
- }
+ sScrollConnection = connection; // For LongScreenshotActivity to pick up.
- @Override
- public void onFinish() {
- Log.d(TAG, "onFinish from ScrollCaptureController");
- finishDismiss();
- }
- });
+ Intent intent = new Intent(mContext, LongScreenshotActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ mContext.startActivity(intent);
+ dismissScreenshot(false);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java
index ad5e637b189e..863116a22ee4 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/ScrollCaptureController.java
@@ -16,29 +16,16 @@
package com.android.systemui.screenshot;
-import android.annotation.IdRes;
import android.annotation.UiThread;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
import android.graphics.Rect;
import android.net.Uri;
-import android.os.UserHandle;
import android.provider.Settings;
-import android.text.TextUtils;
import android.util.Log;
-import android.view.View;
-import android.view.ViewTreeObserver.InternalInsetsInfo;
-import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
-import android.view.Window;
-import android.widget.ImageView;
-
-import com.android.internal.logging.UiEventLogger;
-import com.android.systemui.R;
+
import com.android.systemui.screenshot.ScrollCaptureClient.CaptureResult;
import com.android.systemui.screenshot.ScrollCaptureClient.Connection;
import com.android.systemui.screenshot.ScrollCaptureClient.Session;
-import com.android.systemui.screenshot.TakeScreenshotService.RequestCallback;
import com.google.common.util.concurrent.ListenableFuture;
@@ -50,7 +37,7 @@ import java.util.concurrent.Executor;
/**
* Interaction controller between the UI and ScrollCaptureClient.
*/
-public class ScrollCaptureController implements OnComputeInternalInsetsListener {
+public class ScrollCaptureController {
private static final String TAG = "ScrollCaptureController";
private static final float MAX_PAGES_DEFAULT = 3f;
@@ -64,13 +51,6 @@ public class ScrollCaptureController implements OnComputeInternalInsetsListener
private boolean mAtTopEdge;
private Session mSession;
- // TODO: Support saving without additional action.
- private enum PendingAction {
- SHARE,
- EDIT,
- SAVE
- }
-
public static final int MAX_HEIGHT = 12000;
private final Connection mConnection;
@@ -80,172 +60,59 @@ public class ScrollCaptureController implements OnComputeInternalInsetsListener
private final Executor mBgExecutor;
private final ImageExporter mImageExporter;
private final ImageTileSet mImageTileSet;
- private final UiEventLogger mUiEventLogger;
private ZonedDateTime mCaptureTime;
private UUID mRequestId;
- private RequestCallback mCallback;
- private Window mWindow;
- private ImageView mPreview;
- private View mSave;
- private View mCancel;
- private View mEdit;
- private View mShare;
- private CropView mCropView;
- private MagnifierView mMagnifierView;
+ private ScrollCaptureCallback mCaptureCallback;
public ScrollCaptureController(Context context, Connection connection, Executor uiExecutor,
- Executor bgExecutor, ImageExporter exporter, UiEventLogger uiEventLogger) {
+ Executor bgExecutor, ImageExporter exporter) {
mContext = context;
mConnection = connection;
mUiExecutor = uiExecutor;
mBgExecutor = bgExecutor;
mImageExporter = exporter;
- mUiEventLogger = uiEventLogger;
mImageTileSet = new ImageTileSet(context.getMainThreadHandler());
}
/**
- * @param window the window to display the preview
- */
- public void attach(Window window) {
- mWindow = window;
- }
-
- /**
* Run scroll capture!
*
* @param callback request callback to report back to the service
*/
- public void start(RequestCallback callback) {
+ public void start(ScrollCaptureCallback callback) {
mCaptureTime = ZonedDateTime.now();
mRequestId = UUID.randomUUID();
- mCallback = callback;
-
- setContentView(R.layout.long_screenshot);
- mWindow.getDecorView().getViewTreeObserver()
- .addOnComputeInternalInsetsListener(this);
- mPreview = findViewById(R.id.preview);
-
- mSave = findViewById(R.id.save);
- mCancel = findViewById(R.id.cancel);
- mEdit = findViewById(R.id.edit);
- mShare = findViewById(R.id.share);
- mCropView = findViewById(R.id.crop_view);
- mMagnifierView = findViewById(R.id.magnifier);
- mCropView.setCropInteractionListener(mMagnifierView);
-
- mSave.setOnClickListener(this::onClicked);
- mCancel.setOnClickListener(this::onClicked);
- mEdit.setOnClickListener(this::onClicked);
- mShare.setOnClickListener(this::onClicked);
+ mCaptureCallback = callback;
float maxPages = Settings.Secure.getFloat(mContext.getContentResolver(),
SETTING_KEY_MAX_PAGES, MAX_PAGES_DEFAULT);
mConnection.start(this::startCapture, maxPages);
}
-
- /** Ensure the entire window is touchable */
- public void onComputeInternalInsets(InternalInsetsInfo inoutInfo) {
- inoutInfo.setTouchableInsets(InternalInsetsInfo.TOUCHABLE_INSETS_FRAME);
- }
-
- void disableButtons() {
- mSave.setEnabled(false);
- mCancel.setEnabled(false);
- mEdit.setEnabled(false);
- mShare.setEnabled(false);
- }
-
- private void onClicked(View v) {
- Log.d(TAG, "button clicked!");
-
- int id = v.getId();
- v.setPressed(true);
- disableButtons();
- if (id == R.id.save) {
- startExport(PendingAction.SAVE);
- } else if (id == R.id.cancel) {
- doFinish();
- } else if (id == R.id.edit) {
- mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_EDIT);
- startExport(PendingAction.EDIT);
- } else if (id == R.id.share) {
- mUiEventLogger.log(ScreenshotEvent.SCREENSHOT_LONG_SCREENSHOT_SHARE);
- startExport(PendingAction.SHARE);
- }
- }
-
- private void doFinish() {
- mPreview.setImageDrawable(null);
- mMagnifierView.setImageTileset(null);
- mImageTileSet.clear();
- mCallback.onFinish();
- mWindow.getDecorView().getViewTreeObserver()
- .removeOnComputeInternalInsetsListener(this);
- }
-
- private void startExport(PendingAction action) {
+ /**
+ * @param topCrop [0,1) fraction of the top of the image to be cropped out.
+ * @param bottomCrop (0, 1] fraction to be cropped out, e.g. 0.7 will crop out the bottom 30%.
+ */
+ public void startExport(float topCrop, float bottomCrop, ExportCallback callback) {
Rect croppedPortion = new Rect(
0,
- (int) (mImageTileSet.getHeight() * mCropView.getTopBoundary()),
+ (int) (mImageTileSet.getHeight() * topCrop),
mImageTileSet.getWidth(),
- (int) (mImageTileSet.getHeight() * mCropView.getBottomBoundary()));
+ (int) (mImageTileSet.getHeight() * bottomCrop));
ListenableFuture<ImageExporter.Result> exportFuture = mImageExporter.export(
mBgExecutor, mRequestId, mImageTileSet.toBitmap(croppedPortion), mCaptureTime);
exportFuture.addListener(() -> {
try {
ImageExporter.Result result = exportFuture.get();
- if (action == PendingAction.EDIT) {
- doEdit(result.uri);
- } else if (action == PendingAction.SHARE) {
- doShare(result.uri);
- }
- doFinish();
+ callback.onExportComplete(result.uri);
} catch (InterruptedException | ExecutionException e) {
Log.e(TAG, "failed to export", e);
- mCallback.onFinish();
+ callback.onError();
}
}, mUiExecutor);
}
- private void doEdit(Uri uri) {
- String editorPackage = mContext.getString(R.string.config_screenshotEditor);
- Intent intent = new Intent(Intent.ACTION_EDIT);
- if (!TextUtils.isEmpty(editorPackage)) {
- intent.setComponent(ComponentName.unflattenFromString(editorPackage));
- }
- intent.setType("image/png");
- intent.setData(uri);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
- | Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-
- mContext.startActivityAsUser(intent, UserHandle.CURRENT);
- }
-
- private void doShare(Uri uri) {
- Intent intent = new Intent(Intent.ACTION_SEND);
- intent.setType("image/png");
- intent.setData(uri);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK
- | Intent.FLAG_GRANT_READ_URI_PERMISSION);
- Intent sharingChooserIntent = Intent.createChooser(intent, null)
- .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK
- | Intent.FLAG_GRANT_READ_URI_PERMISSION);
-
- mContext.startActivityAsUser(sharingChooserIntent, UserHandle.CURRENT);
- }
-
- private void setContentView(@IdRes int id) {
- mWindow.setContentView(id);
- }
-
- <T extends View> T findViewById(@IdRes int res) {
- return mWindow.findViewById(res);
- }
-
-
private void onCaptureResult(CaptureResult result) {
Log.d(TAG, "onCaptureResult: " + result);
boolean emptyResult = result.captured.height() == 0;
@@ -327,11 +194,26 @@ public class ScrollCaptureController implements OnComputeInternalInsetsListener
Log.d(TAG, "afterCaptureComplete");
if (mImageTileSet.isEmpty()) {
- session.end(mCallback::onFinish);
+ mCaptureCallback.onError();
} else {
- mPreview.setImageDrawable(mImageTileSet.getDrawable());
- mMagnifierView.setImageTileset(mImageTileSet);
- mCropView.animateBoundaryTo(CropView.CropBoundary.BOTTOM, 0.5f);
+ mCaptureCallback.onComplete(mImageTileSet);
}
}
+
+ /**
+ * Callback for image capture completion or error.
+ */
+ public interface ScrollCaptureCallback {
+ void onComplete(ImageTileSet imageTileSet);
+ void onError();
+ }
+
+ /**
+ * Callback for image export completion or error.
+ */
+ public interface ExportCallback {
+ void onExportComplete(Uri outputUri);
+ void onError();
+ }
+
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 20efa32d63c6..d2ddd212bda6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -1002,10 +1002,6 @@ public class NotificationShelf extends ActivatableNotificationView implements
return false;
}
- public void onUiModeChanged() {
- updateBackgroundColors();
- }
-
public void setController(NotificationShelfController notificationShelfController) {
mController = notificationShelfController;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
index 73c7fd1b64a3..f21771a89c9e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFilter.java
@@ -128,15 +128,6 @@ public class NotificationFilter {
// this is a foreground-service disclosure for a user that does not need to show one
return true;
}
- if (getFsc().isSystemAlertNotification(sbn)) {
- final String[] apps = sbn.getNotification().extras.getStringArray(
- Notification.EXTRA_FOREGROUND_APPS);
- if (apps != null && apps.length >= 1) {
- if (!getFsc().isSystemAlertWarningNeeded(sbn.getUserId(), apps[0])) {
- return true;
- }
- }
- }
if (mIsMediaFlagEnabled && isMediaNotification(sbn)) {
return true;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java
index 998ae9e55313..3a87f6853bcf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java
@@ -95,18 +95,6 @@ public class AppOpsCoordinator implements Coordinator {
sbn.getUser().getIdentifier())) {
return true;
}
-
- // Filters out system alert notifications when unneeded
- if (mForegroundServiceController.isSystemAlertNotification(sbn)) {
- final String[] apps = sbn.getNotification().extras.getStringArray(
- Notification.EXTRA_FOREGROUND_APPS);
- if (apps != null && apps.length >= 1) {
- if (!mForegroundServiceController.isSystemAlertWarningNeeded(
- sbn.getUser().getIdentifier(), apps[0])) {
- return true;
- }
- }
- }
return false;
}
};
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 724921b3f7c8..31d052d75998 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
@@ -191,7 +191,10 @@ public abstract class ActivatableNotificationView extends ExpandableOutlineView
initDimens();
}
- protected void updateBackgroundColors() {
+ /**
+ * Reload background colors from resources and invalidate views.
+ */
+ public void updateBackgroundColors() {
updateColors();
initBackground();
updateBackgroundTint();
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 2c7c5cc91120..417ff5e9aed0 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
@@ -21,6 +21,7 @@ import static com.android.systemui.statusbar.notification.ActivityLaunchAnimator
import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_SILENT;
import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_SWIPE;
import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
+import static com.android.systemui.util.Utils.shouldUseSplitNotificationShade;
import static java.lang.annotation.RetentionPolicy.SOURCE;
@@ -83,6 +84,7 @@ import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.DragDownHelper.DragDownCallback;
import com.android.systemui.statusbar.EmptyShadeView;
+import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.NotificationShelfController;
@@ -453,6 +455,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
private NotificationEntry mTopHeadsUpEntry;
private long mNumHeadsUp;
private NotificationStackScrollLayoutController.TouchHandler mTouchHandler;
+ private final FeatureFlags mFeatureFlags;
private final ExpandableView.OnHeightChangedListener mOnChildHeightChangedListener =
new ExpandableView.OnHeightChangedListener() {
@@ -492,8 +495,8 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
GroupMembershipManager groupMembershipManager,
GroupExpansionManager groupExpansionManager,
SysuiStatusBarStateController statusbarStateController,
- AmbientState ambientState
- ) {
+ AmbientState ambientState,
+ FeatureFlags featureFlags) {
super(context, attrs, 0, 0);
Resources res = getResources();
mSectionsManager = notificationSectionsManager;
@@ -530,6 +533,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
mGroupMembershipManager = groupMembershipManager;
mGroupExpansionManager = groupExpansionManager;
mStatusbarStateController = statusbarStateController;
+ mFeatureFlags = featureFlags;
}
void initializeForegroundServiceSection(ForegroundServiceDungeonView fgsSectionView) {
@@ -622,7 +626,12 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
mBgColor = Utils.getColorAttr(mContext, android.R.attr.colorBackgroundFloating)
.getDefaultColor();
updateBackgroundDimming();
- mShelf.onUiModeChanged();
+ for (int i = 0; i < getChildCount(); i++) {
+ View child = getChildAt(i);
+ if (child instanceof ActivatableNotificationView) {
+ ((ActivatableNotificationView) child).updateBackgroundColors();
+ }
+ }
}
@ShadeViewRefactor(RefactorComponent.DECORATOR)
@@ -1156,8 +1165,13 @@ public class NotificationStackScrollLayout extends ViewGroup implements Dumpable
if (stackStartPosition <= stackEndPosition) {
stackHeight = stackEndPosition;
} else {
- stackHeight = (int) NotificationUtils.interpolate(stackStartPosition,
- stackEndPosition, mQsExpansionFraction);
+ if (shouldUseSplitNotificationShade(mFeatureFlags, getResources())) {
+ // This prevents notifications from being collapsed when QS is expanded.
+ stackHeight = (int) height;
+ } else {
+ stackHeight = (int) NotificationUtils.interpolate(stackStartPosition,
+ stackEndPosition, mQsExpansionFraction);
+ }
}
} else {
stackHeight = (int) height;
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 a51674280c1c..399702869d70 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
@@ -223,6 +223,7 @@ public class NotificationStackScrollLayoutController {
updateShowEmptyShadeView();
mView.updateCornerRadius();
mView.updateBgColor();
+ mView.updateDecorViews();
mView.reinflateViews();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
index 8cdaa63994e4..f4830fbb0028 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceController.java
@@ -134,7 +134,7 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
mStackScrollerController = stackScrollerController;
mNotificationPanelViewController = notificationPanelViewController;
notificationPanelViewController.addTrackingHeadsUpListener(mSetTrackingHeadsUp);
- notificationPanelViewController.addVerticalTranslationListener(mUpdatePanelTranslation);
+ notificationPanelViewController.setVerticalTranslationListener(mUpdatePanelTranslation);
notificationPanelViewController.setHeadsUpAppearanceController(this);
mStackScrollerController.addOnExpandedHeightChangedListener(mSetExpandedHeight);
mStackScrollerController.addOnLayoutChangeListener(mStackScrollLayoutChangeListener);
@@ -171,7 +171,7 @@ public class HeadsUpAppearanceController implements OnHeadsUpChangedListener,
mHeadsUpStatusBarView.setOnDrawingRectChangedListener(null);
mWakeUpCoordinator.removeListener(this);
mNotificationPanelViewController.removeTrackingHeadsUpListener(mSetTrackingHeadsUp);
- mNotificationPanelViewController.removeVerticalTranslationListener(mUpdatePanelTranslation);
+ mNotificationPanelViewController.setVerticalTranslationListener(null);
mNotificationPanelViewController.setHeadsUpAppearanceController(null);
mStackScrollerController.removeOnExpandedHeightChangedListener(mSetExpandedHeight);
mStackScrollerController.removeOnLayoutChangeListener(mStackScrollLayoutChangeListener);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index a6daed5a0850..2ce403764c7d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -344,8 +344,11 @@ public class KeyguardClockPositionAlgorithm {
}
private float burnInPreventionOffsetX() {
- return getBurnInOffset(mBurnInPreventionOffsetX * 2, true /* xAxis */)
- - mBurnInPreventionOffsetX;
+ if (mLockScreenMode == KeyguardUpdateMonitor.LOCK_SCREEN_MODE_NORMAL) {
+ return getBurnInOffset(mBurnInPreventionOffsetX * 2, true /* xAxis */)
+ - mBurnInPreventionOffsetX;
+ }
+ return getBurnInOffset(mBurnInPreventionOffsetX, true /* xAxis */);
}
public static class Result {
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 0b3fd161d865..6940050f754b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -196,7 +196,8 @@ public class NotificationPanelViewController extends PanelViewController {
new MyOnHeadsUpChangedListener();
private final HeightListener mHeightListener = new HeightListener();
private final ConfigurationListener mConfigurationListener = new ConfigurationListener();
- private final StatusBarStateListener mStatusBarStateListener = new StatusBarStateListener();
+ @VisibleForTesting final StatusBarStateListener mStatusBarStateListener =
+ new StatusBarStateListener();
private final ExpansionCallback mExpansionCallback = new ExpansionCallback();
private final BiometricUnlockController mBiometricUnlockController;
private final NotificationPanelView mView;
@@ -280,18 +281,8 @@ public class NotificationPanelViewController extends PanelViewController {
@Override
public void onKeyguardVisibilityChanged(boolean showing) {
- if (mDisabledUdfpsController == null
- && mAuthController.getUdfpsRegion() != null
- && mAuthController.isUdfpsEnrolled(
- KeyguardUpdateMonitor.getCurrentUser())) {
- mLayoutInflater.inflate(R.layout.disabled_udfps_view, mView);
- mDisabledUdfpsController = new DisabledUdfpsController(
- mView.findViewById(R.id.disabled_udfps_view),
- mStatusBarStateController,
- mUpdateMonitor,
- mAuthController,
- mStatusBarKeyguardViewManager);
- mDisabledUdfpsController.init();
+ if (showing) {
+ updateDisabledUdfpsController();
}
}
};
@@ -473,7 +464,7 @@ public class NotificationPanelViewController extends PanelViewController {
private ArrayList<Consumer<ExpandableNotificationRow>>
mTrackingHeadsUpListeners =
new ArrayList<>();
- private ArrayList<Runnable> mVerticalTranslationListener = new ArrayList<>();
+ private Runnable mVerticalTranslationListener;
private HeadsUpAppearanceController mHeadsUpAppearanceController;
private int mPanelAlpha;
@@ -867,25 +858,16 @@ public class NotificationPanelViewController extends PanelViewController {
public void updateResources() {
int qsWidth = mResources.getDimensionPixelSize(R.dimen.qs_panel_width);
- ViewGroup.LayoutParams lp = mQsFrame.getLayoutParams();
- if (lp.width != qsWidth) {
- lp.width = qsWidth;
- mQsFrame.setLayoutParams(lp);
- }
-
int panelWidth = mResources.getDimensionPixelSize(R.dimen.notification_panel_width);
- lp = mNotificationStackScrollLayoutController.getLayoutParams();
- if (lp.width != panelWidth) {
- lp.width = panelWidth;
- mNotificationStackScrollLayoutController.setLayoutParams(lp);
- }
- // In order to change the constraints at runtime, all children of the Constraint Layout
- // must have ids.
+ // To change the constraints at runtime, all children of the ConstraintLayout must have ids
ensureAllViewsHaveIds(mNotificationContainerParent);
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(mNotificationContainerParent);
if (Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources)) {
+ // width = 0 to take up all available space within constraints
+ qsWidth = 0;
+ panelWidth = 0;
constraintSet.connect(R.id.qs_frame, END, R.id.qs_edge_guideline, END);
constraintSet.connect(
R.id.notification_stack_scroller, START,
@@ -894,6 +876,8 @@ public class NotificationPanelViewController extends PanelViewController {
constraintSet.connect(R.id.qs_frame, END, PARENT_ID, END);
constraintSet.connect(R.id.notification_stack_scroller, START, PARENT_ID, START);
}
+ constraintSet.getConstraint(R.id.notification_stack_scroller).layout.mWidth = panelWidth;
+ constraintSet.getConstraint(R.id.qs_frame).layout.mWidth = qsWidth;
constraintSet.applyTo(mNotificationContainerParent);
}
@@ -1852,7 +1836,7 @@ public class NotificationPanelViewController extends PanelViewController {
}
}
- private void setQsExpanded(boolean expanded) {
+ @VisibleForTesting void setQsExpanded(boolean expanded) {
boolean changed = mQsExpanded != expanded;
if (changed) {
mQsExpanded = expanded;
@@ -1955,8 +1939,10 @@ public class NotificationPanelViewController extends PanelViewController {
private void updateQsState() {
mNotificationStackScrollLayoutController.setQsExpanded(mQsExpanded);
mNotificationStackScrollLayoutController.setScrollingEnabled(
- mBarState != KEYGUARD && (!mQsExpanded
- || mQsExpansionFromOverscroll));
+ mBarState != KEYGUARD
+ && (!mQsExpanded
+ || mQsExpansionFromOverscroll
+ || Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources)));
if (mKeyguardUserSwitcherController != null && mQsExpanded
&& !mStackScrollerOverscrolling) {
@@ -2236,13 +2222,16 @@ public class NotificationPanelViewController extends PanelViewController {
@Override
protected boolean canCollapsePanelOnTouch() {
- if (!isInSettings()) {
- return mBarState == KEYGUARD
- || mIsPanelCollapseOnQQS
- || mNotificationStackScrollLayoutController.isScrolledToBottom();
- } else {
+ if (!isInSettings() && mBarState == KEYGUARD) {
return true;
}
+
+ if (mNotificationStackScrollLayoutController.isScrolledToBottom()) {
+ return true;
+ }
+
+ return !Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources)
+ && (isInSettings() || mIsPanelCollapseOnQQS);
}
@Override
@@ -2920,7 +2909,8 @@ public class NotificationPanelViewController extends PanelViewController {
* @param x the x-coordinate the touch event
*/
protected void updateHorizontalPanelPosition(float x) {
- if (mNotificationStackScrollLayoutController.getWidth() * 1.75f > mView.getWidth()) {
+ if (mNotificationStackScrollLayoutController.getWidth() * 1.75f > mView.getWidth()
+ || Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources)) {
resetHorizontalPanelPosition();
return;
}
@@ -2948,9 +2938,8 @@ public class NotificationPanelViewController extends PanelViewController {
protected void setHorizontalPanelTranslation(float translation) {
mNotificationStackScrollLayoutController.setTranslationX(translation);
mQsFrame.setTranslationX(translation);
- int size = mVerticalTranslationListener.size();
- for (int i = 0; i < size; i++) {
- mVerticalTranslationListener.get(i).run();
+ if (mVerticalTranslationListener != null) {
+ mVerticalTranslationListener.run();
}
}
@@ -3243,12 +3232,8 @@ public class NotificationPanelViewController extends PanelViewController {
mTrackingHeadsUpListeners.remove(listener);
}
- public void addVerticalTranslationListener(Runnable verticalTranslationListener) {
- mVerticalTranslationListener.add(verticalTranslationListener);
- }
-
- public void removeVerticalTranslationListener(Runnable verticalTranslationListener) {
- mVerticalTranslationListener.remove(verticalTranslationListener);
+ public void setVerticalTranslationListener(Runnable verticalTranslationListener) {
+ mVerticalTranslationListener = verticalTranslationListener;
}
public void setHeadsUpAppearanceController(
@@ -3566,6 +3551,25 @@ public class NotificationPanelViewController extends PanelViewController {
}
}
+ private void updateDisabledUdfpsController() {
+ final boolean udfpsEnrolled = mAuthController.getUdfpsRegion() != null
+ && mAuthController.isUdfpsEnrolled(
+ KeyguardUpdateMonitor.getCurrentUser());
+ if (mDisabledUdfpsController == null && udfpsEnrolled) {
+ mLayoutInflater.inflate(R.layout.disabled_udfps_view, mView);
+ mDisabledUdfpsController = new DisabledUdfpsController(
+ mView.findViewById(R.id.disabled_udfps_view),
+ mStatusBarStateController,
+ mUpdateMonitor,
+ mAuthController,
+ mStatusBarKeyguardViewManager);
+ mDisabledUdfpsController.init();
+ } else if (mDisabledUdfpsController != null && !udfpsEnrolled) {
+ mDisabledUdfpsController.destroy();
+ mDisabledUdfpsController = null;
+ }
+ }
+
private class OnHeightChangedListener implements ExpandableView.OnHeightChangedListener {
@Override
public void onHeightChanged(ExpandableView view, boolean needsAnimation) {
@@ -3615,6 +3619,10 @@ public class NotificationPanelViewController extends PanelViewController {
NotificationStackScrollLayout.OnOverscrollTopChangedListener {
@Override
public void onOverscrollTopChanged(float amount, boolean isRubberbanded) {
+ // When in split shade, overscroll shouldn't carry through to QS
+ if (Utils.shouldUseSplitNotificationShade(mFeatureFlags, mResources)) {
+ return;
+ }
cancelQsAnimation();
if (!mQsExpansionEnabled) {
amount = 0f;
@@ -3981,6 +3989,7 @@ public class NotificationPanelViewController extends PanelViewController {
FragmentHostManager.get(mView).addTagListener(QS.TAG, mFragmentListener);
mStatusBarStateController.addCallback(mStatusBarStateListener);
mConfigurationController.addCallback(mConfigurationListener);
+ updateDisabledUdfpsController();
mUpdateMonitor.registerCallback(mKeyguardUpdateCallback);
// Theme might have changed between inflating this view and attaching it to the
// window, so
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
index e394ebc65a6b..0c9ed661925c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
@@ -18,14 +18,12 @@ package com.android.systemui.statusbar.phone;
import android.app.Fragment;
import android.content.Context;
-import android.content.res.Configuration;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;
import android.view.WindowInsets;
import android.widget.FrameLayout;
-import androidx.annotation.DimenRes;
import androidx.constraintlayout.widget.ConstraintLayout;
import com.android.systemui.R;
@@ -83,22 +81,6 @@ public class NotificationsQuickSettingsContainer extends ConstraintLayout
}
@Override
- protected void onConfigurationChanged(Configuration newConfig) {
- super.onConfigurationChanged(newConfig);
- reloadWidth(mQsFrame, R.dimen.qs_panel_width);
- reloadWidth(mStackScroller, R.dimen.notification_panel_width);
- }
-
- /**
- * Loads the given width resource and sets it on the given View.
- */
- private void reloadWidth(View view, @DimenRes int width) {
- LayoutParams params = (LayoutParams) view.getLayoutParams();
- params.width = getResources().getDimensionPixelSize(width);
- view.setLayoutParams(params);
- }
-
- @Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
mBottomPadding = insets.getStableInsetBottom();
setPadding(0, 0, 0, mBottomPadding);
diff --git a/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java b/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java
index 365cd2a5d20b..fab1655b1262 100644
--- a/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java
+++ b/packages/SystemUI/src/com/android/systemui/toast/SystemUIToast.java
@@ -187,10 +187,7 @@ public class SystemUIToast implements ToastPlugin.Toast {
mPluginToast.onOrientationChange(orientation);
}
- mDefaultY = mContext.getResources().getDimensionPixelSize(
- mToastStyleEnabled
- ? com.android.systemui.R.dimen.toast_y_offset
- : R.dimen.toast_y_offset);
+ mDefaultY = mContext.getResources().getDimensionPixelSize(R.dimen.toast_y_offset);
mDefaultGravity =
mContext.getResources().getInteger(R.integer.config_toastDefaultGravity);
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
index 78341edefbb2..5b66216f41be 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerActivity.java
@@ -43,11 +43,13 @@ public class TunerActivity extends Activity implements
private static final String TAG_TUNER = "tuner";
private final DemoModeController mDemoModeController;
+ private final TunerService mTunerService;
@Inject
- TunerActivity(DemoModeController demoModeController) {
+ TunerActivity(DemoModeController demoModeController, TunerService tunerService) {
super();
mDemoModeController = demoModeController;
+ mTunerService = tunerService;
}
protected void onCreate(Bundle savedInstanceState) {
@@ -67,7 +69,7 @@ public class TunerActivity extends Activity implements
"com.android.settings.action.DEMO_MODE");
final PreferenceFragment fragment = showDemoMode
? new DemoModeFragment(mDemoModeController)
- : new TunerFragment();
+ : new TunerFragment(mTunerService);
getFragmentManager().beginTransaction().replace(R.id.content_frame,
fragment, TAG_TUNER).commit();
}
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
index 4c724aeea9ae..989462a9fd34 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerFragment.java
@@ -15,7 +15,7 @@
*/
package com.android.systemui.tuner;
-import android.app.ActivityManager;
+import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
@@ -23,7 +23,6 @@ import android.content.DialogInterface;
import android.hardware.display.AmbientDisplayConfiguration;
import android.os.Build;
import android.os.Bundle;
-import android.os.UserHandle;
import android.provider.Settings;
import android.view.Menu;
import android.view.MenuInflater;
@@ -56,6 +55,15 @@ public class TunerFragment extends PreferenceFragment {
private static final int MENU_REMOVE = Menu.FIRST + 1;
+ private final TunerService mTunerService;
+
+ // We are the only ones who ever call this constructor, so don't worry about the warning
+ @SuppressLint("ValidFragment")
+ public TunerFragment(TunerService tunerService) {
+ super();
+ mTunerService = tunerService;
+ }
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -124,13 +132,9 @@ public class TunerFragment extends PreferenceFragment {
getActivity().finish();
return true;
case MENU_REMOVE:
- UserHandle user = new UserHandle(ActivityManager.getCurrentUser());
- TunerService.showResetRequest(getContext(), user, new Runnable() {
- @Override
- public void run() {
- if (getActivity() != null) {
- getActivity().finish();
- }
+ mTunerService.showResetRequest(() -> {
+ if (getActivity() != null) {
+ getActivity().finish();
}
});
return true;
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
index b67574d1c4de..5d09e064604a 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerService.java
@@ -15,19 +15,10 @@
package com.android.systemui.tuner;
import android.content.BroadcastReceiver;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.DialogInterface;
-import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.os.UserHandle;
-import android.provider.Settings;
import com.android.systemui.Dependency;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.phone.SystemUIDialog;
public abstract class TunerService {
@@ -47,6 +38,16 @@ public abstract class TunerService {
public abstract void addTunable(Tunable tunable, String... keys);
public abstract void removeTunable(Tunable tunable);
+ /**
+ * Sets the state of the {@link TunerActivity} component for the current user
+ */
+ public abstract void setTunerEnabled(boolean enabled);
+
+ /**
+ * Returns true if the tuner is enabled for the current user.
+ */
+ public abstract boolean isTunerEnabled();
+
public interface Tunable {
void onTuningChanged(String key, String newValue);
}
@@ -55,38 +56,6 @@ public abstract class TunerService {
mContext = context;
}
- private static Context userContext(Context context, UserHandle user) {
- try {
- return context.createPackageContextAsUser(context.getPackageName(), 0, user);
- } catch (NameNotFoundException e) {
- return context;
- }
- }
-
- /** Enables or disables the tuner for the supplied user. */
- public void setTunerEnabled(UserHandle user, boolean enabled) {
- setTunerEnabled(mContext, user, enabled);
- }
-
- public static final void setTunerEnabled(Context context, UserHandle user, boolean enabled) {
- userContext(context, user).getPackageManager().setComponentEnabledSetting(
- new ComponentName(context, TunerActivity.class),
- enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
- : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
- PackageManager.DONT_KILL_APP);
- }
-
- /** Returns true if the tuner is enabled for the supplied user. */
- public boolean isTunerEnabled(UserHandle user) {
- return isTunerEnabled(mContext, user);
- }
-
- public static final boolean isTunerEnabled(Context context, UserHandle user) {
- return userContext(context, user).getPackageManager().getComponentEnabledSetting(
- new ComponentName(context, TunerActivity.class))
- == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
- }
-
public static class ClearReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
@@ -97,35 +66,7 @@ public abstract class TunerService {
}
/** */
- public void showResetRequest(UserHandle user, final Runnable onDisabled) {
- showResetRequest(mContext, user, onDisabled);
- }
-
- public static final void showResetRequest(final Context context, UserHandle user,
- final Runnable onDisabled) {
- SystemUIDialog dialog = new SystemUIDialog(context);
- dialog.setShowForAllUsers(true);
- dialog.setMessage(R.string.remove_from_settings_prompt);
- dialog.setButton(DialogInterface.BUTTON_NEGATIVE, context.getString(R.string.cancel),
- (OnClickListener) null);
- dialog.setButton(DialogInterface.BUTTON_POSITIVE,
- context.getString(R.string.guest_exit_guest_dialog_remove), new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- // Tell the tuner (in main SysUI process) to clear all its settings.
- context.sendBroadcast(new Intent(TunerService.ACTION_CLEAR));
- // Disable access to tuner.
- TunerService.setTunerEnabled(context, user, false);
- // Make them sit through the warning dialog again.
- Settings.Secure.putInt(context.getContentResolver(),
- TunerFragment.SETTING_SEEN_TUNER_WARNING, 0);
- if (onDisabled != null) {
- onDisabled.run();
- }
- }
- });
- dialog.show();
- }
+ public abstract void showResetRequest(Runnable onDisabled);
public static boolean parseIntegerSwitch(String value, boolean defaultValue) {
try {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
index 027c282ba352..e9e4380859b7 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
@@ -15,8 +15,12 @@
*/
package com.android.systemui.tuner;
+import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.database.ContentObserver;
import android.net.Uri;
@@ -32,13 +36,14 @@ import android.util.ArraySet;
import com.android.internal.util.ArrayUtils;
import com.android.systemui.DejankUtils;
-import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.R;
import com.android.systemui.dagger.SysUISingleton;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.demomode.DemoModeController;
import com.android.systemui.qs.QSTileHost;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.util.leak.LeakDetector;
import java.util.HashSet;
@@ -83,6 +88,7 @@ public class TunerServiceImpl extends TunerService {
private int mCurrentUser;
private UserTracker.Callback mCurrentUserTracker;
private UserTracker mUserTracker;
+ private final ComponentName mTunerComponent;
/**
*/
@@ -92,7 +98,6 @@ public class TunerServiceImpl extends TunerService {
@Main Handler mainHandler,
LeakDetector leakDetector,
DemoModeController demoModeController,
- BroadcastDispatcher broadcastDispatcher,
UserTracker userTracker) {
super(context);
mContext = context;
@@ -100,6 +105,7 @@ public class TunerServiceImpl extends TunerService {
mLeakDetector = leakDetector;
mDemoModeController = demoModeController;
mUserTracker = userTracker;
+ mTunerComponent = new ComponentName(mContext, TunerActivity.class);
for (UserInfo user : UserManager.get(mContext).getUsers()) {
mCurrentUser = user.getUserHandle().getIdentifier();
@@ -142,7 +148,7 @@ public class TunerServiceImpl extends TunerService {
}
}
if (oldVersion < 2) {
- setTunerEnabled(mContext, mUserTracker.getUserHandle(), false);
+ setTunerEnabled(false);
}
// 3 Removed because of a revert.
if (oldVersion < 4) {
@@ -269,6 +275,46 @@ public class TunerServiceImpl extends TunerService {
}
}
+
+ @Override
+ public void setTunerEnabled(boolean enabled) {
+ mUserTracker.getUserContext().getPackageManager().setComponentEnabledSetting(
+ mTunerComponent,
+ enabled ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+ : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+ PackageManager.DONT_KILL_APP
+ );
+ }
+
+ @Override
+ public boolean isTunerEnabled() {
+ return mUserTracker.getUserContext().getPackageManager().getComponentEnabledSetting(
+ mTunerComponent) == PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+ }
+
+ @Override
+ public void showResetRequest(Runnable onDisabled) {
+ SystemUIDialog dialog = new SystemUIDialog(mContext);
+ dialog.setShowForAllUsers(true);
+ dialog.setMessage(R.string.remove_from_settings_prompt);
+ dialog.setButton(DialogInterface.BUTTON_NEGATIVE, mContext.getString(R.string.cancel),
+ (DialogInterface.OnClickListener) null);
+ dialog.setButton(DialogInterface.BUTTON_POSITIVE,
+ mContext.getString(R.string.guest_exit_guest_dialog_remove), (d, which) -> {
+ // Tell the tuner (in main SysUI process) to clear all its settings.
+ mContext.sendBroadcast(new Intent(TunerService.ACTION_CLEAR));
+ // Disable access to tuner.
+ setTunerEnabled(false);
+ // Make them sit through the warning dialog again.
+ Secure.putInt(mContext.getContentResolver(),
+ TunerFragment.SETTING_SEEN_TUNER_WARNING, 0);
+ if (onDisabled != null) {
+ onDisabled.run();
+ }
+ });
+ dialog.show();
+ }
+
private class Observer extends ContentObserver {
public Observer() {
super(new Handler(Looper.getMainLooper()));
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
index 854be1f76722..14b4d0262f60 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerTest.java
@@ -26,11 +26,16 @@ import static org.mockito.Mockito.when;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
+import android.testing.TestableResources;
+import android.view.View;
+import android.view.ViewGroup;
import android.view.WindowInsetsController;
+import android.widget.FrameLayout;
import androidx.test.filters.SmallTest;
import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
+import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import org.junit.Before;
@@ -45,12 +50,21 @@ import org.mockito.junit.MockitoRule;
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper()
public class KeyguardSecurityContainerTest extends SysuiTestCase {
+ private static final int SCREEN_WIDTH = 1600;
+ private static final int FAKE_MEASURE_SPEC =
+ View.MeasureSpec.makeMeasureSpec(SCREEN_WIDTH, View.MeasureSpec.EXACTLY);
+
+ private static final SecurityMode ONE_HANDED_SECURITY_MODE = SecurityMode.PIN;
+ private static final SecurityMode TWO_HANDED_SECURITY_MODE = SecurityMode.Password;
+
+
@Rule
public MockitoRule mRule = MockitoJUnit.rule();
@Mock
private WindowInsetsController mWindowInsetsController;
+
@Mock
private KeyguardSecurityViewFlipper mSecurityViewFlipper;
@@ -58,9 +72,18 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
@Before
public void setup() {
+ // Needed here, otherwise when mKeyguardSecurityContainer is created below, it'll cache
+ // the real references (rather than the TestableResources that this call creates).
+ mContext.ensureTestableResources();
+ FrameLayout.LayoutParams securityViewFlipperLayoutParams = new FrameLayout.LayoutParams(
+ ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+
when(mSecurityViewFlipper.getWindowInsetsController()).thenReturn(mWindowInsetsController);
+ when(mSecurityViewFlipper.getLayoutParams()).thenReturn(securityViewFlipperLayoutParams);
mKeyguardSecurityContainer = new KeyguardSecurityContainer(getContext());
mKeyguardSecurityContainer.mSecurityViewFlipper = mSecurityViewFlipper;
+ mKeyguardSecurityContainer.addView(mSecurityViewFlipper, new ViewGroup.LayoutParams(
+ ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
}
@Test
@@ -69,4 +92,75 @@ public class KeyguardSecurityContainerTest extends SysuiTestCase {
verify(mWindowInsetsController).controlWindowInsetsAnimation(eq(ime()), anyLong(), any(),
any(), any());
}
-} \ No newline at end of file
+
+ @Test
+ public void onMeasure_usesFullWidthWithoutOneHandedMode() {
+ setUpKeyguard(
+ /* deviceConfigCanUseOneHandedKeyguard= */false,
+ /* sysuiResourceCanUseOneHandedKeyguard= */ false,
+ ONE_HANDED_SECURITY_MODE);
+
+ mKeyguardSecurityContainer.onMeasure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
+
+ verify(mSecurityViewFlipper).measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
+ }
+
+ @Test
+ public void onMeasure_usesFullWidthWithDeviceFlagDisabled() {
+ setUpKeyguard(
+ /* deviceConfigCanUseOneHandedKeyguard= */false,
+ /* sysuiResourceCanUseOneHandedKeyguard= */ true,
+ ONE_HANDED_SECURITY_MODE);
+
+ mKeyguardSecurityContainer.onMeasure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
+ verify(mSecurityViewFlipper).measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
+ }
+
+ @Test
+ public void onMeasure_usesFullWidthWithSysUIFlagDisabled() {
+ setUpKeyguard(
+ /* deviceConfigCanUseOneHandedKeyguard= */true,
+ /* sysuiResourceCanUseOneHandedKeyguard= */ false,
+ ONE_HANDED_SECURITY_MODE);
+
+ mKeyguardSecurityContainer.onMeasure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
+ verify(mSecurityViewFlipper).measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
+ }
+
+ @Test
+ public void onMeasure_usesHalfWidthWithFlagsEnabled() {
+ setUpKeyguard(
+ /* deviceConfigCanUseOneHandedKeyguard= */true,
+ /* sysuiResourceCanUseOneHandedKeyguard= */ true,
+ ONE_HANDED_SECURITY_MODE);
+
+ int halfWidthMeasureSpec =
+ View.MeasureSpec.makeMeasureSpec(SCREEN_WIDTH / 2, View.MeasureSpec.EXACTLY);
+ mKeyguardSecurityContainer.onMeasure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
+
+ verify(mSecurityViewFlipper).measure(halfWidthMeasureSpec, FAKE_MEASURE_SPEC);
+ }
+
+ @Test
+ public void onMeasure_usesFullWidthForFullScreenIme() {
+ setUpKeyguard(
+ /* deviceConfigCanUseOneHandedKeyguard= */true,
+ /* sysuiResourceCanUseOneHandedKeyguard= */ true,
+ TWO_HANDED_SECURITY_MODE);
+
+ mKeyguardSecurityContainer.onMeasure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
+ verify(mSecurityViewFlipper).measure(FAKE_MEASURE_SPEC, FAKE_MEASURE_SPEC);
+ }
+
+ private void setUpKeyguard(
+ boolean deviceConfigCanUseOneHandedKeyguard,
+ boolean sysuiResourceCanUseOneHandedKeyguard,
+ SecurityMode securityMode) {
+ TestableResources testableResources = mContext.getOrCreateTestableResources();
+ testableResources.addOverride(com.android.internal.R.bool.config_enableOneHandedKeyguard,
+ deviceConfigCanUseOneHandedKeyguard);
+ testableResources.addOverride(R.bool.can_use_one_handed_bouncer,
+ sysuiResourceCanUseOneHandedKeyguard);
+ mKeyguardSecurityContainer.updateLayoutForSecurityMode(securityMode);
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
index 6c3b37edbd15..ba21afdfab0f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
@@ -309,17 +309,6 @@ public class ForegroundServiceControllerTest extends SysuiTestCase {
}
@Test
- public void testOverlayPredicate() {
- StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, "com.example.app1",
- 5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
- StatusBarNotification sbn_user1_overlay = makeMockSBN(USERID_ONE, "android",
- 0, "AlertWindowNotification", Notification.FLAG_NO_CLEAR);
-
- assertTrue(mFsc.isSystemAlertNotification(sbn_user1_overlay));
- assertFalse(mFsc.isSystemAlertNotification(sbn_user1_app1));
- }
-
- @Test
public void testNoNotifsNorAppOps_noSystemAlertWarningRequired() {
// no notifications nor app op signals that this package/userId requires system alert
// warning
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java b/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java
index 0c69ffdef372..e1ddaada44cf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java
@@ -43,6 +43,7 @@ import android.view.SurfaceHolder;
import com.android.systemui.glwallpaper.ImageWallpaperRenderer;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -53,6 +54,7 @@ import java.util.concurrent.CountDownLatch;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
+@Ignore
public class ImageWallpaperTest extends SysuiTestCase {
private static final int LOW_BMP_WIDTH = 128;
private static final int LOW_BMP_HEIGHT = 128;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
index bc322f7f18fc..97cb8736f01c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
@@ -69,6 +69,7 @@ import java.util.List;
@TestableLooper.RunWithLooper
public class AppOpsControllerTest extends SysuiTestCase {
private static final String TEST_PACKAGE_NAME = "test";
+ private static final String TEST_ATTRIBUTION_NAME = "attribution";
private static final int TEST_UID = UserHandle.getUid(0, 0);
private static final int TEST_UID_OTHER = UserHandle.getUid(1, 0);
private static final int TEST_UID_NON_USER_SENSITIVE = UserHandle.getUid(2, 0);
@@ -164,7 +165,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
mController.onOpActiveChanged(
AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
- AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
+ TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
mTestableLooper.processAllMessages();
verify(mCallback).onActiveStateChanged(AppOpsManager.OP_RECORD_AUDIO,
TEST_UID, TEST_PACKAGE_NAME, true);
@@ -218,8 +219,8 @@ public class AppOpsControllerTest extends SysuiTestCase {
mController.onOpActiveChanged(AppOpsManager.OP_CAMERA,
TEST_UID, TEST_PACKAGE_NAME, true);
mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION,
- TEST_UID, TEST_PACKAGE_NAME, AppOpsManager.OP_FLAG_SELF,
- AppOpsManager.MODE_ALLOWED);
+ TEST_UID, TEST_PACKAGE_NAME, TEST_ATTRIBUTION_NAME,
+ AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
assertEquals(3, mController.getActiveAppOps().size());
}
@@ -230,8 +231,8 @@ public class AppOpsControllerTest extends SysuiTestCase {
mController.onOpActiveChanged(AppOpsManager.OP_CAMERA,
TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION,
- TEST_UID, TEST_PACKAGE_NAME, AppOpsManager.OP_FLAG_SELF,
- AppOpsManager.MODE_ALLOWED);
+ TEST_UID, TEST_PACKAGE_NAME, TEST_ATTRIBUTION_NAME,
+ AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
assertEquals(2,
mController.getActiveAppOpsForUser(UserHandle.getUserId(TEST_UID)).size());
assertEquals(1,
@@ -262,7 +263,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
public void opNotedScheduledForRemoval() {
mController.setBGHandler(mMockHandler);
mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
- AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
+ TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
verify(mMockHandler).scheduleRemoval(any(AppOpItem.class), anyLong());
}
@@ -274,7 +275,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
mController.onOpActiveChanged(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
true);
mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
- AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
+ TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
assertFalse(mController.getActiveAppOps().isEmpty());
mController.setListening(false);
@@ -288,9 +289,9 @@ public class AppOpsControllerTest extends SysuiTestCase {
mController.setBGHandler(mMockHandler);
mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
- AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
+ TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
- AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
+ TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
// Only one post to notify subscribers
verify(mMockHandler, times(1)).post(any());
@@ -304,9 +305,9 @@ public class AppOpsControllerTest extends SysuiTestCase {
mController.setBGHandler(mMockHandler);
mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
- AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
+ TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
- AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
+ TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
// Only one post to notify subscribers
verify(mMockHandler, times(2)).scheduleRemoval(any(), anyLong());
@@ -324,7 +325,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
- AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
+ TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
// Check that we "scheduled" the removal. Don't actually schedule until we are ready to
// process messages at a later time.
@@ -353,7 +354,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
mController.addCallback(new int[]{AppOpsManager.OP_FINE_LOCATION}, mCallback);
mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
- AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
+ TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
mController.onOpActiveChanged(
AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
@@ -382,7 +383,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
mController.addCallback(new int[]{AppOpsManager.OP_FINE_LOCATION}, mCallback);
mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
- AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
+ TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
mController.onOpActiveChanged(
AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
@@ -400,7 +401,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME, true);
mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
- AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
+ TEST_ATTRIBUTION_NAME, AppOpsManager.OP_FLAG_SELF, AppOpsManager.MODE_ALLOWED);
mTestableLooper.processAllMessages();
verify(mCallback).onActiveStateChanged(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java
index d60772730dff..afe5c0b2edbd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeUiTest.java
@@ -41,6 +41,7 @@ import androidx.test.runner.AndroidJUnit4;
import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.phone.DozeParameters;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.util.wakelock.WakeLockFake;
@@ -74,6 +75,8 @@ public class DozeUiTest extends SysuiTestCase {
private Handler mHandler;
private HandlerThread mHandlerThread;
private DozeUi mDozeUi;
+ @Mock
+ private StatusBarStateController mStatusBarStateController;
@Before
public void setUp() throws Exception {
@@ -85,7 +88,8 @@ public class DozeUiTest extends SysuiTestCase {
mHandler = mHandlerThread.getThreadHandler();
mDozeUi = new DozeUi(mContext, mAlarmManager, mWakeLock, mHost, mHandler,
- mDozeParameters, mKeyguardUpdateMonitor, mDozeLog, mTunerService);
+ mDozeParameters, mKeyguardUpdateMonitor, mDozeLog, mTunerService,
+ () -> mStatusBarStateController);
mDozeUi.setDozeMachine(mMachine);
}
@@ -141,7 +145,8 @@ public class DozeUiTest extends SysuiTestCase {
reset(mHost);
when(mDozeParameters.getDisplayNeedsBlanking()).thenReturn(true);
mDozeUi = new DozeUi(mContext, mAlarmManager, mWakeLock, mHost, mHandler,
- mDozeParameters, mKeyguardUpdateMonitor, mDozeLog, mTunerService);
+ mDozeParameters, mKeyguardUpdateMonitor, mDozeLog, mTunerService,
+ () -> mStatusBarStateController);
mDozeUi.setDozeMachine(mMachine);
// Never animate if display doesn't support it.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/EglHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/EglHelperTest.java
index e23507b0a895..a3221b58e937 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/EglHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/EglHelperTest.java
@@ -50,6 +50,7 @@ import org.mockito.Spy;
@SmallTest
@RunWith(AndroidTestingRunner.class)
+@Ignore
public class EglHelperTest extends SysuiTestCase {
@Spy
diff --git a/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/ImageWallpaperRendererTest.java b/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/ImageWallpaperRendererTest.java
index 24f3eb27579a..510b90722650 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/ImageWallpaperRendererTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/glwallpaper/ImageWallpaperRendererTest.java
@@ -33,6 +33,7 @@ import androidx.test.filters.SmallTest;
import com.android.systemui.SysuiTestCase;
import org.junit.Before;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -43,6 +44,7 @@ import java.util.Set;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
+@Ignore
public class ImageWallpaperRendererTest extends SysuiTestCase {
private WallpaperManager mWpmSpy;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
index d3dbe2bf7d2b..ccd9548b269f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
@@ -25,7 +25,6 @@ import androidx.lifecycle.LifecycleOwner
import androidx.test.filters.SmallTest
import com.android.internal.logging.MetricsLogger
import com.android.internal.logging.UiEventLogger
-import com.android.internal.widget.LockPatternUtils
import com.android.systemui.SysuiTestCase
import com.android.systemui.controls.ControlsServiceInfo
import com.android.systemui.controls.controller.ControlsController
@@ -37,9 +36,7 @@ import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.qs.QSHost
import com.android.systemui.qs.logging.QSLogger
-import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.FeatureFlags
-import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.capture
import com.android.systemui.util.settings.FakeSettings
@@ -49,7 +46,6 @@ import com.google.common.truth.Truth.assertThat
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.Answers
import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
@@ -57,6 +53,7 @@ import org.mockito.Mockito.`when`
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
+import java.util.Optional
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -73,6 +70,7 @@ class DeviceControlsTileTest : SysuiTestCase() {
private lateinit var activityStarter: ActivityStarter
@Mock
private lateinit var qsLogger: QSLogger
+ @Mock
private lateinit var controlsComponent: ControlsComponent
@Mock
private lateinit var controlsUiController: ControlsUiController
@@ -96,54 +94,64 @@ class DeviceControlsTileTest : SysuiTestCase() {
private lateinit var testableLooper: TestableLooper
private lateinit var tile: DeviceControlsTile
- @Mock
- private lateinit var keyguardStateController: KeyguardStateController
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private lateinit var userTracker: UserTracker
- @Mock
- private lateinit var lockPatternUtils: LockPatternUtils
- @Mock
private lateinit var secureSettings: SecureSettings
+ private var featureEnabled = true
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
testableLooper = TestableLooper.get(this)
+ secureSettings = FakeSettings()
`when`(qsHost.context).thenReturn(mContext)
`when`(qsHost.uiEventLogger).thenReturn(uiEventLogger)
+ `when`(controlsController.available).thenReturn(true)
+ `when`(controlsComponent.isEnabled()).thenReturn(true)
+ secureSettings.putInt(Settings.Secure.POWER_MENU_LOCKED_SHOW_CONTENT, 1)
- controlsComponent = ControlsComponent(
- true,
- mContext,
- { controlsController },
- { controlsUiController },
- { controlsListingController },
- lockPatternUtils,
- keyguardStateController,
- userTracker,
- secureSettings
- )
+ setupControlsComponent()
globalSettings = FakeSettings()
globalSettings.putInt(DeviceControlsTile.SETTINGS_FLAG, 1)
`when`(featureFlags.isKeyguardLayoutEnabled).thenReturn(true)
- `when`(userTracker.userHandle.identifier).thenReturn(0)
-
tile = createTile()
}
+ private fun setupControlsComponent() {
+ `when`(controlsComponent.getControlsController()).thenAnswer {
+ if (featureEnabled) {
+ Optional.of(controlsController)
+ } else {
+ Optional.empty()
+ }
+ }
+
+ `when`(controlsComponent.getControlsListingController()).thenAnswer {
+ if (featureEnabled) {
+ Optional.of(controlsListingController)
+ } else {
+ Optional.empty()
+ }
+ }
+
+ `when`(controlsComponent.getControlsUiController()).thenAnswer {
+ if (featureEnabled) {
+ Optional.of(controlsUiController)
+ } else {
+ Optional.empty()
+ }
+ }
+ }
+
@Test
fun testAvailable() {
- `when`(controlsController.available).thenReturn(true)
assertThat(tile.isAvailable).isTrue()
}
@Test
fun testNotAvailableFeature() {
- `when`(controlsController.available).thenReturn(true)
`when`(featureFlags.isKeyguardLayoutEnabled).thenReturn(false)
assertThat(tile.isAvailable).isFalse()
@@ -151,24 +159,22 @@ class DeviceControlsTileTest : SysuiTestCase() {
@Test
fun testNotAvailableControls() {
- controlsComponent = ControlsComponent(
- false,
- mContext,
- { controlsController },
- { controlsUiController },
- { controlsListingController },
- lockPatternUtils,
- keyguardStateController,
- userTracker,
- secureSettings
- )
+ featureEnabled = false
tile = createTile()
assertThat(tile.isAvailable).isFalse()
}
@Test
- fun testNotAvailableFlag() {
+ fun testAvailableControlsSettingOff() {
+ `when`(controlsController.available).thenReturn(false)
+
+ tile = createTile()
+ assertThat(tile.isAvailable).isTrue()
+ }
+
+ @Test
+ fun testNotAvailableControlsLockscreenFlag() {
globalSettings.putInt(DeviceControlsTile.SETTINGS_FLAG, 0)
tile = createTile()
@@ -207,11 +213,26 @@ class DeviceControlsTileTest : SysuiTestCase() {
}
@Test
+ fun testStateUnavailableIfNotEnabled() {
+ verify(controlsListingController).observe(
+ any(LifecycleOwner::class.java),
+ capture(listingCallbackCaptor)
+ )
+ `when`(controlsComponent.isEnabled()).thenReturn(false)
+
+ listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo))
+ testableLooper.processAllMessages()
+
+ assertThat(tile.state.state).isEqualTo(Tile.STATE_UNAVAILABLE)
+ }
+
+ @Test
fun testStateAvailableIfListings() {
verify(controlsListingController).observe(
any(LifecycleOwner::class.java),
capture(listingCallbackCaptor)
)
+ `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE)
listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo))
testableLooper.processAllMessages()
@@ -220,6 +241,21 @@ class DeviceControlsTileTest : SysuiTestCase() {
}
@Test
+ fun testStateInactiveIfLocked() {
+ verify(controlsListingController).observe(
+ any(LifecycleOwner::class.java),
+ capture(listingCallbackCaptor)
+ )
+ `when`(controlsComponent.getVisibility())
+ .thenReturn(ControlsComponent.Visibility.AVAILABLE_AFTER_UNLOCK)
+
+ listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo))
+ testableLooper.processAllMessages()
+
+ assertThat(tile.state.state).isEqualTo(Tile.STATE_INACTIVE)
+ }
+
+ @Test
fun testMoveBetweenStates() {
verify(controlsListingController).observe(
any(LifecycleOwner::class.java),
@@ -249,6 +285,7 @@ class DeviceControlsTileTest : SysuiTestCase() {
any(LifecycleOwner::class.java),
capture(listingCallbackCaptor)
)
+ `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE)
listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo))
testableLooper.processAllMessages()
@@ -260,6 +297,24 @@ class DeviceControlsTileTest : SysuiTestCase() {
}
@Test
+ fun testNoDialogWhenInactive() {
+ verify(controlsListingController).observe(
+ any(LifecycleOwner::class.java),
+ capture(listingCallbackCaptor)
+ )
+ `when`(controlsComponent.getVisibility())
+ .thenReturn(ControlsComponent.Visibility.AVAILABLE_AFTER_UNLOCK)
+
+ listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo))
+ testableLooper.processAllMessages()
+
+ tile.click()
+ testableLooper.processAllMessages()
+
+ verify(controlsDialog, never()).show(any(ControlsUiController::class.java))
+ }
+
+ @Test
fun testDialogDismissedOnDestroy() {
verify(controlsListingController).observe(
any(LifecycleOwner::class.java),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
index 05cf33a3729c..b493b9a6bd65 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
@@ -171,62 +171,10 @@ public class NotificationFilterTest extends SysuiTestCase {
}
@Test
- public void testSuppressSystemAlertNotification() {
- when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(false);
- when(mFsc.isSystemAlertNotification(any())).thenReturn(true);
- StatusBarNotification sbn = mRow.getEntry().getSbn();
- Bundle bundle = new Bundle();
- bundle.putStringArray(Notification.EXTRA_FOREGROUND_APPS, new String[]{"something"});
- sbn.getNotification().extras = bundle;
-
- assertTrue(mNotificationFilter.shouldFilterOut(mRow.getEntry()));
- }
-
- @Test
- public void testDoNotSuppressSystemAlertNotification() {
- StatusBarNotification sbn = mRow.getEntry().getSbn();
- Bundle bundle = new Bundle();
- bundle.putStringArray(Notification.EXTRA_FOREGROUND_APPS, new String[]{"something"});
- sbn.getNotification().extras = bundle;
-
- when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(true);
- when(mFsc.isSystemAlertNotification(any())).thenReturn(true);
-
- assertFalse(mNotificationFilter.shouldFilterOut(mRow.getEntry()));
-
- when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(true);
- when(mFsc.isSystemAlertNotification(any())).thenReturn(false);
-
- assertFalse(mNotificationFilter.shouldFilterOut(mRow.getEntry()));
-
- when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(false);
- when(mFsc.isSystemAlertNotification(any())).thenReturn(false);
-
- assertFalse(mNotificationFilter.shouldFilterOut(mRow.getEntry()));
- }
-
- @Test
- public void testDoNotSuppressMalformedSystemAlertNotification() {
- when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(true);
-
- // missing extra
- assertFalse(mNotificationFilter.shouldFilterOut(mRow.getEntry()));
-
- StatusBarNotification sbn = mRow.getEntry().getSbn();
- Bundle bundle = new Bundle();
- bundle.putStringArray(Notification.EXTRA_FOREGROUND_APPS, new String[]{});
- sbn.getNotification().extras = bundle;
-
- // extra missing values
- assertFalse(mNotificationFilter.shouldFilterOut(mRow.getEntry()));
- }
-
- @Test
public void testShouldFilterHiddenNotifications() {
initStatusBarNotification(false);
// setup
when(mFsc.isSystemAlertWarningNeeded(anyInt(), anyString())).thenReturn(false);
- when(mFsc.isSystemAlertNotification(any())).thenReturn(false);
// test should filter out hidden notifications:
// hidden
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java
index 09546216183f..278456859735 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinatorTest.java
@@ -115,41 +115,6 @@ public class AppOpsCoordinatorTest extends SysuiTestCase {
}
@Test
- public void filterTest_systemAlertNotificationUnnecessary() {
- // GIVEN the alert notification isn't needed for this user
- final Bundle extras = new Bundle();
- extras.putStringArray(Notification.EXTRA_FOREGROUND_APPS,
- new String[]{TEST_PKG});
- mEntryBuilder.modifyNotification(mContext)
- .setExtras(extras);
- NotificationEntry entry = mEntryBuilder.build();
- StatusBarNotification sbn = entry.getSbn();
- when(mForegroundServiceController.isSystemAlertWarningNeeded(sbn.getUserId(), TEST_PKG))
- .thenReturn(false);
-
- // GIVEN the notification is a system alert notification + not a disclosure notification
- when(mForegroundServiceController.isSystemAlertNotification(sbn)).thenReturn(true);
- when(mForegroundServiceController.isDisclosureNotification(sbn)).thenReturn(false);
-
-
- // THEN filter out the notification
- assertTrue(mForegroundFilter.shouldFilterOut(entry, 0));
- }
-
- @Test
- public void filterTest_doNotFilter() {
- NotificationEntry entry = mEntryBuilder.build();
- StatusBarNotification sbn = entry.getSbn();
-
- // GIVEN the notification isn't a system alert notification nor a disclosure notification
- when(mForegroundServiceController.isSystemAlertNotification(sbn)).thenReturn(false);
- when(mForegroundServiceController.isDisclosureNotification(sbn)).thenReturn(false);
-
- // THEN don't filter out the notification
- assertFalse(mForegroundFilter.shouldFilterOut(entry, 0));
- }
-
- @Test
public void testIncludeFGSInSection_importanceDefault() {
// GIVEN the notification represents a colorized foreground service with > min importance
mEntryBuilder
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 461f64eda6e5..84fb3689b0b0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -21,6 +21,8 @@ import static android.provider.Settings.Secure.NOTIFICATION_HISTORY_ENABLED;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_ALL;
import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_GENTLE;
+import static com.google.common.truth.Truth.assertWithMessage;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
@@ -49,6 +51,7 @@ import com.android.systemui.ExpandHelper;
import com.android.systemui.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.EmptyShadeView;
+import com.android.systemui.statusbar.FeatureFlags;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationShelf;
import com.android.systemui.statusbar.NotificationShelfController;
@@ -101,6 +104,7 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
@Mock private SysuiStatusBarStateController mStatusBarStateController;
@Mock private NotificationSwipeHelper mNotificationSwipeHelper;
@Mock private NotificationStackScrollLayoutController mStackScrollLayoutController;
+ @Mock private FeatureFlags mFeatureFlags;
@Before
@UiThreadTest
@@ -139,8 +143,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
mGroupMembershipManger,
mGroupExpansionManager,
mStatusBarStateController,
- mAmbientState
- );
+ mAmbientState,
+ mFeatureFlags);
mStackScrollerInternal.initView(getContext(), mKeyguardBypassEnabledProvider,
mNotificationSwipeHelper);
mStackScroller = spy(mStackScrollerInternal);
@@ -205,8 +209,8 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
@Test
@UiThreadTest
public void testSetExpandedHeight_blockingHelperManagerReceivedCallbacks() {
- final float expectedHeight[] = {0f};
- final float expectedAppear[] = {0f};
+ final float[] expectedHeight = {0f};
+ final float[] expectedAppear = {0f};
mStackScroller.addOnExpandedHeightChangedListener((height, appear) -> {
Assert.assertEquals(expectedHeight[0], height, 0);
@@ -222,6 +226,29 @@ public class NotificationStackScrollLayoutTest extends SysuiTestCase {
}
@Test
+ @UiThreadTest
+ public void testSetExpandedHeight_withSplitShade_doesntInterpolateStackHeight() {
+ when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true);
+ final int[] expectedStackHeight = {0};
+
+ mStackScroller.addOnExpandedHeightChangedListener((expandedHeight, appear) -> {
+ assertWithMessage("Given shade enabled: %s",
+ mFeatureFlags.isTwoColumnNotificationShadeEnabled())
+ .that(mStackScroller.getHeight())
+ .isEqualTo(expectedStackHeight[0]);
+ });
+
+ when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(false);
+ expectedStackHeight[0] = 0;
+ mStackScroller.setExpandedHeight(100f);
+
+ when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true);
+ expectedStackHeight[0] = 100;
+ mStackScroller.setExpandedHeight(100f);
+ }
+
+
+ @Test
public void manageNotifications_visible() {
FooterView view = mock(FooterView.class);
mStackScroller.setFooterView(view);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
index 8dea84c4d0b6..6e0cbd9ecfa3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.phone;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
@@ -197,9 +198,9 @@ public class HeadsUpAppearanceControllerTest extends SysuiTestCase {
mHeadsUpAppearanceController.destroy();
verify(mHeadsUpManager).removeListener(any());
verify(mDarkIconDispatcher).removeDarkReceiver((DarkIconDispatcher.DarkReceiver) any());
- verify(mPanelView).removeVerticalTranslationListener(any());
+ verify(mPanelView).setVerticalTranslationListener(isNull());
verify(mPanelView).removeTrackingHeadsUpListener(any());
- verify(mPanelView).setHeadsUpAppearanceController(any());
+ verify(mPanelView).setHeadsUpAppearanceController(isNull());
verify(mStackScrollerController).removeOnExpandedHeightChangedListener(any());
verify(mStackScrollerController).removeOnLayoutChangeListener(any());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index e788a1c0954b..dd31f522b94d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -18,19 +18,22 @@ package com.android.systemui.statusbar.phone;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
+import static com.android.systemui.statusbar.StatusBarState.SHADE;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.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.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.annotation.IdRes;
import android.app.ActivityManager;
import android.app.StatusBarManager;
import android.content.res.Configuration;
@@ -45,6 +48,7 @@ import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.ViewPropertyAnimator;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -53,6 +57,7 @@ import androidx.constraintlayout.widget.ConstraintSet;
import androidx.test.filters.SmallTest;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEventLogger;
import com.android.internal.logging.testing.UiEventLoggerFake;
import com.android.internal.util.LatencyTracker;
import com.android.keyguard.KeyguardClockSwitch;
@@ -100,7 +105,6 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
-import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.mockito.stubbing.Answer;
@@ -116,8 +120,6 @@ public class NotificationPanelViewTest extends SysuiTestCase {
@Mock
private StatusBar mStatusBar;
@Mock
- private SysuiStatusBarStateController mStatusBarStateController;
- @Mock
private NotificationStackScrollLayout mNotificationStackScrollLayout;
@Mock
private KeyguardBottomAreaView mKeyguardBottomArea;
@@ -227,7 +229,10 @@ public class NotificationPanelViewTest extends SysuiTestCase {
private AmbientState mAmbientState;
@Mock
private UserManager mUserManager;
+ @Mock
+ private UiEventLogger mUiEventLogger;
+ private SysuiStatusBarStateController mStatusBarStateController;
private NotificationPanelViewController mNotificationPanelViewController;
private View.AccessibilityDelegate mAccessibiltyDelegate;
private NotificationsQuickSettingsContainer mNotificationContainerParent;
@@ -235,6 +240,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
+ mStatusBarStateController = new StatusBarStateControllerImpl(mUiEventLogger);
+
when(mAuthController.isUdfpsEnrolled(anyInt())).thenReturn(false);
when(mHeadsUpCallback.getContext()).thenReturn(mContext);
when(mView.getResources()).thenReturn(mResources);
@@ -258,12 +265,14 @@ public class NotificationPanelViewTest extends SysuiTestCase {
when(mView.findViewById(R.id.keyguard_bottom_area)).thenReturn(mKeyguardBottomArea);
when(mKeyguardBottomArea.getLeftView()).thenReturn(mock(KeyguardAffordanceView.class));
when(mKeyguardBottomArea.getRightView()).thenReturn(mock(KeyguardAffordanceView.class));
+ when(mKeyguardBottomArea.animate()).thenReturn(mock(ViewPropertyAnimator.class));
when(mView.findViewById(R.id.big_clock_container)).thenReturn(mBigClockContainer);
when(mView.findViewById(R.id.qs_frame)).thenReturn(mQsFrame);
when(mView.findViewById(R.id.keyguard_status_view))
.thenReturn(mock(KeyguardStatusView.class));
- when(mView.findViewById(R.id.keyguard_header)).thenReturn(mKeyguardStatusBar);
mNotificationContainerParent = new NotificationsQuickSettingsContainer(getContext(), null);
+ mNotificationContainerParent.addView(newViewWithId(R.id.qs_frame));
+ mNotificationContainerParent.addView(newViewWithId(R.id.notification_stack_scroller));
when(mView.findViewById(R.id.notification_container_parent))
.thenReturn(mNotificationContainerParent);
FlingAnimationUtils.Builder flingAnimationUtilsBuilder = new FlingAnimationUtils.Builder(
@@ -293,10 +302,6 @@ public class NotificationPanelViewTest extends SysuiTestCase {
.thenReturn(mKeyguardClockSwitchController);
when(mKeyguardStatusViewComponent.getKeyguardStatusViewController())
.thenReturn(mKeyguardStatusViewController);
- when(mQsFrame.getLayoutParams()).thenReturn(
- new ViewGroup.LayoutParams(600, 400));
- when(mNotificationStackScrollLayoutController.getLayoutParams()).thenReturn(
- new ViewGroup.LayoutParams(600, 400));
mNotificationPanelViewController = new NotificationPanelViewController(mView,
mResources,
@@ -336,17 +341,19 @@ public class NotificationPanelViewTest extends SysuiTestCase {
ArgumentCaptor.forClass(View.AccessibilityDelegate.class);
verify(mView).setAccessibilityDelegate(accessibilityDelegateArgumentCaptor.capture());
mAccessibiltyDelegate = accessibilityDelegateArgumentCaptor.getValue();
+ mNotificationPanelViewController.mStatusBarStateController
+ .addCallback(mNotificationPanelViewController.mStatusBarStateListener);
+ mNotificationPanelViewController
+ .setHeadsUpAppearanceController(mock(HeadsUpAppearanceController.class));
}
@Test
public void testSetDozing_notifiesNsslAndStateController() {
- mNotificationPanelViewController.setDozing(true /* dozing */, true /* animate */,
+ mNotificationPanelViewController.setDozing(true /* dozing */, false /* animate */,
null /* touch */);
- InOrder inOrder = inOrder(
- mNotificationStackScrollLayoutController, mStatusBarStateController);
- inOrder.verify(mNotificationStackScrollLayoutController)
- .setDozing(eq(true), eq(true), eq(null));
- inOrder.verify(mStatusBarStateController).setDozeAmount(eq(1f), eq(true));
+ verify(mNotificationStackScrollLayoutController)
+ .setDozing(eq(true), eq(false), eq(null));
+ assertThat(mStatusBarStateController.getDozeAmount()).isEqualTo(1f);
}
@Test
@@ -442,9 +449,8 @@ public class NotificationPanelViewTest extends SysuiTestCase {
@Test
public void testAllChildrenOfNotificationContainer_haveIds() {
- when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(true);
- when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true);
-
+ enableSplitShade();
+ mNotificationContainerParent.removeAllViews();
mNotificationContainerParent.addView(newViewWithId(1));
mNotificationContainerParent.addView(newViewWithId(View.NO_ID));
@@ -457,36 +463,92 @@ public class NotificationPanelViewTest extends SysuiTestCase {
@Test
public void testSinglePaneShadeLayout_isAlignedToParent() {
when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(false);
- mNotificationContainerParent.addView(newViewWithId(R.id.qs_frame));
- mNotificationContainerParent.addView(newViewWithId(R.id.notification_stack_scroller));
mNotificationPanelViewController.updateResources();
- ConstraintSet constraintSet = new ConstraintSet();
- constraintSet.clone(mNotificationContainerParent);
- ConstraintSet.Layout qsFrameLayout = constraintSet.getConstraint(R.id.qs_frame).layout;
- ConstraintSet.Layout stackScrollerLayout = constraintSet.getConstraint(
- R.id.notification_stack_scroller).layout;
- assertThat(qsFrameLayout.endToEnd).isEqualTo(ConstraintSet.PARENT_ID);
- assertThat(stackScrollerLayout.startToStart).isEqualTo(ConstraintSet.PARENT_ID);
+ assertThat(getConstraintSetLayout(R.id.qs_frame).endToEnd)
+ .isEqualTo(ConstraintSet.PARENT_ID);
+ assertThat(getConstraintSetLayout(R.id.notification_stack_scroller).startToStart)
+ .isEqualTo(ConstraintSet.PARENT_ID);
}
@Test
public void testSplitShadeLayout_isAlignedToGuideline() {
- when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(true);
- when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true);
- mNotificationContainerParent.addView(newViewWithId(R.id.qs_frame));
- mNotificationContainerParent.addView(newViewWithId(R.id.notification_stack_scroller));
+ enableSplitShade();
mNotificationPanelViewController.updateResources();
- ConstraintSet constraintSet = new ConstraintSet();
- constraintSet.clone(mNotificationContainerParent);
- ConstraintSet.Layout qsFrameLayout = constraintSet.getConstraint(R.id.qs_frame).layout;
- ConstraintSet.Layout stackScrollerLayout = constraintSet.getConstraint(
- R.id.notification_stack_scroller).layout;
- assertThat(qsFrameLayout.endToEnd).isEqualTo(R.id.qs_edge_guideline);
- assertThat(stackScrollerLayout.startToStart).isEqualTo(R.id.qs_edge_guideline);
+ assertThat(getConstraintSetLayout(R.id.qs_frame).endToEnd)
+ .isEqualTo(R.id.qs_edge_guideline);
+ assertThat(getConstraintSetLayout(R.id.notification_stack_scroller).startToStart)
+ .isEqualTo(R.id.qs_edge_guideline);
+ }
+
+ @Test
+ public void testSinglePaneShadeLayout_childrenHaveConstantWidth() {
+ when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(false);
+
+ mNotificationPanelViewController.updateResources();
+
+ assertThat(getConstraintSetLayout(R.id.qs_frame).mWidth)
+ .isEqualTo(mResources.getDimensionPixelSize(R.dimen.qs_panel_width));
+ assertThat(getConstraintSetLayout(R.id.notification_stack_scroller).mWidth)
+ .isEqualTo(mResources.getDimensionPixelSize(R.dimen.notification_panel_width));
+ }
+
+ @Test
+ public void testSplitShadeLayout_childrenHaveZeroWidth() {
+ enableSplitShade();
+
+ mNotificationPanelViewController.updateResources();
+
+ assertThat(getConstraintSetLayout(R.id.qs_frame).mWidth).isEqualTo(0);
+ assertThat(getConstraintSetLayout(R.id.notification_stack_scroller).mWidth).isEqualTo(0);
+ }
+
+ @Test
+ public void testOnDragDownEvent_horizontalTranslationIsZeroForSplitShade() {
+ when(mNotificationStackScrollLayoutController.getWidth()).thenReturn(350f);
+ when(mView.getWidth()).thenReturn(800);
+ enableSplitShade();
+
+ onTouchEvent(MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN,
+ 200f /* x position */, 0f, 0));
+
+ verify(mQsFrame).setTranslationX(0);
+ }
+
+ @Test
+ public void testCanCollapsePanelOnTouch_trueForKeyGuard() {
+ mStatusBarStateController.setState(KEYGUARD);
+
+ assertThat(mNotificationPanelViewController.canCollapsePanelOnTouch()).isTrue();
+ }
+
+ @Test
+ public void testCanCollapsePanelOnTouch_trueWhenScrolledToBottom() {
+ mStatusBarStateController.setState(SHADE);
+ when(mNotificationStackScrollLayoutController.isScrolledToBottom()).thenReturn(true);
+
+ assertThat(mNotificationPanelViewController.canCollapsePanelOnTouch()).isTrue();
+ }
+
+ @Test
+ public void testCanCollapsePanelOnTouch_trueWhenInSettings() {
+ mStatusBarStateController.setState(SHADE);
+ mNotificationPanelViewController.setQsExpanded(true);
+
+ assertThat(mNotificationPanelViewController.canCollapsePanelOnTouch()).isTrue();
+ }
+
+ @Test
+ public void testCanCollapsePanelOnTouch_falseInDualPaneShade() {
+ mStatusBarStateController.setState(SHADE);
+ when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(true);
+ when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true);
+ mNotificationPanelViewController.setQsExpanded(true);
+
+ assertThat(mNotificationPanelViewController.canCollapsePanelOnTouch()).isFalse();
}
private View newViewWithId(int id) {
@@ -499,6 +561,17 @@ public class NotificationPanelViewTest extends SysuiTestCase {
return view;
}
+ private ConstraintSet.Layout getConstraintSetLayout(@IdRes int id) {
+ ConstraintSet constraintSet = new ConstraintSet();
+ constraintSet.clone(mNotificationContainerParent);
+ return constraintSet.getConstraint(id).layout;
+ }
+
+ private void enableSplitShade() {
+ when(mResources.getBoolean(R.bool.config_use_split_notification_shade)).thenReturn(true);
+ when(mFeatureFlags.isTwoColumnNotificationShadeEnabled()).thenReturn(true);
+ }
+
private void onTouchEvent(MotionEvent ev) {
mTouchHandler.onTouch(mView, ev);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeTunerService.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeTunerService.java
index 97d4aa7e4d19..7d8a28812fde 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeTunerService.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeTunerService.java
@@ -14,7 +14,6 @@
package com.android.systemui.utils.leaks;
-import android.os.UserHandle;
import android.testing.LeakCheck;
import com.android.systemui.tuner.TunerService;
@@ -78,12 +77,15 @@ public class FakeTunerService extends TunerService {
}
@Override
- public void setTunerEnabled(UserHandle user, boolean enabled) {
+ public void setTunerEnabled(boolean enabled) {
mEnabled = enabled;
}
@Override
- public boolean isTunerEnabled(UserHandle user) {
+ public boolean isTunerEnabled() {
return mEnabled;
}
+
+ @Override
+ public void showResetRequest(Runnable onDisabled) {}
}
diff --git a/services/core/java/com/android/server/SensorPrivacyService.java b/services/core/java/com/android/server/SensorPrivacyService.java
index edaf6a90bd4a..84e429dc83e4 100644
--- a/services/core/java/com/android/server/SensorPrivacyService.java
+++ b/services/core/java/com/android/server/SensorPrivacyService.java
@@ -16,6 +16,7 @@
package com.android.server;
+import static android.Manifest.permission.MANAGE_SENSOR_PRIVACY;
import static android.app.ActivityManager.RunningServiceInfo;
import static android.app.ActivityManager.RunningTaskInfo;
import static android.app.AppOpsManager.MODE_ALLOWED;
@@ -197,18 +198,20 @@ public final class SensorPrivacyService extends SystemService {
Intent.EXTRA_USER)).getIdentifier(),
intent.getIntExtra(EXTRA_SENSOR, UNKNOWN), false);
}
- }, new IntentFilter(ACTION_DISABLE_INDIVIDUAL_SENSOR_PRIVACY));
+ }, new IntentFilter(ACTION_DISABLE_INDIVIDUAL_SENSOR_PRIVACY),
+ MANAGE_SENSOR_PRIVACY, null);
}
@Override
- public void onOpStarted(int code, int uid, String packageName,
+ public void onOpStarted(int code, int uid, String packageName, String attributionTag,
@AppOpsManager.OpFlags int flags, @AppOpsManager.Mode int result) {
- onOpNoted(code, uid, packageName, flags, result);
+ onOpNoted(code, uid, packageName, attributionTag, flags, result);
}
@Override
public void onOpNoted(int code, int uid, String packageName,
- @AppOpsManager.OpFlags int flags, @AppOpsManager.Mode int result) {
+ String attributionTag, @AppOpsManager.OpFlags int flags,
+ @AppOpsManager.Mode int result) {
if (result != MODE_ALLOWED || (flags & AppOpsManager.OP_FLAGS_ALL_TRUSTED) == 0) {
return;
}
@@ -459,12 +462,12 @@ public final class SensorPrivacyService extends SystemService {
*/
private void enforceSensorPrivacyPermission() {
if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.MANAGE_SENSOR_PRIVACY) == PERMISSION_GRANTED) {
+ MANAGE_SENSOR_PRIVACY) == PERMISSION_GRANTED) {
return;
}
throw new SecurityException(
"Changing sensor privacy requires the following permission: "
- + android.Manifest.permission.MANAGE_SENSOR_PRIVACY);
+ + MANAGE_SENSOR_PRIVACY);
}
/**
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index a4ff230b0678..5550999b2405 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -2111,7 +2111,8 @@ public final class ActiveServices {
private final AppOpsManager.OnOpNotedListener mOpNotedCallback =
new AppOpsManager.OnOpNotedListener() {
@Override
- public void onOpNoted(int op, int uid, String pkgName, int flags, int result) {
+ public void onOpNoted(int op, int uid, String pkgName,
+ String attributionTag, int flags, int result) {
incrementOpCountIfNeeded(op, uid, result);
}
};
@@ -2119,7 +2120,8 @@ public final class ActiveServices {
private final AppOpsManager.OnOpStartedListener mOpStartedCallback =
new AppOpsManager.OnOpStartedListener() {
@Override
- public void onOpStarted(int op, int uid, String pkgName, int flags,
+ public void onOpStarted(int op, int uid, String pkgName,
+ String attributionTag, int flags,
int result) {
incrementOpCountIfNeeded(op, uid, result);
}
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index d79fb8a265e8..0a8016cf0556 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -72,6 +72,7 @@ import static com.android.server.am.AppProfiler.TAG_PSS;
import static com.android.server.am.ProcessList.TAG_PROCESS_OBSERVERS;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityThread;
import android.app.ApplicationExitInfo;
@@ -229,6 +230,22 @@ public final class OomAdjuster {
private final ArrayDeque<ProcessRecord> mTmpQueue;
private final ArraySet<ProcessRecord> mPendingProcessSet = new ArraySet<>();
+ /**
+ * Flag to mark if there is an ongoing oomAdjUpdate: potentially the oomAdjUpdate
+ * could be called recursively because of the indirect calls during the update;
+ * however the oomAdjUpdate itself doesn't support recursion - in this case we'd
+ * have to queue up the new targets found during the update, and perform another
+ * round of oomAdjUpdate at the end of last update.
+ */
+ @GuardedBy("mService")
+ private boolean mOomAdjUpdateOngoing = false;
+
+ /**
+ * Flag to mark if there is a pending full oomAdjUpdate.
+ */
+ @GuardedBy("mService")
+ private boolean mPendingFullOomAdjUpdate = false;
+
private final PlatformCompatCache mPlatformCompatCache;
private static class PlatformCompatCache {
@@ -439,6 +456,23 @@ public final class OomAdjuster {
if (oomAdjAll && mConstants.OOMADJ_UPDATE_QUICK) {
return updateOomAdjLSP(app, oomAdjReason);
}
+ if (checkAndEnqueueOomAdjTargetLocked(app)) {
+ // Simply return true as there is an oomAdjUpdate ongoing
+ return true;
+ }
+ try {
+ mOomAdjUpdateOngoing = true;
+ return performUpdateOomAdjLSP(app, oomAdjAll, oomAdjReason);
+ } finally {
+ // Kick off the handling of any pending targets enqueued during the above update
+ mOomAdjUpdateOngoing = false;
+ updateOomAdjPendingTargetsLocked(oomAdjReason);
+ }
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ private boolean performUpdateOomAdjLSP(ProcessRecord app, boolean oomAdjAll,
+ String oomAdjReason) {
final ProcessRecord topApp = mService.getTopApp();
final ProcessStateRecord state = app.mState;
final boolean wasCached = state.isCached();
@@ -453,20 +487,21 @@ public final class OomAdjuster {
? state.getCurRawAdj() : ProcessList.UNKNOWN_ADJ;
// Check if this process is in the pending list too, remove from pending list if so.
mPendingProcessSet.remove(app);
- boolean success = updateOomAdjLSP(app, cachedAdj, topApp, false,
+ boolean success = performUpdateOomAdjLSP(app, cachedAdj, topApp, false,
SystemClock.uptimeMillis());
if (oomAdjAll
&& (wasCached != state.isCached()
|| state.getCurRawAdj() == ProcessList.UNKNOWN_ADJ)) {
// Changed to/from cached state, so apps after it in the LRU
// list may also be changed.
- updateOomAdjLSP(oomAdjReason);
+ performUpdateOomAdjLSP(oomAdjReason);
}
+
return success;
}
@GuardedBy({"mService", "mProcLock"})
- private boolean updateOomAdjLSP(ProcessRecord app, int cachedAdj,
+ private boolean performUpdateOomAdjLSP(ProcessRecord app, int cachedAdj,
ProcessRecord TOP_APP, boolean doingAll, long now) {
if (app.getThread() == null) {
return false;
@@ -519,6 +554,22 @@ public final class OomAdjuster {
@GuardedBy({"mService", "mProcLock"})
private void updateOomAdjLSP(String oomAdjReason) {
+ if (checkAndEnqueueOomAdjTargetLocked(null)) {
+ // Simply return as there is an oomAdjUpdate ongoing
+ return;
+ }
+ try {
+ mOomAdjUpdateOngoing = true;
+ performUpdateOomAdjLSP(oomAdjReason);
+ } finally {
+ // Kick off the handling of any pending targets enqueued during the above update
+ mOomAdjUpdateOngoing = false;
+ updateOomAdjPendingTargetsLocked(oomAdjReason);
+ }
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ private void performUpdateOomAdjLSP(String oomAdjReason) {
final ProcessRecord topApp = mService.getTopApp();
// Clear any pending ones because we are doing a full update now.
mPendingProcessSet.clear();
@@ -548,6 +599,23 @@ public final class OomAdjuster {
return true;
}
+ if (checkAndEnqueueOomAdjTargetLocked(app)) {
+ // Simply return true as there is an oomAdjUpdate ongoing
+ return true;
+ }
+
+ try {
+ mOomAdjUpdateOngoing = true;
+ return performUpdateOomAdjLSP(app, oomAdjReason);
+ } finally {
+ // Kick off the handling of any pending targets enqueued during the above update
+ mOomAdjUpdateOngoing = false;
+ updateOomAdjPendingTargetsLocked(oomAdjReason);
+ }
+ }
+
+ @GuardedBy({"mService", "mProcLock"})
+ private boolean performUpdateOomAdjLSP(ProcessRecord app, String oomAdjReason) {
final ProcessRecord topApp = mService.getTopApp();
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
@@ -567,7 +635,7 @@ public final class OomAdjuster {
state.resetCachedInfo();
// Check if this process is in the pending list too, remove from pending list if so.
mPendingProcessSet.remove(app);
- boolean success = updateOomAdjLSP(app, cachedAdj, topApp, false,
+ boolean success = performUpdateOomAdjLSP(app, cachedAdj, topApp, false,
SystemClock.uptimeMillis());
if (!success || (wasCached == state.isCached() && oldAdj != ProcessList.INVALID_ADJ
&& wasBackground == ActivityManager.isProcStateBackground(
@@ -696,14 +764,59 @@ public final class OomAdjuster {
}
/**
+ * Check if there is an ongoing oomAdjUpdate, enqueue the given process record
+ * to {@link #mPendingProcessSet} if there is one.
+ *
+ * @param app The target app to get an oomAdjUpdate, or a full oomAdjUpdate if it's null.
+ * @return {@code true} if there is an ongoing oomAdjUpdate.
+ */
+ @GuardedBy("mService")
+ private boolean checkAndEnqueueOomAdjTargetLocked(@Nullable ProcessRecord app) {
+ if (!mOomAdjUpdateOngoing) {
+ return false;
+ }
+ if (app != null) {
+ mPendingProcessSet.add(app);
+ } else {
+ mPendingFullOomAdjUpdate = true;
+ }
+ return true;
+ }
+
+ /**
* Kick off an oom adj update pass for the pending targets which are enqueued via
* {@link #enqueueOomAdjTargetLocked}.
*/
@GuardedBy("mService")
void updateOomAdjPendingTargetsLocked(String oomAdjReason) {
+ // First check if there is pending full update
+ if (mPendingFullOomAdjUpdate) {
+ mPendingFullOomAdjUpdate = false;
+ mPendingProcessSet.clear();
+ updateOomAdjLocked(oomAdjReason);
+ return;
+ }
if (mPendingProcessSet.isEmpty()) {
return;
}
+
+ if (mOomAdjUpdateOngoing) {
+ // There's another oomAdjUpdate ongoing, return from here now;
+ // that ongoing update would call us again at the end of it.
+ return;
+ }
+ try {
+ mOomAdjUpdateOngoing = true;
+ performUpdateOomAdjPendingTargetsLocked(oomAdjReason);
+ } finally {
+ // Kick off the handling of any pending targets enqueued during the above update
+ mOomAdjUpdateOngoing = false;
+ updateOomAdjPendingTargetsLocked(oomAdjReason);
+ }
+ }
+
+ @GuardedBy("mService")
+ private void performUpdateOomAdjPendingTargetsLocked(String oomAdjReason) {
final ProcessRecord topApp = mService.getTopApp();
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, oomAdjReason);
@@ -1846,8 +1959,8 @@ public final class OomAdjuster {
computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now,
cycleReEval, true);
} else {
- cstate.setCurRawAdj(cstate.getSetAdj());
- cstate.setCurRawProcState(cstate.getSetProcState());
+ cstate.setCurRawAdj(cstate.getCurAdj());
+ cstate.setCurRawProcState(cstate.getCurProcState());
}
int clientAdj = cstate.getCurRawAdj();
@@ -2130,8 +2243,8 @@ public final class OomAdjuster {
if (computeClients) {
computeOomAdjLSP(client, cachedAdj, topApp, doingAll, now, cycleReEval, true);
} else {
- cstate.setCurRawAdj(cstate.getSetAdj());
- cstate.setCurRawProcState(cstate.getSetProcState());
+ cstate.setCurRawAdj(cstate.getCurAdj());
+ cstate.setCurRawProcState(cstate.getCurProcState());
}
if (shouldSkipDueToCycle(state, cstate, procState, adj, cycleReEval)) {
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index c92abd48fdc2..a776458d63c5 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -3124,7 +3124,7 @@ public class AppOpsService extends IAppOpsService.Stub {
final Ops ops = getOpsLocked(uid, packageName, attributionTag, bypass,
true /* edit */);
if (ops == null) {
- scheduleOpNotedIfNeededLocked(code, uid, packageName, flags,
+ scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags,
AppOpsManager.MODE_IGNORED);
if (DEBUG) Slog.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
+ " package " + packageName);
@@ -3142,7 +3142,7 @@ public class AppOpsService extends IAppOpsService.Stub {
final UidState uidState = ops.uidState;
if (isOpRestrictedLocked(uid, code, packageName, bypass)) {
attributedOp.rejected(uidState.state, flags);
- scheduleOpNotedIfNeededLocked(code, uid, packageName, flags,
+ scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags,
AppOpsManager.MODE_IGNORED);
return AppOpsManager.MODE_IGNORED;
}
@@ -3155,7 +3155,8 @@ public class AppOpsService extends IAppOpsService.Stub {
+ switchCode + " (" + code + ") uid " + uid + " package "
+ packageName);
attributedOp.rejected(uidState.state, flags);
- scheduleOpNotedIfNeededLocked(code, uid, packageName, flags, uidMode);
+ scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags,
+ uidMode);
return uidMode;
}
} else {
@@ -3167,7 +3168,8 @@ public class AppOpsService extends IAppOpsService.Stub {
+ switchCode + " (" + code + ") uid " + uid + " package "
+ packageName);
attributedOp.rejected(uidState.state, flags);
- scheduleOpNotedIfNeededLocked(code, uid, packageName, flags, mode);
+ scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags,
+ mode);
return mode;
}
}
@@ -3177,7 +3179,7 @@ public class AppOpsService extends IAppOpsService.Stub {
+ packageName + (attributionTag == null ? ""
: "." + attributionTag));
}
- scheduleOpNotedIfNeededLocked(code, uid, packageName, flags,
+ scheduleOpNotedIfNeededLocked(code, uid, packageName, attributionTag, flags,
AppOpsManager.MODE_ALLOWED);
attributedOp.accessed(proxyUid, proxyPackageName, proxyAttributionTag, uidState.state,
flags);
@@ -3580,7 +3582,7 @@ public class AppOpsService extends IAppOpsService.Stub {
final Ops ops = getOpsLocked(uid, packageName, attributionTag, bypass, true /* edit */);
if (ops == null) {
if (!dryRun) {
- scheduleOpStartedIfNeededLocked(code, uid, packageName,
+ scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag,
flags, AppOpsManager.MODE_IGNORED);
}
if (DEBUG) Slog.d(TAG, "startOperation: no op for code " + code + " uid " + uid
@@ -3590,7 +3592,7 @@ public class AppOpsService extends IAppOpsService.Stub {
final Op op = getOpLocked(ops, code, uid, true);
if (isOpRestrictedLocked(uid, code, packageName, bypass)) {
if (!dryRun) {
- scheduleOpStartedIfNeededLocked(code, uid, packageName,
+ scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag,
flags, AppOpsManager.MODE_IGNORED);
}
return AppOpsManager.MODE_IGNORED;
@@ -3611,7 +3613,8 @@ public class AppOpsService extends IAppOpsService.Stub {
}
if (!dryRun) {
attributedOp.rejected(uidState.state, flags);
- scheduleOpStartedIfNeededLocked(code, uid, packageName, flags, uidMode);
+ scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag,
+ flags, uidMode);
}
return uidMode;
}
@@ -3626,7 +3629,8 @@ public class AppOpsService extends IAppOpsService.Stub {
+ packageName);
if (!dryRun) {
attributedOp.rejected(uidState.state, flags);
- scheduleOpStartedIfNeededLocked(code, uid, packageName, flags, mode);
+ scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag,
+ flags, mode);
}
return mode;
}
@@ -3634,7 +3638,7 @@ public class AppOpsService extends IAppOpsService.Stub {
if (DEBUG) Slog.d(TAG, "startOperation: allowing code " + code + " uid " + uid
+ " package " + packageName);
if (!dryRun) {
- scheduleOpStartedIfNeededLocked(code, uid, packageName, flags,
+ scheduleOpStartedIfNeededLocked(code, uid, packageName, attributionTag, flags,
AppOpsManager.MODE_ALLOWED);
try {
attributedOp.started(clientId, proxyUid, proxyPackageName, proxyAttributionTag,
@@ -3774,7 +3778,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
private void scheduleOpStartedIfNeededLocked(int code, int uid, String pkgName,
- @OpFlags int flags, @Mode int result) {
+ String attributionTag, @OpFlags int flags, @Mode int result) {
ArraySet<StartedCallback> dispatchedCallbacks = null;
final int callbackListCount = mStartedWatchers.size();
for (int i = 0; i < callbackListCount; i++) {
@@ -3799,18 +3803,21 @@ public class AppOpsService extends IAppOpsService.Stub {
mHandler.sendMessage(PooledLambda.obtainMessage(
AppOpsService::notifyOpStarted,
- this, dispatchedCallbacks, code, uid, pkgName, flags, result));
+ this, dispatchedCallbacks, code, uid, pkgName, attributionTag, flags,
+ result));
}
private void notifyOpStarted(ArraySet<StartedCallback> callbacks,
- int code, int uid, String packageName, @OpFlags int flags, @Mode int result) {
+ int code, int uid, String packageName, String attributionTag, @OpFlags int flags,
+ @Mode int result) {
final long identity = Binder.clearCallingIdentity();
try {
final int callbackCount = callbacks.size();
for (int i = 0; i < callbackCount; i++) {
final StartedCallback callback = callbacks.valueAt(i);
try {
- callback.mCallback.opStarted(code, uid, packageName, flags, result);
+ callback.mCallback.opStarted(code, uid, packageName, attributionTag, flags,
+ result);
} catch (RemoteException e) {
/* do nothing */
}
@@ -3821,7 +3828,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
private void scheduleOpNotedIfNeededLocked(int code, int uid, String packageName,
- @OpFlags int flags, @Mode int result) {
+ String attributionTag, @OpFlags int flags, @Mode int result) {
ArraySet<NotedCallback> dispatchedCallbacks = null;
final int callbackListCount = mNotedWatchers.size();
for (int i = 0; i < callbackListCount; i++) {
@@ -3842,11 +3849,13 @@ public class AppOpsService extends IAppOpsService.Stub {
}
mHandler.sendMessage(PooledLambda.obtainMessage(
AppOpsService::notifyOpChecked,
- this, dispatchedCallbacks, code, uid, packageName, flags, result));
+ this, dispatchedCallbacks, code, uid, packageName, attributionTag, flags,
+ result));
}
private void notifyOpChecked(ArraySet<NotedCallback> callbacks,
- int code, int uid, String packageName, @OpFlags int flags, @Mode int result) {
+ int code, int uid, String packageName, String attributionTag, @OpFlags int flags,
+ @Mode int result) {
// There are features watching for checks in our process. The callbacks in
// these features may require permissions our remote caller does not have.
final long identity = Binder.clearCallingIdentity();
@@ -3855,7 +3864,8 @@ public class AppOpsService extends IAppOpsService.Stub {
for (int i = 0; i < callbackCount; i++) {
final NotedCallback callback = callbacks.valueAt(i);
try {
- callback.mCallback.opNoted(code, uid, packageName, flags, result);
+ callback.mCallback.opNoted(code, uid, packageName, attributionTag, flags,
+ result);
} catch (RemoteException e) {
/* do nothing */
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 29ee8b6c675d..5f3405379715 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -726,7 +726,7 @@ public class AudioService extends IAudioService.Stub
// caches the value returned by AudioSystem.isMicrophoneMuted()
private boolean mMicMuteFromSystemCached;
- private boolean mFastScrollSoundEffectsEnabled;
+ private boolean mNavigationRepeatSoundEffectsEnabled;
private boolean mHomeSoundEffectEnabled;
@GuardedBy("mSettingsLock")
@@ -2325,15 +2325,15 @@ public class AudioService extends IAudioService.Stub
VOL_ADJUST_NORMAL);
}
- public void setFastScrollSoundEffectsEnabled(boolean enabled) {
- mFastScrollSoundEffectsEnabled = enabled;
+ public void setNavigationRepeatSoundEffectsEnabled(boolean enabled) {
+ mNavigationRepeatSoundEffectsEnabled = enabled;
}
/**
* @return true if the fast scroll sound effects are enabled
*/
- public boolean areFastScrollSoundEffectsEnabled() {
- return mFastScrollSoundEffectsEnabled;
+ public boolean areNavigationRepeatSoundEffectsEnabled() {
+ return mNavigationRepeatSoundEffectsEnabled;
}
public void setHomeSoundEffectEnabled(boolean enabled) {
diff --git a/services/core/java/com/android/server/audio/SoundEffectsHelper.java b/services/core/java/com/android/server/audio/SoundEffectsHelper.java
index c14bb3ee5df1..7031e02af05a 100644
--- a/services/core/java/com/android/server/audio/SoundEffectsHelper.java
+++ b/services/core/java/com/android/server/audio/SoundEffectsHelper.java
@@ -52,6 +52,7 @@ import java.util.Map;
* used by AudioService. As its methods are called on the message handler thread
* of AudioService, the actual work is offloaded to a dedicated thread.
* This helps keeping AudioService responsive.
+ *
* @hide
*/
class SoundEffectsHelper {
@@ -89,15 +90,18 @@ class SoundEffectsHelper {
final String mFileName;
int mSampleId;
boolean mLoaded; // for effects in SoundPool
+
Resource(String fileName) {
mFileName = fileName;
mSampleId = EFFECT_NOT_IN_SOUND_POOL;
}
+
void unload() {
mSampleId = EFFECT_NOT_IN_SOUND_POOL;
mLoaded = false;
}
}
+
// All the fields below are accessed by the worker thread exclusively
private final List<Resource> mResources = new ArrayList<Resource>();
private final int[] mEffects = new int[AudioManager.NUM_SOUND_EFFECTS]; // indexes in mResources
@@ -116,9 +120,9 @@ class SoundEffectsHelper {
}
/**
- * Unloads samples from the sound pool.
- * This method can be called to free some memory when
- * sound effects are disabled.
+ * Unloads samples from the sound pool.
+ * This method can be called to free some memory when
+ * sound effects are disabled.
*/
/*package*/ void unloadSoundEffects() {
sendMsg(MSG_UNLOAD_EFFECTS, 0, 0, null, 0);
@@ -385,12 +389,12 @@ class SoundEffectsHelper {
}
}
- boolean fastScrollSoundEffectsParsed = allFastScrollSoundsParsed(parserCounter);
+ boolean navigationRepeatFxParsed = allNavigationRepeatSoundsParsed(parserCounter);
boolean homeSoundParsed = parserCounter.getOrDefault(AudioManager.FX_HOME, 0) > 0;
- if (fastScrollSoundEffectsParsed || homeSoundParsed) {
+ if (navigationRepeatFxParsed || homeSoundParsed) {
AudioManager audioManager = mContext.getSystemService(AudioManager.class);
- if (audioManager != null && fastScrollSoundEffectsParsed) {
- audioManager.setFastScrollSoundEffectsEnabled(true);
+ if (audioManager != null && navigationRepeatFxParsed) {
+ audioManager.setNavigationRepeatSoundEffectsEnabled(true);
}
if (audioManager != null && homeSoundParsed) {
audioManager.setHomeSoundEffectEnabled(true);
@@ -410,13 +414,13 @@ class SoundEffectsHelper {
}
}
- private boolean allFastScrollSoundsParsed(Map<Integer, Integer> parserCounter) {
+ private boolean allNavigationRepeatSoundsParsed(Map<Integer, Integer> parserCounter) {
int numFastScrollSoundEffectsParsed =
- parserCounter.getOrDefault(AudioManager.FX_FAST_SCROLL_1, 0)
- + parserCounter.getOrDefault(AudioManager.FX_FAST_SCROLL_2, 0)
- + parserCounter.getOrDefault(AudioManager.FX_FAST_SCROLL_3, 0)
- + parserCounter.getOrDefault(AudioManager.FX_FAST_SCROLL_4, 0);
- return numFastScrollSoundEffectsParsed == AudioManager.NUM_FAST_SCROLL_SOUND_EFFECTS;
+ parserCounter.getOrDefault(AudioManager.FX_FOCUS_NAVIGATION_REPEAT_1, 0)
+ + parserCounter.getOrDefault(AudioManager.FX_FOCUS_NAVIGATION_REPEAT_2, 0)
+ + parserCounter.getOrDefault(AudioManager.FX_FOCUS_NAVIGATION_REPEAT_3, 0)
+ + parserCounter.getOrDefault(AudioManager.FX_FOCUS_NAVIGATION_REPEAT_4, 0);
+ return numFastScrollSoundEffectsParsed == AudioManager.NUM_NAVIGATION_REPEAT_SOUND_EFFECTS;
}
private int findOrAddResourceByFileName(String fileName) {
diff --git a/services/core/java/com/android/server/display/ColorFade.java b/services/core/java/com/android/server/display/ColorFade.java
index 5e1df27167c2..198ea3d3f66a 100644
--- a/services/core/java/com/android/server/display/ColorFade.java
+++ b/services/core/java/com/android/server/display/ColorFade.java
@@ -165,7 +165,7 @@ final class ColorFade {
"Failed to take screenshot because internal display is disconnected");
return false;
}
- boolean isWideColor = SurfaceControl.getActiveColorMode(token)
+ boolean isWideColor = SurfaceControl.getDynamicDisplayInfo(token).activeColorMode
== Display.COLOR_MODE_DISPLAY_P3;
// Set mPrepared here so if initialization fails, resources can be cleaned up.
diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
index 501533d535d3..40cee66a6791 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
@@ -466,7 +466,7 @@ final class DisplayDeviceInfo {
sb.append(", supportedModes ").append(Arrays.toString(supportedModes));
sb.append(", colorMode ").append(colorMode);
sb.append(", supportedColorModes ").append(Arrays.toString(supportedColorModes));
- sb.append(", HdrCapabilities ").append(hdrCapabilities);
+ sb.append(", hdrCapabilities ").append(hdrCapabilities);
sb.append(", allmSupported ").append(allmSupported);
sb.append(", gameContentTypeSupported ").append(gameContentTypeSupported);
sb.append(", density ").append(densityDpi);
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 3b66236c9f0f..7ce4f066b058 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -100,50 +100,48 @@ final class LocalDisplayAdapter extends DisplayAdapter {
private void tryConnectDisplayLocked(long physicalDisplayId) {
final IBinder displayToken = SurfaceControl.getPhysicalDisplayToken(physicalDisplayId);
if (displayToken != null) {
- SurfaceControl.DisplayInfo info = SurfaceControl.getDisplayInfo(displayToken);
- if (info == null) {
- Slog.w(TAG, "No valid info found for display device " + physicalDisplayId);
+ SurfaceControl.StaticDisplayInfo staticInfo =
+ SurfaceControl.getStaticDisplayInfo(displayToken);
+ if (staticInfo == null) {
+ Slog.w(TAG, "No valid static info found for display device " + physicalDisplayId);
return;
}
- SurfaceControl.DisplayMode[] displayModes =
- SurfaceControl.getDisplayModes(displayToken);
- if (displayModes == null) {
+ SurfaceControl.DynamicDisplayInfo dynamicInfo =
+ SurfaceControl.getDynamicDisplayInfo(displayToken);
+ if (dynamicInfo == null) {
+ Slog.w(TAG, "No valid dynamic info found for display device " + physicalDisplayId);
+ return;
+ }
+ if (dynamicInfo.supportedDisplayModes == null) {
// There are no valid modes for this device, so we can't use it
Slog.w(TAG, "No valid modes found for display device " + physicalDisplayId);
return;
}
- int activeDisplayMode = SurfaceControl.getActiveDisplayMode(displayToken);
- if (activeDisplayMode < 0) {
+ if (dynamicInfo.activeDisplayModeId < 0) {
// There is no active mode, and for now we don't have the
// policy to set one.
- Slog.w(TAG, "No active mode found for display device " + physicalDisplayId);
+ Slog.w(TAG, "No valid active mode found for display device " + physicalDisplayId);
return;
}
- int activeColorMode = SurfaceControl.getActiveColorMode(displayToken);
- if (activeColorMode < 0) {
+ if (dynamicInfo.activeColorMode < 0) {
// We failed to get the active color mode. We don't bail out here since on the next
// configuration pass we'll go ahead and set it to whatever it was set to last (or
// COLOR_MODE_NATIVE if this is the first configuration).
- Slog.w(TAG, "Unable to get active color mode for display device " +
- physicalDisplayId);
- activeColorMode = Display.COLOR_MODE_INVALID;
+ Slog.w(TAG, "No valid active color mode for display device " + physicalDisplayId);
+ dynamicInfo.activeColorMode = Display.COLOR_MODE_INVALID;
}
- SurfaceControl.DesiredDisplayModeSpecs modeSpecsSpecs =
+ SurfaceControl.DesiredDisplayModeSpecs modeSpecs =
SurfaceControl.getDesiredDisplayModeSpecs(displayToken);
- int[] colorModes = SurfaceControl.getDisplayColorModes(displayToken);
- Display.HdrCapabilities hdrCapabilities =
- SurfaceControl.getHdrCapabilities(displayToken);
LocalDisplayDevice device = mDevices.get(physicalDisplayId);
if (device == null) {
// Display was added.
final boolean isDefaultDisplay = mDevices.size() == 0;
- device = new LocalDisplayDevice(displayToken, physicalDisplayId, info, displayModes,
- activeDisplayMode, modeSpecsSpecs, colorModes, activeColorMode,
- hdrCapabilities, isDefaultDisplay);
+ device = new LocalDisplayDevice(displayToken, physicalDisplayId, staticInfo,
+ dynamicInfo, modeSpecs, isDefaultDisplay);
mDevices.put(physicalDisplayId, device);
sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_ADDED);
- } else if (device.updateDisplayPropertiesLocked(info, displayModes, activeDisplayMode,
- modeSpecsSpecs, colorModes, activeColorMode, hdrCapabilities)) {
+ } else if (device.updateDisplayPropertiesLocked(staticInfo, dynamicInfo,
+ modeSpecs)) {
sendDisplayDeviceEventLocked(device, DISPLAY_DEVICE_EVENT_CHANGED);
}
} else {
@@ -195,7 +193,6 @@ final class LocalDisplayAdapter extends DisplayAdapter {
private DisplayModeDirector.DesiredDisplayModeSpecs mDisplayModeSpecs =
new DisplayModeDirector.DesiredDisplayModeSpecs();
private boolean mDisplayModeSpecsInvalid;
- private int mActiveDisplayModeId;
private int mActiveColorMode;
private Display.HdrCapabilities mHdrCapabilities;
private boolean mAllmSupported;
@@ -204,8 +201,11 @@ final class LocalDisplayAdapter extends DisplayAdapter {
private boolean mGameContentTypeRequested;
private boolean mSidekickActive;
private SidekickInternal mSidekickInternal;
- private SurfaceControl.DisplayInfo mDisplayInfo;
- private SurfaceControl.DisplayMode[] mDisplayModes;
+ private SurfaceControl.StaticDisplayInfo mStaticDisplayInfo;
+ // The supported display modes according in SurfaceFlinger
+ private SurfaceControl.DisplayMode[] mSfDisplayModes;
+ // The active display mode in SurfaceFlinger
+ private SurfaceControl.DisplayMode mActiveSfDisplayMode;
private Spline mSystemBrightnessToNits;
private Spline mNitsToHalBrightness;
private DisplayDeviceConfig mDisplayDeviceConfig;
@@ -214,15 +214,13 @@ final class LocalDisplayAdapter extends DisplayAdapter {
new DisplayEventReceiver.FrameRateOverride[0];
LocalDisplayDevice(IBinder displayToken, long physicalDisplayId,
- SurfaceControl.DisplayInfo info, SurfaceControl.DisplayMode[] displayModes,
- int activeDisplayModeId, SurfaceControl.DesiredDisplayModeSpecs modeSpecs,
- int[] colorModes, int activeColorMode, Display.HdrCapabilities hdrCapabilities,
- boolean isDefaultDisplay) {
+ SurfaceControl.StaticDisplayInfo staticDisplayInfo,
+ SurfaceControl.DynamicDisplayInfo dynamicInfo,
+ SurfaceControl.DesiredDisplayModeSpecs modeSpecs, boolean isDefaultDisplay) {
super(LocalDisplayAdapter.this, displayToken, UNIQUE_ID_PREFIX + physicalDisplayId);
mPhysicalDisplayId = physicalDisplayId;
mIsDefaultDisplay = isDefaultDisplay;
- updateDisplayPropertiesLocked(info, displayModes, activeDisplayModeId, modeSpecs,
- colorModes, activeColorMode, hdrCapabilities);
+ updateDisplayPropertiesLocked(staticDisplayInfo, dynamicInfo, modeSpecs);
mSidekickInternal = LocalServices.getService(SidekickInternal.class);
mBacklightAdapter = new BacklightAdapter(displayToken, isDefaultDisplay);
mAllmSupported = SurfaceControl.getAutoLowLatencyModeSupport(displayToken);
@@ -241,15 +239,15 @@ final class LocalDisplayAdapter extends DisplayAdapter {
/**
* Returns true if there is a change.
**/
- public boolean updateDisplayPropertiesLocked(SurfaceControl.DisplayInfo info,
- SurfaceControl.DisplayMode[] displayModes,
- int activeDisplayModeId, SurfaceControl.DesiredDisplayModeSpecs modeSpecs,
- int[] colorModes, int activeColorMode, Display.HdrCapabilities hdrCapabilities) {
+ public boolean updateDisplayPropertiesLocked(SurfaceControl.StaticDisplayInfo staticInfo,
+ SurfaceControl.DynamicDisplayInfo dynamicInfo,
+ SurfaceControl.DesiredDisplayModeSpecs modeSpecs) {
boolean changed = updateDisplayModesLocked(
- displayModes, activeDisplayModeId, modeSpecs);
- changed |= updateDisplayInfo(info);
- changed |= updateColorModesLocked(colorModes, activeColorMode);
- changed |= updateHdrCapabilitiesLocked(hdrCapabilities);
+ dynamicInfo.supportedDisplayModes, dynamicInfo.activeDisplayModeId, modeSpecs);
+ changed |= updateStaticInfo(staticInfo);
+ changed |= updateColorModesLocked(dynamicInfo.supportedColorModes,
+ dynamicInfo.activeColorMode);
+ changed |= updateHdrCapabilitiesLocked(dynamicInfo.hdrCapabilities);
if (changed) {
mHavePendingChanges = true;
@@ -260,8 +258,9 @@ final class LocalDisplayAdapter extends DisplayAdapter {
public boolean updateDisplayModesLocked(
SurfaceControl.DisplayMode[] displayModes, int activeDisplayModeId,
SurfaceControl.DesiredDisplayModeSpecs modeSpecs) {
- mDisplayModes = Arrays.copyOf(displayModes, displayModes.length);
- mActiveDisplayModeId = activeDisplayModeId;
+ mSfDisplayModes = Arrays.copyOf(displayModes, displayModes.length);
+ mActiveSfDisplayMode = getModeById(displayModes, activeDisplayModeId);
+
// Build an updated list of all existing modes.
ArrayList<DisplayModeRecord> records = new ArrayList<>();
boolean modesAdded = false;
@@ -282,7 +281,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
// First, check to see if we've already added a matching mode. Since not all
// configuration options are exposed via Display.Mode, it's possible that we have
- // multiple DisplayModess that would generate the same Display.Mode.
+ // multiple DisplayModes that would generate the same Display.Mode.
boolean existingMode = false;
for (DisplayModeRecord record : records) {
if (record.hasMatchingMode(mode)
@@ -312,9 +311,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
// Get the currently active mode
DisplayModeRecord activeRecord = null;
- for (int i = 0; i < records.size(); i++) {
- DisplayModeRecord record = records.get(i);
- if (record.hasMatchingMode(displayModes[activeDisplayModeId])) {
+ for (DisplayModeRecord record : records) {
+ if (record.hasMatchingMode(mActiveSfDisplayMode)) {
activeRecord = record;
break;
}
@@ -370,17 +368,17 @@ final class LocalDisplayAdapter extends DisplayAdapter {
// For a new display, we need to initialize the default mode ID.
if (mDefaultModeId == NO_DISPLAY_MODE_ID) {
mDefaultModeId = activeRecord.mMode.getModeId();
- mDefaultModeGroup = displayModes[activeDisplayModeId].group;
+ mDefaultModeGroup = mActiveSfDisplayMode.group;
} else if (modesAdded && activeModeChanged) {
Slog.d(TAG, "New display modes are added and the active mode has changed, "
+ "use active mode as default mode.");
mDefaultModeId = activeRecord.mMode.getModeId();
- mDefaultModeGroup = displayModes[activeDisplayModeId].group;
+ mDefaultModeGroup = mActiveSfDisplayMode.group;
} else if (findDisplayModeIdLocked(mDefaultModeId, mDefaultModeGroup) < 0) {
Slog.w(TAG, "Default display mode no longer available, using currently"
+ " active mode as default.");
mDefaultModeId = activeRecord.mMode.getModeId();
- mDefaultModeGroup = displayModes[activeDisplayModeId].group;
+ mDefaultModeGroup = mActiveSfDisplayMode.group;
}
// Determine whether the display mode specs' base mode is still there.
@@ -454,11 +452,11 @@ final class LocalDisplayAdapter extends DisplayAdapter {
mSystemBrightnessToNits = sysToNits;
}
- private boolean updateDisplayInfo(SurfaceControl.DisplayInfo info) {
- if (Objects.equals(mDisplayInfo, info)) {
+ private boolean updateStaticInfo(SurfaceControl.StaticDisplayInfo info) {
+ if (Objects.equals(mStaticDisplayInfo, info)) {
return false;
}
- mDisplayInfo = info;
+ mStaticDisplayInfo = info;
return true;
}
@@ -520,6 +518,17 @@ final class LocalDisplayAdapter extends DisplayAdapter {
return true;
}
+ private SurfaceControl.DisplayMode getModeById(SurfaceControl.DisplayMode[] supportedModes,
+ int modeId) {
+ for (SurfaceControl.DisplayMode mode : supportedModes) {
+ if (mode.id == modeId) {
+ return mode;
+ }
+ }
+ Slog.e(TAG, "Can't find display mode with id " + modeId);
+ return null;
+ }
+
private DisplayModeRecord findDisplayModeRecord(SurfaceControl.DisplayMode mode,
List<Float> alternativeRefreshRates) {
for (int i = 0; i < mSupportedModes.size(); i++) {
@@ -556,10 +565,9 @@ final class LocalDisplayAdapter extends DisplayAdapter {
@Override
public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
if (mInfo == null) {
- SurfaceControl.DisplayMode mode = mDisplayModes[mActiveDisplayModeId];
mInfo = new DisplayDeviceInfo();
- mInfo.width = mode.width;
- mInfo.height = mode.height;
+ mInfo.width = mActiveSfDisplayMode.width;
+ mInfo.height = mActiveSfDisplayMode.height;
mInfo.modeId = mActiveModeId;
mInfo.defaultModeId = mDefaultModeId;
mInfo.supportedModes = getDisplayModes(mSupportedModes);
@@ -572,21 +580,21 @@ final class LocalDisplayAdapter extends DisplayAdapter {
mInfo.supportedColorModes[i] = mSupportedColorModes.get(i);
}
mInfo.hdrCapabilities = mHdrCapabilities;
- mInfo.appVsyncOffsetNanos = mode.appVsyncOffsetNanos;
- mInfo.presentationDeadlineNanos = mode.presentationDeadlineNanos;
+ mInfo.appVsyncOffsetNanos = mActiveSfDisplayMode.appVsyncOffsetNanos;
+ mInfo.presentationDeadlineNanos = mActiveSfDisplayMode.presentationDeadlineNanos;
mInfo.state = mState;
mInfo.uniqueId = getUniqueId();
final DisplayAddress.Physical physicalAddress =
DisplayAddress.fromPhysicalDisplayId(mPhysicalDisplayId);
mInfo.address = physicalAddress;
- mInfo.densityDpi = (int) (mDisplayInfo.density * 160 + 0.5f);
- mInfo.xDpi = mode.xDpi;
- mInfo.yDpi = mode.yDpi;
- mInfo.deviceProductInfo = mDisplayInfo.deviceProductInfo;
+ mInfo.densityDpi = (int) (mStaticDisplayInfo.density * 160 + 0.5f);
+ mInfo.xDpi = mActiveSfDisplayMode.xDpi;
+ mInfo.yDpi = mActiveSfDisplayMode.yDpi;
+ mInfo.deviceProductInfo = mStaticDisplayInfo.deviceProductInfo;
// Assume that all built-in displays that have secure output (eg. HDCP) also
// support compositing from gralloc protected buffers.
- if (mDisplayInfo.secure) {
+ if (mStaticDisplayInfo.secure) {
mInfo.flags = DisplayDeviceInfo.FLAG_SECURE
| DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
}
@@ -620,7 +628,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
}
}
- if (mDisplayInfo.isInternal) {
+ if (mStaticDisplayInfo.isInternal) {
mInfo.type = Display.TYPE_INTERNAL;
mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL;
mInfo.flags |= DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT;
@@ -878,9 +886,10 @@ final class LocalDisplayAdapter extends DisplayAdapter {
// Do not lock when calling these SurfaceControl methods because they are sync
// operations that may block for a while when setting display power mode.
SurfaceControl.setDesiredDisplayModeSpecs(displayToken, modeSpecs);
- final int activeMode = SurfaceControl.getActiveDisplayMode(displayToken);
+ final int sfActiveModeId =
+ SurfaceControl.getDynamicDisplayInfo(displayToken).activeDisplayModeId;
synchronized (getSyncRoot()) {
- if (updateActiveModeLocked(activeMode)) {
+ if (updateActiveModeLocked(sfActiveModeId)) {
updateDeviceInfoLocked();
}
}
@@ -891,8 +900,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
updateDeviceInfoLocked();
}
- public void onActiveDisplayModeChangedLocked(int modeId) {
- if (updateActiveModeLocked(modeId)) {
+ public void onActiveDisplayModeChangedLocked(int sfModeId) {
+ if (updateActiveModeLocked(sfModeId)) {
updateDeviceInfoLocked();
}
}
@@ -904,15 +913,15 @@ final class LocalDisplayAdapter extends DisplayAdapter {
}
}
- public boolean updateActiveModeLocked(int activeModeId) {
- if (mActiveDisplayModeId == activeModeId) {
+ public boolean updateActiveModeLocked(int activeSfModeId) {
+ if (mActiveSfDisplayMode.id == activeSfModeId) {
return false;
}
- mActiveDisplayModeId = activeModeId;
- mActiveModeId = findMatchingModeIdLocked(activeModeId);
+ mActiveSfDisplayMode = getModeById(mSfDisplayModes, activeSfModeId);
+ mActiveModeId = findMatchingModeIdLocked(activeSfModeId);
if (mActiveModeId == NO_DISPLAY_MODE_ID) {
Slog.w(TAG, "In unknown mode after setting allowed modes"
- + ", activeModeId=" + mActiveDisplayModeId);
+ + ", activeModeId=" + activeSfModeId);
}
return true;
}
@@ -992,7 +1001,6 @@ final class LocalDisplayAdapter extends DisplayAdapter {
pw.println("mPhysicalDisplayId=" + mPhysicalDisplayId);
pw.println("mDisplayModeSpecs={" + mDisplayModeSpecs + "}");
pw.println("mDisplayModeSpecsInvalid=" + mDisplayModeSpecsInvalid);
- pw.println("mActiveDisplayModeId=" + mActiveDisplayModeId);
pw.println("mActiveModeId=" + mActiveModeId);
pw.println("mActiveColorMode=" + mActiveColorMode);
pw.println("mDefaultModeId=" + mDefaultModeId);
@@ -1003,11 +1011,12 @@ final class LocalDisplayAdapter extends DisplayAdapter {
pw.println("mAllmRequested=" + mAllmRequested);
pw.println("mGameContentTypeSupported=" + mGameContentTypeSupported);
pw.println("mGameContentTypeRequested=" + mGameContentTypeRequested);
- pw.println("mDisplayInfo=" + mDisplayInfo);
- pw.println("mDisplayModes=");
- for (int i = 0; i < mDisplayModes.length; i++) {
- pw.println(" " + mDisplayModes[i]);
+ pw.println("mStaticDisplayInfo=" + mStaticDisplayInfo);
+ pw.println("mSfDisplayModes=");
+ for (int i = 0; i < mSfDisplayModes.length; i++) {
+ pw.println(" " + mSfDisplayModes[i]);
}
+ pw.println("mActiveSfDisplayMode=" + mActiveSfDisplayMode);
pw.println("mSupportedModes=");
for (int i = 0; i < mSupportedModes.size(); i++) {
pw.println(" " + mSupportedModes.valueAt(i));
@@ -1020,17 +1029,16 @@ final class LocalDisplayAdapter extends DisplayAdapter {
int matchingModeId = SurfaceControl.DisplayMode.INVALID_DISPLAY_MODE_ID;
DisplayModeRecord record = mSupportedModes.get(modeId);
if (record != null) {
- for (int i = 0; i < mDisplayModes.length; i++) {
- SurfaceControl.DisplayMode mode = mDisplayModes[i];
+ for (SurfaceControl.DisplayMode mode : mSfDisplayModes) {
if (record.hasMatchingMode(mode)) {
if (matchingModeId
== SurfaceControl.DisplayMode.INVALID_DISPLAY_MODE_ID) {
- matchingModeId = i;
+ matchingModeId = mode.id;
}
// Prefer to return a mode that matches the modeGroup
if (mode.group == modeGroup) {
- return i;
+ return mode.id;
}
}
}
@@ -1038,12 +1046,12 @@ final class LocalDisplayAdapter extends DisplayAdapter {
return matchingModeId;
}
- private int findMatchingModeIdLocked(int modeId) {
- if (modeId < 0 || modeId >= mDisplayModes.length) {
- Slog.e(TAG, "Invalid display config index " + modeId);
+ private int findMatchingModeIdLocked(int sfModeId) {
+ SurfaceControl.DisplayMode mode = getModeById(mSfDisplayModes, sfModeId);
+ if (mode == null) {
+ Slog.e(TAG, "Invalid display mode ID " + sfModeId);
return NO_DISPLAY_MODE_ID;
}
- SurfaceControl.DisplayMode mode = mDisplayModes[modeId];
for (int i = 0; i < mSupportedModes.size(); i++) {
DisplayModeRecord record = mSupportedModes.valueAt(i);
if (record.hasMatchingMode(mode)) {
@@ -1229,8 +1237,6 @@ final class LocalDisplayAdapter extends DisplayAdapter {
/**
* @param displayToken Token for display associated with this backlight.
* @param isDefaultDisplay {@code true} if it is the default display.
- * @param forceSurfaceControl {@code true} if brightness should always be
- * set via SurfaceControl API.
*/
BacklightAdapter(IBinder displayToken, boolean isDefaultDisplay) {
mDisplayToken = displayToken;
diff --git a/services/core/java/com/android/server/location/LocationManagerService.java b/services/core/java/com/android/server/location/LocationManagerService.java
index 6deb19a53629..fd0b9454cfc1 100644
--- a/services/core/java/com/android/server/location/LocationManagerService.java
+++ b/services/core/java/com/android/server/location/LocationManagerService.java
@@ -70,6 +70,7 @@ import android.location.provider.IProviderRequestListener;
import android.location.provider.ProviderProperties;
import android.location.util.identity.CallerIdentity;
import android.os.Binder;
+import android.os.Build;
import android.os.Bundle;
import android.os.ICancellationSignal;
import android.os.ParcelFileDescriptor;
@@ -350,6 +351,22 @@ public class LocationManagerService extends ILocationManager.Stub {
void onSystemReady() {
mInjector.getSettingsHelper().addOnLocationEnabledChangedListener(
this::onLocationModeChanged);
+
+ if (Build.IS_DEBUGGABLE) {
+ // on debug builds, watch for location noteOps while location is off. there are some
+ // scenarios (emergency location) where this is expected, but generally this should
+ // rarely occur, and may indicate bugs. dump occurrences to logs for further evaluation
+ AppOpsManager appOps = Objects.requireNonNull(
+ mContext.getSystemService(AppOpsManager.class));
+ appOps.startWatchingNoted(
+ new int[]{AppOpsManager.OP_FINE_LOCATION, AppOpsManager.OP_COARSE_LOCATION},
+ (code, uid, packageName, attributionTag, flags, result) -> {
+ if (!isLocationEnabledForUser(UserHandle.getUserId(uid))) {
+ Log.w(TAG, "location noteOp with location off - "
+ + CallerIdentity.forTest(uid, 0, packageName, attributionTag));
+ }
+ });
+ }
}
void onSystemThirdPartyAppsCanStart() {
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java b/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java
index 6249a068f591..e1c011d821a7 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubClientBroker.java
@@ -46,6 +46,7 @@ import android.util.proto.ProtoOutputStream;
import com.android.server.location.ClientBrokerProto;
+import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -101,6 +102,11 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
private static final String TAG = "ContextHubClientBroker";
/**
+ * Internal only authorization value used when the auth state is unknown.
+ */
+ private static final int AUTHORIZATION_UNKNOWN = -1;
+
+ /**
* Message used by noteOp when this client receives a message from a nanoapp.
*/
private static final String RECEIVE_MSG_NOTE = "NanoappMessageDelivery ";
@@ -227,7 +233,7 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
if (mMessageChannelNanoappIdMap.containsKey(state.getNanoAppId())) {
List<String> permissions = state.getNanoAppPermissions();
updateNanoAppAuthState(state.getNanoAppId(),
- hasPermissions(permissions), false /* gracePeriodExpired */);
+ permissions, false /* gracePeriodExpired */);
}
}
}
@@ -344,32 +350,13 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
public int sendMessageToNanoApp(NanoAppMessage message) {
ContextHubServiceUtil.checkPermissions(mContext);
- int authState;
- synchronized (mMessageChannelNanoappIdMap) {
- // Default to the granted auth state. The true auth state will be checked async if it's
- // not denied.
- authState = mMessageChannelNanoappIdMap.getOrDefault(
- message.getNanoAppId(), AUTHORIZATION_GRANTED);
- if (authState == AUTHORIZATION_DENIED) {
- return ContextHubTransaction.RESULT_FAILED_PERMISSION_DENIED;
- }
- }
-
int result;
if (isRegistered()) {
- // Even though the auth state is currently not denied, query the nanoapp permissions
- // async and verify that the host app currently holds all the requisite permissions.
- // This can't be done synchronously due to the async query that needs to be performed to
- // obtain the nanoapp permissions.
- boolean initialNanoappMessage = false;
- synchronized (mMessageChannelNanoappIdMap) {
- if (mMessageChannelNanoappIdMap.get(message.getNanoAppId()) == null) {
- mMessageChannelNanoappIdMap.put(message.getNanoAppId(), AUTHORIZATION_GRANTED);
- initialNanoappMessage = true;
- }
- }
-
- if (initialNanoappMessage) {
+ int authState = mMessageChannelNanoappIdMap.getOrDefault(
+ message.getNanoAppId(), AUTHORIZATION_UNKNOWN);
+ if (authState == AUTHORIZATION_DENIED) {
+ return ContextHubTransaction.RESULT_FAILED_PERMISSION_DENIED;
+ } else if (authState == AUTHORIZATION_UNKNOWN) {
// Only check permissions the first time a nanoapp is queried since nanoapp
// permissions don't currently change at runtime. If the host permission changes
// later, that'll be checked by onOpChanged.
@@ -472,7 +459,8 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
List<String> messagePermissions) {
long nanoAppId = message.getNanoAppId();
- int authState = mMessageChannelNanoappIdMap.getOrDefault(nanoAppId, AUTHORIZATION_GRANTED);
+ int authState = updateNanoAppAuthState(nanoAppId, nanoappPermissions,
+ false /* gracePeriodExpired */);
// If in the grace period, the host may not receive any messages containing permissions
// covered data.
@@ -482,7 +470,9 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
return;
}
- if (authState == AUTHORIZATION_DENIED || !hasPermissions(nanoappPermissions)
+ // If in the grace period, don't check permissions state since it'll cause cleanup
+ // messages to be dropped.
+ if (authState == AUTHORIZATION_DENIED
|| !notePermissions(messagePermissions, RECEIVE_MSG_NOTE + nanoAppId)) {
Log.e(TAG, "Dropping message from " + Long.toHexString(nanoAppId) + ". " + mPackage
+ " doesn't have permission");
@@ -629,7 +619,8 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
if (timer != null) {
updateNanoAppAuthState(
- nanoAppId, false /* hasPermissions */, true /* gracePeriodExpired */);
+ nanoAppId, Collections.emptyList() /* nanoappPermissions */,
+ true /* gracePeriodExpired */);
}
}
@@ -643,24 +634,43 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
mTransactionManager.addTransaction(transaction);
}
- /**
- * Updates the latest authentication state for this client to be able to communicate with the
- * given nanoapp.
- */
- private void updateNanoAppAuthState(
- long nanoAppId, boolean hasPermissions, boolean gracePeriodExpired) {
- updateNanoAppAuthState(
- nanoAppId, hasPermissions, gracePeriodExpired, false /* forceDenied */);
+ private int updateNanoAppAuthState(
+ long nanoAppId, List<String> nanoappPermissions, boolean gracePeriodExpired) {
+ return updateNanoAppAuthState(
+ nanoAppId, nanoappPermissions, gracePeriodExpired, false /* forceDenied */);
}
- /* package */ void updateNanoAppAuthState(
- long nanoAppId, boolean hasPermissions, boolean gracePeriodExpired,
+ /**
+ * Updates the latest authenticatication state for the given nanoapp.
+ *
+ * @param nanoAppId the nanoapp that's auth state is being updated
+ * @param nanoappPermissions the Android permissions required to communicate with the nanoapp
+ * @param gracePeriodExpired indicates whether this invocation is a result of the grace period
+ * expiring
+ * @param forceDenied indicates that no matter what auth state is asssociated with this nanoapp
+ * it should transition to denied
+ * @return the latest auth state as of the completion of this method.
+ */
+ /* package */ int updateNanoAppAuthState(
+ long nanoAppId, List<String> nanoappPermissions, boolean gracePeriodExpired,
boolean forceDenied) {
int curAuthState;
int newAuthState;
synchronized (mMessageChannelNanoappIdMap) {
+ // Check permission granted state synchronously since this method can be invoked from
+ // multiple threads.
+ boolean hasPermissions = hasPermissions(nanoappPermissions);
+
curAuthState = mMessageChannelNanoappIdMap.getOrDefault(
- nanoAppId, AUTHORIZATION_GRANTED);
+ nanoAppId, AUTHORIZATION_UNKNOWN);
+ if (curAuthState == AUTHORIZATION_UNKNOWN) {
+ // If there's never been an auth check performed, start the state as granted so the
+ // appropriate state transitions occur below and clients don't receive a granted
+ // callback if they're determined to be in the granted state initially.
+ curAuthState = AUTHORIZATION_GRANTED;
+ mMessageChannelNanoappIdMap.put(nanoAppId, AUTHORIZATION_GRANTED);
+ }
+
newAuthState = curAuthState;
// The below logic ensures that only the following transitions are possible:
// GRANTED -> DENIED_GRACE_PERIOD only if permissions have been lost
@@ -701,6 +711,7 @@ public class ContextHubClientBroker extends IContextHubClient.Stub
// Don't send the callback in the synchronized block or it could end up in a deadlock.
sendAuthStateCallback(nanoAppId, newAuthState);
}
+ return newAuthState;
}
private void sendAuthStateCallback(long nanoAppId, int authState) {
diff --git a/services/core/java/com/android/server/location/contexthub/ContextHubService.java b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
index 1b8f0ded2e79..81c1e45504cb 100644
--- a/services/core/java/com/android/server/location/contexthub/ContextHubService.java
+++ b/services/core/java/com/android/server/location/contexthub/ContextHubService.java
@@ -942,8 +942,8 @@ public class ContextHubService extends IContextHubService.Stub {
mClientManager.forEachClientOfHub(contextHubId, client -> {
if (client.getPackageName().equals(packageName)) {
client.updateNanoAppAuthState(
- nanoAppId, false /* hasPermissions */, false /* gracePeriodExpired */,
- true /* forceDenied */);
+ nanoAppId, Collections.emptyList() /* nanoappPermissions */,
+ false /* gracePeriodExpired */, true /* forceDenied */);
}
});
}
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 5cb9d8ff3f31..9e2ca9d32315 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -781,7 +781,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
@GuardedBy("mLock")
private File mInheritedFilesBase;
@GuardedBy("mLock")
- private boolean mVerityFound;
+ private boolean mVerityFoundForApks;
/**
* Both flags should be guarded with mLock whenever changes need to be in lockstep.
@@ -1010,9 +1010,14 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
throw new IllegalArgumentException(
"DataLoader installation of APEX modules is not allowed.");
}
+
if (this.params.dataLoaderParams.getComponentName().getPackageName()
- == SYSTEM_DATA_LOADER_PACKAGE) {
- assertShellOrSystemCalling("System data loaders");
+ == SYSTEM_DATA_LOADER_PACKAGE && mContext.checkCallingOrSelfPermission(
+ Manifest.permission.USE_SYSTEM_DATA_LOADERS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("You need the "
+ + "com.android.permission.USE_SYSTEM_DATA_LOADERS permission "
+ + "to use system data loaders");
}
}
@@ -2717,8 +2722,8 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
"Missing existing base package");
}
- // Default to require only if existing base has fs-verity.
- mVerityFound = PackageManagerServiceUtils.isApkVerityEnabled()
+ // Default to require only if existing base apk has fs-verity.
+ mVerityFoundForApks = PackageManagerServiceUtils.isApkVerityEnabled()
&& params.mode == SessionParams.MODE_INHERIT_EXISTING
&& VerityUtils.hasFsverity(pkgInfo.applicationInfo.getBaseCodePath());
@@ -3013,34 +3018,18 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
@GuardedBy("mLock")
- private void maybeStageFsveritySignatureLocked(File origFile, File targetFile)
- throws PackageManagerException {
+ private void maybeStageFsveritySignatureLocked(File origFile, File targetFile,
+ boolean fsVerityRequired) throws PackageManagerException {
final File originalSignature = new File(
VerityUtils.getFsveritySignatureFilePath(origFile.getPath()));
- // Make sure .fsv_sig exists when it should, then resolve and stage it.
if (originalSignature.exists()) {
- // mVerityFound can only change from false to true here during the staging loop. Since
- // all or none of files should have .fsv_sig, this should only happen in the first time
- // (or never), otherwise bail out.
- if (!mVerityFound) {
- mVerityFound = true;
- if (mResolvedStagedFiles.size() > 1) {
- throw new PackageManagerException(INSTALL_FAILED_BAD_SIGNATURE,
- "Some file is missing fs-verity signature");
- }
- }
- } else {
- if (!mVerityFound) {
- return;
- }
+ final File stagedSignature = new File(
+ VerityUtils.getFsveritySignatureFilePath(targetFile.getPath()));
+ stageFileLocked(originalSignature, stagedSignature);
+ } else if (fsVerityRequired) {
throw new PackageManagerException(INSTALL_FAILED_BAD_SIGNATURE,
"Missing corresponding fs-verity signature to " + origFile);
}
-
- final File stagedSignature = new File(
- VerityUtils.getFsveritySignatureFilePath(targetFile.getPath()));
-
- stageFileLocked(originalSignature, stagedSignature);
}
@GuardedBy("mLock")
@@ -3059,7 +3048,11 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
DexMetadataHelper.buildDexMetadataPathForApk(targetFile.getName()));
stageFileLocked(dexMetadataFile, targetDexMetadataFile);
- maybeStageFsveritySignatureLocked(dexMetadataFile, targetDexMetadataFile);
+
+ // Also stage .dm.fsv_sig. .dm may be required to install with fs-verity signature on
+ // supported on older devices.
+ maybeStageFsveritySignatureLocked(dexMetadataFile, targetDexMetadataFile,
+ VerityUtils.isFsVeritySupported() && DexMetadataHelper.isFsVerityRequired());
}
private void storeBytesToInstallationFile(final String localPath, final String absolutePath,
@@ -3121,13 +3114,45 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
@GuardedBy("mLock")
+ private boolean isFsVerityRequiredForApk(File origFile, File targetFile)
+ throws PackageManagerException {
+ if (mVerityFoundForApks) {
+ return true;
+ }
+
+ // We haven't seen .fsv_sig for any APKs. Treat it as not required until we see one.
+ final File originalSignature = new File(
+ VerityUtils.getFsveritySignatureFilePath(origFile.getPath()));
+ if (!originalSignature.exists()) {
+ return false;
+ }
+ mVerityFoundForApks = true;
+
+ // When a signature is found, also check any previous staged APKs since they also need to
+ // have fs-verity signature consistently.
+ for (File file : mResolvedStagedFiles) {
+ if (!file.getName().endsWith(".apk")) {
+ continue;
+ }
+ // Ignore the current targeting file.
+ if (targetFile.getName().equals(file.getName())) {
+ continue;
+ }
+ throw new PackageManagerException(INSTALL_FAILED_BAD_SIGNATURE,
+ "Previously staged apk is missing fs-verity signature");
+ }
+ return true;
+ }
+
+ @GuardedBy("mLock")
private void resolveAndStageFileLocked(File origFile, File targetFile, String splitName)
throws PackageManagerException {
stageFileLocked(origFile, targetFile);
- // Stage fsverity signature if present.
- maybeStageFsveritySignatureLocked(origFile, targetFile);
- // Stage dex metadata (.dm) if present.
+ // Stage APK's fs-verity signature if present.
+ maybeStageFsveritySignatureLocked(origFile, targetFile,
+ isFsVerityRequiredForApk(origFile, targetFile));
+ // Stage dex metadata (.dm) and corresponding fs-verity signature if present.
maybeStageDexMetadataLocked(origFile, targetFile);
// Stage checksums (.digests) if present.
maybeStageDigestsLocked(origFile, targetFile, splitName);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 14d15ac49227..2a3feb123dd9 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -316,7 +316,6 @@ import android.util.ExceptionUtils;
import android.util.IntArray;
import android.util.Log;
import android.util.LogPrinter;
-import android.util.LongSparseArray;
import android.util.LongSparseLongArray;
import android.util.MathUtils;
import android.util.PackageUtils;
@@ -401,6 +400,7 @@ import com.android.server.utils.TimingsTraceAndSlog;
import com.android.server.utils.Watchable;
import com.android.server.utils.Watched;
import com.android.server.utils.WatchedArrayMap;
+import com.android.server.utils.WatchedLongSparseArray;
import com.android.server.utils.WatchedSparseBooleanArray;
import com.android.server.utils.Watcher;
import com.android.server.wm.ActivityTaskManagerInternal;
@@ -1402,10 +1402,10 @@ public class PackageManagerService extends IPackageManager.Stub
// Currently known shared libraries.
@Watched
- final WatchedArrayMap<String, LongSparseArray<SharedLibraryInfo>> mSharedLibraries =
- new WatchedArrayMap<>();
+ final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>>
+ mSharedLibraries = new WatchedArrayMap<>();
@Watched
- final WatchedArrayMap<String, LongSparseArray<SharedLibraryInfo>>
+ final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>>
mStaticLibsByDeclaringPackage = new WatchedArrayMap<>();
// Mapping from instrumentation class names to info about them.
@@ -1756,6 +1756,11 @@ public class PackageManagerService extends IPackageManager.Stub
public boolean filterAppAccess(String packageName, int callingUid, int userId) {
return mPmInternal.filterAppAccess(packageName, callingUid, userId);
}
+
+ @Override
+ public int[] getAllUserIds() {
+ return mUserManager.getUserIds();
+ }
}
/**
@@ -1786,8 +1791,8 @@ public class PackageManagerService extends IPackageManager.Stub
public final Settings settings;
public final SparseIntArray isolatedOwners;
public final WatchedArrayMap<String, AndroidPackage> packages;
- public final WatchedArrayMap<String, LongSparseArray<SharedLibraryInfo>> sharedLibs;
- public final WatchedArrayMap<String, LongSparseArray<SharedLibraryInfo>> staticLibs;
+ public final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>> sharedLibs;
+ public final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>> staticLibs;
public final WatchedArrayMap<ComponentName, ParsedInstrumentation> instrumentation;
public final WatchedSparseBooleanArray webInstantAppsDisabled;
public final ComponentName resolveComponentName;
@@ -2005,9 +2010,9 @@ public class PackageManagerService extends IPackageManager.Stub
private final WatchedArrayMap<String, AndroidPackage> mPackages;
private final WatchedArrayMap<ComponentName, ParsedInstrumentation>
mInstrumentation;
- private final WatchedArrayMap<String, LongSparseArray<SharedLibraryInfo>>
+ private final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>>
mStaticLibsByDeclaringPackage;
- private final WatchedArrayMap<String, LongSparseArray<SharedLibraryInfo>>
+ private final WatchedArrayMap<String, WatchedLongSparseArray<SharedLibraryInfo>>
mSharedLibraries;
private final ComponentName mLocalResolveComponentName;
private final ActivityInfo mResolveActivity;
@@ -3546,7 +3551,7 @@ public class PackageManagerService extends IPackageManager.Stub
packageName = normalizedPackageName != null ? normalizedPackageName : packageName;
// Is this a static library?
- LongSparseArray<SharedLibraryInfo> versionedLib =
+ WatchedLongSparseArray<SharedLibraryInfo> versionedLib =
mStaticLibsByDeclaringPackage.get(packageName);
if (versionedLib == null || versionedLib.size() <= 0) {
return packageName;
@@ -4701,6 +4706,10 @@ public class PackageManagerService extends IPackageManager.Stub
// and an image with the flag set false does not use snapshots.
private static final boolean SNAPSHOT_ENABLED = true;
+ // The per-instance snapshot disable/enable flag. This is generally set to false in
+ // test instances and set to SNAPSHOT_ENABLED in operational instances.
+ private final boolean mSnapshotEnabled;
+
/**
* Return the live computer.
*/
@@ -4713,7 +4722,7 @@ public class PackageManagerService extends IPackageManager.Stub
* The live computer will be returned if snapshots are disabled.
*/
private Computer snapshotComputer() {
- if (!SNAPSHOT_ENABLED) {
+ if (!mSnapshotEnabled) {
return mLiveComputer;
}
if (Thread.holdsLock(mLock)) {
@@ -6048,15 +6057,12 @@ public class PackageManagerService extends IPackageManager.Stub
mOverlayConfigSignaturePackage = testParams.overlayConfigSignaturePackage;
mResolveComponentName = testParams.resolveComponentName;
- // Create the computer as soon as the state objects have been installed. The
- // cached computer is the same as the live computer until the end of the
- // constructor, at which time the invalidation method updates it. The cache is
- // corked initially to ensure a cached computer is not built until the end of the
- // constructor.
- sSnapshotCorked = true;
+ // Disable snapshots in this instance of PackageManagerService, which is only used
+ // for testing. The instance still needs a live computer. The snapshot computer
+ // is set to null since it must never be used by this instance.
+ mSnapshotEnabled = false;
mLiveComputer = createLiveComputer();
- mSnapshotComputer = mLiveComputer;
- registerObserver();
+ mSnapshotComputer = null;
mPackages.putAll(testParams.packages);
mEnableFreeCacheV2 = testParams.enableFreeCacheV2;
@@ -6069,7 +6075,6 @@ public class PackageManagerService extends IPackageManager.Stub
mIncrementalVersion = testParams.incrementalVersion;
invalidatePackageInfoCache();
- sSnapshotCorked = false;
}
public PackageManagerService(Injector injector, boolean onlyCore, boolean factoryTest,
@@ -6215,6 +6220,7 @@ public class PackageManagerService extends IPackageManager.Stub
// constructor, at which time the invalidation method updates it. The cache is
// corked initially to ensure a cached computer is not built until the end of the
// constructor.
+ mSnapshotEnabled = SNAPSHOT_ENABLED;
sSnapshotCorked = true;
mLiveComputer = createLiveComputer();
mSnapshotComputer = mLiveComputer;
@@ -8038,7 +8044,7 @@ public class PackageManagerService extends IPackageManager.Stub
final int[] allUsers = mUserManager.getUserIds();
final int libCount = mSharedLibraries.size();
for (int i = 0; i < libCount; i++) {
- final LongSparseArray<SharedLibraryInfo> versionedLib
+ final WatchedLongSparseArray<SharedLibraryInfo> versionedLib
= mSharedLibraries.valueAt(i);
if (versionedLib == null) {
continue;
@@ -8303,7 +8309,8 @@ public class PackageManagerService extends IPackageManager.Stub
final int libCount = mSharedLibraries.size();
for (int i = 0; i < libCount; i++) {
- LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.valueAt(i);
+ WatchedLongSparseArray<SharedLibraryInfo> versionedLib =
+ mSharedLibraries.valueAt(i);
if (versionedLib == null) {
continue;
}
@@ -8372,7 +8379,8 @@ public class PackageManagerService extends IPackageManager.Stub
int libraryCount = mSharedLibraries.size();
for (int i = 0; i < libraryCount; i++) {
- LongSparseArray<SharedLibraryInfo> versionedLibrary = mSharedLibraries.valueAt(i);
+ WatchedLongSparseArray<SharedLibraryInfo> versionedLibrary =
+ mSharedLibraries.valueAt(i);
if (versionedLibrary == null) {
continue;
}
@@ -8533,7 +8541,8 @@ public class PackageManagerService extends IPackageManager.Stub
Set<String> libs = null;
final int libCount = mSharedLibraries.size();
for (int i = 0; i < libCount; i++) {
- LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.valueAt(i);
+ WatchedLongSparseArray<SharedLibraryInfo> versionedLib =
+ mSharedLibraries.valueAt(i);
if (versionedLib == null) {
continue;
}
@@ -8959,6 +8968,10 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public List<String> getAllPackages() {
+ // Allow iorapd to call this method.
+ if (Binder.getCallingUid() != Process.IORAPD_UID) {
+ enforceSystemOrRootOrShell("getAllPackages is limited to privileged callers");
+ }
final int callingUid = Binder.getCallingUid();
final int callingUserId = UserHandle.getUserId(callingUid);
synchronized (mLock) {
@@ -9837,7 +9850,7 @@ public class PackageManagerService extends IPackageManager.Stub
private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
String resolvedType, int flags, int userId) {
- return liveComputer().queryIntentActivitiesInternal(intent,
+ return snapshotComputer().queryIntentActivitiesInternal(intent,
resolvedType, flags, userId);
}
@@ -10324,7 +10337,7 @@ public class PackageManagerService extends IPackageManager.Stub
private @NonNull List<ResolveInfo> queryIntentServicesInternal(Intent intent,
String resolvedType, int flags, int userId, int callingUid,
boolean includeInstantApps) {
- return liveComputer().queryIntentServicesInternal(intent,
+ return snapshotComputer().queryIntentServicesInternal(intent,
resolvedType, flags, userId, callingUid,
includeInstantApps);
}
@@ -12198,10 +12211,10 @@ public class PackageManagerService extends IPackageManager.Stub
@Nullable
private static SharedLibraryInfo getSharedLibraryInfo(String name, long version,
- Map<String, LongSparseArray<SharedLibraryInfo>> existingLibraries,
- @Nullable Map<String, LongSparseArray<SharedLibraryInfo>> newLibraries) {
+ Map<String, WatchedLongSparseArray<SharedLibraryInfo>> existingLibraries,
+ @Nullable Map<String, WatchedLongSparseArray<SharedLibraryInfo>> newLibraries) {
if (newLibraries != null) {
- final LongSparseArray<SharedLibraryInfo> versionedLib = newLibraries.get(name);
+ final WatchedLongSparseArray<SharedLibraryInfo> versionedLib = newLibraries.get(name);
SharedLibraryInfo info = null;
if (versionedLib != null) {
info = versionedLib.get(version);
@@ -12210,7 +12223,7 @@ public class PackageManagerService extends IPackageManager.Stub
return info;
}
}
- final LongSparseArray<SharedLibraryInfo> versionedLib = existingLibraries.get(name);
+ final WatchedLongSparseArray<SharedLibraryInfo> versionedLib = existingLibraries.get(name);
if (versionedLib == null) {
return null;
}
@@ -12218,7 +12231,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
private SharedLibraryInfo getLatestSharedLibraVersionLPr(AndroidPackage pkg) {
- LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(
+ WatchedLongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(
pkg.getStaticSharedLibName());
if (versionedLib == null) {
return null;
@@ -12523,8 +12536,8 @@ public class PackageManagerService extends IPackageManager.Stub
private static ArrayList<SharedLibraryInfo> collectSharedLibraryInfos(AndroidPackage pkg,
Map<String, AndroidPackage> availablePackages,
- @NonNull final Map<String, LongSparseArray<SharedLibraryInfo>> existingLibraries,
- @Nullable final Map<String, LongSparseArray<SharedLibraryInfo>> newLibraries)
+ @NonNull final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> existingLibraries,
+ @Nullable final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> newLibraries)
throws PackageManagerException {
if (pkg == null) {
return null;
@@ -12621,8 +12634,8 @@ public class PackageManagerService extends IPackageManager.Stub
@NonNull String packageName, boolean required, int targetSdk,
@Nullable ArrayList<SharedLibraryInfo> outUsedLibraries,
@NonNull final Map<String, AndroidPackage> availablePackages,
- @NonNull final Map<String, LongSparseArray<SharedLibraryInfo>> existingLibraries,
- @Nullable final Map<String, LongSparseArray<SharedLibraryInfo>> newLibraries)
+ @NonNull final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> existingLibraries,
+ @Nullable final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> newLibraries)
throws PackageManagerException {
final int libCount = requestedLibraries.size();
for (int i = 0; i < libCount; i++) {
@@ -14043,7 +14056,7 @@ public class PackageManagerService extends IPackageManager.Stub
long minVersionCode = Long.MIN_VALUE;
long maxVersionCode = Long.MAX_VALUE;
- LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(
+ WatchedLongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(
pkg.getStaticSharedLibName());
if (versionedLib != null) {
final int versionCount = versionedLib.size();
@@ -14271,8 +14284,8 @@ public class PackageManagerService extends IPackageManager.Stub
}
private static boolean sharedLibExists(final String name, final long version,
- Map<String, LongSparseArray<SharedLibraryInfo>> librarySource) {
- LongSparseArray<SharedLibraryInfo> versionedLib = librarySource.get(name);
+ Map<String, WatchedLongSparseArray<SharedLibraryInfo>> librarySource) {
+ WatchedLongSparseArray<SharedLibraryInfo> versionedLib = librarySource.get(name);
if (versionedLib != null && versionedLib.indexOfKey(version) >= 0) {
return true;
}
@@ -14282,9 +14295,9 @@ public class PackageManagerService extends IPackageManager.Stub
@GuardedBy("mLock")
private void commitSharedLibraryInfoLocked(SharedLibraryInfo libraryInfo) {
final String name = libraryInfo.getName();
- LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
+ WatchedLongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
if (versionedLib == null) {
- versionedLib = new LongSparseArray<>();
+ versionedLib = new WatchedLongSparseArray<>();
mSharedLibraries.put(name, versionedLib);
}
final String declaringPackageName = libraryInfo.getDeclaringPackage().getPackageName();
@@ -14295,7 +14308,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
private boolean removeSharedLibraryLPw(String name, long version) {
- LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
+ WatchedLongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
if (versionedLib == null) {
return false;
}
@@ -18290,7 +18303,7 @@ public class PackageManagerService extends IPackageManager.Stub
public final Map<String, ScanResult> scannedPackages;
public final Map<String, AndroidPackage> allPackages;
- public final Map<String, LongSparseArray<SharedLibraryInfo>> sharedLibrarySource;
+ public final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> sharedLibrarySource;
public final Map<String, InstallArgs> installArgs;
public final Map<String, PackageInstalledInfo> installResults;
public final Map<String, PrepareResult> preparedPackages;
@@ -18301,7 +18314,7 @@ public class PackageManagerService extends IPackageManager.Stub
Map<String, InstallArgs> installArgs,
Map<String, PackageInstalledInfo> installResults,
Map<String, PrepareResult> preparedPackages,
- Map<String, LongSparseArray<SharedLibraryInfo>> sharedLibrarySource,
+ Map<String, WatchedLongSparseArray<SharedLibraryInfo>> sharedLibrarySource,
Map<String, AndroidPackage> allPackages,
Map<String, VersionInfo> versionInfos,
Map<String, PackageSetting> lastStaticSharedLibSettings) {
@@ -18316,7 +18329,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
private ReconcileRequest(Map<String, ScanResult> scannedPackages,
- Map<String, LongSparseArray<SharedLibraryInfo>> sharedLibrarySource,
+ Map<String, WatchedLongSparseArray<SharedLibraryInfo>> sharedLibrarySource,
Map<String, AndroidPackage> allPackages,
Map<String, VersionInfo> versionInfos,
Map<String, PackageSetting> lastStaticSharedLibSettings) {
@@ -18413,7 +18426,7 @@ public class PackageManagerService extends IPackageManager.Stub
combinedPackages.putAll(request.allPackages);
- final Map<String, LongSparseArray<SharedLibraryInfo>> incomingSharedLibraries =
+ final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> incomingSharedLibraries =
new ArrayMap<>();
for (String installPackageName : scannedPackages.keySet()) {
@@ -18637,7 +18650,7 @@ public class PackageManagerService extends IPackageManager.Stub
*/
private static List<SharedLibraryInfo> getAllowedSharedLibInfos(
ScanResult scanResult,
- Map<String, LongSparseArray<SharedLibraryInfo>> existingSharedLibraries) {
+ Map<String, WatchedLongSparseArray<SharedLibraryInfo>> existingSharedLibraries) {
// Let's used the parsed package as scanResult.pkgSetting may be null
final ParsedPackage parsedPackage = scanResult.request.parsedPackage;
if (scanResult.staticSharedLibraryInfo == null
@@ -18707,7 +18720,7 @@ public class PackageManagerService extends IPackageManager.Stub
* added.
*/
private static boolean addSharedLibraryToPackageVersionMap(
- Map<String, LongSparseArray<SharedLibraryInfo>> target,
+ Map<String, WatchedLongSparseArray<SharedLibraryInfo>> target,
SharedLibraryInfo library) {
final String name = library.getName();
if (target.containsKey(name)) {
@@ -18719,7 +18732,7 @@ public class PackageManagerService extends IPackageManager.Stub
return false;
}
} else {
- target.put(name, new LongSparseArray<>());
+ target.put(name, new WatchedLongSparseArray<>());
}
target.get(name).put(library.getLongVersion(), library);
return true;
@@ -23842,7 +23855,7 @@ public class PackageManagerService extends IPackageManager.Stub
final int numSharedLibraries = mSharedLibraries.size();
for (int index = 0; index < numSharedLibraries; index++) {
final String libName = mSharedLibraries.keyAt(index);
- LongSparseArray<SharedLibraryInfo> versionedLib
+ WatchedLongSparseArray<SharedLibraryInfo> versionedLib
= mSharedLibraries.get(libName);
if (versionedLib == null) {
continue;
@@ -24191,7 +24204,7 @@ public class PackageManagerService extends IPackageManager.Stub
final int count = mSharedLibraries.size();
for (int i = 0; i < count; i++) {
final String libName = mSharedLibraries.keyAt(i);
- LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(libName);
+ WatchedLongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(libName);
if (versionedLib == null) {
continue;
}
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java
index 5d4370ae5dd4..b6ea901ecd6b 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationManagerInternal.java
@@ -358,5 +358,8 @@ public interface DomainVerificationManagerInternal extends DomainVerificationMan
@Nullable
AndroidPackage getPackageLocked(@NonNull String pkgName);
+
+ @UserIdInt
+ int[] getAllUserIds();
}
}
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
index e5ed774fcaa8..8e5aead05f96 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationService.java
@@ -423,12 +423,8 @@ public class DomainVerificationService extends SystemService
for (int pkgStateIndex = 0; pkgStateIndex < pkgStateSize; pkgStateIndex++) {
DomainVerificationPkgState pkgState = mAttachedPkgStates.valueAt(pkgStateIndex);
if (userId == UserHandle.USER_ALL) {
- SparseArray<DomainVerificationUserState> userStates =
- pkgState.getUserSelectionStates();
- int userStatesSize = userStates.size();
- for (int userStateIndex = 0; userStateIndex < userStatesSize;
- userStateIndex++) {
- userStates.valueAt(userStateIndex)
+ for (int aUserId : mConnection.getAllUserIds()) {
+ pkgState.getOrCreateUserSelectionState(aUserId)
.setLinkHandlingAllowed(allowed);
}
} else {
@@ -436,7 +432,6 @@ public class DomainVerificationService extends SystemService
.setLinkHandlingAllowed(allowed);
}
}
-
}
} else {
synchronized (mLock) {
@@ -500,28 +495,33 @@ public class DomainVerificationService extends SystemService
@Override
public void setDomainVerificationUserSelectionInternal(@UserIdInt int userId,
- @Nullable String packageName, boolean enabled, @NonNull ArraySet<String> domains)
+ @Nullable String packageName, boolean enabled, @Nullable ArraySet<String> domains)
throws NameNotFoundException {
mEnforcer.assertInternal(mConnection.getCallingUid());
+
if (packageName == null) {
synchronized (mLock) {
Set<String> validDomains = new ArraySet<>();
-
int size = mAttachedPkgStates.size();
for (int index = 0; index < size; index++) {
DomainVerificationPkgState pkgState = mAttachedPkgStates.valueAt(index);
String pkgName = pkgState.getPackageName();
PackageSetting pkgSetting = mConnection.getPackageSettingLocked(pkgName);
- if (pkgSetting == null || pkgSetting.getPkg() == null) {
+ AndroidPackage pkg = pkgSetting == null ? null : pkgSetting.getPkg();
+ if (pkg == null) {
continue;
}
- validDomains.clear();
- validDomains.addAll(domains);
+ if (domains == null) {
+ validDomains = mCollector.collectAllWebDomains(pkg);
+ } else {
+ validDomains.clear();
+ validDomains.addAll(domains);
+ }
setDomainVerificationUserSelectionInternal(userId, pkgState,
- pkgSetting.getPkg(), enabled, validDomains);
+ pkg, enabled, validDomains);
}
}
} else {
@@ -532,12 +532,16 @@ public class DomainVerificationService extends SystemService
}
PackageSetting pkgSetting = mConnection.getPackageSettingLocked(packageName);
- if (pkgSetting == null || pkgSetting.getPkg() == null) {
+ AndroidPackage pkg = pkgSetting == null ? null : pkgSetting.getPkg();
+ if (pkg == null) {
throw DomainVerificationUtils.throwPackageUnavailable(packageName);
}
+ Set<String> validDomains =
+ domains == null ? mCollector.collectAllWebDomains(pkg) : domains;
+
setDomainVerificationUserSelectionInternal(userId, pkgState, pkgSetting.getPkg(),
- enabled, domains);
+ enabled, validDomains);
}
}
@@ -549,12 +553,10 @@ public class DomainVerificationService extends SystemService
boolean enabled, Set<String> domains) {
domains.retainAll(mCollector.collectAllWebDomains(pkg));
- SparseArray<DomainVerificationUserState> userStates =
- pkgState.getUserSelectionStates();
if (userId == UserHandle.USER_ALL) {
- int size = userStates.size();
- for (int index = 0; index < size; index++) {
- DomainVerificationUserState userState = userStates.valueAt(index);
+ for (int aUserId : mConnection.getAllUserIds()) {
+ DomainVerificationUserState userState =
+ pkgState.getOrCreateUserSelectionState(aUserId);
if (enabled) {
userState.addHosts(domains);
} else {
diff --git a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationShell.java b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationShell.java
index 7f9e75aa2926..d083d11cb2e2 100644
--- a/services/core/java/com/android/server/pm/verify/domain/DomainVerificationShell.java
+++ b/services/core/java/com/android/server/pm/verify/domain/DomainVerificationShell.java
@@ -250,6 +250,10 @@ public class DomainVerificationShell {
return false;
}
+ if (domains.size() == 1 && domains.contains("all")) {
+ domains = null;
+ }
+
try {
mCallback.setDomainVerificationUserSelectionInternal(userId,
packageName, enabled, domains);
@@ -446,10 +450,10 @@ public class DomainVerificationShell {
* @param packageName the package whose state to change, or all packages if non is
* specified
* @param enabled whether the domain is now approved by the user
- * @param domains the set of domains to change
+ * @param domains the set of domains to change, or null to affect all domains
*/
void setDomainVerificationUserSelectionInternal(@UserIdInt int userId,
- @Nullable String packageName, boolean enabled, @NonNull ArraySet<String> domains)
+ @Nullable String packageName, boolean enabled, @Nullable ArraySet<String> domains)
throws PackageManager.NameNotFoundException;
/**
diff --git a/services/core/java/com/android/server/power/FaceDownDetector.java b/services/core/java/com/android/server/power/FaceDownDetector.java
new file mode 100644
index 000000000000..2442079bec8b
--- /dev/null
+++ b/services/core/java/com/android/server/power/FaceDownDetector.java
@@ -0,0 +1,456 @@
+/*
+ * 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.server.power;
+
+import static android.provider.DeviceConfig.NAMESPACE_ATTENTION_MANAGER_SERVICE;
+
+import android.annotation.NonNull;
+import android.app.ActivityThread;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorEventListener;
+import android.hardware.SensorManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.SystemClock;
+import android.provider.DeviceConfig;
+import android.util.Slog;
+
+import com.android.internal.util.FrameworkStatsLog;
+
+import java.io.PrintWriter;
+import java.time.Duration;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Consumer;
+
+/**
+ * Class used to detect when the phone is placed face down. This is used for Flip to Screen Off. A
+ * client can use this detector to trigger state changes like screen off when the phone is face
+ * down.
+ */
+public class FaceDownDetector implements SensorEventListener {
+
+ private static final String TAG = "FaceDownDetector";
+ private static final boolean DEBUG = false;
+
+ private static final int SCREEN_OFF_RESULT =
+ FrameworkStatsLog.FACE_DOWN_REPORTED__FACE_DOWN_RESPONSE__SCREEN_OFF;
+ private static final int USER_INTERACTION =
+ FrameworkStatsLog.FACE_DOWN_REPORTED__FACE_DOWN_RESPONSE__USER_INTERACTION;
+ private static final int UNFLIP =
+ FrameworkStatsLog.FACE_DOWN_REPORTED__FACE_DOWN_RESPONSE__UNFLIP;
+
+ /**
+ * Used by the ExponentialMovingAverage accelerations, this determines how quickly the
+ * average can change. A number closer to 1 will mean it will take longer to change.
+ */
+ private static final float MOVING_AVERAGE_WEIGHT = 0.5f;
+
+ /** DeviceConfig flag name, if {@code true}, enables Face Down features. */
+ private static final String KEY_FEATURE_ENABLED = "enable_flip_to_screen_off";
+
+ /** Default value in absence of {@link DeviceConfig} override. */
+ private static final boolean DEFAULT_FEATURE_ENABLED = true;
+
+ private boolean mIsEnabled;
+
+ /**
+ * DeviceConfig flag name, determines how long to disable sensor when user interacts while
+ * device is flipped.
+ */
+ private static final String KEY_INTERACTION_BACKOFF = "face_down_interaction_backoff_millis";
+
+ /** Default value in absence of {@link DeviceConfig} override. */
+ private static final long DEFAULT_INTERACTION_BACKOFF = 60_000;
+
+ private long mUserInteractionBackoffMillis;
+
+ /**
+ * DeviceConfig flag name, defines the max change in acceleration which will prevent face down
+ * due to movement.
+ */
+ static final String KEY_ACCELERATION_THRESHOLD = "acceleration_threshold";
+
+ /** Default value in absence of {@link DeviceConfig} override. */
+ static final float DEFAULT_ACCELERATION_THRESHOLD = 0.2f;
+
+ private float mAccelerationThreshold;
+
+ /**
+ * DeviceConfig flag name, defines the maximum z-axis acceleration that will indicate the phone
+ * is face down.
+ */
+ static final String KEY_Z_ACCELERATION_THRESHOLD = "z_acceleration_threshold";
+
+ /** Default value in absence of {@link DeviceConfig} override. */
+ static final float DEFAULT_Z_ACCELERATION_THRESHOLD = -9.5f;
+
+ private float mZAccelerationThreshold;
+
+ /**
+ * After going face down, we relax the threshold to make it more difficult to exit face down
+ * than to enter it.
+ */
+ private float mZAccelerationThresholdLenient;
+
+ /**
+ * DeviceConfig flag name, defines the minimum amount of time that has to pass while the phone
+ * is face down and not moving in order to trigger face down behavior, in milliseconds.
+ */
+ static final String KEY_TIME_THRESHOLD_MILLIS = "time_threshold_millis";
+
+ /** Default value in absence of {@link DeviceConfig} override. */
+ static final long DEFAULT_TIME_THRESHOLD_MILLIS = 1_000L;
+
+ private Duration mTimeThreshold;
+
+ private Sensor mAccelerometer;
+ private SensorManager mSensorManager;
+ private final Consumer<Boolean> mOnFlip;
+
+ /** Values we store for logging purposes. */
+ private long mLastFlipTime = 0L;
+ public int mPreviousResultType = 0;
+ public long mPreviousResultTime = 0L;
+ private long mMillisSaved = 0L;
+
+ private final ExponentialMovingAverage mCurrentXYAcceleration =
+ new ExponentialMovingAverage(MOVING_AVERAGE_WEIGHT);
+ private final ExponentialMovingAverage mCurrentZAcceleration =
+ new ExponentialMovingAverage(MOVING_AVERAGE_WEIGHT);
+
+ private boolean mFaceDown = false;
+ private boolean mActive = false;
+
+ private float mPrevAcceleration = 0;
+ private long mPrevAccelerationTime = 0;
+
+ private boolean mZAccelerationIsFaceDown = false;
+ private long mZAccelerationFaceDownTime = 0L;
+
+ private final Handler mHandler;
+ private final Runnable mUserActivityRunnable;
+
+ public FaceDownDetector(@NonNull Consumer<Boolean> onFlip) {
+ mOnFlip = Objects.requireNonNull(onFlip);
+ mHandler = new Handler(Looper.getMainLooper());
+ mUserActivityRunnable = () -> {
+ if (mFaceDown) {
+ exitFaceDown(USER_INTERACTION, SystemClock.uptimeMillis() - mLastFlipTime);
+ checkAndUpdateActiveState(false);
+ }
+ };
+ }
+
+ /** Initializes the FaceDownDetector and all necessary listeners. */
+ public void systemReady(Context context) {
+ mSensorManager = context.getSystemService(SensorManager.class);
+ mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
+ readValuesFromDeviceConfig();
+ checkAndUpdateActiveState(true);
+ DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+ ActivityThread.currentApplication().getMainExecutor(),
+ (properties) -> onDeviceConfigChange(properties.getKeyset()));
+ IntentFilter intentFilter = new IntentFilter();
+ intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
+ intentFilter.addAction(Intent.ACTION_SCREEN_ON);
+ intentFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
+ context.registerReceiver(new ScreenStateReceiver(), intentFilter);
+ }
+
+ /**
+ * Sets the active state of the detector. If false, we will not process accelerometer changes.
+ */
+ private void checkAndUpdateActiveState(boolean active) {
+ if (mIsEnabled && mActive != active) {
+ final long currentTime = SystemClock.uptimeMillis();
+ // Don't make active if there was recently a user interaction while face down.
+ if (active && mPreviousResultType == USER_INTERACTION
+ && currentTime - mPreviousResultTime < mUserInteractionBackoffMillis) {
+ return;
+ }
+ if (DEBUG) Slog.d(TAG, "Update active - " + active);
+ mActive = active;
+ if (!active) {
+ if (mFaceDown && mPreviousResultTime != USER_INTERACTION) {
+ mPreviousResultType = SCREEN_OFF_RESULT;
+ mPreviousResultTime = currentTime;
+ }
+ mSensorManager.unregisterListener(this);
+ mFaceDown = false;
+ mOnFlip.accept(false);
+ } else {
+ if (mPreviousResultType == SCREEN_OFF_RESULT) {
+ logScreenOff();
+ }
+ mSensorManager.registerListener(
+ this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
+ }
+ }
+ }
+
+ /** Prints state information about FaceDownDetector */
+ public void dump(PrintWriter pw) {
+ pw.println("FaceDownDetector:");
+ pw.println(" mFaceDown=" + mFaceDown);
+ pw.println(" mActive=" + mActive);
+ pw.println(" mLastFlipTime=" + mLastFlipTime);
+ pw.println(" mUserInteractionBackoffMillis=" + mUserInteractionBackoffMillis);
+ pw.println(" mPreviousResultTime=" + mPreviousResultTime);
+ pw.println(" mPreviousResultType=" + mPreviousResultType);
+ pw.println(" mMillisSaved=" + mMillisSaved);
+ pw.println(" mZAccelerationThreshold=" + mZAccelerationThreshold);
+ pw.println(" mAccelerationThreshold=" + mAccelerationThreshold);
+ pw.println(" mTimeThreshold=" + mTimeThreshold);
+ }
+
+ @Override
+ public void onSensorChanged(SensorEvent event) {
+ if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER) return;
+ if (!mActive || !mIsEnabled) return;
+
+ final float x = event.values[0];
+ final float y = event.values[1];
+ mCurrentXYAcceleration.updateMovingAverage(x * x + y * y);
+ mCurrentZAcceleration.updateMovingAverage(event.values[2]);
+
+ // Detect movement
+ // If the x, y acceleration is within the acc threshold for at least a length of time longer
+ // than the time threshold, we set moving to true.
+ final long curTime = event.timestamp;
+ if (Math.abs(mCurrentXYAcceleration.mMovingAverage - mPrevAcceleration)
+ > mAccelerationThreshold) {
+ mPrevAcceleration = mCurrentXYAcceleration.mMovingAverage;
+ mPrevAccelerationTime = curTime;
+ }
+ final boolean moving = curTime - mPrevAccelerationTime <= mTimeThreshold.toNanos();
+
+ // If the z acceleration is beyond the gravity/z-acceleration threshold for at least a
+ // length of time longer than the time threshold, we set isFaceDownForPeriod to true.
+ final float zAccelerationThreshold =
+ mFaceDown ? mZAccelerationThresholdLenient : mZAccelerationThreshold;
+ final boolean isCurrentlyFaceDown =
+ mCurrentZAcceleration.mMovingAverage < zAccelerationThreshold;
+ final boolean isFaceDownForPeriod = isCurrentlyFaceDown
+ && mZAccelerationIsFaceDown
+ && curTime - mZAccelerationFaceDownTime > mTimeThreshold.toNanos();
+ if (isCurrentlyFaceDown && !mZAccelerationIsFaceDown) {
+ mZAccelerationFaceDownTime = curTime;
+ mZAccelerationIsFaceDown = true;
+ } else if (!isCurrentlyFaceDown) {
+ mZAccelerationIsFaceDown = false;
+ }
+
+
+ if (!moving && isFaceDownForPeriod && !mFaceDown) {
+ faceDownDetected();
+ } else if (!isFaceDownForPeriod && mFaceDown) {
+ unFlipDetected();
+ }
+ }
+
+ @Override
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {}
+
+ private void faceDownDetected() {
+ if (DEBUG) Slog.d(TAG, "Triggered faceDownDetected.");
+ mLastFlipTime = SystemClock.uptimeMillis();
+ mFaceDown = true;
+ mOnFlip.accept(true);
+ }
+
+ private void unFlipDetected() {
+ if (DEBUG) Slog.d(TAG, "Triggered exitFaceDown");
+ exitFaceDown(UNFLIP, SystemClock.uptimeMillis() - mLastFlipTime);
+ }
+
+ /**
+ * The user interacted with the screen while face down, indicated the phone is in use.
+ * We log this event and temporarily make this detector inactive.
+ */
+ public void userActivity() {
+ mHandler.post(mUserActivityRunnable);
+ }
+
+ private void exitFaceDown(int resultType, long millisSinceFlip) {
+ FrameworkStatsLog.write(FrameworkStatsLog.FACE_DOWN_REPORTED,
+ resultType,
+ millisSinceFlip,
+ /* millis_until_normal_timeout= */ 0L,
+ /* millis_until_next_screen_on= */ 0L);
+ mFaceDown = false;
+ mLastFlipTime = 0L;
+ mPreviousResultType = resultType;
+ mPreviousResultTime = SystemClock.uptimeMillis();
+ mOnFlip.accept(false);
+ }
+
+ private void logScreenOff() {
+ if (mPreviousResultType == SCREEN_OFF_RESULT) {
+ final long currentTime = SystemClock.uptimeMillis();
+ FrameworkStatsLog.write(FrameworkStatsLog.FACE_DOWN_REPORTED,
+ mPreviousResultType,
+ /* millis_since_flip= */ mPreviousResultTime - mLastFlipTime,
+ mMillisSaved,
+ /* millis_until_next_screen_on= */ currentTime - mPreviousResultTime);
+ mPreviousResultType = -1;
+ }
+ }
+
+ private boolean isEnabled() {
+ return DeviceConfig.getBoolean(NAMESPACE_ATTENTION_MANAGER_SERVICE, KEY_FEATURE_ENABLED,
+ DEFAULT_FEATURE_ENABLED);
+ }
+
+ private float getAccelerationThreshold() {
+ return getFloatFlagValue(KEY_ACCELERATION_THRESHOLD,
+ DEFAULT_ACCELERATION_THRESHOLD,
+ -2.0f,
+ 2.0f);
+ }
+
+ private float getZAccelerationThreshold() {
+ return getFloatFlagValue(KEY_Z_ACCELERATION_THRESHOLD,
+ DEFAULT_Z_ACCELERATION_THRESHOLD,
+ -15.0f,
+ 0.0f);
+ }
+
+ private long getUserInteractionBackoffMillis() {
+ return getLongFlagValue(KEY_INTERACTION_BACKOFF,
+ DEFAULT_INTERACTION_BACKOFF,
+ 0,
+ 3600_000);
+ }
+
+ private float getFloatFlagValue(String key, float defaultValue, float min, float max) {
+ final float value = DeviceConfig.getFloat(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+ key,
+ defaultValue);
+
+ if (value < min || value > max) {
+ Slog.w(TAG, "Bad flag value supplied for: " + key);
+ return defaultValue;
+ }
+
+ return value;
+ }
+
+ private long getLongFlagValue(String key, long defaultValue, long min, long max) {
+ final long value = DeviceConfig.getLong(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+ key,
+ defaultValue);
+
+ if (value < min || value > max) {
+ Slog.w(TAG, "Bad flag value supplied for: " + key);
+ return defaultValue;
+ }
+
+ return value;
+ }
+
+ private Duration getTimeThreshold() {
+ final long millis = DeviceConfig.getLong(NAMESPACE_ATTENTION_MANAGER_SERVICE,
+ KEY_TIME_THRESHOLD_MILLIS,
+ DEFAULT_TIME_THRESHOLD_MILLIS);
+
+ if (millis < 0 || millis > 15_000) {
+ Slog.w(TAG, "Bad flag value supplied for: " + KEY_TIME_THRESHOLD_MILLIS);
+ return Duration.ofMillis(DEFAULT_TIME_THRESHOLD_MILLIS);
+ }
+
+ return Duration.ofMillis(millis);
+ }
+
+ private void onDeviceConfigChange(@NonNull Set<String> keys) {
+ for (String key : keys) {
+ switch (key) {
+ case KEY_ACCELERATION_THRESHOLD:
+ case KEY_Z_ACCELERATION_THRESHOLD:
+ case KEY_TIME_THRESHOLD_MILLIS:
+ case KEY_FEATURE_ENABLED:
+ readValuesFromDeviceConfig();
+ return;
+ default:
+ Slog.i(TAG, "Ignoring change on " + key);
+ }
+ }
+ }
+
+ private void readValuesFromDeviceConfig() {
+ mAccelerationThreshold = getAccelerationThreshold();
+ mZAccelerationThreshold = getZAccelerationThreshold();
+ mZAccelerationThresholdLenient = mZAccelerationThreshold + 1.0f;
+ mTimeThreshold = getTimeThreshold();
+ mIsEnabled = isEnabled();
+ mUserInteractionBackoffMillis = getUserInteractionBackoffMillis();
+
+ Slog.i(TAG, "readValuesFromDeviceConfig():"
+ + "\nmAccelerationThreshold=" + mAccelerationThreshold
+ + "\nmZAccelerationThreshold=" + mZAccelerationThreshold
+ + "\nmTimeThreshold=" + mTimeThreshold
+ + "\nmIsEnabled=" + mIsEnabled);
+ }
+
+ /**
+ * Sets how much screen on time might be saved as a result of this detector. Currently used for
+ * logging purposes.
+ */
+ public void setMillisSaved(long millisSaved) {
+ mMillisSaved = millisSaved;
+ }
+
+ private final class ScreenStateReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Intent.ACTION_SCREEN_OFF.equals(intent.getAction())) {
+ checkAndUpdateActiveState(false);
+ } else if (Intent.ACTION_SCREEN_ON.equals(intent.getAction())) {
+ checkAndUpdateActiveState(true);
+ }
+ }
+ }
+
+ private final class ExponentialMovingAverage {
+ private final float mAlpha;
+ private final float mInitialAverage;
+ private float mMovingAverage;
+
+ ExponentialMovingAverage(float alpha) {
+ this(alpha, 0.0f);
+ }
+
+ ExponentialMovingAverage(float alpha, float initialAverage) {
+ this.mAlpha = alpha;
+ this.mInitialAverage = initialAverage;
+ this.mMovingAverage = initialAverage;
+ }
+
+ void updateMovingAverage(float newValue) {
+ mMovingAverage = newValue + mAlpha * (mMovingAverage - newValue);
+ }
+
+ void reset() {
+ mMovingAverage = this.mInitialAverage;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index b8e0156fb4cc..f49e2f1631b9 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -119,6 +119,7 @@ public class Notifier {
private final AppOpsManager mAppOps;
private final SuspendBlocker mSuspendBlocker;
private final WindowManagerPolicy mPolicy;
+ private final FaceDownDetector mFaceDownDetector;
private final ActivityManagerInternal mActivityManagerInternal;
private final InputManagerInternal mInputManagerInternal;
private final InputMethodManagerInternal mInputMethodManagerInternal;
@@ -165,12 +166,14 @@ public class Notifier {
private boolean mUserActivityPending;
public Notifier(Looper looper, Context context, IBatteryStats batteryStats,
- SuspendBlocker suspendBlocker, WindowManagerPolicy policy) {
+ SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
+ FaceDownDetector faceDownDetector) {
mContext = context;
mBatteryStats = batteryStats;
mAppOps = mContext.getSystemService(AppOpsManager.class);
mSuspendBlocker = suspendBlocker;
mPolicy = policy;
+ mFaceDownDetector = faceDownDetector;
mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
mInputMethodManagerInternal = LocalServices.getService(InputMethodManagerInternal.class);
@@ -654,6 +657,7 @@ public class Notifier {
TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
tm.notifyUserActivity();
mPolicy.userActivity();
+ mFaceDownDetector.userActivity();
}
void postEnhancedDischargePredictionBroadcast(long delayMs) {
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index c0b820293649..a13570529197 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -176,6 +176,8 @@ public final class PowerManagerService extends SystemService
private static final int DIRTY_VR_MODE_CHANGED = 1 << 13;
// Dirty bit: attentive timer may have timed out
private static final int DIRTY_ATTENTIVE = 1 << 14;
+ // Dirty bit: phone flipped to face down
+ private static final int DIRTY_FACE_DOWN = 1 << 15;
// Summarizes the state of all active wakelocks.
private static final int WAKE_LOCK_CPU = 1 << 0;
@@ -263,6 +265,7 @@ public final class PowerManagerService extends SystemService
private final BatterySaverStateMachine mBatterySaverStateMachine;
private final BatterySavingStats mBatterySavingStats;
private final AttentionDetector mAttentionDetector;
+ private final FaceDownDetector mFaceDownDetector;
private final BinderService mBinderService;
private final LocalService mLocalService;
private final NativeWrapper mNativeWrapper;
@@ -547,6 +550,10 @@ public final class PowerManagerService extends SystemService
public final float mScreenBrightnessMaximumVr;
public final float mScreenBrightnessDefaultVr;
+ // Value we store for tracking face down behavior.
+ private boolean mIsFaceDown = false;
+ private long mLastFlipTime = 0L;
+
// The screen brightness mode.
// One of the Settings.System.SCREEN_BRIGHTNESS_MODE_* constants.
private int mScreenBrightnessModeSetting;
@@ -791,8 +798,10 @@ public final class PowerManagerService extends SystemService
@VisibleForTesting
static class Injector {
Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats,
- SuspendBlocker suspendBlocker, WindowManagerPolicy policy) {
- return new Notifier(looper, context, batteryStats, suspendBlocker, policy);
+ SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
+ FaceDownDetector faceDownDetector) {
+ return new Notifier(
+ looper, context, batteryStats, suspendBlocker, policy, faceDownDetector);
}
SuspendBlocker createSuspendBlocker(PowerManagerService service, String name) {
@@ -906,6 +915,7 @@ public final class PowerManagerService extends SystemService
mAmbientDisplaySuppressionController =
mInjector.createAmbientDisplaySuppressionController(context);
mAttentionDetector = new AttentionDetector(this::onUserAttention, mLock);
+ mFaceDownDetector = new FaceDownDetector(this::onFlip);
mBatterySavingStats = new BatterySavingStats(mLock);
mBatterySaverPolicy =
@@ -1011,6 +1021,26 @@ public final class PowerManagerService extends SystemService
}
}
+ private void onFlip(boolean isFaceDown) {
+ long millisUntilNormalTimeout = 0;
+ synchronized (mLock) {
+ mIsFaceDown = isFaceDown;
+ if (isFaceDown) {
+ final long currentTime = mClock.uptimeMillis();
+ mLastFlipTime = currentTime;
+ final long sleepTimeout = getSleepTimeoutLocked(-1L);
+ final long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout, -1L);
+ millisUntilNormalTimeout =
+ mLastUserActivityTime + screenOffTimeout - mClock.uptimeMillis();
+ mDirty |= DIRTY_FACE_DOWN;
+ updatePowerStateLocked();
+ }
+ }
+ if (isFaceDown) {
+ mFaceDownDetector.setMillisSaved(millisUntilNormalTimeout);
+ }
+ }
+
@Override
public void onStart() {
publishBinderService(Context.POWER_SERVICE, mBinderService, /* allowIsolated= */ false,
@@ -1065,7 +1095,7 @@ public final class PowerManagerService extends SystemService
mBatteryStats = BatteryStatsService.getService();
mNotifier = mInjector.createNotifier(Looper.getMainLooper(), mContext, mBatteryStats,
mInjector.createSuspendBlocker(this, "PowerManagerService.Broadcasts"),
- mPolicy);
+ mPolicy, mFaceDownDetector);
mWirelessChargerDetector = mInjector.createWirelessChargerDetector(sensorManager,
mInjector.createSuspendBlocker(
@@ -1099,6 +1129,7 @@ public final class PowerManagerService extends SystemService
mBatterySaverController.systemReady();
mBatterySaverPolicy.systemReady();
+ mFaceDownDetector.systemReady(mContext);
// Register for settings changes.
resolver.registerContentObserver(Settings.Secure.getUriFor(
@@ -2283,9 +2314,11 @@ public final class PowerManagerService extends SystemService
|| getWakefulnessLocked() == WAKEFULNESS_DOZING) {
final long attentiveTimeout = getAttentiveTimeoutLocked();
final long sleepTimeout = getSleepTimeoutLocked(attentiveTimeout);
- final long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout,
+ long screenOffTimeout = getScreenOffTimeoutLocked(sleepTimeout,
attentiveTimeout);
final long screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
+ screenOffTimeout =
+ getScreenOffTimeoutWithFaceDownLocked(screenOffTimeout, screenDimDuration);
final boolean userInactiveOverride = mUserInactiveOverrideFromWindowManager;
final long nextProfileTimeout = getNextProfileTimeoutLocked(now);
@@ -2541,6 +2574,16 @@ public final class PowerManagerService extends SystemService
(long)(screenOffTimeout * mMaximumScreenDimRatioConfig));
}
+ private long getScreenOffTimeoutWithFaceDownLocked(
+ long screenOffTimeout, long screenDimDuration) {
+ // If face down, we decrease the timeout to equal the dim duration so that the
+ // device will go into a dim state.
+ if (mIsFaceDown) {
+ return Math.min(screenDimDuration, screenOffTimeout);
+ }
+ return screenOffTimeout;
+ }
+
/**
* Updates the wakefulness of the device.
*
@@ -3859,6 +3902,8 @@ public final class PowerManagerService extends SystemService
pw.println(" mDisplayReady=" + mDisplayReady);
pw.println(" mHoldingWakeLockSuspendBlocker=" + mHoldingWakeLockSuspendBlocker);
pw.println(" mHoldingDisplaySuspendBlocker=" + mHoldingDisplaySuspendBlocker);
+ pw.println(" mLastFlipTime=" + mLastFlipTime);
+ pw.println(" mIsFaceDown=" + mIsFaceDown);
pw.println();
pw.println("Settings and Configuration:");
@@ -4003,6 +4048,8 @@ public final class PowerManagerService extends SystemService
mNotifier.dump(pw);
}
+ mFaceDownDetector.dump(pw);
+
mAmbientDisplaySuppressionController.dump(pw);
}
@@ -5121,7 +5168,6 @@ public final class PowerManagerService extends SystemService
@Override // Binder call
public int getPowerSaveModeTrigger() {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.POWER_SAVER, null);
final long ident = Binder.clearCallingIdentity();
try {
return Settings.Global.getInt(mContext.getContentResolver(),
diff --git a/services/core/java/com/android/server/rotationresolver/RotationResolverManagerPerUserService.java b/services/core/java/com/android/server/rotationresolver/RotationResolverManagerPerUserService.java
index 6f7c016cb3f6..0cd0458c6b2b 100644
--- a/services/core/java/com/android/server/rotationresolver/RotationResolverManagerPerUserService.java
+++ b/services/core/java/com/android/server/rotationresolver/RotationResolverManagerPerUserService.java
@@ -65,6 +65,7 @@ final class RotationResolverManagerPerUserService extends
@GuardedBy("mLock")
RemoteRotationResolverService mRemoteService;
+ private static String sTestingPackage;
private ComponentName mComponentName;
RotationResolverManagerPerUserService(@NonNull RotationResolverManagerService main,
@@ -136,19 +137,43 @@ final class RotationResolverManagerPerUserService extends
}
/**
+ * Set the testing package name.
+ *
+ * @param packageName the name of the package that implements {@link RotationResolverService}
+ * and is used for testing only.
+ */
+ @VisibleForTesting
+ void setTestingPackage(String packageName) {
+ sTestingPackage = packageName;
+ mComponentName = resolveRotationResolverService(getContext());
+ }
+
+ /**
+ * get the currently bound component name.
+ */
+ @VisibleForTesting
+ ComponentName getComponentName() {
+ return mComponentName;
+ }
+
+ /**
* Provides rotation resolver service component name at runtime, making sure it's provided
* by the system.
*/
- private static ComponentName resolveRotationResolverService(Context context) {
- final String serviceConfigPackage = getServiceConfigPackage(context);
-
+ static ComponentName resolveRotationResolverService(Context context) {
String resolvedPackage;
int flags = PackageManager.MATCH_SYSTEM_ONLY;
-
- if (!TextUtils.isEmpty(serviceConfigPackage)) {
- resolvedPackage = serviceConfigPackage;
+ if (!TextUtils.isEmpty(sTestingPackage)) {
+ // Testing Package is set.
+ resolvedPackage = sTestingPackage;
+ flags = PackageManager.GET_META_DATA;
} else {
- return null;
+ final String serviceConfigPackage = getServiceConfigPackage(context);
+ if (!TextUtils.isEmpty(serviceConfigPackage)) {
+ resolvedPackage = serviceConfigPackage;
+ } else {
+ return null;
+ }
}
final Intent intent = new Intent(
@@ -158,14 +183,15 @@ final class RotationResolverManagerPerUserService extends
flags, context.getUserId());
if (resolveInfo == null || resolveInfo.serviceInfo == null) {
Slog.wtf(TAG, String.format("Service %s not found in package %s",
- RotationResolverService.SERVICE_INTERFACE, serviceConfigPackage
- ));
+ RotationResolverService.SERVICE_INTERFACE, resolvedPackage));
return null;
}
final ServiceInfo serviceInfo = resolveInfo.serviceInfo;
final String permission = serviceInfo.permission;
if (Manifest.permission.BIND_ROTATION_RESOLVER_SERVICE.equals(permission)) {
+ Slog.i(TAG, String.format("Successfully bound the service from package: %s",
+ resolvedPackage));
return serviceInfo.getComponentName();
}
Slog.e(TAG, String.format(
diff --git a/services/core/java/com/android/server/rotationresolver/RotationResolverShellCommand.java b/services/core/java/com/android/server/rotationresolver/RotationResolverShellCommand.java
index 54a9edba4e03..e5088c023533 100644
--- a/services/core/java/com/android/server/rotationresolver/RotationResolverShellCommand.java
+++ b/services/core/java/com/android/server/rotationresolver/RotationResolverShellCommand.java
@@ -16,12 +16,13 @@
package com.android.server.rotationresolver;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.content.ComponentName;
import android.os.CancellationSignal;
import android.os.ShellCommand;
import android.rotationresolver.RotationResolverInternal.RotationResolverCallbackInternal;
+import android.text.TextUtils;
import android.view.Surface;
import java.io.PrintWriter;
@@ -59,7 +60,7 @@ final class RotationResolverShellCommand extends ShellCommand {
}
}
- final TestableRotationCallbackInternal mTestableRotationCallbackInternal =
+ static final TestableRotationCallbackInternal sTestableRotationCallbackInternal =
new TestableRotationCallbackInternal();
@Override
@@ -73,20 +74,47 @@ final class RotationResolverShellCommand extends ShellCommand {
return runResolveRotation();
case "get-last-resolution":
return getLastResolution();
+ case "set-testing-package":
+ return setTestRotationResolverPackage(getNextArgRequired());
+ case "get-bound-package":
+ return getBoundPackageName();
+ case "clear-testing-package":
+ return resetTestRotationResolverPackage();
default:
return handleDefaultCommands(cmd);
}
}
+ private int getBoundPackageName() {
+ final PrintWriter out = getOutPrintWriter();
+ final ComponentName componentName = mService.getComponentName();
+ out.println(componentName == null ? "" : componentName.getPackageName());
+ return 0;
+ }
+
+ private int setTestRotationResolverPackage(String testingPackage) {
+ if (!TextUtils.isEmpty((testingPackage))) {
+ mService.setTestingPackage(testingPackage);
+ sTestableRotationCallbackInternal.reset();
+ }
+ return 0;
+ }
+
+ private int resetTestRotationResolverPackage() {
+ mService.setTestingPackage("");
+ sTestableRotationCallbackInternal.reset();
+ return 0;
+ }
+
private int runResolveRotation() {
- mService.resolveRotationLocked(mTestableRotationCallbackInternal, Surface.ROTATION_0,
+ mService.resolveRotationLocked(sTestableRotationCallbackInternal, Surface.ROTATION_0,
Surface.ROTATION_0, "", 2000L, new CancellationSignal());
return 0;
}
private int getLastResolution() {
final PrintWriter out = getOutPrintWriter();
- out.println(mTestableRotationCallbackInternal.getLastCallbackCode());
+ out.println(sTestableRotationCallbackInternal.getLastCallbackCode());
return 0;
}
@@ -99,5 +127,8 @@ final class RotationResolverShellCommand extends ShellCommand {
pw.println();
pw.println(" resolve-rotation: request a rotation resolution.");
pw.println(" get-last-resolution: show the last rotation resolution result.");
+ pw.println(" set-testing-package: Set the testing package that implements the service.");
+ pw.println(" get-bound-package: print the bound package that implements the service.");
+ pw.println(" clear-testing-package: reset the testing package.");
}
}
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 342dbfa3f59d..6aa7c8a290c1 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -1471,12 +1471,18 @@ public class StatsPullAtomService extends SystemService {
}
int pullCpuTimePerClusterFreqLocked(int atomTag, List<StatsEvent> pulledData) {
- boolean success = KernelCpuTotalBpfMapReader.read((cluster, freq, timeMs) -> {
- pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, cluster, freq, timeMs));
- });
- if (!success) {
+ int[] freqsClusters = KernelCpuBpfTracking.getFreqsClusters();
+ long[] freqs = KernelCpuBpfTracking.getFreqs();
+ long[] timesMs = KernelCpuTotalBpfMapReader.read();
+ if (timesMs == null) {
return StatsManager.PULL_SKIP;
}
+ for (int freqIndex = 0; freqIndex < timesMs.length; ++freqIndex) {
+ int cluster = freqsClusters[freqIndex];
+ long freq = freqs[freqIndex];
+ long timeMs = timesMs[freqIndex];
+ pulledData.add(FrameworkStatsLog.buildStatsEvent(atomTag, cluster, freq, timeMs));
+ }
return StatsManager.PULL_SUCCESS;
}
@@ -1503,48 +1509,42 @@ public class StatsPullAtomService extends SystemService {
}
private void registerCpuCyclesPerUidCluster() {
- int tagId = FrameworkStatsLog.CPU_CYCLES_PER_UID_CLUSTER;
- PullAtomMetadata metadata = new PullAtomMetadata.Builder()
- .setAdditiveFields(new int[] {3, 4, 5})
- .build();
- mStatsManager.setPullAtomCallback(
- tagId,
- metadata,
- DIRECT_EXECUTOR,
- mStatsCallbackImpl
- );
+ // If eBPF tracking is not support, the procfs fallback is used if the kernel knows about
+ // CPU frequencies.
+ if (KernelCpuBpfTracking.isSupported() || KernelCpuBpfTracking.getClusters() > 0) {
+ int tagId = FrameworkStatsLog.CPU_CYCLES_PER_UID_CLUSTER;
+ PullAtomMetadata metadata = new PullAtomMetadata.Builder()
+ .setAdditiveFields(new int[] {3, 4, 5})
+ .build();
+ mStatsManager.setPullAtomCallback(
+ tagId,
+ metadata,
+ DIRECT_EXECUTOR,
+ mStatsCallbackImpl
+ );
+ }
}
int pullCpuCyclesPerUidClusterLocked(int atomTag, List<StatsEvent> pulledData) {
- // TODO(b/179485697): Remove power profile dependency.
PowerProfile powerProfile = new PowerProfile(mContext);
- // Frequency index to frequency mapping.
- long[] freqs = mCpuUidFreqTimeReader.readFreqs(powerProfile);
- // Frequency index to cluster mapping.
- int[] freqClusters = new int[freqs.length];
- // Frequency index to power mapping.
- double[] freqPowers = new double[freqs.length];
- // Number of clusters.
- int clusters;
-
- // Initialize frequency mappings.
+ int[] freqsClusters = KernelCpuBpfTracking.getFreqsClusters();
+ int clusters = KernelCpuBpfTracking.getClusters();
+ long[] freqs = KernelCpuBpfTracking.getFreqs();
+ double[] freqsPowers = new double[freqs.length];
+ // Initialize frequency power mapping.
{
- int cluster = 0;
int freqClusterIndex = 0;
- long lastFreq = -1;
+ int lastCluster = -1;
for (int freqIndex = 0; freqIndex < freqs.length; ++freqIndex, ++freqClusterIndex) {
- long currFreq = freqs[freqIndex];
- if (currFreq <= lastFreq) {
- cluster++;
+ int cluster = freqsClusters[freqIndex];
+ if (cluster != lastCluster) {
freqClusterIndex = 0;
}
- freqClusters[freqIndex] = cluster;
- freqPowers[freqIndex] =
+ lastCluster = cluster;
+
+ freqsPowers[freqIndex] =
powerProfile.getAveragePowerForCpuCore(cluster, freqClusterIndex);
- lastFreq = currFreq;
}
-
- clusters = cluster + 1;
}
// Aggregate 0: mcycles, 1: runtime ms, 2: power profile estimate for the same uids for
@@ -1570,12 +1570,12 @@ public class StatsPullAtomService extends SystemService {
}
for (int freqIndex = 0; freqIndex < cpuFreqTimeMs.length; ++freqIndex) {
- int cluster = freqClusters[freqIndex];
+ int cluster = freqsClusters[freqIndex];
long timeMs = cpuFreqTimeMs[freqIndex];
values[cluster * CPU_CYCLES_PER_UID_CLUSTER_VALUES] += freqs[freqIndex] * timeMs;
values[cluster * CPU_CYCLES_PER_UID_CLUSTER_VALUES + 1] += timeMs;
values[cluster * CPU_CYCLES_PER_UID_CLUSTER_VALUES + 2] +=
- freqPowers[freqIndex] * timeMs;
+ freqsPowers[freqIndex] * timeMs;
}
});
@@ -1665,34 +1665,6 @@ public class StatsPullAtomService extends SystemService {
}
int pullCpuCyclesPerThreadGroupCluster(int atomTag, List<StatsEvent> pulledData) {
- // TODO(b/179485697): Remove power profile dependency.
- PowerProfile powerProfile = new PowerProfile(mContext);
- // Frequency index to frequency mapping.
- long[] freqs = mCpuUidFreqTimeReader.readFreqs(powerProfile);
- if (freqs == null) {
- return StatsManager.PULL_SKIP;
- }
- // Frequency index to cluster mapping.
- int[] freqClusters = new int[freqs.length];
- // Number of clusters.
- int clusters;
-
- // Initialize frequency mappings.
- {
- int cluster = 0;
- long lastFreq = -1;
- for (int freqIndex = 0; freqIndex < freqs.length; ++freqIndex) {
- long currFreq = freqs[freqIndex];
- if (currFreq <= lastFreq) {
- cluster++;
- }
- freqClusters[freqIndex] = cluster;
- lastFreq = currFreq;
- }
-
- clusters = cluster + 1;
- }
-
SystemServiceCpuThreadTimes times = LocalServices.getService(BatteryStatsInternal.class)
.getSystemServiceCpuThreadTimes();
if (times == null) {
@@ -1701,22 +1673,24 @@ public class StatsPullAtomService extends SystemService {
addCpuCyclesPerThreadGroupClusterAtoms(atomTag, pulledData,
FrameworkStatsLog.CPU_CYCLES_PER_THREAD_GROUP_CLUSTER__THREAD_GROUP__SYSTEM_SERVER,
- times.threadCpuTimesUs, clusters, freqs, freqClusters);
+ times.threadCpuTimesUs);
addCpuCyclesPerThreadGroupClusterAtoms(atomTag, pulledData,
FrameworkStatsLog.CPU_CYCLES_PER_THREAD_GROUP_CLUSTER__THREAD_GROUP__SYSTEM_SERVER_BINDER,
- times.binderThreadCpuTimesUs, clusters, freqs, freqClusters);
+ times.binderThreadCpuTimesUs);
return StatsManager.PULL_SUCCESS;
}
private static void addCpuCyclesPerThreadGroupClusterAtoms(
- int atomTag, List<StatsEvent> pulledData, int threadGroup, long[] cpuTimesUs,
- int clusters, long[] freqs, int[] freqClusters) {
+ int atomTag, List<StatsEvent> pulledData, int threadGroup, long[] cpuTimesUs) {
+ int[] freqsClusters = KernelCpuBpfTracking.getFreqsClusters();
+ int clusters = KernelCpuBpfTracking.getClusters();
+ long[] freqs = KernelCpuBpfTracking.getFreqs();
long[] aggregatedCycles = new long[clusters];
long[] aggregatedTimesUs = new long[clusters];
for (int i = 0; i < cpuTimesUs.length; ++i) {
- aggregatedCycles[freqClusters[i]] += freqs[i] * cpuTimesUs[i] / 1_000;
- aggregatedTimesUs[freqClusters[i]] += cpuTimesUs[i];
+ aggregatedCycles[freqsClusters[i]] += freqs[i] * cpuTimesUs[i] / 1_000;
+ aggregatedTimesUs[freqsClusters[i]] += cpuTimesUs[i];
}
for (int cluster = 0; cluster < clusters; ++cluster) {
pulledData.add(FrameworkStatsLog.buildStatsEvent(
diff --git a/services/core/java/com/android/server/utils/WatchedLongSparseArray.java b/services/core/java/com/android/server/utils/WatchedLongSparseArray.java
new file mode 100644
index 000000000000..bf23de12ffef
--- /dev/null
+++ b/services/core/java/com/android/server/utils/WatchedLongSparseArray.java
@@ -0,0 +1,418 @@
+/*
+ * 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.android.server.utils;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.util.LongSparseArray;
+
+/**
+ * A watched variant of {@link LongSparseArray}. If a {@link Watchable} is stored in the
+ * array, the array registers with the {@link Watchable}. The array registers only once
+ * with each {@link Watchable} no matter how many times the {@link Watchable} is stored in
+ * the array.
+ * @param <E> The element type, stored in the array.
+ */
+public class WatchedLongSparseArray<E> extends WatchableImpl
+ implements Snappable {
+
+ // The storage
+ private final LongSparseArray<E> mStorage;
+
+ // If true, the array is watching its children
+ private volatile boolean mWatching = false;
+
+ // The local observer
+ private final Watcher mObserver = new Watcher() {
+ @Override
+ public void onChange(@Nullable Watchable o) {
+ WatchedLongSparseArray.this.dispatchChange(o);
+ }
+ };
+
+ /**
+ * A private convenience function that notifies registered listeners that an element
+ * has been added to or removed from the array. The what parameter is the array itself.
+ */
+ private void onChanged() {
+ dispatchChange(this);
+ }
+
+ /**
+ * A convenience function. Register the object if it is {@link Watchable} and if the
+ * array is currently watching. Note that the watching flag must be true if this
+ * function is to succeed.
+ */
+ private void registerChild(Object o) {
+ if (mWatching && o instanceof Watchable) {
+ ((Watchable) o).registerObserver(mObserver);
+ }
+ }
+
+ /**
+ * A convenience function. Unregister the object if it is {@link Watchable} and if
+ * the array is currently watching. Note that the watching flag must be true if this
+ * function is to succeed.
+ */
+ private void unregisterChild(Object o) {
+ if (mWatching && o instanceof Watchable) {
+ ((Watchable) o).unregisterObserver(mObserver);
+ }
+ }
+
+ /**
+ * A convenience function. Unregister the object if it is {@link Watchable}, if the array is
+ * currently watching, and if the storage does not contain the object. Note that the watching
+ * flag must be true if this function is to succeed. This must be called after an object has
+ * been removed from the storage.
+ */
+ private void unregisterChildIf(Object o) {
+ if (mWatching && o instanceof Watchable) {
+ if (mStorage.indexOfValue((E) o) == -1) {
+ ((Watchable) o).unregisterObserver(mObserver);
+ }
+ }
+ }
+
+ /**
+ * Register a {@link Watcher} with the array. If this is the first Watcher than any
+ * array values that are {@link Watchable} are registered to the array itself.
+ */
+ @Override
+ public void registerObserver(@NonNull Watcher observer) {
+ super.registerObserver(observer);
+ if (registeredObserverCount() == 1) {
+ // The watching flag must be set true before any children are registered.
+ mWatching = true;
+ final int end = mStorage.size();
+ for (int i = 0; i < end; i++) {
+ registerChild(mStorage.valueAt(i));
+ }
+ }
+ }
+
+ /**
+ * Unregister a {@link Watcher} from the array. If this is the last Watcher than any
+ * array values that are {@link Watchable} are unregistered to the array itself.
+ */
+ @Override
+ public void unregisterObserver(@NonNull Watcher observer) {
+ super.unregisterObserver(observer);
+ if (registeredObserverCount() == 0) {
+ final int end = mStorage.size();
+ for (int i = 0; i < end; i++) {
+ unregisterChild(mStorage.valueAt(i));
+ }
+ // The watching flag must be true while children are unregistered.
+ mWatching = false;
+ }
+ }
+
+ /**
+ * Creates a new WatchedSparseArray containing no mappings.
+ */
+ public WatchedLongSparseArray() {
+ mStorage = new LongSparseArray();
+ }
+
+ /**
+ * Creates a new WatchedSparseArray containing no mappings that
+ * will not require any additional memory allocation to store the
+ * specified number of mappings. If you supply an initial capacity of
+ * 0, the sparse array will be initialized with a light-weight
+ * representation not requiring any additional array allocations.
+ */
+ public WatchedLongSparseArray(int initialCapacity) {
+ mStorage = new LongSparseArray(initialCapacity);
+ }
+
+ /**
+ * Create a {@link WatchedLongSparseArray} from a {@link LongSparseArray}.
+ */
+ public WatchedLongSparseArray(@NonNull LongSparseArray<E> c) {
+ mStorage = c.clone();
+ }
+
+ /**
+ * The copy constructor does not copy the watcher data.
+ */
+ public WatchedLongSparseArray(@NonNull WatchedLongSparseArray<E> r) {
+ mStorage = r.mStorage.clone();
+ }
+
+ /**
+ * Make <this> a copy of src. Any data in <this> is discarded.
+ */
+ public void copyFrom(@NonNull LongSparseArray<E> src) {
+ clear();
+ final int end = src.size();
+ for (int i = 0; i < end; i++) {
+ put(src.keyAt(i), src.valueAt(i));
+ }
+ }
+
+ /**
+ * Make dst a copy of <this>. Any previous data in dst is discarded.
+ */
+ public void copyTo(@NonNull LongSparseArray<E> dst) {
+ dst.clear();
+ final int end = size();
+ for (int i = 0; i < end; i++) {
+ dst.put(keyAt(i), valueAt(i));
+ }
+ }
+
+ /**
+ * Return the underlying storage. This breaks the wrapper but is necessary when
+ * passing the array to distant methods.
+ */
+ public LongSparseArray<E> untrackedStorage() {
+ return mStorage;
+ }
+
+ /**
+ * Gets the Object mapped from the specified key, or <code>null</code>
+ * if no such mapping has been made.
+ */
+ public E get(long key) {
+ return mStorage.get(key);
+ }
+
+ /**
+ * Gets the Object mapped from the specified key, or the specified Object
+ * if no such mapping has been made.
+ */
+ public E get(long key, E valueIfKeyNotFound) {
+ return mStorage.get(key, valueIfKeyNotFound);
+ }
+
+ /**
+ * Removes the mapping from the specified key, if there was any.
+ */
+ public void delete(long key) {
+ E old = mStorage.get(key, null);
+ mStorage.delete(key);
+ unregisterChildIf(old);
+ onChanged();
+
+ }
+
+ /**
+ * Alias for {@link #delete(long)}.
+ */
+ public void remove(long key) {
+ delete(key);
+ }
+
+ /**
+ * Removes the mapping at the specified index.
+ *
+ * <p>For indices outside of the range <code>0...size()-1</code>, an
+ * {@link ArrayIndexOutOfBoundsException} is thrown.</p>
+ */
+ public void removeAt(int index) {
+ E old = mStorage.valueAt(index);
+ mStorage.removeAt(index);
+ unregisterChildIf(old);
+ onChanged();
+ }
+
+ /**
+ * Adds a mapping from the specified key to the specified value,
+ * replacing the previous mapping from the specified key if there
+ * was one.
+ */
+ public void put(long key, E value) {
+ E old = mStorage.get(key);
+ mStorage.put(key, value);
+ unregisterChildIf(old);
+ registerChild(value);
+ onChanged();
+ }
+
+ /**
+ * Returns the number of key-value mappings that this LongSparseArray
+ * currently stores.
+ */
+ public int size() {
+ return mStorage.size();
+ }
+
+ /**
+ * Given an index in the range <code>0...size()-1</code>, returns
+ * the key from the <code>index</code>th key-value mapping that this
+ * LongSparseArray stores.
+ *
+ * <p>The keys corresponding to indices in ascending order are guaranteed to
+ * be in ascending order, e.g., <code>keyAt(0)</code> will return the
+ * smallest key and <code>keyAt(size()-1)</code> will return the largest
+ * key.</p>
+ *
+ * <p>For indices outside of the range <code>0...size()-1</code>, an
+ * {@link ArrayIndexOutOfBoundsException} is thrown.</p>
+ */
+ public long keyAt(int index) {
+ return mStorage.keyAt(index);
+ }
+
+ /**
+ * Given an index in the range <code>0...size()-1</code>, returns
+ * the value from the <code>index</code>th key-value mapping that this
+ * LongSparseArray stores.
+ *
+ * <p>The values corresponding to indices in ascending order are guaranteed
+ * to be associated with keys in ascending order, e.g.,
+ * <code>valueAt(0)</code> will return the value associated with the
+ * smallest key and <code>valueAt(size()-1)</code> will return the value
+ * associated with the largest key.</p>
+ *
+ * <p>For indices outside of the range <code>0...size()-1</code>, an
+ * {@link ArrayIndexOutOfBoundsException} is thrown.</p>
+ */
+ public E valueAt(int index) {
+ return mStorage.valueAt(index);
+ }
+
+ /**
+ * Given an index in the range <code>0...size()-1</code>, sets a new
+ * value for the <code>index</code>th key-value mapping that this
+ * LongSparseArray stores.
+ *
+ * <p>For indices outside of the range <code>0...size()-1</code>, an
+ * {@link ArrayIndexOutOfBoundsException} is thrown.</p>
+ */
+ public void setValueAt(int index, E value) {
+ E old = mStorage.valueAt(index);
+ mStorage.setValueAt(index, value);
+ unregisterChildIf(old);
+ registerChild(value);
+ onChanged();
+ }
+
+ /**
+ * Returns the index for which {@link #keyAt} would return the
+ * specified key, or a negative number if the specified
+ * key is not mapped.
+ */
+ public int indexOfKey(long key) {
+ return mStorage.indexOfKey(key);
+ }
+
+ /**
+ * Returns an index for which {@link #valueAt} would return the
+ * specified key, or a negative number if no keys map to the
+ * specified value.
+ * Beware that this is a linear search, unlike lookups by key,
+ * and that multiple keys can map to the same value and this will
+ * find only one of them.
+ */
+ public int indexOfValue(E value) {
+ return mStorage.indexOfValue(value);
+ }
+
+ /**
+ * Returns an index for which {@link #valueAt} would return the
+ * specified key, or a negative number if no keys map to the
+ * specified value.
+ * <p>Beware that this is a linear search, unlike lookups by key,
+ * and that multiple keys can map to the same value and this will
+ * find only one of them.
+ * <p>Note also that this method uses {@code equals} unlike {@code indexOfValue}.
+ * @hide
+ */
+ public int indexOfValueByValue(E value) {
+ return mStorage.indexOfValueByValue(value);
+ }
+
+ /**
+ * Removes all key-value mappings from this LongSparseArray.
+ */
+ public void clear() {
+ final int end = mStorage.size();
+ for (int i = 0; i < end; i++) {
+ unregisterChild(mStorage.valueAt(i));
+ }
+ mStorage.clear();
+ onChanged();
+ }
+
+ /**
+ * Puts a key/value pair into the array, optimizing for the case where
+ * the key is greater than all existing keys in the array.
+ */
+ public void append(long key, E value) {
+ mStorage.append(key, value);
+ registerChild(value);
+ onChanged();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * <p>This implementation composes a string by iterating over its mappings. If
+ * this map contains itself as a value, the string "(this Map)"
+ * will appear in its place.
+ */
+ @Override
+ public String toString() {
+ return mStorage.toString();
+ }
+
+ /**
+ * Create a copy of the array. If the element is a subclass of Snapper then the copy
+ * contains snapshots of the elements. Otherwise the copy contains references to the
+ * elements. The returned snapshot is immutable.
+ * @return A new array whose elements are the elements of <this>.
+ */
+ public WatchedLongSparseArray<E> snapshot() {
+ WatchedLongSparseArray<E> l = new WatchedLongSparseArray<>(size());
+ snapshot(l, this);
+ return l;
+ }
+
+ /**
+ * Make <this> a snapshot of the argument. Note that <this> is immutable when the
+ * method returns. <this> must be empty when the function is called.
+ * @param r The source array, which is copied into <this>
+ */
+ public void snapshot(@NonNull WatchedLongSparseArray<E> r) {
+ snapshot(this, r);
+ }
+
+ /**
+ * Make the destination a copy of the source. If the element is a subclass of Snapper then the
+ * copy contains snapshots of the elements. Otherwise the copy contains references to the
+ * elements. The destination must be initially empty. Upon return, the destination is
+ * immutable.
+ * @param dst The destination array. It must be empty.
+ * @param src The source array. It is not modified.
+ */
+ public static <E> void snapshot(@NonNull WatchedLongSparseArray<E> dst,
+ @NonNull WatchedLongSparseArray<E> src) {
+ if (dst.size() != 0) {
+ throw new IllegalArgumentException("snapshot destination is not empty");
+ }
+ final int end = src.size();
+ for (int i = 0; i < end; i++) {
+ final E val = Snapshots.maybeSnapshot(src.valueAt(i));
+ final long key = src.keyAt(i);
+ dst.put(key, val);
+ }
+ dst.seal();
+ }
+
+}
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index 904bbe83e020..151895f02ac4 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -235,7 +235,10 @@ class ActivityClientController extends IActivityClientController.Stub {
public void activityRelaunched(IBinder token) {
final long origId = Binder.clearCallingIdentity();
synchronized (mGlobalLock) {
- mTaskSupervisor.activityRelaunchedLocked(token);
+ final ActivityRecord r = ActivityRecord.forTokenLocked(token);
+ if (r != null) {
+ r.finishRelaunching();
+ }
}
Binder.restoreCallingIdentity(origId);
}
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 8c3722dbbe76..5d3b9c197267 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -567,6 +567,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
boolean mVoiceInteraction;
private int mPendingRelaunchCount;
+ long mRelaunchStartTime;
// True if we are current in the process of removing this app token from the display
private boolean mRemovingFromDisplay = false;
@@ -3357,7 +3358,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
return task.isDragResizing();
}
+ @VisibleForTesting
void startRelaunching() {
+ if (mPendingRelaunchCount == 0) {
+ mRelaunchStartTime = SystemClock.elapsedRealtime();
+ }
if (shouldFreezeBounds()) {
freezeBounds();
}
@@ -3396,6 +3401,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
// Update keyguard flags upon finishing relaunch.
checkKeyguardFlagsChanged();
}
+
+ final Task rootTask = getRootTask();
+ if (rootTask != null && rootTask.shouldSleepOrShutDownActivities()) {
+ // Activity is always relaunched to either resumed or paused state. If it was
+ // relaunched while hidden (by keyguard or smth else), it should be stopped.
+ rootTask.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
+ false /* preserveWindows */);
+ }
}
void clearRelaunching() {
@@ -3404,6 +3417,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
}
unfreezeBounds();
mPendingRelaunchCount = 0;
+ mRelaunchStartTime = 0;
}
/**
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index 1264d0c53e0c..bf2aae8867ba 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -2204,19 +2204,6 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks {
task.mTaskId, reason, topActivity.info.applicationInfo.packageName);
}
- void activityRelaunchedLocked(IBinder token) {
- final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token);
- if (r != null) {
- r.finishRelaunching();
- if (r.getRootTask().shouldSleepOrShutDownActivities()) {
- // Activity is always relaunched to either resumed or paused state. If it was
- // relaunched while hidden (by keyguard or smth else), it should be stopped.
- r.getRootTask().ensureActivitiesVisible(null /* starting */, 0 /* configChanges */,
- false /* preserveWindows */);
- }
- }
- }
-
void logRootTaskState() {
mActivityMetricsLogger.logWindowState();
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index d33799c15e8f..0143e70f53ca 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -673,10 +673,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
// Used in updating override configurations
private final Configuration mTempConfig = new Configuration();
- // Used in performing layout, to record the insets provided by other windows above the current
- // window.
- private InsetsState mTmpAboveInsetsState = new InsetsState();
-
/**
* Used to prevent recursions when calling
* {@link #ensureActivitiesVisible(ActivityRecord, int, boolean, boolean)}
@@ -778,13 +774,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
+ " parentHidden=" + w.isParentWindowHidden());
}
- // Sets mAboveInsets for each window. Windows behind the window providing the insets can
- // receive the insets.
- if (!w.mAboveInsetsState.equals(mTmpAboveInsetsState)) {
- w.mAboveInsetsState.set(mTmpAboveInsetsState);
- mWinInsetsChanged.add(w);
- }
-
// If this view is GONE, then skip it -- keep the current frame, and let the caller know
// so they can ignore it if they want. (We do the normal layout for INVISIBLE windows,
// since that means "perform layout as normal, just don't display").
@@ -818,16 +807,8 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
+ " mContainingFrame=" + w.getContainingFrame()
+ " mDisplayFrame=" + w.getDisplayFrame());
}
- provideInsetsByWindow(w);
};
- private void provideInsetsByWindow(WindowState w) {
- for (int i = 0; i < w.mProvidedInsetsSources.size(); i++) {
- final InsetsSource providedSource = w.mProvidedInsetsSources.valueAt(i);
- mTmpAboveInsetsState.addSource(providedSource);
- }
- }
-
private final Consumer<WindowState> mPerformLayoutAttached = w -> {
if (w.mLayoutAttached) {
if (DEBUG_LAYOUT) Slog.v(TAG, "2ND PASS " + w + " mHaveFrame=" + w.mHaveFrame
@@ -2511,8 +2492,13 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
void onDisplayInfoChanged() {
final DisplayInfo info = mDisplayInfo;
- mDisplayFrames.onDisplayInfoUpdated(info, calculateDisplayCutoutForRotation(info.rotation),
- calculateRoundedCornersForRotation(info.rotation));
+ if (mDisplayFrames.onDisplayInfoUpdated(info,
+ calculateDisplayCutoutForRotation(info.rotation),
+ calculateRoundedCornersForRotation(info.rotation))) {
+ // TODO(b/161810301): Set notifyInsetsChange to true while the server no longer performs
+ // layout.
+ mInsetsStateController.onDisplayInfoUpdated(false /* notifyInsetsChange */);
+ }
mInputMonitor.layoutInputConsumers(info.logicalWidth, info.logicalHeight);
mDisplayPolicy.onDisplayInfoChanged(info);
}
@@ -3767,8 +3753,11 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
// 2. Assign window layers based on the IME surface parent to make sure it is on top of the
// app.
assignWindowLayers(true /* setLayoutNeeded */);
- // 3. Update the IME control target to apply any inset change and animation.
- // 4. Reparent the IME container surface to either the input target app, or the IME window
+ // 3. The z-order of IME might have been changed. Update the above insets state.
+ mInsetsStateController.updateAboveInsetsState(
+ mInputMethodWindow, true /* notifyInsetsChange */);
+ // 4. Update the IME control target to apply any inset change and animation.
+ // 5. Reparent the IME container surface to either the input target app, or the IME window
// parent.
updateImeControlTarget();
}
@@ -4341,14 +4330,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
+ " dh=" + mDisplayInfo.logicalHeight);
}
- // Used to indicate that we have processed the insets windows. This needs to be after
- // beginLayoutLw to ensure the raw insets state display related info is initialized.
- final InsetsState rawInsetsState = getInsetsStateController().getRawInsetsState();
- mTmpAboveInsetsState = new InsetsState();
- mTmpAboveInsetsState.setDisplayFrame(rawInsetsState.getDisplayFrame());
- mTmpAboveInsetsState.setDisplayCutout(rawInsetsState.getDisplayCutout());
- mTmpAboveInsetsState.mirrorAlwaysVisibleInsetsSources(rawInsetsState);
-
int seq = mLayoutSeq + 1;
if (seq < 0) seq = 0;
mLayoutSeq = seq;
diff --git a/services/core/java/com/android/server/wm/DisplayFrames.java b/services/core/java/com/android/server/wm/DisplayFrames.java
index e4230a2c8760..a37f3f254276 100644
--- a/services/core/java/com/android/server/wm/DisplayFrames.java
+++ b/services/core/java/com/android/server/wm/DisplayFrames.java
@@ -21,6 +21,7 @@ import static android.view.InsetsState.ITYPE_LEFT_DISPLAY_CUTOUT;
import static android.view.InsetsState.ITYPE_RIGHT_DISPLAY_CUTOUT;
import static android.view.InsetsState.ITYPE_TOP_DISPLAY_CUTOUT;
+import android.annotation.NonNull;
import android.graphics.Rect;
import android.util.proto.ProtoOutputStream;
import android.view.DisplayCutout;
@@ -70,25 +71,28 @@ public class DisplayFrames {
* @param info the updated {@link DisplayInfo}.
* @param displayCutout the updated {@link DisplayCutout}.
* @param roundedCorners the updated {@link RoundedCorners}.
+ * @return {@code true} if the insets state has been changed; {@code false} otherwise.
*/
- public void onDisplayInfoUpdated(DisplayInfo info, WmDisplayCutout displayCutout,
- RoundedCorners roundedCorners) {
- mDisplayWidth = info.logicalWidth;
- mDisplayHeight = info.logicalHeight;
+ public boolean onDisplayInfoUpdated(DisplayInfo info, @NonNull WmDisplayCutout displayCutout,
+ @NonNull RoundedCorners roundedCorners) {
mRotation = info.rotation;
- final WmDisplayCutout wmDisplayCutout =
- displayCutout != null ? displayCutout : WmDisplayCutout.NO_CUTOUT;
final InsetsState state = mInsetsState;
- final Rect unrestricted = mUnrestricted;
final Rect safe = mDisplayCutoutSafe;
- final DisplayCutout cutout = wmDisplayCutout.getDisplayCutout();
+ final DisplayCutout cutout = displayCutout.getDisplayCutout();
+ if (mDisplayWidth == info.logicalWidth && mDisplayHeight == info.logicalHeight
+ && state.getDisplayCutout().equals(cutout)
+ && state.getRoundedCorners().equals(roundedCorners)) {
+ return false;
+ }
+ mDisplayWidth = info.logicalWidth;
+ mDisplayHeight = info.logicalHeight;
+ final Rect unrestricted = mUnrestricted;
unrestricted.set(0, 0, mDisplayWidth, mDisplayHeight);
safe.set(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
state.setDisplayFrame(unrestricted);
state.setDisplayCutout(cutout);
- state.setRoundedCorners(roundedCorners != null ? roundedCorners
- : RoundedCorners.NO_ROUNDED_CORNERS);
+ state.setRoundedCorners(roundedCorners);
if (!cutout.isEmpty()) {
if (cutout.getSafeInsetLeft() > 0) {
safe.left = unrestricted.left + cutout.getSafeInsetLeft();
@@ -116,6 +120,7 @@ public class DisplayFrames {
state.removeSource(ITYPE_RIGHT_DISPLAY_CUTOUT);
state.removeSource(ITYPE_BOTTOM_DISPLAY_CUTOUT);
}
+ return true;
}
public void dumpDebug(ProtoOutputStream proto, long fieldId) {
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index 580d3285c6a5..75176df6aaf7 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -27,6 +27,9 @@ import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_INVALID;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
+import static android.view.WindowInsets.Type.displayCutout;
+import static android.view.WindowInsets.Type.mandatorySystemGestures;
+import static android.view.WindowInsets.Type.systemGestures;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
@@ -293,6 +296,76 @@ class InsetsStateController {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
+ /**
+ * Updates {@link WindowState#mAboveInsetsState} for all windows in the display while the
+ * z-order of a window is changed.
+ *
+ * @param win The window whose z-order has changed.
+ * @param notifyInsetsChange {@code true} if the clients should be notified about the change.
+ */
+ void updateAboveInsetsState(WindowState win, boolean notifyInsetsChange) {
+ if (win == null || win.getDisplayContent() != mDisplayContent) {
+ return;
+ }
+ final boolean[] aboveWin = { true };
+ final InsetsState aboveInsetsState = new InsetsState();
+ aboveInsetsState.set(mState,
+ displayCutout() | systemGestures() | mandatorySystemGestures());
+ final SparseArray<InsetsSource> winProvidedSources = win.mProvidedInsetsSources;
+ final ArrayList<WindowState> insetsChangedWindows = new ArrayList<>();
+ mDisplayContent.forAllWindows(w -> {
+ if (aboveWin[0]) {
+ if (w == win) {
+ aboveWin[0] = false;
+ if (!win.mAboveInsetsState.equals(aboveInsetsState)) {
+ win.mAboveInsetsState.set(aboveInsetsState);
+ insetsChangedWindows.add(win);
+ }
+ return winProvidedSources.size() == 0;
+ } else {
+ final SparseArray<InsetsSource> providedSources = w.mProvidedInsetsSources;
+ for (int i = providedSources.size() - 1; i >= 0; i--) {
+ aboveInsetsState.addSource(providedSources.valueAt(i));
+ }
+ if (winProvidedSources.size() == 0) {
+ return false;
+ }
+ boolean changed = false;
+ for (int i = winProvidedSources.size() - 1; i >= 0; i--) {
+ changed |= w.mAboveInsetsState.removeSource(winProvidedSources.keyAt(i));
+ }
+ if (changed) {
+ insetsChangedWindows.add(w);
+ }
+ }
+ } else {
+ for (int i = winProvidedSources.size() - 1; i >= 0; i--) {
+ w.mAboveInsetsState.addSource(winProvidedSources.valueAt(i));
+ }
+ insetsChangedWindows.add(w);
+ }
+ return false;
+ }, true /* traverseTopToBottom */);
+ if (notifyInsetsChange) {
+ for (int i = insetsChangedWindows.size() - 1; i >= 0; i--) {
+ mDispatchInsetsChanged.accept(insetsChangedWindows.get(i));
+ }
+ }
+ }
+
+ void onDisplayInfoUpdated(boolean notifyInsetsChange) {
+ final ArrayList<WindowState> insetsChangedWindows = new ArrayList<>();
+ mDisplayContent.forAllWindows(w -> {
+ w.mAboveInsetsState.set(mState, displayCutout());
+ insetsChangedWindows.add(w);
+ }, true /* traverseTopToBottom */);
+ if (notifyInsetsChange) {
+ for (int i = insetsChangedWindows.size() - 1; i >= 0; i--) {
+ mDispatchInsetsChanged.accept(insetsChangedWindows.get(i));
+ }
+ }
+ }
+
void onInsetsModified(InsetsControlTarget caller) {
boolean changed = false;
for (int i = mProviders.size() - 1; i >= 0; i--) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 39b749ef54cb..89d30408fe25 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1881,6 +1881,10 @@ public class WindowManagerService extends IWindowManager.Stub
displayContent.sendNewConfiguration();
}
+ // This window doesn't have a frame yet. Don't let this window cause the insets change.
+ displayContent.getInsetsStateController().updateAboveInsetsState(
+ win, false /* notifyInsetsChanged */);
+
getInsetsSourceControls(win, outActiveControls);
}
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index a94b0aa9b72f..3dfdedfec0d1 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -211,11 +211,11 @@ import android.os.Trace;
import android.os.WorkSource;
import android.provider.Settings;
import android.text.TextUtils;
-import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DisplayMetrics;
import android.util.MergedConfiguration;
import android.util.Slog;
+import android.util.SparseArray;
import android.util.TimeUtils;
import android.util.proto.ProtoOutputStream;
import android.view.Display;
@@ -533,6 +533,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
*/
private boolean mOrientationChanging;
+ /** The time when the window was last requested to redraw for orientation change. */
+ private long mOrientationChangeRedrawRequestTime;
+
/**
* Sometimes in addition to the mOrientationChanging
* flag we report that the orientation is changing
@@ -648,12 +651,12 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
/**
* The insets state of sources provided by windows above the current window.
*/
- InsetsState mAboveInsetsState = new InsetsState();
+ final InsetsState mAboveInsetsState = new InsetsState();
/**
* The insets sources provided by this window.
*/
- ArrayMap<Integer, InsetsSource> mProvidedInsetsSources = new ArrayMap<>();
+ final SparseArray<InsetsSource> mProvidedInsetsSources = new SparseArray<>();
/**
* Surface insets from the previous call to relayout(), used to track
@@ -1441,11 +1444,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
// redrawn; to do that, we need to go through the process of getting informed by the
// application when it has finished drawing.
if (getOrientationChanging() || dragResizingChanged) {
- if (getOrientationChanging()) {
- Slog.v(TAG_WM, "Orientation start waiting for draw"
- + ", mDrawState=DRAW_PENDING in " + this
- + ", surfaceController " + winAnimator.mSurfaceController);
- }
if (dragResizingChanged) {
ProtoLog.v(WM_DEBUG_RESIZE,
"Resize start waiting for draw, "
@@ -2204,7 +2202,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
}
- @Override
+ @Override
void removeImmediately() {
super.removeImmediately();
@@ -3651,7 +3649,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
ProtoLog.v(WM_DEBUG_RESIZE, "Reporting new frame to %s: %s", this,
mWindowFrames.mCompatFrame);
- if (mWinAnimator.mDrawState == DRAW_PENDING) {
+ final boolean drawPending = mWinAnimator.mDrawState == DRAW_PENDING;
+ if (drawPending) {
ProtoLog.i(WM_DEBUG_ORIENTATION, "Resizing %s WITH DRAW PENDING", this);
}
@@ -3668,7 +3667,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mWindowFrames.clearReportResizeHints();
final MergedConfiguration mergedConfiguration = mLastReportedConfiguration;
- final boolean reportDraw = mWinAnimator.mDrawState == DRAW_PENDING || useBLASTSync() || !mRedrawForSyncReported;
+ final boolean reportDraw = drawPending || useBLASTSync() || !mRedrawForSyncReported;
final boolean forceRelayout = reportOrientation || isDragResizeChanged() || !mRedrawForSyncReported;
final int displayId = getDisplayId();
fillClientWindowFrames(mClientWindowFrames);
@@ -3679,6 +3678,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
mClient.resized(mClientWindowFrames, reportDraw, mergedConfiguration, forceRelayout,
getDisplayContent().getDisplayPolicy().areSystemBarsForcedShownLw(this),
displayId);
+ if (drawPending && reportOrientation && mOrientationChanging) {
+ mOrientationChangeRedrawRequestTime = SystemClock.elapsedRealtime();
+ ProtoLog.v(WM_DEBUG_ORIENTATION,
+ "Requested redraw for orientation change: %s", this);
+ }
if (mWmService.mAccessibilityController != null) {
mWmService.mAccessibilityController.onSomeWindowResizedOrMoved(displayId);
@@ -5732,6 +5736,18 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
boolean finishDrawing(SurfaceControl.Transaction postDrawTransaction) {
+ if (mOrientationChangeRedrawRequestTime > 0) {
+ final long duration =
+ SystemClock.elapsedRealtime() - mOrientationChangeRedrawRequestTime;
+ Slog.i(TAG, "finishDrawing of orientation change: " + this + " " + duration + "ms");
+ mOrientationChangeRedrawRequestTime = 0;
+ } else if (mActivityRecord != null && mActivityRecord.mRelaunchStartTime != 0
+ && mActivityRecord.findMainWindow() == this) {
+ final long duration =
+ SystemClock.elapsedRealtime() - mActivityRecord.mRelaunchStartTime;
+ Slog.i(TAG, "finishDrawing of relaunch: " + this + " " + duration + "ms");
+ mActivityRecord.mRelaunchStartTime = 0;
+ }
if (!onSyncFinishedDrawing()) {
return mWinAnimator.finishDrawingLocked(postDrawTransaction);
}
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index c1c79eeba96c..29bce792fe30 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -97,6 +97,7 @@ cc_defaults {
"libbase",
"libappfuse",
"libbinder",
+ "libbinder_ndk",
"libcutils",
"libcrypto",
"liblog",
@@ -172,6 +173,7 @@ cc_defaults {
"android.frameworks.schedulerservice@1.0",
"android.frameworks.sensorservice@1.0",
"android.frameworks.stats@1.0",
+ "android.frameworks.stats-V1-ndk_platform",
"android.system.suspend.control-V1-cpp",
"android.system.suspend.control.internal-cpp",
"android.system.suspend@1.0",
diff --git a/services/core/jni/com_android_server_SystemServer.cpp b/services/core/jni/com_android_server_SystemServer.cpp
index 729fa71af169..a73f6c6d8c2d 100644
--- a/services/core/jni/com_android_server_SystemServer.cpp
+++ b/services/core/jni/com_android_server_SystemServer.cpp
@@ -23,6 +23,7 @@
#include <jni.h>
#include <nativehelper/JNIHelp.h>
+#include <android/binder_manager.h>
#include <android/hidl/manager/1.2/IServiceManager.h>
#include <binder/IServiceManager.h>
#include <hidl/HidlTransportSupport.h>
@@ -31,6 +32,7 @@
#include <schedulerservice/SchedulingPolicyService.h>
#include <sensorservice/SensorService.h>
#include <sensorservicehidl/SensorManager.h>
+#include <stats/StatsAidl.h>
#include <stats/StatsHal.h>
#include <bionic/malloc.h>
@@ -45,6 +47,31 @@
using android::base::GetIntProperty;
using namespace std::chrono_literals;
+namespace {
+
+static void startStatsAidlService() {
+ using aidl::android::frameworks::stats::IStats;
+ using aidl::android::frameworks::stats::StatsHal;
+
+ std::shared_ptr<StatsHal> statsService = ndk::SharedRefBase::make<StatsHal>();
+
+ const std::string instance = std::string() + IStats::descriptor + "/default";
+ const binder_exception_t err =
+ AServiceManager_addService(statsService->asBinder().get(), instance.c_str());
+ LOG_ALWAYS_FATAL_IF(err != EX_NONE, "Cannot register %s: %d", instance.c_str(), err);
+}
+
+static void startStatsHidlService() {
+ using android::frameworks::stats::V1_0::IStats;
+ using android::frameworks::stats::V1_0::implementation::StatsHal;
+
+ android::sp<IStats> statsHal = new StatsHal();
+ const android::status_t err = statsHal->registerAsService();
+ LOG_ALWAYS_FATAL_IF(err != android::OK, "Cannot register %s: %d", IStats::descriptor, err);
+}
+
+} // namespace
+
namespace android {
static void android_server_SystemServer_startSensorService(JNIEnv* /* env */, jobject /* clazz */) {
@@ -54,7 +81,6 @@ static void android_server_SystemServer_startSensorService(JNIEnv* /* env */, jo
SensorService::publish(false /* allowIsolated */,
IServiceManager::DUMP_FLAG_PRIORITY_CRITICAL);
}
-
}
static void android_server_SystemServer_startHidlServices(JNIEnv* env, jobject /* clazz */) {
@@ -62,8 +88,6 @@ static void android_server_SystemServer_startHidlServices(JNIEnv* env, jobject /
using ::android::frameworks::schedulerservice::V1_0::implementation::SchedulingPolicyService;
using ::android::frameworks::sensorservice::V1_0::ISensorManager;
using ::android::frameworks::sensorservice::V1_0::implementation::SensorManager;
- using ::android::frameworks::stats::V1_0::IStats;
- using ::android::frameworks::stats::V1_0::implementation::StatsHal;
using ::android::hardware::configureRpcThreadpool;
using ::android::hidl::manager::V1_0::IServiceManager;
@@ -89,9 +113,8 @@ static void android_server_SystemServer_startHidlServices(JNIEnv* env, jobject /
ALOGW("%s is deprecated. Skipping registration.", ISchedulingPolicyService::descriptor);
}
- sp<IStats> statsHal = new StatsHal();
- err = statsHal->registerAsService();
- LOG_ALWAYS_FATAL_IF(err != OK, "Cannot register %s: %d", IStats::descriptor, err);
+ startStatsAidlService();
+ startStatsHidlService();
}
static void android_server_SystemServer_initZygoteChildHeapProfiling(JNIEnv* /* env */,
diff --git a/services/incremental/Android.bp b/services/incremental/Android.bp
index 7e1e99fe0a23..5ffbd771764d 100644
--- a/services/incremental/Android.bp
+++ b/services/incremental/Android.bp
@@ -133,5 +133,8 @@ cc_test {
],
static_libs: [
"libgmock",
- ]
+ ],
+ test_options: {
+ unit_test: true,
+ },
}
diff --git a/services/incremental/IncrementalService.cpp b/services/incremental/IncrementalService.cpp
index 2fa927bcccfd..ce6e6ab1e29c 100644
--- a/services/incremental/IncrementalService.cpp
+++ b/services/incremental/IncrementalService.cpp
@@ -1617,7 +1617,7 @@ bool IncrementalService::configureNativeBinaries(StorageId storage, std::string_
// Need a shared pointer: will be passing it into all unpacking jobs.
std::shared_ptr<ZipArchive> zipFile(zipFileHandle, [](ZipArchiveHandle h) { CloseArchive(h); });
void* cookie = nullptr;
- const auto libFilePrefix = path::join(constants().libDir, abi) + "/";
+ const auto libFilePrefix = path::join(constants().libDir, abi) += "/";
if (StartIteration(zipFile.get(), &cookie, libFilePrefix, constants().libSuffix)) {
LOG(ERROR) << "Failed to start zip iteration for " << apkFullPath;
return false;
@@ -1627,6 +1627,17 @@ bool IncrementalService::configureNativeBinaries(StorageId storage, std::string_
auto openZipTs = Clock::now();
+ auto mapFiles = (mIncFs->features() & incfs::Features::v2);
+ incfs::FileId sourceId;
+ if (mapFiles) {
+ sourceId = mIncFs->getFileId(ifs->control, apkFullPath);
+ if (!incfs::isValidFileId(sourceId)) {
+ LOG(WARNING) << "Error getting IncFS file ID for apk path '" << apkFullPath
+ << "', mapping disabled";
+ mapFiles = false;
+ }
+ }
+
std::vector<Job> jobQueue;
ZipEntry entry;
std::string_view fileName;
@@ -1635,13 +1646,16 @@ bool IncrementalService::configureNativeBinaries(StorageId storage, std::string_
continue;
}
+ const auto entryUncompressed = entry.method == kCompressStored;
+ const auto entryPageAligned = (entry.offset & (constants().blockSize - 1)) == 0;
+
if (!extractNativeLibs) {
// ensure the file is properly aligned and unpacked
- if (entry.method != kCompressStored) {
+ if (!entryUncompressed) {
LOG(WARNING) << "Library " << fileName << " must be uncompressed to mmap it";
return false;
}
- if ((entry.offset & (constants().blockSize - 1)) != 0) {
+ if (!entryPageAligned) {
LOG(WARNING) << "Library " << fileName
<< " must be page-aligned to mmap it, offset = 0x" << std::hex
<< entry.offset;
@@ -1665,6 +1679,28 @@ bool IncrementalService::configureNativeBinaries(StorageId storage, std::string_
continue;
}
+ if (mapFiles && entryUncompressed && entryPageAligned && entry.uncompressed_length > 0) {
+ incfs::NewMappedFileParams mappedFileParams = {
+ .sourceId = sourceId,
+ .sourceOffset = entry.offset,
+ .size = entry.uncompressed_length,
+ };
+
+ if (auto res = mIncFs->makeMappedFile(ifs->control, targetLibPathAbsolute, 0755,
+ mappedFileParams);
+ res == 0) {
+ if (perfLoggingEnabled()) {
+ auto doneTs = Clock::now();
+ LOG(INFO) << "incfs: Mapped " << libName << ": "
+ << elapsedMcs(startFileTs, doneTs) << "mcs";
+ }
+ continue;
+ } else {
+ LOG(WARNING) << "Failed to map file for: '" << targetLibPath << "' errno: " << res
+ << "; falling back to full extraction";
+ }
+ }
+
// Create new lib file without signature info
incfs::NewFileParams libFileParams = {
.size = entry.uncompressed_length,
@@ -1673,7 +1709,7 @@ bool IncrementalService::configureNativeBinaries(StorageId storage, std::string_
.metadata = {targetLibPath.c_str(), (IncFsSize)targetLibPath.size()},
};
incfs::FileId libFileId = idFromMetadata(targetLibPath);
- if (auto res = mIncFs->makeFile(ifs->control, targetLibPathAbsolute, 0777, libFileId,
+ if (auto res = mIncFs->makeFile(ifs->control, targetLibPathAbsolute, 0755, libFileId,
libFileParams)) {
LOG(ERROR) << "Failed to make file for: " << targetLibPath << " errno: " << res;
// If one lib file fails to be created, abort others as well
@@ -1900,25 +1936,33 @@ IncrementalService::LoadingProgress IncrementalService::getLoadingProgress(
}
IncrementalService::LoadingProgress IncrementalService::getLoadingProgressFromPath(
- const IncFsMount& ifs, std::string_view storagePath, bool stopOnFirstIncomplete) const {
- ssize_t totalBlocks = 0, filledBlocks = 0;
- const auto filePaths = mFs->listFilesRecursive(storagePath);
- for (const auto& filePath : filePaths) {
+ const IncFsMount& ifs, std::string_view storagePath,
+ const bool stopOnFirstIncomplete) const {
+ ssize_t totalBlocks = 0, filledBlocks = 0, error = 0;
+ mFs->listFilesRecursive(storagePath, [&, this](auto filePath) {
const auto [filledBlocksCount, totalBlocksCount] =
mIncFs->countFilledBlocks(ifs.control, filePath);
+ if (filledBlocksCount == -EOPNOTSUPP || filledBlocksCount == -ENOTSUP ||
+ filledBlocksCount == -ENOENT) {
+ // a kind of a file that's not really being loaded, e.g. a mapped range
+ // an older IncFS used to return ENOENT in this case, so handle it the same way
+ return true;
+ }
if (filledBlocksCount < 0) {
LOG(ERROR) << "getLoadingProgress failed to get filled blocks count for: " << filePath
<< " errno: " << filledBlocksCount;
- return {filledBlocksCount, filledBlocksCount};
+ error = filledBlocksCount;
+ return false;
}
totalBlocks += totalBlocksCount;
filledBlocks += filledBlocksCount;
if (stopOnFirstIncomplete && filledBlocks < totalBlocks) {
- break;
+ return false;
}
- }
+ return true;
+ });
- return {filledBlocks, totalBlocks};
+ return error ? LoadingProgress{error, error} : LoadingProgress{filledBlocks, totalBlocks};
}
bool IncrementalService::updateLoadingProgress(
diff --git a/services/incremental/ServiceWrappers.cpp b/services/incremental/ServiceWrappers.cpp
index 659d6503e11c..d61328942e5c 100644
--- a/services/incremental/ServiceWrappers.cpp
+++ b/services/incremental/ServiceWrappers.cpp
@@ -134,10 +134,11 @@ private:
} mLooper;
};
-class RealIncFs : public IncFsWrapper {
+class RealIncFs final : public IncFsWrapper {
public:
RealIncFs() = default;
~RealIncFs() final = default;
+ Features features() const final { return incfs::features(); }
void listExistingMounts(const ExistingMountCallback& cb) const final {
for (auto mount : incfs::defaultMountRegistry().copyMounts()) {
auto binds = mount.binds(); // span() doesn't like rvalue containers, needs to save it.
@@ -153,6 +154,10 @@ public:
incfs::NewFileParams params) const final {
return incfs::makeFile(control, path, mode, id, params);
}
+ ErrorCode makeMappedFile(const Control& control, std::string_view path, int mode,
+ incfs::NewMappedFileParams params) const final {
+ return incfs::makeMappedFile(control, path, mode, params);
+ }
ErrorCode makeDir(const Control& control, std::string_view path, int mode) const final {
return incfs::makeDir(control, path, mode);
}
@@ -282,11 +287,10 @@ private:
auto it = mJobs.begin();
// Always acquire begin(). We can't use it after unlock as mTimedJobs can change.
for (; it != mJobs.end() && it->when <= now; it = mJobs.begin()) {
- auto job = std::move(it->what);
- mJobs.erase(it);
+ auto jobNode = mJobs.extract(it);
lock.unlock();
- job();
+ jobNode.value().what();
lock.lock();
}
nextJobTs = it != mJobs.end() ? it->when : kInfinityTs;
@@ -308,20 +312,20 @@ private:
std::thread mThread;
};
-class RealFsWrapper : public FsWrapper {
+class RealFsWrapper final : public FsWrapper {
public:
RealFsWrapper() = default;
~RealFsWrapper() = default;
- std::vector<std::string> listFilesRecursive(std::string_view directoryPath) const final {
- std::vector<std::string> files;
+ void listFilesRecursive(std::string_view directoryPath, FileCallback onFile) const final {
for (const auto& entry : std::filesystem::recursive_directory_iterator(directoryPath)) {
if (!entry.is_regular_file()) {
continue;
}
- files.push_back(entry.path().c_str());
+ if (!onFile(entry.path().native())) {
+ break;
+ }
}
- return files;
}
};
diff --git a/services/incremental/ServiceWrappers.h b/services/incremental/ServiceWrappers.h
index d60035a9274d..245bb3105be5 100644
--- a/services/incremental/ServiceWrappers.h
+++ b/services/incremental/ServiceWrappers.h
@@ -16,6 +16,7 @@
#pragma once
+#include <android-base/function_ref.h>
#include <android-base/unique_fd.h>
#include <android/content/pm/DataLoaderParamsParcel.h>
#include <android/content/pm/FileSystemControlParcel.h>
@@ -77,18 +78,22 @@ public:
using ErrorCode = incfs::ErrorCode;
using UniqueFd = incfs::UniqueFd;
using WaitResult = incfs::WaitResult;
+ using Features = incfs::Features;
- using ExistingMountCallback =
- std::function<void(std::string_view root, std::string_view backingDir,
- std::span<std::pair<std::string_view, std::string_view>> binds)>;
+ using ExistingMountCallback = android::base::function_ref<
+ void(std::string_view root, std::string_view backingDir,
+ std::span<std::pair<std::string_view, std::string_view>> binds)>;
virtual ~IncFsWrapper() = default;
+ virtual Features features() const = 0;
virtual void listExistingMounts(const ExistingMountCallback& cb) const = 0;
virtual Control openMount(std::string_view path) const = 0;
virtual Control createControl(IncFsFd cmd, IncFsFd pendingReads, IncFsFd logs,
IncFsFd blocksWritten) const = 0;
virtual ErrorCode makeFile(const Control& control, std::string_view path, int mode, FileId id,
incfs::NewFileParams params) const = 0;
+ virtual ErrorCode makeMappedFile(const Control& control, std::string_view path, int mode,
+ incfs::NewMappedFileParams params) const = 0;
virtual ErrorCode makeDir(const Control& control, std::string_view path, int mode) const = 0;
virtual ErrorCode makeDirs(const Control& control, std::string_view path, int mode) const = 0;
virtual incfs::RawMetadata getMetadata(const Control& control, FileId fileid) const = 0;
@@ -148,7 +153,9 @@ public:
class FsWrapper {
public:
virtual ~FsWrapper() = default;
- virtual std::vector<std::string> listFilesRecursive(std::string_view directoryPath) const = 0;
+
+ using FileCallback = android::base::function_ref<bool(std::string_view)>;
+ virtual void listFilesRecursive(std::string_view directoryPath, FileCallback onFile) const = 0;
};
class ServiceManagerWrapper {
diff --git a/services/incremental/TEST_MAPPING b/services/incremental/TEST_MAPPING
new file mode 100644
index 000000000000..d93525600a2d
--- /dev/null
+++ b/services/incremental/TEST_MAPPING
@@ -0,0 +1,32 @@
+{
+ "presubmit": [
+ {
+ "name": "CtsContentTestCases",
+ "options": [
+ {
+ "include-filter": "android.content.pm.cts.PackageManagerShellCommandTest"
+ },
+ {
+ "include-filter": "android.content.pm.cts.PackageManagerShellCommandIncrementalTest"
+ },
+ {
+ "include-filter": "android.content.pm.cts.ChecksumsTest"
+ }
+ ]
+ },
+ {
+ "name": "CtsPackageManagerStatsHostTestCases",
+ "options": [
+ {
+ "include-filter": "com.android.cts.packagemanager.stats.host.PackageInstallerV2StatsTests"
+ }
+ ]
+ },
+ {
+ "name": "CtsIncrementalInstallHostTestCases"
+ },
+ {
+ "name": "CtsInstalledLoadingProgressHostTests"
+ }
+ ]
+}
diff --git a/services/incremental/test/IncrementalServiceTest.cpp b/services/incremental/test/IncrementalServiceTest.cpp
index ab491efe8583..b00a84fcd003 100644
--- a/services/incremental/test/IncrementalServiceTest.cpp
+++ b/services/incremental/test/IncrementalServiceTest.cpp
@@ -322,6 +322,7 @@ private:
class MockIncFs : public IncFsWrapper {
public:
+ MOCK_CONST_METHOD0(features, Features());
MOCK_CONST_METHOD1(listExistingMounts, void(const ExistingMountCallback& cb));
MOCK_CONST_METHOD1(openMount, Control(std::string_view path));
MOCK_CONST_METHOD4(createControl,
@@ -330,6 +331,9 @@ public:
MOCK_CONST_METHOD5(makeFile,
ErrorCode(const Control& control, std::string_view path, int mode, FileId id,
NewFileParams params));
+ MOCK_CONST_METHOD4(makeMappedFile,
+ ErrorCode(const Control& control, std::string_view path, int mode,
+ NewMappedFileParams params));
MOCK_CONST_METHOD3(makeDir, ErrorCode(const Control& control, std::string_view path, int mode));
MOCK_CONST_METHOD3(makeDirs,
ErrorCode(const Control& control, std::string_view path, int mode));
@@ -539,16 +543,16 @@ public:
class MockFsWrapper : public FsWrapper {
public:
- MOCK_CONST_METHOD1(listFilesRecursive, std::vector<std::string>(std::string_view));
- void hasNoFile() {
- ON_CALL(*this, listFilesRecursive(_)).WillByDefault(Return(std::vector<std::string>()));
- }
+ MOCK_CONST_METHOD2(listFilesRecursive, void(std::string_view, FileCallback));
+ void hasNoFile() { ON_CALL(*this, listFilesRecursive(_, _)).WillByDefault(Return()); }
void hasFiles() {
- ON_CALL(*this, listFilesRecursive(_))
+ ON_CALL(*this, listFilesRecursive(_, _))
.WillByDefault(Invoke(this, &MockFsWrapper::fakeFiles));
}
- std::vector<std::string> fakeFiles(std::string_view directoryPath) {
- return {"base.apk", "split.apk", "lib/a.so"};
+ void fakeFiles(std::string_view directoryPath, FileCallback onFile) {
+ for (auto file : {"base.apk", "split.apk", "lib/a.so"}) {
+ if (!onFile(file)) break;
+ }
}
};
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 27825a461b40..a382e85538cd 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -64,6 +64,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.AdditionalAnswers.answer;
import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyLong;
import static org.mockito.Mockito.doAnswer;
@@ -73,6 +74,8 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
+import android.app.ActivityManager;
+import android.app.AppOpsManager;
import android.app.IApplicationThread;
import android.app.IServiceConnection;
import android.content.ComponentName;
@@ -178,11 +181,20 @@ public class MockingOomAdjusterTests {
setFieldValue(ActivityManagerService.class, sService, "mAppProfiler", profiler);
setFieldValue(ActivityManagerService.class, sService, "mProcLock",
new ActivityManagerProcLock());
+ setFieldValue(ActivityManagerService.class, sService, "mServices",
+ spy(new ActiveServices(sService)));
+ setFieldValue(ActivityManagerService.class, sService, "mInternal",
+ mock(ActivityManagerService.LocalService.class));
+ setFieldValue(ActivityManagerService.class, sService, "mBatteryStatsService",
+ mock(BatteryStatsService.class));
+ doReturn(mock(AppOpsManager.class)).when(sService).getAppOpsManager();
+ doCallRealMethod().when(sService).enqueueOomAdjTargetLocked(any(ProcessRecord.class));
+ doCallRealMethod().when(sService).updateOomAdjPendingTargetsLocked(any(String.class));
setFieldValue(AppProfiler.class, profiler, "mProfilerLock", new Object());
doReturn(new ActivityManagerService.ProcessChangeItem()).when(pr)
.enqueueProcessChangeItemLocked(anyInt(), anyInt());
sService.mOomAdjuster = new OomAdjuster(sService, sService.mProcessList,
- mock(ActiveUids.class));
+ new ActiveUids(sService, false));
sService.mOomAdjuster.mAdjSeq = 10000;
sService.mWakefulness = new AtomicInteger(PowerManagerInternal.WAKEFULNESS_AWAKE);
}
@@ -1315,6 +1327,115 @@ public class MockingOomAdjusterTests {
@SuppressWarnings("GuardedBy")
@Test
+ public void testUpdateOomAdj_UidIdle_StopService() {
+ final ProcessRecord app1 = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+ MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+ final ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+ MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+ final ProcessRecord client1 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+ MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+ final ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP3_UID,
+ MOCKAPP4_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+ final ProcessRecord app3 = spy(makeDefaultProcessRecord(MOCKAPP5_PID, MOCKAPP5_UID,
+ MOCKAPP5_PROCESSNAME, MOCKAPP5_PACKAGENAME, false));
+ final UidRecord app1UidRecord = new UidRecord(MOCKAPP_UID, sService);
+ final UidRecord app2UidRecord = new UidRecord(MOCKAPP2_UID, sService);
+ final UidRecord app3UidRecord = new UidRecord(MOCKAPP5_UID, sService);
+ final UidRecord clientUidRecord = new UidRecord(MOCKAPP3_UID, sService);
+ app1.setUidRecord(app1UidRecord);
+ app2.setUidRecord(app2UidRecord);
+ app3.setUidRecord(app3UidRecord);
+ client1.setUidRecord(clientUidRecord);
+ client2.setUidRecord(clientUidRecord);
+
+ client1.mServices.setHasForegroundServices(true, 0);
+ client2.mState.setForcingToImportant(new Object());
+ ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
+ lru.clear();
+ lru.add(app1);
+ lru.add(app2);
+ lru.add(app3);
+ lru.add(client1);
+ lru.add(client2);
+ sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+
+ final ComponentName cn1 = ComponentName.unflattenFromString(
+ MOCKAPP_PACKAGENAME + "/.TestService");
+ final ServiceRecord s1 = bindService(app1, client1, null, 0, mock(IBinder.class));
+ setFieldValue(ServiceRecord.class, s1, "name", cn1);
+ s1.startRequested = true;
+
+ final ComponentName cn2 = ComponentName.unflattenFromString(
+ MOCKAPP2_PACKAGENAME + "/.TestService");
+ final ServiceRecord s2 = bindService(app2, client2, null, 0, mock(IBinder.class));
+ setFieldValue(ServiceRecord.class, s2, "name", cn2);
+ s2.startRequested = true;
+
+ final ComponentName cn3 = ComponentName.unflattenFromString(
+ MOCKAPP5_PACKAGENAME + "/.TestService");
+ final ServiceRecord s3 = bindService(app3, client1, null, 0, mock(IBinder.class));
+ setFieldValue(ServiceRecord.class, s3, "name", cn3);
+ s3.startRequested = true;
+
+ final ComponentName cn4 = ComponentName.unflattenFromString(
+ MOCKAPP3_PACKAGENAME + "/.TestService");
+ final ServiceRecord c2s = makeServiceRecord(client2);
+ setFieldValue(ServiceRecord.class, c2s, "name", cn4);
+ c2s.startRequested = true;
+
+ try {
+ sService.mOomAdjuster.mActiveUids.put(MOCKAPP_UID, app1UidRecord);
+ sService.mOomAdjuster.mActiveUids.put(MOCKAPP2_UID, app2UidRecord);
+ sService.mOomAdjuster.mActiveUids.put(MOCKAPP5_UID, app3UidRecord);
+ sService.mOomAdjuster.mActiveUids.put(MOCKAPP3_UID, clientUidRecord);
+
+ setServiceMap(s1, MOCKAPP_UID, cn1);
+ setServiceMap(s2, MOCKAPP2_UID, cn2);
+ setServiceMap(s3, MOCKAPP5_UID, cn3);
+ setServiceMap(c2s, MOCKAPP3_UID, cn4);
+ app2UidRecord.setIdle(false);
+ sService.mOomAdjuster.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertProcStates(app1, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(app3, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertProcStates(client1, PROCESS_STATE_FOREGROUND_SERVICE, PERCEPTIBLE_APP_ADJ,
+ SCHED_GROUP_DEFAULT);
+ assertEquals(PROCESS_STATE_TRANSIENT_BACKGROUND, app2.mState.getSetProcState());
+ assertEquals(PROCESS_STATE_TRANSIENT_BACKGROUND, client2.mState.getSetProcState());
+
+ client1.mServices.setHasForegroundServices(false, 0);
+ client2.mState.setForcingToImportant(null);
+ app1UidRecord.reset();
+ app2UidRecord.reset();
+ app3UidRecord.reset();
+ clientUidRecord.reset();
+ app1UidRecord.setIdle(true);
+ app2UidRecord.setIdle(true);
+ app3UidRecord.setIdle(true);
+ clientUidRecord.setIdle(true);
+ doReturn(ActivityManager.APP_START_MODE_DELAYED).when(sService)
+ .getAppStartModeLOSP(anyInt(), any(String.class), anyInt(),
+ anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
+ doNothing().when(sService.mServices)
+ .scheduleServiceTimeoutLocked(any(ProcessRecord.class));
+ sService.mOomAdjuster.updateOomAdjLocked(client1, OomAdjuster.OOM_ADJ_REASON_NONE);
+
+ assertEquals(PROCESS_STATE_CACHED_EMPTY, client1.mState.getSetProcState());
+ assertEquals(PROCESS_STATE_SERVICE, app1.mState.getSetProcState());
+ assertEquals(PROCESS_STATE_SERVICE, client2.mState.getSetProcState());
+ } finally {
+ doCallRealMethod().when(sService)
+ .getAppStartModeLOSP(anyInt(), any(String.class), anyInt(),
+ anyInt(), anyBoolean(), anyBoolean(), anyBoolean());
+ sService.mServices.mServiceMap.clear();
+ sService.mOomAdjuster.mActiveUids.clear();
+ }
+ }
+
+ @SuppressWarnings("GuardedBy")
+ @Test
public void testUpdateOomAdj_DoAll_Unbound() {
ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
@@ -1815,15 +1936,42 @@ public class MockingOomAdjusterTests {
return app;
}
+ private ServiceRecord makeServiceRecord(ProcessRecord app) {
+ final ServiceRecord record = mock(ServiceRecord.class);
+ record.app = app;
+ setFieldValue(ServiceRecord.class, record, "connections",
+ new ArrayMap<IBinder, ArrayList<ConnectionRecord>>());
+ doCallRealMethod().when(record).getConnections();
+ setFieldValue(ServiceRecord.class, record, "packageName", app.info.packageName);
+ app.mServices.startService(record);
+ record.appInfo = app.info;
+ setFieldValue(ServiceRecord.class, record, "bindings", new ArrayMap<>());
+ setFieldValue(ServiceRecord.class, record, "pendingStarts", new ArrayList<>());
+ return record;
+ }
+
+ private void setServiceMap(ServiceRecord s, int uid, ComponentName cn) {
+ ActiveServices.ServiceMap serviceMap = sService.mServices.mServiceMap.get(
+ UserHandle.getUserId(uid));
+ if (serviceMap == null) {
+ serviceMap = mock(ActiveServices.ServiceMap.class);
+ setFieldValue(ActiveServices.ServiceMap.class, serviceMap, "mServicesByInstanceName",
+ new ArrayMap<>());
+ setFieldValue(ActiveServices.ServiceMap.class, serviceMap, "mActiveForegroundApps",
+ new ArrayMap<>());
+ setFieldValue(ActiveServices.ServiceMap.class, serviceMap, "mServicesByIntent",
+ new ArrayMap<>());
+ setFieldValue(ActiveServices.ServiceMap.class, serviceMap, "mDelayedStartList",
+ new ArrayList<>());
+ sService.mServices.mServiceMap.put(UserHandle.getUserId(uid), serviceMap);
+ }
+ serviceMap.mServicesByInstanceName.put(cn, s);
+ }
+
private ServiceRecord bindService(ProcessRecord service, ProcessRecord client,
ServiceRecord record, int bindFlags, IBinder binder) {
if (record == null) {
- record = mock(ServiceRecord.class);
- record.app = service;
- setFieldValue(ServiceRecord.class, record, "connections",
- new ArrayMap<IBinder, ArrayList<ConnectionRecord>>());
- service.mServices.startService(record);
- doCallRealMethod().when(record).getConnections();
+ record = makeServiceRecord(service);
}
AppBindRecord binding = new AppBindRecord(record, null, client);
ConnectionRecord cr = spy(new ConnectionRecord(binding,
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
index ca534927bd66..7f8784dc2599 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -223,7 +223,7 @@ public class LocalDisplayAdapterTest {
for (int i = 0; i < wrappedModes.length; i++) {
modes[i] = wrappedModes[i].mode;
}
- display.modes = modes;
+ display.dynamicInfo.supportedDisplayModes = modes;
setUpDisplay(display);
mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
@@ -252,53 +252,53 @@ public class LocalDisplayAdapterTest {
testAlternativeRefreshRatesCommon(display, new DisplayModeWrapper[] {
new DisplayModeWrapper(
- createFakeDisplayMode(1920, 1080, 60f, 0), new float[]{24f, 50f}),
+ createFakeDisplayMode(0, 1920, 1080, 60f, 0), new float[]{24f, 50f}),
new DisplayModeWrapper(
- createFakeDisplayMode(1920, 1080, 50f, 0), new float[]{24f, 60f}),
+ createFakeDisplayMode(1, 1920, 1080, 50f, 0), new float[]{24f, 60f}),
new DisplayModeWrapper(
- createFakeDisplayMode(1920, 1080, 24f, 0), new float[]{50f, 60f}),
+ createFakeDisplayMode(2, 1920, 1080, 24f, 0), new float[]{50f, 60f}),
new DisplayModeWrapper(
- createFakeDisplayMode(3840, 2160, 60f, 0), new float[]{24f, 50f}),
+ createFakeDisplayMode(3, 3840, 2160, 60f, 0), new float[]{24f, 50f}),
new DisplayModeWrapper(
- createFakeDisplayMode(3840, 2160, 50f, 0), new float[]{24f, 60f}),
+ createFakeDisplayMode(4, 3840, 2160, 50f, 0), new float[]{24f, 60f}),
new DisplayModeWrapper(
- createFakeDisplayMode(3840, 2160, 24f, 0), new float[]{50f, 60f}),
+ createFakeDisplayMode(5, 3840, 2160, 24f, 0), new float[]{50f, 60f}),
});
testAlternativeRefreshRatesCommon(display, new DisplayModeWrapper[] {
new DisplayModeWrapper(
- createFakeDisplayMode(1920, 1080, 60f, 0), new float[]{50f}),
+ createFakeDisplayMode(0, 1920, 1080, 60f, 0), new float[]{50f}),
new DisplayModeWrapper(
- createFakeDisplayMode(1920, 1080, 50f, 0), new float[]{60f}),
+ createFakeDisplayMode(1, 1920, 1080, 50f, 0), new float[]{60f}),
new DisplayModeWrapper(
- createFakeDisplayMode(1920, 1080, 24f, 1), new float[0]),
+ createFakeDisplayMode(2, 1920, 1080, 24f, 1), new float[0]),
new DisplayModeWrapper(
- createFakeDisplayMode(3840, 2160, 60f, 2), new float[0]),
+ createFakeDisplayMode(3, 3840, 2160, 60f, 2), new float[0]),
new DisplayModeWrapper(
- createFakeDisplayMode(3840, 2160, 50f, 3), new float[]{24f}),
+ createFakeDisplayMode(4, 3840, 2160, 50f, 3), new float[]{24f}),
new DisplayModeWrapper(
- createFakeDisplayMode(3840, 2160, 24f, 3), new float[]{50f}),
+ createFakeDisplayMode(5, 3840, 2160, 24f, 3), new float[]{50f}),
});
testAlternativeRefreshRatesCommon(display, new DisplayModeWrapper[] {
new DisplayModeWrapper(
- createFakeDisplayMode(1920, 1080, 60f, 0), new float[0]),
+ createFakeDisplayMode(0, 1920, 1080, 60f, 0), new float[0]),
new DisplayModeWrapper(
- createFakeDisplayMode(1920, 1080, 50f, 1), new float[0]),
+ createFakeDisplayMode(1, 1920, 1080, 50f, 1), new float[0]),
new DisplayModeWrapper(
- createFakeDisplayMode(1920, 1080, 24f, 2), new float[0]),
+ createFakeDisplayMode(2, 1920, 1080, 24f, 2), new float[0]),
new DisplayModeWrapper(
- createFakeDisplayMode(3840, 2160, 60f, 3), new float[0]),
+ createFakeDisplayMode(3, 3840, 2160, 60f, 3), new float[0]),
new DisplayModeWrapper(
- createFakeDisplayMode(3840, 2160, 50f, 4), new float[0]),
+ createFakeDisplayMode(4, 3840, 2160, 50f, 4), new float[0]),
new DisplayModeWrapper(
- createFakeDisplayMode(3840, 2160, 24f, 5), new float[0]),
+ createFakeDisplayMode(5, 3840, 2160, 24f, 5), new float[0]),
});
}
@Test
public void testAfterDisplayChange_DisplayModesAreUpdated() throws Exception {
- SurfaceControl.DisplayMode displayMode = createFakeDisplayMode(1920, 1080, 60f);
+ SurfaceControl.DisplayMode displayMode = createFakeDisplayMode(0, 1920, 1080, 60f);
SurfaceControl.DisplayMode[] modes =
new SurfaceControl.DisplayMode[]{displayMode};
FakeDisplay display = new FakeDisplay(PORT_A, modes, 0);
@@ -325,18 +325,14 @@ public class LocalDisplayAdapterTest {
displayMode.refreshRate)).isTrue();
// Change the display
- SurfaceControl.DisplayMode addedDisplayInfo = createFakeDisplayMode(3840, 2160,
- 60f);
+ SurfaceControl.DisplayMode addedDisplayInfo = createFakeDisplayMode(1, 3840, 2160, 60f);
modes = new SurfaceControl.DisplayMode[]{displayMode, addedDisplayInfo};
- display.modes = modes;
- display.activeMode = 1;
+ display.dynamicInfo.supportedDisplayModes = modes;
+ display.dynamicInfo.activeDisplayModeId = 1;
setUpDisplay(display);
mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
- assertThat(SurfaceControl.getActiveDisplayMode(display.token)).isEqualTo(1);
- assertThat(SurfaceControl.getDisplayModes(display.token).length).isEqualTo(2);
-
assertThat(mListener.addedDisplays.size()).isEqualTo(1);
assertThat(mListener.changedDisplays.size()).isEqualTo(1);
@@ -360,8 +356,8 @@ public class LocalDisplayAdapterTest {
@Test
public void testAfterDisplayChange_ActiveModeIsUpdated() throws Exception {
SurfaceControl.DisplayMode[] modes = new SurfaceControl.DisplayMode[]{
- createFakeDisplayMode(1920, 1080, 60f),
- createFakeDisplayMode(1920, 1080, 50f)
+ createFakeDisplayMode(0, 1920, 1080, 60f),
+ createFakeDisplayMode(1, 1920, 1080, 50f)
};
FakeDisplay display = new FakeDisplay(PORT_A, modes, /* activeMode */ 0);
setUpDisplay(display);
@@ -379,13 +375,11 @@ public class LocalDisplayAdapterTest {
assertThat(activeMode.matches(1920, 1080, 60f)).isTrue();
// Change the display
- display.activeMode = 1;
+ display.dynamicInfo.activeDisplayModeId = 1;
setUpDisplay(display);
mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
- assertThat(SurfaceControl.getActiveDisplayMode(display.token)).isEqualTo(1);
-
assertThat(mListener.addedDisplays.size()).isEqualTo(1);
assertThat(mListener.changedDisplays.size()).isEqualTo(1);
@@ -402,7 +396,7 @@ public class LocalDisplayAdapterTest {
FakeDisplay display = new FakeDisplay(PORT_A);
Display.HdrCapabilities initialHdrCapabilities = new Display.HdrCapabilities(new int[0],
1000, 1000, 0);
- display.hdrCapabilities = initialHdrCapabilities;
+ display.dynamicInfo.hdrCapabilities = initialHdrCapabilities;
setUpDisplay(display);
updateAvailableDisplays();
mAdapter.registerLocked();
@@ -419,7 +413,7 @@ public class LocalDisplayAdapterTest {
// Change the display
Display.HdrCapabilities changedHdrCapabilities = new Display.HdrCapabilities(
new int[Display.HdrCapabilities.HDR_TYPE_HDR10_PLUS], 1000, 1000, 0);
- display.hdrCapabilities = changedHdrCapabilities;
+ display.dynamicInfo.hdrCapabilities = changedHdrCapabilities;
setUpDisplay(display);
mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
@@ -438,7 +432,7 @@ public class LocalDisplayAdapterTest {
public void testAfterDisplayChange_ColorModesAreUpdated() throws Exception {
FakeDisplay display = new FakeDisplay(PORT_A);
final int[] initialColorModes = new int[]{Display.COLOR_MODE_BT709};
- display.colorModes = initialColorModes;
+ display.dynamicInfo.supportedColorModes = initialColorModes;
setUpDisplay(display);
updateAvailableDisplays();
mAdapter.registerLocked();
@@ -455,7 +449,7 @@ public class LocalDisplayAdapterTest {
// Change the display
final int[] changedColorModes = new int[]{Display.COLOR_MODE_DEFAULT};
- display.colorModes = changedColorModes;
+ display.dynamicInfo.supportedColorModes = changedColorModes;
setUpDisplay(display);
mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
@@ -474,8 +468,8 @@ public class LocalDisplayAdapterTest {
@Test
public void testDisplayChange_withStaleDesiredDisplayModeSpecs() throws Exception {
SurfaceControl.DisplayMode[] modes = new SurfaceControl.DisplayMode[]{
- createFakeDisplayMode(1920, 1080, 60f),
- createFakeDisplayMode(1920, 1080, 50f)
+ createFakeDisplayMode(0, 1920, 1080, 60f),
+ createFakeDisplayMode(1, 1920, 1080, 50f)
};
final int activeMode = 0;
FakeDisplay display = new FakeDisplay(PORT_A, modes, activeMode);
@@ -487,11 +481,11 @@ public class LocalDisplayAdapterTest {
waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
// Change the display
- display.modes = new SurfaceControl.DisplayMode[]{
- createFakeDisplayMode(1920, 1080, 60f)
+ display.dynamicInfo.supportedDisplayModes = new SurfaceControl.DisplayMode[]{
+ createFakeDisplayMode(2, 1920, 1080, 60f)
};
- // SurfaceFlinger can return a stale defaultMode. Make sure this doesn't
- // trigger ArrayOutOfBoundsException.
+ display.dynamicInfo.activeDisplayModeId = 2;
+ // SurfaceFlinger can return a stale defaultMode. Make sure this doesn't crash.
display.desiredDisplayModeSpecs.defaultMode = 1;
setUpDisplay(display);
@@ -588,12 +582,15 @@ public class LocalDisplayAdapterTest {
private static class FakeDisplay {
public final DisplayAddress.Physical address;
public final IBinder token = new Binder();
- public final SurfaceControl.DisplayInfo info;
- public SurfaceControl.DisplayMode[] modes;
- public int activeMode;
- public int[] colorModes = new int[]{ Display.COLOR_MODE_DEFAULT };
- public Display.HdrCapabilities hdrCapabilities = new Display.HdrCapabilities(new int[0],
- 1000, 1000, 0);
+ public final SurfaceControl.StaticDisplayInfo info;
+ public SurfaceControl.DynamicDisplayInfo dynamicInfo =
+ new SurfaceControl.DynamicDisplayInfo();
+ {
+ dynamicInfo.supportedColorModes = new int[]{ Display.COLOR_MODE_DEFAULT };
+ dynamicInfo.hdrCapabilities = new Display.HdrCapabilities(new int[0],
+ 1000, 1000, 0);
+ }
+
public SurfaceControl.DesiredDisplayModeSpecs desiredDisplayModeSpecs =
new SurfaceControl.DesiredDisplayModeSpecs(/* defaultMode */ 0,
/* allowGroupSwitching */ false,
@@ -603,19 +600,19 @@ public class LocalDisplayAdapterTest {
/* appRefreshRateMax */60.f);
private FakeDisplay(int port) {
- this.address = createDisplayAddress(port);
- this.info = createFakeDisplayInfo();
- this.modes = new SurfaceControl.DisplayMode[]{
- createFakeDisplayMode(800, 600, 60f)
+ address = createDisplayAddress(port);
+ info = createFakeDisplayInfo();
+ dynamicInfo.supportedDisplayModes = new SurfaceControl.DisplayMode[]{
+ createFakeDisplayMode(0, 800, 600, 60f)
};
- this.activeMode = 0;
+ dynamicInfo.activeDisplayModeId = 0;
}
private FakeDisplay(int port, SurfaceControl.DisplayMode[] modes, int activeMode) {
- this.address = createDisplayAddress(port);
- this.info = createFakeDisplayInfo();
- this.modes = modes;
- this.activeMode = activeMode;
+ address = createDisplayAddress(port);
+ info = createFakeDisplayInfo();
+ dynamicInfo.supportedDisplayModes = modes;
+ dynamicInfo.activeDisplayModeId = activeMode;
}
}
@@ -623,15 +620,9 @@ public class LocalDisplayAdapterTest {
mAddresses.add(display.address);
doReturn(display.token).when(() ->
SurfaceControl.getPhysicalDisplayToken(display.address.getPhysicalDisplayId()));
- doReturn(display.info).when(() -> SurfaceControl.getDisplayInfo(display.token));
- doReturn(display.modes).when(
- () -> SurfaceControl.getDisplayModes(display.token));
- doReturn(display.activeMode).when(() -> SurfaceControl.getActiveDisplayMode(display.token));
- doReturn(0).when(() -> SurfaceControl.getActiveColorMode(display.token));
- doReturn(display.colorModes).when(
- () -> SurfaceControl.getDisplayColorModes(display.token));
- doReturn(display.hdrCapabilities).when(
- () -> SurfaceControl.getHdrCapabilities(display.token));
+ doReturn(display.info).when(() -> SurfaceControl.getStaticDisplayInfo(display.token));
+ doReturn(display.dynamicInfo).when(
+ () -> SurfaceControl.getDynamicDisplayInfo(display.token));
doReturn(display.desiredDisplayModeSpecs)
.when(() -> SurfaceControl.getDesiredDisplayModeSpecs(display.token));
}
@@ -650,20 +641,21 @@ public class LocalDisplayAdapterTest {
return DisplayAddress.fromPortAndModel(port, DISPLAY_MODEL);
}
- private static SurfaceControl.DisplayInfo createFakeDisplayInfo() {
- final SurfaceControl.DisplayInfo info = new SurfaceControl.DisplayInfo();
+ private static SurfaceControl.StaticDisplayInfo createFakeDisplayInfo() {
+ final SurfaceControl.StaticDisplayInfo info = new SurfaceControl.StaticDisplayInfo();
info.density = 100;
return info;
}
- private static SurfaceControl.DisplayMode createFakeDisplayMode(int width, int height,
+ private static SurfaceControl.DisplayMode createFakeDisplayMode(int id, int width, int height,
float refreshRate) {
- return createFakeDisplayMode(width, height, refreshRate, 0);
+ return createFakeDisplayMode(id, width, height, refreshRate, 0);
}
- private static SurfaceControl.DisplayMode createFakeDisplayMode(int width, int height,
+ private static SurfaceControl.DisplayMode createFakeDisplayMode(int id, int width, int height,
float refreshRate, int group) {
final SurfaceControl.DisplayMode mode = new SurfaceControl.DisplayMode();
+ mode.id = id;
mode.width = width;
mode.height = height;
mode.refreshRate = refreshRate;
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
index 6d40034c6000..91b3cb7dbdd9 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
@@ -25,6 +25,7 @@ import static com.android.server.job.JobSchedulerService.NEVER_INDEX;
import static com.android.server.job.JobSchedulerService.RARE_INDEX;
import static com.android.server.job.JobSchedulerService.RESTRICTED_INDEX;
import static com.android.server.job.JobSchedulerService.WORKING_INDEX;
+import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
import static com.android.server.job.controllers.JobStatus.CONSTRAINT_BACKGROUND_NOT_RESTRICTED;
import static com.android.server.job.controllers.JobStatus.CONSTRAINT_BATTERY_NOT_LOW;
import static com.android.server.job.controllers.JobStatus.CONSTRAINT_CHARGING;
@@ -101,7 +102,7 @@ public class JobStatusTest {
Clock.fixed(Clock.systemUTC().instant(), ZoneOffset.UTC);
JobSchedulerService.sUptimeMillisClock =
Clock.fixed(SystemClock.uptimeClock().instant(), ZoneOffset.UTC);
- JobSchedulerService.sElapsedRealtimeClock =
+ sElapsedRealtimeClock =
Clock.fixed(SystemClock.elapsedRealtimeClock().instant(), ZoneOffset.UTC);
}
@@ -204,7 +205,7 @@ public class JobStatusTest {
@Test
public void testFraction() throws Exception {
- final long now = JobSchedulerService.sElapsedRealtimeClock.millis();
+ final long now = sElapsedRealtimeClock.millis();
assertEquals(1, createJobStatus(0, Long.MAX_VALUE).getFractionRunTime(), DELTA);
@@ -261,15 +262,15 @@ public class JobStatusTest {
final JobStatus job = createJobStatus(jobInfo);
markImplicitConstraintsSatisfied(job, true);
- job.setChargingConstraintSatisfied(false);
+ job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
- job.setChargingConstraintSatisfied(true);
+ job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
markImplicitConstraintsSatisfied(job, false);
- job.setChargingConstraintSatisfied(false);
+ job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
- job.setChargingConstraintSatisfied(true);
+ job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
}
@@ -282,15 +283,15 @@ public class JobStatusTest {
final JobStatus job = createJobStatus(jobInfo);
markImplicitConstraintsSatisfied(job, true);
- job.setIdleConstraintSatisfied(false);
+ job.setIdleConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_IDLE));
- job.setIdleConstraintSatisfied(true);
+ job.setIdleConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_IDLE));
markImplicitConstraintsSatisfied(job, false);
- job.setIdleConstraintSatisfied(false);
+ job.setIdleConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_IDLE));
- job.setIdleConstraintSatisfied(true);
+ job.setIdleConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_IDLE));
}
@@ -303,15 +304,15 @@ public class JobStatusTest {
final JobStatus job = createJobStatus(jobInfo);
markImplicitConstraintsSatisfied(job, true);
- job.setBatteryNotLowConstraintSatisfied(false);
+ job.setBatteryNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_BATTERY_NOT_LOW));
- job.setBatteryNotLowConstraintSatisfied(true);
+ job.setBatteryNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_BATTERY_NOT_LOW));
markImplicitConstraintsSatisfied(job, false);
- job.setBatteryNotLowConstraintSatisfied(false);
+ job.setBatteryNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_BATTERY_NOT_LOW));
- job.setBatteryNotLowConstraintSatisfied(true);
+ job.setBatteryNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_BATTERY_NOT_LOW));
}
@@ -324,15 +325,15 @@ public class JobStatusTest {
final JobStatus job = createJobStatus(jobInfo);
markImplicitConstraintsSatisfied(job, true);
- job.setStorageNotLowConstraintSatisfied(false);
+ job.setStorageNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_STORAGE_NOT_LOW));
- job.setStorageNotLowConstraintSatisfied(true);
+ job.setStorageNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_STORAGE_NOT_LOW));
markImplicitConstraintsSatisfied(job, false);
- job.setStorageNotLowConstraintSatisfied(false);
+ job.setStorageNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_STORAGE_NOT_LOW));
- job.setStorageNotLowConstraintSatisfied(true);
+ job.setStorageNotLowConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_STORAGE_NOT_LOW));
}
@@ -345,15 +346,15 @@ public class JobStatusTest {
final JobStatus job = createJobStatus(jobInfo);
markImplicitConstraintsSatisfied(job, true);
- job.setTimingDelayConstraintSatisfied(false);
+ job.setTimingDelayConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_TIMING_DELAY));
- job.setTimingDelayConstraintSatisfied(true);
+ job.setTimingDelayConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_TIMING_DELAY));
markImplicitConstraintsSatisfied(job, false);
- job.setTimingDelayConstraintSatisfied(false);
+ job.setTimingDelayConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_TIMING_DELAY));
- job.setTimingDelayConstraintSatisfied(true);
+ job.setTimingDelayConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_TIMING_DELAY));
}
@@ -366,15 +367,15 @@ public class JobStatusTest {
final JobStatus job = createJobStatus(jobInfo);
markImplicitConstraintsSatisfied(job, true);
- job.setDeadlineConstraintSatisfied(false);
+ job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
- job.setDeadlineConstraintSatisfied(true);
+ job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
markImplicitConstraintsSatisfied(job, false);
- job.setDeadlineConstraintSatisfied(false);
+ job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
- job.setDeadlineConstraintSatisfied(true);
+ job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
}
@@ -387,15 +388,15 @@ public class JobStatusTest {
final JobStatus job = createJobStatus(jobInfo);
markImplicitConstraintsSatisfied(job, true);
- job.setConnectivityConstraintSatisfied(false);
+ job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
- job.setConnectivityConstraintSatisfied(true);
+ job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
markImplicitConstraintsSatisfied(job, false);
- job.setConnectivityConstraintSatisfied(false);
+ job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
- job.setConnectivityConstraintSatisfied(true);
+ job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
}
@@ -410,15 +411,15 @@ public class JobStatusTest {
final JobStatus job = createJobStatus(jobInfo);
markImplicitConstraintsSatisfied(job, true);
- job.setContentTriggerConstraintSatisfied(false);
+ job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
- job.setContentTriggerConstraintSatisfied(true);
+ job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
markImplicitConstraintsSatisfied(job, false);
- job.setContentTriggerConstraintSatisfied(false);
+ job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
- job.setContentTriggerConstraintSatisfied(true);
+ job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
}
@@ -436,15 +437,15 @@ public class JobStatusTest {
markImplicitConstraintsSatisfied(job, false);
- job.setChargingConstraintSatisfied(false);
- job.setConnectivityConstraintSatisfied(false);
- job.setContentTriggerConstraintSatisfied(false);
+ job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+ job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+ job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
- job.setChargingConstraintSatisfied(true);
- job.setConnectivityConstraintSatisfied(true);
- job.setContentTriggerConstraintSatisfied(true);
+ job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+ job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+ job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
// Still false because implicit constraints aren't satisfied.
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
@@ -452,61 +453,61 @@ public class JobStatusTest {
markImplicitConstraintsSatisfied(job, true);
- job.setChargingConstraintSatisfied(false);
- job.setConnectivityConstraintSatisfied(false);
- job.setContentTriggerConstraintSatisfied(false);
+ job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+ job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+ job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
// Turn on constraints one at a time.
- job.setChargingConstraintSatisfied(true);
- job.setConnectivityConstraintSatisfied(false);
- job.setContentTriggerConstraintSatisfied(false);
+ job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+ job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+ job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
- job.setChargingConstraintSatisfied(false);
- job.setConnectivityConstraintSatisfied(false);
- job.setContentTriggerConstraintSatisfied(true);
+ job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+ job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+ job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
- job.setChargingConstraintSatisfied(false);
- job.setConnectivityConstraintSatisfied(true);
- job.setContentTriggerConstraintSatisfied(false);
+ job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+ job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+ job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
// With two of the 3 constraints satisfied (and implicit constraints also satisfied), only
// the unsatisfied constraint should return true.
- job.setChargingConstraintSatisfied(true);
- job.setConnectivityConstraintSatisfied(false);
- job.setContentTriggerConstraintSatisfied(true);
+ job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+ job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+ job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
- job.setChargingConstraintSatisfied(true);
- job.setConnectivityConstraintSatisfied(true);
- job.setContentTriggerConstraintSatisfied(false);
+ job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+ job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+ job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
- job.setChargingConstraintSatisfied(false);
- job.setConnectivityConstraintSatisfied(true);
- job.setContentTriggerConstraintSatisfied(true);
+ job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+ job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+ job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
- job.setChargingConstraintSatisfied(true);
- job.setConnectivityConstraintSatisfied(true);
- job.setContentTriggerConstraintSatisfied(true);
+ job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+ job.setConnectivityConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+ job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONNECTIVITY));
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
@@ -526,15 +527,15 @@ public class JobStatusTest {
markImplicitConstraintsSatisfied(job, false);
- job.setChargingConstraintSatisfied(false);
- job.setContentTriggerConstraintSatisfied(false);
- job.setDeadlineConstraintSatisfied(false);
+ job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+ job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+ job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
- job.setChargingConstraintSatisfied(true);
- job.setContentTriggerConstraintSatisfied(true);
- job.setDeadlineConstraintSatisfied(true);
+ job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+ job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+ job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
// Still false because implicit constraints aren't satisfied.
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
@@ -542,18 +543,18 @@ public class JobStatusTest {
markImplicitConstraintsSatisfied(job, true);
- job.setChargingConstraintSatisfied(false);
- job.setContentTriggerConstraintSatisfied(false);
- job.setDeadlineConstraintSatisfied(false);
+ job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+ job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+ job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
// Once implicit constraint are satisfied, deadline constraint should always return true.
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
// Turn on constraints one at a time.
- job.setChargingConstraintSatisfied(true);
- job.setContentTriggerConstraintSatisfied(false);
- job.setDeadlineConstraintSatisfied(false);
+ job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+ job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+ job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
// Deadline should force isReady to be true, but isn't needed for the job to be
// considered ready.
@@ -561,17 +562,17 @@ public class JobStatusTest {
// Once implicit constraint are satisfied, deadline constraint should always return true.
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
- job.setChargingConstraintSatisfied(false);
- job.setContentTriggerConstraintSatisfied(true);
- job.setDeadlineConstraintSatisfied(false);
+ job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+ job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+ job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
// Once implicit constraint are satisfied, deadline constraint should always return true.
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
- job.setChargingConstraintSatisfied(false);
- job.setContentTriggerConstraintSatisfied(false);
- job.setDeadlineConstraintSatisfied(true);
+ job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+ job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+ job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
// Since the deadline constraint is satisfied, none of the other explicit constraints are
// needed.
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
@@ -581,33 +582,33 @@ public class JobStatusTest {
// With two of the 3 constraints satisfied (and implicit constraints also satisfied), only
// the unsatisfied constraint should return true.
- job.setChargingConstraintSatisfied(true);
- job.setContentTriggerConstraintSatisfied(true);
- job.setDeadlineConstraintSatisfied(false);
+ job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+ job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+ job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
// Once implicit constraint are satisfied, deadline constraint should always return true.
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
- job.setChargingConstraintSatisfied(true);
- job.setContentTriggerConstraintSatisfied(false);
- job.setDeadlineConstraintSatisfied(true);
+ job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+ job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+ job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
// Once implicit constraint are satisfied, deadline constraint should always return true.
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
- job.setChargingConstraintSatisfied(false);
- job.setContentTriggerConstraintSatisfied(true);
- job.setDeadlineConstraintSatisfied(true);
+ job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
+ job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+ job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
// Once implicit constraint are satisfied, deadline constraint should always return true.
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEADLINE));
- job.setChargingConstraintSatisfied(true);
- job.setContentTriggerConstraintSatisfied(true);
- job.setDeadlineConstraintSatisfied(true);
+ job.setChargingConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+ job.setContentTriggerConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
+ job.setDeadlineConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CHARGING));
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_CONTENT_TRIGGER));
// Once implicit constraint are satisfied, deadline constraint should always return true.
@@ -621,15 +622,15 @@ public class JobStatusTest {
new JobInfo.Builder(101, new ComponentName("foo", "bar")).build());
markImplicitConstraintsSatisfied(job, false);
- job.setDeviceNotDozingConstraintSatisfied(false, false);
+ job.setDeviceNotDozingConstraintSatisfied(sElapsedRealtimeClock.millis(), false, false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEVICE_NOT_DOZING));
- job.setDeviceNotDozingConstraintSatisfied(true, false);
+ job.setDeviceNotDozingConstraintSatisfied(sElapsedRealtimeClock.millis(), true, false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_DEVICE_NOT_DOZING));
markImplicitConstraintsSatisfied(job, true);
- job.setDeviceNotDozingConstraintSatisfied(false, false);
+ job.setDeviceNotDozingConstraintSatisfied(sElapsedRealtimeClock.millis(), false, false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEVICE_NOT_DOZING));
- job.setDeviceNotDozingConstraintSatisfied(true, false);
+ job.setDeviceNotDozingConstraintSatisfied(sElapsedRealtimeClock.millis(), true, false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_DEVICE_NOT_DOZING));
}
@@ -640,15 +641,15 @@ public class JobStatusTest {
new JobInfo.Builder(101, new ComponentName("foo", "bar")).build());
markImplicitConstraintsSatisfied(job, false);
- job.setQuotaConstraintSatisfied(false);
+ job.setQuotaConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_WITHIN_QUOTA));
- job.setQuotaConstraintSatisfied(true);
+ job.setQuotaConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_WITHIN_QUOTA));
markImplicitConstraintsSatisfied(job, true);
- job.setQuotaConstraintSatisfied(false);
+ job.setQuotaConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_WITHIN_QUOTA));
- job.setQuotaConstraintSatisfied(true);
+ job.setQuotaConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_WITHIN_QUOTA));
}
@@ -659,22 +660,24 @@ public class JobStatusTest {
new JobInfo.Builder(101, new ComponentName("foo", "bar")).build());
markImplicitConstraintsSatisfied(job, false);
- job.setBackgroundNotRestrictedConstraintSatisfied(false);
+ job.setBackgroundNotRestrictedConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_BACKGROUND_NOT_RESTRICTED));
- job.setBackgroundNotRestrictedConstraintSatisfied(true);
+ job.setBackgroundNotRestrictedConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertFalse(job.wouldBeReadyWithConstraint(CONSTRAINT_BACKGROUND_NOT_RESTRICTED));
markImplicitConstraintsSatisfied(job, true);
- job.setBackgroundNotRestrictedConstraintSatisfied(false);
+ job.setBackgroundNotRestrictedConstraintSatisfied(sElapsedRealtimeClock.millis(), false);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_BACKGROUND_NOT_RESTRICTED));
- job.setBackgroundNotRestrictedConstraintSatisfied(true);
+ job.setBackgroundNotRestrictedConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
assertTrue(job.wouldBeReadyWithConstraint(CONSTRAINT_BACKGROUND_NOT_RESTRICTED));
}
private void markImplicitConstraintsSatisfied(JobStatus job, boolean isSatisfied) {
- job.setQuotaConstraintSatisfied(isSatisfied);
- job.setDeviceNotDozingConstraintSatisfied(isSatisfied, false);
- job.setBackgroundNotRestrictedConstraintSatisfied(isSatisfied);
+ job.setQuotaConstraintSatisfied(sElapsedRealtimeClock.millis(), isSatisfied);
+ job.setDeviceNotDozingConstraintSatisfied(
+ sElapsedRealtimeClock.millis(), isSatisfied, false);
+ job.setBackgroundNotRestrictedConstraintSatisfied(
+ sElapsedRealtimeClock.millis(), isSatisfied);
}
private static JobStatus createJobStatus(long earliestRunTimeElapsedMillis,
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
index b72121f096ba..88a691bbc209 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/QuotaControllerTest.java
@@ -359,8 +359,9 @@ public class QuotaControllerTest {
// Make sure tests aren't passing just because the default bucket is likely ACTIVE.
js.setStandbyBucket(FREQUENT_INDEX);
// Make sure Doze and background-not-restricted don't affect tests.
- js.setDeviceNotDozingConstraintSatisfied(/* state */ true, /* allowlisted */false);
- js.setBackgroundNotRestrictedConstraintSatisfied(true);
+ js.setDeviceNotDozingConstraintSatisfied(/* nowElapsed */ sElapsedRealtimeClock.millis(),
+ /* state */ true, /* allowlisted */false);
+ js.setBackgroundNotRestrictedConstraintSatisfied(sElapsedRealtimeClock.millis(), true);
return js;
}
diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java
index 41e15631d258..663017890b0c 100644
--- a/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsNotedWatcherTest.java
@@ -66,11 +66,13 @@ public class AppOpsNotedWatcherTest {
inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
.times(1)).onOpNoted(eq(AppOpsManager.OP_FINE_LOCATION),
eq(Process.myUid()), eq(getContext().getPackageName()),
- eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED));
+ eq(getContext().getAttributionTag()), eq(AppOpsManager.OP_FLAG_SELF),
+ eq(AppOpsManager.MODE_ALLOWED));
inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
.times(1)).onOpNoted(eq(AppOpsManager.OP_CAMERA),
eq(Process.myUid()), eq(getContext().getPackageName()),
- eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED));
+ eq(getContext().getAttributionTag()), eq(AppOpsManager.OP_FLAG_SELF),
+ eq(AppOpsManager.MODE_ALLOWED));
// Stop watching
appOpsManager.stopWatchingNoted(listener);
@@ -94,7 +96,8 @@ public class AppOpsNotedWatcherTest {
verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
.times(2)).onOpNoted(eq(AppOpsManager.OP_FINE_LOCATION),
eq(Process.myUid()), eq(getContext().getPackageName()),
- eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED));
+ eq(getContext().getAttributionTag()), eq(AppOpsManager.OP_FLAG_SELF),
+ eq(AppOpsManager.MODE_ALLOWED));
// Finish up
appOpsManager.stopWatchingNoted(listener);
diff --git a/services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java b/services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java
index fec8aa9ceaff..c12eb32a9143 100644
--- a/services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/appop/AppOpsStartedWatcherTest.java
@@ -63,11 +63,13 @@ public class AppOpsStartedWatcherTest {
inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
.times(1)).onOpStarted(eq(AppOpsManager.OP_FINE_LOCATION),
eq(Process.myUid()), eq(getContext().getPackageName()),
- eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED));
+ eq(getContext().getAttributionTag()), eq(AppOpsManager.OP_FLAG_SELF),
+ eq(AppOpsManager.MODE_ALLOWED));
inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
.times(1)).onOpStarted(eq(AppOpsManager.OP_CAMERA),
eq(Process.myUid()), eq(getContext().getPackageName()),
- eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED));
+ eq(getContext().getAttributionTag()), eq(AppOpsManager.OP_FLAG_SELF),
+ eq(AppOpsManager.MODE_ALLOWED));
// Stop watching
appOpsManager.stopWatchingStarted(listener);
@@ -91,7 +93,8 @@ public class AppOpsStartedWatcherTest {
verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
.times(2)).onOpStarted(eq(AppOpsManager.OP_CAMERA),
eq(Process.myUid()), eq(getContext().getPackageName()),
- eq(AppOpsManager.OP_FLAG_SELF), eq(AppOpsManager.MODE_ALLOWED));
+ eq(getContext().getAttributionTag()), eq(AppOpsManager.OP_FLAG_SELF),
+ eq(AppOpsManager.MODE_ALLOWED));
verifyNoMoreInteractions(listener);
// Finish up
diff --git a/services/tests/servicestests/src/com/android/server/power/FaceDownDetectorTest.java b/services/tests/servicestests/src/com/android/server/power/FaceDownDetectorTest.java
new file mode 100644
index 000000000000..ef20ee7e6ecd
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/power/FaceDownDetectorTest.java
@@ -0,0 +1,165 @@
+/*
+ * 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.server.power;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.hardware.Sensor;
+import android.hardware.SensorEvent;
+import android.hardware.SensorManager;
+import android.testing.TestableContext;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+
+import com.android.server.display.TestUtils;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.lang.reflect.Constructor;
+import java.time.Duration;
+
+public class FaceDownDetectorTest {
+ @ClassRule
+ public static final TestableContext sContext = new TestableContext(
+ InstrumentationRegistry.getInstrumentation().getTargetContext(), null);
+
+ private final FaceDownDetector mFaceDownDetector =
+ new FaceDownDetector(this::onFlip);
+
+ @Mock private SensorManager mSensorManager;
+
+ private long mCurrentTime;
+ private int mOnFaceDownCalls = 0;
+ private int mOnFaceDownExitCalls = 0;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ sContext.addMockSystemService(SensorManager.class, mSensorManager);
+ mCurrentTime = 0;
+ }
+
+ @Test
+ public void faceDownFor2Seconds_triggersFaceDown() throws Exception {
+ mFaceDownDetector.systemReady(sContext);
+
+ // Face up
+ // Using 0.5 on x to simulate constant acceleration, such as a sloped surface.
+ mFaceDownDetector.onSensorChanged(createTestEvent(0.5f, 0.0f, 10.0f));
+
+ for (int i = 0; i < 200; i++) {
+ advanceTime(Duration.ofMillis(20));
+ mFaceDownDetector.onSensorChanged(createTestEvent(0.5f, 0.0f, -10.0f));
+ }
+
+ assertThat(mOnFaceDownCalls).isEqualTo(1);
+ assertThat(mOnFaceDownExitCalls).isEqualTo(0);
+ }
+
+ @Test
+ public void faceDownFor2Seconds_withMotion_DoesNotTriggerFaceDown() throws Exception {
+ mFaceDownDetector.systemReady(sContext);
+
+ // Face up
+ mFaceDownDetector.onSensorChanged(createTestEvent(0.5f, 0.0f, 10.0f));
+
+ for (int i = 0; i < 100; i++) {
+ advanceTime(Duration.ofMillis(20));
+ //Move along x direction
+ mFaceDownDetector.onSensorChanged(createTestEvent(0.5f * i, 0.0f, -10.0f));
+ }
+
+ assertThat(mOnFaceDownCalls).isEqualTo(0);
+ assertThat(mOnFaceDownExitCalls).isEqualTo(0);
+ }
+
+ @Test
+ public void faceDownForHalfSecond_DoesNotTriggerFaceDown() throws Exception {
+ mFaceDownDetector.systemReady(sContext);
+
+ // Face up
+ mFaceDownDetector.onSensorChanged(createTestEvent(0.5f, 0.0f, 10.0f));
+
+ for (int i = 0; i < 100; i++) {
+ advanceTime(Duration.ofMillis(5));
+ mFaceDownDetector.onSensorChanged(createTestEvent(0.5f, 0.0f, -10.0f));
+ }
+
+ assertThat(mOnFaceDownCalls).isEqualTo(0);
+ assertThat(mOnFaceDownExitCalls).isEqualTo(0);
+ }
+
+ @Test
+ public void faceDownFor2Seconds_followedByFaceUp_triggersFaceDownExit() throws Exception {
+ mFaceDownDetector.systemReady(sContext);
+
+ // Face up
+ // Using 0.5 on x to simulate constant acceleration, such as a sloped surface.
+ mFaceDownDetector.onSensorChanged(createTestEvent(0.5f, 0.0f, 10.0f));
+
+ // Trigger face down
+ for (int i = 0; i < 100; i++) {
+ advanceTime(Duration.ofMillis(20));
+ mFaceDownDetector.onSensorChanged(createTestEvent(0.5f, 0.0f, -10.0f));
+ }
+
+ // Phone flips
+ for (int i = 0; i < 10; i++) {
+ advanceTime(Duration.ofMillis(5));
+ mFaceDownDetector.onSensorChanged(createTestEvent(0.5f, 1.0f, 0.0f));
+ }
+
+ assertThat(mOnFaceDownCalls).isEqualTo(1);
+ assertThat(mOnFaceDownExitCalls).isEqualTo(1);
+ }
+
+ private void advanceTime(Duration duration) {
+ mCurrentTime += duration.toNanos();
+ }
+
+ /**
+ * Create a test event to replicate an accelerometer sensor event.
+ * @param x Acceleration along the x dimension.
+ * @param y Acceleration along the y dimension.
+ * @param gravity Acceleration along the Z dimension. Relates to
+ */
+ private SensorEvent createTestEvent(float x, float y, float gravity) throws Exception {
+ final Constructor<SensorEvent> constructor =
+ SensorEvent.class.getDeclaredConstructor(int.class);
+ constructor.setAccessible(true);
+ final SensorEvent event = constructor.newInstance(3);
+ event.sensor =
+ TestUtils.createSensor(Sensor.TYPE_ACCELEROMETER, Sensor.STRING_TYPE_ACCELEROMETER);
+ event.values[0] = x;
+ event.values[1] = y;
+ event.values[2] = gravity;
+ event.timestamp = mCurrentTime;
+ return event;
+ }
+
+ private void onFlip(boolean isFaceDown) {
+ if (isFaceDown) {
+ mOnFaceDownCalls++;
+ } else {
+ mOnFaceDownExitCalls++;
+ }
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/power/NotifierTest.java b/services/tests/servicestests/src/com/android/server/power/NotifierTest.java
index 1c2d8e80ea99..5012ca9ab420 100644
--- a/services/tests/servicestests/src/com/android/server/power/NotifierTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/NotifierTest.java
@@ -209,7 +209,8 @@ public class NotifierTest {
private final PowerManagerService.Injector mInjector = new PowerManagerService.Injector() {
@Override
Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats,
- SuspendBlocker suspendBlocker, WindowManagerPolicy policy) {
+ SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
+ FaceDownDetector faceDownDetector) {
return mNotifierMock;
}
@@ -296,6 +297,7 @@ public class NotifierTest {
IBatteryStats.Stub.asInterface(ServiceManager.getService(
BatteryStats.SERVICE_NAME)),
mInjector.createSuspendBlocker(mService, "testBlocker"),
+ null,
null);
}
}
diff --git a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
index 592eea1cd55a..6b95cfc934ac 100644
--- a/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/PowerManagerServiceTest.java
@@ -211,7 +211,8 @@ public class PowerManagerServiceTest {
mService = new PowerManagerService(mContextSpy, new Injector() {
@Override
Notifier createNotifier(Looper looper, Context context, IBatteryStats batteryStats,
- SuspendBlocker suspendBlocker, WindowManagerPolicy policy) {
+ SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
+ FaceDownDetector faceDownDetector) {
return mNotifierMock;
}
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
index 55748366c1ba..5f86d282406a 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorServiceTest.java
@@ -287,8 +287,7 @@ public class TimeDetectorServiceTest {
}
private static ExternalTimeSuggestion createExternalTimeSuggestion() {
- TimestampedValue<Long> timeValue = new TimestampedValue<>(100L, 1_000_000L);
- return new ExternalTimeSuggestion(timeValue);
+ return new ExternalTimeSuggestion(100L, 1_000_000L);
}
private static class StubbedTimeDetectorStrategy implements TimeDetectorStrategy {
diff --git a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
index daa1b25de22f..f7a498bc9d73 100644
--- a/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/timedetector/TimeDetectorStrategyImplTest.java
@@ -1483,11 +1483,8 @@ public class TimeDetectorStrategyImplTest {
* reference time.
*/
ExternalTimeSuggestion generateExternalTimeSuggestion(Instant suggestedTime) {
- TimestampedValue<Long> utcTime =
- new TimestampedValue<>(
- mFakeEnvironment.peekElapsedRealtimeMillis(),
+ return new ExternalTimeSuggestion(mFakeEnvironment.peekElapsedRealtimeMillis(),
suggestedTime.toEpochMilli());
- return new ExternalTimeSuggestion(utcTime);
}
/**
diff --git a/services/tests/servicestests/src/com/android/server/utils/WatcherTest.java b/services/tests/servicestests/src/com/android/server/utils/WatcherTest.java
index b40d59c14b8d..57e95d714593 100644
--- a/services/tests/servicestests/src/com/android/server/utils/WatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/utils/WatcherTest.java
@@ -22,6 +22,7 @@ import static org.junit.Assert.fail;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.LongSparseArray;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
@@ -619,6 +620,129 @@ public class WatcherTest {
}
@Test
+ public void testWatchedLongSparseArray() {
+ final String name = "WatchedLongSparseArray";
+ WatchableTester tester;
+
+ // Create a few leaves
+ Leaf leafA = new Leaf();
+ Leaf leafB = new Leaf();
+ Leaf leafC = new Leaf();
+ Leaf leafD = new Leaf();
+
+ // Test WatchedLongSparseArray
+ WatchedLongSparseArray<Leaf> array = new WatchedLongSparseArray<>();
+ array.put(INDEX_A, leafA);
+ array.put(INDEX_B, leafB);
+ tester = new WatchableTester(array, name);
+ tester.verify(0, "Initial array - no registration");
+ leafA.tick();
+ tester.verify(0, "Updates with no registration");
+ tester.register();
+ tester.verify(0, "Updates with no registration");
+ leafA.tick();
+ tester.verify(1, "Updates with registration");
+ leafB.tick();
+ tester.verify(2, "Updates with registration");
+ array.remove(INDEX_B);
+ tester.verify(3, "Removed b");
+ leafB.tick();
+ tester.verify(3, "Updates with b not watched");
+ array.put(INDEX_B, leafB);
+ array.put(INDEX_C, leafB);
+ tester.verify(5, "Added b twice");
+ leafB.tick();
+ tester.verify(6, "Changed b - single notification");
+ array.remove(INDEX_C);
+ tester.verify(7, "Removed first b");
+ leafB.tick();
+ tester.verify(8, "Changed b - single notification");
+ array.remove(INDEX_B);
+ tester.verify(9, "Removed second b");
+ leafB.tick();
+ tester.verify(9, "Updated leafB - no change");
+ array.clear();
+ tester.verify(10, "Cleared array");
+ leafB.tick();
+ tester.verify(10, "Change to b not in array");
+
+ // Special methods
+ array.put(INDEX_A, leafA);
+ array.put(INDEX_B, leafB);
+ array.put(INDEX_C, leafC);
+ tester.verify(13, "Added c");
+ leafC.tick();
+ tester.verify(14, "Ticked c");
+ array.setValueAt(array.indexOfKey(INDEX_C), leafD);
+ tester.verify(15, "Replaced c with d");
+ leafC.tick();
+ tester.verify(15, "Ticked c (c not registered)");
+ leafD.tick();
+ tester.verify(16, "Ticked d and c (c not registered)");
+ array.append(INDEX_D, leafC);
+ tester.verify(17, "Append c");
+ leafC.tick();
+ leafD.tick();
+ tester.verify(19, "Ticked d and c");
+ assertEquals("Verify four elements", 4, array.size());
+ // Figure out which elements are at which indices.
+ Leaf[] x = new Leaf[4];
+ for (int i = 0; i < 4; i++) {
+ x[i] = array.valueAt(i);
+ }
+ array.removeAt(1);
+ tester.verify(20, "Removed one element");
+ x[1].tick();
+ tester.verify(20, "Ticked one removed element");
+ x[2].tick();
+ tester.verify(21, "Ticked one remaining element");
+
+ // Snapshot
+ {
+ final WatchedLongSparseArray<Leaf> arraySnap = array.snapshot();
+ tester.verify(21, "Generate snapshot (no changes)");
+ // Verify that the snapshot is a proper copy of the source.
+ assertEquals(name + " snap same size",
+ array.size(), arraySnap.size());
+ for (int i = 0; i < array.size(); i++) {
+ for (int j = 0; j < arraySnap.size(); j++) {
+ assertTrue(name + " elements differ",
+ array.valueAt(i) != arraySnap.valueAt(j));
+ }
+ assertTrue(name + " element copy",
+ array.valueAt(i).equals(arraySnap.valueAt(i)));
+ }
+ leafD.tick();
+ tester.verify(22, "Tick after snapshot");
+ // Verify that the array snapshot is sealed
+ verifySealed(name, ()->arraySnap.put(INDEX_A, leafB));
+ assertTrue(!array.isSealed());
+ assertTrue(arraySnap.isSealed());
+ }
+ // Recreate the snapshot since the test corrupted it.
+ {
+ final WatchedLongSparseArray<Leaf> arraySnap = array.snapshot();
+ // Verify that elements are also snapshots
+ final Leaf arraySnapElement = arraySnap.valueAt(0);
+ verifySealed("ArraySnapshotElement", ()->arraySnapElement.tick());
+ }
+ // Verify copy-in/out
+ {
+ final String msg = name + " copy-in/out";
+ LongSparseArray<Leaf> base = new LongSparseArray<>();
+ array.copyTo(base);
+ WatchedLongSparseArray<Leaf> copy = new WatchedLongSparseArray<>();
+ copy.copyFrom(base);
+ final int end = array.size();
+ assertTrue(msg + " size mismatch " + end + " " + copy.size(), end == copy.size());
+ for (int i = 0; i < end; i++) {
+ final long key = array.keyAt(i);
+ assertTrue(msg, array.get(i) == copy.get(i));
+ }
+ }
+ }
+
+ @Test
public void testWatchedSparseBooleanArray() {
final String name = "WatchedSparseBooleanArray";
WatchableTester tester;
@@ -733,4 +857,43 @@ public class WatcherTest {
}
}
}
+
+ @Test
+ public void testNestedArrays() {
+ final String name = "NestedArrays";
+ WatchableTester tester;
+
+ // Create a few leaves
+ Leaf leafA = new Leaf();
+ Leaf leafB = new Leaf();
+ Leaf leafC = new Leaf();
+ Leaf leafD = new Leaf();
+
+ // Test nested arrays.
+ WatchedLongSparseArray<Leaf> lsaA = new WatchedLongSparseArray<>();
+ lsaA.put(2, leafA);
+ WatchedLongSparseArray<Leaf> lsaB = new WatchedLongSparseArray<>();
+ lsaB.put(4, leafB);
+ WatchedLongSparseArray<Leaf> lsaC = new WatchedLongSparseArray<>();
+ lsaC.put(6, leafC);
+
+ WatchedArrayMap<String, WatchedLongSparseArray<Leaf>> array =
+ new WatchedArrayMap<>();
+ array.put("A", lsaA);
+ array.put("B", lsaB);
+
+ // Test WatchedSparseIntArray
+ tester = new WatchableTester(array, name);
+ tester.verify(0, "Initial array - no registration");
+ tester.register();
+ tester.verify(0, "Initial array - post registration");
+ leafA.tick();
+ tester.verify(1, "tick grand-leaf");
+ lsaA.put(2, leafD);
+ tester.verify(2, "replace leafA");
+ leafA.tick();
+ tester.verify(2, "tick unregistered leafA");
+ leafD.tick();
+ tester.verify(3, "tick leafD");
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index b1ea4a58d0f1..5a0466afa85b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -130,7 +130,7 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
// insets state with the global one.
final InsetsState insetsState =
win.getDisplayContent().getInsetsStateController().getRawInsetsState();
- win.mAboveInsetsState = insetsState;
+ win.mAboveInsetsState.set(insetsState);
}
public void setRotation(int rotation, boolean includingWindows) {
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
index 2163661b7506..47cf53b621d3 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -18,6 +18,7 @@ package com.android.server.wm;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
+import static android.view.RoundedCorners.NO_ROUNDED_CORNERS;
import static android.view.Surface.ROTATION_0;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
@@ -37,6 +38,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_BOTTOM;
import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_RIGHT;
+import static com.android.server.wm.utils.WmDisplayCutout.NO_CUTOUT;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -300,9 +302,9 @@ public class DisplayPolicyTests extends WindowTestsBase {
displayPolicy.addWindowLw(mNavBarWindow, mNavBarWindow.mAttrs);
mNavBarWindow.getControllableInsetProvider().setServerVisible(true);
final InsetsState state = mDisplayContent.getInsetsStateController().getRawInsetsState();
- mImeWindow.mAboveInsetsState = state;
+ mImeWindow.mAboveInsetsState.set(state);
mDisplayContent.mDisplayFrames = new DisplayFrames(mDisplayContent.getDisplayId(),
- state, displayInfo, null /* displayCutout */, null /* roundedCorners*/);
+ state, displayInfo, NO_CUTOUT, NO_ROUNDED_CORNERS);
mDisplayContent.setInputMethodWindowLocked(mImeWindow);
mImeWindow.mAttrs.setFitInsetsSides(Side.all() & ~Side.BOTTOM);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
index 20775e84fd8f..683ed889d283 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
@@ -117,7 +117,7 @@ public class DisplayPolicyTestsBase extends WindowTestsBase {
static Pair<DisplayInfo, WmDisplayCutout> displayInfoAndCutoutForRotation(int rotation,
boolean withDisplayCutout, boolean isLongEdgeCutout) {
final DisplayInfo info = new DisplayInfo();
- WmDisplayCutout cutout = null;
+ WmDisplayCutout cutout = WmDisplayCutout.NO_CUTOUT;
final boolean flippedDimensions = rotation == ROTATION_90 || rotation == ROTATION_270;
info.logicalWidth = flippedDimensions ? DISPLAY_HEIGHT : DISPLAY_WIDTH;
diff --git a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
index ee293fcf70e6..be036034542e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InsetsStateControllerTest.java
@@ -32,13 +32,14 @@ import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.wm.DisplayContent.IME_TARGET_INPUT;
+import static com.android.server.wm.WindowContainer.POSITION_TOP;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.atLeast;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -208,7 +209,7 @@ public class InsetsStateControllerTest extends WindowTestsBase {
app.mAboveInsetsState.getSource(ITYPE_IME).setFrame(mImeWindow.getFrame());
// Make sure app got notified.
- verify(app, atLeast(1)).notifyInsetsChanged();
+ verify(app, atLeastOnce()).notifyInsetsChanged();
// app will get visible IME insets while below IME.
assertTrue(getController().getInsetsForWindow(app).getSource(ITYPE_IME).isVisible());
@@ -336,6 +337,92 @@ public class InsetsStateControllerTest extends WindowTestsBase {
assertFalse(app.getInsetsState().getSource(ITYPE_STATUS_BAR).isVisible());
}
+ @Test
+ public void testUpdateAboveInsetsState_provideInsets() {
+ final WindowState app = createTestWindow("app");
+ final WindowState statusBar = createTestWindow("statusBar");
+ final WindowState navBar = createTestWindow("navBar");
+
+ getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null);
+
+ assertNull(app.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
+ assertNull(statusBar.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
+ assertNull(navBar.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
+
+ getController().updateAboveInsetsState(statusBar, true /* notifyInsetsChange */);
+
+ assertNotNull(app.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
+ assertNull(statusBar.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
+ assertNull(navBar.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
+
+ verify(app, atLeastOnce()).notifyInsetsChanged();
+ }
+
+ @Test
+ public void testUpdateAboveInsetsState_receiveInsets() {
+ final WindowState app = createTestWindow("app");
+ final WindowState statusBar = createTestWindow("statusBar");
+ final WindowState navBar = createTestWindow("navBar");
+
+ getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null);
+ getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindow(navBar, null, null);
+
+ assertNull(app.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
+ assertNull(app.mAboveInsetsState.peekSource(ITYPE_NAVIGATION_BAR));
+
+ getController().updateAboveInsetsState(app, true /* notifyInsetsChange */);
+
+ assertNotNull(app.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
+ assertNotNull(app.mAboveInsetsState.peekSource(ITYPE_NAVIGATION_BAR));
+
+ verify(app, atLeastOnce()).notifyInsetsChanged();
+ }
+
+ @Test
+ public void testUpdateAboveInsetsState_zOrderChanged() {
+ final WindowState ime = createTestWindow("ime");
+ final WindowState app = createTestWindow("app");
+ final WindowState statusBar = createTestWindow("statusBar");
+ final WindowState navBar = createTestWindow("navBar");
+
+ getController().getSourceProvider(ITYPE_IME).setWindow(ime, null, null);
+ getController().getSourceProvider(ITYPE_IME).setClientVisible(true);
+ getController().getSourceProvider(ITYPE_STATUS_BAR).setWindow(statusBar, null, null);
+ getController().getSourceProvider(ITYPE_NAVIGATION_BAR).setWindow(navBar, null, null);
+ getController().updateAboveInsetsState(ime, false /* notifyInsetsChange */);
+ getController().updateAboveInsetsState(statusBar, false /* notifyInsetsChange */);
+ getController().updateAboveInsetsState(navBar, false /* notifyInsetsChange */);
+
+ // ime is below others.
+ assertNull(app.mAboveInsetsState.peekSource(ITYPE_IME));
+ assertNull(statusBar.mAboveInsetsState.peekSource(ITYPE_IME));
+ assertNull(navBar.mAboveInsetsState.peekSource(ITYPE_IME));
+ assertNotNull(ime.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
+ assertNotNull(ime.mAboveInsetsState.peekSource(ITYPE_NAVIGATION_BAR));
+
+ ime.getParent().positionChildAt(POSITION_TOP, ime, true /* includingParents */);
+ getController().updateAboveInsetsState(ime, true /* notifyInsetsChange */);
+
+ // ime is above others.
+ assertNotNull(app.mAboveInsetsState.peekSource(ITYPE_IME));
+ assertNotNull(statusBar.mAboveInsetsState.peekSource(ITYPE_IME));
+ assertNotNull(navBar.mAboveInsetsState.peekSource(ITYPE_IME));
+ assertNull(ime.mAboveInsetsState.peekSource(ITYPE_STATUS_BAR));
+ assertNull(ime.mAboveInsetsState.peekSource(ITYPE_NAVIGATION_BAR));
+
+ verify(ime, atLeastOnce()).notifyInsetsChanged();
+ verify(app, atLeastOnce()).notifyInsetsChanged();
+ verify(statusBar, atLeastOnce()).notifyInsetsChanged();
+ verify(navBar, atLeastOnce()).notifyInsetsChanged();
+ }
+
+ private WindowState createTestWindow(String name) {
+ final WindowState win = createWindow(null, TYPE_APPLICATION, name);
+ win.setHasSurface(true);
+ spyOn(win);
+ return win;
+ }
+
private InsetsStateController getController() {
return mDisplayContent.getInsetsStateController();
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index d545c657614c..f64f4283b66a 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -11293,21 +11293,16 @@ public class TelephonyManager {
*
* <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
* or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges})
- * Additionally, depending on the level of location permissions the caller holds (i.e. no
- * location permissions, {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}, or
- * {@link android.Manifest.permission#ACCESS_FINE_LOCATION}), location-sensitive fields will
- * be cleared from the return value.
- *
- * <p>Note also that if the caller holds any sort of location permission, a usage event for the
- * {@link android.app.AppOpsManager#OPSTR_FINE_LOCATION} or
- * {@link android.app.AppOpsManager#OPSTR_FINE_LOCATION}
- * will be logged against the caller when calling this method.
+ * and {@link android.Manifest.permission#ACCESS_COARSE_LOCATION}.
*
* May return {@code null} when the subscription is inactive or when there was an error
* communicating with the phone process.
*/
@SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
- @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
+ @RequiresPermission(allOf = {
+ Manifest.permission.READ_PHONE_STATE,
+ Manifest.permission.ACCESS_COARSE_LOCATION
+ })
public @Nullable ServiceState getServiceState() {
return getServiceStateForSubscriber(getSubId());
}
diff --git a/telephony/java/android/telephony/ims/ImsCallProfile.java b/telephony/java/android/telephony/ims/ImsCallProfile.java
index a9dae898fc9f..9bb4db8edf79 100644
--- a/telephony/java/android/telephony/ims/ImsCallProfile.java
+++ b/telephony/java/android/telephony/ims/ImsCallProfile.java
@@ -282,6 +282,15 @@ public final class ImsCallProfile implements Parcelable {
public static final String EXTRA_PICTURE_URL = "android.telephony.ims.extra.PICTURE_URL";
/**
+ * Boolean extra indicating whether the call is a business call.
+ *
+ * This extra will be set to {@code true} if and only if the SIP INVITE headers contain the
+ * "Organization" header.
+ */
+ public static final String EXTRA_IS_BUSINESS_CALL =
+ "android.telephony.ims.extra.IS_BUSINESS_CALL";
+
+ /**
* Values for EXTRA_OIR / EXTRA_CNAP
*/
/**
@@ -791,7 +800,9 @@ public final class ImsCallProfile implements Parcelable {
+ ", emergencyCallTesting=" + mEmergencyCallTesting
+ ", hasKnownUserIntentEmergency=" + mHasKnownUserIntentEmergency
+ ", mRestrictCause=" + mRestrictCause
- + ", mCallerNumberVerstat= " + mCallerNumberVerificationStatus + " }";
+ + ", mCallerNumberVerstat= " + mCallerNumberVerificationStatus
+ + ", mAcceptedRtpHeaderExtensions= " + mAcceptedRtpHeaderExtensionTypes
+ + " }";
}
@Override
diff --git a/telephony/java/android/telephony/ims/RtpHeaderExtension.java b/telephony/java/android/telephony/ims/RtpHeaderExtension.java
index f9ab7016facb..8815cefae241 100644
--- a/telephony/java/android/telephony/ims/RtpHeaderExtension.java
+++ b/telephony/java/android/telephony/ims/RtpHeaderExtension.java
@@ -134,4 +134,19 @@ public final class RtpHeaderExtension implements Parcelable {
result = 31 * result + Arrays.hashCode(mExtensionData);
return result;
}
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("RtpHeaderExtension{mLocalIdentifier=");
+ sb.append(mLocalIdentifier);
+ sb.append(", mData=");
+ for (byte b : mExtensionData) {
+ sb.append(Integer.toBinaryString(b));
+ sb.append("b_");
+ }
+ sb.append("}");
+
+ return sb.toString();
+ }
}
diff --git a/telephony/java/android/telephony/ims/RtpHeaderExtensionType.java b/telephony/java/android/telephony/ims/RtpHeaderExtensionType.java
index e1d39c217395..af4e23476331 100644
--- a/telephony/java/android/telephony/ims/RtpHeaderExtensionType.java
+++ b/telephony/java/android/telephony/ims/RtpHeaderExtensionType.java
@@ -133,4 +133,16 @@ public final class RtpHeaderExtensionType implements Parcelable {
public int hashCode() {
return Objects.hash(mLocalIdentifier, mUri);
}
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("RtpHeaderExtensionType{mLocalIdentifier=");
+ sb.append(mLocalIdentifier);
+ sb.append(", mUri=");
+ sb.append(mUri);
+ sb.append("}");
+
+ return sb.toString();
+ }
}
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 1d049530ba77..5c255243f52b 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -2340,6 +2340,11 @@ interface ITelephony {
void sendDeviceToDeviceMessage(int message, int value);
/**
+ * Sets the specified transport active; only for use through shell.
+ */
+ void setActiveDeviceToDeviceTransport(String transport);
+
+ /**
* Gets the config of RCS VoLTE single registration enabled for the carrier/subscription.
*/
boolean getCarrierSingleRegistrationEnabled(int subId);
diff --git a/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java b/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java
index ab3572ba2173..d96005b8a71a 100644
--- a/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java
+++ b/tests/ApkVerityTest/src/com/android/apkverity/ApkVerityTest.java
@@ -95,10 +95,13 @@ public class ApkVerityTest extends BaseHostJUnit4Test {
new AddFsVerityCertRule(this, CERT_PATH);
private ITestDevice mDevice;
+ private boolean mDmRequireFsVerity;
@Before
public void setUp() throws DeviceNotAvailableException {
mDevice = getDevice();
+ mDmRequireFsVerity = "true".equals(
+ mDevice.getProperty("pm.dexopt.dm.require_fsverity"));
uninstallPackage(TARGET_PACKAGE);
}
@@ -124,7 +127,7 @@ public class ApkVerityTest extends BaseHostJUnit4Test {
verifyInstalledFiles(
INSTALLED_BASE_APK,
INSTALLED_BASE_APK_FSV_SIG);
- verifyInstalledFilesHaveFsverity();
+ verifyInstalledFilesHaveFsverity(INSTALLED_BASE_APK);
}
@Test
@@ -151,7 +154,9 @@ public class ApkVerityTest extends BaseHostJUnit4Test {
INSTALLED_BASE_APK_FSV_SIG,
INSTALLED_SPLIT_APK,
INSTALLED_SPLIT_APK_FSV_SIG);
- verifyInstalledFilesHaveFsverity();
+ verifyInstalledFilesHaveFsverity(
+ INSTALLED_BASE_APK,
+ INSTALLED_SPLIT_APK);
}
@Test
@@ -167,7 +172,9 @@ public class ApkVerityTest extends BaseHostJUnit4Test {
INSTALLED_BASE_APK_FSV_SIG,
INSTALLED_BASE_DM,
INSTALLED_BASE_DM_FSV_SIG);
- verifyInstalledFilesHaveFsverity();
+ verifyInstalledFilesHaveFsverity(
+ INSTALLED_BASE_APK,
+ INSTALLED_BASE_DM);
}
@Test
@@ -189,7 +196,11 @@ public class ApkVerityTest extends BaseHostJUnit4Test {
INSTALLED_SPLIT_APK_FSV_SIG,
INSTALLED_SPLIT_DM,
INSTALLED_SPLIT_DM_FSV_SIG);
- verifyInstalledFilesHaveFsverity();
+ verifyInstalledFilesHaveFsverity(
+ INSTALLED_BASE_APK,
+ INSTALLED_BASE_DM,
+ INSTALLED_SPLIT_APK,
+ INSTALLED_SPLIT_DM);
}
@Test
@@ -213,7 +224,9 @@ public class ApkVerityTest extends BaseHostJUnit4Test {
INSTALLED_BASE_APK_FSV_SIG,
INSTALLED_SPLIT_APK,
INSTALLED_SPLIT_APK_FSV_SIG);
- verifyInstalledFilesHaveFsverity();
+ verifyInstalledFilesHaveFsverity(
+ INSTALLED_BASE_APK,
+ INSTALLED_SPLIT_APK);
}
@Test
@@ -250,39 +263,92 @@ public class ApkVerityTest extends BaseHostJUnit4Test {
INSTALLED_BASE_APK,
INSTALLED_SPLIT_APK,
INSTALLED_SPLIT_APK_FSV_SIG);
-
}
@Test
- public void testInstallOnlyBaseHasFsvSig()
+ public void testInstallOnlyDmHasFsvSig()
throws DeviceNotAvailableException, FileNotFoundException {
new InstallMultiple()
- .addFileAndSignature(BASE_APK)
+ .addFile(BASE_APK)
+ .addFileAndSignature(BASE_APK_DM)
+ .addFile(SPLIT_APK)
+ .addFileAndSignature(SPLIT_APK_DM)
+ .run();
+ verifyInstalledFiles(
+ INSTALLED_BASE_APK,
+ INSTALLED_BASE_DM,
+ INSTALLED_BASE_DM_FSV_SIG,
+ INSTALLED_SPLIT_APK,
+ INSTALLED_SPLIT_DM,
+ INSTALLED_SPLIT_DM_FSV_SIG);
+ verifyInstalledFilesHaveFsverity(
+ INSTALLED_BASE_DM,
+ INSTALLED_SPLIT_DM);
+ }
+
+ @Test
+ public void testInstallDmWithoutFsvSig_Base()
+ throws DeviceNotAvailableException, FileNotFoundException {
+ InstallMultiple installer = new InstallMultiple()
+ .addFile(BASE_APK)
.addFile(BASE_APK_DM)
.addFile(SPLIT_APK)
- .addFile(SPLIT_APK_DM)
- .runExpectingFailure();
+ .addFileAndSignature(SPLIT_APK_DM);
+ if (mDmRequireFsVerity) {
+ installer.runExpectingFailure();
+ } else {
+ installer.run();
+ verifyInstalledFiles(
+ INSTALLED_BASE_APK,
+ INSTALLED_BASE_DM,
+ INSTALLED_SPLIT_APK,
+ INSTALLED_SPLIT_DM,
+ INSTALLED_SPLIT_DM_FSV_SIG);
+ verifyInstalledFilesHaveFsverity(INSTALLED_SPLIT_DM);
+ }
}
@Test
- public void testInstallOnlyDmHasFsvSig()
+ public void testInstallDmWithoutFsvSig_Split()
throws DeviceNotAvailableException, FileNotFoundException {
- new InstallMultiple()
+ InstallMultiple installer = new InstallMultiple()
.addFile(BASE_APK)
.addFileAndSignature(BASE_APK_DM)
.addFile(SPLIT_APK)
- .addFile(SPLIT_APK_DM)
+ .addFile(SPLIT_APK_DM);
+ if (mDmRequireFsVerity) {
+ installer.runExpectingFailure();
+ } else {
+ installer.run();
+ verifyInstalledFiles(
+ INSTALLED_BASE_APK,
+ INSTALLED_BASE_DM,
+ INSTALLED_BASE_DM_FSV_SIG,
+ INSTALLED_SPLIT_APK,
+ INSTALLED_SPLIT_DM);
+ verifyInstalledFilesHaveFsverity(INSTALLED_BASE_DM);
+ }
+ }
+
+ @Test
+ public void testInstallSomeApkIsMissingFsvSig_Base()
+ throws DeviceNotAvailableException, FileNotFoundException {
+ new InstallMultiple()
+ .addFileAndSignature(BASE_APK)
+ .addFileAndSignature(BASE_APK_DM)
+ .addFile(SPLIT_APK)
+ .addFileAndSignature(SPLIT_APK_DM)
.runExpectingFailure();
}
@Test
- public void testInstallOnlySplitHasFsvSig()
+ public void testInstallSomeApkIsMissingFsvSig_Split()
throws DeviceNotAvailableException, FileNotFoundException {
new InstallMultiple()
.addFile(BASE_APK)
- .addFile(BASE_APK_DM)
+ .addFileAndSignature(BASE_APK_DM)
.addFileAndSignature(SPLIT_APK)
- .addFile(SPLIT_APK_DM)
+ .addFileAndSignature(SPLIT_APK_DM)
.runExpectingFailure();
}
@@ -383,37 +449,36 @@ public class ApkVerityTest extends BaseHostJUnit4Test {
}
}
- private void verifyInstalledFilesHaveFsverity() throws DeviceNotAvailableException {
+ private void verifyInstalledFilesHaveFsverity(String... filenames)
+ throws DeviceNotAvailableException {
// Verify that all files are protected by fs-verity
String apkPath = getApkPath(TARGET_PACKAGE);
String appDir = apkPath.substring(0, apkPath.lastIndexOf("/"));
long kTargetOffset = 0;
- for (String basename : expectRemoteCommandToSucceed("ls " + appDir).split("\n")) {
- if (basename.endsWith(".apk") || basename.endsWith(".dm")) {
- String path = appDir + "/" + basename;
- damageFileAgainstBlockDevice(path, kTargetOffset);
-
- // Retry is sometimes needed to pass the test. Package manager may have FD leaks
- // (see b/122744005 as example) that prevents the file in question to be evicted
- // from filesystem cache. Forcing GC workarounds the problem.
- int retry = 5;
- for (; retry > 0; retry--) {
- BlockDeviceWriter.dropCaches(mDevice);
- if (!BlockDeviceWriter.canReadByte(mDevice, path, kTargetOffset)) {
- break;
- }
- try {
- CLog.d("lsof: " + expectRemoteCommandToSucceed("lsof " + apkPath));
- Thread.sleep(1000);
- String pid = expectRemoteCommandToSucceed("pidof system_server");
- mDevice.executeShellV2Command("kill -10 " + pid); // force GC
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- return;
- }
+ for (String basename : filenames) {
+ String path = appDir + "/" + basename;
+ damageFileAgainstBlockDevice(path, kTargetOffset);
+
+ // Retry is sometimes needed to pass the test. Package manager may have FD leaks
+ // (see b/122744005 as example) that prevents the file in question to be evicted
+ // from filesystem cache. Forcing GC workarounds the problem.
+ int retry = 5;
+ for (; retry > 0; retry--) {
+ BlockDeviceWriter.dropCaches(mDevice);
+ if (!BlockDeviceWriter.canReadByte(mDevice, path, kTargetOffset)) {
+ break;
+ }
+ try {
+ CLog.d("lsof: " + expectRemoteCommandToSucceed("lsof " + apkPath));
+ Thread.sleep(1000);
+ String pid = expectRemoteCommandToSucceed("pidof system_server");
+ mDevice.executeShellV2Command("kill -10 " + pid); // force GC
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ return;
}
- assertTrue("Read from " + path + " should fail", retry > 0);
}
+ assertTrue("Read from " + path + " should fail", retry > 0);
}
}
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
index 2fe49af26cc1..52549a23c9bb 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/ime/ReOpenImeWindowTest.kt
@@ -83,7 +83,7 @@ class ReOpenImeWindowTest(
}
}
transitions {
- device.reopenAppFromOverview()
+ device.reopenAppFromOverview(wmHelper)
wmHelper.waitImeWindowShown()
}
teardown {
diff --git a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
index 84cc8e3ab058..5fb050927dad 100644
--- a/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
+++ b/tests/FlickerTests/src/com/android/server/wm/flicker/launch/OpenAppFromOverviewTest.kt
@@ -81,7 +81,7 @@ class OpenAppFromOverviewTest(
}
}
transitions {
- device.reopenAppFromOverview()
+ device.reopenAppFromOverview(wmHelper)
wmHelper.waitForFullScreenApp(testApp.component)
}
teardown {
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index c6c67feeed72..62ccb1a0b9db 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -400,6 +400,15 @@
</intent-filter>
</activity>
+ <activity android:name="StretchySurfaceViewActivity"
+ android:label="SurfaceView/Stretchy Movement"
+ android:exported="true">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN"/>
+ <category android:name="com.android.test.hwui.TEST"/>
+ </intent-filter>
+ </activity>
+
<activity android:name="GetBitmapSurfaceViewActivity"
android:label="SurfaceView/GetBitmap with Camera source"
android:exported="true">
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java
index 818d899413de..65d7363ad628 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/PositionListenerActivity.java
@@ -19,8 +19,13 @@ package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
+import android.graphics.PointF;
+import android.graphics.RecordingCanvas;
+import android.graphics.Rect;
+import android.graphics.RectF;
import android.graphics.RenderNode;
import android.os.Bundle;
+import android.view.MotionEvent;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.ScrollView;
@@ -38,7 +43,46 @@ public class PositionListenerActivity extends Activity {
ProgressBar spinner = new ProgressBar(this, null, android.R.attr.progressBarStyleLarge);
layout.addView(spinner);
- ScrollView scrollingThing = new ScrollView(this);
+ ScrollView scrollingThing = new ScrollView(this) {
+ int setting = 0;
+ PointF opts[] = new PointF[] {
+ new PointF(0, 0),
+ new PointF(0, -1f),
+ new PointF(1f, 0),
+ new PointF(0, 1f),
+ new PointF(-1f, 0),
+ new PointF(-1f, 1f),
+ };
+ {
+ setWillNotDraw(false);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ if (ev.getActionMasked() == MotionEvent.ACTION_UP) {
+ setting = (setting + 1) % opts.length;
+ invalidate();
+ }
+ return super.onTouchEvent(ev);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+ RenderNode node = ((RecordingCanvas) canvas).mNode;
+ PointF dir = opts[setting];
+ float maxStretchAmount = 100f;
+ // Although we could do this in a single call, the real one won't be - so mimic that
+ if (dir.x != 0f) {
+ node.stretch(0f, 0f, (float) getWidth(), (float) getHeight(),
+ dir.x, 0f, maxStretchAmount);
+ }
+ if (dir.y != 0f) {
+ node.stretch(0f, 0f, (float) getWidth(), (float) getHeight(),
+ 0f, dir.y, maxStretchAmount);
+ }
+ }
+ };
scrollingThing.addView(new MyPositionReporter(this));
layout.addView(scrollingThing);
@@ -49,6 +93,11 @@ public class PositionListenerActivity extends Activity {
RenderNode mNode;
int mCurrentCount = 0;
int mTranslateY = 0;
+ Rect mPosition = new Rect();
+ RectF mStretchArea = new RectF();
+ float mStretchX = 0.0f;
+ float mStretchY = 0.0f;
+ float mStretchMax = 0.0f;
MyPositionReporter(Context c) {
super(c);
@@ -78,18 +127,36 @@ public class PositionListenerActivity extends Activity {
canvas.drawRenderNode(mNode);
}
+ void updateText() {
+ setText(String.format("%d: Position %s, stretch area %s, vec %f,%f, amount %f",
+ mCurrentCount, mPosition.toShortString(), mStretchArea.toShortString(),
+ mStretchX, mStretchY, mStretchMax));
+ }
+
@Override
public void positionChanged(long frameNumber, int left, int top, int right, int bottom) {
- post(() -> {
+ getHandler().postAtFrontOfQueue(() -> {
mCurrentCount++;
- setText(String.format("%d: Position [%d, %d, %d, %d]", mCurrentCount,
- left, top, right, bottom));
+ mPosition.set(left, top, right, bottom);
+ updateText();
+ });
+ }
+
+ @Override
+ public void applyStretch(long frameNumber, float left, float top, float right, float bottom,
+ float vecX, float vecY, float maxStretch) {
+ getHandler().postAtFrontOfQueue(() -> {
+ mStretchArea.set(left, top, right, bottom);
+ mStretchX = vecX;
+ mStretchY = vecY;
+ mStretchMax = maxStretch;
+ updateText();
});
}
@Override
public void positionLost(long frameNumber) {
- post(() -> {
+ getHandler().postAtFrontOfQueue(() -> {
mCurrentCount++;
setText(mCurrentCount + " No position");
});
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/StretchySurfaceViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/StretchySurfaceViewActivity.java
new file mode 100644
index 000000000000..d6042445c2d8
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/StretchySurfaceViewActivity.java
@@ -0,0 +1,157 @@
+/*
+ * 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.test.hwui;
+
+import android.animation.ObjectAnimator;
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.RecordingCanvas;
+import android.graphics.RenderNode;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.SurfaceHolder;
+import android.view.SurfaceHolder.Callback;
+import android.view.SurfaceView;
+import android.view.animation.LinearInterpolator;
+import android.widget.FrameLayout;
+
+public class StretchySurfaceViewActivity extends Activity implements Callback {
+ SurfaceView mSurfaceView;
+ ObjectAnimator mAnimator;
+
+ class MySurfaceView extends SurfaceView {
+ boolean mSlow;
+ boolean mScaled;
+ int mToggle = 0;
+
+ public MySurfaceView(Context context) {
+ super(context);
+ setOnClickListener(v -> {
+ mToggle = (mToggle + 1) % 4;
+ mSlow = (mToggle & 0x2) != 0;
+ mScaled = (mToggle & 0x1) != 0;
+
+ mSurfaceView.setScaleX(mScaled ? 1.6f : 1f);
+ mSurfaceView.setScaleY(mScaled ? 0.8f : 1f);
+
+ setTitle("Slow=" + mSlow + ", scaled=" + mScaled);
+ invalidate();
+ });
+ setWillNotDraw(false);
+ }
+
+ @Override
+ public void draw(Canvas canvas) {
+ super.draw(canvas);
+ if (mSlow) {
+ try {
+ Thread.sleep(16);
+ } catch (InterruptedException e) {}
+ }
+ }
+
+ public void setMyTranslationY(float ty) {
+ setTranslationY(ty);
+ if (mSlow) {
+ invalidate();
+ }
+ }
+
+ public float getMyTranslationY() {
+ return getTranslationY();
+ }
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ FrameLayout content = new FrameLayout(this) {
+ {
+ setWillNotDraw(false);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ Paint paint = new Paint();
+ paint.setAntiAlias(true);
+ paint.setColor(Color.RED);
+ paint.setStyle(Paint.Style.STROKE);
+ paint.setStrokeWidth(10f);
+ canvas.drawLine(0f, 0f, getWidth(), getHeight(), paint);
+ super.onDraw(canvas);
+
+ RenderNode node = ((RecordingCanvas) canvas).mNode;
+ node.stretch(0f, 0f, getWidth(), getHeight() / 2f, 0f, 1f, 400f);
+ }
+ };
+
+ mSurfaceView = new MySurfaceView(this);
+ mSurfaceView.getHolder().addCallback(this);
+
+ final float density = getResources().getDisplayMetrics().density;
+ int size = (int) (200 * density);
+
+ content.addView(mSurfaceView, new FrameLayout.LayoutParams(
+ size, size, Gravity.CENTER_HORIZONTAL | Gravity.TOP));
+ mAnimator = ObjectAnimator.ofFloat(mSurfaceView, "myTranslationY",
+ 0, size);
+ mAnimator.setRepeatMode(ObjectAnimator.REVERSE);
+ mAnimator.setRepeatCount(ObjectAnimator.INFINITE);
+ mAnimator.setDuration(1000);
+ mAnimator.setInterpolator(new LinearInterpolator());
+ setContentView(content);
+ }
+
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {
+ }
+
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ Canvas canvas = holder.lockCanvas();
+ canvas.drawColor(Color.WHITE);
+
+ Paint paint = new Paint();
+ paint.setAntiAlias(true);
+ paint.setColor(Color.GREEN);
+ paint.setStyle(Paint.Style.STROKE);
+ paint.setStrokeWidth(10f);
+ canvas.drawLine(0, 0, width, height, paint);
+
+ holder.unlockCanvasAndPost(canvas);
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mAnimator.start();
+ }
+
+ @Override
+ protected void onPause() {
+ mAnimator.pause();
+ super.onPause();
+ }
+}