summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp3
-rw-r--r--apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java4
-rw-r--r--apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java18
-rw-r--r--apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java8
-rw-r--r--apct-tests/perftests/multiuser/src/android/multiuser/BenchmarkResults.java8
-rw-r--r--api/current.txt539
-rw-r--r--api/system-current.txt84
-rw-r--r--api/test-current.txt116
-rw-r--r--cmds/bootanimation/bootanim.rc3
-rw-r--r--cmds/statsd/src/StatsService.cpp6
-rw-r--r--cmds/statsd/src/atoms.proto13
-rw-r--r--cmds/statsd/src/metrics/ValueMetricProducer.cpp203
-rw-r--r--cmds/statsd/src/metrics/ValueMetricProducer.h92
-rw-r--r--cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp1665
-rw-r--r--cmds/svc/src/com/android/commands/svc/Svc.java1
-rw-r--r--cmds/svc/src/com/android/commands/svc/SystemServerCommand.java67
-rw-r--r--config/boot-image-profile.txt4
-rw-r--r--config/hiddenapi-greylist.txt14
-rw-r--r--core/java/android/app/Activity.java23
-rw-r--r--core/java/android/app/ActivityManager.java8
-rw-r--r--core/java/android/app/ActivityThread.java10
-rw-r--r--core/java/android/app/ActivityView.java11
-rw-r--r--core/java/android/app/ApplicationPackageManager.java31
-rw-r--r--core/java/android/app/ContextImpl.java16
-rw-r--r--core/java/android/app/IActivityManager.aidl9
-rw-r--r--core/java/android/app/IApplicationThread.aidl3
-rw-r--r--core/java/android/app/Notification.java25
-rw-r--r--core/java/android/app/UiAutomationConnection.java8
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java46
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl4
-rw-r--r--core/java/android/app/timezone/RulesState.java34
-rw-r--r--core/java/android/appwidget/AppWidgetHostView.java36
-rw-r--r--core/java/android/content/AutofillOptions.aidl19
-rw-r--r--core/java/android/content/AutofillOptions.java130
-rw-r--r--core/java/android/content/ContentResolver.java2
-rw-r--r--core/java/android/content/Context.java19
-rw-r--r--core/java/android/content/ContextWrapper.java23
-rw-r--r--core/java/android/content/pm/AndroidTestBaseUpdater.java12
-rw-r--r--core/java/android/content/pm/IPackageInstaller.aidl3
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl2
-rw-r--r--core/java/android/content/pm/LauncherApps.java3
-rw-r--r--core/java/android/content/pm/OrgApacheHttpLegacyUpdater.java6
-rw-r--r--core/java/android/content/pm/PackageBackwardCompatibility.java2
-rw-r--r--core/java/android/content/pm/PackageInstaller.java71
-rw-r--r--core/java/android/content/pm/PackageManager.java56
-rw-r--r--core/java/android/content/pm/PackageParser.java11
-rw-r--r--core/java/android/content/pm/PackageSharedLibraryUpdater.java6
-rw-r--r--core/java/android/content/pm/ShortcutInfo.java2
-rw-r--r--core/java/android/content/pm/ShortcutManager.java1
-rw-r--r--core/java/android/hardware/display/BrightnessConfiguration.java18
-rw-r--r--core/java/android/hardware/display/BrightnessCorrection.java14
-rw-r--r--core/java/android/metrics/LogMaker.java2
-rw-r--r--core/java/android/metrics/MetricsReader.java2
-rw-r--r--core/java/android/net/ConnectivityManager.java6
-rw-r--r--core/java/android/net/NetworkFactory.java62
-rw-r--r--core/java/android/os/BugreportManager.java10
-rwxr-xr-xcore/java/android/os/Build.java1
-rw-r--r--core/java/android/os/GraphicsEnvironment.java13
-rw-r--r--core/java/android/os/PowerManager.java2
-rw-r--r--core/java/android/os/UserManager.java40
-rw-r--r--core/java/android/permission/IPermissionController.aidl2
-rw-r--r--core/java/android/permission/PermissionControllerManager.java102
-rw-r--r--core/java/android/permission/PermissionControllerService.java56
-rw-r--r--core/java/android/provider/CallLog.java20
-rw-r--r--core/java/android/provider/DeviceConfig.java2
-rw-r--r--core/java/android/provider/Settings.java36
-rw-r--r--core/java/android/service/autofill/FillRequest.java11
-rw-r--r--core/java/android/service/autofill/augmented/FillWindow.java11
-rw-r--r--core/java/android/text/style/DynamicDrawableSpan.java28
-rw-r--r--core/java/android/util/TimeUtils.java2
-rw-r--r--core/java/android/view/Display.java2
-rw-r--r--core/java/android/view/IWindowManager.aidl9
-rw-r--r--core/java/android/view/IWindowSession.aidl2
-rw-r--r--core/java/android/view/Surface.java4
-rw-r--r--core/java/android/view/SurfaceControl.java39
-rw-r--r--core/java/android/view/ThreadedRenderer.java2
-rw-r--r--core/java/android/view/View.java91
-rw-r--r--core/java/android/view/ViewConfiguration.java4
-rw-r--r--core/java/android/view/ViewDebug.java4
-rw-r--r--core/java/android/view/ViewPropertyAnimator.java4
-rw-r--r--core/java/android/view/ViewRootImpl.java191
-rw-r--r--core/java/android/view/accessibility/AccessibilityCache.java14
-rw-r--r--core/java/android/view/autofill/AutofillManager.java49
-rw-r--r--core/java/android/view/autofill/AutofillManagerInternal.java7
-rw-r--r--core/java/android/view/contentcapture/ChildContentCaptureSession.java2
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureEvent.java14
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureManager.java8
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureSession.java19
-rw-r--r--core/java/android/view/contentcapture/MainContentCaptureSession.java39
-rw-r--r--core/java/android/view/inspector/GeneratedInspectionCompanionProvider.java9
-rw-r--r--core/java/android/view/textclassifier/ExtrasUtils.java3
-rw-r--r--core/java/android/view/textclassifier/TextClassification.java7
-rw-r--r--core/java/android/view/textclassifier/TextClassifierImpl.java64
-rw-r--r--core/java/android/widget/Editor.java4
-rw-r--r--core/java/android/widget/Magnifier.java15
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java12
-rw-r--r--core/java/com/android/internal/app/IntentForwarderActivity.java20
-rw-r--r--core/java/com/android/internal/infra/AbstractMultiplePendingRequestsRemoteService.java4
-rw-r--r--core/java/com/android/internal/infra/AbstractRemoteService.java157
-rw-r--r--core/java/com/android/internal/infra/AbstractSinglePendingRequestRemoteService.java6
-rw-r--r--core/java/com/android/internal/os/RoSystemProperties.java14
-rw-r--r--core/java/com/android/internal/policy/BackdropFrameRenderer.java8
-rw-r--r--core/jni/android_opengl_EGL14.cpp2
-rw-r--r--core/jni/android_opengl_EGL15.cpp4
-rw-r--r--core/jni/android_opengl_EGLExt.cpp2
-rw-r--r--core/jni/android_opengl_GLES10.cpp2
-rw-r--r--core/jni/android_opengl_GLES10Ext.cpp2
-rw-r--r--core/jni/android_opengl_GLES11.cpp2
-rw-r--r--core/jni/android_opengl_GLES11Ext.cpp2
-rw-r--r--core/jni/android_opengl_GLES20.cpp2
-rw-r--r--core/jni/android_opengl_GLES30.cpp2
-rw-r--r--core/jni/android_opengl_GLES31.cpp2
-rw-r--r--core/jni/android_opengl_GLES31Ext.cpp2
-rw-r--r--core/jni/android_opengl_GLES32.cpp2
-rw-r--r--core/jni/android_os_GraphicsEnvironment.cpp9
-rw-r--r--core/jni/android_util_AssetManager.cpp7
-rw-r--r--core/jni/android_view_SurfaceControl.cpp19
-rw-r--r--core/jni/com_android_internal_os_Zygote.cpp555
-rw-r--r--core/jni/com_google_android_gles_jni_GLImpl.cpp2
-rw-r--r--core/proto/android/app/settings_enums.proto4
-rw-r--r--core/proto/android/providers/settings/global.proto3
-rw-r--r--core/proto/android/stats/style/Android.bp27
-rw-r--r--core/proto/android/stats/style/style_enums.proto34
-rw-r--r--core/res/AndroidManifest.xml5
-rw-r--r--core/res/res/values/config.xml9
-rw-r--r--core/res/res/values/public.xml2
-rw-r--r--core/res/res/values/styles_car.xml2
-rw-r--r--core/res/res/values/styles_device_defaults.xml2
-rw-r--r--core/res/res/values/symbols.xml2
-rw-r--r--core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java3
-rw-r--r--core/tests/coretests/src/android/app/timezone/RulesStateTest.java12
-rw-r--r--core/tests/coretests/src/android/content/pm/AndroidTestBaseUpdaterTest.java20
-rw-r--r--core/tests/coretests/src/android/provider/SettingsBackupTest.java3
-rw-r--r--core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java20
-rw-r--r--core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java5
-rw-r--r--core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java46
-rw-r--r--core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java11
-rw-r--r--core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java70
-rw-r--r--graphics/java/android/graphics/Bitmap.java2
-rw-r--r--graphics/java/android/graphics/HardwareRenderer.java2
-rw-r--r--graphics/java/android/graphics/ImageFormat.java40
-rw-r--r--graphics/java/android/graphics/RecordingCanvas.java2
-rw-r--r--graphics/java/android/graphics/RenderNode.java257
-rw-r--r--libs/androidfw/AssetManager2.cpp64
-rw-r--r--libs/androidfw/include/androidfw/AssetManager2.h14
-rw-r--r--location/java/android/location/GnssMeasurementCorrections.java10
-rw-r--r--location/java/android/location/GnssReflectingPlane.java2
-rw-r--r--location/java/android/location/GnssSingleSatCorrection.java30
-rw-r--r--location/tests/locationtests/src/android/location/GnssMeasurementCorrectionsTest.java111
-rw-r--r--location/tests/locationtests/src/android/location/GnssReflectingPlaneTest.java67
-rw-r--r--location/tests/locationtests/src/android/location/GnssSingleSatCorrectionsTest.java81
-rw-r--r--media/java/android/media/AudioManager.java5
-rw-r--r--media/java/android/media/AudioPlaybackCaptureConfiguration.java48
-rw-r--r--media/java/android/media/AudioRecord.java14
-rw-r--r--media/java/android/media/IAudioService.aidl3
-rw-r--r--media/java/android/media/ImageReader.java18
-rw-r--r--media/java/android/media/ImageWriter.java9
-rw-r--r--media/java/android/media/MediaCas.java54
-rw-r--r--media/java/android/media/MediaPlayer.java3
-rw-r--r--media/java/android/media/audiopolicy/AudioMix.java3
-rw-r--r--media/java/android/media/audiopolicy/AudioPolicy.java79
-rw-r--r--media/java/android/media/audiopolicy/AudioPolicyConfig.java2
-rw-r--r--media/java/android/media/session/ControllerLink.java23
-rw-r--r--media/java/android/media/session/ISessionController.aidl1
-rw-r--r--media/java/android/media/session/ISessionManager.aidl2
-rw-r--r--media/java/android/media/session/MediaController.java18
-rw-r--r--media/java/android/media/session/MediaSession.java23
-rw-r--r--media/java/android/media/session/MediaSessionManager.java7
-rw-r--r--packages/CarSystemUI/res/layout/car_navigation_bar.xml4
-rw-r--r--packages/NetworkStack/Android.bp3
-rw-r--r--packages/NetworkStack/src/android/net/metrics/DataStallDetectionStats.java209
-rw-r--r--packages/NetworkStack/src/android/net/metrics/DataStallStatsUtils.java66
-rw-r--r--packages/NetworkStack/src/android/net/util/NetworkStackUtils.java25
-rw-r--r--packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java82
-rw-r--r--packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java30
-rw-r--r--packages/OsuLogin/src/com/android/hotspot2/osu/OsuLoginActivity.java22
-rw-r--r--packages/SettingsLib/EntityHeaderWidgets/src/com/android/settingslib/widget/AppEntitiesHeaderController.java21
-rw-r--r--packages/SettingsLib/res/values-as/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-bn/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-gu/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-iw/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-kn/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-ml/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-mr/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-ne/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-or/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-pa/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-ta/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-ur/strings.xml3
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppEntitiesHeaderControllerTest.java17
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java22
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java6
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java12
-rw-r--r--packages/SystemUI/res/drawable/ic_tune_black_16dp.xml25
-rw-r--r--packages/SystemUI/res/drawable/qs_customize_tile_decoration.xml17
-rw-r--r--packages/SystemUI/res/drawable/qs_customizer_background_primary.xml2
-rw-r--r--packages/SystemUI/res/drawable/qs_customizer_toolbar.xml2
-rw-r--r--packages/SystemUI/res/layout-sw600dp/navigation_layout_rot90.xml44
-rw-r--r--packages/SystemUI/res/layout/bubble_permission_view.xml2
-rw-r--r--packages/SystemUI/res/layout/keyguard_status_bar.xml2
-rw-r--r--packages/SystemUI/res/layout/nav_bar_tuner_inflater.xml4
-rw-r--r--packages/SystemUI/res/layout/navigation_layout.xml3
-rw-r--r--packages/SystemUI/res/layout/navigation_layout_vertical.xml (renamed from packages/SystemUI/res/layout/navigation_layout_rot90.xml)3
-rw-r--r--packages/SystemUI/res/layout/qs_customize_divider.xml1
-rw-r--r--packages/SystemUI/res/layout/qs_customize_header.xml1
-rw-r--r--packages/SystemUI/res/layout/qs_customize_panel_content.xml3
-rw-r--r--packages/SystemUI/res/layout/volume_dialog.xml2
-rw-r--r--packages/SystemUI/res/values-night/colors.xml6
-rw-r--r--packages/SystemUI/res/values/colors.xml19
-rw-r--r--packages/SystemUI/res/values/config.xml12
-rw-r--r--packages/SystemUI/res/values/dimens.xml4
-rw-r--r--packages/SystemUI/res/values/strings.xml9
-rw-r--r--packages/SystemUI/res/values/styles.xml11
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/StatsLogCompat.java13
-rw-r--r--packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/Dependency.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/SwipeHelper.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java51
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java45
-rw-r--r--packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java20
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java57
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/PowerUI.java209
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinder.java52
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationRowBinder.java)22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java92
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java64
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/Events.java27
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java3
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java6
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java119
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarInflaterViewTest.java105
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java4
-rw-r--r--proto/Android.bp11
-rw-r--r--proto/src/metrics_constants/metrics_constants.proto17
-rw-r--r--proto/src/wifi.proto77
-rw-r--r--services/art-profile6
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerService.java26
-rw-r--r--services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java24
-rw-r--r--services/autofill/java/com/android/server/autofill/Session.java11
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java21
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java2
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java16
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java45
-rw-r--r--services/core/java/com/android/server/EventLogTags.logtags2
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java31
-rw-r--r--services/core/java/com/android/server/PinnerService.java15
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java6
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java38
-rw-r--r--services/core/java/com/android/server/audio/AudioService.java92
-rw-r--r--services/core/java/com/android/server/biometrics/ClientMonitor.java6
-rw-r--r--services/core/java/com/android/server/connectivity/PermissionMonitor.java194
-rw-r--r--services/core/java/com/android/server/content/ContentService.java3
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java11
-rw-r--r--services/core/java/com/android/server/gpu/GpuService.java44
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java19
-rw-r--r--services/core/java/com/android/server/infra/AbstractMasterSystemService.java3
-rw-r--r--services/core/java/com/android/server/job/controllers/StorageController.java19
-rw-r--r--services/core/java/com/android/server/location/GnssLocationProvider.java1
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java6
-rw-r--r--services/core/java/com/android/server/media/MediaSessionRecord.java11
-rw-r--r--services/core/java/com/android/server/media/MediaSessionServiceImpl.java16
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java2
-rw-r--r--services/core/java/com/android/server/notification/NotificationShellCmd.java64
-rw-r--r--services/core/java/com/android/server/notification/PreferencesHelper.java3
-rw-r--r--services/core/java/com/android/server/os/BugreportManagerServiceImpl.java4
-rw-r--r--services/core/java/com/android/server/pm/ApexManager.java74
-rw-r--r--services/core/java/com/android/server/pm/LauncherAppsService.java4
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerService.java18
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java124
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java176
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java26
-rw-r--r--services/core/java/com/android/server/pm/ShortcutService.java3
-rw-r--r--services/core/java/com/android/server/pm/StagingManager.java30
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java1
-rw-r--r--services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java20
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java54
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java2
-rw-r--r--services/core/java/com/android/server/policy/PhoneWindowManager.java103
-rw-r--r--services/core/java/com/android/server/policy/WindowManagerPolicy.java8
-rw-r--r--services/core/java/com/android/server/role/TEST_MAPPING11
-rw-r--r--services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java65
-rw-r--r--services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java4
-rw-r--r--services/core/java/com/android/server/timezone/RulesManagerService.java64
-rw-r--r--services/core/java/com/android/server/wm/ActivityStarter.java9
-rw-r--r--services/core/java/com/android/server/wm/DisplayPolicy.java10
-rw-r--r--services/core/java/com/android/server/wm/DisplayRotation.java86
-rw-r--r--services/core/java/com/android/server/wm/DisplayWindowSettings.java16
-rw-r--r--services/core/java/com/android/server/wm/ScreenRotationAnimation.java6
-rw-r--r--services/core/java/com/android/server/wm/Session.java16
-rw-r--r--services/core/java/com/android/server/wm/SurfaceFactory.java27
-rw-r--r--services/core/java/com/android/server/wm/WallpaperController.java30
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java40
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerShellCommand.java15
-rw-r--r--services/core/java/com/android/server/wm/WindowSurfacePlacer.java6
-rw-r--r--services/core/java/com/android/server/wm/WindowTraceBuffer.java5
-rw-r--r--services/core/jni/com_android_server_location_GnssLocationProvider.cpp8
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java136
-rw-r--r--services/java/com/android/server/SystemServer.java25
-rw-r--r--services/net/java/android/net/NetworkStackClient.java65
-rw-r--r--services/net/java/android/net/ip/RouterAdvertisementDaemon.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java3
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java5
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java9
-rw-r--r--services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java143
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java5
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java3
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java7
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java9
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java6
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java5
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java36
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java86
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java32
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/MockSurfaceControlBuilder.java37
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/StubTransaction.java251
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java2
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java10
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java23
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java7
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java13
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java25
-rw-r--r--telecomm/java/android/telecom/CallIdentification.java59
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java4
-rw-r--r--telephony/java/android/telephony/DisconnectCause.java2
-rw-r--r--telephony/java/android/telephony/PhoneStateListener.java24
-rw-r--r--telephony/java/android/telephony/PreciseDisconnectCause.java2
-rw-r--r--telephony/java/android/telephony/ServiceState.java11
-rw-r--r--telephony/java/android/telephony/SignalStrength.java53
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java14
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java35
-rw-r--r--telephony/java/android/telephony/ims/Rcs1To1Thread.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsEvent.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsEventQueryParams.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsEventQueryResult.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsFileTransferCreationParams.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsFileTransferPart.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsGroupThread.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsGroupThreadEvent.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsIncomingMessage.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsManager.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsMessage.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsMessageCreationParams.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsMessageQueryParams.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsMessageQueryResult.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsMessageSnippet.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsMessageStore.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsMessageStoreException.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsOutgoingMessage.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsParticipant.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsParticipantQueryParams.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsParticipantQueryResult.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsQueryContinuationToken.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsThread.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsThreadQueryParams.java2
-rw-r--r--telephony/java/android/telephony/ims/RcsThreadQueryResult.java2
-rwxr-xr-xtelephony/java/com/android/internal/telephony/ISub.aidl2
-rw-r--r--telephony/java/com/android/internal/telephony/ITelephony.aidl8
-rw-r--r--telephony/java/com/android/internal/telephony/TelephonyProperties.java7
-rw-r--r--test-mock/api/test-current.txt4
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/CustomRenderer.java2
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/MyLittleTextureView.java4
-rw-r--r--tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java6
-rw-r--r--tests/net/java/com/android/server/ConnectivityServiceTest.java65
-rw-r--r--tools/aapt2/ResourceUtils.cpp36
-rw-r--r--tools/aapt2/ResourceUtils.h7
-rw-r--r--tools/aapt2/cmd/Link.cpp36
-rw-r--r--tools/aapt2/process/SymbolTable.cpp160
-rw-r--r--tools/aapt2/process/SymbolTable.h10
-rw-r--r--tools/aapt2/process/SymbolTable_test.cpp72
-rw-r--r--tools/aapt2/test/Fixture.cpp10
-rw-r--r--tools/aapt2/test/Fixture.h3
-rw-r--r--tools/aapt2/util/Files.cpp21
-rw-r--r--tools/aapt2/util/Files_test.cpp36
-rw-r--r--wifi/java/android/net/wifi/WifiInfo.java46
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java5
-rw-r--r--wifi/java/android/net/wifi/p2p/WifiP2pDevice.java9
-rw-r--r--wifi/tests/src/android/net/wifi/WifiInfoTest.java7
-rw-r--r--wifi/tests/src/android/net/wifi/p2p/WifiP2pDeviceTest.java73
400 files changed, 7889 insertions, 4292 deletions
diff --git a/Android.bp b/Android.bp
index 628894016f39..385149e3229f 100644
--- a/Android.bp
+++ b/Android.bp
@@ -845,6 +845,7 @@ java_library_host {
// specified on the build command line.
java_library {
name: "framework-atb-backward-compatibility",
+ installable: true,
srcs: [
"core/java/android/content/pm/AndroidTestBaseUpdater.java",
],
@@ -1514,7 +1515,7 @@ droiddoc {
],
proofread_file: "ds-docs-proofrerad.txt",
args: framework_docs_only_args +
- " -toroot / -samplegroup Admin " +
+ " -toroot / -yamlV2 -metalavaApiSince -samplegroup Admin " +
" -samplegroup Background " +
" -samplegroup Connectivity " +
" -samplegroup Content " +
diff --git a/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java b/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java
index e7fe235e0ea8..e805ab912fc1 100644
--- a/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java
+++ b/apct-tests/perftests/core/src/android/graphics/perftests/RenderNodePerfTest.java
@@ -71,7 +71,7 @@ public class RenderNodePerfTest {
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
RenderNode node = RenderNode.create("LinearLayout", null);
while (state.keepRunning()) {
- node.startRecording(100, 100);
+ node.beginRecording(100, 100);
node.endRecording();
}
}
@@ -86,7 +86,7 @@ public class RenderNodePerfTest {
while (state.keepRunning()) {
for (int i = 0; i < nodes.length; i++) {
- nodes[i].startRecording(100, 100);
+ nodes[i].beginRecording(100, 100);
}
for (int i = nodes.length - 1; i >= 0; i--) {
nodes[i].endRecording();
diff --git a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java
index bd7522d0359e..8a6c60f44702 100644
--- a/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java
+++ b/apct-tests/perftests/core/src/android/text/StaticLayoutPerfTest.java
@@ -265,7 +265,7 @@ public class StaticLayoutPerfTest {
state.pauseTiming();
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
- final RecordingCanvas c = node.startRecording(1200, 200);
+ final RecordingCanvas c = node.beginRecording(1200, 200);
state.resumeTiming();
layout.draw(c);
@@ -282,7 +282,7 @@ public class StaticLayoutPerfTest {
final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT);
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
- final RecordingCanvas c = node.startRecording(1200, 200);
+ final RecordingCanvas c = node.beginRecording(1200, 200);
state.resumeTiming();
layout.draw(c);
@@ -299,7 +299,7 @@ public class StaticLayoutPerfTest {
final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
- final RecordingCanvas c = node.startRecording(1200, 200);
+ final RecordingCanvas c = node.beginRecording(1200, 200);
state.resumeTiming();
layout.draw(c);
@@ -316,7 +316,7 @@ public class StaticLayoutPerfTest {
final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT);
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
- final RecordingCanvas c = node.startRecording(1200, 200);
+ final RecordingCanvas c = node.beginRecording(1200, 200);
Canvas.freeTextLayoutCaches();
state.resumeTiming();
@@ -334,7 +334,7 @@ public class StaticLayoutPerfTest {
final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
- final RecordingCanvas c = node.startRecording(1200, 200);
+ final RecordingCanvas c = node.beginRecording(1200, 200);
Canvas.freeTextLayoutCaches();
state.resumeTiming();
@@ -353,7 +353,7 @@ public class StaticLayoutPerfTest {
mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT);
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
- final RecordingCanvas c = node.startRecording(1200, 200);
+ final RecordingCanvas c = node.beginRecording(1200, 200);
state.resumeTiming();
layout.draw(c);
@@ -371,7 +371,7 @@ public class StaticLayoutPerfTest {
mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT);
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
- final RecordingCanvas c = node.startRecording(1200, 200);
+ final RecordingCanvas c = node.beginRecording(1200, 200);
state.resumeTiming();
layout.draw(c);
@@ -389,7 +389,7 @@ public class StaticLayoutPerfTest {
mTextUtil.nextRandomParagraph(WORD_LENGTH, STYLE_TEXT), PAINT);
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
- final RecordingCanvas c = node.startRecording(1200, 200);
+ final RecordingCanvas c = node.beginRecording(1200, 200);
Canvas.freeTextLayoutCaches();
state.resumeTiming();
@@ -408,7 +408,7 @@ public class StaticLayoutPerfTest {
mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT), PAINT);
final StaticLayout layout =
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH).build();
- final RecordingCanvas c = node.startRecording(1200, 200);
+ final RecordingCanvas c = node.beginRecording(1200, 200);
Canvas.freeTextLayoutCaches();
state.resumeTiming();
diff --git a/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java b/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java
index 0bc9ee4e53ab..55d54e452040 100644
--- a/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java
+++ b/apct-tests/perftests/core/src/android/widget/TextViewPrecomputedTextPerfTest.java
@@ -344,7 +344,7 @@ public class TextViewPrecomputedTextPerfTest {
textView.setText(text);
textView.measure(width, height);
textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
- final RecordingCanvas c = node.startRecording(
+ final RecordingCanvas c = node.beginRecording(
textView.getMeasuredWidth(), textView.getMeasuredHeight());
textView.nullLayouts();
Canvas.freeTextLayoutCaches();
@@ -371,7 +371,7 @@ public class TextViewPrecomputedTextPerfTest {
textView.setText(text);
textView.measure(width, height);
textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
- final RecordingCanvas c = node.startRecording(
+ final RecordingCanvas c = node.beginRecording(
textView.getMeasuredWidth(), textView.getMeasuredHeight());
textView.nullLayouts();
Canvas.freeTextLayoutCaches();
@@ -400,7 +400,7 @@ public class TextViewPrecomputedTextPerfTest {
textView.setText(text);
textView.measure(width, height);
textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
- final RecordingCanvas c = node.startRecording(
+ final RecordingCanvas c = node.beginRecording(
textView.getMeasuredWidth(), textView.getMeasuredHeight());
textView.nullLayouts();
Canvas.freeTextLayoutCaches();
@@ -430,7 +430,7 @@ public class TextViewPrecomputedTextPerfTest {
textView.setText(text);
textView.measure(width, height);
textView.layout(0, 0, textView.getMeasuredWidth(), textView.getMeasuredHeight());
- final RecordingCanvas c = node.startRecording(
+ final RecordingCanvas c = node.beginRecording(
textView.getMeasuredWidth(), textView.getMeasuredHeight());
textView.nullLayouts();
Canvas.freeTextLayoutCaches();
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/BenchmarkResults.java b/apct-tests/perftests/multiuser/src/android/multiuser/BenchmarkResults.java
index e417ca791c45..c1362dc3a6a7 100644
--- a/apct-tests/perftests/multiuser/src/android/multiuser/BenchmarkResults.java
+++ b/apct-tests/perftests/multiuser/src/android/multiuser/BenchmarkResults.java
@@ -60,11 +60,13 @@ public class BenchmarkResults {
if (size == 0) {
return 0f;
}
- Collections.sort(mResults);
+
+ final ArrayList<Long> resultsCopy = new ArrayList<>(mResults);
+ Collections.sort(resultsCopy);
final int idx = size / 2;
return size % 2 == 0
- ? (double) (mResults.get(idx) + mResults.get(idx - 1)) / 2
- : mResults.get(idx);
+ ? (double) (resultsCopy.get(idx) + resultsCopy.get(idx - 1)) / 2
+ : resultsCopy.get(idx);
}
private double standardDeviation() {
diff --git a/api/current.txt b/api/current.txt
index 9e28ada17a93..09674793c185 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5478,7 +5478,7 @@ package android.app {
method public android.graphics.drawable.Icon getIcon();
method public android.app.PendingIntent getIntent();
method public boolean getSuppressInitialNotification();
- method public CharSequence getTitle();
+ method @Deprecated public CharSequence getTitle();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.app.Notification.BubbleMetadata> CREATOR;
}
@@ -5492,7 +5492,7 @@ package android.app {
method public android.app.Notification.BubbleMetadata.Builder setIcon(android.graphics.drawable.Icon);
method public android.app.Notification.BubbleMetadata.Builder setIntent(android.app.PendingIntent);
method public android.app.Notification.BubbleMetadata.Builder setSuppressInitialNotification(boolean);
- method public android.app.Notification.BubbleMetadata.Builder setTitle(CharSequence);
+ method @Deprecated public android.app.Notification.BubbleMetadata.Builder setTitle(CharSequence);
}
public static class Notification.Builder {
@@ -6664,7 +6664,7 @@ package android.app.admin {
method public int getPasswordMinimumUpperCase(@Nullable android.content.ComponentName);
method public int getPasswordQuality(@Nullable android.content.ComponentName);
method @Nullable public android.app.admin.SystemUpdateInfo getPendingSystemUpdate(@NonNull android.content.ComponentName);
- method public int getPermissionGrantState(@Nullable android.content.ComponentName, String, String);
+ method public int getPermissionGrantState(@Nullable android.content.ComponentName, @NonNull String, @NonNull String);
method public int getPermissionPolicy(android.content.ComponentName);
method @Nullable public java.util.List<java.lang.String> getPermittedAccessibilityServices(@NonNull android.content.ComponentName);
method @Nullable public java.util.List<java.lang.String> getPermittedCrossProfileNotificationListeners(@NonNull android.content.ComponentName);
@@ -6775,7 +6775,7 @@ package android.app.admin {
method public void setPasswordMinimumSymbols(@NonNull android.content.ComponentName, int);
method public void setPasswordMinimumUpperCase(@NonNull android.content.ComponentName, int);
method public void setPasswordQuality(@NonNull android.content.ComponentName, int);
- method public boolean setPermissionGrantState(@NonNull android.content.ComponentName, String, String, int);
+ method public boolean setPermissionGrantState(@NonNull android.content.ComponentName, @NonNull String, @NonNull String, int);
method public void setPermissionPolicy(@NonNull android.content.ComponentName, int);
method public boolean setPermittedAccessibilityServices(@NonNull android.content.ComponentName, java.util.List<java.lang.String>);
method public boolean setPermittedCrossProfileNotificationListeners(@NonNull android.content.ComponentName, @Nullable java.util.List<java.lang.String>);
@@ -11375,6 +11375,7 @@ package android.content.pm {
method @NonNull public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getMySessions();
method @Nullable public android.content.pm.PackageInstaller.SessionInfo getSessionInfo(int);
method @NonNull public java.util.List<android.content.pm.PackageInstaller.SessionInfo> getStagedSessions();
+ method @RequiresPermission(allOf={android.Manifest.permission.INSTALL_PACKAGES, "com.android.permission.INSTALL_EXISTING_PACKAGES"}) public void installExistingPackage(@NonNull String, int, @Nullable android.content.IntentSender);
method @NonNull public android.content.pm.PackageInstaller.Session openSession(int) throws java.io.IOException;
method public void registerSessionCallback(@NonNull android.content.pm.PackageInstaller.SessionCallback);
method public void registerSessionCallback(@NonNull android.content.pm.PackageInstaller.SessionCallback, @NonNull android.os.Handler);
@@ -11456,10 +11457,10 @@ package android.content.pm {
method public boolean isActive();
method public boolean isMultiPackage();
method public boolean isSealed();
- method public boolean isSessionApplied();
- method public boolean isSessionFailed();
- method public boolean isSessionReady();
method public boolean isStaged();
+ method public boolean isStagedSessionApplied();
+ method public boolean isStagedSessionFailed();
+ method public boolean isStagedSessionReady();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.content.pm.PackageInstaller.SessionInfo> CREATOR;
field public static final int INVALID_ID = -1; // 0xffffffff
@@ -11475,7 +11476,6 @@ package android.content.pm {
method public void setAppIcon(@Nullable android.graphics.Bitmap);
method public void setAppLabel(@Nullable CharSequence);
method public void setAppPackageName(@Nullable String);
- method public void setInstallAsApex();
method public void setInstallLocation(int);
method public void setInstallReason(int);
method public void setMultiPackage();
@@ -11664,6 +11664,7 @@ package android.content.pm {
field public static final String FEATURE_FAKETOUCH_MULTITOUCH_DISTINCT = "android.hardware.faketouch.multitouch.distinct";
field public static final String FEATURE_FAKETOUCH_MULTITOUCH_JAZZHAND = "android.hardware.faketouch.multitouch.jazzhand";
field public static final String FEATURE_FINGERPRINT = "android.hardware.fingerprint";
+ field public static final String FEATURE_FOLDABLE = "android.hardware.type.foldable";
field public static final String FEATURE_FREEFORM_WINDOW_MANAGEMENT = "android.software.freeform_window_management";
field public static final String FEATURE_GAMEPAD = "android.hardware.gamepad";
field public static final String FEATURE_HIFI_SENSORS = "android.hardware.sensor.hifi_sensors";
@@ -14945,13 +14946,15 @@ package android.graphics {
public final class RenderNode {
ctor public RenderNode(@Nullable String);
- method public int computeApproximateMemoryUsage();
+ method public android.graphics.RecordingCanvas beginRecording(int, int);
+ method public android.graphics.RecordingCanvas beginRecording();
+ method public long computeApproximateMemoryUsage();
method public void discardDisplayList();
method public void endRecording();
method public float getAlpha();
- method public int getAmbientShadowColor();
+ method @ColorInt public int getAmbientShadowColor();
method public int getBottom();
- method public float getCameraDistance();
+ method @FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE) public float getCameraDistance();
method public boolean getClipToBounds();
method public boolean getClipToOutline();
method public float getElevation();
@@ -14962,12 +14965,12 @@ package android.graphics {
method public float getPivotX();
method public float getPivotY();
method public int getRight();
- method public float getRotation();
method public float getRotationX();
method public float getRotationY();
+ method public float getRotationZ();
method public float getScaleX();
method public float getScaleY();
- method public int getSpotShadowColor();
+ method @ColorInt public int getSpotShadowColor();
method public int getTop();
method public float getTranslationX();
method public float getTranslationY();
@@ -14985,36 +14988,31 @@ package android.graphics {
method public boolean offsetTopAndBottom(int);
method public boolean resetPivot();
method public boolean setAlpha(float);
- method public boolean setAmbientShadowColor(int);
- method public boolean setBottom(int);
- method public boolean setCameraDistance(float);
- method public boolean setClipBounds(@Nullable android.graphics.Rect);
+ method public boolean setAmbientShadowColor(@ColorInt int);
+ method public boolean setCameraDistance(@FloatRange(from=0.0f, to=java.lang.Float.MAX_VALUE) float);
+ method public boolean setClipRect(@Nullable android.graphics.Rect);
method public boolean setClipToBounds(boolean);
method public boolean setClipToOutline(boolean);
method public boolean setElevation(float);
method public boolean setForceDarkAllowed(boolean);
method public boolean setHasOverlappingRendering(boolean);
- method public boolean setLeft(int);
- method public boolean setLeftTopRightBottom(int, int, int, int);
method public boolean setOutline(@Nullable android.graphics.Outline);
method public boolean setPivotX(float);
method public boolean setPivotY(float);
+ method public boolean setPosition(int, int, int, int);
+ method public boolean setPosition(android.graphics.Rect);
method public boolean setProjectBackwards(boolean);
method public boolean setProjectionReceiver(boolean);
- method public boolean setRight(int);
- method public boolean setRotation(float);
method public boolean setRotationX(float);
method public boolean setRotationY(float);
+ method public boolean setRotationZ(float);
method public boolean setScaleX(float);
method public boolean setScaleY(float);
- method public boolean setSpotShadowColor(int);
- method public boolean setTop(int);
+ method public boolean setSpotShadowColor(@ColorInt int);
method public boolean setTranslationX(float);
method public boolean setTranslationY(float);
method public boolean setTranslationZ(float);
method public boolean setUseCompositingLayer(boolean, @Nullable android.graphics.Paint);
- method public android.graphics.RecordingCanvas startRecording(int, int);
- method public android.graphics.RecordingCanvas startRecording();
}
public class Shader {
@@ -23385,7 +23383,7 @@ package android.media {
}
public static final class AudioPlaybackCaptureConfiguration.Builder {
- ctor public AudioPlaybackCaptureConfiguration.Builder();
+ ctor public AudioPlaybackCaptureConfiguration.Builder(@NonNull android.media.projection.MediaProjection);
method public android.media.AudioPlaybackCaptureConfiguration.Builder addMatchingUid(int);
method public android.media.AudioPlaybackCaptureConfiguration.Builder addMatchingUsage(@NonNull android.media.AudioAttributes);
method public android.media.AudioPlaybackCaptureConfiguration build();
@@ -24014,8 +24012,8 @@ package android.media {
method public int getMaxImages();
method public android.view.Surface getSurface();
method public int getWidth();
- method public static android.media.ImageReader newInstance(int, int, int, int);
- method public static android.media.ImageReader newInstance(int, int, int, int, long);
+ method @NonNull public static android.media.ImageReader newInstance(@IntRange(from=1) int, @IntRange(from=1) int, int, @IntRange(from=1) int);
+ method @NonNull public static android.media.ImageReader newInstance(@IntRange(from=1) int, @IntRange(from=1) int, int, @IntRange(from=1) int, long);
method public void setOnImageAvailableListener(android.media.ImageReader.OnImageAvailableListener, android.os.Handler);
}
@@ -24028,8 +24026,8 @@ package android.media {
method public android.media.Image dequeueInputImage();
method public int getFormat();
method public int getMaxImages();
- method public static android.media.ImageWriter newInstance(android.view.Surface, int);
- method public static android.media.ImageWriter newInstance(android.view.Surface, int, int);
+ method @NonNull public static android.media.ImageWriter newInstance(@NonNull android.view.Surface, @IntRange(from=1) int);
+ method @NonNull public static android.media.ImageWriter newInstance(@NonNull android.view.Surface, @IntRange(from=1) int, int);
method public void queueInputImage(android.media.Image);
method public void setOnImageReleasedListener(android.media.ImageWriter.OnImageReleasedListener, android.os.Handler);
}
@@ -27458,6 +27456,7 @@ package android.media.session {
method @Nullable public CharSequence getQueueTitle();
method public int getRatingType();
method @Nullable public android.app.PendingIntent getSessionActivity();
+ method @Nullable public android.os.Bundle getSessionInfo();
method @NonNull public android.media.session.MediaSession.Token getSessionToken();
method @NonNull public android.media.session.MediaController.TransportControls getTransportControls();
method public void registerCallback(@NonNull android.media.session.MediaController.Callback);
@@ -27517,6 +27516,7 @@ package android.media.session {
public final class MediaSession {
ctor public MediaSession(@NonNull android.content.Context, @NonNull String);
+ ctor public MediaSession(@NonNull android.content.Context, @NonNull String, @Nullable android.os.Bundle);
method @NonNull public android.media.session.MediaController getController();
method @NonNull public android.media.session.MediaSessionManager.RemoteUserInfo getCurrentControllerInfo();
method @NonNull public android.media.session.MediaSession.Token getSessionToken();
@@ -29987,7 +29987,7 @@ package android.net.wifi {
method @Deprecated public boolean reconnect();
method @Deprecated public boolean removeNetwork(int);
method @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE) public int removeNetworkSuggestions(@NonNull java.util.List<android.net.wifi.WifiNetworkSuggestion>);
- method @Deprecated @RequiresPermission(anyOf={"android.permission.NETWORK_SETTINGS", "android.permission.NETWORK_SETUP_WIZARD"}) public void removePasspointConfiguration(String);
+ method @Deprecated @RequiresPermission("android.permission.NETWORK_SETTINGS") public void removePasspointConfiguration(String);
method @Deprecated public boolean saveConfiguration();
method public void setTdlsEnabled(java.net.InetAddress, boolean);
method public void setTdlsEnabledWithMacAddress(String, boolean);
@@ -38832,6 +38832,7 @@ package android.provider {
field public static final String ACTION_NFC_PAYMENT_SETTINGS = "android.settings.NFC_PAYMENT_SETTINGS";
field public static final String ACTION_NFC_SETTINGS = "android.settings.NFC_SETTINGS";
field public static final String ACTION_NIGHT_DISPLAY_SETTINGS = "android.settings.NIGHT_DISPLAY_SETTINGS";
+ field public static final String ACTION_NOTIFICATION_ASSISTANT_SETTINGS = "android.settings.NOTIFICATION_ASSISTANT_SETTINGS";
field public static final String ACTION_NOTIFICATION_LISTENER_SETTINGS = "android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS";
field public static final String ACTION_NOTIFICATION_POLICY_ACCESS_SETTINGS = "android.settings.NOTIFICATION_POLICY_ACCESS_SETTINGS";
field public static final String ACTION_PRINT_SETTINGS = "android.settings.ACTION_PRINT_SETTINGS";
@@ -43339,11 +43340,11 @@ package android.telecom {
public final class CallIdentification implements android.os.Parcelable {
method public int describeContents();
- method @NonNull public String getCallScreeningAppName();
+ method @NonNull public CharSequence getCallScreeningAppName();
method @NonNull public String getCallScreeningPackageName();
- method @Nullable public String getDescription();
- method @Nullable public String getDetails();
- method @Nullable public String getName();
+ method @Nullable public CharSequence getDescription();
+ method @Nullable public CharSequence getDetails();
+ method @Nullable public CharSequence getName();
method public int getNuisanceConfidence();
method @Nullable public android.graphics.drawable.Icon getPhoto();
method public void writeToParcel(android.os.Parcel, int);
@@ -43358,9 +43359,9 @@ package android.telecom {
public static class CallIdentification.Builder {
ctor public CallIdentification.Builder();
method public android.telecom.CallIdentification build();
- method public android.telecom.CallIdentification.Builder setDescription(@Nullable String);
- method public android.telecom.CallIdentification.Builder setDetails(@Nullable String);
- method public android.telecom.CallIdentification.Builder setName(@Nullable String);
+ method public android.telecom.CallIdentification.Builder setDescription(@Nullable CharSequence);
+ method public android.telecom.CallIdentification.Builder setDetails(@Nullable CharSequence);
+ method public android.telecom.CallIdentification.Builder setName(@Nullable CharSequence);
method public android.telecom.CallIdentification.Builder setNuisanceConfidence(int);
method public android.telecom.CallIdentification.Builder setPhoto(@Nullable android.graphics.drawable.Icon);
}
@@ -44858,6 +44859,7 @@ package android.telephony {
method @Deprecated public int getCdmaDbm();
method @Deprecated public int getCdmaEcio();
method @NonNull public java.util.List<android.telephony.CellSignalStrength> getCellSignalStrengths();
+ method public <T extends android.telephony.CellSignalStrength> java.util.List<T> getCellSignalStrengths(@NonNull Class<T>);
method @Deprecated public int getEvdoDbm();
method @Deprecated public int getEvdoEcio();
method @Deprecated public int getEvdoSnr();
@@ -45192,6 +45194,7 @@ package android.telephony {
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.MODIFY_PHONE_STATE}) public boolean isDataEnabled();
method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_NETWORK_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isDataRoamingEnabled();
method public boolean isHearingAidCompatibilitySupported();
+ method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isMultisimSupported();
method public boolean isNetworkRoaming();
method public boolean isRttSupported();
method public boolean isSmsCapable();
@@ -45664,465 +45667,6 @@ package android.telephony.gsm {
}
-package android.telephony.ims {
-
- public class Rcs1To1Thread extends android.telephony.ims.RcsThread {
- method @WorkerThread public long getFallbackThreadId() throws android.telephony.ims.RcsMessageStoreException;
- method @NonNull @WorkerThread public android.telephony.ims.RcsParticipant getRecipient() throws android.telephony.ims.RcsMessageStoreException;
- method public boolean isGroup();
- method @WorkerThread public void setFallbackThreadId(long) throws android.telephony.ims.RcsMessageStoreException;
- }
-
- public abstract class RcsEvent {
- ctor protected RcsEvent(long);
- method public long getTimestamp();
- }
-
- public final class RcsEventQueryParams implements android.os.Parcelable {
- method public int describeContents();
- method @android.telephony.ims.RcsEventQueryParams.EventType public int getEventType();
- method public int getLimit();
- method public boolean getSortDirection();
- method public int getSortingProperty();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final int ALL_EVENTS = -1; // 0xffffffff
- field public static final int ALL_GROUP_THREAD_EVENTS = 0; // 0x0
- field public static final android.os.Parcelable.Creator<android.telephony.ims.RcsEventQueryParams> CREATOR;
- field public static final int GROUP_THREAD_ICON_CHANGED_EVENT = 8; // 0x8
- field public static final int GROUP_THREAD_NAME_CHANGED_EVENT = 16; // 0x10
- field public static final int GROUP_THREAD_PARTICIPANT_JOINED_EVENT = 2; // 0x2
- field public static final int GROUP_THREAD_PARTICIPANT_LEFT_EVENT = 4; // 0x4
- field public static final int PARTICIPANT_ALIAS_CHANGED_EVENT = 1; // 0x1
- field public static final int SORT_BY_CREATION_ORDER = 0; // 0x0
- field public static final int SORT_BY_TIMESTAMP = 1; // 0x1
- }
-
- public static class RcsEventQueryParams.Builder {
- ctor public RcsEventQueryParams.Builder();
- method public android.telephony.ims.RcsEventQueryParams build();
- method @CheckResult public android.telephony.ims.RcsEventQueryParams.Builder setEventType(@android.telephony.ims.RcsEventQueryParams.EventType int);
- method @CheckResult public android.telephony.ims.RcsEventQueryParams.Builder setGroupThread(@NonNull android.telephony.ims.RcsGroupThread);
- method @CheckResult public android.telephony.ims.RcsEventQueryParams.Builder setResultLimit(@IntRange(from=0) int) throws java.security.InvalidParameterException;
- method @CheckResult public android.telephony.ims.RcsEventQueryParams.Builder setSortDirection(boolean);
- method @CheckResult public android.telephony.ims.RcsEventQueryParams.Builder setSortProperty(@android.telephony.ims.RcsEventQueryParams.SortingProperty int);
- }
-
- @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef({android.telephony.ims.RcsEventQueryParams.ALL_EVENTS, android.telephony.ims.RcsEventQueryParams.ALL_GROUP_THREAD_EVENTS, android.telephony.ims.RcsEventQueryParams.PARTICIPANT_ALIAS_CHANGED_EVENT, android.telephony.ims.RcsEventQueryParams.GROUP_THREAD_PARTICIPANT_JOINED_EVENT, android.telephony.ims.RcsEventQueryParams.GROUP_THREAD_PARTICIPANT_LEFT_EVENT, android.telephony.ims.RcsEventQueryParams.GROUP_THREAD_NAME_CHANGED_EVENT, android.telephony.ims.RcsEventQueryParams.GROUP_THREAD_ICON_CHANGED_EVENT}) public static @interface RcsEventQueryParams.EventType {
- }
-
- @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef({android.telephony.ims.RcsEventQueryParams.SORT_BY_CREATION_ORDER, android.telephony.ims.RcsEventQueryParams.SORT_BY_TIMESTAMP}) public static @interface RcsEventQueryParams.SortingProperty {
- }
-
- public class RcsEventQueryResult {
- method public android.telephony.ims.RcsQueryContinuationToken getContinuationToken();
- method public java.util.List<android.telephony.ims.RcsEvent> getEvents();
- }
-
- public final class RcsFileTransferCreationParams implements android.os.Parcelable {
- method public int describeContents();
- method public String getContentMimeType();
- method public android.net.Uri getContentUri();
- method public long getFileSize();
- method @android.telephony.ims.RcsFileTransferPart.RcsFileTransferStatus public int getFileTransferStatus();
- method public int getHeight();
- method public long getMediaDuration();
- method public String getPreviewMimeType();
- method public android.net.Uri getPreviewUri();
- method public String getRcsFileTransferSessionId();
- method public long getTransferOffset();
- method public int getWidth();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.telephony.ims.RcsFileTransferCreationParams> CREATOR;
- }
-
- public class RcsFileTransferCreationParams.Builder {
- ctor public RcsFileTransferCreationParams.Builder();
- method public android.telephony.ims.RcsFileTransferCreationParams build();
- method @CheckResult public android.telephony.ims.RcsFileTransferCreationParams.Builder setContentMimeType(String);
- method @CheckResult public android.telephony.ims.RcsFileTransferCreationParams.Builder setContentUri(android.net.Uri);
- method @CheckResult public android.telephony.ims.RcsFileTransferCreationParams.Builder setFileSize(long);
- method @CheckResult public android.telephony.ims.RcsFileTransferCreationParams.Builder setFileTransferSessionId(String);
- method @CheckResult public android.telephony.ims.RcsFileTransferCreationParams.Builder setFileTransferStatus(@android.telephony.ims.RcsFileTransferPart.RcsFileTransferStatus int);
- method @CheckResult public android.telephony.ims.RcsFileTransferCreationParams.Builder setHeight(int);
- method @CheckResult public android.telephony.ims.RcsFileTransferCreationParams.Builder setMediaDuration(long);
- method @CheckResult public android.telephony.ims.RcsFileTransferCreationParams.Builder setPreviewMimeType(String);
- method @CheckResult public android.telephony.ims.RcsFileTransferCreationParams.Builder setPreviewUri(android.net.Uri);
- method @CheckResult public android.telephony.ims.RcsFileTransferCreationParams.Builder setTransferOffset(long);
- method @CheckResult public android.telephony.ims.RcsFileTransferCreationParams.Builder setWidth(int);
- }
-
- public class RcsFileTransferPart {
- method @WorkerThread @Nullable public String getContentMimeType() throws android.telephony.ims.RcsMessageStoreException;
- method @Nullable @WorkerThread public android.net.Uri getContentUri() throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public long getFileSize() throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public String getFileTransferSessionId() throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread @android.telephony.ims.RcsFileTransferPart.RcsFileTransferStatus public int getFileTransferStatus() throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public int getHeight() throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public long getLength() throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public String getPreviewMimeType() throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public android.net.Uri getPreviewUri() throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public long getTransferOffset() throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public int getWidth() throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setContentMimeType(String) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setContentUri(android.net.Uri) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setFileSize(long) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setFileTransferSessionId(String) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setFileTransferStatus(@android.telephony.ims.RcsFileTransferPart.RcsFileTransferStatus int) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setHeight(int) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setLength(long) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setPreviewMimeType(String) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setPreviewUri(android.net.Uri) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setTransferOffset(long) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setWidth(int) throws android.telephony.ims.RcsMessageStoreException;
- field public static final int DOWNLOADING = 6; // 0x6
- field public static final int DOWNLOADING_CANCELLED = 9; // 0x9
- field public static final int DOWNLOADING_FAILED = 8; // 0x8
- field public static final int DOWNLOADING_PAUSED = 7; // 0x7
- field public static final int DRAFT = 1; // 0x1
- field public static final int NOT_SET = 0; // 0x0
- field public static final int SENDING = 2; // 0x2
- field public static final int SENDING_CANCELLED = 5; // 0x5
- field public static final int SENDING_FAILED = 4; // 0x4
- field public static final int SENDING_PAUSED = 3; // 0x3
- field public static final int SUCCEEDED = 10; // 0xa
- }
-
- @IntDef({android.telephony.ims.RcsFileTransferPart.DRAFT, android.telephony.ims.RcsFileTransferPart.SENDING, android.telephony.ims.RcsFileTransferPart.SENDING_PAUSED, android.telephony.ims.RcsFileTransferPart.SENDING_FAILED, android.telephony.ims.RcsFileTransferPart.SENDING_CANCELLED, android.telephony.ims.RcsFileTransferPart.DOWNLOADING, android.telephony.ims.RcsFileTransferPart.DOWNLOADING_PAUSED, android.telephony.ims.RcsFileTransferPart.DOWNLOADING_FAILED, android.telephony.ims.RcsFileTransferPart.DOWNLOADING_CANCELLED, android.telephony.ims.RcsFileTransferPart.SUCCEEDED}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface RcsFileTransferPart.RcsFileTransferStatus {
- }
-
- public class RcsGroupThread extends android.telephony.ims.RcsThread {
- method @WorkerThread public void addParticipant(@NonNull android.telephony.ims.RcsParticipant) throws android.telephony.ims.RcsMessageStoreException;
- method @Nullable @WorkerThread public android.net.Uri getConferenceUri() throws android.telephony.ims.RcsMessageStoreException;
- method @Nullable public android.net.Uri getGroupIcon() throws android.telephony.ims.RcsMessageStoreException;
- method @Nullable @WorkerThread public String getGroupName() throws android.telephony.ims.RcsMessageStoreException;
- method @Nullable @WorkerThread public android.telephony.ims.RcsParticipant getOwner() throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread @NonNull public java.util.Set<android.telephony.ims.RcsParticipant> getParticipants() throws android.telephony.ims.RcsMessageStoreException;
- method public boolean isGroup();
- method @WorkerThread public void removeParticipant(@NonNull android.telephony.ims.RcsParticipant) throws android.telephony.ims.RcsMessageStoreException;
- method @Nullable @WorkerThread public void setConferenceUri(android.net.Uri) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setGroupIcon(@Nullable android.net.Uri) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setGroupName(String) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setOwner(@Nullable android.telephony.ims.RcsParticipant) throws android.telephony.ims.RcsMessageStoreException;
- }
-
- public abstract class RcsGroupThreadEvent extends android.telephony.ims.RcsEvent {
- method @NonNull public android.telephony.ims.RcsParticipant getOriginatingParticipant();
- method @NonNull public android.telephony.ims.RcsGroupThread getRcsGroupThread();
- }
-
- public final class RcsGroupThreadIconChangedEvent extends android.telephony.ims.RcsGroupThreadEvent {
- ctor public RcsGroupThreadIconChangedEvent(long, @NonNull android.telephony.ims.RcsGroupThread, @NonNull android.telephony.ims.RcsParticipant, @Nullable android.net.Uri);
- method @Nullable public android.net.Uri getNewIcon();
- }
-
- public final class RcsGroupThreadNameChangedEvent extends android.telephony.ims.RcsGroupThreadEvent {
- ctor public RcsGroupThreadNameChangedEvent(long, @NonNull android.telephony.ims.RcsGroupThread, @NonNull android.telephony.ims.RcsParticipant, @Nullable String);
- method @Nullable public String getNewName();
- }
-
- public final class RcsGroupThreadParticipantJoinedEvent extends android.telephony.ims.RcsGroupThreadEvent {
- ctor public RcsGroupThreadParticipantJoinedEvent(long, @NonNull android.telephony.ims.RcsGroupThread, @NonNull android.telephony.ims.RcsParticipant, @NonNull android.telephony.ims.RcsParticipant);
- method public android.telephony.ims.RcsParticipant getJoinedParticipant();
- }
-
- public final class RcsGroupThreadParticipantLeftEvent extends android.telephony.ims.RcsGroupThreadEvent {
- ctor public RcsGroupThreadParticipantLeftEvent(long, @NonNull android.telephony.ims.RcsGroupThread, @NonNull android.telephony.ims.RcsParticipant, @NonNull android.telephony.ims.RcsParticipant);
- method @NonNull public android.telephony.ims.RcsParticipant getLeavingParticipant();
- method public void persist() throws android.telephony.ims.RcsMessageStoreException;
- }
-
- public class RcsIncomingMessage extends android.telephony.ims.RcsMessage {
- method @WorkerThread public long getArrivalTimestamp() throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public long getSeenTimestamp() throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public android.telephony.ims.RcsParticipant getSenderParticipant() throws android.telephony.ims.RcsMessageStoreException;
- method public boolean isIncoming();
- method @WorkerThread public void setArrivalTimestamp(long) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setSeenTimestamp(long) throws android.telephony.ims.RcsMessageStoreException;
- }
-
- public final class RcsIncomingMessageCreationParams extends android.telephony.ims.RcsMessageCreationParams implements android.os.Parcelable {
- method public int describeContents();
- method public long getArrivalTimestamp();
- method public long getSeenTimestamp();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.telephony.ims.RcsIncomingMessageCreationParams> CREATOR;
- }
-
- public static class RcsIncomingMessageCreationParams.Builder extends android.telephony.ims.RcsMessageCreationParams.Builder {
- ctor public RcsIncomingMessageCreationParams.Builder(long, long, int);
- method public android.telephony.ims.RcsIncomingMessageCreationParams build();
- method @CheckResult public android.telephony.ims.RcsIncomingMessageCreationParams.Builder setArrivalTimestamp(long);
- method @CheckResult public android.telephony.ims.RcsIncomingMessageCreationParams.Builder setSeenTimestamp(long);
- method @CheckResult public android.telephony.ims.RcsIncomingMessageCreationParams.Builder setSenderParticipant(android.telephony.ims.RcsParticipant);
- }
-
- public class RcsManager {
- method public android.telephony.ims.RcsMessageStore getRcsMessageStore();
- }
-
- public abstract class RcsMessage {
- method @NonNull @WorkerThread public java.util.Set<android.telephony.ims.RcsFileTransferPart> getFileTransferParts() throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public double getLatitude() throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public double getLongitude() throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public long getOriginationTimestamp() throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public String getRcsMessageId() throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread @android.telephony.ims.RcsMessage.RcsMessageStatus public int getStatus() throws android.telephony.ims.RcsMessageStoreException;
- method public int getSubscriptionId() throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public String getText() throws android.telephony.ims.RcsMessageStoreException;
- method @NonNull @WorkerThread public android.telephony.ims.RcsFileTransferPart insertFileTransfer(android.telephony.ims.RcsFileTransferCreationParams) throws android.telephony.ims.RcsMessageStoreException;
- method public abstract boolean isIncoming();
- method @WorkerThread public void removeFileTransferPart(@NonNull android.telephony.ims.RcsFileTransferPart) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setLatitude(double) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setLongitude(double) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setOriginationTimestamp(long) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setRcsMessageId(String) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setStatus(@android.telephony.ims.RcsMessage.RcsMessageStatus int) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setSubscriptionId(int) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setText(String) throws android.telephony.ims.RcsMessageStoreException;
- field public static final int DRAFT = 1; // 0x1
- field public static final int FAILED = 6; // 0x6
- field public static final double LOCATION_NOT_SET = 4.9E-324;
- field public static final int NOT_SET = 0; // 0x0
- field public static final int QUEUED = 2; // 0x2
- field public static final int RECEIVED = 7; // 0x7
- field public static final int RETRYING = 5; // 0x5
- field public static final int SEEN = 9; // 0x9
- field public static final int SENDING = 3; // 0x3
- field public static final int SENT = 4; // 0x4
- }
-
- @IntDef({android.telephony.ims.RcsMessage.DRAFT, android.telephony.ims.RcsMessage.QUEUED, android.telephony.ims.RcsMessage.SENDING, android.telephony.ims.RcsMessage.SENT, android.telephony.ims.RcsMessage.RETRYING, android.telephony.ims.RcsMessage.FAILED, android.telephony.ims.RcsMessage.RECEIVED, android.telephony.ims.RcsMessage.SEEN}) @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) public static @interface RcsMessage.RcsMessageStatus {
- }
-
- public class RcsMessageCreationParams {
- ctor protected RcsMessageCreationParams(android.telephony.ims.RcsMessageCreationParams.Builder);
- method public double getLatitude();
- method public double getLongitude();
- method public int getMessageStatus();
- method public long getOriginationTimestamp();
- method @Nullable public String getRcsMessageGlobalId();
- method public int getSubId();
- method @Nullable public String getText();
- }
-
- public static class RcsMessageCreationParams.Builder {
- method public android.telephony.ims.RcsMessageCreationParams build();
- method @CheckResult public android.telephony.ims.RcsMessageCreationParams.Builder setLatitude(double);
- method @CheckResult public android.telephony.ims.RcsMessageCreationParams.Builder setLongitude(double);
- method @CheckResult public android.telephony.ims.RcsMessageCreationParams.Builder setRcsMessageId(String);
- method @CheckResult public android.telephony.ims.RcsMessageCreationParams.Builder setStatus(@android.telephony.ims.RcsMessage.RcsMessageStatus int);
- method @CheckResult public android.telephony.ims.RcsMessageCreationParams.Builder setText(String);
- }
-
- public final class RcsMessageQueryParams implements android.os.Parcelable {
- method public int describeContents();
- method public int getFileTransferPresence();
- method public int getLimit();
- method public String getMessageLike();
- method public int getMessageType();
- method public boolean getSortDirection();
- method @android.telephony.ims.RcsMessageQueryParams.SortingProperty public int getSortingProperty();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.telephony.ims.RcsMessageQueryParams> CREATOR;
- field public static final int MESSAGES_WITHOUT_FILE_TRANSFERS = 8; // 0x8
- field public static final int MESSAGES_WITH_FILE_TRANSFERS = 4; // 0x4
- field public static final int MESSAGE_TYPE_INCOMING = 1; // 0x1
- field public static final int MESSAGE_TYPE_OUTGOING = 2; // 0x2
- field public static final int SORT_BY_CREATION_ORDER = 0; // 0x0
- field public static final int SORT_BY_TIMESTAMP = 1; // 0x1
- }
-
- public static class RcsMessageQueryParams.Builder {
- ctor public RcsMessageQueryParams.Builder();
- method public android.telephony.ims.RcsMessageQueryParams build();
- method @CheckResult public android.telephony.ims.RcsMessageQueryParams.Builder setFileTransferPresence(int);
- method @CheckResult public android.telephony.ims.RcsMessageQueryParams.Builder setMessageLike(String);
- method @CheckResult public android.telephony.ims.RcsMessageQueryParams.Builder setMessageType(int);
- method @CheckResult public android.telephony.ims.RcsMessageQueryParams.Builder setResultLimit(@IntRange(from=0) int) throws java.security.InvalidParameterException;
- method @CheckResult public android.telephony.ims.RcsMessageQueryParams.Builder setSortDirection(boolean);
- method @CheckResult public android.telephony.ims.RcsMessageQueryParams.Builder setSortProperty(@android.telephony.ims.RcsMessageQueryParams.SortingProperty int);
- method @CheckResult public android.telephony.ims.RcsMessageQueryParams.Builder setThread(@Nullable android.telephony.ims.RcsThread);
- }
-
- @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef({android.telephony.ims.RcsMessageQueryParams.SORT_BY_CREATION_ORDER, android.telephony.ims.RcsMessageQueryParams.SORT_BY_TIMESTAMP}) public static @interface RcsMessageQueryParams.SortingProperty {
- }
-
- public final class RcsMessageQueryResult implements android.os.Parcelable {
- method public int describeContents();
- method @Nullable public android.telephony.ims.RcsQueryContinuationToken getContinuationToken();
- method @NonNull public java.util.List<android.telephony.ims.RcsMessage> getMessages();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.telephony.ims.RcsMessageQueryResult> CREATOR;
- }
-
- public final class RcsMessageSnippet implements android.os.Parcelable {
- method public int describeContents();
- method @android.telephony.ims.RcsMessage.RcsMessageStatus public int getSnippetStatus();
- method @Nullable public String getSnippetText();
- method public long getSnippetTimestamp();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.telephony.ims.RcsMessageSnippet> CREATOR;
- }
-
- public class RcsMessageStore {
- ctor public RcsMessageStore();
- method @WorkerThread @NonNull public android.telephony.ims.RcsGroupThread createGroupThread(@Nullable java.util.List<android.telephony.ims.RcsParticipant>, @Nullable String, @Nullable android.net.Uri) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread @NonNull public android.telephony.ims.Rcs1To1Thread createRcs1To1Thread(@NonNull android.telephony.ims.RcsParticipant) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread @NonNull public android.telephony.ims.RcsParticipant createRcsParticipant(String, @Nullable String) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void deleteThread(@NonNull android.telephony.ims.RcsThread) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread @NonNull public android.telephony.ims.RcsEventQueryResult getRcsEvents(@Nullable android.telephony.ims.RcsEventQueryParams) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread @NonNull public android.telephony.ims.RcsEventQueryResult getRcsEvents(@NonNull android.telephony.ims.RcsQueryContinuationToken) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread @NonNull public android.telephony.ims.RcsMessageQueryResult getRcsMessages(@Nullable android.telephony.ims.RcsMessageQueryParams) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread @NonNull public android.telephony.ims.RcsMessageQueryResult getRcsMessages(@NonNull android.telephony.ims.RcsQueryContinuationToken) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread @NonNull public android.telephony.ims.RcsParticipantQueryResult getRcsParticipants(@Nullable android.telephony.ims.RcsParticipantQueryParams) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread @NonNull public android.telephony.ims.RcsParticipantQueryResult getRcsParticipants(@NonNull android.telephony.ims.RcsQueryContinuationToken) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread @NonNull public android.telephony.ims.RcsThreadQueryResult getRcsThreads(@Nullable android.telephony.ims.RcsThreadQueryParams) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread @NonNull public android.telephony.ims.RcsThreadQueryResult getRcsThreads(@NonNull android.telephony.ims.RcsQueryContinuationToken) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread @NonNull public void persistRcsEvent(android.telephony.ims.RcsEvent) throws android.telephony.ims.RcsMessageStoreException;
- }
-
- public class RcsMessageStoreException extends java.lang.Exception {
- ctor public RcsMessageStoreException(String);
- }
-
- public class RcsOutgoingMessage extends android.telephony.ims.RcsMessage {
- method @NonNull @WorkerThread public java.util.List<android.telephony.ims.RcsOutgoingMessageDelivery> getOutgoingDeliveries() throws android.telephony.ims.RcsMessageStoreException;
- method public boolean isIncoming();
- }
-
- public final class RcsOutgoingMessageCreationParams extends android.telephony.ims.RcsMessageCreationParams implements android.os.Parcelable {
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.telephony.ims.RcsOutgoingMessageCreationParams> CREATOR;
- }
-
- public static class RcsOutgoingMessageCreationParams.Builder extends android.telephony.ims.RcsMessageCreationParams.Builder {
- ctor public RcsOutgoingMessageCreationParams.Builder(long, int);
- method public android.telephony.ims.RcsOutgoingMessageCreationParams build();
- }
-
- public class RcsOutgoingMessageDelivery {
- method @WorkerThread public long getDeliveredTimestamp() throws android.telephony.ims.RcsMessageStoreException;
- method @NonNull public android.telephony.ims.RcsOutgoingMessage getMessage();
- method @NonNull public android.telephony.ims.RcsParticipant getRecipient();
- method @WorkerThread public long getSeenTimestamp() throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread @android.telephony.ims.RcsMessage.RcsMessageStatus public int getStatus() throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setDeliveredTimestamp(long) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setSeenTimestamp(long) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setStatus(@android.telephony.ims.RcsMessage.RcsMessageStatus int) throws android.telephony.ims.RcsMessageStoreException;
- }
-
- public class RcsParticipant {
- method @Nullable @WorkerThread public String getAlias() throws android.telephony.ims.RcsMessageStoreException;
- method @Nullable @WorkerThread public String getCanonicalAddress() throws android.telephony.ims.RcsMessageStoreException;
- method @Nullable @WorkerThread public String getContactId() throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setAlias(String) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void setContactId(String) throws android.telephony.ims.RcsMessageStoreException;
- }
-
- public final class RcsParticipantAliasChangedEvent extends android.telephony.ims.RcsEvent {
- ctor public RcsParticipantAliasChangedEvent(long, @NonNull android.telephony.ims.RcsParticipant, @Nullable String);
- method @Nullable public String getNewAlias();
- method @NonNull public android.telephony.ims.RcsParticipant getParticipant();
- }
-
- public final class RcsParticipantQueryParams implements android.os.Parcelable {
- method public int describeContents();
- method public String getAliasLike();
- method public String getCanonicalAddressLike();
- method public int getLimit();
- method public boolean getSortDirection();
- method public int getSortingProperty();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.telephony.ims.RcsParticipantQueryParams> CREATOR;
- field public static final int SORT_BY_ALIAS = 1; // 0x1
- field public static final int SORT_BY_CANONICAL_ADDRESS = 2; // 0x2
- field public static final int SORT_BY_CREATION_ORDER = 0; // 0x0
- }
-
- public static class RcsParticipantQueryParams.Builder {
- ctor public RcsParticipantQueryParams.Builder();
- method public android.telephony.ims.RcsParticipantQueryParams build();
- method @CheckResult public android.telephony.ims.RcsParticipantQueryParams.Builder setAliasLike(String);
- method @CheckResult public android.telephony.ims.RcsParticipantQueryParams.Builder setCanonicalAddressLike(String);
- method @CheckResult public android.telephony.ims.RcsParticipantQueryParams.Builder setResultLimit(@IntRange(from=0) int) throws java.security.InvalidParameterException;
- method @CheckResult public android.telephony.ims.RcsParticipantQueryParams.Builder setSortDirection(boolean);
- method @CheckResult public android.telephony.ims.RcsParticipantQueryParams.Builder setSortProperty(@android.telephony.ims.RcsParticipantQueryParams.SortingProperty int);
- method @CheckResult public android.telephony.ims.RcsParticipantQueryParams.Builder setThread(android.telephony.ims.RcsThread);
- }
-
- @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef({android.telephony.ims.RcsParticipantQueryParams.SORT_BY_CREATION_ORDER, android.telephony.ims.RcsParticipantQueryParams.SORT_BY_ALIAS, android.telephony.ims.RcsParticipantQueryParams.SORT_BY_CANONICAL_ADDRESS}) public static @interface RcsParticipantQueryParams.SortingProperty {
- }
-
- public final class RcsParticipantQueryResult implements android.os.Parcelable {
- method public int describeContents();
- method @Nullable public android.telephony.ims.RcsQueryContinuationToken getContinuationToken();
- method @NonNull public java.util.List<android.telephony.ims.RcsParticipant> getParticipants();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.telephony.ims.RcsParticipantQueryResult> CREATOR;
- }
-
- public final class RcsQueryContinuationToken implements android.os.Parcelable {
- method public int describeContents();
- method @android.telephony.ims.RcsQueryContinuationToken.ContinuationTokenType public int getQueryType();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.telephony.ims.RcsQueryContinuationToken> CREATOR;
- field public static final int EVENT_QUERY_CONTINUATION_TOKEN_TYPE = 0; // 0x0
- field public static final int MESSAGE_QUERY_CONTINUATION_TOKEN_TYPE = 1; // 0x1
- field public static final int PARTICIPANT_QUERY_CONTINUATION_TOKEN_TYPE = 2; // 0x2
- field public static final int THREAD_QUERY_CONTINUATION_TOKEN_TYPE = 3; // 0x3
- }
-
- @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef({android.telephony.ims.RcsQueryContinuationToken.EVENT_QUERY_CONTINUATION_TOKEN_TYPE, android.telephony.ims.RcsQueryContinuationToken.MESSAGE_QUERY_CONTINUATION_TOKEN_TYPE, android.telephony.ims.RcsQueryContinuationToken.PARTICIPANT_QUERY_CONTINUATION_TOKEN_TYPE, android.telephony.ims.RcsQueryContinuationToken.THREAD_QUERY_CONTINUATION_TOKEN_TYPE}) public static @interface RcsQueryContinuationToken.ContinuationTokenType {
- }
-
- public abstract class RcsThread {
- method @WorkerThread @NonNull public android.telephony.ims.RcsIncomingMessage addIncomingMessage(@NonNull android.telephony.ims.RcsIncomingMessageCreationParams) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread @NonNull public android.telephony.ims.RcsOutgoingMessage addOutgoingMessage(@NonNull android.telephony.ims.RcsOutgoingMessageCreationParams) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread public void deleteMessage(@NonNull android.telephony.ims.RcsMessage) throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread @NonNull public android.telephony.ims.RcsMessageQueryResult getMessages() throws android.telephony.ims.RcsMessageStoreException;
- method @WorkerThread @NonNull public android.telephony.ims.RcsMessageSnippet getSnippet() throws android.telephony.ims.RcsMessageStoreException;
- method public abstract boolean isGroup();
- }
-
- public final class RcsThreadQueryParams implements android.os.Parcelable {
- method public int describeContents();
- method public int getLimit();
- method public boolean getSortDirection();
- method @android.telephony.ims.RcsThreadQueryParams.SortingProperty public int getSortingProperty();
- method public int getThreadType();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.telephony.ims.RcsThreadQueryParams> CREATOR;
- field public static final int SORT_BY_CREATION_ORDER = 0; // 0x0
- field public static final int SORT_BY_TIMESTAMP = 1; // 0x1
- field public static final int THREAD_TYPE_1_TO_1 = 2; // 0x2
- field public static final int THREAD_TYPE_GROUP = 1; // 0x1
- }
-
- public static class RcsThreadQueryParams.Builder {
- ctor public RcsThreadQueryParams.Builder();
- method public android.telephony.ims.RcsThreadQueryParams build();
- method @CheckResult public android.telephony.ims.RcsThreadQueryParams.Builder setParticipant(@NonNull android.telephony.ims.RcsParticipant);
- method @CheckResult public android.telephony.ims.RcsThreadQueryParams.Builder setParticipants(@NonNull java.util.List<android.telephony.ims.RcsParticipant>);
- method @CheckResult public android.telephony.ims.RcsThreadQueryParams.Builder setResultLimit(@IntRange(from=0) int) throws java.security.InvalidParameterException;
- method @CheckResult public android.telephony.ims.RcsThreadQueryParams.Builder setSortDirection(boolean);
- method @CheckResult public android.telephony.ims.RcsThreadQueryParams.Builder setSortProperty(@android.telephony.ims.RcsThreadQueryParams.SortingProperty int);
- method @CheckResult public android.telephony.ims.RcsThreadQueryParams.Builder setThreadType(int);
- }
-
- @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE) @IntDef({android.telephony.ims.RcsThreadQueryParams.SORT_BY_CREATION_ORDER, android.telephony.ims.RcsThreadQueryParams.SORT_BY_TIMESTAMP}) public static @interface RcsThreadQueryParams.SortingProperty {
- }
-
- public final class RcsThreadQueryResult implements android.os.Parcelable {
- method public int describeContents();
- method @Nullable public android.telephony.ims.RcsQueryContinuationToken getContinuationToken();
- method @NonNull public java.util.List<android.telephony.ims.RcsThread> getThreads();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator<android.telephony.ims.RcsThreadQueryResult> CREATOR;
- }
-
-}
-
package android.telephony.mbms {
public class DownloadProgressListener {
@@ -47477,6 +47021,7 @@ package android.text.style {
method public int getVerticalAlignment();
field public static final int ALIGN_BASELINE = 1; // 0x1
field public static final int ALIGN_BOTTOM = 0; // 0x0
+ field public static final int ALIGN_CENTER = 2; // 0x2
field protected final int mVerticalAlignment;
}
diff --git a/api/system-current.txt b/api/system-current.txt
index c831522f1286..6f314f33a764 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -15,6 +15,7 @@ package android {
field public static final String ACCESS_SHORTCUTS = "android.permission.ACCESS_SHORTCUTS";
field public static final String ACCESS_SURFACE_FLINGER = "android.permission.ACCESS_SURFACE_FLINGER";
field public static final String ACTIVITY_EMBEDDING = "android.permission.ACTIVITY_EMBEDDING";
+ field public static final String ADJUST_RUNTIME_PERMISSIONS_POLICY = "android.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY";
field public static final String ALLOCATE_AGGRESSIVE = "android.permission.ALLOCATE_AGGRESSIVE";
field public static final String ALLOW_ANY_CODEC_FOR_PLAYBACK = "android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK";
field public static final String AMBIENT_WALLPAPER = "android.permission.AMBIENT_WALLPAPER";
@@ -1304,8 +1305,8 @@ package android.content {
}
public abstract class ContentResolver {
- method @Nullable public android.os.Bundle getCache(@NonNull android.net.Uri);
- method public void putCache(@NonNull android.net.Uri, @Nullable android.os.Bundle);
+ method @Nullable @RequiresPermission("android.permission.CACHE_CONTENT") public android.os.Bundle getCache(@NonNull android.net.Uri);
+ method @RequiresPermission("android.permission.CACHE_CONTENT") public void putCache(@NonNull android.net.Uri, @Nullable android.os.Bundle);
}
public abstract class Context {
@@ -1557,6 +1558,7 @@ package android.content.pm {
method public void setDontKillApp(boolean);
method public void setEnableRollback();
method @RequiresPermission(android.Manifest.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS) public void setGrantedRuntimePermissions(String[]);
+ method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setInstallAsApex();
method public void setInstallAsInstantApp(boolean);
method public void setInstallAsVirtualPreload();
method @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES) public void setStaged();
@@ -1575,6 +1577,7 @@ package android.content.pm {
method @RequiresPermission("android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS") public abstract void addOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener);
method public abstract boolean arePermissionsIndividuallyControlled();
method public abstract java.util.List<android.content.IntentFilter> getAllIntentFilters(String);
+ method public boolean getAppDetailsActivityEnabled(@NonNull String);
method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public android.content.pm.ApplicationInfo getApplicationInfoAsUser(@NonNull String, int, @NonNull android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
method @NonNull public android.content.pm.dex.ArtManager getArtManager();
method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL) public abstract String getDefaultBrowserPackageNameAsUser(int);
@@ -1590,8 +1593,8 @@ package android.content.pm {
method @android.content.pm.PackageManager.PermissionFlags @RequiresPermission(anyOf={android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS, android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS}) public abstract int getPermissionFlags(String, String, @NonNull android.os.UserHandle);
method @NonNull @RequiresPermission(android.Manifest.permission.SUSPEND_APPS) public String[] getUnsuspendablePackages(@NonNull String[]);
method @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS) public abstract void grantRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
- method public abstract int installExistingPackage(String) throws android.content.pm.PackageManager.NameNotFoundException;
- method public abstract int installExistingPackage(String, int) throws android.content.pm.PackageManager.NameNotFoundException;
+ method @Deprecated public abstract int installExistingPackage(String) throws android.content.pm.PackageManager.NameNotFoundException;
+ method @Deprecated public abstract int installExistingPackage(String, int) throws android.content.pm.PackageManager.NameNotFoundException;
method @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceiversAsUser(android.content.Intent, int, android.os.UserHandle);
method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryIntentActivitiesAsUser(@NonNull android.content.Intent, int, @NonNull android.os.UserHandle);
method @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS) public java.util.List<android.content.pm.ResolveInfo> queryIntentContentProvidersAsUser(@NonNull android.content.Intent, int, @NonNull android.os.UserHandle);
@@ -1601,6 +1604,7 @@ package android.content.pm {
method @Deprecated public void replacePreferredActivity(@NonNull android.content.IntentFilter, int, @NonNull java.util.List<android.content.ComponentName>, @NonNull android.content.ComponentName);
method @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS) public abstract void revokeRuntimePermission(@NonNull String, @NonNull String, @NonNull android.os.UserHandle);
method public void sendDeviceCustomizationReadyBroadcast();
+ method @RequiresPermission(value=android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE, conditional=true) public void setAppDetailsActivityEnabled(@NonNull String, boolean);
method @RequiresPermission(allOf={android.Manifest.permission.SET_PREFERRED_APPLICATIONS, android.Manifest.permission.INTERACT_ACROSS_USERS_FULL}) public abstract boolean setDefaultBrowserPackageNameAsUser(String, int);
method @NonNull @RequiresPermission(android.Manifest.permission.SUSPEND_APPS) public String[] setDistractingPackageRestrictions(@NonNull String[], int);
method @RequiresPermission(android.Manifest.permission.SET_HARMFUL_APP_WARNINGS) public void setHarmfulAppWarning(@NonNull String, @Nullable CharSequence);
@@ -1711,8 +1715,13 @@ package android.content.pm {
field public boolean handleAllWebDataURI;
}
+ public final class ShortcutInfo implements android.os.Parcelable {
+ method @Nullable public android.app.Person[] getPersons();
+ }
+
public class ShortcutManager {
method @NonNull public java.util.List<android.content.pm.ShortcutManager.ShareShortcutInfo> getShareTargets(@NonNull android.content.IntentFilter);
+ method public boolean hasShareTargets(@NonNull String);
}
public static final class ShortcutManager.ShareShortcutInfo implements android.os.Parcelable {
@@ -1890,7 +1899,7 @@ package android.hardware.display {
public final class BrightnessConfiguration implements android.os.Parcelable {
method public int describeContents();
method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByCategory(int);
- method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByPackageName(String);
+ method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByPackageName(@NonNull String);
method public android.util.Pair<float[],float[]> getCurve();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessConfiguration> CREATOR;
@@ -1898,8 +1907,8 @@ package android.hardware.display {
public static class BrightnessConfiguration.Builder {
ctor public BrightnessConfiguration.Builder(float[], float[]);
- method public android.hardware.display.BrightnessConfiguration.Builder addCorrectionByCategory(int, android.hardware.display.BrightnessCorrection);
- method public android.hardware.display.BrightnessConfiguration.Builder addCorrectionByPackageName(String, android.hardware.display.BrightnessCorrection);
+ method public android.hardware.display.BrightnessConfiguration.Builder addCorrectionByCategory(int, @NonNull android.hardware.display.BrightnessCorrection);
+ method public android.hardware.display.BrightnessConfiguration.Builder addCorrectionByPackageName(@NonNull String, @NonNull android.hardware.display.BrightnessCorrection);
method public android.hardware.display.BrightnessConfiguration build();
method public int getMaxCorrectionsByCategory();
method public int getMaxCorrectionsByPackageName();
@@ -1907,7 +1916,7 @@ package android.hardware.display {
}
public final class BrightnessCorrection implements android.os.Parcelable {
- method public float apply(float);
+ method @FloatRange(from=0.0) public float apply(@FloatRange(from=0.0) float);
method @NonNull public static android.hardware.display.BrightnessCorrection createScaleAndTranslateLog(float, float);
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
@@ -3036,21 +3045,21 @@ package android.location {
method public double getHorizontalPositionUncertaintyMeters();
method public double getLatitudeDegrees();
method public double getLongitudeDegrees();
- method @Nullable public java.util.List<android.location.GnssSingleSatCorrection> getSingleSatCorrectionList();
+ method @Nullable public java.util.List<android.location.GnssSingleSatCorrection> getSingleSatelliteCorrectionList();
method public long getToaGpsNanosecondsOfWeek();
method public double getVerticalPositionUncertaintyMeters();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssMeasurementCorrections> CREATOR;
}
- public static class GnssMeasurementCorrections.Builder {
+ public static final class GnssMeasurementCorrections.Builder {
ctor public GnssMeasurementCorrections.Builder();
method public android.location.GnssMeasurementCorrections build();
method public android.location.GnssMeasurementCorrections.Builder setAltitudeMeters(double);
method public android.location.GnssMeasurementCorrections.Builder setHorizontalPositionUncertaintyMeters(double);
method public android.location.GnssMeasurementCorrections.Builder setLatitudeDegrees(double);
method public android.location.GnssMeasurementCorrections.Builder setLongitudeDegrees(double);
- method public android.location.GnssMeasurementCorrections.Builder setSingleSatCorrectionList(@Nullable java.util.List<android.location.GnssSingleSatCorrection>);
+ method public android.location.GnssMeasurementCorrections.Builder setSingleSatelliteCorrectionList(@Nullable java.util.List<android.location.GnssSingleSatCorrection>);
method public android.location.GnssMeasurementCorrections.Builder setToaGpsNanosecondsOfWeek(long);
method public android.location.GnssMeasurementCorrections.Builder setVerticalPositionUncertaintyMeters(double);
}
@@ -3065,7 +3074,7 @@ package android.location {
field public static final android.os.Parcelable.Creator<android.location.GnssReflectingPlane> CREATOR;
}
- public static class GnssReflectingPlane.Builder {
+ public static final class GnssReflectingPlane.Builder {
ctor public GnssReflectingPlane.Builder();
method public android.location.GnssReflectingPlane build();
method public android.location.GnssReflectingPlane.Builder setAltitudeMeters(double);
@@ -3080,14 +3089,14 @@ package android.location {
method public int getConstellationType();
method public float getExcessPathLengthMeters();
method public float getExcessPathLengthUncertaintyMeters();
- method @FloatRange(from=0.0f, to=1.0f) public float getProbSatIsLos();
+ method @FloatRange(from=0.0f, to=1.0f) public float getProbabilityLineOfSight();
method @Nullable public android.location.GnssReflectingPlane getReflectingPlane();
- method public int getSatId();
- method public int getSingleSatCorrectionFlags();
+ method public int getSatelliteId();
+ method public int getSingleSatelliteCorrectionFlags();
method public boolean hasExcessPathLength();
method public boolean hasExcessPathLengthUncertainty();
method public boolean hasReflectingPlane();
- method public boolean hasSatelliteLineOfSight();
+ method public boolean hasValidSatelliteLineOfSight();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.location.GnssSingleSatCorrection> CREATOR;
field public static final int HAS_EXCESS_PATH_LENGTH_MASK = 2; // 0x2
@@ -3096,17 +3105,17 @@ package android.location {
field public static final int HAS_REFLECTING_PLANE_MASK = 8; // 0x8
}
- public static class GnssSingleSatCorrection.Builder {
+ public static final class GnssSingleSatCorrection.Builder {
ctor public GnssSingleSatCorrection.Builder();
method public android.location.GnssSingleSatCorrection build();
method public android.location.GnssSingleSatCorrection.Builder setCarrierFrequencyHz(float);
method public android.location.GnssSingleSatCorrection.Builder setConstellationType(int);
method public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthMeters(float);
method public android.location.GnssSingleSatCorrection.Builder setExcessPathLengthUncertaintyMeters(float);
- method public android.location.GnssSingleSatCorrection.Builder setProbSatIsLos(@FloatRange(from=0.0f, to=1.0f) float);
+ method public android.location.GnssSingleSatCorrection.Builder setProbabilityLineOfSight(@FloatRange(from=0.0f, to=1.0f) float);
method public android.location.GnssSingleSatCorrection.Builder setReflectingPlane(android.location.GnssReflectingPlane);
- method public android.location.GnssSingleSatCorrection.Builder setSatId(int);
- method public android.location.GnssSingleSatCorrection.Builder setSingleSatCorrectionFlags(int);
+ method public android.location.GnssSingleSatCorrection.Builder setSatelliteId(int);
+ method public android.location.GnssSingleSatCorrection.Builder setSingleSatelliteCorrectionFlags(int);
}
public class GpsClock implements android.os.Parcelable {
@@ -4664,7 +4673,10 @@ package android.net.wifi {
}
public class WifiInfo implements android.os.Parcelable {
+ method @Nullable public String getFqdn();
+ method @Nullable public String getProviderFriendlyName();
method public boolean isOsuAp();
+ method public boolean isPasspointAp();
}
public class WifiManager {
@@ -5121,6 +5133,7 @@ package android.os {
method public void onError(int);
method public void onFinished();
method public void onProgress(float);
+ field public static final int BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS = 5; // 0x5
field public static final int BUGREPORT_ERROR_INVALID_INPUT = 1; // 0x1
field public static final int BUGREPORT_ERROR_RUNTIME = 2; // 0x2
field public static final int BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT = 4; // 0x4
@@ -5537,6 +5550,7 @@ package android.os {
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.PersistableBundle getSeedAccountOptions();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getSeedAccountType();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public long[] getSerialNumbersOfUsers(boolean);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.graphics.Bitmap getUserIcon();
method @Deprecated @android.os.UserManager.UserRestrictionSource @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public int getUserRestrictionSource(String, android.os.UserHandle);
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public java.util.List<android.os.UserManager.EnforcingUser> getUserRestrictionSources(String, android.os.UserHandle);
method public boolean hasRestrictedProfiles();
@@ -5547,6 +5561,8 @@ package android.os {
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isPrimaryUser();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean isRestrictedProfile();
method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public boolean removeUser(android.os.UserHandle);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserIcon(android.graphics.Bitmap);
+ method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void setUserName(String);
field public static final String ACTION_USER_RESTRICTIONS_CHANGED = "android.os.action.USER_RESTRICTIONS_CHANGED";
field @Deprecated public static final String DISALLOW_OEM_UNLOCK = "no_oem_unlock";
field public static final String DISALLOW_RUN_IN_BACKGROUND = "no_run_in_background";
@@ -5623,6 +5639,7 @@ package android.permission {
method @BinderThread public abstract void onRestoreRuntimePermissionsBackup(@NonNull android.os.UserHandle, @NonNull java.io.InputStream);
method public abstract void onRevokeRuntimePermission(@NonNull String, @NonNull String);
method @NonNull public abstract java.util.Map<java.lang.String,java.util.List<java.lang.String>> onRevokeRuntimePermissions(@NonNull java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, @NonNull String);
+ method public abstract boolean onSetRuntimePermissionGrantStateByDeviceAdmin(@NonNull String, @NonNull String, @NonNull String, int);
field public static final String SERVICE_INTERFACE = "android.permission.PermissionControllerService";
}
@@ -7459,7 +7476,7 @@ package android.telephony {
field public static final int VSNCP_TIMEOUT = 2236; // 0x8bc
}
- public class DisconnectCause {
+ public final class DisconnectCause {
field public static final int ALREADY_DIALING = 72; // 0x48
field public static final int ANSWERED_ELSEWHERE = 52; // 0x34
field public static final int BUSY = 4; // 0x4
@@ -7637,18 +7654,18 @@ package android.telephony {
public class PhoneStateListener {
method public void onCallAttributesChanged(@NonNull android.telephony.CallAttributes);
- method public void onCallDisconnectCauseChanged(int, int);
- method public void onImsCallDisconnectCauseChanged(@NonNull android.telephony.ims.ImsReasonInfo);
- method public void onPreciseCallStateChanged(android.telephony.PreciseCallState);
- method public void onPreciseDataConnectionStateChanged(android.telephony.PreciseDataConnectionState);
+ method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onCallDisconnectCauseChanged(int, int);
+ method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onImsCallDisconnectCauseChanged(@NonNull android.telephony.ims.ImsReasonInfo);
+ method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onPreciseCallStateChanged(@NonNull android.telephony.PreciseCallState);
+ method @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public void onPreciseDataConnectionStateChanged(android.telephony.PreciseDataConnectionState);
method public void onRadioPowerStateChanged(int);
method public void onSrvccStateChanged(int);
method public void onVoiceActivationStateChanged(int);
field public static final int LISTEN_CALL_ATTRIBUTES_CHANGED = 67108864; // 0x4000000
- field public static final int LISTEN_CALL_DISCONNECT_CAUSES = 33554432; // 0x2000000
- field public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES = 134217728; // 0x8000000
- field public static final int LISTEN_PRECISE_CALL_STATE = 2048; // 0x800
- field public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 4096; // 0x1000
+ field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_CALL_DISCONNECT_CAUSES = 33554432; // 0x2000000
+ field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES = 134217728; // 0x8000000
+ field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_CALL_STATE = 2048; // 0x800
+ field @RequiresPermission("android.permission.READ_PRECISE_PHONE_STATE") public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 4096; // 0x1000
field public static final int LISTEN_RADIO_POWER_STATE_CHANGED = 8388608; // 0x800000
field @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public static final int LISTEN_SRVCC_STATE_CHANGED = 16384; // 0x4000
field public static final int LISTEN_VOICE_ACTIVATION_STATE = 131072; // 0x20000
@@ -7683,7 +7700,7 @@ package android.telephony {
field public static final android.os.Parcelable.Creator<android.telephony.PreciseDataConnectionState> CREATOR;
}
- public class PreciseDisconnectCause {
+ public final class PreciseDisconnectCause {
field public static final int ACCESS_CLASS_BLOCKED = 260; // 0x104
field public static final int ACCESS_INFORMATION_DISCARDED = 43; // 0x2b
field public static final int ACM_LIMIT_EXCEEDED = 68; // 0x44
@@ -7901,7 +7918,7 @@ package android.telephony {
method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public int getRadioPowerState();
method public int getSimApplicationState();
method public int getSimCardState();
- method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public String getSimLocale();
+ method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Locale getSimLocale();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getSupportedRadioAccessFamily();
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.UiccSlotInfo[] getUiccSlotsInfo();
@@ -7912,7 +7929,6 @@ package android.telephony {
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isCurrentPotentialEmergencyNumber(@NonNull String);
method public boolean isDataConnectivityPossible();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isIdle();
- method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isMultisimCarrierRestricted();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook();
method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRadioOn();
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isRebootRequiredForModemConfigChange();
@@ -9222,7 +9238,7 @@ package android.telephony.mbms {
package android.telephony.mbms.vendor {
- public class MbmsDownloadServiceBase extends android.os.Binder {
+ public class MbmsDownloadServiceBase extends android.os.Binder implements android.os.IInterface {
ctor public MbmsDownloadServiceBase();
method public int addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) throws android.os.RemoteException;
method public int addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) throws android.os.RemoteException;
@@ -9255,7 +9271,7 @@ package android.telephony.mbms.vendor {
method public void updateGroupCall(int, long, java.util.List<java.lang.Integer>, java.util.List<java.lang.Integer>);
}
- public class MbmsStreamingServiceBase extends android.os.Binder {
+ public class MbmsStreamingServiceBase extends android.os.Binder implements android.os.IInterface {
ctor public MbmsStreamingServiceBase();
method public android.os.IBinder asBinder();
method public void dispose(int) throws android.os.RemoteException;
diff --git a/api/test-current.txt b/api/test-current.txt
index 2a45cd3b15a2..0cd20be4b879 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -17,6 +17,10 @@ package android {
field public static final String WRITE_OBB = "android.permission.WRITE_OBB";
}
+ public static final class R.bool {
+ field public static final int config_perDisplayFocusEnabled = 17891332; // 0x1110004
+ }
+
public static final class R.string {
field public static final int config_defaultAssistant = 17039393; // 0x1040021
field public static final int config_defaultDialer = 17039395; // 0x1040023
@@ -48,6 +52,7 @@ package android.app {
method public long getTotalRam();
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public int getUidImportance(int);
method @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS) public void removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener);
+ method public static void resumeAppSwitches() throws android.os.RemoteException;
method @RequiresPermission(android.Manifest.permission.CHANGE_CONFIGURATION) public void scheduleApplicationInfoChanged(java.util.List<java.lang.String>, int);
}
@@ -94,6 +99,31 @@ package android.app {
field public static final int SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT = 0; // 0x0
}
+ public class ActivityView extends android.view.ViewGroup {
+ ctor public ActivityView(android.content.Context);
+ ctor public ActivityView(android.content.Context, android.util.AttributeSet);
+ ctor public ActivityView(android.content.Context, android.util.AttributeSet, int);
+ ctor public ActivityView(android.content.Context, android.util.AttributeSet, int, boolean);
+ method public void onLayout(boolean, int, int, int, int);
+ method public void onLocationChanged();
+ method public void performBackPress();
+ method public void release();
+ method public void setCallback(android.app.ActivityView.StateCallback);
+ method public void setForwardedInsets(android.graphics.Insets);
+ method public void startActivity(@NonNull android.content.Intent);
+ method public void startActivity(@NonNull android.content.Intent, android.os.UserHandle);
+ method public void startActivity(@NonNull android.app.PendingIntent);
+ }
+
+ public abstract static class ActivityView.StateCallback {
+ ctor public ActivityView.StateCallback();
+ method public abstract void onActivityViewDestroyed(android.app.ActivityView);
+ method public abstract void onActivityViewReady(android.app.ActivityView);
+ method public void onTaskCreated(int, android.content.ComponentName);
+ method public void onTaskMovedToFront(int);
+ method public void onTaskRemovalStarted(int);
+ }
+
public class AppDetailsActivity extends android.app.Activity {
ctor public AppDetailsActivity();
}
@@ -483,6 +513,17 @@ package android.bluetooth {
package android.content {
+ public final class AutofillOptions implements android.os.Parcelable {
+ ctor public AutofillOptions(int, boolean);
+ method public int describeContents();
+ method public static android.content.AutofillOptions forWhitelistingItself();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.content.AutofillOptions> CREATOR;
+ field public boolean augmentedEnabled;
+ field public final boolean compatModeEnabled;
+ field public final int loggingLevel;
+ }
+
public final class ContentCaptureOptions implements android.os.Parcelable {
ctor public ContentCaptureOptions(int, int, int, int, int, @Nullable android.util.ArraySet<android.content.ComponentName>);
method public int describeContents();
@@ -507,12 +548,17 @@ package android.content {
public abstract class Context {
method public android.content.Context createPackageContextAsUser(String, int, android.os.UserHandle) throws android.content.pm.PackageManager.NameNotFoundException;
+ method public abstract android.view.Display getDisplay();
method public android.os.UserHandle getUser();
method public int getUserId();
- method public void setAutofillCompatibilityEnabled(boolean);
+ method public void setAutofillOptions(@Nullable android.content.AutofillOptions);
method public void setContentCaptureOptions(@Nullable android.content.ContentCaptureOptions);
}
+ public class ContextWrapper extends android.content.Context {
+ method public android.view.Display getDisplay();
+ }
+
}
package android.content.pm {
@@ -719,7 +765,7 @@ package android.hardware.display {
public final class BrightnessConfiguration implements android.os.Parcelable {
method public int describeContents();
method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByCategory(int);
- method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByPackageName(String);
+ method @Nullable public android.hardware.display.BrightnessCorrection getCorrectionByPackageName(@NonNull String);
method public android.util.Pair<float[],float[]> getCurve();
method public void writeToParcel(android.os.Parcel, int);
field public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessConfiguration> CREATOR;
@@ -727,8 +773,8 @@ package android.hardware.display {
public static class BrightnessConfiguration.Builder {
ctor public BrightnessConfiguration.Builder(float[], float[]);
- method public android.hardware.display.BrightnessConfiguration.Builder addCorrectionByCategory(int, android.hardware.display.BrightnessCorrection);
- method public android.hardware.display.BrightnessConfiguration.Builder addCorrectionByPackageName(String, android.hardware.display.BrightnessCorrection);
+ method public android.hardware.display.BrightnessConfiguration.Builder addCorrectionByCategory(int, @NonNull android.hardware.display.BrightnessCorrection);
+ method public android.hardware.display.BrightnessConfiguration.Builder addCorrectionByPackageName(@NonNull String, @NonNull android.hardware.display.BrightnessCorrection);
method public android.hardware.display.BrightnessConfiguration build();
method public int getMaxCorrectionsByCategory();
method public int getMaxCorrectionsByPackageName();
@@ -736,7 +782,7 @@ package android.hardware.display {
}
public final class BrightnessCorrection implements android.os.Parcelable {
- method public float apply(float);
+ method @FloatRange(from=0.0) public float apply(@FloatRange(from=0.0) float);
method @NonNull public static android.hardware.display.BrightnessCorrection createScaleAndTranslateLog(float, float);
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
@@ -958,6 +1004,50 @@ package android.media.audiofx {
}
+package android.metrics {
+
+ public class LogMaker {
+ ctor public LogMaker(int);
+ ctor public LogMaker(Object[]);
+ method public android.metrics.LogMaker addTaggedData(int, Object);
+ method public android.metrics.LogMaker clearCategory();
+ method public android.metrics.LogMaker clearPackageName();
+ method public android.metrics.LogMaker clearSubtype();
+ method public android.metrics.LogMaker clearTaggedData(int);
+ method public android.metrics.LogMaker clearType();
+ method public void deserialize(Object[]);
+ method public int getCategory();
+ method public long getCounterBucket();
+ method public String getCounterName();
+ method public int getCounterValue();
+ method public String getPackageName();
+ method public int getProcessId();
+ method public int getSubtype();
+ method public Object getTaggedData(int);
+ method public long getTimestamp();
+ method public int getType();
+ method public int getUid();
+ method public boolean isLongCounterBucket();
+ method public boolean isSubsetOf(android.metrics.LogMaker);
+ method public boolean isValidValue(Object);
+ method public Object[] serialize();
+ method public android.metrics.LogMaker setCategory(int);
+ method public android.metrics.LogMaker setPackageName(String);
+ method public android.metrics.LogMaker setSubtype(int);
+ method public android.metrics.LogMaker setType(int);
+ }
+
+ public class MetricsReader {
+ ctor public MetricsReader();
+ method public void checkpoint();
+ method public boolean hasNext();
+ method public android.metrics.LogMaker next();
+ method public void read(long);
+ method public void reset();
+ }
+
+}
+
package android.net {
public class CaptivePortal implements android.os.Parcelable {
@@ -1302,6 +1392,7 @@ package android.os {
public class Build {
method public static boolean is64BitAbi(String);
+ field public static final boolean IS_EMULATOR;
}
public static class Build.VERSION {
@@ -1861,6 +1952,7 @@ package android.provider {
public static final class Settings.Global extends android.provider.Settings.NameValueTable {
field public static final String AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES = "autofill_compat_mode_allowed_packages";
field public static final String AUTOMATIC_POWER_SAVER_MODE = "automatic_power_saver_mode";
+ field public static final String BATTERY_SAVER_CONSTANTS = "battery_saver_constants";
field public static final String CAPTIVE_PORTAL_FALLBACK_PROBE_SPECS = "captive_portal_fallback_probe_specs";
field public static final String CAPTIVE_PORTAL_FALLBACK_URL = "captive_portal_fallback_url";
field public static final String CAPTIVE_PORTAL_HTTPS_URL = "captive_portal_https_url";
@@ -1882,6 +1974,7 @@ package android.provider {
field public static final String LOCATION_GLOBAL_KILL_SWITCH = "location_global_kill_switch";
field public static final String LOW_POWER_MODE = "low_power";
field public static final String LOW_POWER_MODE_STICKY = "low_power_sticky";
+ field public static final String OVERLAY_DISPLAY_DEVICES = "overlay_display_devices";
field public static final String SMS_ACCESS_RESTRICTION_ENABLED = "sms_access_restriction_enabled";
field public static final String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
}
@@ -1900,6 +1993,7 @@ package android.provider {
field public static final String CONTENT_CAPTURE_ENABLED = "content_capture_enabled";
field public static final String DISABLED_PRINT_SERVICES = "disabled_print_services";
field @Deprecated public static final String ENABLED_NOTIFICATION_POLICY_ACCESS_PACKAGES = "enabled_notification_policy_access_packages";
+ field public static final String ENABLED_VR_LISTENERS = "enabled_vr_listeners";
field public static final String LOCATION_ACCESS_CHECK_DELAY_MILLIS = "location_access_check_delay_millis";
field public static final String LOCATION_ACCESS_CHECK_INTERVAL_MILLIS = "location_access_check_interval_millis";
field public static final String NOTIFICATION_BADGING = "notification_badging";
@@ -2288,7 +2382,7 @@ package android.telephony.mbms {
package android.telephony.mbms.vendor {
- public class MbmsDownloadServiceBase extends android.os.Binder {
+ public class MbmsDownloadServiceBase extends android.os.Binder implements android.os.IInterface {
ctor public MbmsDownloadServiceBase();
method public int addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) throws android.os.RemoteException;
method public int addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) throws android.os.RemoteException;
@@ -2321,7 +2415,7 @@ package android.telephony.mbms.vendor {
method public void updateGroupCall(int, long, java.util.List<java.lang.Integer>, java.util.List<java.lang.Integer>);
}
- public class MbmsStreamingServiceBase extends android.os.Binder {
+ public class MbmsStreamingServiceBase extends android.os.Binder implements android.os.IInterface {
ctor public MbmsStreamingServiceBase();
method public android.os.IBinder asBinder();
method public void dispose(int) throws android.os.RemoteException;
@@ -2380,6 +2474,10 @@ package android.util {
method public E valueAtUnchecked(int);
}
+ public class TimeUtils {
+ method public static String formatDuration(long);
+ }
+
}
package android.util.proto {
@@ -2601,6 +2699,10 @@ package android.view {
field public static final int CALLBACK_ANIMATION = 1; // 0x1
}
+ public final class Display {
+ method public boolean supportsSystemDecorations();
+ }
+
public class FocusFinder {
method public static void sort(android.view.View[], int, int, android.view.ViewGroup, boolean);
}
diff --git a/cmds/bootanimation/bootanim.rc b/cmds/bootanimation/bootanim.rc
index 469c9646a4aa..3666d6af29f5 100644
--- a/cmds/bootanimation/bootanim.rc
+++ b/cmds/bootanimation/bootanim.rc
@@ -2,6 +2,9 @@ service bootanim /system/bin/bootanimation
class core animation
user graphics
group graphics audio
+ # bootanimation depends on libandroidicu in the Runtime APEX.
+ # TODO(b/124939955): Remove this dependency on libandroidicu
+ updatable
disabled
oneshot
writepid /dev/stune/top-app/tasks
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 4deb8bd83a9f..69fbf1f9d881 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -1200,9 +1200,9 @@ Status StatsService::sendBinaryPushStateChangedAtom(const android::String16& tra
userid_t userId = multiuser_get_user_id(uid);
- bool requiresStaging = options | IStatsManager::FLAG_REQUIRE_STAGING;
- bool rollbackEnabled = options | IStatsManager::FLAG_ROLLBACK_ENABLED;
- bool requiresLowLatencyMonitor = options | IStatsManager::FLAG_REQUIRE_LOW_LATENCY_MONITOR;
+ bool requiresStaging = options & IStatsManager::FLAG_REQUIRE_STAGING;
+ bool rollbackEnabled = options & IStatsManager::FLAG_ROLLBACK_ENABLED;
+ bool requiresLowLatencyMonitor = options & IStatsManager::FLAG_REQUIRE_LOW_LATENCY_MONITOR;
ProtoOutputStream proto;
for (const auto& expId : experimentIds) {
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 78e994fc5c61..de42398f8720 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -45,6 +45,7 @@ import "frameworks/base/core/proto/android/stats/docsui/docsui_enums.proto";
import "frameworks/base/core/proto/android/stats/devicepolicy/device_policy.proto";
import "frameworks/base/core/proto/android/stats/devicepolicy/device_policy_enums.proto";
import "frameworks/base/core/proto/android/stats/launcher/launcher.proto";
+import "frameworks/base/core/proto/android/stats/style/style_enums.proto";
import "frameworks/base/core/proto/android/telecomm/enums.proto";
import "frameworks/base/core/proto/android/telephony/enums.proto";
import "frameworks/base/core/proto/android/view/enums.proto";
@@ -247,6 +248,7 @@ message Atom {
AssistGestureProgressReported assist_gesture_progress_reported = 176;
TouchGestureClassified touch_gesture_classified = 177;
HiddenApiUsed hidden_api_used = 178 [(allow_from_any_uid) = true];
+ StyleUIChanged style_ui_changed = 179;
}
// Pulled events will start at field 10000.
@@ -2349,6 +2351,17 @@ message LauncherUIChanged {
optional bool is_swipe_up_enabled = 5;
}
+message StyleUIChanged {
+ optional android.stats.style.Action action = 1;
+ optional int32 color_package_hash = 2;
+ optional int32 font_package_hash = 3;
+ optional int32 shape_package_hash = 4;
+ optional int32 clock_package_hash = 5;
+ optional int32 launcher_grid = 6;
+ optional int32 wallpaper_category_hash = 7;
+ optional int32 wallpaper_id_hash = 8;
+}
+
/**
* Logs when Settings UI has changed.
*
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.cpp b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
index e7f7af2c09e1..9de62a2cce03 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.cpp
@@ -155,7 +155,7 @@ ValueMetricProducer::ValueMetricProducer(
mCurrentBucketStartTimeNs = startTimeNs;
// Kicks off the puller immediately if condition is true and diff based.
if (mIsPulled && mCondition == ConditionState::kTrue && mUseDiff) {
- pullAndMatchEventsLocked(startTimeNs);
+ pullAndMatchEventsLocked(startTimeNs, mCondition);
}
VLOG("value metric %lld created. bucket size %lld start_time: %lld", (long long)metric.id(),
(long long)mBucketSizeNs, (long long)mTimeBaseNs);
@@ -174,13 +174,17 @@ void ValueMetricProducer::onSlicedConditionMayChangeLocked(bool overallCondition
}
void ValueMetricProducer::dropDataLocked(const int64_t dropTimeNs) {
- flushIfNeededLocked(dropTimeNs);
StatsdStats::getInstance().noteBucketDropped(mMetricId);
- mPastBuckets.clear();
+ // We are going to flush the data without doing a pull first so we need to invalidte the data.
+ bool pullNeeded = mIsPulled && mCondition == ConditionState::kTrue;
+ if (pullNeeded) {
+ invalidateCurrentBucket();
+ }
+ flushIfNeededLocked(dropTimeNs);
+ clearPastBucketsLocked(dropTimeNs);
}
void ValueMetricProducer::clearPastBucketsLocked(const int64_t dumpTimeNs) {
- flushIfNeededLocked(dumpTimeNs);
mPastBuckets.clear();
mSkippedBuckets.clear();
}
@@ -192,7 +196,6 @@ void ValueMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
std::set<string> *str_set,
ProtoOutputStream* protoOutput) {
VLOG("metric %lld dump report now...", (long long)mMetricId);
- flushIfNeededLocked(dumpTimeNs);
if (include_current_partial_bucket) {
// For pull metrics, we need to do a pull at bucket boundaries. If we do not do that the
// current bucket will have incomplete data and the next will have the wrong snapshot to do
@@ -205,10 +208,10 @@ void ValueMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
invalidateCurrentBucket();
break;
case NO_TIME_CONSTRAINTS:
- pullAndMatchEventsLocked(dumpTimeNs);
+ pullAndMatchEventsLocked(dumpTimeNs, mCondition);
break;
}
- }
+ }
flushCurrentBucketLocked(dumpTimeNs, dumpTimeNs);
}
protoOutput->write(FIELD_TYPE_INT64 | FIELD_ID_ID, (long long)mMetricId);
@@ -325,12 +328,16 @@ void ValueMetricProducer::onDumpReportLocked(const int64_t dumpTimeNs,
}
}
-void ValueMetricProducer::invalidateCurrentBucket() {
+void ValueMetricProducer::invalidateCurrentBucketWithoutResetBase() {
if (!mCurrentBucketIsInvalid) {
// Only report once per invalid bucket.
StatsdStats::getInstance().noteInvalidatedBucket(mMetricId);
}
mCurrentBucketIsInvalid = true;
+}
+
+void ValueMetricProducer::invalidateCurrentBucket() {
+ invalidateCurrentBucketWithoutResetBase();
resetBase();
}
@@ -345,82 +352,112 @@ void ValueMetricProducer::resetBase() {
void ValueMetricProducer::onConditionChangedLocked(const bool condition,
const int64_t eventTimeNs) {
- if (eventTimeNs < mCurrentBucketStartTimeNs) {
+ bool isEventTooLate = eventTimeNs < mCurrentBucketStartTimeNs;
+ if (!isEventTooLate) {
+ if (mCondition == ConditionState::kUnknown) {
+ // If the condition was unknown, we mark the bucket as invalid since the bucket will
+ // contain partial data. For instance, the condition change might happen close to the
+ // end of the bucket and we might miss lots of data.
+ //
+ // We still want to pull to set the base.
+ invalidateCurrentBucket();
+ }
+
+ // Pull on condition changes.
+ ConditionState newCondition = condition ? ConditionState::kTrue : ConditionState::kFalse;
+ bool conditionChanged =
+ (mCondition == ConditionState::kTrue && newCondition == ConditionState::kFalse)
+ || (mCondition == ConditionState::kFalse && newCondition == ConditionState::kTrue);
+ // We do not need to pull when we go from unknown to false.
+ //
+ // We also pull if the condition was already true in order to be able to flush the bucket at
+ // the end if needed.
+ //
+ // onConditionChangedLocked might happen on bucket boundaries if this is called before
+ // #onDataPulled.
+ if (mIsPulled && (conditionChanged || condition)) {
+ pullAndMatchEventsLocked(eventTimeNs, newCondition);
+ }
+
+ // When condition change from true to false, clear diff base but don't
+ // reset other counters as we may accumulate more value in the bucket.
+ if (mUseDiff && mCondition == ConditionState::kTrue
+ && newCondition == ConditionState::kFalse) {
+ resetBase();
+ }
+ mCondition = newCondition;
+
+ } else {
VLOG("Skip event due to late arrival: %lld vs %lld", (long long)eventTimeNs,
(long long)mCurrentBucketStartTimeNs);
StatsdStats::getInstance().noteConditionChangeInNextBucket(mMetricId);
invalidateCurrentBucket();
- return;
+ // Something weird happened. If we received another event if the future, the condition might
+ // be wrong.
+ mCondition = ConditionState::kUnknown;
}
+ // This part should alway be called.
flushIfNeededLocked(eventTimeNs);
-
- // Pull on condition changes.
- bool conditionChanged = mCondition != condition;
- bool unknownToFalse = mCondition == ConditionState::kUnknown
- && condition == ConditionState::kFalse;
- // We do not need to pull when we go from unknown to false.
- if (mIsPulled && conditionChanged && !unknownToFalse) {
- pullAndMatchEventsLocked(eventTimeNs);
- }
-
- // when condition change from true to false, clear diff base but don't
- // reset other counters as we may accumulate more value in the bucket.
- if (mUseDiff && mCondition == ConditionState::kTrue && condition == ConditionState::kFalse) {
- resetBase();
- }
-
- mCondition = condition ? ConditionState::kTrue : ConditionState::kFalse;
}
-void ValueMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs) {
+void ValueMetricProducer::pullAndMatchEventsLocked(const int64_t timestampNs, ConditionState condition) {
vector<std::shared_ptr<LogEvent>> allData;
if (!mPullerManager->Pull(mPullTagId, &allData)) {
- ALOGE("Gauge Stats puller failed for tag: %d at %lld", mPullTagId, (long long)timestampNs);
+ ALOGE("Stats puller failed for tag: %d at %lld", mPullTagId, (long long)timestampNs);
invalidateCurrentBucket();
return;
}
- accumulateEvents(allData, timestampNs, timestampNs);
+ accumulateEvents(allData, timestampNs, timestampNs, condition);
}
int64_t ValueMetricProducer::calcPreviousBucketEndTime(const int64_t currentTimeNs) {
return mTimeBaseNs + ((currentTimeNs - mTimeBaseNs) / mBucketSizeNs) * mBucketSizeNs;
}
+// By design, statsd pulls data at bucket boundaries using AlarmManager. These pulls are likely
+// to be delayed. Other events like condition changes or app upgrade which are not based on
+// AlarmManager might have arrived earlier and close the bucket.
void ValueMetricProducer::onDataPulled(const std::vector<std::shared_ptr<LogEvent>>& allData,
bool pullSuccess, int64_t originalPullTimeNs) {
std::lock_guard<std::mutex> lock(mMutex);
- if (mCondition == ConditionState::kTrue) {
- if (!pullSuccess) {
+ if (mCondition == ConditionState::kTrue) {
// If the pull failed, we won't be able to compute a diff.
- invalidateCurrentBucket();
- return;
+ if (!pullSuccess) {
+ invalidateCurrentBucket();
+ } else {
+ bool isEventLate = originalPullTimeNs < getCurrentBucketEndTimeNs();
+ if (isEventLate) {
+ // If the event is late, we are in the middle of a bucket. Just
+ // process the data without trying to snap the data to the nearest bucket.
+ accumulateEvents(allData, originalPullTimeNs, originalPullTimeNs, mCondition);
+ } else {
+ // For scheduled pulled data, the effective event time is snap to the nearest
+ // bucket end. In the case of waking up from a deep sleep state, we will
+ // attribute to the previous bucket end. If the sleep was long but not very
+ // long, we will be in the immediate next bucket. Previous bucket may get a
+ // larger number as we pull at a later time than real bucket end.
+ //
+ // If the sleep was very long, we skip more than one bucket before sleep. In
+ // this case, if the diff base will be cleared and this new data will serve as
+ // new diff base.
+ int64_t bucketEndTime = calcPreviousBucketEndTime(originalPullTimeNs) - 1;
+ StatsdStats::getInstance().noteBucketBoundaryDelayNs(
+ mMetricId, originalPullTimeNs - bucketEndTime);
+ accumulateEvents(allData, originalPullTimeNs, bucketEndTime, mCondition);
+ }
+ }
}
- // For scheduled pulled data, the effective event time is snap to the nearest
- // bucket end. In the case of waking up from a deep sleep state, we will
- // attribute to the previous bucket end. If the sleep was long but not very long, we
- // will be in the immediate next bucket. Previous bucket may get a larger number as
- // we pull at a later time than real bucket end.
- // If the sleep was very long, we skip more than one bucket before sleep. In this case,
- // if the diff base will be cleared and this new data will serve as new diff base.
- int64_t bucketEndTime = calcPreviousBucketEndTime(originalPullTimeNs) - 1;
- StatsdStats::getInstance().noteBucketBoundaryDelayNs(
- mMetricId, originalPullTimeNs - bucketEndTime);
- accumulateEvents(allData, originalPullTimeNs, bucketEndTime);
-
- // We can probably flush the bucket. Since we used bucketEndTime when calling
- // #onMatchedLogEventInternalLocked, the current bucket will not have been flushed.
- flushIfNeededLocked(originalPullTimeNs);
-
- } else {
- VLOG("No need to commit data on condition false.");
- }
+ // We can probably flush the bucket. Since we used bucketEndTime when calling
+ // #onMatchedLogEventInternalLocked, the current bucket will not have been flushed.
+ flushIfNeededLocked(originalPullTimeNs);
}
-void ValueMetricProducer::accumulateEvents(const std::vector<std::shared_ptr<LogEvent>>& allData,
- int64_t originalPullTimeNs, int64_t eventElapsedTimeNs) {
+void ValueMetricProducer::accumulateEvents(const std::vector<std::shared_ptr<LogEvent>>& allData,
+ int64_t originalPullTimeNs, int64_t eventElapsedTimeNs,
+ ConditionState condition) {
bool isEventLate = eventElapsedTimeNs < mCurrentBucketStartTimeNs;
if (isEventLate) {
VLOG("Skip bucket end pull due to late arrival: %lld vs %lld",
@@ -459,7 +496,7 @@ void ValueMetricProducer::accumulateEvents(const std::vector<std::shared_ptr<Log
// If the new pulled data does not contains some keys we track in our intervals, we need to
// reset the base.
for (auto& slice : mCurrentSlicedBucket) {
- bool presentInPulledData = mMatchedMetricDimensionKeys.find(slice.first)
+ bool presentInPulledData = mMatchedMetricDimensionKeys.find(slice.first)
!= mMatchedMetricDimensionKeys.end();
if (!presentInPulledData) {
for (auto& interval : slice.second) {
@@ -583,7 +620,10 @@ void ValueMetricProducer::onMatchedLogEventInternalLocked(const size_t matcherIn
}
mMatchedMetricDimensionKeys.insert(eventKey);
- flushIfNeededLocked(eventTimeNs);
+ if (!mIsPulled) {
+ // We cannot flush without doing a pull first.
+ flushIfNeededLocked(eventTimeNs);
+ }
// For pulled data, we already check condition when we decide to pull or
// in onDataPulled. So take all of them.
@@ -718,26 +758,26 @@ void ValueMetricProducer::onMatchedLogEventInternalLocked(const size_t matcherIn
}
}
+// For pulled metrics, we always need to make sure we do a pull before flushing the bucket
+// if mCondition is true!
void ValueMetricProducer::flushIfNeededLocked(const int64_t& eventTimeNs) {
int64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs();
-
if (eventTimeNs < currentBucketEndTimeNs) {
VLOG("eventTime is %lld, less than next bucket start time %lld", (long long)eventTimeNs,
(long long)(currentBucketEndTimeNs));
return;
}
-
- int64_t numBucketsForward = 1 + (eventTimeNs - currentBucketEndTimeNs) / mBucketSizeNs;
+ int64_t numBucketsForward = calcBucketsForwardCount(eventTimeNs);
int64_t nextBucketStartTimeNs = currentBucketEndTimeNs + (numBucketsForward - 1) * mBucketSizeNs;
flushCurrentBucketLocked(eventTimeNs, nextBucketStartTimeNs);
+}
- mCurrentBucketNum += numBucketsForward;
- if (numBucketsForward > 1) {
- VLOG("Skipping forward %lld buckets", (long long)numBucketsForward);
- StatsdStats::getInstance().noteSkippedForwardBuckets(mMetricId);
- // take base again in future good bucket.
- resetBase();
+int64_t ValueMetricProducer::calcBucketsForwardCount(const int64_t& eventTimeNs) const {
+ int64_t currentBucketEndTimeNs = getCurrentBucketEndTimeNs();
+ if (eventTimeNs < currentBucketEndTimeNs) {
+ return 0;
}
+ return 1 + (eventTimeNs - currentBucketEndTimeNs) / mBucketSizeNs;
}
void ValueMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs,
@@ -746,6 +786,16 @@ void ValueMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs,
StatsdStats::getInstance().noteBucketUnknownCondition(mMetricId);
}
+ int64_t numBucketsForward = calcBucketsForwardCount(eventTimeNs);
+ mCurrentBucketNum += numBucketsForward;
+ if (numBucketsForward > 1) {
+ VLOG("Skipping forward %lld buckets", (long long)numBucketsForward);
+ StatsdStats::getInstance().noteSkippedForwardBuckets(mMetricId);
+ // Something went wrong. Maybe the device was sleeping for a long time. It is better
+ // to mark the current bucket as invalid. The last pull might have been successful through.
+ invalidateCurrentBucketWithoutResetBase();
+ }
+
VLOG("finalizing bucket for %ld, dumping %d slices", (long)mCurrentBucketStartTimeNs,
(int)mCurrentSlicedBucket.size());
int64_t fullBucketEndTimeNs = getCurrentBucketEndTimeNs();
@@ -769,12 +819,7 @@ void ValueMetricProducer::flushCurrentBucketLocked(const int64_t& eventTimeNs,
if (!mCurrentBucketIsInvalid) {
appendToFullBucket(eventTimeNs, fullBucketEndTimeNs);
}
- StatsdStats::getInstance().noteBucketCount(mMetricId);
- initCurrentSlicedBucket();
- mCurrentBucketIsInvalid = false;
- mCurrentBucketStartTimeNs = nextBucketStartTimeNs;
- VLOG("metric %lld: new bucket start time: %lld", (long long)mMetricId,
- (long long)mCurrentBucketStartTimeNs);
+ initCurrentSlicedBucket(nextBucketStartTimeNs);
}
ValueBucket ValueMetricProducer::buildPartialBucket(int64_t bucketEndTime,
@@ -801,7 +846,9 @@ ValueBucket ValueMetricProducer::buildPartialBucket(int64_t bucketEndTime,
return bucket;
}
-void ValueMetricProducer::initCurrentSlicedBucket() {
+void ValueMetricProducer::initCurrentSlicedBucket(int64_t nextBucketStartTimeNs) {
+ StatsdStats::getInstance().noteBucketCount(mMetricId);
+ // Cleanup data structure to aggregate values.
for (auto it = mCurrentSlicedBucket.begin(); it != mCurrentSlicedBucket.end();) {
bool obsolete = true;
for (auto& interval : it->second) {
@@ -819,6 +866,16 @@ void ValueMetricProducer::initCurrentSlicedBucket() {
it++;
}
}
+
+ mCurrentBucketIsInvalid = false;
+ // If we do not have a global base when the condition is true,
+ // we will have incomplete bucket for the next bucket.
+ if (mUseDiff && !mHasGlobalBase && mCondition) {
+ mCurrentBucketIsInvalid = false;
+ }
+ mCurrentBucketStartTimeNs = nextBucketStartTimeNs;
+ VLOG("metric %lld: new bucket start time: %lld", (long long)mMetricId,
+ (long long)mCurrentBucketStartTimeNs);
}
void ValueMetricProducer::appendToFullBucket(int64_t eventTimeNs, int64_t fullBucketEndTimeNs) {
diff --git a/cmds/statsd/src/metrics/ValueMetricProducer.h b/cmds/statsd/src/metrics/ValueMetricProducer.h
index 696d4fa7ae45..f317c3768dd9 100644
--- a/cmds/statsd/src/metrics/ValueMetricProducer.h
+++ b/cmds/statsd/src/metrics/ValueMetricProducer.h
@@ -39,6 +39,13 @@ struct ValueBucket {
std::vector<Value> values;
};
+
+// Aggregates values within buckets.
+//
+// There are different events that might complete a bucket
+// - a condition change
+// - an app upgrade
+// - an alarm set to the end of the bucket
class ValueMetricProducer : public virtual MetricProducer, public virtual PullDataReceiver {
public:
ValueMetricProducer(const ConfigKey& key, const ValueMetric& valueMetric,
@@ -61,9 +68,8 @@ public:
if (!mSplitBucketForAppUpgrade) {
return;
}
- flushIfNeededLocked(eventTimeNs - 1);
if (mIsPulled && mCondition) {
- pullAndMatchEventsLocked(eventTimeNs - 1);
+ pullAndMatchEventsLocked(eventTimeNs, mCondition);
}
flushCurrentBucketLocked(eventTimeNs, eventTimeNs);
};
@@ -94,9 +100,12 @@ private:
void dumpStatesLocked(FILE* out, bool verbose) const override;
- // Util function to flush the old packet.
+ // For pulled metrics, this method should only be called if a pull has be done. Else we will
+ // not have complete data for the bucket.
void flushIfNeededLocked(const int64_t& eventTime) override;
+ // For pulled metrics, this method should only be called if a pulled have be done. Else we will
+ // not have complete data for the bucket.
void flushCurrentBucketLocked(const int64_t& eventTimeNs,
const int64_t& nextBucketStartTimeNs) override;
@@ -105,8 +114,12 @@ private:
// Calculate previous bucket end time based on current time.
int64_t calcPreviousBucketEndTime(const int64_t currentTimeNs);
+ // Calculate how many buckets are present between the current bucket and eventTimeNs.
+ int64_t calcBucketsForwardCount(const int64_t& eventTimeNs) const;
+
// Mark the data as invalid.
void invalidateCurrentBucket();
+ void invalidateCurrentBucketWithoutResetBase();
const int mWhatMatcherIndex;
@@ -163,14 +176,15 @@ private:
bool hitFullBucketGuardRailLocked(const MetricDimensionKey& newKey);
- void pullAndMatchEventsLocked(const int64_t timestampNs);
+ void pullAndMatchEventsLocked(const int64_t timestampNs, ConditionState condition);
void accumulateEvents(const std::vector<std::shared_ptr<LogEvent>>& allData,
- int64_t originalPullTimeNs, int64_t eventElapsedTimeNs);
+ int64_t originalPullTimeNs, int64_t eventElapsedTimeNs,
+ ConditionState condition);
ValueBucket buildPartialBucket(int64_t bucketEndTime,
const std::vector<Interval>& intervals);
- void initCurrentSlicedBucket();
+ void initCurrentSlicedBucket(int64_t nextBucketStartTimeNs);
void appendToFullBucket(int64_t eventTimeNs, int64_t fullBucketEndTimeNs);
// Reset diff base and mHasGlobalBase
@@ -214,47 +228,55 @@ private:
const bool mSplitBucketForAppUpgrade;
+ FRIEND_TEST(ValueMetricProducerTest, TestAnomalyDetection);
+ FRIEND_TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange);
+ FRIEND_TEST(ValueMetricProducerTest, TestBucketBoundariesOnAppUpgrade);
+ FRIEND_TEST(ValueMetricProducerTest, TestBucketBoundariesOnConditionChange);
+ FRIEND_TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition);
+ FRIEND_TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition);
+ FRIEND_TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2);
+ FRIEND_TEST(ValueMetricProducerTest, TestBucketIncludingUnknownConditionIsInvalid);
+ FRIEND_TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet);
+ FRIEND_TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime);
+ FRIEND_TEST(ValueMetricProducerTest, TestDataIsNotUpdatedWhenNoConditionChanged);
+ FRIEND_TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary);
+ FRIEND_TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged);
+ FRIEND_TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled);
+ FRIEND_TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition);
+ FRIEND_TEST(ValueMetricProducerTest, TestFirstBucket);
+ FRIEND_TEST(ValueMetricProducerTest, TestInvalidBucketWhenGuardRailHit);
+ FRIEND_TEST(ValueMetricProducerTest, TestInvalidBucketWhenInitialPullFailed);
+ FRIEND_TEST(ValueMetricProducerTest, TestInvalidBucketWhenLastPullFailed);
+ FRIEND_TEST(ValueMetricProducerTest, TestInvalidBucketWhenOneConditionFailed);
+ FRIEND_TEST(ValueMetricProducerTest, TestLateOnDataPulledWithDiff);
+ FRIEND_TEST(ValueMetricProducerTest, TestLateOnDataPulledWithoutDiff);
+ FRIEND_TEST(ValueMetricProducerTest, TestPartialBucketCreated);
+ FRIEND_TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries);
FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsNoCondition);
- FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering);
FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset);
FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset);
- FRIEND_TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition);
- FRIEND_TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade);
+ FRIEND_TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering);
FRIEND_TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade);
- FRIEND_TEST(ValueMetricProducerTest, TestPartialBucketCreated);
FRIEND_TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse);
FRIEND_TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled);
- FRIEND_TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition);
- FRIEND_TEST(ValueMetricProducerTest, TestPushedEventsWithCondition);
- FRIEND_TEST(ValueMetricProducerTest, TestAnomalyDetection);
- FRIEND_TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition);
- FRIEND_TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition);
- FRIEND_TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2);
- FRIEND_TEST(ValueMetricProducerTest, TestPushedAggregateMin);
- FRIEND_TEST(ValueMetricProducerTest, TestPushedAggregateMax);
FRIEND_TEST(ValueMetricProducerTest, TestPushedAggregateAvg);
+ FRIEND_TEST(ValueMetricProducerTest, TestPushedAggregateMax);
+ FRIEND_TEST(ValueMetricProducerTest, TestPushedAggregateMin);
FRIEND_TEST(ValueMetricProducerTest, TestPushedAggregateSum);
- FRIEND_TEST(ValueMetricProducerTest, TestFirstBucket);
- FRIEND_TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime);
+ FRIEND_TEST(ValueMetricProducerTest, TestPushedEventsWithCondition);
+ FRIEND_TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade);
+ FRIEND_TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition);
+ FRIEND_TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded);
+ FRIEND_TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange);
+ FRIEND_TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfBucket);
+ FRIEND_TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange);
+ FRIEND_TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate);
FRIEND_TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput);
FRIEND_TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue);
+ FRIEND_TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey);
FRIEND_TEST(ValueMetricProducerTest, TestUseZeroDefaultBase);
FRIEND_TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures);
- FRIEND_TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey);
- FRIEND_TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange);
- FRIEND_TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange);
- FRIEND_TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfBucket);
- FRIEND_TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate);
- FRIEND_TEST(ValueMetricProducerTest, TestInvalidBucketWhenOneConditionFailed);
- FRIEND_TEST(ValueMetricProducerTest, TestInvalidBucketWhenGuardRailHit);
- FRIEND_TEST(ValueMetricProducerTest, TestInvalidBucketWhenInitialPullFailed);
- FRIEND_TEST(ValueMetricProducerTest, TestInvalidBucketWhenLastPullFailed);
- FRIEND_TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded);
- FRIEND_TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange);
- FRIEND_TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled);
- FRIEND_TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged);
- FRIEND_TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary);
- FRIEND_TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries);
+ friend class ValueMetricProducerTestHelper;
};
} // namespace statsd
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index a9d2c8810adc..e5e453490159 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -52,15 +52,100 @@ const int64_t bucket5StartTimeNs = bucketStartTimeNs + 4 * bucketSizeNs;
const int64_t bucket6StartTimeNs = bucketStartTimeNs + 5 * bucketSizeNs;
double epsilon = 0.001;
+static void assertPastBucketValuesSingleKey(
+ const std::unordered_map<MetricDimensionKey, std::vector<ValueBucket>>& mPastBuckets,
+ const std::initializer_list<int>& expectedValuesList) {
+ std::vector<int> expectedValues(expectedValuesList);
+ if (expectedValues.size() == 0) {
+ ASSERT_EQ(0, mPastBuckets.size());
+ return;
+ }
+
+ ASSERT_EQ(1, mPastBuckets.size());
+ ASSERT_EQ(expectedValues.size(), mPastBuckets.begin()->second.size());
+
+ auto buckets = mPastBuckets.begin()->second;
+ for (int i = 0; i < expectedValues.size(); i++) {
+ EXPECT_EQ(expectedValues[i], buckets[i].values[0].long_value)
+ << "Values differ at index " << i;
+ }
+}
+
+
+class ValueMetricProducerTestHelper {
+
+ public:
+ static shared_ptr<LogEvent> createEvent(int64_t eventTimeNs, int64_t value) {
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, eventTimeNs);
+ event->write(tagId);
+ event->write(value);
+ event->write(value);
+ event->init();
+ return event;
+ }
+
+ static sp<ValueMetricProducer> createValueProducerNoConditions(
+ sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+ sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
+ kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+ logEventMatcherIndex, eventMatcherWizard, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ return valueProducer;
+ }
+
+ static sp<ValueMetricProducer> createValueProducerWithCondition(
+ sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
+ UidMap uidMap;
+ SimpleAtomMatcher atomMatcher;
+ atomMatcher.set_atom_id(tagId);
+ sp<EventMatcherWizard> eventMatcherWizard =
+ new EventMatcherWizard({new SimpleLogMatchingTracker(
+ atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+ sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+ EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+
+ sp<ValueMetricProducer> valueProducer =
+ new ValueMetricProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
+ eventMatcherWizard, tagId, bucketStartTimeNs,
+ bucketStartTimeNs, pullerManager);
+ valueProducer->mCondition = ConditionState::kFalse;
+ return valueProducer;
+ }
+
+ static ValueMetric createMetric() {
+ ValueMetric metric;
+ metric.set_id(metricId);
+ metric.set_bucket(ONE_MINUTE);
+ metric.mutable_value_field()->set_field(tagId);
+ metric.mutable_value_field()->add_child()->set_field(2);
+ metric.set_max_pull_delay_sec(INT_MAX);
+ return metric;
+ }
+
+ static ValueMetric createMetricWithCondition() {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ metric.set_condition(StringToId("SCREEN_ON"));
+ return metric;
+ }
+};
+
+
/*
* Tests that the first bucket works correctly
*/
TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
int64_t startTimeBase = 11;
UidMap uidMap;
@@ -90,11 +175,7 @@ TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) {
* Tests that the first bucket works correctly
*/
TEST(ValueMetricProducerTest, TestFirstBucket) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -120,23 +201,8 @@ TEST(ValueMetricProducerTest, TestFirstBucket) {
* Tests pulled atoms with no conditions
*/
TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_max_pull_delay_sec(INT_MAX);
-
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, Pull(tagId, _))
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
@@ -148,9 +214,8 @@ TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -160,17 +225,17 @@ TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(11, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(8, curInterval.value.long_value);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
allData.clear();
event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
@@ -178,19 +243,19 @@ TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
event->write(23);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(23, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(12, curInterval.value.long_value);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
- EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
+ EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
allData.clear();
event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
@@ -198,39 +263,24 @@ TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
event->write(36);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(36, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(13, curInterval.value.long_value);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(3UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
- EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second[1].values[0].long_value);
- EXPECT_EQ(13, valueProducer.mPastBuckets.begin()->second[2].values[0].long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(3UL, valueProducer->mPastBuckets.begin()->second.size());
+ EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
+ EXPECT_EQ(13, valueProducer->mPastBuckets.begin()->second[2].values[0].long_value);
}
TEST(ValueMetricProducerTest, TestPartialBucketCreated) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_max_pull_delay_sec(INT_MAX);
-
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
EXPECT_CALL(*pullerManager, Pull(tagId, _))
// Initialize bucket.
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
@@ -253,9 +303,8 @@ TEST(ValueMetricProducerTest, TestPartialBucketCreated) {
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
// First bucket ends.
vector<shared_ptr<LogEvent>> allData;
@@ -265,14 +314,14 @@ TEST(ValueMetricProducerTest, TestPartialBucketCreated) {
event->write(2);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** success */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, /** success */ true, bucket2StartTimeNs);
// Partial buckets created in 2nd bucket.
- valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1);
+ valueProducer->notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1);
// One full bucket and one partial bucket.
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- vector<ValueBucket> buckets = valueProducer.mPastBuckets.begin()->second;
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ vector<ValueBucket> buckets = valueProducer->mPastBuckets.begin()->second;
EXPECT_EQ(2UL, buckets.size());
// Full bucket (2 - 1)
EXPECT_EQ(1, buckets[0].values[0].long_value);
@@ -284,12 +333,7 @@ TEST(ValueMetricProducerTest, TestPartialBucketCreated) {
* Tests pulled atoms with filtering
*/
TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -315,9 +359,10 @@ TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
+ kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+ logEventMatcherIndex, eventMatcherWizard, tagId,
+ bucketStartTimeNs, bucketStartTimeNs, pullerManager);
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -327,18 +372,18 @@ TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(11, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(8, curInterval.value.long_value);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
allData.clear();
event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
@@ -346,16 +391,16 @@ TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
event->write(23);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// No new data seen, so data has been cleared.
- EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
+ EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(11, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(8, curInterval.value.long_value);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
allData.clear();
event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
@@ -363,46 +408,30 @@ TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
event->write(36);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
// the base was reset
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(36, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.begin()->second.size());
+ EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
}
/*
* Tests pulled atoms with no conditions and take absolute value after reset
*/
TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_use_absolute_value_on_reset(true);
- metric.set_max_pull_delay_sec(INT_MAX);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
-
- ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -412,15 +441,15 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(11, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
allData.clear();
event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
@@ -428,16 +457,16 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
event->write(10);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(10, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(10, curInterval.value.long_value);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
allData.clear();
event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
@@ -445,45 +474,28 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
event->write(36);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(36, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(26, curInterval.value.long_value);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
- EXPECT_EQ(26, valueProducer.mPastBuckets.begin()->second[1].values[0].long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
+ EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
}
/*
* Tests pulled atoms with no conditions and take zero value after reset
*/
TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_max_pull_delay_sec(INT_MAX);
-
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false));
-
- ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -493,15 +505,15 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(11, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
allData.clear();
event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
@@ -509,14 +521,14 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
event->write(10);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(10, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
allData.clear();
event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
@@ -524,39 +536,24 @@ TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
event->write(36);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(36, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(26, curInterval.value.long_value);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(26, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
}
/*
* Test pulled event with non sliced condition.
*/
TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_condition(StringToId("SCREEN_ON"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
EXPECT_CALL(*pullerManager, Pull(tagId, _))
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
@@ -572,25 +569,25 @@ TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
data->clear();
shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
event->write(tagId);
- event->write(120);
+ event->write(130);
event->init();
data->push_back(event);
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
// startUpdated:false sum:0 start:100
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(100, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -599,34 +596,30 @@ TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
event->write(110);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10});
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(110, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(10, curInterval.value.long_value);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
- valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
+ valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10});
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasValue);
- EXPECT_EQ(10, curInterval.value.long_value);
+ EXPECT_EQ(20, curInterval.value.long_value);
EXPECT_EQ(false, curInterval.hasBase);
}
TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -670,12 +663,7 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) {
}
TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -733,12 +721,7 @@ TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) {
}
TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_split_bucket_for_app_upgrade(false);
UidMap uidMap;
@@ -773,24 +756,9 @@ TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
}
TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_condition(StringToId("SCREEN_ON"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, Pull(tagId, _))
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
@@ -810,29 +778,25 @@ TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse) {
data->push_back(event);
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 1);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.onConditionChanged(false, bucket2StartTimeNs-100);
- EXPECT_FALSE(valueProducer.mCondition);
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
- valueProducer.notifyAppUpgrade(bucket2StartTimeNs-50, "ANY.APP", 1, 1);
+ valueProducer->onConditionChanged(false, bucket2StartTimeNs-100);
+ EXPECT_FALSE(valueProducer->mCondition);
+
+ valueProducer->notifyAppUpgrade(bucket2StartTimeNs-50, "ANY.APP", 1, 1);
// Expect one full buckets already done and starting a partial bucket.
- EXPECT_EQ(bucket2StartTimeNs-50, valueProducer.mCurrentBucketStartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
- EXPECT_EQ(bucketStartTimeNs, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
- EXPECT_EQ(20L, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].values[0].long_value);
- EXPECT_FALSE(valueProducer.mCondition);
+ EXPECT_EQ(bucket2StartTimeNs-50, valueProducer->mCurrentBucketStartTimeNs);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+ EXPECT_EQ(bucketStartTimeNs, valueProducer->mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
+ EXPECT_EQ(20L, valueProducer->mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].values[0].long_value);
+ EXPECT_FALSE(valueProducer->mCondition);
}
TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -869,18 +833,12 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(30, curInterval.value.long_value);
- valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(30, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
+ valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
+ assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {30});
}
TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -894,6 +852,7 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
pullerManager);
+ valueProducer.mCondition = ConditionState::kFalse;
shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
event1->write(1);
@@ -939,10 +898,8 @@ TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(50, curInterval.value.long_value);
- valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(50, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
+ valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
+ assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {50});
}
TEST(ValueMetricProducerTest, TestAnomalyDetection) {
@@ -955,11 +912,7 @@ TEST(ValueMetricProducerTest, TestAnomalyDetection) {
const int32_t refPeriodSec = 3;
alert.set_refractory_period_secs(refPeriodSec);
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -1036,28 +989,11 @@ TEST(ValueMetricProducerTest, TestAnomalyDetection) {
// Test value metric no condition, the pull on bucket boundary come in time and too late
TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_max_pull_delay_sec(INT_MAX);
-
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
-
- ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
vector<shared_ptr<LogEvent>> allData;
// pull 1
@@ -1068,16 +1004,16 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
// startUpdated:true sum:0 start:11
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(11, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
// pull 2 at correct time
allData.clear();
@@ -1086,16 +1022,15 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
event->write(23);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
// tartUpdated:false sum:12
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(23, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12});
// pull 3 come late.
// The previous bucket gets closed with error. (Has start value 23, no ending)
@@ -1107,16 +1042,14 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
event->write(36);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
// startUpdated:false sum:12
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(36, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(12, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12});
}
/*
@@ -1124,25 +1057,9 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
* was delivered late.
*/
TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_condition(StringToId("SCREEN_ON"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
EXPECT_CALL(*pullerManager, Pull(tagId, _))
// condition becomes true
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
@@ -1164,44 +1081,35 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
data->push_back(event);
return true;
}));
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(100, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
// pull on bucket boundary come late, condition change happens before it
- valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20});
EXPECT_EQ(false, curInterval.hasBase);
- EXPECT_EQ(true, curInterval.hasValue);
- EXPECT_EQ(20, curInterval.value.long_value);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
// Now the alarm is delivered.
// since the condition turned to off before this pull finish, it has no effect
vector<shared_ptr<LogEvent>> allData;
- allData.clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 30);
- event->write(1);
- event->write(110);
- event->init();
- allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 110));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20});
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(false, curInterval.hasBase);
- EXPECT_EQ(true, curInterval.hasValue);
- EXPECT_EQ(20, curInterval.value.long_value);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(false, curInterval.hasValue);
}
/*
@@ -1209,25 +1117,9 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
* change to false, and then true again. This is due to alarm delivered late.
*/
TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_condition(StringToId("SCREEN_ON"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillRepeatedly(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
EXPECT_CALL(*pullerManager, Pull(tagId, _))
// condition becomes true
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
@@ -1260,61 +1152,57 @@ TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
// startUpdated:false sum:0 start:100
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(100, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
// pull on bucket boundary come late, condition change happens before it
- valueProducer.onConditionChanged(false, bucket2StartTimeNs + 1);
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20});
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(false, curInterval.hasBase);
- EXPECT_EQ(true, curInterval.hasValue);
- EXPECT_EQ(20, curInterval.value.long_value);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(false, curInterval.hasValue);
// condition changed to true again, before the pull alarm is delivered
- valueProducer.onConditionChanged(true, bucket2StartTimeNs + 25);
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->onConditionChanged(true, bucket2StartTimeNs + 25);
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20});
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(130, curInterval.base.long_value);
- EXPECT_EQ(true, curInterval.hasValue);
- EXPECT_EQ(20, curInterval.value.long_value);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(false, curInterval.hasValue);
- // Now the alarm is delivered, but it is considered late, the bucket is invalidated.
+ // Now the alarm is delivered, but it is considered late, the data will be used
+ // for the new bucket since it was just pulled.
vector<shared_ptr<LogEvent>> allData;
- allData.clear();
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 50);
- event->write(1);
- event->write(110);
- event->init();
- allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 50, 140));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 50);
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
- EXPECT_EQ(false, curInterval.hasBase);
- EXPECT_EQ(130, curInterval.base.long_value);
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(140, curInterval.base.long_value);
EXPECT_EQ(true, curInterval.hasValue);
- EXPECT_EQ(20, curInterval.value.long_value);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(10, curInterval.value.long_value);
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20});
+
+ allData.clear();
+ allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs, 160));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20, 30});
}
TEST(ValueMetricProducerTest, TestPushedAggregateMin) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_aggregation_type(ValueMetric::MIN);
UidMap uidMap;
@@ -1352,18 +1240,12 @@ TEST(ValueMetricProducerTest, TestPushedAggregateMin) {
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(10, curInterval.value.long_value);
- valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(10, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
+ valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
+ assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {10});
}
TEST(ValueMetricProducerTest, TestPushedAggregateMax) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_aggregation_type(ValueMetric::MAX);
UidMap uidMap;
@@ -1402,17 +1284,13 @@ TEST(ValueMetricProducerTest, TestPushedAggregateMax) {
EXPECT_EQ(20, curInterval.value.long_value);
valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(20, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
+ /* EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); */
+ /* EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size()); */
+ /* EXPECT_EQ(20, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value); */
}
TEST(ValueMetricProducerTest, TestPushedAggregateAvg) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_aggregation_type(ValueMetric::AVG);
UidMap uidMap;
@@ -1453,18 +1331,14 @@ TEST(ValueMetricProducerTest, TestPushedAggregateAvg) {
EXPECT_EQ(25, curInterval.value.long_value);
EXPECT_EQ(2, curInterval.sampleSize);
- valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
+ valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
EXPECT_TRUE(std::abs(valueProducer.mPastBuckets.begin()->second.back().values[0].double_value - 12.5) < epsilon);
}
TEST(ValueMetricProducerTest, TestPushedAggregateSum) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_aggregation_type(ValueMetric::SUM);
UidMap uidMap;
@@ -1502,18 +1376,12 @@ TEST(ValueMetricProducerTest, TestPushedAggregateSum) {
curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(25, curInterval.value.long_value);
- valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
- EXPECT_EQ(25, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value);
+ valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
+ assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {25});
}
TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_aggregation_type(ValueMetric::MIN);
metric.set_use_diff(true);
@@ -1584,11 +1452,7 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
}
TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.mutable_value_field()->add_child()->set_field(3);
metric.set_aggregation_type(ValueMetric::MIN);
metric.set_use_diff(true);
@@ -1694,26 +1558,12 @@ TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
* Tests zero default base.
*/
TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.mutable_dimensions_in_what()->set_field(tagId);
metric.mutable_dimensions_in_what()->add_child()->set_field(1);
metric.set_use_zero_default_base(true);
- metric.set_max_pull_delay_sec(INT_MAX);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, Pull(tagId, _))
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
@@ -1725,19 +1575,18 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) {
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- auto iter = valueProducer.mCurrentSlicedBucket.begin();
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ auto iter = valueProducer->mCurrentSlicedBucket.begin();
auto& interval1 = iter->second[0];
EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
EXPECT_EQ(true, interval1.hasBase);
EXPECT_EQ(3, interval1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
- EXPECT_EQ(true, valueProducer.mHasGlobalBase);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -1752,15 +1601,15 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) {
allData.push_back(event1);
allData.push_back(event2);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size());
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
EXPECT_EQ(true, interval1.hasBase);
EXPECT_EQ(11, interval1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
EXPECT_EQ(8, interval1.value.long_value);
- auto it = valueProducer.mCurrentSlicedBucket.begin();
- for (; it != valueProducer.mCurrentSlicedBucket.end(); it++) {
+ auto it = valueProducer->mCurrentSlicedBucket.begin();
+ for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
if (it != iter) {
break;
}
@@ -1773,8 +1622,8 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) {
EXPECT_EQ(false, interval2.hasValue);
EXPECT_EQ(4, interval2.value.long_value);
- EXPECT_EQ(2UL, valueProducer.mPastBuckets.size());
- auto iterator = valueProducer.mPastBuckets.begin();
+ EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
+ auto iterator = valueProducer->mPastBuckets.begin();
EXPECT_EQ(8, iterator->second[0].values[0].long_value);
iterator++;
EXPECT_EQ(4, iterator->second[0].values[0].long_value);
@@ -1784,26 +1633,12 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) {
* Tests using zero default base with failed pull.
*/
TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.mutable_dimensions_in_what()->set_field(tagId);
metric.mutable_dimensions_in_what()->add_child()->set_field(1);
metric.set_use_zero_default_base(true);
- metric.set_max_pull_delay_sec(INT_MAX);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, Pull(tagId, _))
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
@@ -1815,19 +1650,18 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- auto iter = valueProducer.mCurrentSlicedBucket.begin();
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ auto iter = valueProducer->mCurrentSlicedBucket.begin();
auto& interval1 = iter->second[0];
EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
EXPECT_EQ(true, interval1.hasBase);
EXPECT_EQ(3, interval1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
- EXPECT_EQ(true, valueProducer.mHasGlobalBase);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -1842,15 +1676,15 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
allData.push_back(event1);
allData.push_back(event2);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size());
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
EXPECT_EQ(true, interval1.hasBase);
EXPECT_EQ(11, interval1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
EXPECT_EQ(8, interval1.value.long_value);
- auto it = valueProducer.mCurrentSlicedBucket.begin();
- for (; it != valueProducer.mCurrentSlicedBucket.end(); it++) {
+ auto it = valueProducer->mCurrentSlicedBucket.begin();
+ for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
if (it != iter) {
break;
}
@@ -1862,7 +1696,7 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
EXPECT_EQ(4, interval2.base.long_value);
EXPECT_EQ(false, interval2.hasValue);
EXPECT_EQ(4, interval2.value.long_value);
- EXPECT_EQ(2UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
// next pull somehow did not happen, skip to end of bucket 3
allData.clear();
@@ -1871,16 +1705,14 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
event1->write(5);
event1->init();
allData.push_back(event1);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
EXPECT_EQ(true, interval2.hasBase);
- EXPECT_EQ(4, interval2.base.long_value);
+ EXPECT_EQ(5, interval2.base.long_value);
EXPECT_EQ(false, interval2.hasValue);
- EXPECT_EQ(true, interval1.hasBase);
- EXPECT_EQ(false, interval1.hasValue);
- EXPECT_EQ(true, valueProducer.mHasGlobalBase);
- EXPECT_EQ(2UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+ EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
allData.clear();
event1 = make_shared<LogEvent>(tagId, bucket5StartTimeNs + 1);
@@ -1893,44 +1725,32 @@ TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
event2->write(5);
event2->init();
allData.push_back(event2);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
-
- EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size());
- EXPECT_EQ(true, interval2.hasBase);
- EXPECT_EQ(5, interval2.base.long_value);
- EXPECT_EQ(false, interval2.hasValue);
- EXPECT_EQ(5, interval2.value.long_value);
- EXPECT_EQ(true, interval1.hasBase);
- EXPECT_EQ(13, interval1.base.long_value);
- EXPECT_EQ(false, interval1.hasValue);
- EXPECT_EQ(8, interval1.value.long_value);
- EXPECT_EQ(true, valueProducer.mHasGlobalBase);
- EXPECT_EQ(2UL, valueProducer.mPastBuckets.size());
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
+
+ EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+ auto it1 = std::next(valueProducer->mCurrentSlicedBucket.begin())->second[0];
+ EXPECT_EQ(true, it1.hasBase);
+ EXPECT_EQ(13, it1.base.long_value);
+ EXPECT_EQ(false, it1.hasValue);
+ EXPECT_EQ(8, it1.value.long_value);
+ auto it2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(true, it2.hasBase);
+ EXPECT_EQ(5, it2.base.long_value);
+ EXPECT_EQ(false, it2.hasValue);
+ EXPECT_EQ(5, it2.value.long_value);
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+ EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
}
/*
* Tests trim unused dimension key if no new data is seen in an entire bucket.
*/
TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.mutable_dimensions_in_what()->set_field(tagId);
metric.mutable_dimensions_in_what()->add_child()->set_field(1);
- metric.set_max_pull_delay_sec(INT_MAX);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
EXPECT_CALL(*pullerManager, Pull(tagId, _))
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
@@ -1942,18 +1762,17 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- auto iter = valueProducer.mCurrentSlicedBucket.begin();
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ auto iter = valueProducer->mCurrentSlicedBucket.begin();
auto& interval1 = iter->second[0];
EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
EXPECT_EQ(true, interval1.hasBase);
EXPECT_EQ(3, interval1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
vector<shared_ptr<LogEvent>> allData;
allData.clear();
@@ -1968,18 +1787,17 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
allData.push_back(event1);
allData.push_back(event2);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size());
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
EXPECT_EQ(true, interval1.hasBase);
EXPECT_EQ(11, interval1.base.long_value);
EXPECT_EQ(false, interval1.hasValue);
EXPECT_EQ(8, interval1.value.long_value);
EXPECT_FALSE(interval1.seenNewData);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(8, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8});
- auto it = valueProducer.mCurrentSlicedBucket.begin();
- for (; it != valueProducer.mCurrentSlicedBucket.end(); it++) {
+ auto it = valueProducer->mCurrentSlicedBucket.begin();
+ for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
if (it != iter) {
break;
}
@@ -1991,7 +1809,7 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
EXPECT_EQ(4, interval2.base.long_value);
EXPECT_EQ(false, interval2.hasValue);
EXPECT_FALSE(interval2.seenNewData);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8});
// next pull somehow did not happen, skip to end of bucket 3
allData.clear();
@@ -2000,17 +1818,16 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
event1->write(5);
event1->init();
allData.push_back(event1);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
-
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
// Only one interval left. One was trimmed.
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- interval2 = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
EXPECT_EQ(true, interval2.hasBase);
EXPECT_EQ(5, interval2.base.long_value);
EXPECT_EQ(false, interval2.hasValue);
EXPECT_FALSE(interval2.seenNewData);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8});
allData.clear();
event1 = make_shared<LogEvent>(tagId, bucket5StartTimeNs + 1);
@@ -2018,40 +1835,24 @@ TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
event1->write(14);
event1->init();
allData.push_back(event1);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
- interval2 = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, interval2.hasBase);
EXPECT_EQ(14, interval2.base.long_value);
EXPECT_EQ(false, interval2.hasValue);
EXPECT_FALSE(interval2.seenNewData);
- EXPECT_EQ(2UL, valueProducer.mPastBuckets.size());
- auto iterator = valueProducer.mPastBuckets.begin();
+ ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
+ auto iterator = valueProducer->mPastBuckets.begin();
EXPECT_EQ(9, iterator->second[0].values[0].long_value);
iterator++;
EXPECT_EQ(8, iterator->second[0].values[0].long_value);
}
TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfBucket) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_condition(StringToId("SCREEN_ON"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
// Used by onConditionChanged.
EXPECT_CALL(*pullerManager, Pull(tagId, _))
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
@@ -2064,47 +1865,30 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfB
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(100, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
vector<shared_ptr<LogEvent>> allData;
- valueProducer.onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
EXPECT_EQ(false, curInterval.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(false, valueProducer.mHasGlobalBase);
+ EXPECT_EQ(false, valueProducer->mHasGlobalBase);
}
TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_condition(StringToId("SCREEN_ON"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
EXPECT_CALL(*pullerManager, Pull(tagId, _))
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
@@ -2117,50 +1901,33 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange) {
}))
.WillOnce(Return(false));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 8);
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(100, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
- valueProducer.onConditionChanged(false, bucketStartTimeNs + 20);
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 20);
// has one slice
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
EXPECT_EQ(false, curInterval.hasValue);
EXPECT_EQ(false, curInterval.hasBase);
- EXPECT_EQ(false, valueProducer.mHasGlobalBase);
+ EXPECT_EQ(false, valueProducer->mHasGlobalBase);
}
TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_condition(StringToId("SCREEN_ON"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
EXPECT_CALL(*pullerManager, Pull(tagId, _))
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
@@ -2172,45 +1939,30 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange) {
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.mCondition = ConditionState::kTrue;
+ valueProducer->mCondition = ConditionState::kTrue;
vector<shared_ptr<LogEvent>> allData;
- valueProducer.onDataPulled(allData, /** succeed */ false, bucketStartTimeNs);
- EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
+ valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs);
+ EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
- valueProducer.onConditionChanged(false, bucketStartTimeNs + 1);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 1);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(false, curInterval.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(false, valueProducer.mHasGlobalBase);
+ EXPECT_EQ(false, valueProducer->mHasGlobalBase);
}
TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.set_condition(StringToId("SCREEN_ON"));
metric.set_max_pull_delay_sec(0);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
EXPECT_CALL(*pullerManager, Pull(tagId, _))
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
@@ -2222,25 +1974,18 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) {
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.mCondition = ConditionState::kFalse;
+ valueProducer->mCondition = ConditionState::kFalse;
// Max delay is set to 0 so pull will exceed max delay.
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 1);
- EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
+ EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
}
TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_condition(StringToId("SCREEN_ON"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -2266,24 +2011,9 @@ TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) {
}
TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_condition(StringToId("SCREEN_ON"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
EXPECT_CALL(*pullerManager, Pull(tagId, _))
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
data->clear();
@@ -2295,44 +2025,27 @@ TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange) {
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.mCondition = ConditionState::kFalse;
- valueProducer.mHasGlobalBase = false;
+ valueProducer->mCondition = ConditionState::kFalse;
+ valueProducer->mHasGlobalBase = false;
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 1);
- valueProducer.mHasGlobalBase = true;
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
+ valueProducer->mHasGlobalBase = true;
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(100, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(true, valueProducer.mHasGlobalBase);
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
}
TEST(ValueMetricProducerTest, TestInvalidBucketWhenOneConditionFailed) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_condition(StringToId("SCREEN_ON"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
EXPECT_CALL(*pullerManager, Pull(tagId, _))
// First onConditionChanged
.WillOnce(Return(false))
@@ -2347,11 +2060,10 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenOneConditionFailed) {
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.mCondition = ConditionState::kTrue;
+ valueProducer->mCondition = ConditionState::kTrue;
// Bucket start.
vector<shared_ptr<LogEvent>> allData;
@@ -2361,12 +2073,12 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenOneConditionFailed) {
event->write(110);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
// This will fail and should invalidate the whole bucket since we do not have all the data
// needed to compute the metric value when the screen was on.
- valueProducer.onConditionChanged(false, bucketStartTimeNs + 2);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 3);
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
// Bucket end.
allData.clear();
@@ -2375,48 +2087,33 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenOneConditionFailed) {
event2->write(140);
event2->init();
allData.push_back(event2);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+
+ valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
- valueProducer.flushIfNeededLocked(bucket2StartTimeNs + 1);
-
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
// Contains base from last pull which was successful.
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(140, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(true, valueProducer.mHasGlobalBase);
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
}
TEST(ValueMetricProducerTest, TestInvalidBucketWhenGuardRailHit) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.mutable_dimensions_in_what()->set_field(tagId);
metric.mutable_dimensions_in_what()->add_child()->set_field(1);
metric.set_condition(StringToId("SCREEN_ON"));
- metric.set_max_pull_delay_sec(INT_MAX);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
EXPECT_CALL(*pullerManager, Pull(tagId, _))
// First onConditionChanged
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
for (int i = 0; i < 2000; i++) {
- shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
event->write(i);
event->write(i);
event->init();
@@ -2425,36 +2122,19 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenGuardRailHit) {
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+ valueProducer->mCondition = ConditionState::kFalse;
- valueProducer.mCondition = ConditionState::kFalse;
- valueProducer.onConditionChanged(true, bucket2StartTimeNs + 2);
- EXPECT_EQ(true, valueProducer.mCurrentBucketIsInvalid);
- EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 2);
+ EXPECT_EQ(true, valueProducer->mCurrentBucketIsInvalid);
+ EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
}
TEST(ValueMetricProducerTest, TestInvalidBucketWhenInitialPullFailed) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_condition(StringToId("SCREEN_ON"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
EXPECT_CALL(*pullerManager, Pull(tagId, _))
// First onConditionChanged
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
@@ -2477,11 +2157,10 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenInitialPullFailed) {
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.mCondition = ConditionState::kTrue;
+ valueProducer->mCondition = ConditionState::kTrue;
// Bucket start.
vector<shared_ptr<LogEvent>> allData;
@@ -2491,10 +2170,10 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenInitialPullFailed) {
event->write(110);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ false, bucketStartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs);
- valueProducer.onConditionChanged(false, bucketStartTimeNs + 2);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 3);
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
// Bucket end.
allData.clear();
@@ -2503,41 +2182,25 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenInitialPullFailed) {
event2->write(140);
event2->init();
allData.push_back(event2);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+
+ valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
- valueProducer.flushIfNeededLocked(bucket2StartTimeNs + 1);
-
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
// Contains base from last pull which was successful.
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(140, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(true, valueProducer.mHasGlobalBase);
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
}
TEST(ValueMetricProducerTest, TestInvalidBucketWhenLastPullFailed) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_condition(StringToId("SCREEN_ON"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
EXPECT_CALL(*pullerManager, Pull(tagId, _))
// First onConditionChanged
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
@@ -2560,11 +2223,10 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenLastPullFailed) {
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.mCondition = ConditionState::kTrue;
+ valueProducer->mCondition = ConditionState::kTrue;
// Bucket start.
vector<shared_ptr<LogEvent>> allData;
@@ -2574,12 +2236,12 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenLastPullFailed) {
event->write(110);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
// This will fail and should invalidate the whole bucket since we do not have all the data
// needed to compute the metric value when the screen was on.
- valueProducer.onConditionChanged(false, bucketStartTimeNs + 2);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 3);
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
// Bucket end.
allData.clear();
@@ -2588,39 +2250,23 @@ TEST(ValueMetricProducerTest, TestInvalidBucketWhenLastPullFailed) {
event2->write(140);
event2->init();
allData.push_back(event2);
- valueProducer.onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
- valueProducer.flushIfNeededLocked(bucket2StartTimeNs + 1);
-
- EXPECT_EQ(0UL, valueProducer.mPastBuckets.size());
+ valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
+
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
// Last pull failed so based has been reset.
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(false, curInterval.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(false, valueProducer.mHasGlobalBase);
+ EXPECT_EQ(false, valueProducer->mHasGlobalBase);
}
TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_max_pull_delay_sec(INT_MAX);
-
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
EXPECT_CALL(*pullerManager, Pull(tagId, _))
// Start bucket.
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
@@ -2633,9 +2279,8 @@ TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
- logEventMatcherIndex, eventMatcherWizard, tagId,
- bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
// Bucket 2 start.
vector<shared_ptr<LogEvent>> allData;
@@ -2645,41 +2290,25 @@ TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
event->write(110);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
// Bucket 3 empty.
allData.clear();
shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
event2->init();
allData.push_back(event2);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
// Data has been trimmed.
- EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+ EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
}
TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_condition(StringToId("SCREEN_ON"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
EXPECT_CALL(*pullerManager, Pull(tagId, _))
// First onConditionChanged
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
@@ -2696,47 +2325,30 @@ TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) {
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 10);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(true, valueProducer.mHasGlobalBase);
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
// Empty pull.
- valueProducer.onConditionChanged(false, bucketStartTimeNs + 10);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(false, curInterval.hasBase);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(false, valueProducer.mHasGlobalBase);
+ EXPECT_EQ(false, valueProducer->mHasGlobalBase);
}
TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_condition(StringToId("SCREEN_ON"));
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
EXPECT_CALL(*pullerManager, Pull(tagId, _))
// First onConditionChanged
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
@@ -2767,58 +2379,42 @@ TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) {
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 10);
- valueProducer.onConditionChanged(false, bucketStartTimeNs + 11);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 12);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 11);
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 12);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
ValueMetricProducer::Interval& curInterval =
- valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->mCurrentSlicedBucket.begin()->second[0];
EXPECT_EQ(true, curInterval.hasBase);
EXPECT_EQ(true, curInterval.hasValue);
- EXPECT_EQ(true, valueProducer.mHasGlobalBase);
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
// End of bucket
vector<shared_ptr<LogEvent>> allData;
allData.clear();
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
- curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
// Data is empty, base should be reset.
EXPECT_EQ(false, curInterval.hasBase);
EXPECT_EQ(5, curInterval.base.long_value);
EXPECT_EQ(false, curInterval.hasValue);
- EXPECT_EQ(true, valueProducer.mHasGlobalBase);
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
- EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
- EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
+ EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+ EXPECT_EQ(1, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
}
TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
metric.mutable_dimensions_in_what()->set_field(tagId);
metric.mutable_dimensions_in_what()->add_child()->set_field(1);
metric.set_condition(StringToId("SCREEN_ON"));
- metric.set_max_pull_delay_sec(INT_MAX);
- UidMap uidMap;
- SimpleAtomMatcher atomMatcher;
- atomMatcher.set_atom_id(tagId);
- sp<EventMatcherWizard> eventMatcherWizard =
- new EventMatcherWizard({new SimpleLogMatchingTracker(
- atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
- sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
- EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
- EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
EXPECT_CALL(*pullerManager, Pull(tagId, _))
// First onConditionChanged
.WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
@@ -2832,12 +2428,11 @@ TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) {
return true;
}));
- ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
- eventMatcherWizard, tagId, bucketStartTimeNs,
- bucketStartTimeNs, pullerManager);
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
- valueProducer.onConditionChanged(true, bucketStartTimeNs + 10);
- EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
// End of bucket
vector<shared_ptr<LogEvent>> allData;
@@ -2847,11 +2442,11 @@ TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) {
event->write(2);
event->init();
allData.push_back(event);
- valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
// Key 1 should be reset since in not present in the most pull.
- EXPECT_EQ(2UL, valueProducer.mCurrentSlicedBucket.size());
- auto iterator = valueProducer.mCurrentSlicedBucket.begin();
+ EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+ auto iterator = valueProducer->mCurrentSlicedBucket.begin();
EXPECT_EQ(true, iterator->second[0].hasBase);
EXPECT_EQ(2, iterator->second[0].base.long_value);
EXPECT_EQ(false, iterator->second[0].hasValue);
@@ -2860,7 +2455,244 @@ TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) {
EXPECT_EQ(1, iterator->second[0].base.long_value);
EXPECT_EQ(false, iterator->second[0].hasValue);
- EXPECT_EQ(true, valueProducer.mHasGlobalBase);
+ EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+}
+
+TEST(ValueMetricProducerTest, TestBucketIncludingUnknownConditionIsInvalid) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ metric.mutable_dimensions_in_what()->set_field(tagId);
+ metric.mutable_dimensions_in_what()->add_child()->set_field(1);
+ metric.set_condition(StringToId("SCREEN_ON"));
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Second onConditionChanged.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+ event->write(tagId);
+ event->write(2);
+ event->write(2);
+ event->init();
+ data->push_back(event);
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+ valueProducer->mCondition = ConditionState::kUnknown;
+
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 20);
+
+ // End of bucket
+ vector<shared_ptr<LogEvent>> allData;
+ allData.clear();
+ shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+ event->write(4);
+ event->write(4);
+ event->init();
+ allData.push_back(event);
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+
+ // Bucket is incomplete so it is mark as invalid, however the base is fine since the last pull
+ // succeeded.
+ EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+}
+
+TEST(ValueMetricProducerTest, TestBucketBoundariesOnConditionChange) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Second onConditionChanged.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 10, 5));
+ return true;
+ }))
+ // Third onConditionChanged.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs + 10, 7));
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+ valueProducer->mCondition = ConditionState::kUnknown;
+
+ valueProducer->onConditionChanged(false, bucketStartTimeNs);
+ ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+
+ // End of first bucket
+ vector<shared_ptr<LogEvent>> allData;
+ allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 1, 4));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1);
+ ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+
+ valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
+ ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(true, curInterval.hasBase);
+ EXPECT_EQ(5, curInterval.base.long_value);
+ EXPECT_EQ(false, curInterval.hasValue);
+
+ valueProducer->onConditionChanged(false, bucket3StartTimeNs + 10);
+
+ // Bucket should have been completed.
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2});
+}
+
+TEST(ValueMetricProducerTest, TestLateOnDataPulledWithoutDiff) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+ metric.set_use_diff(false);
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+
+ vector<shared_ptr<LogEvent>> allData;
+ allData.push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30);
+
+ allData.clear();
+ allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 20));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+
+ // Bucket should have been completed.
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30});
+}
+
+TEST(ValueMetricProducerTest, TestLateOnDataPulledWithDiff) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Initialization.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+
+ vector<shared_ptr<LogEvent>> allData;
+ allData.push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30);
+
+ allData.clear();
+ allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 20));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+
+ // Bucket should have been completed.
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {19});
+}
+
+TEST(ValueMetricProducerTest, TestBucketBoundariesOnAppUpgrade) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // Initialization.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
+ return true;
+ }))
+ // notifyAppUpgrade.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 2, 10));
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+
+ valueProducer->notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1);
+
+ // Bucket should have been completed.
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {9});
+}
+
+TEST(ValueMetricProducerTest, TestDataIsNotUpdatedWhenNoConditionChanged) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // First on condition changed.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
+ return true;
+ }))
+ // Second on condition changed.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 3));
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+
+ valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
+ valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
+
+ EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+ auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+ EXPECT_EQ(true, curInterval.hasValue);
+ EXPECT_EQ(2, curInterval.value.long_value);
+}
+
+TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) {
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+
+ sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+ EXPECT_CALL(*pullerManager, Pull(tagId, _))
+ // First condition change.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
+ return true;
+ }))
+ // 2nd condition change.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 1));
+ return true;
+ }))
+ // 3rd condition change.
+ .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+ data->clear();
+ data->push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 1));
+ return true;
+ }));
+
+ sp<ValueMetricProducer> valueProducer =
+ ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+ valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
+
+ vector<shared_ptr<LogEvent>> allData;
+ allData.push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 3, 10));
+ valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs + 3);
+
+ allData.clear();
+ allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 20));
+ valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
+
+ valueProducer->onConditionChanged(false, bucket2StartTimeNs + 8);
+ valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
+
+ allData.clear();
+ allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs, 30));
+ valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+
+ // There was not global base available so all buckets are invalid.
+ assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {});
}
static StatsLogReport outputStreamToProto(ProtoOutputStream* proto) {
@@ -2881,12 +2713,7 @@ static StatsLogReport outputStreamToProto(ProtoOutputStream* proto) {
}
TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -2918,7 +2745,7 @@ TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
ProtoOutputStream output;
std::set<string> strSet;
- valueProducer.onDumpReport(bucketStartTimeNs + 10,
+ valueProducer.onDumpReport(bucketStartTimeNs + 10,
true /* include recent buckets */, true,
FAST, &strSet, &output);
@@ -2928,12 +2755,7 @@ TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
}
TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -2975,7 +2797,7 @@ TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
ProtoOutputStream output;
std::set<string> strSet;
- valueProducer.onDumpReport(bucket4StartTimeNs,
+ valueProducer.onDumpReport(bucket4StartTimeNs,
false /* include recent buckets */, true,
FAST, &strSet, &output);
@@ -2986,12 +2808,7 @@ TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
}
TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) {
- ValueMetric metric;
- metric.set_id(metricId);
- metric.set_bucket(ONE_MINUTE);
- metric.mutable_value_field()->set_field(tagId);
- metric.mutable_value_field()->add_child()->set_field(2);
- metric.set_max_pull_delay_sec(INT_MAX);
+ ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
UidMap uidMap;
SimpleAtomMatcher atomMatcher;
@@ -3033,7 +2850,7 @@ TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) {
ProtoOutputStream output;
std::set<string> strSet;
- valueProducer.onDumpReport(bucketStartTimeNs + 10,
+ valueProducer.onDumpReport(bucketStartTimeNs + 10,
true /* include recent buckets */, true,
NO_TIME_CONSTRAINTS, &strSet, &output);
diff --git a/cmds/svc/src/com/android/commands/svc/Svc.java b/cmds/svc/src/com/android/commands/svc/Svc.java
index 62225df0d6ae..68fb8e694e6f 100644
--- a/cmds/svc/src/com/android/commands/svc/Svc.java
+++ b/cmds/svc/src/com/android/commands/svc/Svc.java
@@ -98,5 +98,6 @@ public class Svc {
new UsbCommand(),
new NfcCommand(),
new BluetoothCommand(),
+ new SystemServerCommand(),
};
}
diff --git a/cmds/svc/src/com/android/commands/svc/SystemServerCommand.java b/cmds/svc/src/com/android/commands/svc/SystemServerCommand.java
new file mode 100644
index 000000000000..b9104d169fa6
--- /dev/null
+++ b/cmds/svc/src/com/android/commands/svc/SystemServerCommand.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.commands.svc;
+
+import android.app.ActivityManager;
+import android.os.ParcelFileDescriptor;
+
+import java.io.FileInputStream;
+
+public class SystemServerCommand extends Svc.Command {
+ public SystemServerCommand() {
+ super("system-server");
+ }
+
+ @Override
+ public String shortHelp() {
+ return "System server process related command";
+ }
+
+ @Override
+ public String longHelp() {
+ return shortHelp() + "\n"
+ + "\n"
+ + "usage: system-server wait-for-crash\n"
+ + " Wait until the system server process crashes.\n\n";
+ }
+
+ private void waitForCrash() throws Exception {
+ ParcelFileDescriptor fd = ActivityManager.getService().getLifeMonitor();
+ if (fd == null) {
+ System.err.println("Unable to get life monitor.");
+ return;
+ }
+ System.out.println("Waiting for the system server process to die...");
+ new FileInputStream(fd.getFileDescriptor()).read();
+ }
+
+ @Override
+ public void run(String[] args) {
+ try {
+ if (args.length > 1) {
+ switch (args[1]) {
+ case "wait-for-crash":
+ waitForCrash();
+ return;
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ System.err.println(longHelp());
+ }
+}
diff --git a/config/boot-image-profile.txt b/config/boot-image-profile.txt
index 0a26bfb49bf7..d2535c9ba8ee 100644
--- a/config/boot-image-profile.txt
+++ b/config/boot-image-profile.txt
@@ -32983,7 +32983,7 @@ HSPLandroid/view/IWindowSession$Stub$Proxy;->getDisplayFrame(Landroid/view/IWind
HSPLandroid/view/IWindowSession$Stub$Proxy;->getInTouchMode()Z
HSPLandroid/view/IWindowSession$Stub$Proxy;->getWindowId(Landroid/os/IBinder;)Landroid/view/IWindowId;
HSPLandroid/view/IWindowSession$Stub$Proxy;->onRectangleOnScreenRequested(Landroid/os/IBinder;Landroid/graphics/Rect;)V
-HSPLandroid/view/IWindowSession$Stub$Proxy;->performHapticFeedback(Landroid/view/IWindow;IZ)Z
+HSPLandroid/view/IWindowSession$Stub$Proxy;->performHapticFeedback(IZ)Z
HSPLandroid/view/IWindowSession$Stub$Proxy;->pokeDrawLock(Landroid/os/IBinder;)V
HSPLandroid/view/IWindowSession$Stub$Proxy;->relayout(Landroid/view/IWindow;ILandroid/view/WindowManager$LayoutParams;IIIIJLandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/view/DisplayCutout$ParcelableWrapper;Landroid/util/MergedConfiguration;Landroid/view/Surface;)I
HSPLandroid/view/IWindowSession$Stub$Proxy;->remove(Landroid/view/IWindow;)V
@@ -33007,7 +33007,7 @@ HSPLandroid/view/IWindowSession;->getWindowId(Landroid/os/IBinder;)Landroid/view
HSPLandroid/view/IWindowSession;->onRectangleOnScreenRequested(Landroid/os/IBinder;Landroid/graphics/Rect;)V
HSPLandroid/view/IWindowSession;->outOfMemory(Landroid/view/IWindow;)Z
HSPLandroid/view/IWindowSession;->performDrag(Landroid/view/IWindow;ILandroid/view/SurfaceControl;IFFFFLandroid/content/ClipData;)Landroid/os/IBinder;
-HSPLandroid/view/IWindowSession;->performHapticFeedback(Landroid/view/IWindow;IZ)Z
+HSPLandroid/view/IWindowSession;->performHapticFeedback(IZ)Z
HSPLandroid/view/IWindowSession;->pokeDrawLock(Landroid/os/IBinder;)V
HSPLandroid/view/IWindowSession;->prepareToReplaceWindows(Landroid/os/IBinder;Z)V
HSPLandroid/view/IWindowSession;->relayout(Landroid/view/IWindow;ILandroid/view/WindowManager$LayoutParams;IIIIJLandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/view/DisplayCutout$ParcelableWrapper;Landroid/util/MergedConfiguration;Landroid/view/Surface;)I
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index a836e8ef202f..e25f463a9442 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -688,7 +688,6 @@ Landroid/os/Build$VERSION;->ACTIVE_CODENAMES:[Ljava/lang/String;
Landroid/os/Build;->getLong(Ljava/lang/String;)J
Landroid/os/Build;->getString(Ljava/lang/String;)Ljava/lang/String;
Landroid/os/Build;->IS_DEBUGGABLE:Z
-Landroid/os/Build;->IS_EMULATOR:Z
Landroid/os/Bundle;->filterValues()Landroid/os/Bundle;
Landroid/os/Bundle;->forPair(Ljava/lang/String;Ljava/lang/String;)Landroid/os/Bundle;
Landroid/os/Bundle;->getIBinder(Ljava/lang/String;)Landroid/os/IBinder;
@@ -1524,7 +1523,7 @@ Landroid/view/IWindowSession$Stub;->asInterface(Landroid/os/IBinder;)Landroid/vi
Landroid/view/IWindowSession;->finishDrawing(Landroid/view/IWindow;)V
Landroid/view/IWindowSession;->getInTouchMode()Z
Landroid/view/IWindowSession;->performDrag(Landroid/view/IWindow;ILandroid/view/SurfaceControl;IFFFFLandroid/content/ClipData;)Landroid/os/IBinder;
-Landroid/view/IWindowSession;->performHapticFeedback(Landroid/view/IWindow;IZ)Z
+Landroid/view/IWindowSession;->performHapticFeedback(IZ)Z
Landroid/view/IWindowSession;->remove(Landroid/view/IWindow;)V
Landroid/view/IWindowSession;->setInTouchMode(Z)V
Landroid/view/IWindowSession;->setTransparentRegion(Landroid/view/IWindow;Landroid/graphics/Region;)V
@@ -2910,15 +2909,8 @@ Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->logd(Ljava/lang/S
Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->loge(Ljava/lang/String;)V
Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mAdnCache:Lcom/android/internal/telephony/uicc/AdnRecordCache;
Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mBaseHandler:Landroid/os/Handler;
-Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mCurrentApp:Lcom/android/internal/telephony/uicc/UiccCardApplication;
-Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mIs3gCard:Z
-Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mLock:Ljava/lang/Object;
Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mPhone:Lcom/android/internal/telephony/Phone;
-Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mRecords:Ljava/util/List;
-Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mRecordSize:[I
-Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->mSuccess:Z
Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->updateEfForIccType(I)I
-Lcom/android/internal/telephony/IccPhoneBookInterfaceManager;->waitForResult(Ljava/util/concurrent/atomic/AtomicBoolean;)V
Lcom/android/internal/telephony/IccProvider;-><init>()V
Lcom/android/internal/telephony/IccProvider;->ADDRESS_BOOK_COLUMN_NAMES:[Ljava/lang/String;
Lcom/android/internal/telephony/IccProvider;->DBG:Z
@@ -3107,10 +3099,6 @@ Lcom/android/internal/telephony/ISms$Stub;-><init>()V
Lcom/android/internal/telephony/ISms$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ISms;
Lcom/android/internal/telephony/ISub$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Lcom/android/internal/telephony/ISub$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ISub;
-Lcom/android/internal/telephony/ISub;->getActiveSubIdList()[I
-Lcom/android/internal/telephony/ISub;->getDefaultDataSubId()I
-Lcom/android/internal/telephony/ISub;->getDefaultSubId()I
-Lcom/android/internal/telephony/ISub;->setDefaultDataSubId(I)V
Lcom/android/internal/telephony/ITelephony$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
Lcom/android/internal/telephony/ITelephony$Stub$Proxy;->getDeviceId(Ljava/lang/String;)Ljava/lang/String;
Lcom/android/internal/telephony/ITelephony$Stub$Proxy;->isRadioOn(Ljava/lang/String;)Z
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 89e848b2820e..425f6d0055c5 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -127,7 +127,6 @@ import android.view.autofill.AutofillPopupWindow;
import android.view.autofill.IAutofillWindowPresenter;
import android.view.contentcapture.ContentCaptureContext;
import android.view.contentcapture.ContentCaptureManager;
-import android.view.contentcapture.ContentCaptureSession;
import android.widget.AdapterView;
import android.widget.Toast;
import android.widget.Toolbar;
@@ -1038,15 +1037,11 @@ public class Activity extends ContextThemeWrapper
}
/** @hide */ private static final int CONTENT_CAPTURE_START = 1;
- /** @hide */ private static final int CONTENT_CAPTURE_PAUSE = 2;
- /** @hide */ private static final int CONTENT_CAPTURE_RESUME = 3;
- /** @hide */ private static final int CONTENT_CAPTURE_STOP = 4;
+ /** @hide */ private static final int CONTENT_CAPTURE_STOP = 2;
/** @hide */
@IntDef(prefix = { "CONTENT_CAPTURE_" }, value = {
CONTENT_CAPTURE_START,
- CONTENT_CAPTURE_PAUSE,
- CONTENT_CAPTURE_RESUME,
CONTENT_CAPTURE_STOP
})
@Retention(RetentionPolicy.SOURCE)
@@ -1056,10 +1051,6 @@ public class Activity extends ContextThemeWrapper
switch (type) {
case CONTENT_CAPTURE_START:
return "START";
- case CONTENT_CAPTURE_PAUSE:
- return "PAUSE";
- case CONTENT_CAPTURE_RESUME:
- return "RESUME";
case CONTENT_CAPTURE_STOP:
return "STOP";
default:
@@ -1088,12 +1079,6 @@ public class Activity extends ContextThemeWrapper
}
cm.onActivityStarted(mToken, getComponentName(), flags);
break;
- case CONTENT_CAPTURE_PAUSE:
- cm.flush(ContentCaptureSession.FLUSH_REASON_ACTIVITY_PAUSED);
- break;
- case CONTENT_CAPTURE_RESUME:
- cm.flush(ContentCaptureSession.FLUSH_REASON_ACTIVITY_RESUMED);
- break;
case CONTENT_CAPTURE_STOP:
cm.onActivityStopped();
break;
@@ -1781,7 +1766,6 @@ public class Activity extends ContextThemeWrapper
}
}
mCalled = true;
- notifyContentCaptureManagerIfNeeded(CONTENT_CAPTURE_RESUME);
}
/**
@@ -2198,7 +2182,6 @@ public class Activity extends ContextThemeWrapper
}
}
mCalled = true;
- notifyContentCaptureManagerIfNeeded(CONTENT_CAPTURE_PAUSE);
}
/**
@@ -2387,8 +2370,8 @@ public class Activity extends ContextThemeWrapper
getAutofillManager().onPendingSaveUi(AutofillManager.PENDING_UI_OPERATION_CANCEL,
mIntent.getIBinderExtra(AutofillManager.EXTRA_RESTORE_SESSION_TOKEN));
}
- notifyContentCaptureManagerIfNeeded(CONTENT_CAPTURE_STOP);
}
+ notifyContentCaptureManagerIfNeeded(CONTENT_CAPTURE_STOP);
mEnterAnimationComplete = false;
}
@@ -7608,7 +7591,7 @@ public class Activity extends ContextThemeWrapper
mWindow.setColorMode(info.colorMode);
- setAutofillCompatibilityEnabled(application.isAutofillCompatibilityEnabled());
+ setAutofillOptions(application.getAutofillOptions());
setContentCaptureOptions(application.getContentCaptureOptions());
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 5d4f988c3630..ee7288ffd52c 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -3925,6 +3925,14 @@ public class ActivityManager {
/**
* @hide
*/
+ @TestApi
+ public static void resumeAppSwitches() throws RemoteException {
+ getService().resumeAppSwitches();
+ }
+
+ /**
+ * @hide
+ */
public static void noteWakeupAlarm(PendingIntent ps, WorkSource workSource, int sourceUid,
String sourcePkg, String tag) {
try {
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 001cd69067a1..92302c501caf 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -43,6 +43,7 @@ import android.app.servertransaction.PendingTransactionActions;
import android.app.servertransaction.PendingTransactionActions.StopInfo;
import android.app.servertransaction.TransactionExecutor;
import android.app.servertransaction.TransactionExecutorHelper;
+import android.content.AutofillOptions;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
@@ -745,7 +746,7 @@ public final class ActivityThread extends ClientTransactionHandler {
/** Initial values for {@link Profiler}. */
ProfilerInfo initProfilerInfo;
- boolean autofillCompatibilityEnabled;
+ AutofillOptions autofillOptions;
/**
* Content capture options for the application - when null, it means ContentCapture is not
@@ -975,9 +976,8 @@ public final class ActivityThread extends ClientTransactionHandler {
boolean enableBinderTracking, boolean trackAllocation,
boolean isRestrictedBackupMode, boolean persistent, Configuration config,
CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
- String buildSerial, boolean autofillCompatibilityEnabled,
+ String buildSerial, AutofillOptions autofillOptions,
ContentCaptureOptions contentCaptureOptions) {
-
if (services != null) {
if (false) {
// Test code to make sure the app could see the passed-in services.
@@ -1023,7 +1023,7 @@ public final class ActivityThread extends ClientTransactionHandler {
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
data.buildSerial = buildSerial;
- data.autofillCompatibilityEnabled = autofillCompatibilityEnabled;
+ data.autofillOptions = autofillOptions;
data.contentCaptureOptions = contentCaptureOptions;
sendMessage(H.BIND_APPLICATION, data);
}
@@ -6164,7 +6164,7 @@ public final class ActivityThread extends ClientTransactionHandler {
app = data.info.makeApplication(data.restrictedBackupMode, null);
// Propagate autofill compat state
- app.setAutofillCompatibilityEnabled(data.autofillCompatibilityEnabled);
+ app.setAutofillOptions(data.autofillOptions);
// Propagate Content Capture options
app.setContentCaptureOptions(data.contentCaptureOptions);
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index a4b763dbfa9c..2ef085690f8f 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -21,7 +21,7 @@ import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_C
import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC;
import android.annotation.NonNull;
-import android.annotation.UnsupportedAppUsage;
+import android.annotation.TestApi;
import android.app.ActivityManager.StackInfo;
import android.content.ComponentName;
import android.content.Context;
@@ -59,6 +59,7 @@ import java.util.List;
* on VirtualDisplays.
* @hide
*/
+@TestApi
public class ActivityView extends ViewGroup {
private static final String DISPLAY_NAME = "ActivityViewVirtualDisplay";
@@ -92,7 +93,6 @@ public class ActivityView extends ViewGroup {
private Insets mForwardedInsets;
- @UnsupportedAppUsage
public ActivityView(Context context) {
this(context, null /* attrs */);
}
@@ -151,7 +151,7 @@ public class ActivityView extends ViewGroup {
* Called when a task is moved to the front of the stack inside the container.
* This is a filtered version of {@link TaskStackListener}
*/
- public void onTaskMovedToFront(ActivityManager.StackInfo stackInfo) { }
+ public void onTaskMovedToFront(int taskId) { }
/**
* Called when a task is about to be removed from the stack inside the container.
@@ -195,7 +195,6 @@ public class ActivityView extends ViewGroup {
* @see StateCallback
* @see #startActivity(PendingIntent)
*/
- @UnsupportedAppUsage
public void startActivity(@NonNull Intent intent) {
final ActivityOptions options = prepareActivityOptions();
getContext().startActivity(intent, options.toBundle());
@@ -238,7 +237,6 @@ public class ActivityView extends ViewGroup {
* @see StateCallback
* @see #startActivity(Intent)
*/
- @UnsupportedAppUsage
public void startActivity(@NonNull PendingIntent pendingIntent) {
final ActivityOptions options = prepareActivityOptions();
try {
@@ -272,7 +270,6 @@ public class ActivityView extends ViewGroup {
*
* @see StateCallback
*/
- @UnsupportedAppUsage
public void release() {
if (mVirtualDisplay == null) {
throw new IllegalStateException(
@@ -556,7 +553,7 @@ public class ActivityView extends ViewGroup {
// notifying the callback
if (stackInfo != null
&& taskInfo.taskId == stackInfo.taskIds[stackInfo.taskIds.length - 1]) {
- mActivityViewCallback.onTaskMovedToFront(stackInfo);
+ mActivityViewCallback.onTaskMovedToFront(taskInfo.taskId);
}
}
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 98032dc3d297..d3e350779c6b 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -696,7 +696,9 @@ public class ApplicationPackageManager extends PackageManager {
int flagMask, int flagValues, UserHandle user) {
try {
mPM.updatePermissionFlags(permissionName, packageName, flagMask,
- flagValues, user.getIdentifier());
+ flagValues,
+ mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q,
+ user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2467,6 +2469,33 @@ public class ApplicationPackageManager extends PackageManager {
}
@Override
+ public void setAppDetailsActivityEnabled(String packageName, boolean enabled) {
+ try {
+ ComponentName componentName = new ComponentName(packageName,
+ PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME);
+ mPM.setComponentEnabledSetting(componentName, enabled
+ ? PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
+ : PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
+ PackageManager.DONT_KILL_APP, getUserId());
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ @Override
+ public boolean getAppDetailsActivityEnabled(String packageName) {
+ try {
+ ComponentName componentName = new ComponentName(packageName,
+ PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME);
+ int state = mPM.getComponentEnabledSetting(componentName, getUserId());
+ return state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED
+ || state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ @Override
public void setComponentEnabledSetting(ComponentName componentName,
int newState, int flags) {
try {
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 3a1e80dc1c3f..b607f9adebbe 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -21,6 +21,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
+import android.content.AutofillOptions;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentCaptureOptions;
@@ -215,8 +216,8 @@ class ContextImpl extends Context {
// The name of the split this Context is representing. May be null.
private @Nullable String mSplitName = null;
- private AutofillClient mAutofillClient = null;
- private boolean mIsAutofillCompatEnabled;
+ private @Nullable AutofillClient mAutofillClient = null;
+ private @Nullable AutofillOptions mAutofillOptions;
private ContentCaptureOptions mContentCaptureOptions = null;
@@ -2283,8 +2284,8 @@ class ContextImpl extends Context {
return (mFlags & Context.CONTEXT_IGNORE_SECURITY) != 0;
}
+ @TestApi
@Override
- @UnsupportedAppUsage
public Display getDisplay() {
if (mDisplay == null) {
return mResourcesManager.getAdjustedDisplay(Display.DEFAULT_DISPLAY,
@@ -2376,15 +2377,14 @@ class ContextImpl extends Context {
/** @hide */
@Override
- public boolean isAutofillCompatibilityEnabled() {
- return mIsAutofillCompatEnabled;
+ public AutofillOptions getAutofillOptions() {
+ return mAutofillOptions;
}
/** @hide */
- @TestApi
@Override
- public void setAutofillCompatibilityEnabled(boolean autofillCompatEnabled) {
- mIsAutofillCompatEnabled = autofillCompatEnabled;
+ public void setAutofillOptions(AutofillOptions options) {
+ mAutofillOptions = options;
}
/** @hide */
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 3aa9fa7fedee..780dd630d834 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -486,4 +486,13 @@ interface IActivityManager {
* started from the shell.
*/
void stopDelegateShellPermissionIdentity();
+
+ /** Returns a file descriptor that'll be closed when the system server process dies. */
+ ParcelFileDescriptor getLifeMonitor();
+
+ /**
+ * Start user, if it us not already running, and bring it to foreground.
+ * unlockProgressListener can be null if monitoring progress is not necessary.
+ */
+ boolean startUserInForegroundWithListener(int userid, IProgressListener unlockProgressListener);
}
diff --git a/core/java/android/app/IApplicationThread.aidl b/core/java/android/app/IApplicationThread.aidl
index b73092a1276f..b8af8989170e 100644
--- a/core/java/android/app/IApplicationThread.aidl
+++ b/core/java/android/app/IApplicationThread.aidl
@@ -21,6 +21,7 @@ import android.app.IUiAutomationConnection;
import android.app.ProfilerInfo;
import android.app.ResultInfo;
import android.app.servertransaction.ClientTransaction;
+import android.content.AutofillOptions;
import android.content.ComponentName;
import android.content.ContentCaptureOptions;
import android.content.IIntentReceiver;
@@ -69,7 +70,7 @@ oneway interface IApplicationThread {
int debugMode, boolean enableBinderTracking, boolean trackAllocation,
boolean restrictedBackupMode, boolean persistent, in Configuration config,
in CompatibilityInfo compatInfo, in Map services,
- in Bundle coreSettings, in String buildSerial, boolean isAutofillCompatEnabled,
+ in Bundle coreSettings, in String buildSerial, in AutofillOptions autofillOptions,
in ContentCaptureOptions contentCaptureOptions);
void runIsolatedEntryPoint(in String entryPoint, in String[] entryPointArgs);
void scheduleExit();
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 0166f521999e..2e7093db92f0 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -8409,7 +8409,6 @@ public class Notification implements Parcelable
private PendingIntent mPendingIntent;
private PendingIntent mDeleteIntent;
- private CharSequence mTitle;
private Icon mIcon;
private int mDesiredHeight;
private int mFlags;
@@ -8438,9 +8437,8 @@ public class Notification implements Parcelable
private static final int FLAG_SUPPRESS_INITIAL_NOTIFICATION = 0x00000002;
private BubbleMetadata(PendingIntent expandIntent, PendingIntent deleteIntent,
- CharSequence title, Icon icon, int height) {
+ Icon icon, int height) {
mPendingIntent = expandIntent;
- mTitle = title;
mIcon = icon;
mDesiredHeight = height;
mDeleteIntent = deleteIntent;
@@ -8448,7 +8446,6 @@ public class Notification implements Parcelable
private BubbleMetadata(Parcel in) {
mPendingIntent = PendingIntent.CREATOR.createFromParcel(in);
- mTitle = in.readCharSequence();
mIcon = Icon.CREATOR.createFromParcel(in);
mDesiredHeight = in.readInt();
mFlags = in.readInt();
@@ -8474,11 +8471,13 @@ public class Notification implements Parcelable
/**
* @return the title that will appear along with the app content defined by
* {@link #getIntent()} for this bubble.
+ *
+ * @deprecated titles are no longer required or shown.
*/
+ @Deprecated
public CharSequence getTitle() {
- return mTitle;
+ return "";
}
-
/**
* @return the icon that will be displayed for this bubble when it is collapsed.
*/
@@ -8534,7 +8533,6 @@ public class Notification implements Parcelable
@Override
public void writeToParcel(Parcel out, int flags) {
mPendingIntent.writeToParcel(out, 0);
- out.writeCharSequence(mTitle);
mIcon.writeToParcel(out, 0);
out.writeInt(mDesiredHeight);
out.writeInt(mFlags);
@@ -8554,7 +8552,6 @@ public class Notification implements Parcelable
public static class Builder {
private PendingIntent mPendingIntent;
- private CharSequence mTitle;
private Icon mIcon;
private int mDesiredHeight;
private int mFlags;
@@ -8583,12 +8580,11 @@ public class Notification implements Parcelable
*
* <p>A title is required and should expect to fit on a single line and make sense when
* shown with the content defined by {@link #setIntent(PendingIntent)}.</p>
+ *
+ * @deprecated titles are no longer required or shown.
*/
+ @Deprecated
public BubbleMetadata.Builder setTitle(CharSequence title) {
- if (TextUtils.isEmpty(title)) {
- throw new IllegalArgumentException("Bubbles require non-null or empty title");
- }
- mTitle = title;
return this;
}
@@ -8667,13 +8663,10 @@ public class Notification implements Parcelable
if (mPendingIntent == null) {
throw new IllegalStateException("Must supply pending intent to bubble");
}
- if (TextUtils.isEmpty(mTitle)) {
- throw new IllegalStateException("Must supply a title for the bubble");
- }
if (mIcon == null) {
throw new IllegalStateException("Must supply an icon for the bubble");
}
- BubbleMetadata data = new BubbleMetadata(mPendingIntent, mDeleteIntent, mTitle,
+ BubbleMetadata data = new BubbleMetadata(mPendingIntent, mDeleteIntent,
mIcon, mDesiredHeight);
data.setFlags(mFlags);
return data;
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index 31521a369a4c..7e074460bff8 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -128,7 +128,13 @@ public final class UiAutomationConnection extends IUiAutomationConnection.Stub {
: InputManager.INJECT_INPUT_EVENT_MODE_ASYNC;
final long identity = Binder.clearCallingIdentity();
try {
- return InputManager.getInstance().injectInputEvent(event, mode);
+ IWindowManager manager = IWindowManager.Stub.asInterface(
+ ServiceManager.getService(Context.WINDOW_SERVICE));
+ try {
+ return manager.injectInputAfterTransactionsApplied(event, mode);
+ } catch (RemoteException e) {
+ }
+ return false;
} finally {
Binder.restoreCallingIdentity(identity);
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 3587c68ef234..a32e01fb68e5 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -59,6 +59,7 @@ import android.os.Build;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.os.Parcelable;
+import android.os.ParcelableException;
import android.os.PersistableBundle;
import android.os.Process;
import android.os.RemoteCallback;
@@ -115,6 +116,8 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
/**
@@ -1576,6 +1579,19 @@ public class DevicePolicyManager {
public static final int PERMISSION_POLICY_AUTO_DENY = 2;
/**
+ * Possible policy values for permissions.
+ *
+ * @hide
+ */
+ @IntDef(prefix = { "PERMISSION_GRANT_STATE_" }, value = {
+ PERMISSION_GRANT_STATE_DEFAULT,
+ PERMISSION_GRANT_STATE_GRANTED,
+ PERMISSION_GRANT_STATE_DENIED
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface PermissionGrantState {}
+
+ /**
* Runtime permission state: The user can manage the permission
* through the UI.
*/
@@ -8667,8 +8683,15 @@ public class DevicePolicyManager {
* Setting the grant state to {@link #PERMISSION_GRANT_STATE_DEFAULT default} does not revoke
* the permission. It retains the previous grant, if any.
* <p/>
- * Permissions can be granted or revoked only for applications built with a
- * {@code targetSdkVersion} of {@link android.os.Build.VERSION_CODES#M} or later.
+ * Device admins with a {@code targetSdkVersion} &lt; {@link android.os.Build.VERSION_CODES#Q}
+ * cannot grant and revoke permissions for applications built with a {@code targetSdkVersion}
+ * &lt; {@link android.os.Build.VERSION_CODES#M}.
+ * <p/>
+ * Admins with a {@code targetSdkVersion} &ge; {@link android.os.Build.VERSION_CODES#Q} can
+ * grant and revoke permissions of all apps. Similar to the user revoking a permission from a
+ * application built with a {@code targetSdkVersion} &lt;
+ * {@link android.os.Build.VERSION_CODES#M} the app-op matching the permission is set to
+ * {@link android.app.AppOpsManager#MODE_IGNORED}, but the permission stays granted.
*
* @param admin Which profile or device owner this request is associated with.
* @param packageName The application to grant or revoke a permission to.
@@ -8684,14 +8707,21 @@ public class DevicePolicyManager {
* @see #setDelegatedScopes
* @see #DELEGATION_PERMISSION_GRANT
*/
- public boolean setPermissionGrantState(@NonNull ComponentName admin, String packageName,
- String permission, int grantState) {
+ public boolean setPermissionGrantState(@NonNull ComponentName admin,
+ @NonNull String packageName, @NonNull String permission,
+ @PermissionGrantState int grantState) {
throwIfParentInstance("setPermissionGrantState");
try {
- return mService.setPermissionGrantState(admin, mContext.getPackageName(), packageName,
- permission, grantState);
+ CompletableFuture<Boolean> result = new CompletableFuture<>();
+
+ mService.setPermissionGrantState(admin, mContext.getPackageName(), packageName,
+ permission, grantState, new RemoteCallback((b) -> result.complete(b != null)));
+
+ return result.get();
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
+ } catch (InterruptedException | ExecutionException e) {
+ throw new RuntimeException(e);
}
}
@@ -8719,8 +8749,8 @@ public class DevicePolicyManager {
* @see #setDelegatedScopes
* @see #DELEGATION_PERMISSION_GRANT
*/
- public int getPermissionGrantState(@Nullable ComponentName admin, String packageName,
- String permission) {
+ public @PermissionGrantState int getPermissionGrantState(@Nullable ComponentName admin,
+ @NonNull String packageName, @NonNull String permission) {
throwIfParentInstance("getPermissionGrantState");
try {
return mService.getPermissionGrantState(admin, mContext.getPackageName(), packageName,
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 5790fda718a7..9478a3c83d23 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -311,8 +311,8 @@ interface IDevicePolicyManager {
void setPermissionPolicy(in ComponentName admin, in String callerPackage, int policy);
int getPermissionPolicy(in ComponentName admin);
- boolean setPermissionGrantState(in ComponentName admin, in String callerPackage, String packageName,
- String permission, int grantState);
+ void setPermissionGrantState(in ComponentName admin, in String callerPackage, String packageName,
+ String permission, int grantState, in RemoteCallback resultReceiver);
int getPermissionGrantState(in ComponentName admin, in String callerPackage, String packageName, String permission);
boolean isProvisioningAllowed(String action, String packageName);
int checkProvisioningPreCondition(String action, String packageName);
diff --git a/core/java/android/app/timezone/RulesState.java b/core/java/android/app/timezone/RulesState.java
index e86d348a85fa..38dd1ebf1c45 100644
--- a/core/java/android/app/timezone/RulesState.java
+++ b/core/java/android/app/timezone/RulesState.java
@@ -33,7 +33,7 @@ import java.lang.annotation.RetentionPolicy;
*
* <p>The following properties are included:
* <dl>
- * <dt>systemRulesVersion</dt>
+ * <dt>baseRulesVersion</dt>
* <dd>the IANA rules version that shipped with the OS. Always present. e.g. "2017a".</dd>
* <dt>distroFormatVersionSupported</dt>
* <dd>the distro format version supported by this device. Always present.</dd>
@@ -98,7 +98,7 @@ public final class RulesState implements Parcelable {
private static final byte BYTE_FALSE = 0;
private static final byte BYTE_TRUE = 1;
- private final String mSystemRulesVersion;
+ private final String mBaseRulesVersion;
private final DistroFormatVersion mDistroFormatVersionSupported;
private final boolean mOperationInProgress;
@StagedOperationType private final int mStagedOperationType;
@@ -106,13 +106,13 @@ public final class RulesState implements Parcelable {
@DistroStatus private final int mDistroStatus;
@Nullable private final DistroRulesVersion mInstalledDistroRulesVersion;
- public RulesState(String systemRulesVersion, DistroFormatVersion distroFormatVersionSupported,
+ public RulesState(String baseRulesVersion, DistroFormatVersion distroFormatVersionSupported,
boolean operationInProgress,
@StagedOperationType int stagedOperationType,
@Nullable DistroRulesVersion stagedDistroRulesVersion,
@DistroStatus int distroStatus,
@Nullable DistroRulesVersion installedDistroRulesVersion) {
- this.mSystemRulesVersion = validateRulesVersion("systemRulesVersion", systemRulesVersion);
+ this.mBaseRulesVersion = validateRulesVersion("baseRulesVersion", baseRulesVersion);
this.mDistroFormatVersionSupported =
validateNotNull("distroFormatVersionSupported", distroFormatVersionSupported);
this.mOperationInProgress = operationInProgress;
@@ -132,8 +132,8 @@ public final class RulesState implements Parcelable {
"installedDistroRulesVersion", installedDistroRulesVersion);
}
- public String getSystemRulesVersion() {
- return mSystemRulesVersion;
+ public String getBaseRulesVersion() {
+ return mBaseRulesVersion;
}
public boolean isOperationInProgress() {
@@ -172,14 +172,14 @@ public final class RulesState implements Parcelable {
}
/**
- * Returns true if the system image data files contain IANA rules data that are newer than the
+ * Returns true if the base data files contain IANA rules data that are newer than the
* distro IANA rules version supplied, i.e. true when the version specified would be "worse"
- * than the one that is in the system image. Returns false if the system image version is the
+ * than the one that is in the base data. Returns false if the base version is the
* same or older, i.e. false when the version specified would be "better" than the one that is
- * in the system image.
+ * in the base set.
*/
- public boolean isSystemVersionNewerThan(DistroRulesVersion distroRulesVersion) {
- return mSystemRulesVersion.compareTo(distroRulesVersion.getRulesVersion()) > 0;
+ public boolean isBaseVersionNewerThan(DistroRulesVersion distroRulesVersion) {
+ return mBaseRulesVersion.compareTo(distroRulesVersion.getRulesVersion()) > 0;
}
public static final Parcelable.Creator<RulesState> CREATOR =
@@ -194,14 +194,14 @@ public final class RulesState implements Parcelable {
};
private static RulesState createFromParcel(Parcel in) {
- String systemRulesVersion = in.readString();
+ String baseRulesVersion = in.readString();
DistroFormatVersion distroFormatVersionSupported = in.readParcelable(null);
boolean operationInProgress = in.readByte() == BYTE_TRUE;
int distroStagedState = in.readByte();
DistroRulesVersion stagedDistroRulesVersion = in.readParcelable(null);
int installedDistroStatus = in.readByte();
DistroRulesVersion installedDistroRulesVersion = in.readParcelable(null);
- return new RulesState(systemRulesVersion, distroFormatVersionSupported, operationInProgress,
+ return new RulesState(baseRulesVersion, distroFormatVersionSupported, operationInProgress,
distroStagedState, stagedDistroRulesVersion,
installedDistroStatus, installedDistroRulesVersion);
}
@@ -213,7 +213,7 @@ public final class RulesState implements Parcelable {
@Override
public void writeToParcel(Parcel out, int flags) {
- out.writeString(mSystemRulesVersion);
+ out.writeString(mBaseRulesVersion);
out.writeParcelable(mDistroFormatVersionSupported, 0);
out.writeByte(mOperationInProgress ? BYTE_TRUE : BYTE_FALSE);
out.writeByte((byte) mStagedOperationType);
@@ -242,7 +242,7 @@ public final class RulesState implements Parcelable {
if (mDistroStatus != that.mDistroStatus) {
return false;
}
- if (!mSystemRulesVersion.equals(that.mSystemRulesVersion)) {
+ if (!mBaseRulesVersion.equals(that.mBaseRulesVersion)) {
return false;
}
if (!mDistroFormatVersionSupported.equals(that.mDistroFormatVersionSupported)) {
@@ -259,7 +259,7 @@ public final class RulesState implements Parcelable {
@Override
public int hashCode() {
- int result = mSystemRulesVersion.hashCode();
+ int result = mBaseRulesVersion.hashCode();
result = 31 * result + mDistroFormatVersionSupported.hashCode();
result = 31 * result + (mOperationInProgress ? 1 : 0);
result = 31 * result + mStagedOperationType;
@@ -275,7 +275,7 @@ public final class RulesState implements Parcelable {
@Override
public String toString() {
return "RulesState{"
- + "mSystemRulesVersion='" + mSystemRulesVersion + '\''
+ + "mBaseRulesVersion='" + mBaseRulesVersion + '\''
+ ", mDistroFormatVersionSupported=" + mDistroFormatVersionSupported
+ ", mOperationInProgress=" + mOperationInProgress
+ ", mStagedOperationType=" + mStagedOperationType
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 3e9dd2882600..85f0e2342412 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -30,7 +30,6 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Rect;
-import android.os.Build;
import android.os.Bundle;
import android.os.CancellationSignal;
import android.os.Parcelable;
@@ -178,40 +177,29 @@ public class AppWidgetHostView extends FrameLayout {
*/
public static Rect getDefaultPaddingForWidget(Context context, ComponentName component,
Rect padding) {
- ApplicationInfo appInfo = null;
- try {
- appInfo = context.getPackageManager().getApplicationInfo(component.getPackageName(), 0);
- } catch (NameNotFoundException e) {
- // if we can't find the package, ignore
- }
- return getDefaultPaddingForWidget(context, appInfo, padding);
+ return getDefaultPaddingForWidget(context, padding);
}
- @UnsupportedAppUsage
- private static Rect getDefaultPaddingForWidget(Context context, ApplicationInfo appInfo,
- Rect padding) {
+ private static Rect getDefaultPaddingForWidget(Context context, Rect padding) {
if (padding == null) {
padding = new Rect(0, 0, 0, 0);
} else {
padding.set(0, 0, 0, 0);
}
- if (appInfo != null && appInfo.targetSdkVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
- Resources r = context.getResources();
- padding.left = r.getDimensionPixelSize(com.android.internal.
- R.dimen.default_app_widget_padding_left);
- padding.right = r.getDimensionPixelSize(com.android.internal.
- R.dimen.default_app_widget_padding_right);
- padding.top = r.getDimensionPixelSize(com.android.internal.
- R.dimen.default_app_widget_padding_top);
- padding.bottom = r.getDimensionPixelSize(com.android.internal.
- R.dimen.default_app_widget_padding_bottom);
- }
+ Resources r = context.getResources();
+ padding.left = r.getDimensionPixelSize(
+ com.android.internal.R.dimen.default_app_widget_padding_left);
+ padding.right = r.getDimensionPixelSize(
+ com.android.internal.R.dimen.default_app_widget_padding_right);
+ padding.top = r.getDimensionPixelSize(
+ com.android.internal.R.dimen.default_app_widget_padding_top);
+ padding.bottom = r.getDimensionPixelSize(
+ com.android.internal.R.dimen.default_app_widget_padding_bottom);
return padding;
}
private Rect getDefaultPadding() {
- return getDefaultPaddingForWidget(mContext,
- mInfo == null ? null : mInfo.providerInfo.applicationInfo, null);
+ return getDefaultPaddingForWidget(mContext, null);
}
public int getAppWidgetId() {
diff --git a/core/java/android/content/AutofillOptions.aidl b/core/java/android/content/AutofillOptions.aidl
new file mode 100644
index 000000000000..7e4fed20957f
--- /dev/null
+++ b/core/java/android/content/AutofillOptions.aidl
@@ -0,0 +1,19 @@
+/*
+** Copyright 2019, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+package android.content;
+
+parcelable AutofillOptions;
diff --git a/core/java/android/content/AutofillOptions.java b/core/java/android/content/AutofillOptions.java
new file mode 100644
index 000000000000..fd7e52aaebcd
--- /dev/null
+++ b/core/java/android/content/AutofillOptions.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content;
+
+import android.annotation.NonNull;
+import android.annotation.TestApi;
+import android.app.ActivityThread;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+import android.view.autofill.AutofillManager;
+
+import java.io.PrintWriter;
+
+/**
+ * Autofill options for a given package.
+ *
+ * <p>This object is created by the Autofill System Service and passed back to the app when the
+ * application is created.
+ *
+ * @hide
+ */
+@TestApi
+public final class AutofillOptions implements Parcelable {
+
+ private static final String TAG = AutofillOptions.class.getSimpleName();
+
+ /**
+ * Logging level for {@code logcat} statements.
+ */
+ public final int loggingLevel;
+
+ /**
+ * Whether compatibility mode is enabled for the package.
+ */
+ public final boolean compatModeEnabled;
+
+ /**
+ * Whether package is whitelisted for augmented autofill.
+ */
+ public boolean augmentedEnabled;
+ // TODO(b/123100824): add (optional) list of activities
+
+ public AutofillOptions(int loggingLevel, boolean compatModeEnabled) {
+ this.loggingLevel = loggingLevel;
+ this.compatModeEnabled = compatModeEnabled;
+ }
+
+ /**
+ * @hide
+ */
+ @TestApi
+ public static AutofillOptions forWhitelistingItself() {
+ final ActivityThread at = ActivityThread.currentActivityThread();
+ if (at == null) {
+ throw new IllegalStateException("No ActivityThread");
+ }
+
+ final String packageName = at.getApplication().getPackageName();
+
+ if (!"android.autofillservice.cts".equals(packageName)) {
+ Log.e(TAG, "forWhitelistingItself(): called by " + packageName);
+ throw new SecurityException("Thou shall not pass!");
+ }
+
+ final AutofillOptions options = new AutofillOptions(
+ AutofillManager.FLAG_ADD_CLIENT_VERBOSE, /* compatModeAllowed= */ true);
+ options.augmentedEnabled = true;
+ // Always log, as it's used by test only
+ Log.i(TAG, "forWhitelistingItself(" + packageName + "): " + options);
+
+ return options;
+ }
+
+ @Override
+ public String toString() {
+ return "AutofillOptions [loggingLevel=" + loggingLevel + ", compatMode="
+ + compatModeEnabled + ", augmentedEnabled=" + augmentedEnabled + "]";
+ }
+
+ /** @hide */
+ public void dumpShort(@NonNull PrintWriter pw) {
+ pw.print("logLvl="); pw.print(loggingLevel);
+ pw.print(", compatMode="); pw.print(compatModeEnabled);
+ pw.print(", augmented="); pw.print(augmentedEnabled);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeInt(loggingLevel);
+ parcel.writeBoolean(compatModeEnabled);
+ parcel.writeBoolean(augmentedEnabled);
+ }
+
+ public static final Parcelable.Creator<AutofillOptions> CREATOR =
+ new Parcelable.Creator<AutofillOptions>() {
+
+ @Override
+ public AutofillOptions createFromParcel(Parcel parcel) {
+ final int loggingLevel = parcel.readInt();
+ final boolean compatMode = parcel.readBoolean();
+ final AutofillOptions options = new AutofillOptions(loggingLevel, compatMode);
+ options.augmentedEnabled = parcel.readBoolean();
+ return options;
+ }
+
+ @Override
+ public AutofillOptions[] newArray(int size) {
+ return new AutofillOptions[size];
+ }
+ };
+}
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index c44520aae607..1e4b1e7b45c6 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -3159,6 +3159,7 @@ public abstract class ContentResolver implements ContentInterface {
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.CACHE_CONTENT)
public void putCache(@NonNull Uri key, @Nullable Bundle value) {
try {
getContentService().putCache(mContext.getPackageName(), key, value,
@@ -3178,6 +3179,7 @@ public abstract class ContentResolver implements ContentInterface {
* @hide
*/
@SystemApi
+ @RequiresPermission(android.Manifest.permission.CACHE_CONTENT)
public @Nullable Bundle getCache(@NonNull Uri key) {
try {
final Bundle bundle = getContentService().getCache(mContext.getPackageName(), key,
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index fdb0041d49ed..29added9aa51 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -5241,9 +5241,10 @@ public abstract class Context {
public abstract DisplayAdjustments getDisplayAdjustments(int displayId);
/**
+ * @return Returns the {@link Display} object this context is associated with.
* @hide
*/
- @UnsupportedAppUsage
+ @TestApi
public abstract Display getDisplay();
/**
@@ -5340,16 +5341,24 @@ public abstract class Context {
/**
* @hide
*/
- public boolean isAutofillCompatibilityEnabled() {
- return false;
+ public final boolean isAutofillCompatibilityEnabled() {
+ final AutofillOptions options = getAutofillOptions();
+ return options != null && options.compatModeEnabled;
+ }
+
+ /**
+ * @hide
+ */
+ @Nullable
+ public AutofillOptions getAutofillOptions() {
+ return null;
}
/**
* @hide
*/
@TestApi
- public void setAutofillCompatibilityEnabled(
- @SuppressWarnings("unused") boolean autofillCompatEnabled) {
+ public void setAutofillOptions(@SuppressWarnings("unused") @Nullable AutofillOptions options) {
}
/**
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index 68b4320568c2..40559d31d631 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -919,11 +919,9 @@ public class ContextWrapper extends Context {
return mBase.getDisplayAdjustments(displayId);
}
- /**
- * @hide
- */
+ /** @hide */
+ @TestApi
@Override
- @UnsupportedAppUsage
public Display getDisplay() {
return mBase.getDisplay();
}
@@ -1031,22 +1029,17 @@ public class ContextWrapper extends Context {
mBase.setAutofillClient(client);
}
- /**
- * @hide
- */
+ /** @hide */
@Override
- public boolean isAutofillCompatibilityEnabled() {
- return mBase != null && mBase.isAutofillCompatibilityEnabled();
+ public AutofillOptions getAutofillOptions() {
+ return mBase == null ? null : mBase.getAutofillOptions();
}
- /**
- * @hide
- */
- @TestApi
+ /** @hide */
@Override
- public void setAutofillCompatibilityEnabled(boolean autofillCompatEnabled) {
+ public void setAutofillOptions(AutofillOptions options) {
if (mBase != null) {
- mBase.setAutofillCompatibilityEnabled(autofillCompatEnabled);
+ mBase.setAutofillOptions(options);
}
}
diff --git a/core/java/android/content/pm/AndroidTestBaseUpdater.java b/core/java/android/content/pm/AndroidTestBaseUpdater.java
index 2aaac0280a0e..6a1778cfd3f6 100644
--- a/core/java/android/content/pm/AndroidTestBaseUpdater.java
+++ b/core/java/android/content/pm/AndroidTestBaseUpdater.java
@@ -19,11 +19,12 @@ import static android.content.pm.SharedLibraryNames.ANDROID_TEST_BASE;
import static android.content.pm.SharedLibraryNames.ANDROID_TEST_RUNNER;
import android.content.pm.PackageParser.Package;
+import android.os.Build;
import com.android.internal.annotations.VisibleForTesting;
/**
- * Updates a package to ensure that if it targets < P that the android.test.base library is
+ * Updates a package to ensure that if it targets <= P that the android.test.base library is
* included by default.
*
* <p>This is separated out so that it can be conditionally included at build time depending on
@@ -37,12 +38,17 @@ import com.android.internal.annotations.VisibleForTesting;
@VisibleForTesting
public class AndroidTestBaseUpdater extends PackageSharedLibraryUpdater {
+ private static boolean apkTargetsApiLevelLessThanOrEqualToP(Package pkg) {
+ int targetSdkVersion = pkg.applicationInfo.targetSdkVersion;
+ return targetSdkVersion <= Build.VERSION_CODES.P;
+ }
+
@Override
public void updatePackage(Package pkg) {
- // Packages targeted at <= O_MR1 expect the classes in the android.test.base library
+ // Packages targeted at <= P expect the classes in the android.test.base library
// to be accessible so this maintains backward compatibility by adding the
// android.test.base library to those packages.
- if (apkTargetsApiLevelLessThanOrEqualToOMR1(pkg)) {
+ if (apkTargetsApiLevelLessThanOrEqualToP(pkg)) {
prefixRequiredLibrary(pkg, ANDROID_TEST_BASE);
} else {
// If a package already depends on android.test.runner then add a dependency on
diff --git a/core/java/android/content/pm/IPackageInstaller.aidl b/core/java/android/content/pm/IPackageInstaller.aidl
index a251c0036a78..0cf83fd4655b 100644
--- a/core/java/android/content/pm/IPackageInstaller.aidl
+++ b/core/java/android/content/pm/IPackageInstaller.aidl
@@ -50,5 +50,8 @@ interface IPackageInstaller {
void uninstall(in VersionedPackage versionedPackage, String callerPackageName, int flags,
in IntentSender statusReceiver, int userId);
+ void installExistingPackage(String packageName, int installFlags, int installReason,
+ in IntentSender statusReceiver, int userId);
+
void setPermissionsResult(int sessionId, boolean accepted);
}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 14e77258c65e..dcbb4ac2d5f3 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -111,7 +111,7 @@ interface IPackageManager {
int getPermissionFlags(String permissionName, String packageName, int userId);
void updatePermissionFlags(String permissionName, String packageName, int flagMask,
- int flagValues, int userId);
+ int flagValues, boolean checkAdjustPolicyFlagPermission, int userId);
void updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId);
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index b0d16cdace21..f87ce827dbfb 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -514,7 +514,8 @@ public class LauncherApps {
/**
* Retrieves a list of launchable activities that match {@link Intent#ACTION_MAIN} and
- * {@link Intent#CATEGORY_LAUNCHER}, for a specified user.
+ * {@link Intent#CATEGORY_LAUNCHER}, for a specified user. Result may include
+ * synthesized activities like app details Activity injected by system.
*
* @param packageName The specific package to query. If null, it checks all installed packages
* in the profile.
diff --git a/core/java/android/content/pm/OrgApacheHttpLegacyUpdater.java b/core/java/android/content/pm/OrgApacheHttpLegacyUpdater.java
index 7790067b03de..707443b19679 100644
--- a/core/java/android/content/pm/OrgApacheHttpLegacyUpdater.java
+++ b/core/java/android/content/pm/OrgApacheHttpLegacyUpdater.java
@@ -18,6 +18,7 @@ package android.content.pm;
import static android.content.pm.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY;
import android.content.pm.PackageParser.Package;
+import android.os.Build;
import com.android.internal.annotations.VisibleForTesting;
@@ -30,6 +31,11 @@ import com.android.internal.annotations.VisibleForTesting;
@VisibleForTesting
public class OrgApacheHttpLegacyUpdater extends PackageSharedLibraryUpdater {
+ private static boolean apkTargetsApiLevelLessThanOrEqualToOMR1(Package pkg) {
+ int targetSdkVersion = pkg.applicationInfo.targetSdkVersion;
+ return targetSdkVersion < Build.VERSION_CODES.P;
+ }
+
@Override
public void updatePackage(Package pkg) {
// Packages targeted at <= O_MR1 expect the classes in the org.apache.http.legacy library
diff --git a/core/java/android/content/pm/PackageBackwardCompatibility.java b/core/java/android/content/pm/PackageBackwardCompatibility.java
index b19196a9b636..4331bd4ac4d4 100644
--- a/core/java/android/content/pm/PackageBackwardCompatibility.java
+++ b/core/java/android/content/pm/PackageBackwardCompatibility.java
@@ -116,7 +116,7 @@ public class PackageBackwardCompatibility extends PackageSharedLibraryUpdater {
private final PackageSharedLibraryUpdater[] mPackageUpdaters;
- public PackageBackwardCompatibility(
+ private PackageBackwardCompatibility(
boolean bootClassPathContainsATB, PackageSharedLibraryUpdater[] packageUpdaters) {
this.mBootClassPathContainsATB = bootClassPathContainsATB;
this.mPackageUpdaters = packageUpdaters;
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 80954731bffb..0304f19cc5b4 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -590,6 +590,30 @@ public class PackageInstaller {
}
}
+ /**
+ * Install the given package, which already exists on the device, for the user for which this
+ * installer was created.
+ *
+ * @param packageName The package to install.
+ * @param installReason Reason for install.
+ * @param statusReceiver Where to deliver the result.
+ */
+ @RequiresPermission(allOf = {
+ Manifest.permission.INSTALL_PACKAGES,
+ Manifest.permission.INSTALL_EXISTING_PACKAGES})
+ public void installExistingPackage(@NonNull String packageName,
+ @InstallReason int installReason,
+ @Nullable IntentSender statusReceiver) {
+ Preconditions.checkNotNull(packageName, "packageName cannot be null");
+ try {
+ mInstaller.installExistingPackage(packageName, 0, installReason, statusReceiver,
+ mUserId);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+
/** {@hide} */
@SystemApi
@RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES)
@@ -1545,7 +1569,11 @@ public class PackageInstaller {
/**
* Set this session to be installing an APEX package.
+ *
+ * {@hide}
*/
+ @SystemApi
+ @RequiresPermission(Manifest.permission.INSTALL_PACKAGES)
public void setInstallAsApex() {
installFlags |= PackageManager.INSTALL_APEX;
}
@@ -1715,11 +1743,11 @@ public class PackageInstaller {
public int[] childSessionIds = NO_SESSIONS;
/** {@hide} */
- public boolean isSessionApplied;
+ public boolean isStagedSessionApplied;
/** {@hide} */
- public boolean isSessionReady;
+ public boolean isStagedSessionReady;
/** {@hide} */
- public boolean isSessionFailed;
+ public boolean isStagedSessionFailed;
private int mStagedSessionErrorCode;
private String mStagedSessionErrorMessage;
@@ -1758,9 +1786,9 @@ public class PackageInstaller {
if (childSessionIds == null) {
childSessionIds = NO_SESSIONS;
}
- isSessionApplied = source.readBoolean();
- isSessionReady = source.readBoolean();
- isSessionFailed = source.readBoolean();
+ isStagedSessionApplied = source.readBoolean();
+ isStagedSessionReady = source.readBoolean();
+ isStagedSessionFailed = source.readBoolean();
mStagedSessionErrorCode = source.readInt();
mStagedSessionErrorMessage = source.readString();
}
@@ -2054,36 +2082,46 @@ public class PackageInstaller {
return childSessionIds;
}
+ private void checkSessionIsStaged() {
+ if (!isStaged) {
+ throw new IllegalStateException("Session is not marked as staged.");
+ }
+ }
+
/**
* Whether the staged session has been applied successfully, meaning that all of its
* packages have been activated and no further action is required.
* Only meaningful if {@code isStaged} is true.
*/
- public boolean isSessionApplied() {
- return isSessionApplied;
+ public boolean isStagedSessionApplied() {
+ checkSessionIsStaged();
+ return isStagedSessionApplied;
}
/**
* Whether the staged session is ready to be applied at next reboot. Only meaningful if
* {@code isStaged} is true.
*/
- public boolean isSessionReady() {
- return isSessionReady;
+ public boolean isStagedSessionReady() {
+ checkSessionIsStaged();
+ return isStagedSessionReady;
}
/**
* Whether something went wrong and the staged session is declared as failed, meaning that
* it will be ignored at next reboot. Only meaningful if {@code isStaged} is true.
*/
- public boolean isSessionFailed() {
- return isSessionFailed;
+ public boolean isStagedSessionFailed() {
+ checkSessionIsStaged();
+ return isStagedSessionFailed;
}
/**
* If something went wrong with a staged session, clients can check this error code to
* understand which kind of failure happened. Only meaningful if {@code isStaged} is true.
*/
- public int getStagedSessionErrorCode() {
+ public @StagedSessionErrorCode int getStagedSessionErrorCode() {
+ checkSessionIsStaged();
return mStagedSessionErrorCode;
}
@@ -2092,6 +2130,7 @@ public class PackageInstaller {
* empty string if no error was encountered.
*/
public String getStagedSessionErrorMessage() {
+ checkSessionIsStaged();
return mStagedSessionErrorMessage;
}
@@ -2134,9 +2173,9 @@ public class PackageInstaller {
dest.writeBoolean(isStaged);
dest.writeInt(parentSessionId);
dest.writeIntArray(childSessionIds);
- dest.writeBoolean(isSessionApplied);
- dest.writeBoolean(isSessionReady);
- dest.writeBoolean(isSessionFailed);
+ dest.writeBoolean(isStagedSessionApplied);
+ dest.writeBoolean(isStagedSessionReady);
+ dest.writeBoolean(isStagedSessionFailed);
dest.writeInt(mStagedSessionErrorCode);
dest.writeString(mStagedSessionErrorMessage);
}
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 00419212544a..a5464c2137af 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -33,6 +33,7 @@ import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
import android.annotation.XmlRes;
import android.app.ActivityManager;
+import android.app.AppDetailsActivity;
import android.app.PackageDeleteObserver;
import android.app.PackageInstallObserver;
import android.app.admin.DevicePolicyManager;
@@ -2564,6 +2565,14 @@ public abstract class PackageManager {
public static final String FEATURE_PC = "android.hardware.type.pc";
/**
+ * Feature for {@link #getSystemAvailableFeatures} and
+ * {@link #hasSystemFeature}: This is a foldable device. Properties such as
+ * the display size may change in response to being folded.
+ */
+ @SdkConstant(SdkConstantType.FEATURE)
+ public static final String FEATURE_FOLDABLE = "android.hardware.type.foldable";
+
+ /**
* Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}:
* The device supports printing.
*/
@@ -3030,6 +3039,13 @@ public abstract class PackageManager {
public static final int MASK_PERMISSION_FLAGS = 0xFF;
/**
+ * Injected activity in app that forwards user to setting activity of that app.
+ *
+ * @hide
+ */
+ public static final String APP_DETAILS_ACTIVITY_CLASS_NAME = AppDetailsActivity.class.getName();
+
+ /**
* This is a library that contains components apps can invoke. For
* example, a services for apps to bind to, or standard chooser UI,
* etc. This library is versioned and backwards compatible. Clients
@@ -5114,7 +5130,10 @@ public abstract class PackageManager {
* If there is already an application with the given package name installed
* on the system for other users, also install it for the calling user.
* @hide
+ *
+ * @deprecated use {@link PackageInstaller#installExistingPackage()} instead.
*/
+ @Deprecated
@SystemApi
public abstract int installExistingPackage(String packageName) throws NameNotFoundException;
@@ -5122,7 +5141,10 @@ public abstract class PackageManager {
* If there is already an application with the given package name installed
* on the system for other users, also install it for the calling user.
* @hide
+ *
+ * @deprecated use {@link PackageInstaller#installExistingPackage()} instead.
*/
+ @Deprecated
@SystemApi
public abstract int installExistingPackage(String packageName, @InstallReason int installReason)
throws NameNotFoundException;
@@ -5131,7 +5153,10 @@ public abstract class PackageManager {
* If there is already an application with the given package name installed
* on the system for other users, also install it for the specified user.
* @hide
+ *
+ * @deprecated use {@link PackageInstaller#installExistingPackage()} instead.
*/
+ @Deprecated
@RequiresPermission(anyOf = {
Manifest.permission.INSTALL_EXISTING_PACKAGES,
Manifest.permission.INSTALL_PACKAGES,
@@ -5792,6 +5817,37 @@ public abstract class PackageManager {
@NonNull ComponentName componentName);
/**
+ * Set the enabled setting for a package app settings activity.
+ *
+ * @param packageName The package name of the app
+ * @param enabled The new enabled state for app details activity
+ *
+ * @hide
+ */
+ @RequiresPermission(value = android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE,
+ conditional = true)
+ @SystemApi
+ public void setAppDetailsActivityEnabled(@NonNull String packageName, boolean enabled) {
+ throw new UnsupportedOperationException(
+ "setAppDetailsActivityEnabled not implemented");
+ }
+
+
+ /**
+ * Return the enabled setting for a package app settings activity.
+ *
+ * @param packageName The package name of the app
+ * @return Returns the current enabled state for app settings activity.
+ *
+ * @hide
+ */
+ @SystemApi
+ public boolean getAppDetailsActivityEnabled(@NonNull String packageName) {
+ throw new UnsupportedOperationException(
+ "getAppDetailsActivityEnabled not implemented");
+ }
+
+ /**
* Set the enabled setting for an application
* This setting will override any enabled state which may have been set by the application in
* its manifest. It also overrides the enabled state set in the manifest for any of the
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 0f67262bf901..4db7d0a91c6a 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -48,7 +48,6 @@ import android.annotation.Nullable;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.app.ActivityTaskManager;
-import android.app.AppDetailsActivity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.IntentFilter;
@@ -725,6 +724,9 @@ public class PackageParser {
for (int i = 0; i < N; i++) {
final Activity a = p.activities.get(i);
if (state.isMatch(a.info, flags)) {
+ if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(a.className)) {
+ continue;
+ }
res[num++] = generateActivityInfo(a, flags, state, userId);
}
}
@@ -4311,7 +4313,7 @@ public class PackageParser {
} else {
String outInfoName
= buildClassName(owner.applicationInfo.packageName, name, outError);
- if (AppDetailsActivity.class.getName().equals(outInfoName)) {
+ if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(outInfoName)) {
outError[0] = tag + " invalid android:name";
return false;
}
@@ -4364,13 +4366,14 @@ public class PackageParser {
boolean hardwareAccelerated) {
// Build custom App Details activity info instead of parsing it from xml
- Activity a = new Activity(owner, AppDetailsActivity.class.getName(), new ActivityInfo());
+ Activity a = new Activity(owner, PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME,
+ new ActivityInfo());
a.owner = owner;
a.setPackageName(owner.packageName);
a.info.theme = android.R.style.Theme_NoDisplay;
a.info.exported = true;
- a.info.name = AppDetailsActivity.class.getName();
+ a.info.name = PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME;
a.info.processName = owner.applicationInfo.processName;
a.info.uiOptions = a.info.applicationInfo.uiOptions;
a.info.taskAffinity = buildTaskAffinityName(owner.packageName, owner.packageName,
diff --git a/core/java/android/content/pm/PackageSharedLibraryUpdater.java b/core/java/android/content/pm/PackageSharedLibraryUpdater.java
index b14b321a2481..1565d9ce77d4 100644
--- a/core/java/android/content/pm/PackageSharedLibraryUpdater.java
+++ b/core/java/android/content/pm/PackageSharedLibraryUpdater.java
@@ -17,7 +17,6 @@ package android.content.pm;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.os.Build;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
@@ -60,11 +59,6 @@ public abstract class PackageSharedLibraryUpdater {
|| ArrayUtils.contains(usesOptionalLibraries, apacheHttpLegacy);
}
- static boolean apkTargetsApiLevelLessThanOrEqualToOMR1(PackageParser.Package pkg) {
- int targetSdkVersion = pkg.applicationInfo.targetSdkVersion;
- return targetSdkVersion < Build.VERSION_CODES.P;
- }
-
/**
* Add an implicit dependency.
*
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index b1553250d638..e674b8b7fd3d 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -18,6 +18,7 @@ package android.content.pm;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.annotation.UserIdInt;
@@ -1482,6 +1483,7 @@ public final class ShortcutInfo implements Parcelable {
* @hide
*/
@Nullable
+ @SystemApi
public Person[] getPersons() {
return clonePersons(mPersons);
}
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
index 849fd03eacb3..bd327b0be874 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -644,6 +644,7 @@ public class ShortcutManager {
* @return True if the package has any share target definitions, False otherwise.
* @hide
*/
+ @SystemApi
public boolean hasShareTargets(@NonNull String packageName) {
try {
return mService.hasShareTargets(mContext.getPackageName(), packageName,
diff --git a/core/java/android/hardware/display/BrightnessConfiguration.java b/core/java/android/hardware/display/BrightnessConfiguration.java
index 8c74ddc7698c..ed8a97c7e263 100644
--- a/core/java/android/hardware/display/BrightnessConfiguration.java
+++ b/core/java/android/hardware/display/BrightnessConfiguration.java
@@ -16,6 +16,7 @@
package android.hardware.display;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
@@ -93,7 +94,7 @@ public final class BrightnessConfiguration implements Parcelable {
*
*/
@Nullable
- public BrightnessCorrection getCorrectionByPackageName(String packageName) {
+ public BrightnessCorrection getCorrectionByPackageName(@NonNull String packageName) {
return mCorrectionsByPackageName.get(packageName);
}
@@ -106,7 +107,7 @@ public final class BrightnessConfiguration implements Parcelable {
* @return The matching brightness correction, or null.
*/
@Nullable
- public BrightnessCorrection getCorrectionByCategory(int category) {
+ public BrightnessCorrection getCorrectionByCategory(@ApplicationInfo.Category int category) {
return mCorrectionsByCategory.get(category);
}
@@ -238,7 +239,7 @@ public final class BrightnessConfiguration implements Parcelable {
*
* @hide
*/
- public void saveToXml(XmlSerializer serializer) throws IOException {
+ public void saveToXml(@NonNull XmlSerializer serializer) throws IOException {
serializer.startTag(null, TAG_BRIGHTNESS_CURVE);
if (mDescription != null) {
serializer.attribute(null, ATTR_DESCRIPTION, mDescription);
@@ -284,7 +285,7 @@ public final class BrightnessConfiguration implements Parcelable {
*
* @hide
*/
- public static BrightnessConfiguration loadFromXml(XmlPullParser parser)
+ public static BrightnessConfiguration loadFromXml(@NonNull XmlPullParser parser)
throws IOException, XmlPullParserException {
String description = null;
List<Float> luxList = new ArrayList<>();
@@ -443,8 +444,10 @@ public final class BrightnessConfiguration implements Parcelable {
* {@link #getMaxCorrectionsByPackageName}).
*
*/
- public Builder addCorrectionByPackageName(String packageName,
- BrightnessCorrection correction) {
+ public Builder addCorrectionByPackageName(@NonNull String packageName,
+ @NonNull BrightnessCorrection correction) {
+ Objects.requireNonNull(packageName, "packageName must not be null");
+ Objects.requireNonNull(correction, "correction must not be null");
if (mCorrectionsByPackageName.size() >= getMaxCorrectionsByPackageName()) {
throw new IllegalArgumentException("Too many corrections by package name");
}
@@ -470,7 +473,8 @@ public final class BrightnessConfiguration implements Parcelable {
*
*/
public Builder addCorrectionByCategory(@ApplicationInfo.Category int category,
- BrightnessCorrection correction) {
+ @NonNull BrightnessCorrection correction) {
+ Objects.requireNonNull(correction, "correction must not be null");
if (mCorrectionsByCategory.size() >= getMaxCorrectionsByCategory()) {
throw new IllegalArgumentException("Too many corrections by category");
}
diff --git a/core/java/android/hardware/display/BrightnessCorrection.java b/core/java/android/hardware/display/BrightnessCorrection.java
index 6a073ffaaa5b..ee8d8467d827 100644
--- a/core/java/android/hardware/display/BrightnessCorrection.java
+++ b/core/java/android/hardware/display/BrightnessCorrection.java
@@ -16,6 +16,7 @@
package android.hardware.display;
+import android.annotation.FloatRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
@@ -59,15 +60,15 @@ public final class BrightnessCorrection implements Parcelable {
/**
* Creates a BrightnessCorrection that given {@code brightness}, corrects it to be
- * {@code exp(scale * log(brightness) + translate)}.
+ * {@code exp(scale * ln(brightness) + translate)}.
*
* @param scale
- * How much to scale the log brightness.
+ * How much to scale the log (base e) brightness.
* @param translate
- * How much to translate the log brightness.
+ * How much to translate the log (base e) brightness.
*
* @return A BrightnessCorrection that given {@code brightness}, corrects it to be
- * {@code exp(scale * log(brightness) + translate)}.
+ * {@code exp(scale * ln(brightness) + translate)}.
*
* @throws IllegalArgumentException
* - scale or translate are NaN.
@@ -87,7 +88,8 @@ public final class BrightnessCorrection implements Parcelable {
*
* @return The corrected brightness.
*/
- public float apply(float brightness) {
+ @FloatRange(from = 0.0)
+ public float apply(@FloatRange(from = 0.0) float brightness) {
return mImplementation.apply(brightness);
}
@@ -202,7 +204,7 @@ public final class BrightnessCorrection implements Parcelable {
/**
* A BrightnessCorrection that given {@code brightness}, corrects it to be
- * {@code exp(scale * log(brightness) + translate)}.
+ * {@code exp(scale * ln(brightness) + translate)}.
*/
private static class ScaleAndTranslateLog implements BrightnessCorrectionImplementation {
private static final float MIN_SCALE = 0.5f;
diff --git a/core/java/android/metrics/LogMaker.java b/core/java/android/metrics/LogMaker.java
index 19848ee6d415..5496e17206d9 100644
--- a/core/java/android/metrics/LogMaker.java
+++ b/core/java/android/metrics/LogMaker.java
@@ -16,6 +16,7 @@
package android.metrics;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.content.ComponentName;
import android.util.Log;
import android.util.SparseArray;
@@ -31,6 +32,7 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
* @hide
*/
@SystemApi
+@TestApi
public class LogMaker {
private static final String TAG = "LogBuilder";
diff --git a/core/java/android/metrics/MetricsReader.java b/core/java/android/metrics/MetricsReader.java
index 5f356ca00d88..27f9a5dbf51c 100644
--- a/core/java/android/metrics/MetricsReader.java
+++ b/core/java/android/metrics/MetricsReader.java
@@ -16,6 +16,7 @@
package android.metrics;
import android.annotation.SystemApi;
+import android.annotation.TestApi;
import android.util.EventLog;
import com.android.internal.annotations.VisibleForTesting;
@@ -35,6 +36,7 @@ import java.util.concurrent.TimeUnit;
* @hide
*/
@SystemApi
+@TestApi
public class MetricsReader {
private Queue<LogMaker> mPendingQueue = new LinkedList<>();
private Queue<LogMaker> mSeenQueue = new LinkedList<>();
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 6d195ae47449..c1bce5e52a8d 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -3147,9 +3147,9 @@ public class ConnectivityManager {
/**
* Called if no network is found in the timeout time specified in
- * {@link #requestNetwork(NetworkRequest, NetworkCallback, int)} call. This callback is not
- * called for the version of {@link #requestNetwork(NetworkRequest, NetworkCallback)}
- * without timeout. When this callback is invoked the associated
+ * {@link #requestNetwork(NetworkRequest, NetworkCallback, int)} call or if the
+ * requested network request cannot be fulfilled (whether or not a timeout was
+ * specified). When this callback is invoked the associated
* {@link NetworkRequest} will have already been removed and released, as if
* {@link #unregisterNetworkCallback(NetworkCallback)} had been called.
*/
diff --git a/core/java/android/net/NetworkFactory.java b/core/java/android/net/NetworkFactory.java
index 0dfe7a495738..5b1d12c603b4 100644
--- a/core/java/android/net/NetworkFactory.java
+++ b/core/java/android/net/NetworkFactory.java
@@ -27,11 +27,13 @@ import android.util.Log;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.AsyncChannel;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Protocol;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -113,7 +115,16 @@ public class NetworkFactory extends Handler {
*/
private static final int CMD_SET_FILTER = BASE + 3;
+ /**
+ * Sent by NetworkFactory to ConnectivityService to indicate that a request is
+ * unfulfillable.
+ * @see #releaseRequestAsUnfulfillableByAnyFactory(NetworkRequest).
+ */
+ public static final int EVENT_UNFULFILLABLE_REQUEST = BASE + 4;
+
private final Context mContext;
+ private final ArrayList<Message> mPreConnectedQueue = new ArrayList<Message>();
+ private AsyncChannel mAsyncChannel;
private final String LOG_TAG;
private final SparseArray<NetworkRequestInfo> mNetworkRequests =
@@ -155,6 +166,36 @@ public class NetworkFactory extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
+ case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
+ if (mAsyncChannel != null) {
+ log("Received new connection while already connected!");
+ break;
+ }
+ if (VDBG) log("NetworkFactory fully connected");
+ AsyncChannel ac = new AsyncChannel();
+ ac.connected(null, this, msg.replyTo);
+ ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
+ AsyncChannel.STATUS_SUCCESSFUL);
+ mAsyncChannel = ac;
+ for (Message m : mPreConnectedQueue) {
+ ac.sendMessage(m);
+ }
+ mPreConnectedQueue.clear();
+ break;
+ }
+ case AsyncChannel.CMD_CHANNEL_DISCONNECT: {
+ if (VDBG) log("CMD_CHANNEL_DISCONNECT");
+ if (mAsyncChannel != null) {
+ mAsyncChannel.disconnect();
+ mAsyncChannel = null;
+ }
+ break;
+ }
+ case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
+ if (DBG) log("NetworkFactory channel lost");
+ mAsyncChannel = null;
+ break;
+ }
case CMD_REQUEST_NETWORK: {
handleAddRequest((NetworkRequest) msg.obj, msg.arg1, msg.arg2);
break;
@@ -355,6 +396,27 @@ public class NetworkFactory extends Handler {
});
}
+ /**
+ * Can be called by a factory to release a request as unfulfillable: the request will be
+ * removed, and the caller will get a
+ * {@link ConnectivityManager.NetworkCallback#onUnavailable()} callback after this function
+ * returns.
+ *
+ * Note: this should only be called by factory which KNOWS that it is the ONLY factory which
+ * is able to fulfill this request!
+ */
+ protected void releaseRequestAsUnfulfillableByAnyFactory(NetworkRequest r) {
+ post(() -> {
+ if (DBG) log("releaseRequestAsUnfulfillableByAnyFactory: " + r);
+ Message msg = obtainMessage(EVENT_UNFULFILLABLE_REQUEST, r);
+ if (mAsyncChannel != null) {
+ mAsyncChannel.sendMessage(msg);
+ } else {
+ mPreConnectedQueue.add(msg);
+ }
+ });
+ }
+
// override to do simple mode (request independent)
protected void startNetwork() { }
protected void stopNetwork() { }
diff --git a/core/java/android/os/BugreportManager.java b/core/java/android/os/BugreportManager.java
index 27f7e2296e7f..684369a6f720 100644
--- a/core/java/android/os/BugreportManager.java
+++ b/core/java/android/os/BugreportManager.java
@@ -59,7 +59,8 @@ public class BugreportManager {
BUGREPORT_ERROR_INVALID_INPUT,
BUGREPORT_ERROR_RUNTIME,
BUGREPORT_ERROR_USER_DENIED_CONSENT,
- BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT
+ BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT,
+ BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS
})
/** Possible error codes taking a bugreport can encounter */
@@ -81,6 +82,10 @@ public class BugreportManager {
public static final int BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT =
IDumpstateListener.BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT;
+ /** There is currently a bugreport running. The caller should try again later. */
+ public static final int BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS =
+ IDumpstateListener.BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS;
+
/**
* Called when there is a progress update.
* @param progress the progress in [0.0, 100.0]
@@ -96,6 +101,9 @@ public class BugreportManager {
* <p>If {@code BUGREPORT_ERROR_USER_CONSENT_TIMED_OUT} is passed, then the consent timed
* out, but the bugreport could be available in the internal directory of dumpstate for
* manual retrieval.
+ *
+ * <p> If {@code BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS} is passed, then the
+ * caller should try later, as only one bugreport can be in progress at a time.
*/
public void onError(@BugreportErrorCode int errorCode) {}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 83a7654d494b..0425c6234a04 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -107,6 +107,7 @@ public class Build {
* Whether this build was for an emulator device.
* @hide
*/
+ @TestApi
public static final boolean IS_EMULATOR = getString("ro.kernel.qemu").equals("1");
/**
diff --git a/core/java/android/os/GraphicsEnvironment.java b/core/java/android/os/GraphicsEnvironment.java
index 47b1eefdcb07..650d21785ec2 100644
--- a/core/java/android/os/GraphicsEnvironment.java
+++ b/core/java/android/os/GraphicsEnvironment.java
@@ -664,8 +664,15 @@ public class GraphicsEnvironment {
.append(abi);
final String paths = sb.toString();
- if (DEBUG) Log.v(TAG, "gfx driver package libs: " + paths);
- setDriverPath(paths);
+ final String sphalLibraries =
+ coreSettings.getString(Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES);
+
+ if (DEBUG) {
+ Log.v(TAG,
+ "gfx driver package search path: " + paths
+ + ", required sphal libraries: " + sphalLibraries);
+ }
+ setDriverPathAndSphalLibraries(paths, sphalLibraries);
if (driverAppInfo.metaData == null) {
throw new NullPointerException("apk's meta-data cannot be null");
@@ -700,7 +707,7 @@ public class GraphicsEnvironment {
private static native void setLayerPaths(ClassLoader classLoader, String layerPaths);
private static native void setDebugLayers(String layers);
private static native void setDebugLayersGLES(String layers);
- private static native void setDriverPath(String path);
+ private static native void setDriverPathAndSphalLibraries(String path, String sphalLibraries);
private static native void setGpuStats(String driverPackageName, String driverVersionName,
long driverVersionCode, long driverBuildTime, String appPackageName);
private static native void setAngleInfo(String path, String appPackage, String devOptIn,
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 6bd1f2b59fad..91ddf82b5400 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -1569,7 +1569,7 @@ public final class PowerManager {
@LocationPowerSaveMode
public int getLocationPowerSaveMode() {
final PowerSaveState powerSaveState = getPowerSaveState(ServiceType.LOCATION);
- if (!powerSaveState.globalBatterySaverEnabled) {
+ if (!powerSaveState.batterySaverEnabled) {
return LOCATION_MODE_NO_CHANGE;
}
return powerSaveState.locationMode;
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index e2b5730e10f4..067375590c99 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -2697,6 +2697,19 @@ public class UserManager {
}
/**
+ * Updates the calling user's name.
+ * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+ *
+ * @param name the new name for the user
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+ public void setUserName(String name) {
+ setUserName(getUserHandle(), name);
+ }
+
+ /**
* Sets the user's photo.
* @param userHandle the user for whom to change the photo.
* @param icon the bitmap to set as the photo.
@@ -2711,6 +2724,19 @@ public class UserManager {
}
/**
+ * Sets the calling user's photo.
+ * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+ *
+ * @param icon the bitmap to set as the photo.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+ public void setUserIcon(Bitmap icon) {
+ setUserIcon(getUserHandle(), icon);
+ }
+
+ /**
* Returns a file descriptor for the user's photo. PNG data can be read from this file.
* @param userHandle the user whose photo we want to read.
* @return a {@link Bitmap} of the user's photo, or null if there's no photo.
@@ -2737,6 +2763,20 @@ public class UserManager {
}
/**
+ * Returns a Bitmap for the calling user's photo.
+ * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+ *
+ * @return a {@link Bitmap} of the user's photo, or null if there's no photo.
+ * @see com.android.internal.util.UserIcons#getDefaultUserIcon for a default.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
+ public Bitmap getUserIcon() {
+ return getUserIcon(getUserHandle());
+ }
+
+ /**
* Returns the maximum number of users that can be created on this device. A return value
* of 1 means that it is a single user device.
* @hide
diff --git a/core/java/android/permission/IPermissionController.aidl b/core/java/android/permission/IPermissionController.aidl
index 7e9ba5d4b628..cb2517e956df 100644
--- a/core/java/android/permission/IPermissionController.aidl
+++ b/core/java/android/permission/IPermissionController.aidl
@@ -40,4 +40,6 @@ oneway interface IPermissionController {
void getPermissionUsages(boolean countSystem, long numMillis, in RemoteCallback callback);
void isApplicationQualifiedForRole(String roleName, String packageName,
in RemoteCallback callback);
+ void setRuntimePermissionGrantStateByDeviceAdmin(String callerPackageName, String packageName,
+ String permission, int grantState, in RemoteCallback callback);
}
diff --git a/core/java/android/permission/PermissionControllerManager.java b/core/java/android/permission/PermissionControllerManager.java
index d62bc6c5a872..9d58064ab6d0 100644
--- a/core/java/android/permission/PermissionControllerManager.java
+++ b/core/java/android/permission/PermissionControllerManager.java
@@ -16,8 +16,12 @@
package android.permission;
+import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT;
+import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED;
+import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED;
import static android.permission.PermissionControllerService.SERVICE_INTERFACE;
+import static com.android.internal.util.Preconditions.checkArgument;
import static com.android.internal.util.Preconditions.checkArgumentNonnegative;
import static com.android.internal.util.Preconditions.checkCollectionElementsNotNull;
import static com.android.internal.util.Preconditions.checkFlagsArgument;
@@ -35,6 +39,7 @@ import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
+import android.app.admin.DevicePolicyManager.PermissionGrantState;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -268,6 +273,40 @@ public final class PermissionControllerManager {
}
/**
+ * Set the runtime permission state from a device admin.
+ *
+ * @param callerPackageName The package name of the admin requesting the change
+ * @param packageName Package the permission belongs to
+ * @param permission Permission to change
+ * @param grantState State to set the permission into
+ * @param executor Executor to run the {@code callback} on
+ * @param callback The callback
+ *
+ * @hide
+ */
+ @RequiresPermission(allOf = {Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
+ Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
+ Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY},
+ conditional = true)
+ public void setRuntimePermissionGrantStateByDeviceAdmin(@NonNull String callerPackageName,
+ @NonNull String packageName, @NonNull String permission,
+ @PermissionGrantState int grantState, @NonNull @CallbackExecutor Executor executor,
+ @NonNull Consumer<Boolean> callback) {
+ checkStringNotEmpty(callerPackageName);
+ checkStringNotEmpty(packageName);
+ checkStringNotEmpty(permission);
+ checkArgument(grantState == PERMISSION_GRANT_STATE_GRANTED
+ || grantState == PERMISSION_GRANT_STATE_DENIED
+ || grantState == PERMISSION_GRANT_STATE_DEFAULT);
+ checkNotNull(executor);
+ checkNotNull(callback);
+
+ mRemoteService.scheduleRequest(new PendingSetRuntimePermissionGrantStateByDeviceAdmin(
+ mRemoteService, callerPackageName, packageName, permission, grantState, executor,
+ callback));
+ }
+
+ /**
* Create a backup of the runtime permissions.
*
* @param user The user to be backed up
@@ -480,7 +519,7 @@ public final class PermissionControllerManager {
}
@Override
- public void scheduleRequest(@NonNull PendingRequest<RemoteService,
+ public void scheduleRequest(@NonNull BasePendingRequest<RemoteService,
IPermissionController> pendingRequest) {
super.scheduleRequest(pendingRequest);
}
@@ -797,6 +836,67 @@ public final class PermissionControllerManager {
}
/**
+ * Request for {@link #getRuntimePermissionBackup}
+ */
+ private static final class PendingSetRuntimePermissionGrantStateByDeviceAdmin extends
+ AbstractRemoteService.PendingRequest<RemoteService, IPermissionController> {
+ private final @NonNull String mCallerPackageName;
+ private final @NonNull String mPackageName;
+ private final @NonNull String mPermission;
+ private final @PermissionGrantState int mGrantState;
+
+ private final @NonNull Executor mExecutor;
+ private final @NonNull Consumer<Boolean> mCallback;
+ private final @NonNull RemoteCallback mRemoteCallback;
+
+ private PendingSetRuntimePermissionGrantStateByDeviceAdmin(@NonNull RemoteService service,
+ @NonNull String callerPackageName, @NonNull String packageName,
+ @NonNull String permission, @PermissionGrantState int grantState,
+ @NonNull @CallbackExecutor Executor executor, @NonNull Consumer<Boolean> callback) {
+ super(service);
+
+ mCallerPackageName = callerPackageName;
+ mPackageName = packageName;
+ mPermission = permission;
+ mGrantState = grantState;
+ mExecutor = executor;
+ mCallback = callback;
+
+ mRemoteCallback = new RemoteCallback(result -> executor.execute(() -> {
+ long token = Binder.clearCallingIdentity();
+ try {
+ callback.accept(result.getBoolean(KEY_RESULT, false));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+
+ finish();
+ }
+ }), null);
+ }
+
+ @Override
+ protected void onTimeout(RemoteService remoteService) {
+ long token = Binder.clearCallingIdentity();
+ try {
+ mExecutor.execute(() -> mCallback.accept(false));
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override
+ public void run() {
+ try {
+ getService().getServiceInterface().setRuntimePermissionGrantStateByDeviceAdmin(
+ mCallerPackageName, mPackageName, mPermission, mGrantState, mRemoteCallback);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error setting permissions state for device admin " + mPackageName,
+ e);
+ }
+ }
+ }
+
+ /**
* Request for {@link #restoreRuntimePermissionBackup}
*/
private static final class PendingRestoreRuntimePermissionBackup implements
diff --git a/core/java/android/permission/PermissionControllerService.java b/core/java/android/permission/PermissionControllerService.java
index fb6c061c536f..e883d25ab0bd 100644
--- a/core/java/android/permission/PermissionControllerService.java
+++ b/core/java/android/permission/PermissionControllerService.java
@@ -16,6 +16,9 @@
package android.permission;
+import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT;
+import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED;
+import static android.app.admin.DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED;
import static android.permission.PermissionControllerManager.COUNT_ONLY_WHEN_GRANTED;
import static android.permission.PermissionControllerManager.COUNT_WHEN_SYSTEM;
@@ -32,6 +35,7 @@ import android.annotation.BinderThread;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.app.Service;
+import android.app.admin.DevicePolicyManager.PermissionGrantState;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
@@ -180,6 +184,18 @@ public abstract class PermissionControllerService extends Service {
public abstract boolean onIsApplicationQualifiedForRole(@NonNull String roleName,
@NonNull String packageName);
+ /**
+ * Set the runtime permission state from a device admin.
+ *
+ * @param callerPackageName The package name of the admin requesting the change
+ * @param packageName Package the permission belongs to
+ * @param permission Permission to change
+ * @param grantState State to set the permission into
+ */
+ public abstract boolean onSetRuntimePermissionGrantStateByDeviceAdmin(
+ @NonNull String callerPackageName, @NonNull String packageName,
+ @NonNull String permission, @PermissionGrantState int grantState);
+
@Override
public final IBinder onBind(Intent intent) {
return new IPermissionController.Stub() {
@@ -326,6 +342,35 @@ public abstract class PermissionControllerService extends Service {
PermissionControllerService::isApplicationQualifiedForRole,
PermissionControllerService.this, roleName, packageName, callback));
}
+
+ @Override
+ public void setRuntimePermissionGrantStateByDeviceAdmin(String callerPackageName,
+ String packageName, String permission, int grantState,
+ RemoteCallback callback) {
+ checkStringNotEmpty(callerPackageName);
+ checkStringNotEmpty(packageName);
+ checkStringNotEmpty(permission);
+ checkArgument(grantState == PERMISSION_GRANT_STATE_GRANTED
+ || grantState == PERMISSION_GRANT_STATE_DENIED
+ || grantState == PERMISSION_GRANT_STATE_DEFAULT);
+ checkNotNull(callback);
+
+ if (grantState == PERMISSION_GRANT_STATE_DENIED) {
+ enforceCallingPermission(Manifest.permission.GRANT_RUNTIME_PERMISSIONS, null);
+ }
+
+ if (grantState == PERMISSION_GRANT_STATE_DENIED) {
+ enforceCallingPermission(Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, null);
+ }
+
+ enforceCallingPermission(Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
+ null);
+
+ mHandler.sendMessage(obtainMessage(
+ PermissionControllerService::setRuntimePermissionGrantStateByDeviceAdmin,
+ PermissionControllerService.this, callerPackageName, packageName,
+ permission, grantState, callback));
+ }
};
}
@@ -399,4 +444,15 @@ public abstract class PermissionControllerService extends Service {
result.putBoolean(PermissionControllerManager.KEY_RESULT, qualified);
callback.sendResult(result);
}
+
+ private void setRuntimePermissionGrantStateByDeviceAdmin(@NonNull String callerPackageName,
+ @NonNull String packageName, @NonNull String permission,
+ @PermissionGrantState int grantState, @NonNull RemoteCallback callback) {
+ boolean wasSet = onSetRuntimePermissionGrantStateByDeviceAdmin(callerPackageName,
+ packageName, permission, grantState);
+
+ Bundle result = new Bundle();
+ result.putBoolean(PermissionControllerManager.KEY_RESULT, wasSet);
+ callback.sendResult(result);
+ }
}
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index f63c0adbdf4b..44adc1c5cba4 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -783,7 +783,7 @@ public class CallLog {
String postDialDigits, String viaNumber, int presentation, int callType,
int features, PhoneAccountHandle accountHandle, long start, int duration,
Long dataUsage, boolean addForAllUsers, UserHandle userToBeInsertedTo,
- boolean isRead, int callBlockReason, String callScreeningAppName,
+ boolean isRead, int callBlockReason, CharSequence callScreeningAppName,
String callScreeningComponentName, CallIdentification callIdentification) {
if (VERBOSE_LOG) {
Log.v(LOG_TAG, String.format("Add call: number=%s, user=%s, for all=%s",
@@ -836,15 +836,19 @@ public class CallLog {
}
values.put(BLOCK_REASON, callBlockReason);
- values.put(CALL_SCREENING_APP_NAME, callScreeningAppName);
+ values.put(CALL_SCREENING_APP_NAME, charSequenceToString(callScreeningAppName));
values.put(CALL_SCREENING_COMPONENT_NAME, callScreeningComponentName);
if (callIdentification != null) {
values.put(CALL_ID_PACKAGE_NAME, callIdentification.getCallScreeningPackageName());
- values.put(CALL_ID_APP_NAME, callIdentification.getCallScreeningAppName());
- values.put(CALL_ID_NAME, callIdentification.getName());
- values.put(CALL_ID_DESCRIPTION, callIdentification.getDescription());
- values.put(CALL_ID_DETAILS, callIdentification.getDetails());
+ values.put(CALL_ID_APP_NAME,
+ charSequenceToString(callIdentification.getCallScreeningAppName()));
+ values.put(CALL_ID_NAME,
+ charSequenceToString(callIdentification.getName()));
+ values.put(CALL_ID_DESCRIPTION,
+ charSequenceToString(callIdentification.getDescription()));
+ values.put(CALL_ID_DETAILS,
+ charSequenceToString(callIdentification.getDetails()));
values.put(CALL_ID_NUISANCE_CONFIDENCE, callIdentification.getNuisanceConfidence());
} else {
values.putNull(CALL_ID_PACKAGE_NAME);
@@ -987,6 +991,10 @@ public class CallLog {
return result;
}
+ private static String charSequenceToString(CharSequence sequence) {
+ return sequence == null ? null : sequence.toString();
+ }
+
/** @hide */
public static boolean shouldHaveSharedCallLogEntries(Context context,
UserManager userManager, int userId) {
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index f6a8388a7d40..868a36b56bf4 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -169,7 +169,7 @@ public final class DeviceConfig {
*
* @hide for internal use only
*/
- String BLASTULA_POOL_SIZE_MIN = "blastula_pool_size_max";
+ String BLASTULA_POOL_SIZE_MIN = "blastula_pool_size_min";
/**
* The threshold used to determine if the pool should be refilled.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index a465b3271407..4c4bd6c2990f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1204,6 +1204,21 @@ public final class Settings {
public static final String ACTION_DREAM_SETTINGS = "android.settings.DREAM_SETTINGS";
/**
+ * Activity Action: Show Notification assistant settings.
+ * <p>
+ * In some cases, a matching Activity may not exist, so ensure you
+ * safeguard against this.
+ * <p>
+ * Input: Nothing.
+ * <p>
+ * Output: Nothing.
+ * @see android.service.notification.NotificationAssistantService
+ */
+ @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+ public static final String ACTION_NOTIFICATION_ASSISTANT_SETTINGS =
+ "android.settings.NOTIFICATION_ASSISTANT_SETTINGS";
+
+ /**
* Activity Action: Show Notification listener settings.
* <p>
* In some cases, a matching Activity may not exist, so ensure you
@@ -8131,6 +8146,7 @@ public final class Settings {
*
* @hide
*/
+ @TestApi
public static final String ENABLED_VR_LISTENERS = "enabled_vr_listeners";
private static final Validator ENABLED_VR_LISTENERS_VALIDATOR =
@@ -10780,6 +10796,7 @@ public final class Settings {
*
* @hide
*/
+ @TestApi
public static final String OVERLAY_DISPLAY_DEVICES = "overlay_display_devices";
/**
@@ -11506,6 +11523,7 @@ public final class Settings {
* @hide
* @see com.android.server.power.batterysaver.BatterySaverPolicy
*/
+ @TestApi
public static final String BATTERY_SAVER_CONSTANTS = "battery_saver_constants";
/**
@@ -13045,6 +13063,15 @@ public final class Settings {
*/
public static final String LTE_SERVICE_FORCED = "lte_service_forced";
+
+ /**
+ * Specifies the behaviour the lid triggers when closed
+ * <p>
+ * See WindowManagerPolicy.WindowManagerFuncs
+ * @hide
+ */
+ public static final String LID_BEHAVIOR = "lid_behavior";
+
/**
* Ephemeral app cookie max size in bytes.
* <p>
@@ -14096,17 +14123,16 @@ public final class Settings {
public static final String SHOW_TEMPERATURE_WARNING = "show_temperature_warning";
/**
- * Temperature at which the high temperature warning notification should be shown.
+ * Whether to show the usb high temperature alarm notification.
* @hide
*/
- public static final String WARNING_TEMPERATURE = "warning_temperature";
-
+ public static final String SHOW_USB_TEMPERATURE_ALARM = "show_usb_temperature_alarm";
/**
- * USB Temperature at which the high temperature alarm notification should be shown.
+ * Temperature at which the high temperature warning notification should be shown.
* @hide
*/
- public static final String USB_ALARM_TEMPERATURE = "usb_alarm_temperature";
+ public static final String WARNING_TEMPERATURE = "warning_temperature";
/**
* Whether the diskstats logging task is enabled/disabled.
diff --git a/core/java/android/service/autofill/FillRequest.java b/core/java/android/service/autofill/FillRequest.java
index 1d0c987403db..cbd0cd94c0e3 100644
--- a/core/java/android/service/autofill/FillRequest.java
+++ b/core/java/android/service/autofill/FillRequest.java
@@ -71,6 +71,14 @@ public final class FillRequest implements Parcelable {
*/
public static final int FLAG_COMPATIBILITY_MODE_REQUEST = 0x2;
+ // Private flags below start from the highest-significative bit (0x80000000)
+ /**
+ * Request was only triggered for augmented autofill.
+ *
+ * @hide
+ */
+ public static final int FLAG_AUGMENTED_AUTOFILL_REQUEST = 0x80000000;
+
/** @hide */
public static final int INVALID_REQUEST_ID = Integer.MIN_VALUE;
@@ -115,7 +123,8 @@ public final class FillRequest implements Parcelable {
/**
* Gets the flags associated with this request.
*
- * @see #FLAG_MANUAL_REQUEST
+ * @return any combination of {@link #FLAG_MANUAL_REQUEST} and
+ * {@link #FLAG_COMPATIBILITY_MODE_REQUEST}.
*/
public @RequestFlags int getFlags() {
return mFlags;
diff --git a/core/java/android/service/autofill/augmented/FillWindow.java b/core/java/android/service/autofill/augmented/FillWindow.java
index 6e06754e7b8a..bd532a32035c 100644
--- a/core/java/android/service/autofill/augmented/FillWindow.java
+++ b/core/java/android/service/autofill/augmented/FillWindow.java
@@ -82,6 +82,8 @@ public final class FillWindow implements AutoCloseable {
private Rect mBounds;
@GuardedBy("mLock")
+ private boolean mUpdateCalled;
+ @GuardedBy("mLock")
private boolean mDestroyed;
private AutofillProxy mProxy;
@@ -103,6 +105,7 @@ public final class FillWindow implements AutoCloseable {
}
// TODO(b/123100712): add test case for null
Preconditions.checkNotNull(area);
+ Preconditions.checkNotNull(area.proxy);
Preconditions.checkNotNull(rootView);
// TODO(b/123100712): must check the area is a valid object returned by
// SmartSuggestionParams, throw IAE if not
@@ -149,6 +152,7 @@ public final class FillWindow implements AutoCloseable {
if (DEBUG) {
Log.d(TAG, "Created FillWindow: params= " + smartSuggestion + " view=" + rootView);
}
+ mUpdateCalled = true;
mDestroyed = false;
mProxy.setFillWindow(this);
return true;
@@ -237,8 +241,10 @@ public final class FillWindow implements AutoCloseable {
}
synchronized (mLock) {
if (mDestroyed) return;
- hide();
- mProxy.report(AutofillProxy.REPORT_EVENT_UI_DESTROYED);
+ if (mUpdateCalled) {
+ hide();
+ mProxy.report(AutofillProxy.REPORT_EVENT_UI_DESTROYED);
+ }
mDestroyed = true;
mCloseGuard.close();
}
@@ -266,6 +272,7 @@ public final class FillWindow implements AutoCloseable {
public void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
synchronized (this) {
pw.print(prefix); pw.print("destroyed: "); pw.println(mDestroyed);
+ pw.print(prefix); pw.print("updateCalled: "); pw.println(mUpdateCalled);
if (mFillView != null) {
pw.print(prefix); pw.print("fill window: ");
pw.println(mShowing ? "shown" : "hidden");
diff --git a/core/java/android/text/style/DynamicDrawableSpan.java b/core/java/android/text/style/DynamicDrawableSpan.java
index 575401458691..1a508a1f6c6d 100644
--- a/core/java/android/text/style/DynamicDrawableSpan.java
+++ b/core/java/android/text/style/DynamicDrawableSpan.java
@@ -16,6 +16,9 @@
package android.text.style;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -25,6 +28,7 @@ import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
+import java.lang.annotation.Retention;
import java.lang.ref.WeakReference;
/**
@@ -80,10 +84,21 @@ public abstract class DynamicDrawableSpan extends ReplacementSpan {
/**
* A constant indicating that this span should be vertically centered between
* the top and the lowest descender.
- * @hide
*/
public static final int ALIGN_CENTER = 2;
+ /**
+ * Defines acceptable alignment types.
+ * @hide
+ */
+ @Retention(SOURCE)
+ @IntDef(prefix = { "ALIGN_" }, value = {
+ ALIGN_BOTTOM,
+ ALIGN_BASELINE,
+ ALIGN_CENTER
+ })
+ public @interface AlignmentType {}
+
protected final int mVerticalAlignment;
@UnsupportedAppUsage
@@ -100,17 +115,18 @@ public abstract class DynamicDrawableSpan extends ReplacementSpan {
/**
* Creates a {@link DynamicDrawableSpan} based on a vertical alignment.\
*
- * @param verticalAlignment one of {@link #ALIGN_BOTTOM} or {@link #ALIGN_BASELINE}
+ * @param verticalAlignment one of {@link #ALIGN_BOTTOM}, {@link #ALIGN_BASELINE} or
+ * {@link #ALIGN_CENTER}
*/
- protected DynamicDrawableSpan(int verticalAlignment) {
+ protected DynamicDrawableSpan(@AlignmentType int verticalAlignment) {
mVerticalAlignment = verticalAlignment;
}
/**
- * Returns the vertical alignment of this span, one of {@link #ALIGN_BOTTOM} or
- * {@link #ALIGN_BASELINE}.
+ * Returns the vertical alignment of this span, one of {@link #ALIGN_BOTTOM},
+ * {@link #ALIGN_BASELINE} or {@link #ALIGN_CENTER}.
*/
- public int getVerticalAlignment() {
+ public @AlignmentType int getVerticalAlignment() {
return mVerticalAlignment;
}
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index e4c8eeb3b9b0..f8b38e9d215d 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -18,6 +18,7 @@ package android.util;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Build;
import android.os.SystemClock;
@@ -302,6 +303,7 @@ public class TimeUtils {
}
/** @hide Just for debugging; not internationalized. */
+ @TestApi
public static String formatDuration(long duration) {
synchronized (sFormatSync) {
int len = formatDurationLocked(duration, 0);
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index cb5100a4d57a..94a9a1c0ff30 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -21,6 +21,7 @@ import static android.Manifest.permission.CONFIGURE_DISPLAY_COLOR_MODE;
import android.annotation.IntDef;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
+import android.annotation.TestApi;
import android.annotation.UnsupportedAppUsage;
import android.app.KeyguardManager;
import android.content.res.CompatibilityInfo;
@@ -911,6 +912,7 @@ public final class Display {
* @see #FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
* @hide
*/
+ @TestApi
// TODO (b/114338689): Remove the method and use IWindowManager#shouldShowSystemDecors
public boolean supportsSystemDecorations() {
return (mDisplayInfo.flags & FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0;
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 2ef7c4b16d9d..5dc54a566676 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -582,4 +582,13 @@ interface IWindowManager
* display should be re-parented to.
*/
void reparentDisplayContent(int displayId, in SurfaceControl sc);
+
+ /**
+ * Waits for transactions to get applied before injecting input.
+ * This includes waiting for the input windows to get sent to InputManager.
+ *
+ * This is needed for testing since the system add windows and injects input
+ * quick enough that the windows don't have time to get sent to InputManager.
+ */
+ boolean injectInputAfterTransactionsApplied(in InputEvent ev, int mode);
}
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 658f06ad21f9..240aad5a0c56 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -148,7 +148,7 @@ interface IWindowSession {
void setInTouchMode(boolean showFocus);
boolean getInTouchMode();
- boolean performHapticFeedback(IWindow window, int effectId, boolean always);
+ boolean performHapticFeedback(int effectId, boolean always);
/**
* Initiate the drag operation itself
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index d0194f990148..a15a20a58abb 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -922,7 +922,7 @@ public class Surface implements Parcelable {
if (mCanvas != null) {
throw new IllegalStateException("Surface was already locked!");
}
- mCanvas = mRenderNode.start(width, height);
+ mCanvas = mRenderNode.beginRecording(width, height);
return mCanvas;
}
@@ -931,7 +931,7 @@ public class Surface implements Parcelable {
throw new IllegalArgumentException("canvas object must be the same instance that "
+ "was previously returned by lockCanvas");
}
- mRenderNode.end(mCanvas);
+ mRenderNode.endRecording();
mCanvas = null;
nHwuiDraw(mHwuiRenderer);
}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index e5db44eca684..ee91c8519ff4 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -88,7 +88,8 @@ public final class SurfaceControl implements Parcelable {
private static native void nativeDisconnect(long nativeObject);
private static native GraphicBuffer nativeScreenshot(IBinder displayToken,
- Rect sourceCrop, int width, int height, boolean useIdentityTransform, int rotation);
+ Rect sourceCrop, int width, int height, boolean useIdentityTransform, int rotation,
+ boolean captureSecureLayers);
private static native GraphicBuffer nativeCaptureLayers(IBinder layerHandleToken,
Rect sourceCrop, float frameScale);
@@ -189,6 +190,7 @@ public final class SurfaceControl implements Parcelable {
IBinder toToken);
private static native boolean nativeGetProtectedContentSupport();
private static native void nativeSetMetadata(long transactionObj, int key, Parcel data);
+ private static native void nativeSyncInputWindows(long transactionObj);
private final CloseGuard mCloseGuard = CloseGuard.get();
private String mName;
@@ -1852,7 +1854,29 @@ public final class SurfaceControl implements Parcelable {
throw new IllegalArgumentException("displayToken must not be null");
}
- return nativeScreenshot(display, sourceCrop, width, height, useIdentityTransform, rotation);
+ return nativeScreenshot(display, sourceCrop, width, height, useIdentityTransform, rotation,
+ false /* captureSecureLayers */);
+ }
+
+ /**
+ * Like screenshotToBuffer, but if the caller is AID_SYSTEM, allows
+ * for the capture of secure layers. This is used for the screen rotation
+ * animation where the system server takes screenshots but does
+ * not persist them or allow them to leave the server. However in other
+ * cases in the system server, we mostly want to omit secure layers
+ * like when we take a screenshot on behalf of the assistant.
+ *
+ * @hide
+ */
+ public static GraphicBuffer screenshotToBufferWithSecureLayersUnsafe(IBinder display,
+ Rect sourceCrop, int width, int height, boolean useIdentityTransform,
+ int rotation) {
+ if (display == null) {
+ throw new IllegalArgumentException("displayToken must not be null");
+ }
+
+ return nativeScreenshot(display, sourceCrop, width, height, useIdentityTransform, rotation,
+ true /* captureSecureLayers */);
}
private static void rotateCropForSF(Rect crop, int rot) {
@@ -2109,6 +2133,17 @@ public final class SurfaceControl implements Parcelable {
}
/**
+ * Waits until any changes to input windows have been sent from SurfaceFlinger to
+ * InputFlinger before returning.
+ *
+ * @hide
+ */
+ public Transaction syncInputWindows() {
+ nativeSyncInputWindows(mNativeObject);
+ return this;
+ }
+
+ /**
* Specify how the buffer assosciated with this Surface is mapped in to the
* parent coordinate space. The source frame will be scaled to fit the destination
* frame, after being rotated according to the orientation parameter.
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 20978127f510..3d3d5dc7db32 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -590,7 +590,7 @@ public final class ThreadedRenderer extends HardwareRenderer {
}
if (mRootNodeNeedsUpdate || !mRootNode.hasDisplayList()) {
- RecordingCanvas canvas = mRootNode.startRecording(mSurfaceWidth, mSurfaceHeight);
+ RecordingCanvas canvas = mRootNode.beginRecording(mSurfaceWidth, mSurfaceHeight);
try {
final int saveCount = canvas.save();
canvas.translate(mInsetLeft, mInsetTop);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 278b9ff01c58..8b17ea693542 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -40,6 +40,7 @@ import android.annotation.StyleRes;
import android.annotation.TestApi;
import android.annotation.UiThread;
import android.annotation.UnsupportedAppUsage;
+import android.content.AutofillOptions;
import android.content.ClipData;
import android.content.Context;
import android.content.ContextWrapper;
@@ -9408,20 +9409,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
setNotifiedContentCaptureAppeared();
- // TODO(b/123307965): instead of post, we should queue it on AttachInfo and then
- // dispatch on RootImpl, as we're doing with the removed ones (in that case, we should
- // merge the delayNotifyContentCaptureDisappeared() into a more generic method that
- // takes a session and a command, where the command is either view added or removed
-
- // The code below doesn't take much for a unique view, but it's called for all views
- // the first time the view hiearchy is laid off, which could acccumulative delay the
- // initial layout. Hence, we're postponing it to a later stage - it might still cost a
- // lost frame (or more), but that jank cost would only happen after the 1st layout.
- Choreographer.getInstance().postCallback(Choreographer.CALLBACK_COMMIT, () -> {
- final ViewStructure structure = session.newViewStructure(this);
- onProvideContentCaptureStructure(structure, /* flags= */ 0);
- session.notifyViewAppeared(structure);
- }, /* token= */ null);
+ if (ai != null) {
+ ai.delayNotifyContentCaptureEvent(session, this, appeared);
+ } else {
+ if (DEBUG_CONTENT_CAPTURE) {
+ Log.w(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on appeared for " + this);
+ }
+ }
} else {
if ((mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED) == 0
|| (mPrivateFlags4 & PFLAG4_NOTIFIED_CONTENT_CAPTURE_DISAPPEARED) != 0) {
@@ -9440,13 +9434,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mPrivateFlags4 &= ~PFLAG4_NOTIFIED_CONTENT_CAPTURE_APPEARED;
if (ai != null) {
- ai.delayNotifyContentCaptureDisappeared(session, getAutofillId());
+ ai.delayNotifyContentCaptureEvent(session, this, appeared);
} else {
if (DEBUG_CONTENT_CAPTURE) {
- Log.v(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on gone for " + this);
+ Log.v(CONTENT_CAPTURE_LOG_TAG, "no AttachInfo on disappeared for " + this);
}
- Choreographer.getInstance().postCallback(Choreographer.CALLBACK_COMMIT,
- () -> session.notifyViewDisappeared(getAutofillId()), /* token= */ null);
}
}
}
@@ -9533,8 +9525,22 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
private boolean isAutofillable() {
- return getAutofillType() != AUTOFILL_TYPE_NONE && isImportantForAutofill()
- && getAutofillViewId() > LAST_APP_AUTOFILL_ID;
+ if (getAutofillType() == AUTOFILL_TYPE_NONE) return false;
+
+ if (!isImportantForAutofill()) {
+ // View is not important for "regular" autofill, so we must check if Augmented Autofill
+ // is enabled for the activity
+ final AutofillOptions options = mContext.getAutofillOptions();
+ if (options == null || !options.augmentedEnabled) {
+ // TODO(b/123100824): should also check if activity is whitelisted
+ return false;
+ }
+ final AutofillManager afm = getAutofillManager();
+ if (afm == null) return false;
+ afm.notifyViewEnteredForAugmentedAutofill(this);
+ }
+
+ return getAutofillViewId() > LAST_APP_AUTOFILL_ID;
}
/** @hide */
@@ -9703,13 +9709,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*
* @hide
*/
- public void dispatchInitialProvideContentCaptureStructure(@NonNull ContentCaptureManager ccm) {
+ public void dispatchInitialProvideContentCaptureStructure() {
AttachInfo ai = mAttachInfo;
if (ai == null) {
Log.w(CONTENT_CAPTURE_LOG_TAG,
"dispatchProvideContentCaptureStructure(): no AttachInfo for " + this);
return;
}
+ ContentCaptureManager ccm = ai.mContentCaptureManager;
+ if (ccm == null) {
+ Log.w(CONTENT_CAPTURE_LOG_TAG, "dispatchProvideContentCaptureStructure(): "
+ + "no ContentCaptureManager for " + this);
+ return;
+ }
// We must set it before checkign if the view itself is important, because it might
// initially not be (for example, if it's empty), although that might change later (for
@@ -16043,7 +16055,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
@ViewDebug.ExportedProperty(category = "drawing")
@InspectableProperty
public float getRotation() {
- return mRenderNode.getRotation();
+ return mRenderNode.getRotationZ();
}
/**
@@ -16064,7 +16076,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (rotation != getRotation()) {
// Double-invalidation is necessary to capture view's old and new areas
invalidateViewProperty(true, false);
- mRenderNode.setRotation(rotation);
+ mRenderNode.setRotationZ(rotation);
invalidateViewProperty(false, true);
invalidateParentIfNeededAndWasQuickRejected();
@@ -20578,7 +20590,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
int height = mBottom - mTop;
int layerType = getLayerType();
- final RecordingCanvas canvas = renderNode.startRecording(width, height);
+ final RecordingCanvas canvas = renderNode.beginRecording(width, height);
try {
if (layerType == LAYER_TYPE_SOFTWARE) {
@@ -21233,7 +21245,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
} else {
mClipBounds = null;
}
- mRenderNode.setClipBounds(mClipBounds);
+ mRenderNode.setClipRect(mClipBounds);
invalidateViewProperty(false, false);
}
@@ -21978,7 +21990,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
final Rect bounds = drawable.getBounds();
final int width = bounds.width();
final int height = bounds.height();
- final RecordingCanvas canvas = renderNode.startRecording(width, height);
+ final RecordingCanvas canvas = renderNode.beginRecording(width, height);
// Reverse left/top translation done by drawable canvas, which will
// instead be applied by rendernode's LTRB bounds below. This way, the
@@ -28358,11 +28370,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
boolean mReadyForContentCaptureUpdates;
/**
- * Map of ids (per session) that need to be notified after as gone the view hierchy is
- * traversed.
+ * Map(keyed by session) of content capture events that need to be notified after the view
+ * hierarchy is traversed: value is either the view itself for appearead events, or its
+ * autofill id for disappeared.
*/
// TODO(b/121197119): use SparseArray once session id becomes integer
- ArrayMap<String, ArrayList<AutofillId>> mContentCaptureRemovedIds;
+ ArrayMap<String, ArrayList<Object>> mContentCaptureEvents;
/**
* Cached reference to the {@link ContentCaptureManager}.
@@ -28388,24 +28401,24 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mTreeObserver = new ViewTreeObserver(context);
}
- private void delayNotifyContentCaptureDisappeared(@NonNull ContentCaptureSession session,
- @NonNull AutofillId id) {
- if (mContentCaptureRemovedIds == null) {
+ private void delayNotifyContentCaptureEvent(@NonNull ContentCaptureSession session,
+ @NonNull View view, boolean appeared) {
+ if (mContentCaptureEvents == null) {
// Most of the time there will be just one session, so intial capacity is 1
- mContentCaptureRemovedIds = new ArrayMap<>(1);
+ mContentCaptureEvents = new ArrayMap<>(1);
}
String sessionId = session.getId();
// TODO: life would be much easier if we provided a MultiMap implementation somwhere...
- ArrayList<AutofillId> ids = mContentCaptureRemovedIds.get(sessionId);
- if (ids == null) {
- ids = new ArrayList<>();
- mContentCaptureRemovedIds.put(sessionId, ids);
+ ArrayList<Object> events = mContentCaptureEvents.get(sessionId);
+ if (events == null) {
+ events = new ArrayList<>();
+ mContentCaptureEvents.put(sessionId, events);
}
- ids.add(id);
+ events.add(appeared ? view : view.getAutofillId());
}
@Nullable
- private ContentCaptureManager getContentCaptureManager(@NonNull Context context) {
+ ContentCaptureManager getContentCaptureManager(@NonNull Context context) {
if (mContentCaptureManager != null) {
return mContentCaptureManager;
}
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index bb29ed6c5339..c030ac2a0eb8 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -928,8 +928,8 @@ public class ViewConfiguration {
}
/**
- * If a MotionEvent has CLASSIFICATION_AMBIGUOUS_GESTURE set, then certain actions, such as
- * scrolling, will be inhibited.
+ * If a MotionEvent has {@link android.view.MotionEvent#CLASSIFICATION_AMBIGUOUS_GESTURE} set,
+ * then certain actions, such as scrolling, will be inhibited.
* However, to account for the possibility of incorrect classification,
* the default scrolling will only be inhibited if the pointer travels less than
* (getScaledTouchSlop() * this factor).
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 6f9ee4b554f3..a390db2e9644 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -611,11 +611,11 @@ public class ViewDebug {
}
if (view.isHardwareAccelerated()) {
- RecordingCanvas canvas = node.start(dm.widthPixels, dm.heightPixels);
+ RecordingCanvas canvas = node.beginRecording(dm.widthPixels, dm.heightPixels);
try {
return profileViewOperation(view, () -> view.draw(canvas));
} finally {
- node.end(canvas);
+ node.endRecording();
}
} else {
Bitmap bitmap = Bitmap.createBitmap(
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index 68c0d9ec465b..afee1e5cf7f4 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -985,7 +985,7 @@ public class ViewPropertyAnimator {
renderNode.setTranslationZ(value);
break;
case ROTATION:
- renderNode.setRotation(value);
+ renderNode.setRotationZ(value);
break;
case ROTATION_X:
renderNode.setRotationX(value);
@@ -1031,7 +1031,7 @@ public class ViewPropertyAnimator {
case TRANSLATION_Z:
return node.getTranslationZ();
case ROTATION:
- return node.getRotation();
+ return node.getRotationZ();
case ROTATION_X:
return node.getRotationX();
case ROTATION_Y:
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index ab4847ded0e6..91156281983d 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -29,6 +29,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY;
import android.Manifest;
import android.animation.LayoutTransition;
+import android.annotation.AnyThread;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UnsupportedAppUsage;
@@ -107,6 +108,7 @@ import android.view.animation.Interpolator;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillManager;
import android.view.contentcapture.ContentCaptureManager;
+import android.view.contentcapture.ContentCaptureSession;
import android.view.contentcapture.MainContentCaptureSession;
import android.view.inputmethod.InputMethodManager;
import android.widget.Scroller;
@@ -222,10 +224,25 @@ public final class ViewRootImpl implements ViewParent,
*/
static final int MAX_TRACKBALL_DELAY = 250;
+ /**
+ * Initial value for {@link #mContentCaptureEnabled}.
+ */
+ private static final int CONTENT_CAPTURE_ENABLED_NOT_CHECKED = 0;
+
+ /**
+ * Value for {@link #mContentCaptureEnabled} when it was checked and set to {@code true}.
+ */
+ private static final int CONTENT_CAPTURE_ENABLED_TRUE = 1;
+
+ /**
+ * Value for {@link #mContentCaptureEnabled} when it was checked and set to {@code false}.
+ */
+ private static final int CONTENT_CAPTURE_ENABLED_FALSE = 2;
+
@UnsupportedAppUsage
static final ThreadLocal<HandlerActionQueue> sRunQueues = new ThreadLocal<HandlerActionQueue>();
- static final ArrayList<Runnable> sFirstDrawHandlers = new ArrayList();
+ static final ArrayList<Runnable> sFirstDrawHandlers = new ArrayList<>();
static boolean sFirstDrawComplete = false;
/**
@@ -417,7 +434,11 @@ public final class ViewRootImpl implements ViewParent,
boolean mApplyInsetsRequested;
boolean mLayoutRequested;
boolean mFirst;
+
+ @Nullable
+ int mContentCaptureEnabled = CONTENT_CAPTURE_ENABLED_NOT_CHECKED;
boolean mPerformContentCapture;
+
boolean mReportNextDraw;
boolean mFullRedrawNeeded;
boolean mNewSurfaceNeeded;
@@ -1041,10 +1062,22 @@ public final class ViewRootImpl implements ViewParent,
return mHeight;
}
+ /**
+ * Destroys hardware rendering resources for this ViewRootImpl
+ *
+ * May be called on any thread
+ */
+ @AnyThread
void destroyHardwareResources() {
- if (mAttachInfo.mThreadedRenderer != null) {
- mAttachInfo.mThreadedRenderer.destroyHardwareResources(mView);
- mAttachInfo.mThreadedRenderer.destroy();
+ final ThreadedRenderer renderer = mAttachInfo.mThreadedRenderer;
+ if (renderer != null) {
+ // This is called by WindowManagerGlobal which may or may not be on the right thread
+ if (Looper.myLooper() != mAttachInfo.mHandler.getLooper()) {
+ mAttachInfo.mHandler.postAtFrontOfQueue(this::destroyHardwareResources);
+ return;
+ }
+ renderer.destroyHardwareResources(mView);
+ renderer.destroy();
}
}
@@ -2763,25 +2796,58 @@ public final class ViewRootImpl implements ViewParent,
}
}
- if (mAttachInfo.mContentCaptureRemovedIds != null) {
+ if (mAttachInfo.mContentCaptureEvents != null) {
+ notifyContentCatpureEvents();
+ }
+
+ mIsInTraversal = false;
+ }
+
+ private void notifyContentCatpureEvents() {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "notifyContentCaptureEvents");
+ try {
MainContentCaptureSession mainSession = mAttachInfo.mContentCaptureManager
.getMainContentCaptureSession();
- Trace.traceBegin(Trace.TRACE_TAG_VIEW, "notifyContentCaptureViewsGone");
- try {
- for (int i = 0; i < mAttachInfo.mContentCaptureRemovedIds.size(); i++) {
- String sessionId = mAttachInfo.mContentCaptureRemovedIds
- .keyAt(i);
- ArrayList<AutofillId> ids = mAttachInfo.mContentCaptureRemovedIds
- .valueAt(i);
- mainSession.notifyViewsDisappeared(sessionId, ids);
- }
- mAttachInfo.mContentCaptureRemovedIds = null;
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ if (mainSession == null) {
+ Log.w(mTag, "no MainContentCaptureSession on AttachInfo");
+ return;
}
+ for (int i = 0; i < mAttachInfo.mContentCaptureEvents.size(); i++) {
+ String sessionId = mAttachInfo.mContentCaptureEvents
+ .keyAt(i);
+ mainSession.notifyViewHierarchyEvent(sessionId, /* started = */ true);
+ ArrayList<Object> events = mAttachInfo.mContentCaptureEvents
+ .valueAt(i);
+ for_each_event: for (int j = 0; j < events.size(); j++) {
+ Object event = events.get(j);
+ if (event instanceof AutofillId) {
+ mainSession.notifyViewDisappeared(sessionId, (AutofillId) event);
+ } else if (event instanceof View) {
+ View view = (View) event;
+ ContentCaptureSession session = view.getContentCaptureSession();
+ if (session == null) {
+ Log.w(mTag, "no content capture session on view: " + view);
+ continue for_each_event;
+ }
+ String actualId = session.getId().toString();
+ if (!actualId.equals(sessionId)) {
+ Log.w(mTag, "content capture session mismatch for view (" + view
+ + "): was " + sessionId + " before, it's " + actualId + " now");
+ continue for_each_event;
+ }
+ ViewStructure structure = session.newViewStructure(view);
+ view.onProvideContentCaptureStructure(structure, /* flags= */ 0);
+ session.notifyViewAppeared(structure);
+ } else {
+ Log.w(mTag, "invalid content capture event: " + event);
+ }
+ }
+ mainSession.notifyViewHierarchyEvent(sessionId, /* started = */ false);
+ }
+ mAttachInfo.mContentCaptureEvents = null;
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
-
- mIsInTraversal = false;
}
private void notifySurfaceDestroyed() {
@@ -2914,6 +2980,13 @@ public final class ViewRootImpl implements ViewParent,
}
}
mFirstInputStage.onWindowFocusChanged(hasWindowFocus);
+ // NOTE: there's no view visibility (appeared / disapparead) events when the windows focus
+ // is lost, so we don't need to to force a flush - there might be other events such as
+ // text changes, but these should be flushed independently.
+ if (hasWindowFocus) {
+ performContentCaptureFlushIfNecessary(
+ ContentCaptureSession.FLUSH_REASON_VIEW_ROOT_ENTERED);
+ }
}
private void fireAccessibilityFocusEventIfHasFocusedNode() {
@@ -3481,36 +3554,90 @@ public final class ViewRootImpl implements ViewParent,
}
}
if (mPerformContentCapture) {
- performContentCapture();
+ performContentCaptureInitialReport();
+ }
+ }
+
+ /**
+ * Checks (and caches) if content capture is enabled for this context.
+ */
+ private boolean isContentCaptureEnabled() {
+ switch (mContentCaptureEnabled) {
+ case CONTENT_CAPTURE_ENABLED_TRUE:
+ return true;
+ case CONTENT_CAPTURE_ENABLED_FALSE:
+ return false;
+ case CONTENT_CAPTURE_ENABLED_NOT_CHECKED:
+ final boolean reallyEnabled = isContentCaptureReallyEnabled();
+ mContentCaptureEnabled = reallyEnabled ? CONTENT_CAPTURE_ENABLED_TRUE
+ : CONTENT_CAPTURE_ENABLED_FALSE;
+ return reallyEnabled;
+ default:
+ Log.w(TAG, "isContentCaptureEnabled(): invalid state " + mContentCaptureEnabled);
+ return false;
}
+
}
- private void performContentCapture() {
+ /**
+ * Checks (without caching) if content capture is enabled for this context.
+ */
+ private boolean isContentCaptureReallyEnabled() {
+ // First check if context supports it, so it saves a service lookup when it doesn't
+ if (mContext.getContentCaptureOptions() == null) return false;
+
+ final ContentCaptureManager ccm = mAttachInfo.getContentCaptureManager(mContext);
+ // Then check if it's enabled in the contex itself.
+ if (ccm == null || !ccm.isContentCaptureEnabled()) return false;
+
+ return true;
+ }
+
+ private void performContentCaptureInitialReport() {
mPerformContentCapture = false; // One-time offer!
final View rootView = mView;
if (DEBUG_CONTENT_CAPTURE) {
- Log.v(mTag, "dispatchContentCapture() on " + rootView);
+ Log.v(mTag, "performContentCaptureInitialReport() on " + rootView);
}
if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "dispatchContentCapture() for "
+ getClass().getSimpleName());
}
try {
- // First check if context supports it, so it saves a service lookup when it doesn't
- if (mContext.getContentCaptureOptions() == null) return;
-
- // Then check if it's enabled in the contex itself.
- final ContentCaptureManager ccm = mContext
- .getSystemService(ContentCaptureManager.class);
- if (ccm == null || !ccm.isContentCaptureEnabled()) return;
+ if (!isContentCaptureEnabled()) return;
// Content capture is a go!
- rootView.dispatchInitialProvideContentCaptureStructure(ccm);
+ rootView.dispatchInitialProvideContentCaptureStructure();
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
+ private void performContentCaptureFlushIfNecessary(
+ @ContentCaptureSession.FlushReason int flushReason) {
+ if (DEBUG_CONTENT_CAPTURE) {
+ Log.v(mTag, "performContentCaptureFlushIfNecessary("
+ + ContentCaptureSession.getFlushReasonAsString(flushReason) + ")");
+ }
+ if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
+ Trace.traceBegin(Trace.TRACE_TAG_VIEW, "flushContentCapture for "
+ + getClass().getSimpleName());
+ }
+ try {
+ if (!isContentCaptureEnabled()) return;
+
+ final ContentCaptureManager ccm = mAttachInfo.mContentCaptureManager;
+ if (ccm == null) {
+ Log.w(TAG, "flush content capture: no ContentCapture on AttachInfo");
+ return;
+ }
+ ccm.flush(flushReason);
+ } finally {
+ Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+ }
+ }
+
+
private boolean draw(boolean fullRedrawNeeded) {
Surface surface = mSurface;
if (!surface.isValid()) {
@@ -6983,7 +7110,7 @@ public final class ViewRootImpl implements ViewParent,
@Override
public boolean performHapticFeedback(int effectId, boolean always) {
try {
- return mWindowSession.performHapticFeedback(mWindow, effectId, always);
+ return mWindowSession.performHapticFeedback(effectId, always);
} catch (RemoteException e) {
return false;
}
@@ -7080,7 +7207,7 @@ public final class ViewRootImpl implements ViewParent,
RenderNode renderNode = view.mRenderNode;
info[0]++;
if (renderNode != null) {
- info[1] += renderNode.computeApproximateMemoryUsage();
+ info[1] += (int) renderNode.computeApproximateMemoryUsage();
}
if (view instanceof ViewGroup) {
diff --git a/core/java/android/view/accessibility/AccessibilityCache.java b/core/java/android/view/accessibility/AccessibilityCache.java
index 5d59e4205579..87e18b71069c 100644
--- a/core/java/android/view/accessibility/AccessibilityCache.java
+++ b/core/java/android/view/accessibility/AccessibilityCache.java
@@ -424,28 +424,20 @@ public class AccessibilityCache {
*
* @param nodes The nodes in the hosting window.
* @param rootNodeId The id of the root to evict.
- *
- * @return {@code true} if the cache was cleared
*/
- private boolean clearSubTreeRecursiveLocked(LongSparseArray<AccessibilityNodeInfo> nodes,
+ private void clearSubTreeRecursiveLocked(LongSparseArray<AccessibilityNodeInfo> nodes,
long rootNodeId) {
AccessibilityNodeInfo current = nodes.get(rootNodeId);
if (current == null) {
- // The node isn't in the cache, but its descendents might be.
- clear();
- return true;
+ return;
}
nodes.remove(rootNodeId);
final int childCount = current.getChildCount();
for (int i = 0; i < childCount; i++) {
final long childNodeId = current.getChildId(i);
- if (clearSubTreeRecursiveLocked(nodes, childNodeId)) {
- current.recycle();
- return true;
- }
+ clearSubTreeRecursiveLocked(nodes, childNodeId);
}
current.recycle();
- return false;
}
/**
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index e9b16836157f..046c4c02253c 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -16,6 +16,7 @@
package android.view.autofill;
+import static android.service.autofill.FillRequest.FLAG_AUGMENTED_AUTOFILL_REQUEST;
import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
import static android.view.autofill.Helper.sDebug;
import static android.view.autofill.Helper.sVerbose;
@@ -28,6 +29,7 @@ import android.annotation.RequiresFeature;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.annotation.TestApi;
+import android.content.AutofillOptions;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@@ -466,6 +468,13 @@ public final class AutofillManager {
@GuardedBy("mLock")
@Nullable private ArraySet<AutofillId> mEnteredIds;
+ /**
+ * Views that were otherwised not important for autofill but triggered a session because the
+ * context is whitelisted for augmented autofill.
+ */
+ @GuardedBy("mLock")
+ @Nullable private Set<AutofillId> mEnteredForAugmentedAutofillIds;
+
/** If set, session is commited when the field is clicked. */
@GuardedBy("mLock")
@Nullable private AutofillId mSaveTriggerId;
@@ -482,6 +491,9 @@ public final class AutofillManager {
@GuardedBy("mLock")
private CompatibilityBridge mCompatibilityBridge;
+ @Nullable
+ private final AutofillOptions mOptions;
+
/** @hide */
public interface AutofillClient {
/**
@@ -618,6 +630,12 @@ public final class AutofillManager {
public AutofillManager(Context context, IAutoFillManager service) {
mContext = Preconditions.checkNotNull(context, "context cannot be null");
mService = service;
+ mOptions = context.getAutofillOptions();
+
+ if (mOptions != null) {
+ sDebug = (mOptions.loggingLevel & FLAG_ADD_CLIENT_DEBUG) != 0;
+ sVerbose = (mOptions.loggingLevel & FLAG_ADD_CLIENT_VERBOSE) != 0;
+ }
}
/**
@@ -1616,6 +1634,11 @@ public final class AutofillManager {
@GuardedBy("mLock")
private void startSessionLocked(@NonNull AutofillId id, @NonNull Rect bounds,
@NonNull AutofillValue value, int flags) {
+ if (mEnteredForAugmentedAutofillIds != null
+ && mEnteredForAugmentedAutofillIds.contains(id)) {
+ if (sVerbose) Log.v(TAG, "Starting session for augmented autofill on " + id);
+ flags |= FLAG_AUGMENTED_AUTOFILL_REQUEST;
+ }
if (sVerbose) {
Log.v(TAG, "startSessionLocked(): id=" + id + ", bounds=" + bounds + ", value=" + value
+ ", flags=" + flags + ", state=" + getStateAsStringLocked()
@@ -1851,6 +1874,25 @@ public final class AutofillManager {
return set == null ? null : new ArrayList<T>(set);
}
+ /**
+ * Notifies that a non-autofillable view was entered because the activity is whitelisted for
+ * augmented autofill.
+ *
+ * <p>This method is necessary to set the right flag on start, so the server-side session
+ * doesn't trigger the standard autofill workflow, but the augmented's instead.
+ *
+ * @hide
+ */
+ public void notifyViewEnteredForAugmentedAutofill(@NonNull View view) {
+ final AutofillId id = view.getAutofillId();
+ synchronized (mLock) {
+ if (mEnteredForAugmentedAutofillIds == null) {
+ mEnteredForAugmentedAutofillIds = new ArraySet<>(1);
+ }
+ mEnteredForAugmentedAutofillIds.add(id);
+ }
+ }
+
private void requestShowFillUi(int sessionId, AutofillId id, int width, int height,
Rect anchorBounds, IAutofillWindowPresenter presenter) {
final View anchor = findView(id);
@@ -2350,8 +2392,15 @@ public final class AutofillManager {
}
pw.print(pfx); pw.print("fillable ids: "); pw.println(mFillableIds);
pw.print(pfx); pw.print("entered ids: "); pw.println(mEnteredIds);
+ if (mEnteredForAugmentedAutofillIds != null) {
+ pw.print(pfx); pw.print("entered ids for augmented autofill: ");
+ pw.println(mEnteredForAugmentedAutofillIds);
+ }
pw.print(pfx); pw.print("save trigger id: "); pw.println(mSaveTriggerId);
pw.print(pfx); pw.print("save on finish(): "); pw.println(mSaveOnFinish);
+ if (mOptions != null) {
+ pw.print(pfx); pw.print("options: "); mOptions.dumpShort(pw); pw.println();
+ }
pw.print(pfx); pw.print("compat mode enabled: ");
synchronized (mLock) {
if (mCompatibilityBridge != null) {
diff --git a/core/java/android/view/autofill/AutofillManagerInternal.java b/core/java/android/view/autofill/AutofillManagerInternal.java
index 155fe721311c..d5862bd2f942 100644
--- a/core/java/android/view/autofill/AutofillManagerInternal.java
+++ b/core/java/android/view/autofill/AutofillManagerInternal.java
@@ -16,7 +16,9 @@
package android.view.autofill;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.content.AutofillOptions;
/**
* Autofill Manager local system service interface.
@@ -31,12 +33,13 @@ public abstract class AutofillManagerInternal {
public abstract void onBackKeyPressed();
/**
- * Gets whether compatibility mode is enabled for a package
+ * Gets autofill options for a package
*
* @param packageName The package for which to query.
* @param versionCode The package version code.
* @param userId The user id for which to query.
*/
- public abstract boolean isCompatibilityModeRequested(@NonNull String packageName,
+ @Nullable
+ public abstract AutofillOptions getAutofillOptions(@NonNull String packageName,
long versionCode, @UserIdInt int userId);
}
diff --git a/core/java/android/view/contentcapture/ChildContentCaptureSession.java b/core/java/android/view/contentcapture/ChildContentCaptureSession.java
index 13e8a6584218..03eef5e07321 100644
--- a/core/java/android/view/contentcapture/ChildContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ChildContentCaptureSession.java
@@ -85,7 +85,7 @@ final class ChildContentCaptureSession extends ContentCaptureSession {
@Override
public void internalNotifyViewHierarchyEvent(boolean started) {
- getMainCaptureSession().notifyInitialViewHierarchyEvent(mId, started);
+ getMainCaptureSession().notifyViewHierarchyEvent(mId, started);
}
@Override
diff --git a/core/java/android/view/contentcapture/ContentCaptureEvent.java b/core/java/android/view/contentcapture/ContentCaptureEvent.java
index 9cdbefac3d1d..1dd1bee95c4b 100644
--- a/core/java/android/view/contentcapture/ContentCaptureEvent.java
+++ b/core/java/android/view/contentcapture/ContentCaptureEvent.java
@@ -72,23 +72,25 @@ public final class ContentCaptureEvent implements Parcelable {
public static final int TYPE_VIEW_TEXT_CHANGED = 3;
/**
- * Called before events (such as {@link #TYPE_VIEW_APPEARED}) representing the initial view
- * hierarchy are sent.
+ * Called before events (such as {@link #TYPE_VIEW_APPEARED} and/or
+ * {@link #TYPE_VIEW_DISAPPEARED}) representing a view hierarchy are sent.
*
* <p><b>NOTE</b>: there is no guarantee this event will be sent. For example, it's not sent
* if the initial view hierarchy doesn't initially have any view that's important for content
* capture.
*/
+ // TODO(b/125395044): change to TYPE_VIEW_TREE_APPEARING
public static final int TYPE_INITIAL_VIEW_TREE_APPEARING = 4;
/**
- * Called after events (such as {@link #TYPE_VIEW_APPEARED}) representing the initial view
- * hierarchy are sent.
+ * Called after events (such as {@link #TYPE_VIEW_APPEARED} and/or
+ * {@link #TYPE_VIEW_DISAPPEARED}) representing a view hierarchy were sent.
*
* <p><b>NOTE</b>: there is no guarantee this event will be sent. For example, it's not sent
* if the initial view hierarchy doesn't initially have any view that's important for content
* capture.
*/
+ // TODO(b/125395044): change to TYPE_VIEW_TREE_APPEARED
public static final int TYPE_INITIAL_VIEW_TREE_APPEARED = 5;
/**
@@ -418,9 +420,9 @@ public final class ContentCaptureEvent implements Parcelable {
case TYPE_VIEW_TEXT_CHANGED:
return "VIEW_TEXT_CHANGED";
case TYPE_INITIAL_VIEW_TREE_APPEARING:
- return "INITIAL_VIEW_HIERARCHY_STARTED";
+ return "VIEW_TREE_APPEARING";
case TYPE_INITIAL_VIEW_TREE_APPEARED:
- return "INITIAL_VIEW_HIERARCHY_FINISHED";
+ return "VIEW_TREE_APPEARED";
case TYPE_CONTEXT_UPDATED:
return "CONTEXT_UPDATED";
default:
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index 336d9979a781..cdd4f35f538b 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -129,6 +129,14 @@ public final class ContentCaptureManager {
@TestApi
public static final String DEVICE_CONFIG_PROPERTY_LOGGING_LEVEL = "logging_level";
+ /**
+ * Sets how long (in ms) the service is bound while idle.
+ *
+ * <p>Use {@code 0} to keep it permanently bound.
+ *
+ * @hide
+ */
+ public static final String DEVICE_CONFIG_PROPERTY_IDLE_UNBIND_TIMEOUT = "idle_unbind_timeout";
/** @hide */
@TestApi
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index 1e051a43a42f..544a4f6dd386 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -132,9 +132,7 @@ public abstract class ContentCaptureSession implements AutoCloseable {
/** @hide */
public static final int FLUSH_REASON_FULL = 1;
/** @hide */
- public static final int FLUSH_REASON_ACTIVITY_PAUSED = 2;
- /** @hide */
- public static final int FLUSH_REASON_ACTIVITY_RESUMED = 3;
+ public static final int FLUSH_REASON_VIEW_ROOT_ENTERED = 2;
/** @hide */
public static final int FLUSH_REASON_SESSION_STARTED = 4;
/** @hide */
@@ -145,14 +143,13 @@ public abstract class ContentCaptureSession implements AutoCloseable {
/** @hide */
@IntDef(prefix = { "FLUSH_REASON_" }, value = {
FLUSH_REASON_FULL,
- FLUSH_REASON_ACTIVITY_PAUSED,
- FLUSH_REASON_ACTIVITY_RESUMED,
FLUSH_REASON_SESSION_STARTED,
FLUSH_REASON_SESSION_FINISHED,
- FLUSH_REASON_IDLE_TIMEOUT
+ FLUSH_REASON_IDLE_TIMEOUT,
+ FLUSH_REASON_VIEW_ROOT_ENTERED,
})
@Retention(RetentionPolicy.SOURCE)
- @interface FlushReason{}
+ public @interface FlushReason{}
private final Object mLock = new Object();
@@ -500,20 +497,18 @@ public abstract class ContentCaptureSession implements AutoCloseable {
/** @hide */
@NonNull
- static String getflushReasonAsString(@FlushReason int reason) {
+ public static String getFlushReasonAsString(@FlushReason int reason) {
switch (reason) {
case FLUSH_REASON_FULL:
return "FULL";
- case FLUSH_REASON_ACTIVITY_PAUSED:
- return "PAUSED";
- case FLUSH_REASON_ACTIVITY_RESUMED:
- return "RESUMED";
case FLUSH_REASON_SESSION_STARTED:
return "STARTED";
case FLUSH_REASON_SESSION_FINISHED:
return "FINISHED";
case FLUSH_REASON_IDLE_TIMEOUT:
return "IDLE";
+ case FLUSH_REASON_VIEW_ROOT_ENTERED:
+ return "ENTERED";
default:
return "UNKOWN-" + reason;
}
diff --git a/core/java/android/view/contentcapture/MainContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index 0abf68992938..14b2b28deaeb 100644
--- a/core/java/android/view/contentcapture/MainContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -126,7 +126,6 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
@Nullable
private final LocalLog mFlushHistory;
- /** @hide */
protected MainContentCaptureSession(@NonNull Context context,
@NonNull ContentCaptureManager manager, @NonNull Handler handler,
@NonNull IContentCaptureManager systemServerInterface) {
@@ -153,8 +152,6 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
/**
* Starts this session.
- *
- * @hide
*/
@UiThread
void start(@NonNull IBinder token, @NonNull ComponentName component,
@@ -451,7 +448,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
}
final int numberEvents = mEvents.size();
- final String reasonString = getflushReasonAsString(reason);
+ final String reasonString = getFlushReasonAsString(reason);
if (sDebug) {
Log.d(TAG, "Flushing " + numberEvents + " event(s) for " + getDebugState(reason));
}
@@ -547,7 +544,7 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
@Override
public void internalNotifyViewHierarchyEvent(boolean started) {
- notifyInitialViewHierarchyEvent(mId, started);
+ notifyViewHierarchyEvent(mId, started);
}
@Override
@@ -581,21 +578,9 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
.setViewNode(node.mNode));
}
- void notifyViewDisappeared(@NonNull String sessionId, @NonNull AutofillId id) {
- sendEvent(
- new ContentCaptureEvent(sessionId, TYPE_VIEW_DISAPPEARED).setAutofillId(id));
- }
-
- /** @hide */
- public void notifyViewsDisappeared(@NonNull String sessionId,
- @NonNull ArrayList<AutofillId> ids) {
- final ContentCaptureEvent event = new ContentCaptureEvent(sessionId, TYPE_VIEW_DISAPPEARED);
- if (ids.size() == 1) {
- event.setAutofillId(ids.get(0));
- } else {
- event.setAutofillIds(ids);
- }
- sendEvent(event);
+ /** Public because is also used by ViewRootImpl */
+ public void notifyViewDisappeared(@NonNull String sessionId, @NonNull AutofillId id) {
+ sendEvent(new ContentCaptureEvent(sessionId, TYPE_VIEW_DISAPPEARED).setAutofillId(id));
}
void notifyViewTextChanged(@NonNull String sessionId, @NonNull AutofillId id,
@@ -604,13 +589,11 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
.setText(text));
}
- void notifyInitialViewHierarchyEvent(@NonNull String sessionId, boolean started) {
- if (started) {
- sendEvent(new ContentCaptureEvent(sessionId, TYPE_INITIAL_VIEW_TREE_APPEARING));
- } else {
- sendEvent(new ContentCaptureEvent(sessionId, TYPE_INITIAL_VIEW_TREE_APPEARED),
- FORCE_FLUSH);
- }
+ /** Public because is also used by ViewRootImpl */
+ public void notifyViewHierarchyEvent(@NonNull String sessionId, boolean started) {
+ final int type = started ? TYPE_INITIAL_VIEW_TREE_APPEARING
+ : TYPE_INITIAL_VIEW_TREE_APPEARED;
+ sendEvent(new ContentCaptureEvent(sessionId, type), FORCE_FLUSH);
}
void notifyContextUpdated(@NonNull String sessionId,
@@ -684,6 +667,6 @@ public final class MainContentCaptureSession extends ContentCaptureSession {
@NonNull
private String getDebugState(@FlushReason int reason) {
- return getDebugState() + ", reason=" + getflushReasonAsString(reason);
+ return getDebugState() + ", reason=" + getFlushReasonAsString(reason);
}
}
diff --git a/core/java/android/view/inspector/GeneratedInspectionCompanionProvider.java b/core/java/android/view/inspector/GeneratedInspectionCompanionProvider.java
index 8faae1f1da98..d4b7e858bebd 100644
--- a/core/java/android/view/inspector/GeneratedInspectionCompanionProvider.java
+++ b/core/java/android/view/inspector/GeneratedInspectionCompanionProvider.java
@@ -40,8 +40,15 @@ public class GeneratedInspectionCompanionProvider implements InspectionCompanion
final Class<InspectionCompanion<T>> companionClass =
(Class<InspectionCompanion<T>>) cls.getClassLoader().loadClass(companionName);
return companionClass.newInstance();
- } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
+ } catch (ClassNotFoundException e) {
return null;
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InstantiationException e) {
+ Throwable cause = e.getCause();
+ if (cause instanceof RuntimeException) throw (RuntimeException) cause;
+ if (cause instanceof Error) throw (Error) cause;
+ throw new RuntimeException(cause);
}
}
}
diff --git a/core/java/android/view/textclassifier/ExtrasUtils.java b/core/java/android/view/textclassifier/ExtrasUtils.java
index b0e7ad5d7264..2ad17a84a64e 100644
--- a/core/java/android/view/textclassifier/ExtrasUtils.java
+++ b/core/java/android/view/textclassifier/ExtrasUtils.java
@@ -94,7 +94,8 @@ public final class ExtrasUtils {
if (actionIntents != null) {
final int size = actionIntents.size();
for (int i = 0; i < size; i++) {
- if (intentAction.equals(actionIntents.get(i).getAction())) {
+ final Intent intent = actionIntents.get(i);
+ if (intent != null && intentAction.equals(intent.getAction())) {
return classification.getActions().get(i);
}
}
diff --git a/core/java/android/view/textclassifier/TextClassification.java b/core/java/android/view/textclassifier/TextClassification.java
index a05920960dcf..052ee953e971 100644
--- a/core/java/android/view/textclassifier/TextClassification.java
+++ b/core/java/android/view/textclassifier/TextClassification.java
@@ -54,6 +54,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
/**
* Information for generating a widget to handle classified text.
@@ -276,8 +277,8 @@ public final class TextClassification implements Parcelable {
@Override
public String toString() {
return String.format(Locale.US,
- "TextClassification {text=%s, entities=%s, actions=%s, id=%s}",
- mText, mEntityConfidence, mActions, mId);
+ "TextClassification {text=%s, entities=%s, actions=%s, id=%s, extras=%s}",
+ mText, mEntityConfidence, mActions, mId, mExtras);
}
/**
@@ -532,7 +533,7 @@ public final class TextClassification implements Parcelable {
private Bundle buildExtras() {
final Bundle extras = mExtras == null ? new Bundle() : mExtras.deepCopy();
- if (!mActionIntents.isEmpty()) {
+ if (mActionIntents.stream().anyMatch(Objects::nonNull)) {
ExtrasUtils.putActionsIntents(extras, mActionIntents);
}
if (mForeignLanguageExtra != null) {
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 295c8b72b943..e628f19668ae 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -240,9 +240,7 @@ public final class TextClassifierImpl implements TextClassifier {
refTime.getZone().getId(),
localesString),
mContext,
- // TODO: Pass the locale list once it is supported in
- // native side.
- LocaleList.getDefault().get(0).toLanguageTag()
+ getResourceLocaleString()
);
if (results.length > 0) {
return createClassificationResult(
@@ -403,8 +401,7 @@ public final class TextClassifierImpl implements TextClassifier {
nativeConversation,
null,
mContext,
- // TODO: Pass the locale list once it is supported in native side.
- LocaleList.getDefault().get(0).toLanguageTag());
+ getResourceLocaleString());
return createConversationActionResult(request, nativeSuggestions);
} catch (Throwable t) {
// Avoid throwing from this method. Log the error.
@@ -456,10 +453,9 @@ public final class TextClassifierImpl implements TextClassifier {
TextLanguage textLanguage = detectLanguage(request);
int localeHypothesisCount = textLanguage.getLocaleHypothesisCount();
List<String> languageTags = new ArrayList<>();
- // TODO: Reconsider this and probably make the score threshold configurable.
for (int i = 0; i < localeHypothesisCount; i++) {
ULocale locale = textLanguage.getLocale(i);
- if (textLanguage.getConfidenceScore(locale) < 0.5) {
+ if (textLanguage.getConfidenceScore(locale) < getForeignLanguageThreshold()) {
break;
}
languageTags.add(locale.toLanguageTag());
@@ -587,15 +583,10 @@ public final class TextClassifierImpl implements TextClassifier {
}
}
- final float foreignTextThreshold = mSettings.getLangIdThresholdOverride() >= 0
- ? mSettings.getLangIdThresholdOverride()
- : 0.5f /* TODO: Load this from the langId model. */;
- final Bundle foreignLanguageBundle =
- detectForeignLanguage(classifiedText, foreignTextThreshold);
+ final Bundle foreignLanguageBundle = detectForeignLanguage(classifiedText);
builder.setForeignLanguageExtra(foreignLanguageBundle);
boolean isPrimaryAction = true;
- final ArrayList<Intent> sourceIntents = new ArrayList<>();
List<LabeledIntent> labeledIntents = mIntentFactory.create(
mContext,
classifiedText,
@@ -626,16 +617,20 @@ public final class TextClassifierImpl implements TextClassifier {
/**
* Returns a bundle with the language and confidence score if it finds the text to be
- * in a foreign language. Otherwise returns null.
+ * in a foreign language. Otherwise returns null. This algorithm defines what the system thinks
+ * is a foreign language.
*/
+ // TODO: Revisit this algorithm.
+ // TODO: Consider making this public API.
@Nullable
- private Bundle detectForeignLanguage(String text, float threshold) {
- if (threshold > 1) {
- return null;
- }
-
- // TODO: Revisit this algorithm.
+ private Bundle detectForeignLanguage(String text) {
try {
+ final float threshold = getForeignLanguageThreshold();
+ if (threshold > 1) {
+ Log.v(LOG_TAG, "Foreign language detection disabled.");
+ return null;
+ }
+
final LangIdModel langId = getLangIdImpl();
final LangIdModel.LanguageResult[] langResults = langId.detectLanguages(text);
if (langResults.length <= 0) {
@@ -651,8 +646,8 @@ public final class TextClassifierImpl implements TextClassifier {
if (highestScoringResult.getScore() < threshold) {
return null;
}
- // TODO: Remove
- Log.d(LOG_TAG, String.format("Language detected: <%s:%s>",
+
+ Log.v(LOG_TAG, String.format("Language detected: <%s:%s>",
highestScoringResult.getLanguage(), highestScoringResult.getScore()));
final Locale detected = new Locale(highestScoringResult.getLanguage());
@@ -671,6 +666,18 @@ public final class TextClassifierImpl implements TextClassifier {
return null;
}
+ private float getForeignLanguageThreshold() {
+ try {
+ return mSettings.getLangIdThresholdOverride() >= 0
+ ? mSettings.getLangIdThresholdOverride()
+ : getLangIdImpl().getTranslateThreshold();
+ } catch (FileNotFoundException e) {
+ final float defaultThreshold = 0.5f;
+ Log.v(LOG_TAG, "Using default foreign language threshold: " + defaultThreshold);
+ return defaultThreshold;
+ }
+ }
+
@Override
public void dump(@NonNull IndentingPrintWriter printWriter) {
synchronized (mLock) {
@@ -719,6 +726,19 @@ public final class TextClassifierImpl implements TextClassifier {
}
/**
+ * Returns the locale string for the current resources configuration.
+ */
+ private String getResourceLocaleString() {
+ // TODO: Pass the locale list once it is supported in native side.
+ try {
+ return mContext.getResources().getConfiguration().getLocales().get(0).toLanguageTag();
+ } catch (NullPointerException e) {
+ // NPE is unexpected. Erring on the side of caution.
+ return LocaleList.getDefault().get(0).toLanguageTag();
+ }
+ }
+
+ /**
* Helper class to store the information from which RemoteActions are built.
*/
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index ded3be4e4ef5..b6ec5f936fbd 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1947,7 +1947,7 @@ public class Editor {
// Rebuild display list if it is invalid
if (blockDisplayListIsInvalid) {
- final RecordingCanvas recordingCanvas = blockDisplayList.start(
+ final RecordingCanvas recordingCanvas = blockDisplayList.beginRecording(
right - left, bottom - top);
try {
// drawText is always relative to TextView's origin, this translation
@@ -1958,7 +1958,7 @@ public class Editor {
// No need to untranslate, previous context is popped after
// drawDisplayList
} finally {
- blockDisplayList.end(recordingCanvas);
+ blockDisplayList.endRecording();
// Same as drawDisplayList below, handled by our TextView's parent
blockDisplayList.setClipToBounds(false);
}
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index 249f49956256..49c01237f2cc 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -859,7 +859,7 @@ public final class Magnifier {
);
setupOverlay();
- final RecordingCanvas canvas = mRenderer.getRootNode().start(width, height);
+ final RecordingCanvas canvas = mRenderer.getRootNode().beginRecording(width, height);
try {
canvas.insertReorderBarrier();
canvas.drawRenderNode(mBitmapRenderNode);
@@ -867,7 +867,7 @@ public final class Magnifier {
canvas.drawRenderNode(mOverlayRenderNode);
canvas.insertInorderBarrier();
} finally {
- mRenderer.getRootNode().end(canvas);
+ mRenderer.getRootNode().endRecording();
}
if (mCallback != null) {
mCurrentContent =
@@ -898,11 +898,12 @@ public final class Magnifier {
bitmapRenderNode.setClipToOutline(true);
// Create a dummy draw, which will be replaced later with real drawing.
- final RecordingCanvas canvas = bitmapRenderNode.start(mContentWidth, mContentHeight);
+ final RecordingCanvas canvas = bitmapRenderNode.beginRecording(
+ mContentWidth, mContentHeight);
try {
canvas.drawColor(0xFF00FF00);
} finally {
- bitmapRenderNode.end(canvas);
+ bitmapRenderNode.endRecording();
}
return bitmapRenderNode;
@@ -954,7 +955,7 @@ public final class Magnifier {
// Draw the drawable to the render node. This happens once during
// initialization and whenever the overlay drawable is invalidated.
final RecordingCanvas canvas =
- mOverlayRenderNode.startRecording(mContentWidth, mContentHeight);
+ mOverlayRenderNode.beginRecording(mContentWidth, mContentHeight);
try {
mOverlay.setBounds(0, 0, mContentWidth, mContentHeight);
mOverlay.draw(canvas);
@@ -1035,7 +1036,7 @@ public final class Magnifier {
}
final RecordingCanvas canvas =
- mBitmapRenderNode.start(mContentWidth, mContentHeight);
+ mBitmapRenderNode.beginRecording(mContentWidth, mContentHeight);
try {
final Rect srcRect = new Rect(0, 0, mBitmap.getWidth(), mBitmap.getHeight());
final Rect dstRect = new Rect(0, 0, mContentWidth, mContentHeight);
@@ -1043,7 +1044,7 @@ public final class Magnifier {
paint.setFilterBitmap(true);
canvas.drawBitmap(mBitmap, srcRect, dstRect, paint);
} finally {
- mBitmapRenderNode.end(canvas);
+ mBitmapRenderNode.endRecording();
}
if (mPendingWindowPositionUpdate || mFirstDraw) {
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 0fbd4dca700b..89e3d6b6460f 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -381,6 +381,8 @@ public class ChooserActivity extends ResolverActivity {
final long systemCost = mChooserShownTime - intentReceivedTime;
getMetricsLogger().write(new LogMaker(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN)
+ .setSubtype(isWorkProfile() ? MetricsEvent.MANAGED_PROFILE :
+ MetricsEvent.PARENT_PROFILE)
.addTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE, target.getType())
.addTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS, systemCost));
@@ -418,6 +420,16 @@ public class ChooserActivity extends ResolverActivity {
}
/**
+ * Check if the profile currently used is a work profile.
+ * @return true if it is work profile, false if it is parent profile (or no work profile is
+ * set up)
+ */
+ protected boolean isWorkProfile() {
+ return ((UserManager) getSystemService(Context.USER_SERVICE))
+ .getUserInfo(UserHandle.myUserId()).isManagedProfile();
+ }
+
+ /**
* Override method to add content preview area, specific to the chooser activity.
*/
@Override
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index d13bcf2aa186..64f00103eb4b 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -31,6 +31,7 @@ import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
+import android.metrics.LogMaker;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -39,6 +40,8 @@ import android.util.Slog;
import android.widget.Toast;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import java.util.Arrays;
import java.util.HashSet;
@@ -66,6 +69,8 @@ public class IntentForwarderActivity extends Activity {
private Injector mInjector;
+ private MetricsLogger mMetricsLogger;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -78,9 +83,17 @@ public class IntentForwarderActivity extends Activity {
if (className.equals(FORWARD_INTENT_TO_PARENT)) {
userMessageId = com.android.internal.R.string.forward_intent_to_owner;
targetUserId = getProfileParent();
+
+ getMetricsLogger().write(
+ new LogMaker(MetricsEvent.ACTION_SWITCH_SHARE_PROFILE)
+ .setSubtype(MetricsEvent.PARENT_PROFILE));
} else if (className.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) {
userMessageId = com.android.internal.R.string.forward_intent_to_work;
targetUserId = getManagedProfile();
+
+ getMetricsLogger().write(
+ new LogMaker(MetricsEvent.ACTION_SWITCH_SHARE_PROFILE)
+ .setSubtype(MetricsEvent.MANAGED_PROFILE));
} else {
Slog.wtf(TAG, IntentForwarderActivity.class.getName() + " cannot be called directly");
userMessageId = -1;
@@ -257,6 +270,13 @@ public class IntentForwarderActivity extends Activity {
intent.setComponent(null);
}
+ protected MetricsLogger getMetricsLogger() {
+ if (mMetricsLogger == null) {
+ mMetricsLogger = new MetricsLogger();
+ }
+ return mMetricsLogger;
+ }
+
@VisibleForTesting
protected Injector createInjector() {
return new InjectorImpl();
diff --git a/core/java/com/android/internal/infra/AbstractMultiplePendingRequestsRemoteService.java b/core/java/com/android/internal/infra/AbstractMultiplePendingRequestsRemoteService.java
index 26cf1809313e..293ffd34da8d 100644
--- a/core/java/com/android/internal/infra/AbstractMultiplePendingRequestsRemoteService.java
+++ b/core/java/com/android/internal/infra/AbstractMultiplePendingRequestsRemoteService.java
@@ -39,7 +39,7 @@ public abstract class AbstractMultiplePendingRequestsRemoteService<S
private final int mInitialCapacity;
- protected ArrayList<PendingRequest<S, I>> mPendingRequests;
+ protected ArrayList<BasePendingRequest<S, I>> mPendingRequests;
public AbstractMultiplePendingRequestsRemoteService(@NonNull Context context,
@NonNull String serviceInterface, @NonNull ComponentName componentName, int userId,
@@ -85,7 +85,7 @@ public abstract class AbstractMultiplePendingRequestsRemoteService<S
}
@Override // from AbstractRemoteService
- void handlePendingRequestWhileUnBound(@NonNull PendingRequest<S, I> pendingRequest) {
+ void handlePendingRequestWhileUnBound(@NonNull BasePendingRequest<S, I> pendingRequest) {
if (mPendingRequests == null) {
mPendingRequests = new ArrayList<>(mInitialCapacity);
}
diff --git a/core/java/com/android/internal/infra/AbstractRemoteService.java b/core/java/com/android/internal/infra/AbstractRemoteService.java
index a937aa7cc32e..f4c904dc750e 100644
--- a/core/java/com/android/internal/infra/AbstractRemoteService.java
+++ b/core/java/com/android/internal/infra/AbstractRemoteService.java
@@ -67,7 +67,7 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
private static final int MSG_BIND = 1;
private static final int MSG_UNBIND = 2;
- protected static final long PERMANENT_BOUND_TIMEOUT_MS = 0;
+ public static final long PERMANENT_BOUND_TIMEOUT_MS = 0;
protected static final int LAST_PRIVATE_MSG = MSG_UNBIND;
@@ -95,7 +95,7 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
private long mNextUnbind;
/** Requests that have been scheduled, but that are not finished yet */
- private final ArrayList<PendingRequest<S, I>> mUnfinishedRequests = new ArrayList<>();
+ private final ArrayList<BasePendingRequest<S, I>> mUnfinishedRequests = new ArrayList<>();
/**
* Callback called when the service dies.
@@ -183,8 +183,15 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
/**
* Defines how long after we make a remote request to a fill service we timeout.
+ *
+ * <p>Just need to be overridden by subclasses that uses sync {@link PendingRequest}s.
+ *
+ * @throws UnsupportedOperationException if called when not overridden.
+ *
*/
- protected abstract long getRemoteRequestMillis();
+ protected long getRemoteRequestMillis() {
+ throw new UnsupportedOperationException("not implemented by " + getClass());
+ }
/**
* Gets the currently registered service interface or {@code null} if the service is not
@@ -243,7 +250,7 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
pw.append(prefix).append(tab).append("destroyed=")
.append(String.valueOf(mDestroyed)).println();
pw.append(prefix).append(tab).append("numUnfinishedRequests=")
- .append(String.valueOf(mUnfinishedRequests.size()));
+ .append(String.valueOf(mUnfinishedRequests.size())).println();
final boolean bound = handleIsBound();
pw.append(prefix).append(tab).append("bound=")
.append(String.valueOf(bound));
@@ -260,9 +267,13 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
pw.println();
pw.append(prefix).append("mBindInstantServiceAllowed=").println(mBindInstantServiceAllowed);
pw.append(prefix).append("idleTimeout=")
- .append(Long.toString(idleTimeout / 1000)).append("s").println();
- pw.append(prefix).append("requestTimeout=")
- .append(Long.toString(getRemoteRequestMillis() / 1000)).append("s").println();
+ .append(Long.toString(idleTimeout / 1000)).append("s\n");
+ pw.append(prefix).append("requestTimeout=");
+ try {
+ pw.append(Long.toString(getRemoteRequestMillis() / 1000)).append("s\n");
+ } catch (UnsupportedOperationException e) {
+ pw.append("not supported\n");
+ }
pw.println();
}
@@ -273,7 +284,7 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
* othewise it will trigger a {@link PendingRequest#onTimeout(AbstractRemoteService)} if the
* service doesn't respond.
*/
- protected void scheduleRequest(@NonNull PendingRequest<S, I> pendingRequest) {
+ protected void scheduleRequest(@NonNull BasePendingRequest<S, I> pendingRequest) {
mHandler.sendMessage(obtainMessage(
AbstractRemoteService::handlePendingRequest, this, pendingRequest));
}
@@ -283,12 +294,12 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
*
* @param finshedRequest The request that is finished
*/
- void finishRequest(@NonNull PendingRequest<S, I> finshedRequest) {
+ void finishRequest(@NonNull BasePendingRequest<S, I> finshedRequest) {
mHandler.sendMessage(
obtainMessage(AbstractRemoteService::handleFinishRequest, this, finshedRequest));
}
- private void handleFinishRequest(@NonNull PendingRequest<S, I> finshedRequest) {
+ private void handleFinishRequest(@NonNull BasePendingRequest<S, I> finshedRequest) {
mUnfinishedRequests.remove(finshedRequest);
if (mUnfinishedRequests.isEmpty()) {
@@ -361,7 +372,7 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
* Handles a request, either processing it right now when bound, or saving it to be handled when
* bound.
*/
- protected final void handlePendingRequest(@NonNull PendingRequest<S, I> pendingRequest) {
+ protected final void handlePendingRequest(@NonNull BasePendingRequest<S, I> pendingRequest) {
if (checkIfDestroyed() || mCompleted) return;
if (!handleIsBound()) {
@@ -384,7 +395,8 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
/**
* Defines what to do with a request that arrives while not bound to the service.
*/
- abstract void handlePendingRequestWhileUnBound(@NonNull PendingRequest<S, I> pendingRequest);
+ abstract void handlePendingRequestWhileUnBound(
+ @NonNull BasePendingRequest<S, I> pendingRequest);
private boolean handleIsBound() {
return mService != null;
@@ -471,50 +483,28 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
/**
* Base class for the requests serviced by the remote service.
*
- * <p><b>NOTE: </b> this class is typically used when the service needs to use a callback to
- * communicate back with the system server. For cases where that's not needed, you should use
- * {@link AbstractRemoteService#scheduleAsyncRequest(AsyncRequest)} instead.
+ * <p><b>NOTE: </b> this class is not used directly, you should either override
+ * {@link com.android.internal.infra.AbstractRemoteService.PendingRequest} for sync requests, or
+ * use {@link AbstractRemoteService#scheduleAsyncRequest(AsyncRequest)} for async requests.
*
* @param <S> the remote service class
* @param <I> the interface of the binder service
*/
- public abstract static class PendingRequest<S extends AbstractRemoteService<S, I>,
+ public abstract static class BasePendingRequest<S extends AbstractRemoteService<S, I>,
I extends IInterface> implements Runnable {
protected final String mTag = getClass().getSimpleName();
protected final Object mLock = new Object();
- private final WeakReference<S> mWeakService;
- private final Runnable mTimeoutTrigger;
- private final Handler mServiceHandler;
+ final WeakReference<S> mWeakService;
@GuardedBy("mLock")
- private boolean mCancelled;
+ boolean mCancelled;
@GuardedBy("mLock")
- private boolean mCompleted;
+ boolean mCompleted;
- protected PendingRequest(@NonNull S service) {
+ BasePendingRequest(@NonNull S service) {
mWeakService = new WeakReference<>(service);
- mServiceHandler = service.mHandler;
- mTimeoutTrigger = () -> {
- synchronized (mLock) {
- if (mCancelled) {
- return;
- }
- mCompleted = true;
- }
-
- final S remoteService = mWeakService.get();
- if (remoteService != null) {
- // TODO(b/117779333): we should probably ignore it if service is destroyed.
- Slog.w(mTag, "timed out after " + service.getRemoteRequestMillis() + " ms");
- onTimeout(remoteService);
- } else {
- Slog.w(mTag, "timed out (no service)");
- }
- };
- mServiceHandler.postAtTime(mTimeoutTrigger,
- SystemClock.uptimeMillis() + service.getRemoteRequestMillis());
}
/**
@@ -543,10 +533,13 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
service.finishRequest(this);
}
- mServiceHandler.removeCallbacks(mTimeoutTrigger);
+ onFinished();
+
return true;
}
+ void onFinished() { }
+
/**
* Checks whether this request was cancelled.
*/
@@ -568,15 +561,11 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
mCancelled = true;
}
- mServiceHandler.removeCallbacks(mTimeoutTrigger);
+ onCancel();
return true;
}
- /**
- * Called by the self-destruct timeout when the remote service didn't reply to the
- * request on time.
- */
- protected abstract void onTimeout(S remoteService);
+ void onCancel() {}
/**
* Checks whether this request leads to a final state where no other requests can be made.
@@ -587,6 +576,67 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
}
/**
+ * Base class for the requests serviced by the remote service.
+ *
+ * <p><b>NOTE: </b> this class is typically used when the service needs to use a callback to
+ * communicate back with the system server. For cases where that's not needed, you should use
+ * {@link AbstractRemoteService#scheduleAsyncRequest(AsyncRequest)} instead.
+ *
+ * <p><b>NOTE: </b> you must override {@link AbstractRemoteService#getRemoteRequestMillis()},
+ * otherwise the constructor will throw an {@link UnsupportedOperationException}.
+ *
+ * @param <S> the remote service class
+ * @param <I> the interface of the binder service
+ */
+ public abstract static class PendingRequest<S extends AbstractRemoteService<S, I>,
+ I extends IInterface> extends BasePendingRequest<S, I> {
+
+ private final Runnable mTimeoutTrigger;
+ private final Handler mServiceHandler;
+
+ protected PendingRequest(S service) {
+ super(service);
+ mServiceHandler = service.mHandler;
+
+ mTimeoutTrigger = () -> {
+ synchronized (mLock) {
+ if (mCancelled) {
+ return;
+ }
+ mCompleted = true;
+ }
+
+ final S remoteService = mWeakService.get();
+ if (remoteService != null) {
+ // TODO(b/117779333): we should probably ignore it if service is destroyed.
+ Slog.w(mTag, "timed out after " + service.getRemoteRequestMillis() + " ms");
+ onTimeout(remoteService);
+ } else {
+ Slog.w(mTag, "timed out (no service)");
+ }
+ };
+ mServiceHandler.postAtTime(mTimeoutTrigger,
+ SystemClock.uptimeMillis() + service.getRemoteRequestMillis());
+ }
+
+ @Override
+ final void onFinished() {
+ mServiceHandler.removeCallbacks(mTimeoutTrigger);
+ }
+
+ @Override
+ final void onCancel() {
+ mServiceHandler.removeCallbacks(mTimeoutTrigger);
+ }
+
+ /**
+ * Called by the self-destruct timeout when the remote service didn't reply to the
+ * request on time.
+ */
+ protected abstract void onTimeout(S remoteService);
+ }
+
+ /**
* Represents a request that does not expect a callback from the remote service.
*
* @param <I> the interface of the binder service
@@ -600,7 +650,7 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
}
private static final class MyAsyncPendingRequest<S extends AbstractRemoteService<S, I>,
- I extends IInterface> extends PendingRequest<S, I> {
+ I extends IInterface> extends BasePendingRequest<S, I> {
private static final String TAG = MyAsyncPendingRequest.class.getSimpleName();
private final AsyncRequest<I> mRequest;
@@ -623,12 +673,5 @@ public abstract class AbstractRemoteService<S extends AbstractRemoteService<S, I
finish();
}
}
-
- @Override
- protected void onTimeout(S remoteService) {
- // TODO(b/117779333): should not happen because we called finish() on run(), although
- // currently it might be called if the service is destroyed while showing it.
- Slog.w(TAG, "AsyncPending requested timed out");
- }
}
}
diff --git a/core/java/com/android/internal/infra/AbstractSinglePendingRequestRemoteService.java b/core/java/com/android/internal/infra/AbstractSinglePendingRequestRemoteService.java
index f0c223388137..3e92a0b196ee 100644
--- a/core/java/com/android/internal/infra/AbstractSinglePendingRequestRemoteService.java
+++ b/core/java/com/android/internal/infra/AbstractSinglePendingRequestRemoteService.java
@@ -38,7 +38,7 @@ public abstract class AbstractSinglePendingRequestRemoteService<S
extends AbstractSinglePendingRequestRemoteService<S, I>, I extends IInterface>
extends AbstractRemoteService<S, I> {
- protected PendingRequest<S, I> mPendingRequest;
+ protected BasePendingRequest<S, I> mPendingRequest;
public AbstractSinglePendingRequestRemoteService(@NonNull Context context,
@NonNull String serviceInterface, @NonNull ComponentName componentName, int userId,
@@ -51,7 +51,7 @@ public abstract class AbstractSinglePendingRequestRemoteService<S
@Override // from AbstractRemoteService
void handlePendingRequests() {
if (mPendingRequest != null) {
- final PendingRequest<S, I> pendingRequest = mPendingRequest;
+ final BasePendingRequest<S, I> pendingRequest = mPendingRequest;
mPendingRequest = null;
handlePendingRequest(pendingRequest);
}
@@ -73,7 +73,7 @@ public abstract class AbstractSinglePendingRequestRemoteService<S
}
@Override // from AbstractRemoteService
- void handlePendingRequestWhileUnBound(@NonNull PendingRequest<S, I> pendingRequest) {
+ void handlePendingRequestWhileUnBound(@NonNull BasePendingRequest<S, I> pendingRequest) {
if (mPendingRequest != null) {
if (mVerbose) {
Slog.v(mTag, "handlePendingRequestWhileUnBound(): cancelling " + mPendingRequest
diff --git a/core/java/com/android/internal/os/RoSystemProperties.java b/core/java/com/android/internal/os/RoSystemProperties.java
index f4902d46992b..524a5cc353f3 100644
--- a/core/java/com/android/internal/os/RoSystemProperties.java
+++ b/core/java/com/android/internal/os/RoSystemProperties.java
@@ -61,17 +61,19 @@ public class RoSystemProperties {
SystemProperties.getBoolean("ro.fw.system_user_split", false);
// ------ ro.crypto.* -------- //
- public static final String CRYPTO_STATE = SystemProperties.get("ro.crypto.state");
- public static final String CRYPTO_TYPE = CryptoProperties.type().orElse("");
+ public static final CryptoProperties.state_values CRYPTO_STATE =
+ CryptoProperties.state().orElse(CryptoProperties.state_values.UNSUPPORTED);
+ public static final CryptoProperties.type_values CRYPTO_TYPE =
+ CryptoProperties.type().orElse(CryptoProperties.type_values.NONE);
// These are pseudo-properties
public static final boolean CRYPTO_ENCRYPTABLE =
- !CRYPTO_STATE.isEmpty() && !"unsupported".equals(CRYPTO_STATE);
+ CRYPTO_STATE != CryptoProperties.state_values.UNSUPPORTED;
public static final boolean CRYPTO_ENCRYPTED =
- "encrypted".equalsIgnoreCase(CRYPTO_STATE);
+ CRYPTO_STATE == CryptoProperties.state_values.ENCRYPTED;
public static final boolean CRYPTO_FILE_ENCRYPTED =
- "file".equalsIgnoreCase(CRYPTO_TYPE);
+ CRYPTO_TYPE == CryptoProperties.type_values.FILE;
public static final boolean CRYPTO_BLOCK_ENCRYPTED =
- "block".equalsIgnoreCase(CRYPTO_TYPE);
+ CRYPTO_TYPE == CryptoProperties.type_values.BLOCK;
public static final boolean CONTROL_PRIVAPP_PERMISSIONS_LOG =
"log".equalsIgnoreCase(CONTROL_PRIVAPP_PERMISSIONS);
diff --git a/core/java/com/android/internal/policy/BackdropFrameRenderer.java b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
index cc958f4ed735..fa737582f7f6 100644
--- a/core/java/com/android/internal/policy/BackdropFrameRenderer.java
+++ b/core/java/com/android/internal/policy/BackdropFrameRenderer.java
@@ -339,7 +339,7 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
mFrameAndBackdropNode.setLeftTopRightBottom(left, top, left + width, top + height);
// Draw the caption and content backdrops in to our render node.
- RecordingCanvas canvas = mFrameAndBackdropNode.start(width, height);
+ RecordingCanvas canvas = mFrameAndBackdropNode.beginRecording(width, height);
final Drawable drawable = mUserCaptionBackgroundDrawable != null
? mUserCaptionBackgroundDrawable : mCaptionBackgroundDrawable;
@@ -353,7 +353,7 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
mResizingBackgroundDrawable.setBounds(0, mLastCaptionHeight, left + width, top + height);
mResizingBackgroundDrawable.draw(canvas);
}
- mFrameAndBackdropNode.end(canvas);
+ mFrameAndBackdropNode.endRecording();
drawColorViews(left, top, width, height, fullscreen, systemInsets, stableInsets);
@@ -368,7 +368,7 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
if (mSystemBarBackgroundNode == null) {
return;
}
- RecordingCanvas canvas = mSystemBarBackgroundNode.start(width, height);
+ RecordingCanvas canvas = mSystemBarBackgroundNode.beginRecording(width, height);
mSystemBarBackgroundNode.setLeftTopRightBottom(left, top, left + width, top + height);
final int topInset = DecorView.getColorViewTopInset(mStableInsets.top, mSystemInsets.top);
if (mStatusBarColor != null) {
@@ -384,7 +384,7 @@ public class BackdropFrameRenderer extends Thread implements Choreographer.Frame
mNavigationBarColor.setBounds(mTmpRect);
mNavigationBarColor.draw(canvas);
}
- mSystemBarBackgroundNode.end(canvas);
+ mSystemBarBackgroundNode.endRecording();
mRenderer.drawRenderNode(mSystemBarBackgroundNode);
}
diff --git a/core/jni/android_opengl_EGL14.cpp b/core/jni/android_opengl_EGL14.cpp
index 15d1944205b6..13b059830eb9 100644
--- a/core/jni/android_opengl_EGL14.cpp
+++ b/core/jni/android_opengl_EGL14.cpp
@@ -35,8 +35,6 @@
#include <ui/ANativeObjectBase.h>
-static int initialized = 0;
-
static jclass egldisplayClass;
static jclass eglcontextClass;
static jclass eglsurfaceClass;
diff --git a/core/jni/android_opengl_EGL15.cpp b/core/jni/android_opengl_EGL15.cpp
index 2abd95020f1c..563f5db011e7 100644
--- a/core/jni/android_opengl_EGL15.cpp
+++ b/core/jni/android_opengl_EGL15.cpp
@@ -27,8 +27,6 @@
#include <ui/ANativeObjectBase.h>
-static int initialized = 0;
-
// classes from EGL 1.4
static jclass egldisplayClass;
static jclass eglsurfaceClass;
@@ -171,8 +169,6 @@ getPointer(JNIEnv *_env, jobject buffer, jarray *array, jint *remaining, jint *o
*array = NULL;
return reinterpret_cast<void*>(pointer);
}
- eglimageGetHandleID = _env->GetMethodID(eglimageClass, "getNativeHandle", "()J");
- eglsyncGetHandleID = _env->GetMethodID(eglsyncClass, "getNativeHandle", "()J");
*array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
getBaseArrayID, buffer);
diff --git a/core/jni/android_opengl_EGLExt.cpp b/core/jni/android_opengl_EGLExt.cpp
index 75a25fe95e09..1eb110135bf5 100644
--- a/core/jni/android_opengl_EGLExt.cpp
+++ b/core/jni/android_opengl_EGLExt.cpp
@@ -36,8 +36,6 @@
#include <ui/ANativeObjectBase.h>
-static int initialized = 0;
-
static jclass egldisplayClass;
static jclass eglcontextClass;
static jclass eglsurfaceClass;
diff --git a/core/jni/android_opengl_GLES10.cpp b/core/jni/android_opengl_GLES10.cpp
index ee5b5941202d..a4ab5db8c8d7 100644
--- a/core/jni/android_opengl_GLES10.cpp
+++ b/core/jni/android_opengl_GLES10.cpp
@@ -29,8 +29,6 @@
#include <utils/misc.h>
#include <assert.h>
-static int initialized = 0;
-
static jclass nioAccessClass;
static jclass bufferClass;
static jmethodID getBasePointerID;
diff --git a/core/jni/android_opengl_GLES10Ext.cpp b/core/jni/android_opengl_GLES10Ext.cpp
index da7d0f01928f..ee82fc71ce8d 100644
--- a/core/jni/android_opengl_GLES10Ext.cpp
+++ b/core/jni/android_opengl_GLES10Ext.cpp
@@ -29,8 +29,6 @@
#include <utils/misc.h>
#include <assert.h>
-static int initialized = 0;
-
static jclass nioAccessClass;
static jclass bufferClass;
static jmethodID getBasePointerID;
diff --git a/core/jni/android_opengl_GLES11.cpp b/core/jni/android_opengl_GLES11.cpp
index 391ae5366a3b..be86a037bfbd 100644
--- a/core/jni/android_opengl_GLES11.cpp
+++ b/core/jni/android_opengl_GLES11.cpp
@@ -29,8 +29,6 @@
#include <utils/misc.h>
#include <assert.h>
-static int initialized = 0;
-
static jclass nioAccessClass;
static jclass bufferClass;
static jmethodID getBasePointerID;
diff --git a/core/jni/android_opengl_GLES11Ext.cpp b/core/jni/android_opengl_GLES11Ext.cpp
index 09dce32b9e56..d28d9a387b5e 100644
--- a/core/jni/android_opengl_GLES11Ext.cpp
+++ b/core/jni/android_opengl_GLES11Ext.cpp
@@ -29,8 +29,6 @@
#include <utils/misc.h>
#include <assert.h>
-static int initialized = 0;
-
static jclass nioAccessClass;
static jclass bufferClass;
static jmethodID getBasePointerID;
diff --git a/core/jni/android_opengl_GLES20.cpp b/core/jni/android_opengl_GLES20.cpp
index 99922cfe401d..ff4536ee17de 100644
--- a/core/jni/android_opengl_GLES20.cpp
+++ b/core/jni/android_opengl_GLES20.cpp
@@ -29,8 +29,6 @@
#include <utils/misc.h>
#include <assert.h>
-static int initialized = 0;
-
static jclass nioAccessClass;
static jclass bufferClass;
static jmethodID getBasePointerID;
diff --git a/core/jni/android_opengl_GLES30.cpp b/core/jni/android_opengl_GLES30.cpp
index adc635ed4eea..9aca86672fb9 100644
--- a/core/jni/android_opengl_GLES30.cpp
+++ b/core/jni/android_opengl_GLES30.cpp
@@ -29,8 +29,6 @@
#include <utils/misc.h>
#include <assert.h>
-static int initialized = 0;
-
static jclass nioAccessClass;
static jclass bufferClass;
static jmethodID getBasePointerID;
diff --git a/core/jni/android_opengl_GLES31.cpp b/core/jni/android_opengl_GLES31.cpp
index 512f562062e6..4c51e2dc5f37 100644
--- a/core/jni/android_opengl_GLES31.cpp
+++ b/core/jni/android_opengl_GLES31.cpp
@@ -27,8 +27,6 @@
#include <utils/misc.h>
#include <assert.h>
-static int initialized = 0;
-
static jclass nioAccessClass;
static jclass bufferClass;
static jmethodID getBasePointerID;
diff --git a/core/jni/android_opengl_GLES31Ext.cpp b/core/jni/android_opengl_GLES31Ext.cpp
index 5543fcadaed0..5b671c8e55fb 100644
--- a/core/jni/android_opengl_GLES31Ext.cpp
+++ b/core/jni/android_opengl_GLES31Ext.cpp
@@ -28,8 +28,6 @@
#include <utils/misc.h>
#include <assert.h>
-static int initialized = 0;
-
static jclass nioAccessClass;
static jclass bufferClass;
static jmethodID getBasePointerID;
diff --git a/core/jni/android_opengl_GLES32.cpp b/core/jni/android_opengl_GLES32.cpp
index 2f1e31e7fab9..d59d25c2c483 100644
--- a/core/jni/android_opengl_GLES32.cpp
+++ b/core/jni/android_opengl_GLES32.cpp
@@ -27,8 +27,6 @@
#include <utils/misc.h>
#include <assert.h>
-static int initialized = 0;
-
static jclass nioAccessClass;
static jclass bufferClass;
static jmethodID getBasePointerID;
diff --git a/core/jni/android_os_GraphicsEnvironment.cpp b/core/jni/android_os_GraphicsEnvironment.cpp
index d9d3cdf43d18..72e3d3495e37 100644
--- a/core/jni/android_os_GraphicsEnvironment.cpp
+++ b/core/jni/android_os_GraphicsEnvironment.cpp
@@ -27,9 +27,12 @@ int getCanLoadSystemLibraries_native() {
return android::GraphicsEnv::getInstance().getCanLoadSystemLibraries();
}
-void setDriverPath(JNIEnv* env, jobject clazz, jstring path) {
+void setDriverPathAndSphalLibraries_native(JNIEnv* env, jobject clazz, jstring path,
+ jstring sphalLibraries) {
ScopedUtfChars pathChars(env, path);
- android::GraphicsEnv::getInstance().setDriverPath(pathChars.c_str());
+ ScopedUtfChars sphalLibrariesChars(env, sphalLibraries);
+ android::GraphicsEnv::getInstance().setDriverPathAndSphalLibraries(pathChars.c_str(),
+ sphalLibrariesChars.c_str());
}
void setGpuStats_native(JNIEnv* env, jobject clazz, jstring driverPackageName,
@@ -84,7 +87,7 @@ void setDebugLayersGLES_native(JNIEnv* env, jobject clazz, jstring layers) {
const JNINativeMethod g_methods[] = {
{ "getCanLoadSystemLibraries", "()I", reinterpret_cast<void*>(getCanLoadSystemLibraries_native) },
- { "setDriverPath", "(Ljava/lang/String;)V", reinterpret_cast<void*>(setDriverPath) },
+ { "setDriverPathAndSphalLibraries", "(Ljava/lang/String;Ljava/lang/String;)V", reinterpret_cast<void*>(setDriverPathAndSphalLibraries_native) },
{ "setGpuStats", "(Ljava/lang/String;Ljava/lang/String;JJLjava/lang/String;)V", reinterpret_cast<void*>(setGpuStats_native) },
{ "setAngleInfo", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/io/FileDescriptor;JJ)V", reinterpret_cast<void*>(setAngleInfo_native) },
{ "getShouldUseAngle", "(Ljava/lang/String;)Z", reinterpret_cast<void*>(shouldUseAngle_native) },
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index a212f47c0104..af2d41399016 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -343,7 +343,9 @@ static jobject NativeGetOverlayableMap(JNIEnv* env, jclass /*clazz*/, jlong ptr,
assetmanager->ForEachPackage([&](const std::string& this_package_name, uint8_t package_id) {
if (this_package_name == std_package_name) {
map = assetmanager->GetOverlayableMapForPackage(package_id);
+ return false;
}
+ return true;
});
if (map == nullptr) {
@@ -521,15 +523,16 @@ static jobject NativeGetAssignedPackageIdentifiers(JNIEnv* env, jclass /*clazz*/
return nullptr;
}
- assetmanager->ForEachPackage([&](const std::string& package_name, uint8_t package_id) {
+ assetmanager->ForEachPackage([&](const std::string& package_name, uint8_t package_id) -> bool {
jstring jpackage_name = env->NewStringUTF(package_name.c_str());
if (jpackage_name == nullptr) {
// An exception is pending.
- return;
+ return false;
}
env->CallVoidMethod(sparse_array, gSparseArrayOffsets.put, static_cast<jint>(package_id),
jpackage_name);
+ return true;
});
return sparse_array;
}
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 6b8d8b1bb91f..4069e95d8c35 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -205,7 +205,7 @@ static Rect rectFromObj(JNIEnv* env, jobject rectObj) {
static jobject nativeScreenshot(JNIEnv* env, jclass clazz,
jobject displayTokenObj, jobject sourceCropObj, jint width, jint height,
- bool useIdentityTransform, int rotation) {
+ bool useIdentityTransform, int rotation, bool captureSecureLayers) {
sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
if (displayToken == NULL) {
return NULL;
@@ -213,9 +213,9 @@ static jobject nativeScreenshot(JNIEnv* env, jclass clazz,
Rect sourceCrop = rectFromObj(env, sourceCropObj);
sp<GraphicBuffer> buffer;
status_t res = ScreenshotClient::capture(displayToken, ui::Dataspace::V0_SRGB,
- ui::PixelFormat::RGBA_8888,
- sourceCrop, width, height,
- useIdentityTransform, rotation, &buffer);
+ ui::PixelFormat::RGBA_8888,
+ sourceCrop, width, height,
+ useIdentityTransform, rotation, captureSecureLayers, &buffer);
if (res != NO_ERROR) {
return NULL;
}
@@ -406,6 +406,11 @@ static void nativeTransferTouchFocus(JNIEnv* env, jclass clazz, jlong transactio
transaction->transferTouchFocus(fromToken, toToken);
}
+static void nativeSyncInputWindows(JNIEnv* env, jclass clazz, jlong transactionObj) {
+ auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
+ transaction->syncInputWindows();
+}
+
static void nativeSetMetadata(JNIEnv* env, jclass clazz, jlong transactionObj,
jlong nativeObject, jint id, jobject parcelObj) {
Parcel* parcel = parcelForJavaObject(env, parcelObj);
@@ -1227,7 +1232,7 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeSetOverrideScalingMode },
{"nativeGetHandle", "(J)Landroid/os/IBinder;",
(void*)nativeGetHandle },
- {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/graphics/Rect;IIZI)Landroid/graphics/GraphicBuffer;",
+ {"nativeScreenshot", "(Landroid/os/IBinder;Landroid/graphics/Rect;IIZIZ)Landroid/graphics/GraphicBuffer;",
(void*)nativeScreenshot },
{"nativeCaptureLayers", "(Landroid/os/IBinder;Landroid/graphics/Rect;F)Landroid/graphics/GraphicBuffer;",
(void*)nativeCaptureLayers },
@@ -1246,7 +1251,9 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
"(Landroid/os/IBinder;JJ)Landroid/hardware/display/DisplayedContentSample;",
(void*)nativeGetDisplayedContentSample },
{"nativeSetGeometry", "(JJLandroid/graphics/Rect;Landroid/graphics/Rect;J)V",
- (void*)nativeSetGeometry }
+ (void*)nativeSetGeometry },
+ {"nativeSyncInputWindows", "(J)V",
+ (void*)nativeSyncInputWindows }
};
int register_android_view_SurfaceControl(JNIEnv* env)
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 15ceca96313e..73e67896443c 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -572,214 +572,246 @@ static void SetSchedulerPolicy(fail_fn_t fail_fn) {
}
static int UnmountTree(const char* path) {
- size_t path_len = strlen(path);
+ size_t path_len = strlen(path);
- FILE* fp = setmntent("/proc/mounts", "r");
- if (fp == nullptr) {
- ALOGE("Error opening /proc/mounts: %s", strerror(errno));
- return -errno;
- }
+ FILE* fp = setmntent("/proc/mounts", "r");
+ if (fp == nullptr) {
+ ALOGE("Error opening /proc/mounts: %s", strerror(errno));
+ return -errno;
+ }
- // Some volumes can be stacked on each other, so force unmount in
- // reverse order to give us the best chance of success.
- std::list<std::string> toUnmount;
- mntent* mentry;
- while ((mentry = getmntent(fp)) != nullptr) {
- if (strncmp(mentry->mnt_dir, path, path_len) == 0) {
- toUnmount.push_front(std::string(mentry->mnt_dir));
- }
+ // Some volumes can be stacked on each other, so force unmount in
+ // reverse order to give us the best chance of success.
+ std::list<std::string> to_unmount;
+ mntent* mentry;
+ while ((mentry = getmntent(fp)) != nullptr) {
+ if (strncmp(mentry->mnt_dir, path, path_len) == 0) {
+ to_unmount.push_front(std::string(mentry->mnt_dir));
}
- endmntent(fp);
+ }
+ endmntent(fp);
- for (const auto& path : toUnmount) {
- if (umount2(path.c_str(), MNT_DETACH)) {
- ALOGW("Failed to unmount %s: %s", path.c_str(), strerror(errno));
- }
+ for (const auto& path : to_unmount) {
+ if (umount2(path.c_str(), MNT_DETACH)) {
+ ALOGW("Failed to unmount %s: %s", path.c_str(), strerror(errno));
}
- return 0;
+ }
+ return 0;
}
static void CreateDir(const std::string& dir,
mode_t mode, uid_t uid, gid_t gid,
fail_fn_t fail_fn) {
- if (TEMP_FAILURE_RETRY(access(dir.c_str(), F_OK)) == 0) {
- return;
- } else if (errno != ENOENT) {
- fail_fn(CREATE_ERROR("Failed to stat %s: %s", dir.c_str(), strerror(errno)));
- }
- if (fs_prepare_dir(dir.c_str(), mode, uid, gid) != 0) {
- fail_fn(CREATE_ERROR("fs_prepare_dir failed on %s: %s",
- dir.c_str(), strerror(errno)));
- }
+ if (TEMP_FAILURE_RETRY(access(dir.c_str(), F_OK)) == 0) {
+ return;
+ } else if (errno != ENOENT) {
+ fail_fn(CREATE_ERROR("Failed to stat %s: %s", dir.c_str(), strerror(errno)));
+ }
+ if (fs_prepare_dir(dir.c_str(), mode, uid, gid) != 0) {
+ fail_fn(CREATE_ERROR("fs_prepare_dir failed on %s: %s",
+ dir.c_str(), strerror(errno)));
+ }
}
-static void CreatePkgSandboxTarget(uid_t uid, const std::string& package_name, fail_fn_t fail_fn) {
- // Create /mnt/user/0/package/<package-name>
- userid_t user_id = multiuser_get_user_id(uid);
- std::string pkg_sandbox_dir = StringPrintf("/mnt/user/%d", user_id);
- CreateDir(pkg_sandbox_dir, 0751, AID_ROOT, AID_ROOT, fail_fn);
-
- StringAppendF(&pkg_sandbox_dir, "/package");
- CreateDir(pkg_sandbox_dir, 0700, AID_ROOT, AID_ROOT, fail_fn);
+static void CreatePkgSandboxTarget(userid_t user_id, fail_fn_t fail_fn) {
+ // Create /mnt/user/0/package
+ std::string pkg_sandbox_dir = StringPrintf("/mnt/user/%d", user_id);
+ CreateDir(pkg_sandbox_dir, 0751, AID_ROOT, AID_ROOT, fail_fn);
- StringAppendF(&pkg_sandbox_dir, "/%s", package_name.c_str());
- CreateDir(pkg_sandbox_dir, 0755, uid, uid, fail_fn);
+ StringAppendF(&pkg_sandbox_dir, "/package");
+ CreateDir(pkg_sandbox_dir, 0755, AID_ROOT, AID_ROOT, fail_fn);
}
-static void BindMount(const std::string& sourceDir, const std::string& targetDir,
+static void BindMount(const std::string& source_dir, const std::string& target_dir,
fail_fn_t fail_fn) {
- if (TEMP_FAILURE_RETRY(mount(sourceDir.c_str(), targetDir.c_str(), nullptr,
- MS_BIND, nullptr)) == -1) {
- fail_fn(CREATE_ERROR("Failed to mount %s to %s: %s",
- sourceDir.c_str(), targetDir.c_str(), strerror(errno)));
- }
+ if (TEMP_FAILURE_RETRY(mount(source_dir.c_str(), target_dir.c_str(), nullptr,
+ MS_BIND, nullptr)) == -1) {
+ fail_fn(CREATE_ERROR("Failed to mount %s to %s: %s",
+ source_dir.c_str(), target_dir.c_str(), strerror(errno)));
+ }
}
-static void MountPkgSpecificDir(const std::string& mntSourceRoot,
- const std::string& mntTargetRoot,
- const std::string& packageName,
+static void MountPkgSpecificDir(const std::string& mnt_source_root,
+ const std::string& mnt_target_root,
+ const std::string& package_name,
uid_t uid,
- const char* dirName,
+ const char* dir_name,
fail_fn_t fail_fn) {
- std::string mntSourceDir = StringPrintf("%s/Android/%s/%s",
- mntSourceRoot.c_str(), dirName, packageName.c_str());
+ std::string mnt_source_dir = StringPrintf("%s/Android/%s/%s",
+ mnt_source_root.c_str(), dir_name, package_name.c_str());
- std::string mntTargetDir = StringPrintf("%s/Android/%s/%s",
- mntTargetRoot.c_str(), dirName, packageName.c_str());
+ std::string mnt_target_dir = StringPrintf("%s/Android/%s/%s",
+ mnt_target_root.c_str(), dir_name, package_name.c_str());
- BindMount(mntSourceDir, mntTargetDir, fail_fn);
+ BindMount(mnt_source_dir, mnt_target_dir, fail_fn);
}
-static void CreateSubDirs(int dirfd, const std::string& parentDirPath,
- const std::vector<std::string>& subDirs,
+static void CreateSubDirs(int parent_fd, const std::string& parent_path,
+ const std::vector<std::string>& sub_dirs,
fail_fn_t fail_fn) {
- for (auto& dirName : subDirs) {
- struct stat sb;
- if (TEMP_FAILURE_RETRY(fstatat(dirfd, dirName.c_str(), &sb, 0)) == 0) {
- if (S_ISDIR(sb.st_mode)) {
- continue;
- } else if (TEMP_FAILURE_RETRY(unlinkat(dirfd, dirName.c_str(), 0)) == -1) {
- fail_fn(CREATE_ERROR("Failed to unlinkat on %s/%s: %s",
- parentDirPath.c_str(), dirName.c_str(), strerror(errno)));
- }
- } else if (errno != ENOENT) {
- fail_fn(CREATE_ERROR("Failed to fstatat on %s/%s: %s",
- parentDirPath.c_str(), dirName.c_str(), strerror(errno)));
- }
- if (TEMP_FAILURE_RETRY(mkdirat(dirfd, dirName.c_str(), 0700)) == -1 && errno != EEXIST) {
- fail_fn(CREATE_ERROR("Failed to mkdirat on %s/%s: %s",
- parentDirPath.c_str(), dirName.c_str(), strerror(errno)));
- }
+ for (auto& dir_name : sub_dirs) {
+ struct stat sb;
+ if (TEMP_FAILURE_RETRY(fstatat(parent_fd, dir_name.c_str(), &sb, 0)) == 0) {
+ if (S_ISDIR(sb.st_mode)) {
+ continue;
+ } else if (TEMP_FAILURE_RETRY(unlinkat(parent_fd, dir_name.c_str(), 0)) == -1) {
+ fail_fn(CREATE_ERROR("Failed to unlinkat on %s/%s: %s",
+ parent_path.c_str(), dir_name.c_str(), strerror(errno)));
+ }
+ } else if (errno != ENOENT) {
+ fail_fn(CREATE_ERROR("Failed to fstatat on %s/%s: %s",
+ parent_path.c_str(), dir_name.c_str(), strerror(errno)));
}
+ if (TEMP_FAILURE_RETRY(mkdirat(parent_fd, dir_name.c_str(), 0700)) == -1 && errno != EEXIST) {
+ fail_fn(CREATE_ERROR("Failed to mkdirat on %s/%s: %s",
+ parent_path.c_str(), dir_name.c_str(), strerror(errno)));
+ }
+ }
}
static void EnsurePkgSpecificDirs(const std::string& path,
- const std::vector<std::string>& packageNames,
- bool createSandboxDir,
+ const std::vector<std::string>& package_names,
+ bool create_sandbox_dir,
fail_fn_t fail_fn) {
- std::string androidDir = StringPrintf("%s/Android", path.c_str());
- android::base::unique_fd androidFd(
- open(androidDir.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
- if (androidFd.get() < 0) {
- if (errno == ENOENT || errno == ENOTDIR) {
- if (errno == ENOTDIR && TEMP_FAILURE_RETRY(unlink(androidDir.c_str())) == -1) {
- fail_fn(CREATE_ERROR("Failed to unlink %s: %s",
- androidDir.c_str(), strerror(errno)));
- }
- if (TEMP_FAILURE_RETRY(mkdir(androidDir.c_str(), 0700)) == -1
- && errno != EEXIST) {
- fail_fn(CREATE_ERROR("Failed to mkdir %s: %s",
- androidDir.c_str(), strerror(errno)));
- }
- androidFd.reset(open(androidDir.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
- }
-
- if (androidFd.get() < 0) {
- fail_fn(CREATE_ERROR("Failed to open %s: %s", androidDir.c_str(), strerror(errno)));
- }
+ std::string android_dir = StringPrintf("%s/Android", path.c_str());
+ android::base::unique_fd android_fd(open(android_dir.c_str(),
+ O_RDONLY | O_DIRECTORY | O_CLOEXEC));
+ if (android_fd.get() < 0) {
+ if (errno == ENOENT || errno == ENOTDIR) {
+ if (errno == ENOTDIR && TEMP_FAILURE_RETRY(unlink(android_dir.c_str())) == -1) {
+ fail_fn(CREATE_ERROR("Failed to unlink %s: %s",
+ android_dir.c_str(), strerror(errno)));
+ }
+ if (TEMP_FAILURE_RETRY(mkdir(android_dir.c_str(), 0700)) == -1
+ && errno != EEXIST) {
+ fail_fn(CREATE_ERROR("Failed to mkdir %s: %s",
+ android_dir.c_str(), strerror(errno)));
+ }
+ android_fd.reset(open(android_dir.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
}
- std::vector<std::string> dataMediaObbDirs = {"data", "media", "obb"};
- if (createSandboxDir) {
- dataMediaObbDirs.push_back("sandbox");
- }
- CreateSubDirs(androidFd.get(), androidDir, dataMediaObbDirs, fail_fn);
- if (createSandboxDir) {
- dataMediaObbDirs.pop_back();
+ if (android_fd.get() < 0) {
+ fail_fn(CREATE_ERROR("Failed to open %s: %s", android_dir.c_str(), strerror(errno)));
}
- for (auto& dirName : dataMediaObbDirs) {
- std::string dataDir = StringPrintf("%s/%s", androidDir.c_str(), dirName.c_str());
- android::base::unique_fd dataFd(
- openat(androidFd, dirName.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
- if (dataFd.get() < 0) {
- fail_fn(CREATE_ERROR("Failed to openat %s/%s: %s",
- androidDir.c_str(), dirName.c_str(), strerror(errno)));
- }
- CreateSubDirs(dataFd.get(), dataDir, packageNames, fail_fn);
+ }
+
+ std::vector<std::string> data_media_obb_dirs = {"data", "media", "obb"};
+ if (create_sandbox_dir) {
+ data_media_obb_dirs.push_back("sandbox");
+ }
+ CreateSubDirs(android_fd.get(), android_dir, data_media_obb_dirs, fail_fn);
+ if (create_sandbox_dir) {
+ data_media_obb_dirs.pop_back();
+ }
+ for (auto& dir_name : data_media_obb_dirs) {
+ std::string data_dir = StringPrintf("%s/%s", android_dir.c_str(), dir_name.c_str());
+ android::base::unique_fd data_fd(openat(android_fd, dir_name.c_str(),
+ O_RDONLY | O_DIRECTORY | O_CLOEXEC));
+ if (data_fd.get() < 0) {
+ fail_fn(CREATE_ERROR("Failed to openat %s/%s: %s",
+ android_dir.c_str(), dir_name.c_str(), strerror(errno)));
}
+ CreateSubDirs(data_fd.get(), data_dir, package_names, fail_fn);
+ }
}
-static void CreatePkgSandboxSource(const std::string& sandboxSource, fail_fn_t fail_fn) {
+static void CreatePkgSandboxSource(const std::string& sandbox_source, fail_fn_t fail_fn) {
- struct stat sb;
- if (TEMP_FAILURE_RETRY(stat(sandboxSource.c_str(), &sb)) == 0) {
- if (S_ISDIR(sb.st_mode)) {
- return;
- } else if (TEMP_FAILURE_RETRY(unlink(sandboxSource.c_str())) == -1) {
- fail_fn(CREATE_ERROR("Failed to unlink %s: %s",
- sandboxSource.c_str(), strerror(errno)));
- }
- } else if (errno != ENOENT) {
- fail_fn(CREATE_ERROR("Failed to stat %s: %s",
- sandboxSource.c_str(), strerror(errno)));
- }
- if (TEMP_FAILURE_RETRY(mkdir(sandboxSource.c_str(), 0700)) == -1 && errno != EEXIST) {
- fail_fn(CREATE_ERROR("Failed to mkdir %s: %s",
- sandboxSource.c_str(), strerror(errno)));
+ struct stat sb;
+ if (TEMP_FAILURE_RETRY(stat(sandbox_source.c_str(), &sb)) == 0) {
+ if (S_ISDIR(sb.st_mode)) {
+ return;
+ } else if (TEMP_FAILURE_RETRY(unlink(sandbox_source.c_str())) == -1) {
+ fail_fn(CREATE_ERROR("Failed to unlink %s: %s",
+ sandbox_source.c_str(), strerror(errno)));
}
+ } else if (errno != ENOENT) {
+ fail_fn(CREATE_ERROR("Failed to stat %s: %s",
+ sandbox_source.c_str(), strerror(errno)));
+ }
+ if (TEMP_FAILURE_RETRY(mkdir(sandbox_source.c_str(), 0700)) == -1 && errno != EEXIST) {
+ fail_fn(CREATE_ERROR("Failed to mkdir %s: %s",
+ sandbox_source.c_str(), strerror(errno)));
+ }
}
-static void PreparePkgSpecificDirs(const std::vector<std::string>& packageNames,
- const std::vector<std::string>& volumeLabels,
- bool mountAllObbs, const std::string& sandboxId,
- userid_t userId, uid_t uid, fail_fn_t fail_fn) {
- for (auto& label : volumeLabels) {
- std::string mntSource = StringPrintf("/mnt/runtime/write/%s", label.c_str());
- std::string mntTarget = StringPrintf("/storage/%s", label.c_str());
- if (label == "emulated") {
- StringAppendF(&mntSource, "/%d", userId);
- StringAppendF(&mntTarget, "/%d", userId);
- }
+static void PreparePkgSpecificDirs(const std::vector<std::string>& package_names,
+ const std::vector<std::string>& volume_labels,
+ bool mount_all_obbs, const std::string& sandbox_id,
+ userid_t user_id, uid_t uid, fail_fn_t fail_fn) {
+ for (auto& label : volume_labels) {
+ std::string mnt_source = StringPrintf("/mnt/runtime/write/%s", label.c_str());
+ std::string mnt_target = StringPrintf("/storage/%s", label.c_str());
+ if (label == "emulated") {
+ StringAppendF(&mnt_source, "/%d", user_id);
+ StringAppendF(&mnt_target, "/%d", user_id);
+ }
- if (TEMP_FAILURE_RETRY(access(mntSource.c_str(), F_OK)) == -1) {
- ALOGE("Can't access %s: %s", mntSource.c_str(), strerror(errno));
- continue;
- }
+ if (TEMP_FAILURE_RETRY(access(mnt_source.c_str(), F_OK)) == -1) {
+ ALOGE("Can't access %s: %s", mnt_source.c_str(), strerror(errno));
+ continue;
+ } else if (TEMP_FAILURE_RETRY(access(mnt_target.c_str(), F_OK)) == -1) {
+ ALOGE("Can't access %s: %s", mnt_target.c_str(), strerror(errno));
+ continue;
+ }
- // Ensure /mnt/runtime/write/emulated/0/Android/{data,media,obb}
- EnsurePkgSpecificDirs(mntSource, packageNames, true, fail_fn);
-
- std::string sandboxSource = StringPrintf("%s/Android/sandbox/%s",
- mntSource.c_str(), sandboxId.c_str());
- CreatePkgSandboxSource(sandboxSource, fail_fn);
- BindMount(sandboxSource, mntTarget, fail_fn);
-
- // Ensure /storage/emulated/0/Android/{data,media,obb}
- EnsurePkgSpecificDirs(mntTarget, packageNames, false, fail_fn);
- for (auto& package : packageNames) {
- MountPkgSpecificDir(mntSource, mntTarget, package, uid, "data", fail_fn);
- MountPkgSpecificDir(mntSource, mntTarget, package, uid, "media", fail_fn);
- if (!mountAllObbs) {
- MountPkgSpecificDir(mntSource, mntTarget, package, uid, "obb", fail_fn);
- }
- }
+ // Ensure /mnt/runtime/write/emulated/0/Android/{data,media,obb}
+ EnsurePkgSpecificDirs(mnt_source, package_names, true, fail_fn);
+
+ std::string sandbox_source = StringPrintf("%s/Android/sandbox/%s",
+ mnt_source.c_str(), sandbox_id.c_str());
+ CreatePkgSandboxSource(sandbox_source, fail_fn);
+ BindMount(sandbox_source, mnt_target, fail_fn);
+
+ // Ensure /storage/emulated/0/Android/{data,media,obb}
+ EnsurePkgSpecificDirs(mnt_target, package_names, false, fail_fn);
+ for (auto& package : package_names) {
+ MountPkgSpecificDir(mnt_source, mnt_target, package, uid, "data", fail_fn);
+ MountPkgSpecificDir(mnt_source, mnt_target, package, uid, "media", fail_fn);
+ if (!mount_all_obbs) {
+ MountPkgSpecificDir(mnt_source, mnt_target, package, uid, "obb", fail_fn);
+ }
+ }
- if (mountAllObbs) {
- StringAppendF(&mntSource, "/Android/obb");
- StringAppendF(&mntTarget, "/Android/obb");
- BindMount(mntSource, mntTarget, fail_fn);
- }
+ if (mount_all_obbs) {
+ StringAppendF(&mnt_source, "/Android/obb");
+ StringAppendF(&mnt_target, "/Android/obb");
+ BindMount(mnt_source, mnt_target, fail_fn);
}
+ }
+}
+
+static void HandleMountModeInstaller(int mount_mode,
+ userid_t user_id,
+ const std::string& sandbox_id,
+ fail_fn_t fail_fn) {
+ std::string obb_mount_dir = StringPrintf("/mnt/user/%d/obb_mount", user_id);
+ std::string obb_mount_file = StringPrintf("%s/%s", obb_mount_dir.c_str(), sandbox_id.c_str());
+ if (mount_mode == MOUNT_EXTERNAL_INSTALLER) {
+ if (TEMP_FAILURE_RETRY(access(obb_mount_file.c_str(), F_OK)) != -1) {
+ return;
+ } else if (errno != ENOENT) {
+ fail_fn(CREATE_ERROR("Failed to access %s: %s", obb_mount_file.c_str(), strerror(errno)));
+ }
+ if (fs_prepare_dir(obb_mount_dir.c_str(), 0700, AID_ROOT, AID_ROOT) != 0) {
+ fail_fn(CREATE_ERROR("Failed to fs_prepare_dir %s: %s",
+ obb_mount_dir.c_str(), strerror(errno)));
+ }
+ const android::base::unique_fd fd(TEMP_FAILURE_RETRY(
+ open(obb_mount_file.c_str(), O_RDWR | O_CREAT, 0600)));
+ if (fd.get() < 0) {
+ fail_fn(CREATE_ERROR("Failed to create %s: %s", obb_mount_file.c_str(), strerror(errno)));
+ }
+ } else {
+ if (TEMP_FAILURE_RETRY(access(obb_mount_file.c_str(), F_OK)) != -1) {
+ if (TEMP_FAILURE_RETRY(unlink(obb_mount_file.c_str())) == -1) {
+ fail_fn(CREATE_ERROR("Failed to unlink %s: %s",
+ obb_mount_dir.c_str(), strerror(errno)));
+ }
+ } else if (errno != ENOENT) {
+ fail_fn(CREATE_ERROR("Failed to access %s: %s", obb_mount_file.c_str(), strerror(errno)));
+ }
+ }
}
// Create a private mount namespace and bind mount appropriate emulated
@@ -789,126 +821,97 @@ static void MountEmulatedStorage(uid_t uid, jint mount_mode,
const std::vector<std::string>& packages_for_uid,
const std::vector<std::string>& visible_vol_ids, const std::string& sandbox_id,
fail_fn_t fail_fn) {
- // See storage config details at http://source.android.com/tech/storage/
+ // See storage config details at http://source.android.com/tech/storage/
+
+ String8 storage_source;
+ if (mount_mode == MOUNT_EXTERNAL_DEFAULT) {
+ storage_source = "/mnt/runtime/default";
+ } else if (mount_mode == MOUNT_EXTERNAL_READ) {
+ storage_source = "/mnt/runtime/read";
+ } else if (mount_mode == MOUNT_EXTERNAL_WRITE) {
+ storage_source = "/mnt/runtime/write";
+ } else if (mount_mode == MOUNT_EXTERNAL_NONE && !force_mount_namespace) {
+ // Sane default of no storage visible
+ return;
+ }
- String8 storageSource;
- if (mount_mode == MOUNT_EXTERNAL_DEFAULT) {
- storageSource = "/mnt/runtime/default";
- } else if (mount_mode == MOUNT_EXTERNAL_READ) {
- storageSource = "/mnt/runtime/read";
- } else if (mount_mode == MOUNT_EXTERNAL_WRITE) {
- storageSource = "/mnt/runtime/write";
- } else if (mount_mode == MOUNT_EXTERNAL_NONE && !force_mount_namespace) {
- // Sane default of no storage visible
- return;
- }
+ // Create a second private mount namespace for our process
+ if (unshare(CLONE_NEWNS) == -1) {
+ fail_fn(CREATE_ERROR("Failed to unshare(): %s", strerror(errno)));
+ }
- // Create a second private mount namespace for our process
- if (unshare(CLONE_NEWNS) == -1) {
- fail_fn(CREATE_ERROR("Failed to unshare(): %s", strerror(errno)));
- }
+ // Handle force_mount_namespace with MOUNT_EXTERNAL_NONE.
+ if (mount_mode == MOUNT_EXTERNAL_NONE) {
+ return;
+ }
- // Handle force_mount_namespace with MOUNT_EXTERNAL_NONE.
- if (mount_mode == MOUNT_EXTERNAL_NONE) {
- return;
- }
+ if (GetBoolProperty(kIsolatedStorageSnapshot, GetBoolProperty(kIsolatedStorage, true))) {
+ if (mount_mode == MOUNT_EXTERNAL_FULL || mount_mode == MOUNT_EXTERNAL_LEGACY) {
+ storage_source = (mount_mode == MOUNT_EXTERNAL_FULL)
+ ? "/mnt/runtime/full" : "/mnt/runtime/write";
+ if (TEMP_FAILURE_RETRY(mount(storage_source.string(), "/storage",
+ NULL, MS_BIND | MS_REC | MS_SLAVE, NULL)) == -1) {
+ fail_fn(CREATE_ERROR("Failed to mount %s to /storage: %s",
+ storage_source.string(),
+ strerror(errno)));
+ }
- if (GetBoolProperty(kIsolatedStorageSnapshot, GetBoolProperty(kIsolatedStorage, true))) {
- if (mount_mode == MOUNT_EXTERNAL_FULL || mount_mode == MOUNT_EXTERNAL_LEGACY) {
- storageSource = (mount_mode == MOUNT_EXTERNAL_FULL)
- ? "/mnt/runtime/full" : "/mnt/runtime/write";
- if (TEMP_FAILURE_RETRY(mount(storageSource.string(), "/storage",
- NULL, MS_BIND | MS_REC | MS_SLAVE, NULL)) == -1) {
- fail_fn(CREATE_ERROR("Failed to mount %s to /storage: %s",
- storageSource.string(),
- strerror(errno)));
- }
-
- // Mount user-specific symlink helper into place
- userid_t user_id = multiuser_get_user_id(uid);
- const String8 userSource(String8::format("/mnt/user/%d", user_id));
- if (fs_prepare_dir(userSource.string(), 0751, 0, 0) == -1) {
- fail_fn(CREATE_ERROR("fs_prepare_dir failed on %s (%s)",
- userSource.string(), strerror(errno)));
- }
-
- if (TEMP_FAILURE_RETRY(mount(userSource.string(), "/storage/self", nullptr, MS_BIND,
- nullptr)) == -1) {
- fail_fn(CREATE_ERROR("Failed to mount %s to /storage/self: %s",
- userSource.string(),
- strerror(errno)));
- }
- } else {
- if (package_name.empty() || sandbox_id.empty()) {
- return;
- }
-
- userid_t user_id = multiuser_get_user_id(uid);
- std::string pkgSandboxDir =
- StringPrintf("/mnt/user/%d/package/%s", user_id, package_name.c_str());
- bool sandboxAlreadyCreated = true;
- if (TEMP_FAILURE_RETRY(access(pkgSandboxDir.c_str(), F_OK)) == -1) {
- if (errno == ENOENT) {
- ALOGD("Sandbox not yet created for %s", pkgSandboxDir.c_str());
- sandboxAlreadyCreated = false;
- CreatePkgSandboxTarget(uid, package_name, fail_fn);
- } else {
- fail_fn(CREATE_ERROR("Failed to access %s: %s",
- pkgSandboxDir.c_str(), strerror(errno)));
- }
- }
-
- if (TEMP_FAILURE_RETRY(mount(pkgSandboxDir.c_str(), "/storage",
- nullptr, MS_BIND | MS_REC | MS_SLAVE, nullptr)) == -1) {
- fail_fn(CREATE_ERROR("Failed to mount %s to /storage: %s",
- pkgSandboxDir.c_str(), strerror(errno)));
- }
-
- if (TEMP_FAILURE_RETRY(access("/storage/obb_mount", F_OK)) == 0) {
- if (mount_mode != MOUNT_EXTERNAL_INSTALLER) {
- remove("/storage/obb_mount");
- }
- } else {
- if (mount_mode == MOUNT_EXTERNAL_INSTALLER) {
- int fd =
- TEMP_FAILURE_RETRY(open("/storage/obb_mount", O_RDWR | O_CREAT, 0660));
- if (fd == -1) {
- fail_fn(CREATE_ERROR("Couldn't create /storage/obb_mount: %s",
- strerror(errno)));
- }
- close(fd);
- }
- }
- // If the sandbox was already created by vold, only then set up the bind mounts for
- // pkg specific directories. Otherwise, leave as is and bind mounts will be taken
- // care of by vold later.
- if (sandboxAlreadyCreated) {
- PreparePkgSpecificDirs(packages_for_uid, visible_vol_ids,
- mount_mode == MOUNT_EXTERNAL_INSTALLER, sandbox_id, user_id, uid, fail_fn);
- }
- }
+ // Mount user-specific symlink helper into place
+ userid_t user_id = multiuser_get_user_id(uid);
+ const String8 user_source(String8::format("/mnt/user/%d", user_id));
+ if (fs_prepare_dir(user_source.string(), 0751, 0, 0) == -1) {
+ fail_fn(CREATE_ERROR("fs_prepare_dir failed on %s (%s)",
+ user_source.string(), strerror(errno)));
+ }
+
+ if (TEMP_FAILURE_RETRY(mount(user_source.string(), "/storage/self", nullptr, MS_BIND,
+ nullptr)) == -1) {
+ fail_fn(CREATE_ERROR("Failed to mount %s to /storage/self: %s",
+ user_source.string(),
+ strerror(errno)));
+ }
} else {
- if (TEMP_FAILURE_RETRY(mount(storageSource.string(), "/storage", nullptr,
- MS_BIND | MS_REC | MS_SLAVE, nullptr)) == -1) {
- fail_fn(CREATE_ERROR("Failed to mount %s to /storage: %s",
- storageSource.string(),
- strerror(errno)));
- }
+ if (package_name.empty() || sandbox_id.empty()) {
+ return;
+ }
- // Mount user-specific symlink helper into place
- userid_t user_id = multiuser_get_user_id(uid);
- const String8 userSource(String8::format("/mnt/user/%d", user_id));
- if (fs_prepare_dir(userSource.string(), 0751, 0, 0) == -1) {
- fail_fn(CREATE_ERROR("fs_prepare_dir failed on %s",
- userSource.string()));
- }
+ userid_t user_id = multiuser_get_user_id(uid);
+ CreatePkgSandboxTarget(user_id, fail_fn);
- if (TEMP_FAILURE_RETRY(mount(userSource.string(), "/storage/self",
- nullptr, MS_BIND, nullptr)) == -1) {
- fail_fn(CREATE_ERROR("Failed to mount %s to /storage/self: %s",
- userSource.string(), strerror(errno)));
- }
+ std::string pkgSandboxDir = StringPrintf("/mnt/user/%d/package", user_id);
+ if (TEMP_FAILURE_RETRY(mount(pkgSandboxDir.c_str(), "/storage",
+ nullptr, MS_BIND | MS_REC | MS_SLAVE, nullptr)) == -1) {
+ fail_fn(CREATE_ERROR("Failed to mount %s to /storage: %s",
+ pkgSandboxDir.c_str(), strerror(errno)));
+ }
+
+ HandleMountModeInstaller(mount_mode, user_id, sandbox_id, fail_fn);
+
+ PreparePkgSpecificDirs(packages_for_uid, visible_vol_ids,
+ mount_mode == MOUNT_EXTERNAL_INSTALLER, sandbox_id, user_id, uid, fail_fn);
+ }
+ } else {
+ if (TEMP_FAILURE_RETRY(mount(storage_source.string(), "/storage", nullptr,
+ MS_BIND | MS_REC | MS_SLAVE, nullptr)) == -1) {
+ fail_fn(CREATE_ERROR("Failed to mount %s to /storage: %s",
+ storage_source.string(),
+ strerror(errno)));
}
+
+ // Mount user-specific symlink helper into place
+ userid_t user_id = multiuser_get_user_id(uid);
+ const String8 userSource(String8::format("/mnt/user/%d", user_id));
+ if (fs_prepare_dir(userSource.string(), 0751, 0, 0) == -1) {
+ fail_fn(CREATE_ERROR("fs_prepare_dir failed on %s",
+ userSource.string()));
+ }
+
+ if (TEMP_FAILURE_RETRY(mount(userSource.string(), "/storage/self",
+ nullptr, MS_BIND, nullptr)) == -1) {
+ fail_fn(CREATE_ERROR("Failed to mount %s to /storage/self: %s",
+ userSource.string(), strerror(errno)));
+ }
+ }
}
static bool NeedsNoRandomizeWorkaround() {
diff --git a/core/jni/com_google_android_gles_jni_GLImpl.cpp b/core/jni/com_google_android_gles_jni_GLImpl.cpp
index 40ff7e4c5517..ee14a89b54ef 100644
--- a/core/jni/com_google_android_gles_jni_GLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_GLImpl.cpp
@@ -65,8 +65,6 @@ GL_API void GL_APIENTRY glWeightPointerOESBounds(GLint size, GLenum type,
GLsizei stride, const GLvoid *pointer, GLsizei count);
}
-static int initialized = 0;
-
static jclass nioAccessClass;
static jclass bufferClass;
static jclass G11ImplClass;
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index 5497b8665cf0..f74fc2129740 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -1622,6 +1622,10 @@ enum PageId {
// OPEN: Settings > Apps > Default Apps > Default sms
DEFAULT_SMS_PICKER = 789;
+ // OPEN: Settings > Apps > Notification > Notification Assistant
+ DEFAULT_NOTIFICATION_ASSISTANT = 790;
+
+
// OPEN: Settings > Apps > Default Apps > Warning dialog to confirm selection
DEFAULT_APP_PICKER_CONFIRMATION_DIALOG = 791;
diff --git a/core/proto/android/providers/settings/global.proto b/core/proto/android/providers/settings/global.proto
index cccb40d51722..c1cbd525b4d1 100644
--- a/core/proto/android/providers/settings/global.proto
+++ b/core/proto/android/providers/settings/global.proto
@@ -920,8 +920,7 @@ message GlobalSettingsProto {
// Temperature at which the high temperature warning notification should
// be shown.
optional SettingProto warning_temperature_level = 2 [ (android.privacy).dest = DEST_AUTOMATIC ];
- // USB temperature at which the high temperature alarm notification should be shown.
- optional SettingProto usb_alarm_temperature_level = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
+ optional SettingProto show_usb_temperature_alarm = 3 [ (android.privacy).dest = DEST_AUTOMATIC ];
}
optional TemperatureWarning temperature_warning = 119;
diff --git a/core/proto/android/stats/style/Android.bp b/core/proto/android/stats/style/Android.bp
new file mode 100644
index 000000000000..f085a52f8cdb
--- /dev/null
+++ b/core/proto/android/stats/style/Android.bp
@@ -0,0 +1,27 @@
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+java_library {
+ name: "styleprotosnano",
+ proto: {
+ type: "nano",
+ output_params: ["store_unknown_fields=true"],
+ include_dirs: ["external/protobuf/src"],
+ },
+
+ sdk_version: "current",
+ srcs: [
+ "*.proto",
+ ],
+}
diff --git a/core/proto/android/stats/style/style_enums.proto b/core/proto/android/stats/style/style_enums.proto
new file mode 100644
index 000000000000..b0e4391efd00
--- /dev/null
+++ b/core/proto/android/stats/style/style_enums.proto
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+package android.stats.style;
+option java_multiple_files = true;
+
+enum Action {
+ DEFAULT_ACTION = 0;
+ ONRESUME = 1;
+ ONSTOP = 2;
+ PICKER_SELECT = 3;
+ PICKER_APPLIED = 4;
+ WALLPAPER_OPEN_CATEGORY = 5;
+ WALLPAPER_SELECT = 6;
+ WALLPAPER_APPLIED = 7;
+ WALLPAPER_EXPLORE = 8;
+ WALLPAPER_DOWNLOAD = 9;
+ WALLPAPER_REMOVE = 10;
+}
+
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index fc896cf3c514..0149365b4fb5 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -3418,6 +3418,11 @@
<permission android:name="android.permission.GET_RUNTIME_PERMISSIONS"
android:protectionLevel="signature" />
+ <!-- @SystemApi Allows an application to change policy_fixed permissions.
+ @hide -->
+ <permission android:name="android.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY"
+ android:protectionLevel="signature|installer" />
+
<!-- @hide Allows an application to observe permission changes. -->
<permission android:name="android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS"
android:protectionLevel="signature|privileged" />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 6571cd264583..489ceb72ad60 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2673,11 +2673,6 @@
</string-array>
- <!-- Flag indicating that this device does not rotate and will always remain in its default
- orientation. Activities that desire to run in a non-compatible orientation will be run
- from an emulated display within the physical display. -->
- <bool name="config_forceDefaultOrientation">false</bool>
-
<!-- Default Gravity setting for the system Toast view. Equivalent to: Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM -->
<integer name="config_toastDefaultGravity">0x00000051</integer>
@@ -3368,6 +3363,10 @@
<!-- True if home app should be pinned via Pinner Service -->
<bool name="config_pinnerHomeApp">false</bool>
+ <!-- List of files pinned by the Pinner Service with the apex boot image b/119800099 -->
+ <string-array translatable="false" name="config_apexBootImagePinnerServiceFiles">
+ </string-array>
+
<!-- Number of days preloaded file cache should be preserved on a device before it can be
deleted -->
<integer name="config_keepPreloadsMinDays">7</integer>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index e1ce2f69ba70..5a3c536b0042 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2998,6 +2998,8 @@
<public name="config_showDefaultEmergency" />
<!-- @hide @SystemApi -->
<public name="config_showDefaultHome" />
+ <!-- @hide @TestApi -->
+ <public name="config_perDisplayFocusEnabled" />
</public-group>
<public-group type="dimen" first-id="0x01050007">
diff --git a/core/res/res/values/styles_car.xml b/core/res/res/values/styles_car.xml
index f6ff1b651788..2129734ef9ce 100644
--- a/core/res/res/values/styles_car.xml
+++ b/core/res/res/values/styles_car.xml
@@ -59,7 +59,7 @@
<style name="CarAction1">
<item name="textStyle">bold</item>
<item name="textSize">@dimen/car_action1_size</item>
- <item name="textColor">@color/car_highlight</item>
+ <item name="textColor">@color/control_default_material</item>
</style>
<style name="CarAction1.Dark">
diff --git a/core/res/res/values/styles_device_defaults.xml b/core/res/res/values/styles_device_defaults.xml
index 93068ea975bd..3c7b36d8030e 100644
--- a/core/res/res/values/styles_device_defaults.xml
+++ b/core/res/res/values/styles_device_defaults.xml
@@ -38,6 +38,8 @@ easier.
<style name="Widget.DeviceDefault.Button.Inset" parent="Widget.Material.Button.Inset"/>
<style name="Widget.DeviceDefault.Button.Toggle" parent="Widget.Material.Button.Toggle"/>
<style name="Widget.DeviceDefault.Button.Colored" parent="Widget.Material.Button.Colored">
+ <item name="outlineAmbientShadowColor">@color/btn_colored_background_material</item>
+ <item name="outlineSpotShadowColor">@color/btn_colored_background_material</item>
<item name="textAppearance">?attr/textAppearanceButton</item>
<item name="textColor">@color/btn_colored_text_material</item>
</style>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 4ae239e191e3..1f73dda18c7b 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -347,7 +347,6 @@
<java-symbol type="bool" name="config_requireRadioPowerOffOnSimRefreshReset" />
<java-symbol type="bool" name="config_speed_up_audio_on_mt_calls" />
<java-symbol type="bool" name="config_useFixedVolume" />
- <java-symbol type="bool" name="config_forceDefaultOrientation" />
<java-symbol type="bool" name="config_wifi_batched_scan_supported" />
<java-symbol type="bool" name="config_wifi_softap_acs_supported" />
<java-symbol type="string" name="config_wifi_softap_acs_supported_channel_list" />
@@ -3048,6 +3047,7 @@
<java-symbol type="array" name="config_defaultPinnerServiceFiles" />
<java-symbol type="bool" name="config_pinnerCameraApp" />
<java-symbol type="bool" name="config_pinnerHomeApp" />
+ <java-symbol type="array" name="config_apexBootImagePinnerServiceFiles" />
<java-symbol type="string" name="config_doubleTouchGestureEnableFile" />
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
index 9fabe44f2a8a..d73c174212bd 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionParcelTests.java
@@ -28,6 +28,7 @@ import android.app.IApplicationThread;
import android.app.IInstrumentationWatcher;
import android.app.IUiAutomationConnection;
import android.app.ProfilerInfo;
+import android.content.AutofillOptions;
import android.content.ComponentName;
import android.content.ContentCaptureOptions;
import android.content.IIntentReceiver;
@@ -407,7 +408,7 @@ public class TransactionParcelTests {
IUiAutomationConnection iUiAutomationConnection, int i, boolean b, boolean b1,
boolean b2, boolean b3, Configuration configuration,
CompatibilityInfo compatibilityInfo, Map map, Bundle bundle1, String s1,
- boolean autofillCompatEnabled, ContentCaptureOptions o) throws RemoteException {
+ AutofillOptions ao, ContentCaptureOptions co) throws RemoteException {
}
@Override
diff --git a/core/tests/coretests/src/android/app/timezone/RulesStateTest.java b/core/tests/coretests/src/android/app/timezone/RulesStateTest.java
index bb535b6fac7d..30cc7ffc5366 100644
--- a/core/tests/coretests/src/android/app/timezone/RulesStateTest.java
+++ b/core/tests/coretests/src/android/app/timezone/RulesStateTest.java
@@ -46,11 +46,11 @@ public class RulesStateTest {
RulesState.DISTRO_STATUS_INSTALLED, rulesVersion("2016b", 2));
assertEqualsContract(one, two);
- RulesState differentSystemRules = new RulesState(
+ RulesState differentBaseRules = new RulesState(
"2016b", formatVersion(1, 2), false /* operationInProgress */,
RulesState.STAGED_OPERATION_INSTALL, rulesVersion("2016a", 3),
RulesState.DISTRO_STATUS_INSTALLED, rulesVersion("2016b", 2));
- assertFalse(one.equals(differentSystemRules));
+ assertFalse(one.equals(differentBaseRules));
RulesState differentFormatVersion = new RulesState(
"2016a", formatVersion(1, 1), false /* operationInProgress */,
@@ -121,14 +121,14 @@ public class RulesStateTest {
}
@Test
- public void isSystemVersionNewerThan() {
+ public void isBaseVersionNewerThan() {
RulesState rulesState = new RulesState(
"2016b", formatVersion(1, 1), false /* operationInProgress */,
RulesState.STAGED_OPERATION_NONE, null /* stagedDistroRulesVersion */,
RulesState.DISTRO_STATUS_INSTALLED, rulesVersion("2016b", 3));
- assertTrue(rulesState.isSystemVersionNewerThan(rulesVersion("2016a", 1)));
- assertFalse(rulesState.isSystemVersionNewerThan(rulesVersion("2016b", 1)));
- assertFalse(rulesState.isSystemVersionNewerThan(rulesVersion("2016c", 1)));
+ assertTrue(rulesState.isBaseVersionNewerThan(rulesVersion("2016a", 1)));
+ assertFalse(rulesState.isBaseVersionNewerThan(rulesVersion("2016b", 1)));
+ assertFalse(rulesState.isBaseVersionNewerThan(rulesVersion("2016c", 1)));
}
private static void assertEqualsContract(RulesState one, RulesState two) {
diff --git a/core/tests/coretests/src/android/content/pm/AndroidTestBaseUpdaterTest.java b/core/tests/coretests/src/android/content/pm/AndroidTestBaseUpdaterTest.java
index 0ed76dcf7c5d..125b9ff61f7f 100644
--- a/core/tests/coretests/src/android/content/pm/AndroidTestBaseUpdaterTest.java
+++ b/core/tests/coretests/src/android/content/pm/AndroidTestBaseUpdaterTest.java
@@ -37,37 +37,37 @@ public class AndroidTestBaseUpdaterTest extends PackageSharedLibraryUpdaterTest
private static final String OTHER_LIBRARY = "other.library";
@Test
- public void targeted_at_O() {
+ public void targeted_at_P() {
PackageBuilder before = builder()
- .targetSdkVersion(Build.VERSION_CODES.O);
+ .targetSdkVersion(Build.VERSION_CODES.P);
// Should add org.apache.http.legacy.
PackageBuilder after = builder()
- .targetSdkVersion(Build.VERSION_CODES.O)
+ .targetSdkVersion(Build.VERSION_CODES.P)
.requiredLibraries(ANDROID_TEST_BASE);
checkBackwardsCompatibility(before, after);
}
@Test
- public void targeted_at_O_not_empty_usesLibraries() {
+ public void targeted_at_P_not_empty_usesLibraries() {
PackageBuilder before = builder()
- .targetSdkVersion(Build.VERSION_CODES.O)
+ .targetSdkVersion(Build.VERSION_CODES.P)
.requiredLibraries(OTHER_LIBRARY);
// The org.apache.http.legacy jar should be added at the start of the list because it
// is not on the bootclasspath and the package targets pre-P.
PackageBuilder after = builder()
- .targetSdkVersion(Build.VERSION_CODES.O)
+ .targetSdkVersion(Build.VERSION_CODES.P)
.requiredLibraries(ANDROID_TEST_BASE, OTHER_LIBRARY);
checkBackwardsCompatibility(before, after);
}
@Test
- public void targeted_at_O_in_usesLibraries() {
+ public void targeted_at_P_in_usesLibraries() {
PackageBuilder before = builder()
- .targetSdkVersion(Build.VERSION_CODES.O)
+ .targetSdkVersion(Build.VERSION_CODES.P)
.requiredLibraries(ANDROID_TEST_BASE);
// No change is required because although org.apache.http.legacy has been removed from
@@ -76,9 +76,9 @@ public class AndroidTestBaseUpdaterTest extends PackageSharedLibraryUpdaterTest
}
@Test
- public void targeted_at_O_in_usesOptionalLibraries() {
+ public void targeted_at_P_in_usesOptionalLibraries() {
PackageBuilder before = builder()
- .targetSdkVersion(Build.VERSION_CODES.O)
+ .targetSdkVersion(Build.VERSION_CODES.P)
.optionalLibraries(ANDROID_TEST_BASE);
// No change is required because although org.apache.http.legacy has been removed from
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index 46cac7a49f13..23cd96382d1a 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -319,6 +319,7 @@ public class SettingsBackupTest {
Settings.Global.LOW_POWER_MODE_STICKY,
Settings.Global.LOW_POWER_MODE_SUGGESTION_PARAMS,
Settings.Global.LTE_SERVICE_FORCED,
+ Settings.Global.LID_BEHAVIOR,
Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE,
Settings.Global.MAX_SOUND_TRIGGER_DETECTION_SERVICE_OPS_PER_DAY,
Settings.Global.MDC_INITIAL_MAX_RETRY,
@@ -429,6 +430,7 @@ public class SettingsBackupTest {
Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS,
Settings.Global.SHOW_RESTART_IN_CRASH_DIALOG,
Settings.Global.SHOW_TEMPERATURE_WARNING,
+ Settings.Global.SHOW_USB_TEMPERATURE_ALARM,
Settings.Global.SIGNED_CONFIG_VERSION,
Settings.Global.SMART_SELECTION_UPDATE_CONTENT_URL,
Settings.Global.SMART_SELECTION_UPDATE_METADATA_URL,
@@ -504,7 +506,6 @@ public class SettingsBackupTest {
Settings.Global.USER_SWITCHER_ENABLED,
Settings.Global.NETWORK_ACCESS_TIMEOUT_MS,
Settings.Global.WARNING_TEMPERATURE,
- Settings.Global.USB_ALARM_TEMPERATURE,
Settings.Global.WEBVIEW_DATA_REDUCTION_PROXY_KEY,
Settings.Global.WEBVIEW_FALLBACK_LOGIC_ENABLED,
Settings.Global.WEBVIEW_MULTIPROCESS,
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
index a88968bfd089..e3852e1b627e 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityCacheTest.java
@@ -301,26 +301,6 @@ public class AccessibilityCacheTest {
}
@Test
- public void subTreeChangeEventFromUncachedNode_clearsNodeInCache() {
- AccessibilityNodeInfo nodeInfo = getNodeWithA11yAndWindowId(CHILD_VIEW_ID, WINDOW_ID_1);
- long id = nodeInfo.getSourceNodeId();
- mAccessibilityCache.add(nodeInfo);
- nodeInfo.recycle();
-
- AccessibilityEvent event = AccessibilityEvent
- .obtain(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
- event.setContentChangeTypes(AccessibilityEvent.CONTENT_CHANGE_TYPE_SUBTREE);
- event.setSource(getMockViewWithA11yAndWindowIds(PARENT_VIEW_ID, WINDOW_ID_1));
-
- mAccessibilityCache.onAccessibilityEvent(event);
- AccessibilityNodeInfo shouldBeNull = mAccessibilityCache.getNode(WINDOW_ID_1, id);
- if (shouldBeNull != null) {
- shouldBeNull.recycle();
- }
- assertNull(shouldBeNull);
- }
-
- @Test
public void scrollEvent_clearsNodeAndChild() {
AccessibilityEvent event = AccessibilityEvent
.obtain(AccessibilityEvent.TYPE_VIEW_SCROLLED);
diff --git a/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java b/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java
index 99c959ef57e4..d54402975f65 100644
--- a/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java
+++ b/core/tests/coretests/src/android/view/textclassifier/TextClassificationTest.java
@@ -93,8 +93,8 @@ public class TextClassificationTest {
final String id = "id";
final TextClassification reference = new TextClassification.Builder()
.setText(text)
- .addAction(remoteAction0)
- .addAction(remoteAction1)
+ .addAction(remoteAction0) // Action intent not included.
+ .addAction(remoteAction1) // Action intent not included.
.setEntityType(TextClassifier.TYPE_ADDRESS, 0.3f)
.setEntityType(TextClassifier.TYPE_PHONE, 0.7f)
.setId(id)
@@ -132,6 +132,7 @@ public class TextClassificationTest {
// Extras
assertEquals(BUNDLE_VALUE, result.getExtras().getString(BUNDLE_KEY));
+ assertNull(ExtrasUtils.getActionsIntents(result));
}
@Test
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index f27f3f9ca427..9fbc1666aed1 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -57,7 +57,7 @@ import androidx.test.rule.ActivityTestRule;
import com.android.internal.R;
import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.nano.MetricsProto;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import org.junit.Before;
import org.junit.Rule;
@@ -524,15 +524,45 @@ public class ChooserActivityTest {
waitForIdle();
verify(mockLogger, atLeastOnce()).write(logMakerCaptor.capture());
assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
- is(MetricsProto.MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
+ is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
assertThat(logMakerCaptor
.getAllValues().get(0)
- .getTaggedData(MetricsProto.MetricsEvent.FIELD_TIME_TO_APP_TARGETS),
+ .getTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS),
is(notNullValue()));
assertThat(logMakerCaptor
.getAllValues().get(0)
- .getTaggedData(MetricsProto.MetricsEvent.FIELD_SHARESHEET_MIMETYPE),
+ .getTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE),
is("TestType"));
+ assertThat(logMakerCaptor
+ .getAllValues().get(0)
+ .getSubtype(),
+ is(MetricsEvent.PARENT_PROFILE));
+ }
+
+ @Test
+ public void testOnCreateLoggingFromWorkProfile() {
+ Intent sendIntent = createSendTextIntent();
+ sendIntent.setType("TestType");
+ sOverrides.alternateProfileSetting = MetricsEvent.MANAGED_PROFILE;
+ MetricsLogger mockLogger = sOverrides.metricsLogger;
+ ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
+ mActivityRule.launchActivity(Intent.createChooser(sendIntent, "logger test"));
+ waitForIdle();
+ verify(mockLogger, atLeastOnce()).write(logMakerCaptor.capture());
+ assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
+ is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
+ assertThat(logMakerCaptor
+ .getAllValues().get(0)
+ .getTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS),
+ is(notNullValue()));
+ assertThat(logMakerCaptor
+ .getAllValues().get(0)
+ .getTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE),
+ is("TestType"));
+ assertThat(logMakerCaptor
+ .getAllValues().get(0)
+ .getSubtype(),
+ is(MetricsEvent.MANAGED_PROFILE));
}
@Test
@@ -547,7 +577,7 @@ public class ChooserActivityTest {
verify(mockLogger, Mockito.times(1)).write(logMakerCaptor.capture());
// First invocation is from onCreate
assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
- is(MetricsProto.MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
+ is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
}
@Test
@@ -569,7 +599,7 @@ public class ChooserActivityTest {
verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
// First invocation is from onCreate
assertThat(logMakerCaptor.getAllValues().get(1).getCategory(),
- is(MetricsProto.MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
+ is(MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
assertThat(logMakerCaptor.getAllValues().get(1).getSubtype(),
is(CONTENT_PREVIEW_TEXT));
}
@@ -599,11 +629,11 @@ public class ChooserActivityTest {
verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
// First invocation is from onCreate
assertThat(logMakerCaptor.getAllValues().get(1).getCategory(),
- is(MetricsProto.MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
+ is(MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
assertThat(logMakerCaptor.getAllValues().get(1).getSubtype(),
is(CONTENT_PREVIEW_IMAGE));
assertThat(logMakerCaptor.getAllValues().get(2).getCategory(),
- is(MetricsProto.MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
+ is(MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
assertThat(logMakerCaptor.getAllValues().get(2).getSubtype(),
is(CONTENT_PREVIEW_IMAGE));
}
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
index 57c84ff5c8ac..a8dd69a2666d 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
@@ -28,6 +28,7 @@ import android.net.Uri;
import android.util.Size;
import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import java.util.function.Function;
@@ -112,6 +113,14 @@ public class ChooserWrapperActivity extends ChooserActivity {
return super.queryResolver(resolver, uri);
}
+ @Override
+ protected boolean isWorkProfile() {
+ if (sOverrides.alternateProfileSetting != 0) {
+ return sOverrides.alternateProfileSetting == MetricsEvent.MANAGED_PROFILE;
+ }
+ return super.isWorkProfile();
+ }
+
/**
* We cannot directly mock the activity created since instrumentation creates it.
* <p>
@@ -128,6 +137,7 @@ public class ChooserWrapperActivity extends ChooserActivity {
public boolean resolverForceException;
public Bitmap previewThumbnail;
public MetricsLogger metricsLogger;
+ public int alternateProfileSetting;
public void reset() {
onSafelyStartCallback = null;
@@ -139,6 +149,7 @@ public class ChooserWrapperActivity extends ChooserActivity {
resolverForceException = false;
resolverListController = mock(ResolverListController.class);
metricsLogger = mock(MetricsLogger.class);
+ alternateProfileSetting = 0;
}
}
}
diff --git a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
index 9b13af2a4357..abfb4fb3cedc 100644
--- a/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/IntentForwarderActivityTest.java
@@ -25,6 +25,7 @@ import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -40,6 +41,7 @@ import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
+import android.metrics.LogMaker;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
@@ -51,6 +53,9 @@ import androidx.test.InstrumentationRegistry;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -70,6 +75,11 @@ public class IntentForwarderActivityTest {
"android",
IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE
);
+ private static final ComponentName FORWARD_TO_PARENT_COMPONENT_NAME =
+ new ComponentName(
+ "android",
+ IntentForwarderActivity.FORWARD_INTENT_TO_PARENT
+ );
private static final String TYPE_PLAIN_TEXT = "text/plain";
private static UserInfo MANAGED_PROFILE_INFO = new UserInfo();
@@ -522,6 +532,60 @@ public class IntentForwarderActivityTest {
verify(sInjector).showToast(anyInt(), anyInt());
}
+ @Test
+ public void forwardToManagedProfile_LoggingTest() throws Exception {
+ sComponentName = FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME;
+
+ // Intent can be forwarded.
+ when(mIPm.canForwardTo(
+ any(Intent.class), nullable(String.class), anyInt(), anyInt())).thenReturn(true);
+
+ // Managed profile exists.
+ List<UserInfo> profiles = new ArrayList<>();
+ profiles.add(CURRENT_USER_INFO);
+ profiles.add(MANAGED_PROFILE_INFO);
+ when(mUserManager.getProfiles(anyInt())).thenReturn(profiles);
+
+ Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class);
+ intent.setAction(Intent.ACTION_SEND);
+ intent.setType(TYPE_PLAIN_TEXT);
+ IntentForwarderWrapperActivity activity = mActivityRule.launchActivity(intent);
+
+ ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
+ verify(activity.getMetricsLogger()).write(logMakerCaptor.capture());
+ assertEquals(MetricsEvent.ACTION_SWITCH_SHARE_PROFILE,
+ logMakerCaptor.getValue().getCategory());
+ assertEquals(MetricsEvent.MANAGED_PROFILE,
+ logMakerCaptor.getValue().getSubtype());
+ }
+
+ @Test
+ public void forwardToParent_LoggingTest() throws Exception {
+ sComponentName = FORWARD_TO_PARENT_COMPONENT_NAME;
+
+ // Intent can be forwarded.
+ when(mIPm.canForwardTo(
+ any(Intent.class), nullable(String.class), anyInt(), anyInt())).thenReturn(true);
+
+ // Managed profile exists.
+ List<UserInfo> profiles = new ArrayList<>();
+ profiles.add(CURRENT_USER_INFO);
+ profiles.add(MANAGED_PROFILE_INFO);
+ when(mUserManager.getProfiles(anyInt())).thenReturn(profiles);
+
+ Intent intent = new Intent(mContext, IntentForwarderWrapperActivity.class);
+ intent.setAction(Intent.ACTION_SEND);
+ intent.setType(TYPE_PLAIN_TEXT);
+ IntentForwarderWrapperActivity activity = mActivityRule.launchActivity(intent);
+
+ ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
+ verify(activity.getMetricsLogger()).write(logMakerCaptor.capture());
+ assertEquals(MetricsEvent.ACTION_SWITCH_SHARE_PROFILE,
+ logMakerCaptor.getValue().getCategory());
+ assertEquals(MetricsEvent.PARENT_PROFILE,
+ logMakerCaptor.getValue().getSubtype());
+ }
+
private void setupShouldSkipDisclosureTest() throws RemoteException {
sComponentName = FORWARD_TO_MANAGED_PROFILE_COMPONENT_NAME;
sActivityName = "MyTestActivity";
@@ -541,6 +605,7 @@ public class IntentForwarderActivityTest {
private Intent mStartActivityIntent;
private int mUserIdActivityLaunchedIn;
+ private MetricsLogger mMetricsLogger = mock(MetricsLogger.class);
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -559,6 +624,11 @@ public class IntentForwarderActivityTest {
mStartActivityIntent = intent;
mUserIdActivityLaunchedIn = userId;
}
+
+ @Override
+ protected MetricsLogger getMetricsLogger() {
+ return mMetricsLogger;
+ }
}
public class TestInjector implements IntentForwarderActivity.Injector {
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 8d3bac8622f6..60ce595b82b8 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -1270,7 +1270,7 @@ public final class Bitmap implements Parcelable {
node.setLeftTopRightBottom(0, 0, width, height);
node.setClipToBounds(false);
node.setForceDarkAllowed(false);
- final RecordingCanvas canvas = node.startRecording(width, height);
+ final RecordingCanvas canvas = node.beginRecording(width, height);
if (source.getWidth() != width || source.getHeight() != height) {
canvas.scale(width / (float) source.getWidth(),
height / (float) source.getHeight());
diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java
index b020556cd15f..e6233548651e 100644
--- a/graphics/java/android/graphics/HardwareRenderer.java
+++ b/graphics/java/android/graphics/HardwareRenderer.java
@@ -258,7 +258,7 @@ public class HardwareRenderer {
* and the renderer will draw nothing.
*/
public void setContentRoot(@Nullable RenderNode content) {
- RecordingCanvas canvas = mRootNode.startRecording();
+ RecordingCanvas canvas = mRootNode.beginRecording();
if (content != null) {
canvas.drawRenderNode(content);
}
diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java
index 62647741dcfa..15d855e9560c 100644
--- a/graphics/java/android/graphics/ImageFormat.java
+++ b/graphics/java/android/graphics/ImageFormat.java
@@ -16,7 +16,43 @@
package android.graphics;
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
public class ImageFormat {
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(value = {
+ UNKNOWN,
+ RGB_565,
+ YV12,
+ Y8,
+ Y16,
+ NV16,
+ NV21,
+ YUY2,
+ JPEG,
+ DEPTH_JPEG,
+ YUV_420_888,
+ YUV_422_888,
+ YUV_444_888,
+ FLEX_RGB_888,
+ FLEX_RGBA_8888,
+ RAW_SENSOR,
+ RAW_PRIVATE,
+ RAW10,
+ RAW12,
+ DEPTH16,
+ DEPTH_POINT_CLOUD,
+ RAW_DEPTH,
+ PRIVATE,
+ HEIC
+ })
+ public @interface Format {
+ }
+
/*
* these constants are chosen to be binary compatible with their previous
* location in PixelFormat.java
@@ -731,7 +767,7 @@ public class ImageFormat {
* @return the number of bits per pixel of the given format or -1 if the
* format doesn't exist or is not supported.
*/
- public static int getBitsPerPixel(int format) {
+ public static int getBitsPerPixel(@Format int format) {
switch (format) {
case RGB_565:
return 16;
@@ -781,7 +817,7 @@ public class ImageFormat {
*
* @hide
*/
- public static boolean isPublicFormat(int format) {
+ public static boolean isPublicFormat(@Format int format) {
switch (format) {
case RGB_565:
case NV16:
diff --git a/graphics/java/android/graphics/RecordingCanvas.java b/graphics/java/android/graphics/RecordingCanvas.java
index 515532ffda52..30466e1f6b1f 100644
--- a/graphics/java/android/graphics/RecordingCanvas.java
+++ b/graphics/java/android/graphics/RecordingCanvas.java
@@ -31,7 +31,7 @@ import dalvik.annotation.optimization.FastNative;
* Bitmap objects that it draws, preventing the backing memory of Bitmaps from being released while
* the RecordingCanvas is still holding a native reference to the memory.
*
- * This is obtained by calling {@link RenderNode#startRecording()} and is valid until the matching
+ * This is obtained by calling {@link RenderNode#beginRecording()} and is valid until the matching
* {@link RenderNode#endRecording()} is called. It must not be retained beyond that as it is
* internally reused.
*/
diff --git a/graphics/java/android/graphics/RenderNode.java b/graphics/java/android/graphics/RenderNode.java
index 09b18b771250..e98879d0c5bd 100644
--- a/graphics/java/android/graphics/RenderNode.java
+++ b/graphics/java/android/graphics/RenderNode.java
@@ -16,6 +16,9 @@
package android.graphics;
+import android.annotation.BytesLong;
+import android.annotation.ColorInt;
+import android.annotation.FloatRange;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -59,7 +62,7 @@ import java.lang.annotation.RetentionPolicy;
* <pre class="prettyprint">
* RenderNode renderNode = RenderNode.create("myRenderNode");
* renderNode.setLeftTopRightBottom(0, 0, 50, 50); // Set the size to 50x50
- * RecordingCanvas canvas = renderNode.startRecording();
+ * RecordingCanvas canvas = renderNode.beginRecording();
* try {
* // Draw with the canvas
* canvas.drawRect(...);
@@ -71,14 +74,13 @@ import java.lang.annotation.RetentionPolicy;
* <h3>Drawing a RenderNode in a View</h3>
* <pre class="prettyprint">
* protected void onDraw(Canvas canvas) {
- * if (canvas instanceof RecordingCanvas) {
- * RecordingCanvas recordingCanvas = (RecordingCanvas) canvas;
+ * if (canvas.isHardwareAccelerated()) {
* // Check that the RenderNode has a display list, re-recording it if it does not.
* if (!myRenderNode.hasDisplayList()) {
* updateDisplayList(myRenderNode);
* }
* // Draw the RenderNode into this canvas.
- * recordingCanvas.drawRenderNode(myRenderNode);
+ * canvas.drawRenderNode(myRenderNode);
* }
* }
* </pre>
@@ -95,7 +97,7 @@ import java.lang.annotation.RetentionPolicy;
*
* <h3>Properties</h3>
* <p>In addition, a RenderNode offers several properties, such as
- * {@link #setScaleX(float)} or {@link #setLeft(int)}, that can be used to affect all
+ * {@link #setScaleX(float)} or {@link #setTranslationX(float)}, that can be used to affect all
* the drawing commands recorded within. For instance, these properties can be used
* to move around a large number of images without re-issuing all the individual
* <code>canvas.drawBitmap()</code> calls.</p>
@@ -104,7 +106,7 @@ import java.lang.annotation.RetentionPolicy;
* private void createDisplayList() {
* mRenderNode = RenderNode.create("MyRenderNode");
* mRenderNode.setLeftTopRightBottom(0, 0, width, height);
- * RecordingCanvas canvas = mRenderNode.startRecording();
+ * RecordingCanvas canvas = mRenderNode.beginRecording();
* try {
* for (Bitmap b : mBitmaps) {
* canvas.drawBitmap(b, 0.0f, 0.0f, null);
@@ -116,9 +118,8 @@ import java.lang.annotation.RetentionPolicy;
* }
*
* protected void onDraw(Canvas canvas) {
- * if (canvas instanceof RecordingCanvas) {
- * RecordingCanvas recordingCanvas = (RecordingCanvas) canvas;
- * recordingCanvas.drawRenderNode(mRenderNode);
+ * if (canvas.isHardwareAccelerated())
+ * canvas.drawRenderNode(mRenderNode);
* }
* }
*
@@ -263,19 +264,20 @@ public final class RenderNode {
* stored in this display list.
*
* {@link #endRecording()} must be called when the recording is finished in order to apply
- * the updated display list.
+ * the updated display list. Failing to call {@link #endRecording()} will result in an
+ * {@link IllegalStateException} if {@link #beginRecording(int, int)} is called again.
*
* @param width The width of the recording viewport. This will not alter the width of the
- * RenderNode itself, that must be set with {@link #setLeft(int)} and
- * {@link #setRight(int)}
+ * RenderNode itself, that must be set with {@link #setPosition(Rect)}.
* @param height The height of the recording viewport. This will not alter the height of the
- * RenderNode itself, that must be set with {@link #setTop(int)} and
- * {@link #setBottom(int)}.
+ * RenderNode itself, that must be set with {@link #setPosition(Rect)}.
* @return A canvas to record drawing operations.
+ * @throws IllegalStateException If a recording is already in progress. That is, the previous
+ * call to {@link #beginRecording(int, int)} did not call {@link #endRecording()}.
* @see #endRecording()
* @see #hasDisplayList()
*/
- public RecordingCanvas startRecording(int width, int height) {
+ public RecordingCanvas beginRecording(int width, int height) {
if (mCurrentRecordingCanvas != null) {
throw new IllegalStateException(
"Recording currently in progress - missing #endRecording() call?");
@@ -285,21 +287,18 @@ public final class RenderNode {
}
/**
- * Same as {@link #startRecording(int, int)} with the width & height set
+ * Same as {@link #beginRecording(int, int)} with the width & height set
* to the RenderNode's own width & height. The RenderNode's width & height may be set
- * with {@link #setLeftTopRightBottom(int, int, int, int)}.
- */
- public RecordingCanvas startRecording() {
- return startRecording(nGetWidth(mNativeRenderNode), nGetHeight(mNativeRenderNode));
- }
-
- /**
- * @hide
- * @deprecated use {@link #startRecording(int, int)} instead
+ * with {@link #setPosition(int, int, int, int)}.
+ *
+ * @return A canvas to record drawing operations.
+ * @throws IllegalStateException If a recording is already in progress. That is, the previous
+ * call to {@link #beginRecording(int, int)} did not call {@link #endRecording()}.
+ * @see #endRecording()
+ * @see #hasDisplayList()
*/
- @Deprecated
- public RecordingCanvas start(int width, int height) {
- return startRecording(width, height);
+ public RecordingCanvas beginRecording() {
+ return beginRecording(nGetWidth(mNativeRenderNode), nGetHeight(mNativeRenderNode));
}
/**
@@ -307,13 +306,13 @@ public final class RenderNode {
* Ends the recording for this display list. Calling this method marks
* the display list valid and {@link #hasDisplayList()} will return true.
*
- * @see #startRecording(int, int)
+ * @see #beginRecording(int, int)
* @see #hasDisplayList()
*/
public void endRecording() {
if (mCurrentRecordingCanvas == null) {
throw new IllegalStateException(
- "No recording in progress, forgot to call #startRecording()?");
+ "No recording in progress, forgot to call #beginRecording()?");
}
RecordingCanvas canvas = mCurrentRecordingCanvas;
mCurrentRecordingCanvas = null;
@@ -324,13 +323,21 @@ public final class RenderNode {
/**
* @hide
+ * @deprecated use {@link #beginRecording(int, int)} instead
+ */
+ @Deprecated
+ public RecordingCanvas start(int width, int height) {
+ return beginRecording(width, height);
+ }
+
+ /**
+ * @hide
* @deprecated use {@link #endRecording()} instead
*/
@Deprecated
public void end(RecordingCanvas canvas) {
- if (mCurrentRecordingCanvas != canvas) {
- throw new IllegalArgumentException(
- "Canvas given isn't the one that was returned from #startRecording");
+ if (canvas != mCurrentRecordingCanvas) {
+ throw new IllegalArgumentException("Wrong canvas");
}
endRecording();
}
@@ -346,7 +353,7 @@ public final class RenderNode {
/**
* Returns whether the RenderNode has a display list. If this returns false, the RenderNode
- * should be re-recorded with {@link #startRecording()} and {@link #endRecording()}.
+ * should be re-recorded with {@link #beginRecording()} and {@link #endRecording()}.
*
* A RenderNode without a display list may still be drawn, however it will have no impact
* on the rendering content until its display list is updated.
@@ -425,18 +432,21 @@ public final class RenderNode {
* for performance or required for the current combination of {@link #setAlpha(float)} and
* {@link #setHasOverlappingRendering(boolean)}.
*
- * The usage of this is instead to allow for either overriding of the internal behavior
+ * <p>The usage of this is instead to allow for either overriding of the internal behavior
* if it's measured to be necessary for the particular rendering content in question or, more
* usefully, to add a composition effect to the RenderNode via the optional paint parameter.
*
- * Note: When a RenderNode is using a compositing layer it will also result in
+ * <p>Note: When a RenderNode is using a compositing layer it will also result in
* clipToBounds=true behavior.
*
* @param forceToLayer if true this forces the RenderNode to use an intermediate buffer.
* Default & generally recommended value is false.
* @param paint The blend mode, alpha, and ColorFilter to apply to the compositing layer.
- * Only applies if forceToLayer is true.
- * @return true if anything changed, false otherwise
+ * Only applies if forceToLayer is true. The paint's alpha is multiplied
+ * with {@link #getAlpha()} to resolve the final alpha of the RenderNode.
+ * If null then no additional composition effects are applied on top of the
+ * composition layer.
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setUseCompositingLayer(boolean forceToLayer, @Nullable Paint paint) {
boolean didChange = nSetLayerType(mNativeRenderNode, forceToLayer ? 2 : 0);
@@ -457,15 +467,22 @@ public final class RenderNode {
}
/**
- * Sets the clip bounds of the RenderNode. If null, the clip bounds is removed from the
- * RenderNode. If non-null, the RenderNode will be clipped to this rect. If
+ * Sets an additional clip on the RenderNode. If null, the extra clip is removed from the
+ * RenderNode. If non-null, the RenderNode will be clipped to this rect. In addition if
* {@link #setClipToBounds(boolean)} is true, then the RenderNode will be clipped to the
- * intersection of this rectangle and the bounds of the render node.
+ * intersection of this rectangle and the bounds of the render node, which is set with
+ * {@link #setPosition(Rect)}.
+ *
+ * <p>This is equivalent to do a {@link Canvas#clipRect(Rect)} at the start of this
+ * RenderNode's display list. However, as this is a property of the RenderNode instead
+ * of part of the display list it can be more easily animated for transient additional
+ * clipping. An example usage of this would be the {@link android.transition.ChangeBounds}
+ * transition animation with the resizeClip=true option.
*
- * @param rect the bounds to clip to. If null, the clip bounds are reset
- * @return True if the clip bounds changed, false otherwise
+ * @param rect the bounds to clip to. If null, the additional clip is removed.
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
- public boolean setClipBounds(@Nullable Rect rect) {
+ public boolean setClipRect(@Nullable Rect rect) {
if (rect == null) {
return nSetClipBoundsEmpty(mNativeRenderNode);
} else {
@@ -477,11 +494,12 @@ public final class RenderNode {
* Set whether the Render node should clip itself to its bounds. This defaults to true,
* and is useful to the renderer in enable quick-rejection of chunks of the tree as well as
* better partial invalidation support. Clipping can be further restricted or controlled
- * through the combination of this property as well as {@link #setClipBounds(Rect)}, which
+ * through the combination of this property as well as {@link #setClipRect(Rect)}, which
* allows for a different clipping rectangle to be used in addition to or instead of the
- * {@link #setLeftTopRightBottom(int, int, int, int)} or the RenderNode.
+ * {@link #setPosition(int, int, int, int)} or the RenderNode.
*
* @param clipToBounds true if the display list should clip to its bounds, false otherwise.
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setClipToBounds(boolean clipToBounds) {
return nSetClipToBounds(mNativeRenderNode, clipToBounds);
@@ -489,7 +507,7 @@ public final class RenderNode {
/**
* Returns whether or not the RenderNode is clipping to its bounds. See
- * {@link #setClipToBounds(boolean)} and {@link #setLeftTopRightBottom(int, int, int, int)}
+ * {@link #setClipToBounds(boolean)} and {@link #setPosition(int, int, int, int)}
*
* @return true if the render node clips to its bounds, false otherwise.
*/
@@ -498,20 +516,58 @@ public final class RenderNode {
}
/**
- * Sets whether the RenderNode should be drawn immediately after the
+ * <p>Sets whether the RenderNode should be drawn immediately after the
* closest ancestor RenderNode containing a projection receiver.
*
+ * <p>The default is false, and the rendering of this node happens in the typical draw order.
+ *
+ * <p>If true, then at rendering time this rendernode will not be drawn in order with the
+ * {@link Canvas#drawRenderNode(RenderNode)} command that drew this RenderNode, but instead
+ * it will be re-positioned in the RenderNode tree to be drawn on the closet ancestor with a
+ * child rendernode that has {@link #setProjectionReceiver(boolean)} as true.
+ *
+ * <p>The typical usage of this is to allow a child RenderNode to draw on a parent's background,
+ * such as the platform's usage with {@link android.graphics.drawable.RippleDrawable}. Consider
+ * the following structure, built out of which RenderNode called drawRenderNode on a different
+ * RenderNode:
+ *
+ * <pre>
+ * +-------------+
+ * |RenderNode: P|
+ * +-+----------++
+ * | |
+ * v v
+ * +-------+-----+ +-+--------------+
+ * |RenderNode: C| |RenderNode: P'BG|
+ * +-------+-----+ +----------------+
+ * |
+ * |
+ * +--------+-------+
+ * |RenderNode: C'BG|
+ * +----------------+
+ * </pre>
+ *
+ * If P'BG is a projection receiver, and C'BG is set to project backwards then C'BG will
+ * behave as if it was drawn directly by P'BG instead of by C. This includes inheriting P'BG's
+ * clip instead of C's clip.
+ *
* @param shouldProject true if the display list should be projected onto a
- * containing volume.
+ * containing volume. Default is false.
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setProjectBackwards(boolean shouldProject) {
return nSetProjectBackwards(mNativeRenderNode, shouldProject);
}
/**
- * Sets whether the RenderNode is a projection receiver - that its parent
- * RenderNode should draw any descendent RenderNodes with
- * ProjectBackwards=true directly on top of it. Default value is false.
+ * Sets whether the RenderNode is a projection receiver. If true then this RenderNode's parent
+ * should draw any descendant RenderNodes with ProjectBackwards=true directly on top of it.
+ * Default value is false. See
+ * {@link #setProjectBackwards(boolean)} for a description of what this entails.
+ *
+ * @param shouldRecieve True if this RenderNode is a projection receiver, false otherwise.
+ * Default is false.
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setProjectionReceiver(boolean shouldRecieve) {
return nSetProjectionReceiver(mNativeRenderNode, shouldRecieve);
@@ -526,6 +582,7 @@ public final class RenderNode {
* outline for those changes to be applied.
*
* @param outline The outline to use for this RenderNode.
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setOutline(@Nullable Outline outline) {
if (outline == null) {
@@ -572,8 +629,9 @@ public final class RenderNode {
* {@link android.R.attr#spotShadowAlpha} theme attribute
*
* @param color The color this RenderNode will cast for its elevation spot shadow.
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
- public boolean setSpotShadowColor(int color) {
+ public boolean setSpotShadowColor(@ColorInt int color) {
return nSetSpotShadowColor(mNativeRenderNode, color);
}
@@ -581,7 +639,7 @@ public final class RenderNode {
* @return The shadow color set by {@link #setSpotShadowColor(int)}, or black if nothing
* was set
*/
- public int getSpotShadowColor() {
+ public @ColorInt int getSpotShadowColor() {
return nGetSpotShadowColor(mNativeRenderNode);
}
@@ -597,8 +655,9 @@ public final class RenderNode {
* {@link android.R.attr#ambientShadowAlpha} theme attribute.
*
* @param color The color this RenderNode will cast for its elevation shadow.
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
- public boolean setAmbientShadowColor(int color) {
+ public boolean setAmbientShadowColor(@ColorInt int color) {
return nSetAmbientShadowColor(mNativeRenderNode, color);
}
@@ -606,7 +665,7 @@ public final class RenderNode {
* @return The shadow color set by {@link #setAmbientShadowColor(int)}, or black if
* nothing was set
*/
- public int getAmbientShadowColor() {
+ public @ColorInt int getAmbientShadowColor() {
return nGetAmbientShadowColor(mNativeRenderNode);
}
@@ -614,6 +673,8 @@ public final class RenderNode {
* Enables or disables clipping to the outline.
*
* @param clipToOutline true if clipping to the outline.
+ * @return True if the clipToOutline value changed, false if previous value matched the new
+ * value.
*/
public boolean setClipToOutline(boolean clipToOutline) {
return nSetClipToOutline(mNativeRenderNode, clipToOutline);
@@ -640,7 +701,7 @@ public final class RenderNode {
/**
* Set the static matrix on the display list. The specified matrix is combined with other
- * transforms (such as {@link #setScaleX(float)}, {@link #setRotation(float)}, etc.)
+ * transforms (such as {@link #setScaleX(float)}, {@link #setRotationZ(float)}, etc.)
*
* @param matrix A transform matrix to apply to this display list
* @hide TODO Do we want this?
@@ -669,6 +730,7 @@ public final class RenderNode {
* @param alpha The translucency of the display list, must be a value between 0.0f and 1.0f
* @see View#setAlpha(float)
* @see #getAlpha()
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setAlpha(float alpha) {
return nSetAlpha(mNativeRenderNode, alpha);
@@ -742,7 +804,7 @@ public final class RenderNode {
* Sets the base elevation of this RenderNode in pixels
*
* @param lift the elevation in pixels
- * @return true if the elevation changed, false if it was the same
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setElevation(float lift) {
return nSetElevation(mNativeRenderNode, lift);
@@ -763,6 +825,7 @@ public final class RenderNode {
* @param translationX The X axis translation value of the display list, in pixels
* @see View#setTranslationX(float)
* @see #getTranslationX()
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setTranslationX(float translationX) {
return nSetTranslationX(mNativeRenderNode, translationX);
@@ -783,6 +846,7 @@ public final class RenderNode {
* @param translationY The Y axis translation value of the display list, in pixels
* @see View#setTranslationY(float)
* @see #getTranslationY()
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setTranslationY(float translationY) {
return nSetTranslationY(mNativeRenderNode, translationY);
@@ -802,6 +866,7 @@ public final class RenderNode {
*
* @see View#setTranslationZ(float)
* @see #getTranslationZ()
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setTranslationZ(float translationZ) {
return nSetTranslationZ(mNativeRenderNode, translationZ);
@@ -820,19 +885,20 @@ public final class RenderNode {
* Sets the rotation value for the display list around the Z axis.
*
* @param rotation The rotation value of the display list, in degrees
- * @see View#setRotation(float)
- * @see #getRotation()
+ * @see View#setRotationZ(float)
+ * @see #getRotationZ()
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
- public boolean setRotation(float rotation) {
+ public boolean setRotationZ(float rotation) {
return nSetRotation(mNativeRenderNode, rotation);
}
/**
* Returns the rotation value for this display list around the Z axis, in degrees.
*
- * @see #setRotation(float)
+ * @see #setRotationZ(float)
*/
- public float getRotation() {
+ public float getRotationZ() {
return nGetRotation(mNativeRenderNode);
}
@@ -842,6 +908,7 @@ public final class RenderNode {
* @param rotationX The rotation value of the display list, in degrees
* @see View#setRotationX(float)
* @see #getRotationX()
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setRotationX(float rotationX) {
return nSetRotationX(mNativeRenderNode, rotationX);
@@ -862,6 +929,7 @@ public final class RenderNode {
* @param rotationY The rotation value of the display list, in degrees
* @see View#setRotationY(float)
* @see #getRotationY()
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setRotationY(float rotationY) {
return nSetRotationY(mNativeRenderNode, rotationY);
@@ -882,6 +950,7 @@ public final class RenderNode {
* @param scaleX The scale value of the display list
* @see View#setScaleX(float)
* @see #getScaleX()
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setScaleX(float scaleX) {
return nSetScaleX(mNativeRenderNode, scaleX);
@@ -902,6 +971,7 @@ public final class RenderNode {
* @param scaleY The scale value of the display list
* @see View#setScaleY(float)
* @see #getScaleY()
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setScaleY(float scaleY) {
return nSetScaleY(mNativeRenderNode, scaleY);
@@ -922,6 +992,7 @@ public final class RenderNode {
* @param pivotX The pivot value of the display list on the X axis, in pixels
* @see View#setPivotX(float)
* @see #getPivotX()
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setPivotX(float pivotX) {
return nSetPivotX(mNativeRenderNode, pivotX);
@@ -942,6 +1013,7 @@ public final class RenderNode {
* @param pivotY The pivot value of the display list on the Y axis, in pixels
* @see View#setPivotY(float)
* @see #getPivotY()
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setPivotY(float pivotY) {
return nSetPivotY(mNativeRenderNode, pivotY);
@@ -969,6 +1041,8 @@ public final class RenderNode {
* Clears any pivot previously set by a call to {@link #setPivotX(float)} or
* {@link #setPivotY(float)}. After calling this {@link #isPivotExplicitlySet()} will be false
* and the pivot used for rotation will return to default of being centered on the view.
+ *
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean resetPivot() {
return nResetPivot(mNativeRenderNode);
@@ -997,8 +1071,10 @@ public final class RenderNode {
* @param distance The distance in pixels, must always be positive
* @see #setRotationX(float)
* @see #setRotationY(float)
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
- public boolean setCameraDistance(float distance) {
+ public boolean setCameraDistance(
+ @FloatRange(from = 0.0f, to = Float.MAX_VALUE) float distance) {
if (!Float.isFinite(distance) || distance < 0.0f) {
throw new IllegalArgumentException("distance must be finite & positive, given="
+ distance);
@@ -1013,7 +1089,7 @@ public final class RenderNode {
* @return the distance along the Z axis in pixels.
* @see #setCameraDistance(float)
*/
- public float getCameraDistance() {
+ public @FloatRange(from = 0.0f, to = Float.MAX_VALUE) float getCameraDistance() {
return -nGetCameraDistance(mNativeRenderNode);
}
@@ -1022,6 +1098,7 @@ public final class RenderNode {
*
* @param left The left position, in pixels, of the RenderNode
* @return true if the value changed, false otherwise
+ * @hide
*/
public boolean setLeft(int left) {
return nSetLeft(mNativeRenderNode, left);
@@ -1032,6 +1109,7 @@ public final class RenderNode {
*
* @param top The top position, in pixels, of the RenderNode
* @return true if the value changed, false otherwise.
+ * @hide
*/
public boolean setTop(int top) {
return nSetTop(mNativeRenderNode, top);
@@ -1042,6 +1120,7 @@ public final class RenderNode {
*
* @param right The right position, in pixels, of the RenderNode
* @return true if the value changed, false otherwise.
+ * @hide
*/
public boolean setRight(int right) {
return nSetRight(mNativeRenderNode, right);
@@ -1052,6 +1131,7 @@ public final class RenderNode {
*
* @param bottom The bottom position, in pixels, of the RenderNode
* @return true if the value changed, false otherwise.
+ * @hide
*/
public boolean setBottom(int bottom) {
return nSetBottom(mNativeRenderNode, bottom);
@@ -1060,8 +1140,6 @@ public final class RenderNode {
/**
* Gets the left position for the RenderNode.
*
- * See {@link #setLeft(int)}
- *
* @return the left position in pixels
*/
public int getLeft() {
@@ -1071,8 +1149,6 @@ public final class RenderNode {
/**
* Gets the top position for the RenderNode.
*
- * See {@link #setTop(int)}
- *
* @return the top position in pixels
*/
public int getTop() {
@@ -1082,8 +1158,6 @@ public final class RenderNode {
/**
* Gets the right position for the RenderNode.
*
- * See {@link #setRight(int)}
- *
* @return the right position in pixels
*/
public int getRight() {
@@ -1093,8 +1167,6 @@ public final class RenderNode {
/**
* Gets the bottom position for the RenderNode.
*
- * See {@link #setBottom(int)}
- *
* @return the bottom position in pixels
*/
public int getBottom() {
@@ -1127,20 +1199,41 @@ public final class RenderNode {
* @param right The right position of the RenderNode, in pixels
* @param bottom The bottom position of the RenderNode, in pixels
* @return true if any values changed, false otherwise.
- * @see #setLeft(int)
- * @see #setTop(int)
- * @see #setRight(int)
- * @see #setBottom(int)
+ * @hide
*/
public boolean setLeftTopRightBottom(int left, int top, int right, int bottom) {
return nSetLeftTopRightBottom(mNativeRenderNode, left, top, right, bottom);
}
/**
+ * Sets the position of the RenderNode.
+ *
+ * @param left The left position of the RenderNode, in pixels
+ * @param top The top position of the RenderNode, in pixels
+ * @param right The right position of the RenderNode, in pixels
+ * @param bottom The bottom position of the RenderNode, in pixels
+ * @return True if the value changed, false if the new value was the same as the previous value.
+ */
+ public boolean setPosition(int left, int top, int right, int bottom) {
+ return nSetLeftTopRightBottom(mNativeRenderNode, left, top, right, bottom);
+ }
+
+ /**
+ * Sets the position of the RenderNode.
+ *
+ * @param position The position rectangle in pixels
+ * @return True if the value changed, false if the new value was the same as the previous value.
+ */
+ public boolean setPosition(Rect position) {
+ return nSetLeftTopRightBottom(mNativeRenderNode,
+ position.left, position.top, position.right, position.bottom);
+ }
+
+ /**
* Offsets the left and right positions for the RenderNode
*
* @param offset The amount that the left and right positions are offset in pixels
- * @return true if any values changed, false otherwise.
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean offsetLeftAndRight(int offset) {
return nOffsetLeftAndRight(mNativeRenderNode, offset);
@@ -1150,7 +1243,7 @@ public final class RenderNode {
* Offsets the top and bottom values for the RenderNode
*
* @param offset The amount that the left and right positions are offset in pixels
- * @return true if any values changed, false otherwise.
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean offsetTopAndBottom(int offset) {
return nOffsetTopAndBottom(mNativeRenderNode, offset);
@@ -1170,8 +1263,10 @@ public final class RenderNode {
* Gets the approximate memory usage of the RenderNode for debug purposes. Does not include
* the memory usage of any child RenderNodes nor any bitmaps, only the memory usage of
* this RenderNode and any data it owns.
+ *
+ * @return Approximate memory usage in bytes.
*/
- public int computeApproximateMemoryUsage() {
+ public @BytesLong long computeApproximateMemoryUsage() {
return nGetDebugSize(mNativeRenderNode);
}
@@ -1186,7 +1281,7 @@ public final class RenderNode {
* it prevent any 'false' in any of its children.
*
* @param allow Whether or not to allow force dark.
- * @return true If the value has changed, false otherwise.
+ * @return True if the value changed, false if the new value was the same as the previous value.
*/
public boolean setForceDarkAllowed(boolean allow) {
return nSetAllowForceDark(mNativeRenderNode, allow);
diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp
index 66d8542553d2..d7b84ff1060d 100644
--- a/libs/androidfw/AssetManager2.cpp
+++ b/libs/androidfw/AssetManager2.cpp
@@ -356,6 +356,7 @@ std::unique_ptr<Asset> AssetManager2::OpenNonAsset(const std::string& filename,
ApkAssetsCookie AssetManager2::FindEntry(uint32_t resid, uint16_t density_override,
bool /*stop_at_first_match*/,
+ bool ignore_configuration,
FindEntryResult* out_entry) const {
// Might use this if density_override != 0.
ResTable_config density_override_config;
@@ -399,7 +400,7 @@ ApkAssetsCookie AssetManager2::FindEntry(uint32_t resid, uint16_t density_overri
// If desired_config is the same as the set configuration, then we can use our filtered list
// and we don't need to match the configurations, since they already matched.
- const bool use_fast_path = desired_config == &configuration_;
+ const bool use_fast_path = !ignore_configuration && desired_config == &configuration_;
for (size_t pi = 0; pi < package_count; pi++) {
const ConfiguredPackage& loaded_package_impl = package_group.packages_[pi];
@@ -475,21 +476,23 @@ ApkAssetsCookie AssetManager2::FindEntry(uint32_t resid, uint16_t density_overri
// ResTable_config, we must copy it.
const auto iter_end = type_spec->types + type_spec->type_count;
for (auto iter = type_spec->types; iter != iter_end; ++iter) {
- ResTable_config this_config;
- this_config.copyFromDtoH((*iter)->config);
+ ResTable_config this_config{};
- if (!this_config.match(*desired_config)) {
- continue;
- }
+ if (!ignore_configuration) {
+ this_config.copyFromDtoH((*iter)->config);
+ if (!this_config.match(*desired_config)) {
+ continue;
+ }
- if (best_config == nullptr) {
- resolution_type = Resolution::Step::Type::INITIAL;
- } else if (this_config.isBetterThan(*best_config, desired_config)) {
- resolution_type = Resolution::Step::Type::BETTER_MATCH;
- } else if (package_is_overlay && this_config.compare(*best_config) == 0) {
- resolution_type = Resolution::Step::Type::OVERLAID;
- } else {
- continue;
+ if (best_config == nullptr) {
+ resolution_type = Resolution::Step::Type::INITIAL;
+ } else if (this_config.isBetterThan(*best_config, desired_config)) {
+ resolution_type = Resolution::Step::Type::BETTER_MATCH;
+ } else if (package_is_overlay && this_config.compare(*best_config) == 0) {
+ resolution_type = Resolution::Step::Type::OVERLAID;
+ } else {
+ continue;
+ }
}
// The configuration matches and is better than the previous selection.
@@ -506,6 +509,11 @@ ApkAssetsCookie AssetManager2::FindEntry(uint32_t resid, uint16_t density_overri
best_config = &best_config_copy;
best_offset = offset;
+ if (ignore_configuration) {
+ // Any configuration will suffice, so break.
+ break;
+ }
+
if (resource_resolution_logging_enabled_) {
resolution_steps.push_back(Resolution::Step{resolution_type,
this_config.toString(),
@@ -622,8 +630,9 @@ std::string AssetManager2::GetLastResourceResolution() const {
bool AssetManager2::GetResourceName(uint32_t resid, ResourceName* out_name) const {
FindEntryResult entry;
- ApkAssetsCookie cookie =
- FindEntry(resid, 0u /* density_override */, true /* stop_at_first_match */, &entry);
+ ApkAssetsCookie cookie = FindEntry(resid, 0u /* density_override */,
+ true /* stop_at_first_match */,
+ true /* ignore_configuration */, &entry);
if (cookie == kInvalidCookie) {
return false;
}
@@ -652,13 +661,14 @@ bool AssetManager2::GetResourceName(uint32_t resid, ResourceName* out_name) cons
bool AssetManager2::GetResourceFlags(uint32_t resid, uint32_t* out_flags) const {
FindEntryResult entry;
- ApkAssetsCookie cookie =
- FindEntry(resid, 0u /* density_override */, false /* stop_at_first_match */, &entry);
+ ApkAssetsCookie cookie = FindEntry(resid, 0u /* density_override */,
+ false /* stop_at_first_match */,
+ true /* ignore_configuration */, &entry);
if (cookie != kInvalidCookie) {
*out_flags = entry.type_flags;
- return cookie;
+ return true;
}
- return kInvalidCookie;
+ return false;
}
ApkAssetsCookie AssetManager2::GetResource(uint32_t resid, bool may_be_bag,
@@ -666,8 +676,8 @@ ApkAssetsCookie AssetManager2::GetResource(uint32_t resid, bool may_be_bag,
ResTable_config* out_selected_config,
uint32_t* out_flags) const {
FindEntryResult entry;
- ApkAssetsCookie cookie =
- FindEntry(resid, density_override, false /* stop_at_first_match */, &entry);
+ ApkAssetsCookie cookie = FindEntry(resid, density_override, false /* stop_at_first_match */,
+ false /* ignore_configuration */, &entry);
if (cookie == kInvalidCookie) {
return kInvalidCookie;
}
@@ -759,8 +769,10 @@ const ResolvedBag* AssetManager2::GetBag(uint32_t resid, std::vector<uint32_t>&
}
FindEntryResult entry;
- ApkAssetsCookie cookie =
- FindEntry(resid, 0u /* density_override */, false /* stop_at_first_match */, &entry);
+ ApkAssetsCookie cookie = FindEntry(resid, 0u /* density_override */,
+ false /* stop_at_first_match */,
+ false /* ignore_configuration */,
+ &entry);
if (cookie == kInvalidCookie) {
return nullptr;
}
@@ -1387,7 +1399,9 @@ void Theme::SetTo(const Theme& o) {
// Find the cookie of the attribute resource id
FindEntryResult attribute_entry_result;
ApkAssetsCookie attribute_cookie =
- o.asset_manager_->FindEntry(make_resid(p, t, e), 0 /* density_override */ , false,
+ o.asset_manager_->FindEntry(make_resid(p, t, e), 0 /* density_override */ ,
+ true /* stop_at_first_match */,
+ true /* ignore_configuration */,
&attribute_entry_result);
// Determine the package id of the attribute in the destination AssetManager
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index fc5aa9c7f1b9..1e2b36cb1703 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -257,11 +257,12 @@ class AssetManager2 {
// Creates a new Theme from this AssetManager.
std::unique_ptr<Theme> NewTheme();
- template <typename Func>
- void ForEachPackage(Func func) const {
+ void ForEachPackage(const std::function<bool(const std::string&, uint8_t)> func) const {
for (const PackageGroup& package_group : package_groups_) {
- func(package_group.packages_.front().loaded_package_->GetPackageName(),
- package_group.dynamic_ref_table.mAssignedPackageId);
+ if (!func(package_group.packages_.front().loaded_package_->GetPackageName(),
+ package_group.dynamic_ref_table.mAssignedPackageId)) {
+ return;
+ }
}
}
@@ -282,10 +283,13 @@ class AssetManager2 {
// care about the value. In this case, the value of `FindEntryResult::type_flags` is incomplete
// and should not be used.
//
+ // When `ignore_configuration` is true, FindEntry will return always select the first entry in
+ // for the type seen regardless of its configuration.
+ //
// NOTE: FindEntry takes care of ensuring that structs within FindEntryResult have been properly
// bounds-checked. Callers of FindEntry are free to trust the data if this method succeeds.
ApkAssetsCookie FindEntry(uint32_t resid, uint16_t density_override, bool stop_at_first_match,
- FindEntryResult* out_entry) const;
+ bool ignore_configuration, FindEntryResult* out_entry) const;
// Assigns package IDs to all shared library ApkAssets.
// Should be called whenever the ApkAssets are changed.
diff --git a/location/java/android/location/GnssMeasurementCorrections.java b/location/java/android/location/GnssMeasurementCorrections.java
index 3ce48b4f7627..9d3211d1b4f8 100644
--- a/location/java/android/location/GnssMeasurementCorrections.java
+++ b/location/java/android/location/GnssMeasurementCorrections.java
@@ -124,7 +124,7 @@ public final class GnssMeasurementCorrections implements Parcelable {
* Gets a set of {@link GnssSingleSatCorrection} each containing measurement corrections for a
* satellite in view
*/
- public @Nullable List<GnssSingleSatCorrection> getSingleSatCorrectionList() {
+ public @Nullable List<GnssSingleSatCorrection> getSingleSatelliteCorrectionList() {
return mSingleSatCorrectionList;
}
@@ -137,7 +137,7 @@ public final class GnssMeasurementCorrections implements Parcelable {
new Creator<GnssMeasurementCorrections>() {
@Override
public GnssMeasurementCorrections createFromParcel(Parcel parcel) {
- GnssMeasurementCorrections.Builder gnssMeasurementCorrectons =
+ final GnssMeasurementCorrections.Builder gnssMeasurementCorrectons =
new Builder()
.setLatitudeDegrees(parcel.readDouble())
.setLongitudeDegrees(parcel.readDouble())
@@ -147,7 +147,7 @@ public final class GnssMeasurementCorrections implements Parcelable {
.setToaGpsNanosecondsOfWeek(parcel.readLong());
List<GnssSingleSatCorrection> singleSatCorrectionList = new ArrayList<>();
parcel.readTypedList(singleSatCorrectionList, GnssSingleSatCorrection.CREATOR);
- gnssMeasurementCorrectons.setSingleSatCorrectionList(
+ gnssMeasurementCorrectons.setSingleSatelliteCorrectionList(
singleSatCorrectionList.isEmpty() ? null : singleSatCorrectionList);
return gnssMeasurementCorrectons.build();
}
@@ -188,7 +188,7 @@ public final class GnssMeasurementCorrections implements Parcelable {
}
/** Builder for {@link GnssMeasurementCorrections} */
- public static class Builder {
+ public static final class Builder {
/**
* For documentation of below fields, see corresponding fields in {@link
* GnssMeasurementCorrections}.
@@ -253,7 +253,7 @@ public final class GnssMeasurementCorrections implements Parcelable {
* Sets a the list of {@link GnssSingleSatCorrection} containing measurement corrections for
* a satellite in view
*/
- public Builder setSingleSatCorrectionList(
+ public Builder setSingleSatelliteCorrectionList(
@Nullable List<GnssSingleSatCorrection> singleSatCorrectionList) {
if (singleSatCorrectionList == null) {
mSingleSatCorrectionList = null;
diff --git a/location/java/android/location/GnssReflectingPlane.java b/location/java/android/location/GnssReflectingPlane.java
index 64b37524e37f..9a106a760ec4 100644
--- a/location/java/android/location/GnssReflectingPlane.java
+++ b/location/java/android/location/GnssReflectingPlane.java
@@ -116,7 +116,7 @@ public final class GnssReflectingPlane implements Parcelable {
}
/** Builder for {@link GnssReflectingPlane} */
- public static class Builder {
+ public static final class Builder {
/** For documentation, see corresponding fields in {@link GnssReflectingPlane}. */
private double mLatitudeDegrees;
diff --git a/location/java/android/location/GnssSingleSatCorrection.java b/location/java/android/location/GnssSingleSatCorrection.java
index 4d5303f18b81..f719e1a985b8 100644
--- a/location/java/android/location/GnssSingleSatCorrection.java
+++ b/location/java/android/location/GnssSingleSatCorrection.java
@@ -60,6 +60,7 @@ public final class GnssSingleSatCorrection implements Parcelable {
private int mSingleSatCorrectionFlags;
/** Defines the constellation of the given satellite as defined in {@link GnssStatus}. */
+ @GnssStatus.ConstellationType
private int mConstellationType;
/**
@@ -115,7 +116,7 @@ public final class GnssSingleSatCorrection implements Parcelable {
}
/** Gets a bitmask of fields present in this object */
- public int getSingleSatCorrectionFlags() {
+ public int getSingleSatelliteCorrectionFlags() {
return mSingleSatCorrectionFlags;
}
@@ -136,7 +137,7 @@ public final class GnssSingleSatCorrection implements Parcelable {
* <p>Interpretation depends on {@link #getConstellationType()}. See {@link
* GnssStatus#getSvid(int)}.
*/
- public int getSatId() {
+ public int getSatelliteId() {
return mSatId;
}
@@ -162,7 +163,7 @@ public final class GnssSingleSatCorrection implements Parcelable {
* location.
*/
@FloatRange(from = 0f, to = 1f)
- public float getProbSatIsLos() {
+ public float getProbabilityLineOfSight() {
return mProbSatIsLos;
}
@@ -189,8 +190,8 @@ public final class GnssSingleSatCorrection implements Parcelable {
return mReflectingPlane;
}
- /** Returns {@code true} if {@link #getProbSatIsLos()} is valid. */
- public boolean hasSatelliteLineOfSight() {
+ /** Returns {@code true} if {@link #getProbabilityLineOfSight()} is valid. */
+ public boolean hasValidSatelliteLineOfSight() {
return (mSingleSatCorrectionFlags & HAS_PROB_SAT_IS_LOS_MASK) != 0;
}
@@ -220,11 +221,11 @@ public final class GnssSingleSatCorrection implements Parcelable {
public GnssSingleSatCorrection createFromParcel(Parcel parcel) {
GnssSingleSatCorrection singleSatCorrection =
new Builder()
- .setSingleSatCorrectionFlags(parcel.readInt())
+ .setSingleSatelliteCorrectionFlags(parcel.readInt())
.setConstellationType(parcel.readInt())
- .setSatId(parcel.readInt())
+ .setSatelliteId(parcel.readInt())
.setCarrierFrequencyHz(parcel.readFloat())
- .setProbSatIsLos(parcel.readFloat())
+ .setProbabilityLineOfSight(parcel.readFloat())
.setExcessPathLengthMeters(parcel.readFloat())
.setExcessPathLengthUncertaintyMeters(parcel.readFloat())
.setReflectingPlane(
@@ -272,7 +273,7 @@ public final class GnssSingleSatCorrection implements Parcelable {
}
/** Builder for {@link GnssSingleSatCorrection} */
- public static class Builder {
+ public static final class Builder {
/**
* For documentation of below fields, see corresponding fields in {@link
@@ -289,19 +290,19 @@ public final class GnssSingleSatCorrection implements Parcelable {
private GnssReflectingPlane mReflectingPlane;
/** Sets a bitmask of fields present in this object */
- public Builder setSingleSatCorrectionFlags(int singleSatCorrectionFlags) {
+ public Builder setSingleSatelliteCorrectionFlags(int singleSatCorrectionFlags) {
mSingleSatCorrectionFlags = singleSatCorrectionFlags;
return this;
}
/** Sets the constellation type. */
- public Builder setConstellationType(int constellationType) {
+ public Builder setConstellationType(@GnssStatus.ConstellationType int constellationType) {
mConstellationType = constellationType;
return this;
}
- /** Sets the Satellite ID. */
- public Builder setSatId(int satId) {
+ /** Sets the Satellite ID defined in the ICD of the given constellation. */
+ public Builder setSatelliteId(int satId) {
mSatId = satId;
return this;
}
@@ -316,7 +317,8 @@ public final class GnssSingleSatCorrection implements Parcelable {
* Sets the line-of-sight probability of the satellite at the given location in the range
* between 0 and 1.
*/
- public Builder setProbSatIsLos(@FloatRange(from = 0f, to = 1f) float probSatIsLos) {
+ public Builder setProbabilityLineOfSight(
+ @FloatRange(from = 0f, to = 1f) float probSatIsLos) {
Preconditions.checkArgumentInRange(
probSatIsLos, 0, 1, "probSatIsLos should be between 0 and 1.");
mProbSatIsLos = probSatIsLos;
diff --git a/location/tests/locationtests/src/android/location/GnssMeasurementCorrectionsTest.java b/location/tests/locationtests/src/android/location/GnssMeasurementCorrectionsTest.java
deleted file mode 100644
index 8f46e84195d5..000000000000
--- a/location/tests/locationtests/src/android/location/GnssMeasurementCorrectionsTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.location;
-
-import android.os.Parcel;
-
-import junit.framework.TestCase;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/** Unit tests for {@link GnssMeasurementCorrections}. */
-public class GnssMeasurementCorrectionsTest extends TestCase {
- public void testDescribeContents() {
- GnssMeasurementCorrections measurementCorrections =
- new GnssMeasurementCorrections.Builder().build();
- measurementCorrections.describeContents();
- }
-
- public void testWriteToParcel() {
- GnssMeasurementCorrections.Builder measurementCorrections =
- new GnssMeasurementCorrections.Builder();
- setTestValues(measurementCorrections);
- Parcel parcel = Parcel.obtain();
- measurementCorrections.build().writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- GnssMeasurementCorrections newMeasurementCorrection =
- GnssMeasurementCorrections.CREATOR.createFromParcel(parcel);
- verifyTestValues(newMeasurementCorrection);
- parcel.recycle();
- }
-
- private static void verifyTestValues(GnssMeasurementCorrections measurementCorrections) {
- assertEquals(37.386051, measurementCorrections.getLatitudeDegrees());
- assertEquals(-122.083855, measurementCorrections.getLongitudeDegrees());
- assertEquals(32.0, measurementCorrections.getAltitudeMeters());
- assertEquals(9.25, measurementCorrections.getHorizontalPositionUncertaintyMeters());
- assertEquals(2.3, measurementCorrections.getVerticalPositionUncertaintyMeters());
- assertEquals(604000000000000L, measurementCorrections.getToaGpsNanosecondsOfWeek());
-
- GnssSingleSatCorrection singleSatCorrection =
- measurementCorrections.getSingleSatCorrectionList().get(0);
- GnssSingleSatCorrectionsTest.verifyTestValues(singleSatCorrection);
-
- singleSatCorrection = measurementCorrections.getSingleSatCorrectionList().get(1);
- assertEquals(15, singleSatCorrection.getSingleSatCorrectionFlags());
- assertEquals(GnssStatus.CONSTELLATION_GPS, singleSatCorrection.getConstellationType());
- assertEquals(11, singleSatCorrection.getSatId());
- assertEquals(1575430000f, singleSatCorrection.getCarrierFrequencyHz());
- assertEquals(0.9f, singleSatCorrection.getProbSatIsLos());
- assertEquals(50.0f, singleSatCorrection.getExcessPathLengthMeters());
- assertEquals(55.0f, singleSatCorrection.getExcessPathLengthUncertaintyMeters());
- GnssReflectingPlane reflectingPlane = singleSatCorrection.getReflectingPlane();
- assertEquals(37.386054, reflectingPlane.getLatitudeDegrees());
- assertEquals(-122.083855, reflectingPlane.getLongitudeDegrees());
- assertEquals(120.0, reflectingPlane.getAltitudeMeters());
- assertEquals(153.0, reflectingPlane.getAzimuthDegrees());
- }
-
- private static void setTestValues(GnssMeasurementCorrections.Builder measurementCorrections) {
- measurementCorrections
- .setLatitudeDegrees(37.386051)
- .setLongitudeDegrees(-122.083855)
- .setAltitudeMeters(32)
- .setHorizontalPositionUncertaintyMeters(9.25)
- .setVerticalPositionUncertaintyMeters(2.3)
- .setToaGpsNanosecondsOfWeek(604000000000000L);
- List<GnssSingleSatCorrection> singleSatCorrectionList = new ArrayList<>();
- singleSatCorrectionList.add(GnssSingleSatCorrectionsTest.generateTestSingleSatCorrection());
- singleSatCorrectionList.add(generateTestSingleSatCorrection());
- measurementCorrections.setSingleSatCorrectionList(singleSatCorrectionList);
- }
-
- private static GnssSingleSatCorrection generateTestSingleSatCorrection() {
- GnssSingleSatCorrection.Builder singleSatCorrection = new GnssSingleSatCorrection.Builder();
- singleSatCorrection
- .setSingleSatCorrectionFlags(8)
- .setConstellationType(GnssStatus.CONSTELLATION_GPS)
- .setSatId(11)
- .setCarrierFrequencyHz(1575430000f)
- .setProbSatIsLos(0.9f)
- .setExcessPathLengthMeters(50.0f)
- .setExcessPathLengthUncertaintyMeters(55.0f)
- .setReflectingPlane(generateTestReflectingPlane());
- return singleSatCorrection.build();
- }
-
- private static GnssReflectingPlane generateTestReflectingPlane() {
- GnssReflectingPlane.Builder reflectingPlane =
- new GnssReflectingPlane.Builder()
- .setLatitudeDegrees(37.386054)
- .setLongitudeDegrees(-122.083855)
- .setAltitudeMeters(120.0)
- .setAzimuthDegrees(153);
- return reflectingPlane.build();
- }
-}
diff --git a/location/tests/locationtests/src/android/location/GnssReflectingPlaneTest.java b/location/tests/locationtests/src/android/location/GnssReflectingPlaneTest.java
deleted file mode 100644
index d7a3378e5a12..000000000000
--- a/location/tests/locationtests/src/android/location/GnssReflectingPlaneTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.location;
-
-import android.os.Parcel;
-
-import junit.framework.TestCase;
-
-/** Unit tests for {@link GnssReflectingPlane}. */
-public class GnssReflectingPlaneTest extends TestCase {
- public void testDescribeContents() {
- GnssReflectingPlane reflectingPlane = new GnssReflectingPlane.Builder().build();
- reflectingPlane.describeContents();
- }
-
- public void testWriteToParcel() {
- GnssReflectingPlane.Builder reflectingPlane = new GnssReflectingPlane.Builder();
- setTestValues(reflectingPlane);
- Parcel parcel = Parcel.obtain();
- reflectingPlane.build().writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- GnssReflectingPlane newReflectingPlane =
- GnssReflectingPlane.CREATOR.createFromParcel(parcel);
- verifyTestValues(newReflectingPlane);
- parcel.recycle();
- }
-
- public static void verifyTestValues(GnssReflectingPlane reflectingPlane) {
- assertEquals(37.386052, reflectingPlane.getLatitudeDegrees());
- assertEquals(-122.083853, reflectingPlane.getLongitudeDegrees());
- assertEquals(100.0, reflectingPlane.getAltitudeMeters());
- assertEquals(123.0, reflectingPlane.getAzimuthDegrees());
- }
-
- private static void setTestValues(GnssReflectingPlane.Builder reflectingPlane) {
- GnssReflectingPlane refPlane = generateTestReflectingPlane();
- reflectingPlane
- .setLatitudeDegrees(refPlane.getLatitudeDegrees())
- .setLongitudeDegrees(refPlane.getLongitudeDegrees())
- .setAltitudeMeters(refPlane.getAltitudeMeters())
- .setAzimuthDegrees(refPlane.getAzimuthDegrees());
- }
-
- public static GnssReflectingPlane generateTestReflectingPlane() {
- GnssReflectingPlane.Builder reflectingPlane =
- new GnssReflectingPlane.Builder()
- .setLatitudeDegrees(37.386052)
- .setLongitudeDegrees(-122.083853)
- .setAltitudeMeters(100.0)
- .setAzimuthDegrees(123.0);
- return reflectingPlane.build();
- }
-}
diff --git a/location/tests/locationtests/src/android/location/GnssSingleSatCorrectionsTest.java b/location/tests/locationtests/src/android/location/GnssSingleSatCorrectionsTest.java
deleted file mode 100644
index f358806d0b26..000000000000
--- a/location/tests/locationtests/src/android/location/GnssSingleSatCorrectionsTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.location;
-
-import android.os.Parcel;
-
-import junit.framework.TestCase;
-
-/** Unit tests for {@link GnssSingleSatCorrection}. */
-public class GnssSingleSatCorrectionsTest extends TestCase {
- public void testDescribeContents() {
- GnssSingleSatCorrection singleSatCorrection = new GnssSingleSatCorrection.Builder().build();
- singleSatCorrection.describeContents();
- }
-
- public void testWriteToParcel() {
- GnssSingleSatCorrection.Builder singleSatCorrection = new GnssSingleSatCorrection.Builder();
- setTestValues(singleSatCorrection);
- Parcel parcel = Parcel.obtain();
- singleSatCorrection.build().writeToParcel(parcel, 0);
- parcel.setDataPosition(0);
- GnssSingleSatCorrection newSingleSatCorrection =
- GnssSingleSatCorrection.CREATOR.createFromParcel(parcel);
- verifyTestValues(newSingleSatCorrection);
- parcel.recycle();
- }
-
- public static void verifyTestValues(GnssSingleSatCorrection singleSatCorrection) {
- assertEquals(15, singleSatCorrection.getSingleSatCorrectionFlags());
- assertEquals(GnssStatus.CONSTELLATION_GALILEO, singleSatCorrection.getConstellationType());
- assertEquals(12, singleSatCorrection.getSatId());
- assertEquals(1575420000f, singleSatCorrection.getCarrierFrequencyHz());
- assertEquals(0.1f, singleSatCorrection.getProbSatIsLos());
- assertEquals(10.0f, singleSatCorrection.getExcessPathLengthMeters());
- assertEquals(5.0f, singleSatCorrection.getExcessPathLengthUncertaintyMeters());
- GnssReflectingPlane reflectingPlane = singleSatCorrection.getReflectingPlane();
- GnssReflectingPlaneTest.verifyTestValues(reflectingPlane);
- }
-
- private static void setTestValues(GnssSingleSatCorrection.Builder singleSatCorrection) {
- GnssSingleSatCorrection singleSatCorr = generateTestSingleSatCorrection();
- singleSatCorrection
- .setSingleSatCorrectionFlags(singleSatCorr.getSingleSatCorrectionFlags())
- .setConstellationType(singleSatCorr.getConstellationType())
- .setSatId(singleSatCorr.getSatId())
- .setCarrierFrequencyHz(singleSatCorr.getCarrierFrequencyHz())
- .setProbSatIsLos(singleSatCorr.getProbSatIsLos())
- .setExcessPathLengthMeters(singleSatCorr.getExcessPathLengthMeters())
- .setExcessPathLengthUncertaintyMeters(
- singleSatCorr.getExcessPathLengthUncertaintyMeters())
- .setReflectingPlane(singleSatCorr.getReflectingPlane());
- }
-
- public static GnssSingleSatCorrection generateTestSingleSatCorrection() {
- GnssSingleSatCorrection.Builder singleSatCorrection =
- new GnssSingleSatCorrection.Builder()
- .setSingleSatCorrectionFlags(15)
- .setConstellationType(GnssStatus.CONSTELLATION_GALILEO)
- .setSatId(12)
- .setCarrierFrequencyHz(1575420000f)
- .setProbSatIsLos(0.1f)
- .setExcessPathLengthMeters(10.0f)
- .setExcessPathLengthUncertaintyMeters(5.0f)
- .setReflectingPlane(GnssReflectingPlaneTest.generateTestReflectingPlane());
- return singleSatCorrection.build();
- }
-}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 7de7f8fb3820..bd828eea8179 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -36,6 +36,7 @@ import android.content.Context;
import android.content.Intent;
import android.media.audiopolicy.AudioPolicy;
import android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener;
+import android.media.projection.MediaProjection;
import android.media.session.MediaController;
import android.media.session.MediaSession;
import android.media.session.MediaSessionLegacyHelper;
@@ -3197,8 +3198,10 @@ public class AudioManager {
}
final IAudioService service = getService();
try {
+ MediaProjection projection = policy.getMediaProjection();
String regId = service.registerAudioPolicy(policy.getConfig(), policy.cb(),
- policy.hasFocusListener(), policy.isFocusPolicy(), policy.isVolumeController());
+ policy.hasFocusListener(), policy.isFocusPolicy(), policy.isVolumeController(),
+ projection == null ? null : projection.getProjection());
if (regId == null) {
return ERROR;
} else {
diff --git a/media/java/android/media/AudioPlaybackCaptureConfiguration.java b/media/java/android/media/AudioPlaybackCaptureConfiguration.java
index 22f14aedf091..d714dc7772f9 100644
--- a/media/java/android/media/AudioPlaybackCaptureConfiguration.java
+++ b/media/java/android/media/AudioPlaybackCaptureConfiguration.java
@@ -19,34 +19,52 @@ package android.media;
import android.annotation.NonNull;
import android.media.audiopolicy.AudioMix;
import android.media.audiopolicy.AudioMixingRule;
+import android.media.projection.MediaProjection;
+import android.os.RemoteException;
import com.android.internal.util.Preconditions;
/**
* Configuration for capturing audio played by other apps.
*
+ * For privacy and copyright reason, only the following audio can be captured:
+ * - usage MUST be UNKNOWN or GAME or MEDIA. All other usages CAN NOT be capturable.
+ * - audio attributes MUST NOT have the FLAG_NO_CAPTURE
+ * - played by apps that MUST be in the same user profile as the capturing app
+ * (eg work profile can not capture user profile apps and vice-versa).
+ * - played by apps that MUST NOT have in their manifest.xml the application
+ * attribute android:allowPlaybackCapture="false"
+ * - played by apps that MUST have a targetSdkVersion higher or equal to 29 (Q).
+ *
* <p>An example for creating a capture configuration for capturing all media playback:
*
* <pre>
+ * MediaProjection mediaProjection;
+ * // Retrieve a audio capable projection from the MediaProjectionManager
* AudioAttributes mediaAttr = new AudioAttributes.Builder()
* .setUsage(AudioAttributes.USAGE_MEDIA)
* .build();
- * AudioPlaybackCaptureConfiguration config = new AudioPlaybackCaptureConfiguration.Builder()
+ * AudioPlaybackCaptureConfiguration config =
+ * new AudioPlaybackCaptureConfiguration.Builder(mediaProjection)
* .addMatchingUsage(mediaAttr)
* .build();
* AudioRecord record = new AudioRecord.Builder()
- * .setPlaybackCaptureConfig(config)
+ * .setAudioPlaybackCaptureConfig(config)
* .build();
* </pre>
*
- * @see AudioRecord.Builder#setPlaybackCaptureConfig(AudioPlaybackCaptureConfiguration)
+ * @see MediaProjectionManager#getMediaProjection(int, Intent)
+ * @see AudioRecord.Builder#setAudioPlaybackCaptureConfig(AudioPlaybackCaptureConfiguration)
*/
public final class AudioPlaybackCaptureConfiguration {
private final AudioMixingRule mAudioMixingRule;
+ private final MediaProjection mProjection;
- private AudioPlaybackCaptureConfiguration(AudioMixingRule audioMixingRule) {
+ private AudioPlaybackCaptureConfiguration(AudioMixingRule audioMixingRule,
+ MediaProjection projection) {
mAudioMixingRule = audioMixingRule;
+ mProjection = projection;
}
/**
@@ -60,6 +78,9 @@ public final class AudioPlaybackCaptureConfiguration {
.setRouteFlags(AudioMix.ROUTE_FLAG_LOOP_BACK | AudioMix.ROUTE_FLAG_RENDER)
.build();
}
+ MediaProjection getMediaProjection() {
+ return mProjection;
+ }
/** Builder for creating {@link AudioPlaybackCaptureConfiguration} instances. */
public static final class Builder {
@@ -70,12 +91,26 @@ public final class AudioPlaybackCaptureConfiguration {
private static final String ERROR_MESSAGE_MISMATCHED_RULES =
"Inclusive and exclusive usage rules cannot be combined";
+ private static final String ERROR_MESSAGE_START_ACTIVITY_FAILED =
+ "startActivityForResult failed";
+ private static final String ERROR_MESSAGE_NON_AUDIO_PROJECTION =
+ "MediaProjection can not project audio";
private final AudioMixingRule.Builder mAudioMixingRuleBuilder;
+ private final MediaProjection mProjection;
private int mUsageMatchType = MATCH_TYPE_UNSPECIFIED;
private int mUidMatchType = MATCH_TYPE_UNSPECIFIED;
- public Builder() {
+ /** @param projection A MediaProjection that supports audio projection. */
+ public Builder(@NonNull MediaProjection projection) {
+ Preconditions.checkNotNull(projection);
+ try {
+ Preconditions.checkArgument(projection.getProjection().canProjectAudio(),
+ ERROR_MESSAGE_NON_AUDIO_PROJECTION);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ mProjection = projection;
mAudioMixingRuleBuilder = new AudioMixingRule.Builder();
}
@@ -155,7 +190,8 @@ public final class AudioPlaybackCaptureConfiguration {
* @throws UnsupportedOperationException if the parameters set are incompatible.
*/
public AudioPlaybackCaptureConfiguration build() {
- return new AudioPlaybackCaptureConfiguration(mAudioMixingRuleBuilder.build());
+ return new AudioPlaybackCaptureConfiguration(mAudioMixingRuleBuilder.build(),
+ mProjection);
}
}
}
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 10accf23364c..ec1a854a66d5 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -26,6 +26,7 @@ import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
import android.media.audiopolicy.AudioMix;
import android.media.audiopolicy.AudioPolicy;
+import android.media.projection.MediaProjection;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -401,7 +402,7 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
int initResult = native_setup( new WeakReference<AudioRecord>(this),
mAudioAttributes, sampleRate, mChannelMask, mChannelIndexMask,
mAudioFormat, mNativeBufferSizeInBytes,
- session, ActivityThread.currentOpPackageName(), 0 /*nativeRecordInJavaObj*/);
+ session, getCurrentOpPackageName(), 0 /*nativeRecordInJavaObj*/);
if (initResult != SUCCESS) {
loge("Error code "+initResult+" when initializing native AudioRecord object.");
return; // with mState == STATE_UNINITIALIZED
@@ -413,6 +414,15 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
mState = STATE_INITIALIZED;
}
+ private String getCurrentOpPackageName() {
+ String opPackageName = ActivityThread.currentOpPackageName();
+ if (opPackageName != null) {
+ return opPackageName;
+ }
+ // Command line utility
+ return "uid:" + Binder.getCallingUid();
+ }
+
/**
* A constructor which explicitly connects a Native (C++) AudioRecord. For use by
* the AudioRecordRoutingProxy subclass.
@@ -639,7 +649,9 @@ public class AudioRecord implements AudioRouting, MicrophoneDirection,
private AudioRecord buildAudioPlaybackCaptureRecord() {
AudioMix audioMix = mAudioPlaybackCaptureConfiguration.createAudioMix(mFormat);
+ MediaProjection projection = mAudioPlaybackCaptureConfiguration.getMediaProjection();
AudioPolicy audioPolicy = new AudioPolicy.Builder(/*context=*/ null)
+ .setMediaProjection(projection)
.addMix(audioMix).build();
AudioRecord record = audioPolicy.createAudioRecordSink(audioMix);
record.unregisterAudioPolicyOnRelease(audioPolicy);
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index f5aeca717424..571e67e1ccfc 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -34,6 +34,7 @@ import android.media.PlayerBase;
import android.media.VolumePolicy;
import android.media.audiopolicy.AudioPolicyConfig;
import android.media.audiopolicy.IAudioPolicyCallback;
+import android.media.projection.IMediaProjection;
/**
* {@hide}
@@ -176,7 +177,7 @@ interface IAudioService {
String registerAudioPolicy(in AudioPolicyConfig policyConfig,
in IAudioPolicyCallback pcb, boolean hasFocusListener, boolean isFocusPolicy,
- boolean isVolumeController);
+ boolean isVolumeController, in IMediaProjection projection);
oneway void unregisterAudioPolicyAsync(in IAudioPolicyCallback pcb);
diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java
index 6116429ae561..ba87f2bbffb5 100644
--- a/media/java/android/media/ImageReader.java
+++ b/media/java/android/media/ImageReader.java
@@ -16,8 +16,12 @@
package android.media;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
import android.graphics.ImageFormat;
+import android.graphics.ImageFormat.Format;
import android.hardware.HardwareBuffer;
+import android.hardware.HardwareBuffer.Usage;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -120,7 +124,11 @@ public class ImageReader implements AutoCloseable {
* Must be greater than 0.
* @see Image
*/
- public static ImageReader newInstance(int width, int height, int format, int maxImages) {
+ public static @NonNull ImageReader newInstance(
+ @IntRange(from = 1) int width,
+ @IntRange(from = 1) int height,
+ @Format int format,
+ @IntRange(from = 1) int maxImages) {
// If the format is private don't default to USAGE_CPU_READ_OFTEN since it may not
// work, and is inscrutable anyway
return new ImageReader(width, height, format, maxImages,
@@ -210,8 +218,12 @@ public class ImageReader implements AutoCloseable {
* @see Image
* @see HardwareBuffer
*/
- public static ImageReader newInstance(int width, int height, int format, int maxImages,
- long usage) {
+ public static @NonNull ImageReader newInstance(
+ @IntRange(from = 1) int width,
+ @IntRange(from = 1) int height,
+ @Format int format,
+ @IntRange(from = 1) int maxImages,
+ @Usage long usage) {
// TODO: Check this - can't do it just yet because format support is different
// Unify formats! The only reliable way to validate usage is to just try it and see.
diff --git a/media/java/android/media/ImageWriter.java b/media/java/android/media/ImageWriter.java
index dd09afc3ddb0..f813d1b68419 100644
--- a/media/java/android/media/ImageWriter.java
+++ b/media/java/android/media/ImageWriter.java
@@ -16,7 +16,10 @@
package android.media;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
import android.graphics.ImageFormat;
+import android.graphics.ImageFormat.Format;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.hardware.camera2.utils.SurfaceUtils;
@@ -124,7 +127,8 @@ public class ImageWriter implements AutoCloseable {
* {@link #dequeueInputImage()}.
* @return a new ImageWriter instance.
*/
- public static ImageWriter newInstance(Surface surface, int maxImages) {
+ public static @NonNull ImageWriter newInstance(@NonNull Surface surface,
+ @IntRange(from = 1) int maxImages) {
return new ImageWriter(surface, maxImages, ImageFormat.UNKNOWN);
}
@@ -169,7 +173,8 @@ public class ImageWriter implements AutoCloseable {
*
* @return a new ImageWriter instance.
*/
- public static ImageWriter newInstance(Surface surface, int maxImages, int format) {
+ public static @NonNull ImageWriter newInstance(@NonNull Surface surface,
+ @IntRange(from = 1) int maxImages, @Format int format) {
if (!ImageFormat.isPublicFormat(format) && !PixelFormat.isPublicFormat(format)) {
throw new IllegalArgumentException("Invalid format is specified: " + format);
}
diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java
index cf5711d73278..a9e33fd8e472 100644
--- a/media/java/android/media/MediaCas.java
+++ b/media/java/android/media/MediaCas.java
@@ -19,9 +19,9 @@ package android.media;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.hardware.cas.V1_0.HidlCasPluginDescriptor;
-import android.hardware.cas.V1_1.ICas;
+import android.hardware.cas.V1_0.ICas;
+import android.hardware.cas.V1_0.IMediaCasService;
import android.hardware.cas.V1_1.ICasListener;
-import android.hardware.cas.V1_1.IMediaCasService;
import android.media.MediaCasException.*;
import android.os.Bundle;
import android.os.Handler;
@@ -99,23 +99,35 @@ import java.util.ArrayList;
public final class MediaCas implements AutoCloseable {
private static final String TAG = "MediaCas";
private ICas mICas;
+ private android.hardware.cas.V1_1.ICas mICasV11;
private EventListener mListener;
private HandlerThread mHandlerThread;
private EventHandler mEventHandler;
- private static final Singleton<IMediaCasService> gDefault =
- new Singleton<IMediaCasService>() {
+ private static final Singleton<IMediaCasService> sService = new Singleton<IMediaCasService>() {
@Override
protected IMediaCasService create() {
try {
- return IMediaCasService.getService(true /*wait*/);
- } catch (RemoteException e) {}
+ Log.d(TAG, "Tried to get cas@1.1 service");
+ android.hardware.cas.V1_1.IMediaCasService serviceV11 =
+ android.hardware.cas.V1_1.IMediaCasService.getService(true /*wait*/);
+ if (serviceV11 != null) {
+ return serviceV11;
+ }
+ } catch (Exception eV1_1) {
+ try {
+ Log.d(TAG, "Tried to get cas@1.0 service");
+ return IMediaCasService.getService(true /*wait*/);
+ } catch (Exception eV1_0) {
+ Log.d(TAG, "Failed to get cas@1.0 service");
+ }
+ }
return null;
}
};
static IMediaCasService getService() {
- return gDefault.get();
+ return sService.get();
}
private void validateInternalStates() {
@@ -126,11 +138,12 @@ public final class MediaCas implements AutoCloseable {
private void cleanupAndRethrowIllegalState() {
mICas = null;
+ mICasV11 = null;
throw new IllegalStateException();
}
- private class EventHandler extends Handler
- {
+ private class EventHandler extends Handler {
+
private static final int MSG_CAS_EVENT = 0;
private static final int MSG_CAS_SESSION_EVENT = 1;
private static final String SESSION_KEY = "sessionId";
@@ -164,7 +177,7 @@ public final class MediaCas implements AutoCloseable {
}
@Override
public void onSessionEvent(@NonNull ArrayList<Byte> sessionId,
- int event, int arg, @Nullable ArrayList<Byte> data)
+ int event, int arg, @Nullable ArrayList<Byte> data)
throws RemoteException {
Message msg = mEventHandler.obtainMessage();
msg.what = EventHandler.MSG_CAS_SESSION_EVENT;
@@ -177,7 +190,6 @@ public final class MediaCas implements AutoCloseable {
mEventHandler.sendMessage(msg);
}
};
-
/**
* Describe a CAS plugin with its CA_system_ID and string name.
*
@@ -338,9 +350,14 @@ public final class MediaCas implements AutoCloseable {
throws MediaCasException {
validateInternalStates();
+ if (mICasV11 == null) {
+ Log.d(TAG, "Send Session Event isn't supported by cas@1.0 interface");
+ throw new UnsupportedCasException("Send Session Event is not supported");
+ }
+
try {
MediaCasException.throwExceptionIfNeeded(
- mICas.sendSessionEvent(mSessionId, event, arg, toByteArray(data)));
+ mICasV11.sendSessionEvent(mSessionId, event, arg, toByteArray(data)));
} catch (RemoteException e) {
cleanupAndRethrowIllegalState();
}
@@ -427,7 +444,16 @@ public final class MediaCas implements AutoCloseable {
*/
public MediaCas(int CA_system_id) throws UnsupportedCasException {
try {
- mICas = getService().createPluginExt(CA_system_id, mBinder);
+ IMediaCasService service = getService();
+ android.hardware.cas.V1_1.IMediaCasService serviceV11 =
+ android.hardware.cas.V1_1.IMediaCasService.castFrom(service);
+ if (serviceV11 == null) {
+ Log.d(TAG, "Used cas@1_0 interface to create plugin");
+ mICas = service.createPlugin(CA_system_id, mBinder);
+ } else {
+ Log.d(TAG, "Used cas@1.1 interface to create plugin");
+ mICas = mICasV11 = serviceV11.createPluginExt(CA_system_id, mBinder);
+ }
} catch(Exception e) {
Log.e(TAG, "Failed to create plugin: " + e);
mICas = null;
@@ -528,7 +554,7 @@ public final class MediaCas implements AutoCloseable {
}
}
- private class OpenSessionCallback implements ICas.openSessionCallback {
+ private class OpenSessionCallback implements android.hardware.cas.V1_1.ICas.openSessionCallback{
public Session mSession;
public int mStatus;
@Override
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index e4d356b48f6d..08ce9fc87918 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -2645,6 +2645,7 @@ public class MediaPlayer extends PlayerBase
*/
private synchronized void setSubtitleAnchor() {
if ((mSubtitleController == null) && (ActivityThread.currentApplication() != null)) {
+ getMediaTimeProvider();
final HandlerThread thread = new HandlerThread("SetSubtitleAnchorThread");
thread.start();
Handler handler = new Handler(thread.getLooper());
@@ -2660,7 +2661,7 @@ public class MediaPlayer extends PlayerBase
@Override
public Looper getSubtitleLooper() {
- return Looper.getMainLooper();
+ return mTimeProvider.mEventHandler.getLooper();
}
});
thread.getLooper().quitSafely();
diff --git a/media/java/android/media/audiopolicy/AudioMix.java b/media/java/android/media/audiopolicy/AudioMix.java
index 761b62588e5a..6fd6298adb7d 100644
--- a/media/java/android/media/audiopolicy/AudioMix.java
+++ b/media/java/android/media/audiopolicy/AudioMix.java
@@ -133,7 +133,8 @@ public class AudioMix {
}
- int getRouteFlags() {
+ /** @hide */
+ public int getRouteFlags() {
return mRouteFlags;
}
diff --git a/media/java/android/media/audiopolicy/AudioPolicy.java b/media/java/android/media/audiopolicy/AudioPolicy.java
index 65f3294800f5..445edd1da8f1 100644
--- a/media/java/android/media/audiopolicy/AudioPolicy.java
+++ b/media/java/android/media/audiopolicy/AudioPolicy.java
@@ -18,7 +18,9 @@ package android.media.audiopolicy;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
+import android.app.ActivityManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.media.AudioAttributes;
@@ -30,6 +32,7 @@ import android.media.AudioRecord;
import android.media.AudioTrack;
import android.media.IAudioService;
import android.media.MediaRecorder;
+import android.media.projection.MediaProjection;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -93,6 +96,8 @@ public class AudioPolicy {
private AudioPolicyConfig mConfig;
+ private final MediaProjection mProjection;
+
/** @hide */
public AudioPolicyConfig getConfig() { return mConfig; }
/** @hide */
@@ -101,13 +106,17 @@ public class AudioPolicy {
public boolean isFocusPolicy() { return mIsFocusPolicy; }
/** @hide */
public boolean isVolumeController() { return mVolCb != null; }
+ /** @hide */
+ public @Nullable MediaProjection getMediaProjection() {
+ return mProjection;
+ }
/**
* The parameter is guaranteed non-null through the Builder
*/
private AudioPolicy(AudioPolicyConfig config, Context context, Looper looper,
AudioPolicyFocusListener fl, AudioPolicyStatusListener sl, boolean isFocusPolicy,
- AudioPolicyVolumeCallback vc) {
+ AudioPolicyVolumeCallback vc, @Nullable MediaProjection projection) {
mConfig = config;
mStatus = POLICY_STATUS_UNREGISTERED;
mContext = context;
@@ -124,6 +133,7 @@ public class AudioPolicy {
mStatusListener = sl;
mIsFocusPolicy = isFocusPolicy;
mVolCb = vc;
+ mProjection = projection;
}
/**
@@ -138,6 +148,7 @@ public class AudioPolicy {
private AudioPolicyStatusListener mStatusListener;
private boolean mIsFocusPolicy = false;
private AudioPolicyVolumeCallback mVolCb;
+ private MediaProjection mProjection;
/**
* Constructs a new Builder with no audio mixes.
@@ -222,6 +233,23 @@ public class AudioPolicy {
}
/**
+ * Set a media projection obtained through createMediaProjection().
+ *
+ * A MediaProjection that can project audio allows to register an audio
+ * policy LOOPBACK|RENDER without the MODIFY_AUDIO_ROUTING permission.
+ *
+ * @hide
+ */
+ public Builder setMediaProjection(@NonNull MediaProjection projection) {
+ if (projection == null) {
+ throw new IllegalArgumentException("Invalid null volume callback");
+ }
+ mProjection = projection;
+ return this;
+
+ }
+
+ /**
* Combines all of the attributes that have been set on this {@code Builder} and returns a
* new {@link AudioPolicy} object.
* @return a new {@code AudioPolicy} object.
@@ -241,7 +269,7 @@ public class AudioPolicy {
+ "an AudioPolicyFocusListener");
}
return new AudioPolicy(new AudioPolicyConfig(mMixes), mContext, mLooper,
- mFocusListener, mStatusListener, mIsFocusPolicy, mVolCb);
+ mFocusListener, mStatusListener, mIsFocusPolicy, mVolCb, mProjection);
}
}
@@ -417,24 +445,57 @@ public class AudioPolicy {
Log.e(TAG, "Cannot use unregistered AudioPolicy");
return false;
}
- if (mContext == null) {
- Log.e(TAG, "Cannot use AudioPolicy without context");
- return false;
- }
if (mRegistrationId == null) {
Log.e(TAG, "Cannot use unregistered AudioPolicy");
return false;
}
}
- if (!(PackageManager.PERMISSION_GRANTED == mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.MODIFY_AUDIO_ROUTING))) {
+
+ // Loopback|capture only need an audio projection, everything else need MODIFY_AUDIO_ROUTING
+ boolean canModifyAudioRouting = PackageManager.PERMISSION_GRANTED
+ == checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING);
+
+ boolean canProjectAudio;
+ try {
+ canProjectAudio = mProjection != null && mProjection.getProjection().canProjectAudio();
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to check if MediaProjection#canProjectAudio");
+ throw e.rethrowFromSystemServer();
+ }
+
+ if (!((isLoopbackRenderPolicy() && canProjectAudio) || canModifyAudioRouting)) {
Slog.w(TAG, "Cannot use AudioPolicy for pid " + Binder.getCallingPid() + " / uid "
- + Binder.getCallingUid() + ", needs MODIFY_AUDIO_ROUTING");
+ + Binder.getCallingUid() + ", needs MODIFY_AUDIO_ROUTING or "
+ + "MediaProjection that can project audio.");
return false;
}
return true;
}
+ private boolean isLoopbackRenderPolicy() {
+ synchronized (mLock) {
+ return mConfig.mMixes.stream().allMatch(mix -> mix.getRouteFlags()
+ == (mix.ROUTE_FLAG_RENDER | mix.ROUTE_FLAG_LOOP_BACK));
+ }
+ }
+
+ /**
+ * Returns {@link PackageManager#PERMISSION_GRANTED} if the caller has the given permission.
+ */
+ private @PackageManager.PermissionResult int checkCallingOrSelfPermission(String permission) {
+ if (mContext != null) {
+ return mContext.checkCallingOrSelfPermission(permission);
+ }
+ Slog.v(TAG, "Null context, checking permission via ActivityManager");
+ int pid = Binder.getCallingPid();
+ int uid = Binder.getCallingUid();
+ try {
+ return ActivityManager.getService().checkPermission(permission, pid, uid);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
private void checkMixReadyToUse(AudioMix mix, boolean forTrack)
throws IllegalArgumentException{
if (mix == null) {
diff --git a/media/java/android/media/audiopolicy/AudioPolicyConfig.java b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
index f725cacf5f21..a56fd31fbaeb 100644
--- a/media/java/android/media/audiopolicy/AudioPolicyConfig.java
+++ b/media/java/android/media/audiopolicy/AudioPolicyConfig.java
@@ -18,8 +18,6 @@ package android.media.audiopolicy;
import android.annotation.NonNull;
import android.media.AudioFormat;
-import android.media.AudioManager;
-import android.media.AudioPatch;
import android.media.audiopolicy.AudioMixingRule.AudioMixMatchCriterion;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/media/java/android/media/session/ControllerLink.java b/media/java/android/media/session/ControllerLink.java
index 40c716607697..5828fbdd1700 100644
--- a/media/java/android/media/session/ControllerLink.java
+++ b/media/java/android/media/session/ControllerLink.java
@@ -158,6 +158,18 @@ public final class ControllerLink implements Parcelable {
}
/**
+ * Gets the session info of the connected session.
+ */
+ @Nullable
+ Bundle getSessionInfo() {
+ try {
+ return mISessionController.getSessionInfo();
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
* Gets the {@link PendingIntent} for launching UI of the connected session.
*/
@Nullable
@@ -666,6 +678,12 @@ public final class ControllerLink implements Parcelable {
return null;
}
+ /** Stub method for ISessionController.getSessionInfo */
+ @Nullable
+ public Bundle getSessionInfo() {
+ return null;
+ }
+
/** Stub method for ISessionController.getLaunchPendingIntent */
@Nullable
public PendingIntent getLaunchPendingIntent() {
@@ -856,6 +874,11 @@ public final class ControllerLink implements Parcelable {
}
@Override
+ public Bundle getSessionInfo() {
+ return mControllerStub.getSessionInfo();
+ }
+
+ @Override
public PendingIntent getLaunchPendingIntent() {
return mControllerStub.getLaunchPendingIntent();
}
diff --git a/media/java/android/media/session/ISessionController.aidl b/media/java/android/media/session/ISessionController.aidl
index 3e7b4fbdebd3..298085f005da 100644
--- a/media/java/android/media/session/ISessionController.aidl
+++ b/media/java/android/media/session/ISessionController.aidl
@@ -44,6 +44,7 @@ interface ISessionController {
void unregisterCallback(in ControllerCallbackLink cb);
String getPackageName();
String getTag();
+ Bundle getSessionInfo();
PendingIntent getLaunchPendingIntent();
long getFlags();
MediaController.PlaybackInfo getVolumeAttributes();
diff --git a/media/java/android/media/session/ISessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
index 8143bfa00dc1..e85461f93731 100644
--- a/media/java/android/media/session/ISessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -35,7 +35,7 @@ import android.view.KeyEvent;
*/
interface ISessionManager {
SessionLink createSession(String packageName, in SessionCallbackLink sessionCb, String tag,
- int userId);
+ in Bundle sessionInfo, int userId);
void notifySession2Created(in Session2Token sessionToken);
List<MediaSession.Token> getSessions(in ComponentName compName, int userId);
List<Session2Token> getSession2Tokens(int userId);
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/MediaController.java
index 9e4199cba47a..fb21f69b2aca 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/MediaController.java
@@ -79,6 +79,7 @@ public final class MediaController {
private boolean mCbRegistered = false;
private String mPackageName;
private String mTag;
+ private Bundle mSessionInfo;
private final TransportControls mTransportControls;
@@ -410,6 +411,23 @@ public final class MediaController {
}
/**
+ * Gets the additional session information which was set when the session was created.
+ *
+ * @return The additional session information
+ */
+ @Nullable
+ public Bundle getSessionInfo() {
+ if (mSessionInfo == null) {
+ try {
+ mSessionInfo = mSessionBinder.getSessionInfo();
+ } catch (RuntimeException e) {
+ Log.d(TAG, "Dead object in getSessionInfo.", e);
+ }
+ }
+ return mSessionInfo;
+ }
+
+ /**
* Get the session's tag for debugging purposes.
*
* @return The session's tag.
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/MediaSession.java
index 8ab893b03a62..9fdefa62a35f 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/MediaSession.java
@@ -132,6 +132,27 @@ public final class MediaSession {
* @param tag A short name for debugging purposes.
*/
public MediaSession(@NonNull Context context, @NonNull String tag) {
+ this(context, tag, null);
+ }
+
+ /**
+ * Creates a new session. The session will automatically be registered with
+ * the system but will not be published until {@link #setActive(boolean)
+ * setActive(true)} is called. You must call {@link #release()} when
+ * finished with the session.
+ * <p>
+ * The {@code sessionInfo} can include additional unchanging information about this session.
+ * For example, it can include the version of the application, or the list of the custom
+ * commands that this session supports.
+ *
+ * @param context The context to use to create the session.
+ * @param tag A short name for debugging purposes.
+ * @param sessionInfo A bundle for additional information about this session.
+ * Controllers can get this information by calling
+ * {@link MediaController#getSessionInfo()}.
+ */
+ public MediaSession(@NonNull Context context, @NonNull String tag,
+ @Nullable Bundle sessionInfo) {
if (context == null) {
throw new IllegalArgumentException("context cannot be null.");
}
@@ -142,7 +163,7 @@ public final class MediaSession {
.getSystemService(Context.MEDIA_SESSION_SERVICE);
try {
SessionCallbackLink cbLink = new SessionCallbackLink(context);
- SessionLink sessionLink = manager.createSession(cbLink, tag);
+ SessionLink sessionLink = manager.createSession(cbLink, tag, sessionInfo);
mImpl = new MediaSessionEngine(context, sessionLink, cbLink);
mMaxBitmapSize = context.getResources().getDimensionPixelSize(
android.R.dimen.config_mediaMetadataBitmapMaxSize);
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/MediaSessionManager.java
index 46f6c71c5be0..fde4f8837fa5 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/MediaSessionManager.java
@@ -28,6 +28,7 @@ import android.media.AudioManager;
import android.media.IRemoteVolumeController;
import android.media.MediaSession2;
import android.media.Session2Token;
+import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
@@ -101,13 +102,15 @@ public final class MediaSessionManager {
* Create a new session in the system and get the binder for it.
*
* @param tag A short name for debugging purposes.
+ * @param sessionInfo A bundle for additional information about this session.
* @return The binder object from the system
* @hide
*/
@NonNull
- public SessionLink createSession(@NonNull SessionCallbackLink cbStub, @NonNull String tag) {
+ public SessionLink createSession(@NonNull SessionCallbackLink cbStub, @NonNull String tag,
+ @Nullable Bundle sessionInfo) {
try {
- return mService.createSession(mContext.getPackageName(), cbStub, tag,
+ return mService.createSession(mContext.getPackageName(), cbStub, tag, sessionInfo,
UserHandle.myUserId());
} catch (RemoteException e) {
throw new RuntimeException(e);
diff --git a/packages/CarSystemUI/res/layout/car_navigation_bar.xml b/packages/CarSystemUI/res/layout/car_navigation_bar.xml
index e591ea90c112..93d2b67dcda2 100644
--- a/packages/CarSystemUI/res/layout/car_navigation_bar.xml
+++ b/packages/CarSystemUI/res/layout/car_navigation_bar.xml
@@ -81,9 +81,9 @@
<com.android.systemui.statusbar.car.CarFacetButton
android:id="@+id/phone_nav"
style="@style/NavigationBarButton"
- systemui:componentNames="com.android.car.dialer/.TelecomActivity"
systemui:icon="@drawable/car_ic_phone"
- systemui:intent="intent:#Intent;component=com.android.car.dialer/.TelecomActivity;launchFlags=0x14000000;end"
+ systemui:intent="intent:#Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;package=com.android.car.dialer;launchFlags=0x10000000;end"
+ systemui:packages="com.android.car.dialer"
systemui:selectedIcon="@drawable/car_ic_phone_selected"
systemui:useMoreIcon="false"
/>
diff --git a/packages/NetworkStack/Android.bp b/packages/NetworkStack/Android.bp
index b700bf324817..5f1f26d88171 100644
--- a/packages/NetworkStack/Android.bp
+++ b/packages/NetworkStack/Android.bp
@@ -28,6 +28,7 @@ java_library {
static_libs: [
"netd_aidl_interface-java",
"networkstack-aidl-interfaces-java",
+ "datastallprotosnano",
]
}
@@ -43,4 +44,4 @@ android_app {
jarjar_rules: "jarjar-rules-shared.txt",
manifest: "AndroidManifest.xml",
required: ["NetworkStackPermissionStub"],
-} \ No newline at end of file
+}
diff --git a/packages/NetworkStack/src/android/net/metrics/DataStallDetectionStats.java b/packages/NetworkStack/src/android/net/metrics/DataStallDetectionStats.java
new file mode 100644
index 000000000000..6ea1e3d49dd4
--- /dev/null
+++ b/packages/NetworkStack/src/android/net/metrics/DataStallDetectionStats.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.util.NetworkStackUtils;
+import android.net.wifi.WifiInfo;
+
+import com.android.internal.util.HexDump;
+import com.android.server.connectivity.nano.CellularData;
+import com.android.server.connectivity.nano.DataStallEventProto;
+import com.android.server.connectivity.nano.DnsEvent;
+import com.android.server.connectivity.nano.WifiData;
+
+import com.google.protobuf.nano.MessageNano;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Class to record the stats of detection level information for data stall.
+ *
+ * @hide
+ */
+public final class DataStallDetectionStats {
+ private static final int UNKNOWN_SIGNAL_STRENGTH = -1;
+ @NonNull
+ final byte[] mCellularInfo;
+ @NonNull
+ final byte[] mWifiInfo;
+ @NonNull
+ final byte[] mDns;
+ final int mEvaluationType;
+ final int mNetworkType;
+
+ public DataStallDetectionStats(@Nullable byte[] cell, @Nullable byte[] wifi,
+ @NonNull int[] returnCode, @NonNull long[] dnsTime, int evalType, int netType) {
+ mCellularInfo = emptyCellDataIfNull(cell);
+ mWifiInfo = emptyWifiInfoIfNull(wifi);
+
+ DnsEvent dns = new DnsEvent();
+ dns.dnsReturnCode = returnCode;
+ dns.dnsTime = dnsTime;
+ mDns = MessageNano.toByteArray(dns);
+ mEvaluationType = evalType;
+ mNetworkType = netType;
+ }
+
+ private byte[] emptyCellDataIfNull(@Nullable byte[] cell) {
+ if (cell != null) return cell;
+
+ CellularData data = new CellularData();
+ data.ratType = DataStallEventProto.RADIO_TECHNOLOGY_UNKNOWN;
+ data.networkMccmnc = "";
+ data.simMccmnc = "";
+ data.signalStrength = UNKNOWN_SIGNAL_STRENGTH;
+ return MessageNano.toByteArray(data);
+ }
+
+ private byte[] emptyWifiInfoIfNull(@Nullable byte[] wifi) {
+ if (wifi != null) return wifi;
+
+ WifiData data = new WifiData();
+ data.wifiBand = DataStallEventProto.AP_BAND_UNKNOWN;
+ data.signalStrength = UNKNOWN_SIGNAL_STRENGTH;
+ return MessageNano.toByteArray(data);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("type: ").append(mNetworkType)
+ .append(", evaluation type: ")
+ .append(mEvaluationType)
+ .append(", wifi info: ")
+ .append(HexDump.toHexString(mWifiInfo))
+ .append(", cell info: ")
+ .append(HexDump.toHexString(mCellularInfo))
+ .append(", dns: ")
+ .append(HexDump.toHexString(mDns));
+ return sb.toString();
+ }
+
+ /**
+ * Utility to create an instance of {@Link DataStallDetectionStats}
+ *
+ * @hide
+ */
+ public static class Builder {
+ @Nullable
+ private byte[] mCellularInfo;
+ @Nullable
+ private byte[] mWifiInfo;
+ @NonNull
+ private final List<Integer> mDnsReturnCode = new ArrayList<Integer>();
+ @NonNull
+ private final List<Long> mDnsTimeStamp = new ArrayList<Long>();
+ private int mEvaluationType;
+ private int mNetworkType;
+
+ /**
+ * Add a dns event into Builder.
+ *
+ * @param code the return code of the dns event.
+ * @param timeMs the elapsedRealtime in ms that the the dns event was received from netd.
+ * @return {@code this} {@link Builder} instance.
+ */
+ public Builder addDnsEvent(int code, long timeMs) {
+ mDnsReturnCode.add(code);
+ mDnsTimeStamp.add(timeMs);
+ return this;
+ }
+
+ /**
+ * Set the dns evaluation type into Builder.
+ *
+ * @param type the return code of the dns event.
+ * @return {@code this} {@link Builder} instance.
+ */
+ public Builder setEvaluationType(int type) {
+ mEvaluationType = type;
+ return this;
+ }
+
+ /**
+ * Set the network type into Builder.
+ *
+ * @param type the network type of the logged network.
+ * @return {@code this} {@link Builder} instance.
+ */
+ public Builder setNetworkType(int type) {
+ mNetworkType = type;
+ return this;
+ }
+
+ /**
+ * Set the wifi data into Builder.
+ *
+ * @param info a {@link WifiInfo} of the connected wifi network.
+ * @return {@code this} {@link Builder} instance.
+ */
+ public Builder setWiFiData(@Nullable final WifiInfo info) {
+ WifiData data = new WifiData();
+ data.wifiBand = getWifiBand(info);
+ data.signalStrength = (info != null) ? info.getRssi() : UNKNOWN_SIGNAL_STRENGTH;
+ mWifiInfo = MessageNano.toByteArray(data);
+ return this;
+ }
+
+ private static int getWifiBand(@Nullable final WifiInfo info) {
+ if (info != null) {
+ int freq = info.getFrequency();
+ // Refer to ScanResult.is5GHz() and ScanResult.is24GHz().
+ if (freq > 4900 && freq < 5900) {
+ return DataStallEventProto.AP_BAND_5GHZ;
+ } else if (freq > 2400 && freq < 2500) {
+ return DataStallEventProto.AP_BAND_2GHZ;
+ }
+ }
+ return DataStallEventProto.AP_BAND_UNKNOWN;
+ }
+
+ /**
+ * Set the cellular data into Builder.
+ *
+ * @param radioType the radio technology of the logged cellular network.
+ * @param roaming a boolean indicates if logged cellular network is roaming or not.
+ * @param networkMccmnc the mccmnc of the camped network.
+ * @param simMccmnc the mccmnc of the sim.
+ * @return {@code this} {@link Builder} instance.
+ */
+ public Builder setCellData(int radioType, boolean roaming,
+ @NonNull String networkMccmnc, @NonNull String simMccmnc, int ss) {
+ CellularData data = new CellularData();
+ data.ratType = radioType;
+ data.isRoaming = roaming;
+ data.networkMccmnc = networkMccmnc;
+ data.simMccmnc = simMccmnc;
+ data.signalStrength = ss;
+ mCellularInfo = MessageNano.toByteArray(data);
+ return this;
+ }
+
+ /**
+ * Create a new {@Link DataStallDetectionStats}.
+ */
+ public DataStallDetectionStats build() {
+ return new DataStallDetectionStats(mCellularInfo, mWifiInfo,
+ NetworkStackUtils.convertToIntArray(mDnsReturnCode),
+ NetworkStackUtils.convertToLongArray(mDnsTimeStamp),
+ mEvaluationType, mNetworkType);
+ }
+ }
+}
diff --git a/packages/NetworkStack/src/android/net/metrics/DataStallStatsUtils.java b/packages/NetworkStack/src/android/net/metrics/DataStallStatsUtils.java
new file mode 100644
index 000000000000..17a36ad4e6d2
--- /dev/null
+++ b/packages/NetworkStack/src/android/net/metrics/DataStallStatsUtils.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net.metrics;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.net.captiveportal.CaptivePortalProbeResult;
+import android.util.Log;
+
+import com.android.internal.util.HexDump;
+import com.android.server.connectivity.nano.DataStallEventProto;
+
+/**
+ * Collection of utilities for data stall metrics.
+ *
+ * To see if the logs are properly sent to statsd, execute following command.
+ *
+ * $ adb shell cmd stats print-logs
+ * $ adb logcat | grep statsd OR $ adb logcat -b stats
+ *
+ * @hide
+ */
+public class DataStallStatsUtils {
+ private static final String TAG = DataStallStatsUtils.class.getSimpleName();
+ private static final boolean DBG = false;
+
+ private static int probeResultToEnum(@Nullable final CaptivePortalProbeResult result) {
+ if (result == null) return DataStallEventProto.INVALID;
+
+ // TODO: Add partial connectivity support.
+ if (result.isSuccessful()) {
+ return DataStallEventProto.VALID;
+ } else if (result.isPortal()) {
+ return DataStallEventProto.PORTAL;
+ } else {
+ return DataStallEventProto.INVALID;
+ }
+ }
+
+ /**
+ * Write the metric to {@link StatsLog}.
+ */
+ public static void write(@NonNull final DataStallDetectionStats stats,
+ @NonNull final CaptivePortalProbeResult result) {
+ int validationResult = probeResultToEnum(result);
+ if (DBG) {
+ Log.d(TAG, "write: " + stats + " with result: " + validationResult
+ + ", dns: " + HexDump.toHexString(stats.mDns));
+ }
+ // TODO(b/124613085): Send to Statsd once the public StatsLog API is ready.
+ }
+}
diff --git a/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java b/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java
index 98123a5c7261..481dbdadbac0 100644
--- a/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java
+++ b/packages/NetworkStack/src/android/net/util/NetworkStackUtils.java
@@ -16,8 +16,11 @@
package android.net.util;
+import android.annotation.NonNull;
+
import java.io.FileDescriptor;
import java.io.IOException;
+import java.util.List;
/**
* Collection of utilities for the network stack.
@@ -40,4 +43,26 @@ public class NetworkStackUtils {
} catch (IOException ignored) {
}
}
+
+ /**
+ * Returns an int array from the given Integer list.
+ */
+ public static int[] convertToIntArray(@NonNull List<Integer> list) {
+ int[] array = new int[list.size()];
+ for (int i = 0; i < list.size(); i++) {
+ array[i] = list.get(i);
+ }
+ return array;
+ }
+
+ /**
+ * Returns a long array from the given long list.
+ */
+ public static long[] convertToLongArray(@NonNull List<Long> list) {
+ long[] array = new long[list.size()];
+ for (int i = 0; i < list.size(); i++) {
+ array[i] = list.get(i);
+ }
+ return array;
+ }
}
diff --git a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
index 4b846b0fb372..3c129ce81b65 100644
--- a/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/packages/NetworkStack/src/com/android/server/connectivity/NetworkMonitor.java
@@ -33,6 +33,7 @@ import static android.net.metrics.ValidationProbeEvent.PROBE_FALLBACK;
import static android.net.metrics.ValidationProbeEvent.PROBE_PRIVDNS;
import static android.net.util.NetworkStackUtils.isEmpty;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
@@ -50,6 +51,8 @@ import android.net.TrafficStats;
import android.net.Uri;
import android.net.captiveportal.CaptivePortalProbeResult;
import android.net.captiveportal.CaptivePortalProbeSpec;
+import android.net.metrics.DataStallDetectionStats;
+import android.net.metrics.DataStallStatsUtils;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.NetworkEvent;
import android.net.metrics.ValidationProbeEvent;
@@ -66,8 +69,10 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.provider.Settings;
import android.telephony.AccessNetworkConstants;
+import android.telephony.CellSignalStrength;
import android.telephony.NetworkRegistrationState;
import android.telephony.ServiceState;
+import android.telephony.SignalStrength;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
@@ -126,6 +131,9 @@ public class NetworkMonitor extends StateMachine {
private static final int DATA_STALL_EVALUATION_TYPE_DNS = 1;
private static final int DEFAULT_DATA_STALL_EVALUATION_TYPES =
(1 << DATA_STALL_EVALUATION_TYPE_DNS);
+ // Reevaluate it as intending to increase the number. Larger log size may cause statsd
+ // log buffer bust and have stats log lost.
+ private static final int DEFAULT_DNS_LOG_SIZE = 20;
enum EvaluationResult {
VALIDATED(true),
@@ -244,6 +252,7 @@ public class NetworkMonitor extends StateMachine {
private final ConnectivityManager mCm;
private final IpConnectivityLog mMetricsLog;
private final Dependencies mDependencies;
+ private final DataStallStatsUtils mDetectionStatsUtils;
// Configuration values for captive portal detection probes.
private final String mCaptivePortalUserAgent;
@@ -302,17 +311,19 @@ public class NetworkMonitor extends StateMachine {
private final int mDataStallEvaluationType;
private final DnsStallDetector mDnsStallDetector;
private long mLastProbeTime;
+ // Set to true if data stall is suspected and reset to false after metrics are sent to statsd.
+ private boolean mCollectDataStallMetrics = false;
public NetworkMonitor(Context context, INetworkMonitorCallbacks cb, Network network,
SharedLog validationLog) {
this(context, cb, network, new IpConnectivityLog(), validationLog,
- Dependencies.DEFAULT);
+ Dependencies.DEFAULT, new DataStallStatsUtils());
}
@VisibleForTesting
protected NetworkMonitor(Context context, INetworkMonitorCallbacks cb, Network network,
IpConnectivityLog logger, SharedLog validationLogs,
- Dependencies deps) {
+ Dependencies deps, DataStallStatsUtils detectionStatsUtils) {
// Add suffix indicating which NetworkMonitor we're talking about.
super(TAG + "/" + network.toString());
@@ -325,6 +336,7 @@ public class NetworkMonitor extends StateMachine {
mValidationLogs = validationLogs;
mCallback = cb;
mDependencies = deps;
+ mDetectionStatsUtils = detectionStatsUtils;
mNonPrivateDnsBypassNetwork = network;
mNetwork = deps.getPrivateDnsBypassNetwork(network);
mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
@@ -656,6 +668,7 @@ public class NetworkMonitor extends StateMachine {
case EVENT_DNS_NOTIFICATION:
mDnsStallDetector.accumulateConsecutiveDnsTimeoutCount(message.arg1);
if (isDataStall()) {
+ mCollectDataStallMetrics = true;
validationLog("Suspecting data stall, reevaluate");
transitionTo(mEvaluatingState);
}
@@ -667,6 +680,65 @@ public class NetworkMonitor extends StateMachine {
}
}
+ private void writeDataStallStats(@NonNull final CaptivePortalProbeResult result) {
+ /*
+ * Collect data stall detection level information for each transport type. Collect type
+ * specific information for cellular and wifi only currently. Generate
+ * DataStallDetectionStats for each transport type. E.g., if a network supports both
+ * TRANSPORT_WIFI and TRANSPORT_VPN, two DataStallDetectionStats will be generated.
+ */
+ final int[] transports = mNetworkCapabilities.getTransportTypes();
+
+ for (int i = 0; i < transports.length; i++) {
+ DataStallStatsUtils.write(buildDataStallDetectionStats(transports[i]), result);
+ }
+ mCollectDataStallMetrics = false;
+ }
+
+ @VisibleForTesting
+ protected DataStallDetectionStats buildDataStallDetectionStats(int transport) {
+ final DataStallDetectionStats.Builder stats = new DataStallDetectionStats.Builder();
+ if (VDBG_STALL) log("collectDataStallMetrics: type=" + transport);
+ stats.setEvaluationType(DATA_STALL_EVALUATION_TYPE_DNS);
+ stats.setNetworkType(transport);
+ switch (transport) {
+ case NetworkCapabilities.TRANSPORT_WIFI:
+ // TODO: Update it if status query in dual wifi is supported.
+ final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+ stats.setWiFiData(wifiInfo);
+ break;
+ case NetworkCapabilities.TRANSPORT_CELLULAR:
+ final boolean isRoaming = !mNetworkCapabilities.hasCapability(
+ NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING);
+ final SignalStrength ss = mTelephonyManager.getSignalStrength();
+ // TODO(b/120452078): Support multi-sim.
+ stats.setCellData(
+ mTelephonyManager.getDataNetworkType(),
+ isRoaming,
+ mTelephonyManager.getNetworkOperator(),
+ mTelephonyManager.getSimOperator(),
+ (ss != null)
+ ? ss.getLevel() : CellSignalStrength.SIGNAL_STRENGTH_NONE_OR_UNKNOWN);
+ break;
+ default:
+ // No transport type specific information for the other types.
+ break;
+ }
+ addDnsEvents(stats);
+
+ return stats.build();
+ }
+
+ private void addDnsEvents(@NonNull final DataStallDetectionStats.Builder stats) {
+ final int size = mDnsStallDetector.mResultIndices.size();
+ for (int i = 1; i <= DEFAULT_DNS_LOG_SIZE && i <= size; i++) {
+ final int index = mDnsStallDetector.mResultIndices.indexOf(size - i);
+ stats.addDnsEvent(mDnsStallDetector.mDnsEvents[index].mReturnCode,
+ mDnsStallDetector.mDnsEvents[index].mTimeStamp);
+ }
+ }
+
+
// Being in the MaybeNotifyState State indicates the user may have been notified that sign-in
// is required. This State takes care to clear the notification upon exit from the State.
private class MaybeNotifyState extends State {
@@ -972,6 +1044,11 @@ public class NetworkMonitor extends StateMachine {
final CaptivePortalProbeResult probeResult =
(CaptivePortalProbeResult) message.obj;
mLastProbeTime = SystemClock.elapsedRealtime();
+
+ if (mCollectDataStallMetrics) {
+ writeDataStallStats(probeResult);
+ }
+
if (probeResult.isSuccessful()) {
// Transit EvaluatingPrivateDnsState to get to Validated
// state (even if no Private DNS validation required).
@@ -1617,7 +1694,6 @@ public class NetworkMonitor extends StateMachine {
*/
@VisibleForTesting
protected class DnsStallDetector {
- private static final int DEFAULT_DNS_LOG_SIZE = 50;
private int mConsecutiveTimeoutCount = 0;
private int mSize;
final DnsResult[] mDnsEvents;
diff --git a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
index 9a16bb77182e..beb975d745c2 100644
--- a/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
+++ b/packages/NetworkStack/tests/src/com/android/server/connectivity/NetworkMonitorTest.java
@@ -30,6 +30,7 @@ import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyObject;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
@@ -48,6 +49,7 @@ import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.net.captiveportal.CaptivePortalProbeResult;
+import android.net.metrics.DataStallStatsUtils;
import android.net.metrics.IpConnectivityLog;
import android.net.util.SharedLog;
import android.net.wifi.WifiManager;
@@ -98,6 +100,7 @@ public class NetworkMonitorTest {
private @Mock NetworkMonitor.Dependencies mDependencies;
private @Mock INetworkMonitorCallbacks mCallbacks;
private @Spy Network mNetwork = new Network(TEST_NETID);
+ private @Mock DataStallStatsUtils mDataStallStatsUtils;
private static final int TEST_NETID = 4242;
@@ -186,9 +189,9 @@ public class NetworkMonitorTest {
private long mProbeTime = 0;
WrappedNetworkMonitor(Context context, Network network, IpConnectivityLog logger,
- Dependencies deps) {
+ Dependencies deps, DataStallStatsUtils statsUtils) {
super(context, mCallbacks, network, logger,
- new SharedLog("test_nm"), deps);
+ new SharedLog("test_nm"), deps, statsUtils);
}
@Override
@@ -203,7 +206,7 @@ public class NetworkMonitorTest {
private WrappedNetworkMonitor makeMeteredWrappedNetworkMonitor() {
final WrappedNetworkMonitor nm = new WrappedNetworkMonitor(
- mContext, mNetwork, mLogger, mDependencies);
+ mContext, mNetwork, mLogger, mDependencies, mDataStallStatsUtils);
when(mCm.getNetworkCapabilities(any())).thenReturn(METERED_CAPABILITIES);
nm.start();
waitForIdle(nm.getHandler());
@@ -212,7 +215,7 @@ public class NetworkMonitorTest {
private WrappedNetworkMonitor makeNotMeteredWrappedNetworkMonitor() {
final WrappedNetworkMonitor nm = new WrappedNetworkMonitor(
- mContext, mNetwork, mLogger, mDependencies);
+ mContext, mNetwork, mLogger, mDependencies, mDataStallStatsUtils);
when(mCm.getNetworkCapabilities(any())).thenReturn(NOT_METERED_CAPABILITIES);
nm.start();
waitForIdle(nm.getHandler());
@@ -222,7 +225,7 @@ public class NetworkMonitorTest {
private NetworkMonitor makeMonitor() {
final NetworkMonitor nm = new NetworkMonitor(
mContext, mCallbacks, mNetwork, mLogger, mValidationLogger,
- mDependencies);
+ mDependencies, mDataStallStatsUtils);
nm.start();
waitForIdle(nm.getHandler());
return nm;
@@ -505,6 +508,23 @@ public class NetworkMonitorTest {
.notifyNetworkTested(NETWORK_TEST_RESULT_VALID, null);
}
+ @Test
+ public void testDataStall_StallSuspectedAndSendMetrics() throws IOException {
+ WrappedNetworkMonitor wrappedMonitor = makeNotMeteredWrappedNetworkMonitor();
+ wrappedMonitor.setLastProbeTime(SystemClock.elapsedRealtime() - 1000);
+ makeDnsTimeoutEvent(wrappedMonitor, 5);
+ assertTrue(wrappedMonitor.isDataStall());
+ verify(mDataStallStatsUtils, times(1)).write(eq(anyObject()), eq(anyObject()));
+ }
+
+ @Test
+ public void testDataStall_NoStallSuspectedAndSendMetrics() throws IOException {
+ WrappedNetworkMonitor wrappedMonitor = makeNotMeteredWrappedNetworkMonitor();
+ wrappedMonitor.setLastProbeTime(SystemClock.elapsedRealtime() - 1000);
+ makeDnsTimeoutEvent(wrappedMonitor, 3);
+ assertFalse(wrappedMonitor.isDataStall());
+ verify(mDataStallStatsUtils, times(0)).write(eq(anyObject()), eq(anyObject()));
+ }
private void makeDnsTimeoutEvent(WrappedNetworkMonitor wrappedMonitor, int count) {
for (int i = 0; i < count; i++) {
wrappedMonitor.getDnsStallDetector().accumulateConsecutiveDnsTimeoutCount(
diff --git a/packages/OsuLogin/src/com/android/hotspot2/osu/OsuLoginActivity.java b/packages/OsuLogin/src/com/android/hotspot2/osu/OsuLoginActivity.java
index 28b05396acce..82e33cc4aff9 100644
--- a/packages/OsuLogin/src/com/android/hotspot2/osu/OsuLoginActivity.java
+++ b/packages/OsuLogin/src/com/android/hotspot2/osu/OsuLoginActivity.java
@@ -46,8 +46,6 @@ import com.android.hotspot2.R;
import java.net.MalformedURLException;
import java.net.URL;
-
-
/**
* Online Sign Up Login Web View launched during Provision Process of Hotspot 2.0 rel2.
*/
@@ -64,6 +62,7 @@ public class OsuLoginActivity extends Activity {
private WebView mWebView;
private SwipeRefreshLayout mSwipeRefreshLayout;
private ProgressBar mProgressBar;
+ private boolean mForceDisconnect = true;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
@@ -141,6 +140,7 @@ public class OsuLoginActivity extends Activity {
if (DBG) {
Log.d(TAG, "Lost for the current Network, close the browser");
}
+ mForceDisconnect = false; // It is already disconnected.
if (mNetwork.equals(network)) {
finishAndRemoveTask();
}
@@ -193,12 +193,6 @@ public class OsuLoginActivity extends Activity {
mWebView.goBack();
return true;
}
-
- // In case of back key, it needs to disconnect current connection with OSU AP to
- // abort current Provisioning flow.
- if (mWifiManager != null) {
- mWifiManager.disconnect();
- }
}
return super.onKeyDown(keyCode, event);
}
@@ -207,6 +201,11 @@ public class OsuLoginActivity extends Activity {
protected void onDestroy() {
if (mNetworkCallback != null) {
mCm.unregisterNetworkCallback(mNetworkCallback);
+ mNetworkCallback = null;
+ }
+ if (mWifiManager != null && mForceDisconnect) {
+ mWifiManager.disconnect();
+ mWifiManager = null;
}
super.onDestroy();
}
@@ -232,6 +231,7 @@ public class OsuLoginActivity extends Activity {
private class OsuWebViewClient extends WebViewClient {
boolean mPageError = false;
+ boolean mRedirectResponseReceived = false;
@Override
public void onPageStarted(WebView view, String urlString, Bitmap favicon) {
@@ -247,6 +247,10 @@ public class OsuLoginActivity extends Activity {
// Do not show the page error on UI.
if (mPageError) {
+ if (mRedirectResponseReceived) {
+ // Do not disconnect current connection while provisioning is in progress.
+ mForceDisconnect = false;
+ }
finishAndRemoveTask();
}
}
@@ -255,6 +259,7 @@ public class OsuLoginActivity extends Activity {
public void onReceivedError(WebView view, WebResourceRequest request,
WebResourceError error) {
if (request.getUrl().toString().startsWith("http://127.0.0.1")) {
+ mRedirectResponseReceived = true;
view.stopLoading();
}
@@ -266,5 +271,4 @@ public class OsuLoginActivity extends Activity {
}
}
}
-
}
diff --git a/packages/SettingsLib/EntityHeaderWidgets/src/com/android/settingslib/widget/AppEntitiesHeaderController.java b/packages/SettingsLib/EntityHeaderWidgets/src/com/android/settingslib/widget/AppEntitiesHeaderController.java
index 330049fc6673..6e95a0ed106a 100644
--- a/packages/SettingsLib/EntityHeaderWidgets/src/com/android/settingslib/widget/AppEntitiesHeaderController.java
+++ b/packages/SettingsLib/EntityHeaderWidgets/src/com/android/settingslib/widget/AppEntitiesHeaderController.java
@@ -90,6 +90,7 @@ public class AppEntitiesHeaderController {
private int mHeaderTitleRes;
private int mHeaderDetailsRes;
private int mHeaderEmptyRes;
+ private CharSequence mHeaderDetails;
private View.OnClickListener mDetailsOnClickListener;
/**
@@ -148,6 +149,14 @@ public class AppEntitiesHeaderController {
}
/**
+ * Set the text for app entities header details.
+ */
+ public AppEntitiesHeaderController setHeaderDetails(CharSequence detailsText) {
+ mHeaderDetails = detailsText;
+ return this;
+ }
+
+ /**
* Register a callback to be invoked when header details view is clicked.
*/
public AppEntitiesHeaderController setHeaderDetailsClickListener(
@@ -232,11 +241,13 @@ public class AppEntitiesHeaderController {
}
private void bindHeaderDetailsView() {
- CharSequence detailsText = "";
- try {
- detailsText = mContext.getText(mHeaderDetailsRes);
- } catch (Resources.NotFoundException e) {
- Log.e(TAG, "Resource of header details can't not be found!", e);
+ CharSequence detailsText = mHeaderDetails;
+ if (TextUtils.isEmpty(detailsText)) {
+ try {
+ detailsText = mContext.getText(mHeaderDetailsRes);
+ } catch (Resources.NotFoundException e) {
+ Log.e(TAG, "Resource of header details can't not be found!", e);
+ }
}
mHeaderDetailsView.setText(detailsText);
mHeaderDetailsView.setVisibility(
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index f865563200e1..68f1e6fb6f13 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -136,8 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"আঁতৰোৱা এপ্‌সমূহ"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"আঁতৰোৱা এপ্‌ আৰু ব্যৱহাৰকাৰীসমূহ"</string>
- <!-- no translation found for data_usage_ota (5377889154805560860) -->
- <skip />
+ <string name="data_usage_ota" msgid="5377889154805560860">"ছিষ্টেম আপডে’ট"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"ইউএছবি টেডাৰিং"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"প\'ৰ্টেবল হটস্পট"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ব্লুটুথ টেডাৰিং"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index ef8dd3de56a9..4f2913101c38 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -136,8 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"সরানো অ্যাপ্লিকেশানগুলি"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"সরানো অ্যাপ্লিকেশানগুলি এবং ব্যবহারকারীগণ"</string>
- <!-- no translation found for data_usage_ota (5377889154805560860) -->
- <skip />
+ <string name="data_usage_ota" msgid="5377889154805560860">"সিস্টেম আপডেট"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB টিথারিং"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"পোর্টেবল হটস্পট"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ব্লুটুথ টিথারিং"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 97b9036157a3..36e04bb5f2bf 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -136,8 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"દૂર કરેલી ઍપ્લિકેશનો"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"દૂર કરેલી ઍપ્લિકેશનો અને વપરાશકર્તાઓ"</string>
- <!-- no translation found for data_usage_ota (5377889154805560860) -->
- <skip />
+ <string name="data_usage_ota" msgid="5377889154805560860">"સિસ્ટમ અપડેટ"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ટિથરિંગ"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"પોર્ટેબલ હૉટસ્પૉટ"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"બ્લૂટૂથ ટિથરિંગ"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 6e37c9a6eeda..89d6361395eb 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -136,8 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"אפליקציות שהוסרו"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"אפליקציות ומשתמשים שהוסרו"</string>
- <!-- no translation found for data_usage_ota (5377889154805560860) -->
- <skip />
+ <string name="data_usage_ota" msgid="5377889154805560860">"עדכוני מערכת"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"‏שיתוף אינטרנט דרך USB"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"נקודה לשיתוף אינטרנט"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"‏שיתוף אינטרנט דרך Bluetooth"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 41b0fbda408f..1e9a0d51ee67 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -136,8 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"ತೆಗೆದುಹಾಕಲಾದ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"ಅಪ್ಲಿಕೇಶನ್‌ಗಳು ಮತ್ತು ಬಳಕೆದಾರರನ್ನು ತೆಗೆದುಹಾಕಲಾಗಿದೆ"</string>
- <!-- no translation found for data_usage_ota (5377889154805560860) -->
- <skip />
+ <string name="data_usage_ota" msgid="5377889154805560860">"ಸಿಸ್ಟಂ ಅಪ್‌ಡೇಟ್‌ಗಳು"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ಟೆಥರಿಂಗ್"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ಪೋರ್ಟಬಲ್ ಹಾಟ್‌ಸ್ಪಾಟ್"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ಬ್ಲೂಟೂತ್‌‌ ಟೆಥರಿಂಗ್‌"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 0292cabb73bf..ae97fb24f573 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -136,8 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"നീക്കംചെയ്‌ത അപ്ലിക്കേഷനുകൾ"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"നീക്കംചെയ്‌ത അപ്ലിക്കേഷനുകളും ഉപയോക്താക്കളും"</string>
- <!-- no translation found for data_usage_ota (5377889154805560860) -->
- <skip />
+ <string name="data_usage_ota" msgid="5377889154805560860">"സിസ്‌റ്റം അപ്‌ഡേറ്റുകൾ"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ടെതറിംഗ്"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"പോർട്ടബിൾ ഹോട്ട്സ്‌പോട്ട്"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ബ്ലൂടൂത്ത് ടെതറിംഗ്"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 0c2f0eefb0e7..88de8f43b888 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -136,8 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"काढलेले अॅप्स"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"काढलेले अॅप्स आणि वापरकर्ते"</string>
- <!-- no translation found for data_usage_ota (5377889154805560860) -->
- <skip />
+ <string name="data_usage_ota" msgid="5377889154805560860">"सिस्टम अपडेट"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB टेदरिंग"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"पोर्टेबल हॉटस्पॉट"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ब्लूटूथ टेदरिंग"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 7daf9564cc9b..ac15f1b55564 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -136,8 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"एन्ड्रोइड OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"हटाइएका अनुप्रयोगहरू"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"अनुप्रयोगहरू र प्रयोगकर्ताहरू हटाइयो।"</string>
- <!-- no translation found for data_usage_ota (5377889154805560860) -->
- <skip />
+ <string name="data_usage_ota" msgid="5377889154805560860">"प्रणालीसम्बन्धी अद्यावधिकहरू"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB टेथर गर्दै"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"पोर्टेबल हटस्पट"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ब्लुटुथ टेथर गर्दै"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index 54ddf845847e..847586e06cfc 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -136,8 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"କଢ଼ାଯାଇଥିବା ଆପ୍‌ଗୁଡ଼ିକ"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"ଆପ୍‌ ଏବଂ ଉପଯୋଗକର୍ତ୍ତା ବାହାର କରାଗଲା"</string>
- <!-- no translation found for data_usage_ota (5377889154805560860) -->
- <skip />
+ <string name="data_usage_ota" msgid="5377889154805560860">"ସିଷ୍ଟମ୍ ଅପ୍‌ଡେଟ୍"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ଟିଥରିଙ୍ଗ"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ପୋର୍ଟବଲ୍‌ ହଟସ୍ପଟ୍‌"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ବ୍ଲୁଟୂଥ ଟିଥରିଙ୍ଗ"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index dcf3e3cb46ec..0675b6be525e 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -136,8 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"ਹਟਾਏ ਗਏ ਐਪਸ"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"ਹਟਾਏ ਗਏ ਐਪਸ ਅਤੇ ਉਪਭੋਗਤਾ"</string>
- <!-- no translation found for data_usage_ota (5377889154805560860) -->
- <skip />
+ <string name="data_usage_ota" msgid="5377889154805560860">"ਸਿਸਟਮ ਅੱਪਡੇਟ"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB ਟੈਦਰਿੰਗ"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"ਪੋਰਟੇਬਲ ਹੌਟਸਪੌਟ"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"ਬਲੂਟੁੱਥ ਟੈਦਰਿੰਗ"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 71716cec6886..3cf43c844354 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -136,8 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"அகற்றப்பட்ட பயன்பாடுகள்"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"அகற்றப்பட்ட பயன்பாடுகள் மற்றும் பயனர்கள்"</string>
- <!-- no translation found for data_usage_ota (5377889154805560860) -->
- <skip />
+ <string name="data_usage_ota" msgid="5377889154805560860">"சிஸ்டம் புதுப்பிப்புகள்"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"USB டெதெரிங்"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"போர்ட்டபிள் ஹாட்ஸ்பாட்"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"புளூடூத் டெதெரிங்"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 65ed110d3c46..c22362927e31 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -136,8 +136,7 @@
<string name="process_kernel_label" msgid="3916858646836739323">"Android OS"</string>
<string name="data_usage_uninstalled_apps" msgid="614263770923231598">"ہٹائی گئی ایپس"</string>
<string name="data_usage_uninstalled_apps_users" msgid="7986294489899813194">"ہٹائی گئی ایپس اور صارفین"</string>
- <!-- no translation found for data_usage_ota (5377889154805560860) -->
- <skip />
+ <string name="data_usage_ota" msgid="5377889154805560860">"سسٹم اپ ڈیٹس"</string>
<string name="tether_settings_title_usb" msgid="6688416425801386511">"‏USB ٹیدرنگ"</string>
<string name="tether_settings_title_wifi" msgid="3277144155960302049">"پورٹیبل ہاٹ اسپاٹ"</string>
<string name="tether_settings_title_bluetooth" msgid="355855408317564420">"بلوٹوتھ ٹیدرنگ"</string>
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppEntitiesHeaderControllerTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppEntitiesHeaderControllerTest.java
index 63a958eeb5bb..9a07ca885914 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppEntitiesHeaderControllerTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/AppEntitiesHeaderControllerTest.java
@@ -85,6 +85,23 @@ public class AppEntitiesHeaderControllerTest {
}
@Test
+ public void setHeaderDetails_onlyDetailsTextSet_shouldSetToDetailsView() {
+ mController.setHeaderDetails(TITLE).apply();
+ final TextView view = mAppEntitiesHeaderView.findViewById(R.id.header_details);
+
+ assertThat(view.getText()).isEqualTo(TITLE);
+ }
+
+ @Test
+ public void setHeaderDetails_detailsTextAndResBothSet_shouldSetTextToDetailsView() {
+ mController.setHeaderDetailsRes(R.string.expand_button_title);
+ mController.setHeaderDetails(TITLE).apply();
+ final TextView view = mAppEntitiesHeaderView.findViewById(R.id.header_details);
+
+ assertThat(view.getText()).isEqualTo(TITLE);
+ }
+
+ @Test
public void setHeaderDetailsClickListener_setClickListener_detailsViewAttachClickListener() {
mController.setHeaderDetailsClickListener(v -> {
}).apply();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index ef90dc981870..0ee16a9e9ed2 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -23,6 +23,7 @@ import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
+import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
@@ -2440,6 +2441,7 @@ class DatabaseHelper extends SQLiteOpenHelper {
private void loadGlobalSettings(SQLiteDatabase db) {
SQLiteStatement stmt = null;
+ final Resources res = mContext.getResources();
try {
stmt = db.compileStatement("INSERT OR IGNORE INTO global(name,value)"
+ " VALUES(?,?);");
@@ -2468,7 +2470,7 @@ class DatabaseHelper extends SQLiteOpenHelper {
loadSetting(stmt, Settings.Global.STAY_ON_WHILE_PLUGGED_IN,
("1".equals(SystemProperties.get("ro.kernel.qemu")) ||
- mContext.getResources().getBoolean(R.bool.def_stay_on_while_plugged_in))
+ res.getBoolean(R.bool.def_stay_on_while_plugged_in))
? 1 : 0);
loadIntegerSetting(stmt, Settings.Global.WIFI_SLEEP_POLICY,
@@ -2505,14 +2507,14 @@ class DatabaseHelper extends SQLiteOpenHelper {
loadBooleanSetting(stmt, Settings.Global.DEVICE_PROVISIONED,
R.bool.def_device_provisioned);
- final int maxBytes = mContext.getResources().getInteger(
+ final int maxBytes = res.getInteger(
R.integer.def_download_manager_max_bytes_over_mobile);
if (maxBytes > 0) {
loadSetting(stmt, Settings.Global.DOWNLOAD_MAX_BYTES_OVER_MOBILE,
Integer.toString(maxBytes));
}
- final int recommendedMaxBytes = mContext.getResources().getInteger(
+ final int recommendedMaxBytes = res.getInteger(
R.integer.def_download_manager_recommended_max_bytes_over_mobile);
if (recommendedMaxBytes > 0) {
loadSetting(stmt, Settings.Global.DOWNLOAD_RECOMMENDED_MAX_BYTES_OVER_MOBILE,
@@ -2609,6 +2611,20 @@ class DatabaseHelper extends SQLiteOpenHelper {
loadSetting(stmt, Settings.Global.DEVICE_NAME, getDefaultDeviceName());
+ // Set default lid/cover behaviour according to legacy device config
+ final int defaultLidBehavior;
+ if (res.getBoolean(com.android.internal.R.bool.config_lidControlsSleep)) {
+ // WindowManagerFuncs.LID_BEHAVIOR_SLEEP
+ defaultLidBehavior = 1;
+ } else if (res.getBoolean(com.android.internal.R.bool.config_lidControlsScreenLock)) {
+ // WindowManagerFuncs.LID_BEHAVIOR_LOCK
+ defaultLidBehavior = 2;
+ } else {
+ // WindowManagerFuncs.LID_BEHAVIOR_NONE
+ defaultLidBehavior = 0;
+ }
+ loadSetting(stmt, Settings.Global.LID_BEHAVIOR, defaultLidBehavior);
+
/*
* IMPORTANT: Do not add any more upgrade steps here as the global,
* secure, and system settings are no longer stored in a database
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 81b304dc2ce4..0f8fd9265eaa 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -1353,11 +1353,11 @@ class SettingsProtoDumpUtil {
Settings.Global.SHOW_TEMPERATURE_WARNING,
GlobalSettingsProto.TemperatureWarning.SHOW_TEMPERATURE_WARNING);
dumpSetting(s, p,
+ Settings.Global.SHOW_USB_TEMPERATURE_ALARM,
+ GlobalSettingsProto.TemperatureWarning.SHOW_USB_TEMPERATURE_ALARM);
+ dumpSetting(s, p,
Settings.Global.WARNING_TEMPERATURE,
GlobalSettingsProto.TemperatureWarning.WARNING_TEMPERATURE_LEVEL);
- dumpSetting(s, p,
- Settings.Global.USB_ALARM_TEMPERATURE,
- GlobalSettingsProto.TemperatureWarning.USB_ALARM_TEMPERATURE_LEVEL);
p.end(tempWarningToken);
final long tetherToken = p.start(GlobalSettingsProto.TETHER);
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index a7ad2239b402..ceafbfa4da15 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -1379,8 +1379,8 @@ public class SettingsProvider extends ContentProvider {
}
}
if (enableOverride) {
- if (Secure.LOCATION_PROVIDERS_ALLOWED.equals(name)) {
- final Setting overridden = getLocationProvidersAllowedSetting(owningUserId);
+ if (Secure.LOCATION_MODE.equals(name)) {
+ final Setting overridden = getLocationModeSetting(owningUserId);
if (overridden != null) {
return overridden;
}
@@ -1475,7 +1475,7 @@ public class SettingsProvider extends ContentProvider {
return null;
}
- private Setting getLocationProvidersAllowedSetting(int owningUserId) {
+ private Setting getLocationModeSetting(int owningUserId) {
synchronized (mLock) {
final Setting setting = getGlobalSetting(
Global.LOCATION_GLOBAL_KILL_SWITCH);
@@ -1486,7 +1486,7 @@ public class SettingsProvider extends ContentProvider {
final SettingsState settingsState = mSettingsRegistry.getSettingsLocked(
SETTINGS_TYPE_SECURE, owningUserId);
return settingsState.new Setting(
- Secure.LOCATION_PROVIDERS_ALLOWED,
+ Secure.LOCATION_MODE,
"", // value
"", // tag
"", // default value
@@ -1497,7 +1497,7 @@ public class SettingsProvider extends ContentProvider {
@Override
public boolean update(String value, boolean setDefault, String packageName,
String tag, boolean forceNonSystemPackage) {
- Slog.wtf(LOG_TAG, "update shoudln't be called on this instance.");
+ Slog.wtf(LOG_TAG, "update shouldn't be called on this instance.");
return false;
}
};
@@ -3115,7 +3115,7 @@ public class SettingsProvider extends ContentProvider {
final int key = makeKey(SETTINGS_TYPE_SECURE, userId);
mGenerationRegistry.incrementGeneration(key);
- final Uri uri = getNotificationUriFor(key, Secure.LOCATION_PROVIDERS_ALLOWED);
+ final Uri uri = getNotificationUriFor(key, Secure.LOCATION_MODE);
mHandler.obtainMessage(MyHandler.MSG_NOTIFY_URI_CHANGED,
userId, 0, uri).sendToTarget();
}
diff --git a/packages/SystemUI/res/drawable/ic_tune_black_16dp.xml b/packages/SystemUI/res/drawable/ic_tune_black_16dp.xml
new file mode 100644
index 000000000000..339cb70e3ed0
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_tune_black_16dp.xml
@@ -0,0 +1,25 @@
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="16dp"
+ android:height="16dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M3,17v2h6v-2L3,17zM3,5v2h10L13,5L3,5zM13,21v-2h8v-2h-8v-2h-2v6h2zM7,9v2L3,11v2h4v2h2L9,9L7,9zM21,13v-2L11,11v2h10zM15,9h2L17,7h4L21,5h-4L17,3h-2v6z"/>
+</vector> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/qs_customize_tile_decoration.xml b/packages/SystemUI/res/drawable/qs_customize_tile_decoration.xml
new file mode 100644
index 000000000000..f086cec01234
--- /dev/null
+++ b/packages/SystemUI/res/drawable/qs_customize_tile_decoration.xml
@@ -0,0 +1,17 @@
+<!--
+ Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<color xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="@color/qs_customize_decoration"/> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/qs_customizer_background_primary.xml b/packages/SystemUI/res/drawable/qs_customizer_background_primary.xml
index abe1429697ac..215dee41d548 100644
--- a/packages/SystemUI/res/drawable/qs_customizer_background_primary.xml
+++ b/packages/SystemUI/res/drawable/qs_customizer_background_primary.xml
@@ -15,7 +15,7 @@
-->
<inset xmlns:android="http://schemas.android.com/apk/res/android">
<shape>
- <solid android:color="?android:attr/colorPrimary"/>
+ <solid android:color="@color/qs_customize_background"/>
<corners android:radius="?android:attr/dialogCornerRadius" />
</shape>
</inset>
diff --git a/packages/SystemUI/res/drawable/qs_customizer_toolbar.xml b/packages/SystemUI/res/drawable/qs_customizer_toolbar.xml
index 557cae150303..648d45b4f903 100644
--- a/packages/SystemUI/res/drawable/qs_customizer_toolbar.xml
+++ b/packages/SystemUI/res/drawable/qs_customizer_toolbar.xml
@@ -15,7 +15,7 @@
-->
<inset xmlns:android="http://schemas.android.com/apk/res/android">
<shape>
- <solid android:color="?android:attr/colorSecondary"/>
+ <solid android:color="@color/qs_customize_background"/>
<corners
android:topLeftRadius="?android:attr/dialogCornerRadius"
android:topRightRadius="?android:attr/dialogCornerRadius" />
diff --git a/packages/SystemUI/res/layout-sw600dp/navigation_layout_rot90.xml b/packages/SystemUI/res/layout-sw600dp/navigation_layout_rot90.xml
deleted file mode 100644
index 78304fd894dd..000000000000
--- a/packages/SystemUI/res/layout-sw600dp/navigation_layout_rot90.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2016 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<FrameLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <FrameLayout
- android:id="@+id/nav_buttons"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <LinearLayout
- android:id="@+id/ends_group"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal"
- android:clipChildren="false" />
-
- <LinearLayout
- android:id="@+id/center_group"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center"
- android:orientation="horizontal"
- android:clipChildren="false" />
-
- </FrameLayout>
-
-</FrameLayout>
diff --git a/packages/SystemUI/res/layout/bubble_permission_view.xml b/packages/SystemUI/res/layout/bubble_permission_view.xml
index 7fbb78a6feee..c9d8a9128d7c 100644
--- a/packages/SystemUI/res/layout/bubble_permission_view.xml
+++ b/packages/SystemUI/res/layout/bubble_permission_view.xml
@@ -17,7 +17,7 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_height="@dimen/bubble_permission_height"
android:animateLayoutChanges="true"
android:orientation="vertical"
android:paddingStart="@dimen/bubble_expanded_header_horizontal_padding"
diff --git a/packages/SystemUI/res/layout/keyguard_status_bar.xml b/packages/SystemUI/res/layout/keyguard_status_bar.xml
index 5b9816d91965..66c0c5c275ed 100644
--- a/packages/SystemUI/res/layout/keyguard_status_bar.xml
+++ b/packages/SystemUI/res/layout/keyguard_status_bar.xml
@@ -71,7 +71,7 @@
android:gravity="center_vertical"
android:ellipsize="marquee"
android:textDirection="locale"
- android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textAppearance="@style/TextAppearance.StatusBar.Clock"
android:textColor="?attr/wallpaperTextColorSecondary"
android:singleLine="true"
systemui:showMissingSim="true"
diff --git a/packages/SystemUI/res/layout/nav_bar_tuner_inflater.xml b/packages/SystemUI/res/layout/nav_bar_tuner_inflater.xml
index b2376333a30e..133b2158c771 100644
--- a/packages/SystemUI/res/layout/nav_bar_tuner_inflater.xml
+++ b/packages/SystemUI/res/layout/nav_bar_tuner_inflater.xml
@@ -20,8 +20,8 @@
android:layout_width="match_parent"
android:layout_height="@dimen/navigation_bar_size">
- <include android:id="@+id/rot0" layout="@layout/navigation_layout" />
+ <include android:id="@+id/horizontal" layout="@layout/navigation_layout" />
- <include android:id="@+id/rot90" layout="@layout/navigation_layout_rot90" />
+ <include android:id="@+id/vertical" layout="@layout/navigation_layout_vertical" />
</com.android.systemui.tuner.PreviewNavInflater>
diff --git a/packages/SystemUI/res/layout/navigation_layout.xml b/packages/SystemUI/res/layout/navigation_layout.xml
index d72021e27e0b..db1c79d24c54 100644
--- a/packages/SystemUI/res/layout/navigation_layout.xml
+++ b/packages/SystemUI/res/layout/navigation_layout.xml
@@ -22,7 +22,8 @@
android:layout_marginStart="@dimen/rounded_corner_content_padding"
android:layout_marginEnd="@dimen/rounded_corner_content_padding"
android:paddingStart="@dimen/nav_content_padding"
- android:paddingEnd="@dimen/nav_content_padding">
+ android:paddingEnd="@dimen/nav_content_padding"
+ android:id="@+id/horizontal">
<com.android.systemui.statusbar.phone.NearestTouchFrame
android:id="@+id/nav_buttons"
diff --git a/packages/SystemUI/res/layout/navigation_layout_rot90.xml b/packages/SystemUI/res/layout/navigation_layout_vertical.xml
index 24a0c71f3bad..285c5c4e0a01 100644
--- a/packages/SystemUI/res/layout/navigation_layout_rot90.xml
+++ b/packages/SystemUI/res/layout/navigation_layout_vertical.xml
@@ -22,7 +22,8 @@
android:layout_marginTop="@dimen/rounded_corner_content_padding"
android:layout_marginBottom="@dimen/rounded_corner_content_padding"
android:paddingTop="@dimen/nav_content_padding"
- android:paddingBottom="@dimen/nav_content_padding">
+ android:paddingBottom="@dimen/nav_content_padding"
+ android:id="@+id/vertical">
<com.android.systemui.statusbar.phone.NearestTouchFrame
android:id="@+id/nav_buttons"
diff --git a/packages/SystemUI/res/layout/qs_customize_divider.xml b/packages/SystemUI/res/layout/qs_customize_divider.xml
index 6fcfa8d27a7a..d6664fefe2da 100644
--- a/packages/SystemUI/res/layout/qs_customize_divider.xml
+++ b/packages/SystemUI/res/layout/qs_customize_divider.xml
@@ -24,5 +24,4 @@
android:paddingTop="20dp"
android:paddingBottom="13dp"
android:textAppearance="@style/TextAppearance.QSEdit.Headers"
- android:textColor="?android:attr/colorAccent"
android:text="@string/drag_to_add_tiles" />
diff --git a/packages/SystemUI/res/layout/qs_customize_header.xml b/packages/SystemUI/res/layout/qs_customize_header.xml
index d54dfee8c670..58066a3ef19c 100644
--- a/packages/SystemUI/res/layout/qs_customize_header.xml
+++ b/packages/SystemUI/res/layout/qs_customize_header.xml
@@ -24,5 +24,4 @@
android:gravity="center"
android:minHeight="@dimen/qs_customize_header_min_height"
android:textAppearance="@style/TextAppearance.QSEdit.Headers"
- android:textColor="?android:attr/colorAccent"
android:text="@string/drag_to_rearrange_tiles" /> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_customize_panel_content.xml b/packages/SystemUI/res/layout/qs_customize_panel_content.xml
index 87b455129835..09f512f72f84 100644
--- a/packages/SystemUI/res/layout/qs_customize_panel_content.xml
+++ b/packages/SystemUI/res/layout/qs_customize_panel_content.xml
@@ -37,7 +37,8 @@
android:layout_height="wrap_content"
android:background="@drawable/qs_customizer_toolbar"
android:navigationContentDescription="@*android:string/action_bar_up_description"
- style="?android:attr/toolbarStyle" />
+ style="@style/QSCustomizeToolbar"
+ />
<androidx.recyclerview.widget.RecyclerView
android:id="@android:id/list"
diff --git a/packages/SystemUI/res/layout/volume_dialog.xml b/packages/SystemUI/res/layout/volume_dialog.xml
index e67bb60555f3..ca34c23eca1f 100644
--- a/packages/SystemUI/res/layout/volume_dialog.xml
+++ b/packages/SystemUI/res/layout/volume_dialog.xml
@@ -87,7 +87,7 @@
android:background="@drawable/rounded_bg_bottom_background">
<com.android.keyguard.AlphaOptimizedImageButton
android:id="@+id/settings"
- android:src="@drawable/ic_settings_16dp"
+ android:src="@drawable/ic_tune_black_16dp"
android:layout_width="@dimen/volume_dialog_tap_target_size"
android:layout_height="@dimen/volume_dialog_tap_target_size"
android:layout_gravity="center"
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index 2c5120dd06f3..5803bf129c24 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -41,4 +41,10 @@
<!-- The color of the text inside a notification -->
<color name="notification_primary_text_color">@*android:color/notification_primary_text_color_dark</color>
+
+ <!-- The color of the background in the top part of QSCustomizer -->
+ <color name="qs_customize_background">@color/GM2_grey_900</color>
+
+ <!-- The color of the background in the bottom part of QSCustomizer -->
+ <color name="qs_customize_decoration">@color/GM2_grey_800</color>
</resources> \ No newline at end of file
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index d5f29badd893..0e4ffee81165 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -35,6 +35,8 @@
<color name="status_bar_clock_color">#FFFFFFFF</color>
<color name="qs_user_detail_icon_muted">#FFFFFFFF</color> <!-- not so muted after all -->
<color name="qs_tile_disabled_color">#9E9E9E</color> <!-- 38% black -->
+ <color name="qs_customize_background">@color/GM2_grey_50</color>
+ <color name="qs_customize_decoration">@color/GM2_grey_100</color>
<!-- Tint color for the content on the notification overflow card. -->
<color name="keyguard_overflow_content_color">#ff686868</color>
@@ -72,7 +74,7 @@
<color name="notification_primary_text_color">@*android:color/notification_primary_text_color_light</color>
<!-- The "inside" of a notification, reached via longpress -->
- <color name="notification_guts_bg_color">#f8f9fa</color>
+ <color name="notification_guts_bg_color">@color/GM2_grey_50</color>
<color name="assist_orb_color">#ffffff</color>
@@ -123,7 +125,7 @@
<color name="zen_introduction">#ffffffff</color>
- <color name="smart_reply_button_text">#5F6368</color>
+ <color name="smart_reply_button_text">@color/GM2_grey_700</color>
<color name="smart_reply_button_text_dark_bg">@*android:color/notification_primary_text_color_dark</color>
<color name="smart_reply_button_background">#ffffffff</color>
<color name="smart_reply_button_stroke">#ffdadce0</color>
@@ -134,4 +136,17 @@
<!-- Logout button -->
<color name="logout_button_bg_color">#ccffffff</color>
+
+ <!-- GM2 colors -->
+ <color name="GM2_grey_50">#F8F9FA</color>
+ <color name="GM2_grey_100">#F1F3F4</color>
+ <color name="GM2_grey_200">#E8EAED</color>
+ <color name="GM2_grey_300">#DADCE0</color>
+ <color name="GM2_grey_400">#BDC1C6</color>
+ <color name="GM2_grey_500">#9AA0A6</color>
+ <color name="GM2_grey_600">#80868B</color>
+ <color name="GM2_grey_650">#70757A</color>
+ <color name="GM2_grey_700">#5F6368</color>
+ <color name="GM2_grey_800">#3C4043</color>
+ <color name="GM2_grey_900">#202124</color>
</resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 4396a42929ba..b4dc0eff0761 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -329,16 +329,11 @@
<bool name="quick_settings_show_full_alarm">false</bool>
- <!-- Whether to show a warning notification when the device reaches a certain temperature. -->
+ <!-- Whether to show a warning notification when device's skin temperature is high. -->
<integer name="config_showTemperatureWarning">0</integer>
- <!-- Temp at which to show a warning notification if config_showTemperatureWarning is true.
- If < 0, uses the skin temperature sensor shutdown value from
- HardwarePropertiesManager#getDeviceTemperatures - config_warningTemperatureTolerance. -->
- <integer name="config_warningTemperature">-1</integer>
-
- <!-- Fudge factor for how much below the shutdown temp to show the warning. -->
- <integer name="config_warningTemperatureTolerance">2</integer>
+ <!-- Whether to show a alarm dialog when device's usb port is overheating. -->
+ <integer name="config_showUsbPortAlarm">0</integer>
<!-- Accessibility actions -->
<item type="id" name="action_split_task_to_left" />
@@ -485,4 +480,5 @@
</string-array>
<integer name="ongoing_appops_dialog_max_apps">5</integer>
+
</resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 1f6e3c2ff876..536bc4edf341 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1045,4 +1045,8 @@
<dimen name="bubble_header_icon_size">48dp</dimen>
<!-- Size of the app icon shown in the bubble permission view -->
<dimen name="bubble_permission_icon_size">24dp</dimen>
+ <!-- Space between the pointer triangle and the bubble expanded view -->
+ <dimen name="bubble_pointer_margin">8dp</dimen>
+ <!-- Height of the permission prompt shown with bubbles -->
+ <dimen name="bubble_permission_height">120dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 0fde2de1e2f1..4905e572af1d 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2118,6 +2118,14 @@
<string name="high_temp_notif_message">Some features limited while phone cools down</string>
<!-- Text body for dialog alerting user that their phone has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=300] -->
<string name="high_temp_dialog_message">Your phone will automatically try to cool down. You can still use your phone, but it may run slower.\n\nOnce your phone has cooled down, it will run normally.</string>
+ <!-- Title for alarm dialog alerting user the usb adapter has reached a certain temperature that should disconnect charging cable immediately. [CHAR LIMIT=30] -->
+ <string name="high_temp_alarm_title">Unplug charger</string>
+ <!-- Text body for dialog alerting user the usb adapter has reached a certain temperature that should disconnect charging cable immediately. [CHAR LIMIT=300] -->
+ <string name="high_temp_alarm_notify_message">There\u2019s an issue charging this device. Unplug the power adapter, and take care as the cable may be warm.</string>
+ <!-- Text for See care steps button [CHAR LIMIT=300] -->
+ <string name="high_temp_alarm_help_care_steps">See care steps</string>
+ <!-- Text link directs to usb overheat help page. -->
+ <string name="high_temp_alarm_help_url" translatable="false">help_uri_usb_warm</string>
<!-- SysUI Tuner: Button to select lock screen shortcut [CHAR LIMIT=60] -->
<string name="lockscreen_shortcut_left">Left shortcut</string>
@@ -2378,5 +2386,4 @@
<string name="no_bubbles">Block</string>
<!-- Text used for button allowing user to approve / enable bubbles [CHAR LIMIT=20] -->
<string name="yes_bubbles">Allow</string>
-
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 96cdbd38ed0b..1e411cf7f92b 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -458,8 +458,15 @@
</style>
<style name="TextAppearance.QSEdit.Headers"
- parent="@*android:style/TextAppearance.Material.Body2">
- <item name="android:fontFamily">@*android:string/config_headlineFontFamily</item>
+ parent="@*android:style/TextAppearance.DeviceDefault.Body2">
+ <item name="android:textSize">11sp</item>
+ <item name="android:textColor">?android:attr/textColorSecondary</item>
+ <item name="android:textAllCaps">true</item>
+ </style>
+
+ <style name="QSCustomizeToolbar" parent="@*android:style/Widget.DeviceDefault.Toolbar">
+ <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <item name="android:elevation">10dp</item>
</style>
<style name="edit_theme" parent="qs_theme">
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/StatsLogCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/StatsLogCompat.java
index 5bc1f2511411..d17725f1e219 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/StatsLogCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/StatsLogCompat.java
@@ -32,4 +32,17 @@ public class StatsLogCompat {
StatsLog.write(19, action, srcState, dstState, extension,
swipeUpEnabled);
}
+
+ /**
+ * StatsLog.write(StatsLog.STYLE_EVENT, action, colorPackageHash,
+ * fontPackageHash, shapePackageHash, clockPackageHash,
+ * launcherGrid, wallpaperCategoryHash, wallpaperIdHash);
+ */
+ public static void write(int action, int colorPackageHash,
+ int fontPackageHash, int shapePackageHash, int clockPackageHash,
+ int launcherGrid, int wallpaperCategoryHash, int wallpaperIdHash) {
+ StatsLog.write(179, action, colorPackageHash,
+ fontPackageHash, shapePackageHash, clockPackageHash,
+ launcherGrid, wallpaperCategoryHash, wallpaperIdHash);
+ }
}
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
index c5dc3244d0a3..3827e445c136 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
@@ -34,6 +34,7 @@ import android.util.DisplayMetrics;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.MeasureSpec;
+import android.view.ViewGroup;
import androidx.annotation.VisibleForTesting;
@@ -241,6 +242,7 @@ public final class ClockManager {
// Draw clock view hierarchy to canvas.
Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight, Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
+ dispatchVisibilityAggregated(clockView, true);
clockView.measure(MeasureSpec.makeMeasureSpec(mWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mHeight, MeasureSpec.EXACTLY));
clockView.layout(0, 0, mWidth, mHeight);
@@ -250,6 +252,24 @@ public final class ClockManager {
return bitmap;
}
+ private void dispatchVisibilityAggregated(View view, boolean isVisible) {
+ // Similar to View.dispatchVisibilityAggregated implementation.
+ final boolean thisVisible = view.getVisibility() == View.VISIBLE;
+ if (thisVisible || !isVisible) {
+ view.onVisibilityAggregated(isVisible);
+ }
+
+ if (view instanceof ViewGroup) {
+ isVisible = thisVisible && isVisible;
+ ViewGroup vg = (ViewGroup) view;
+ int count = vg.getChildCount();
+
+ for (int i = 0; i < count; i++) {
+ dispatchVisibilityAggregated(vg.getChildAt(i), isVisible);
+ }
+ }
+ }
+
private void notifyClockChanged(ClockPlugin plugin) {
for (int i = 0; i < mListeners.size(); i++) {
// It probably doesn't make sense to supply the same plugin instances to multiple
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 567207376996..87f004fc12e6 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -61,7 +61,6 @@ import com.android.systemui.statusbar.notification.NotificationAlertingManager;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationFilter;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
-import com.android.systemui.statusbar.notification.NotificationRowBinder;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationData.KeyguardEnvironment;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
@@ -266,7 +265,6 @@ public class Dependency extends SystemUI {
@Inject Lazy<NotificationListener> mNotificationListener;
@Inject Lazy<NotificationLogger> mNotificationLogger;
@Inject Lazy<NotificationViewHierarchyManager> mNotificationViewHierarchyManager;
- @Inject Lazy<NotificationRowBinder> mNotificationRowBinder;
@Inject Lazy<NotificationFilter> mNotificationFilter;
@Inject Lazy<NotificationInterruptionStateProvider> mNotificationInterruptionStateProvider;
@Inject Lazy<KeyguardDismissUtil> mKeyguardDismissUtil;
@@ -440,7 +438,6 @@ public class Dependency extends SystemUI {
mProviders.put(NotificationLogger.class, mNotificationLogger::get);
mProviders.put(NotificationViewHierarchyManager.class,
mNotificationViewHierarchyManager::get);
- mProviders.put(NotificationRowBinder.class, mNotificationRowBinder::get);
mProviders.put(NotificationFilter.class, mNotificationFilter::get);
mProviders.put(NotificationInterruptionStateProvider.class,
mNotificationInterruptionStateProvider::get);
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 9efa656b3ed3..60e6083790dc 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -474,8 +474,6 @@ public class SwipeHelper implements Gefingerpoken {
if (anim == null) {
return;
}
- int duration = SNAP_ANIM_LEN;
- anim.setDuration(duration);
anim.addListener(new AnimatorListenerAdapter() {
boolean wasCancelled = false;
@@ -495,6 +493,9 @@ public class SwipeHelper implements Gefingerpoken {
});
prepareSnapBackAnimation(animView, anim);
mSnappingChild = true;
+ float maxDistance = Math.abs(targetLeft - getTranslation(animView));
+ mFlingAnimationUtils.apply(anim, getTranslation(animView), targetLeft, velocity,
+ maxDistance);
anim.start();
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
index 4eea9f883f81..471619e897c5 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java
@@ -80,16 +80,21 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe
// Enables some subset of notifs to automatically become bubbles
private static final boolean DEBUG_ENABLE_AUTO_BUBBLE = false;
- // Secure settings flags
- // Feature level flag
+ /** Flag to enable or disable the entire feature */
private static final String ENABLE_BUBBLES = "experiment_enable_bubbles";
- // Auto bubble flags set whether different notification types should be presented as a bubble
+ /** Auto bubble flags set whether different notif types should be presented as a bubble */
private static final String ENABLE_AUTO_BUBBLE_MESSAGES = "experiment_autobubble_messaging";
private static final String ENABLE_AUTO_BUBBLE_ONGOING = "experiment_autobubble_ongoing";
private static final String ENABLE_AUTO_BUBBLE_ALL = "experiment_autobubble_all";
- // Use an activity view for an auto-bubbled notification if it has an appropriate content intent
+
+ /** Use an activityView for an auto-bubbled notifs if it has an appropriate content intent */
private static final String ENABLE_BUBBLE_CONTENT_INTENT = "experiment_bubble_content_intent";
+ /** Whether the row of bubble circles are anchored to the top or bottom of the screen. */
+ private static final String ENABLE_BUBBLES_AT_TOP = "experiment_enable_top_bubbles";
+ /** Flag to position the header below the activity view */
+ private static final String ENABLE_BUBBLE_FOOTER = "experiment_enable_bubble_footer";
+
private final Context mContext;
private final NotificationEntryManager mNotificationEntryManager;
private final IActivityTaskManager mActivityTaskManager;
@@ -548,6 +553,22 @@ public class BubbleController implements BubbleExpandedView.OnBubbleBlockedListe
ENABLE_BUBBLES, 1) != 0;
}
+ /**
+ * Whether bubbles should be positioned at the top of the screen or not.
+ */
+ public static boolean showBubblesAtTop(Context context) {
+ return Settings.Secure.getInt(context.getContentResolver(),
+ ENABLE_BUBBLES_AT_TOP, 0) != 0;
+ }
+
+ /**
+ * Whether the bubble chrome should display as a footer or not (in which case it's a header).
+ */
+ public static boolean useFooter(Context context) {
+ return Settings.Secure.getInt(context.getContentResolver(),
+ ENABLE_BUBBLE_FOOTER, 0) != 0;
+ }
+
/** PinnedStackListener that dispatches IME visibility updates to the stack. */
private class BubblesImeListener extends IPinnedStackListener.Stub {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
index 7884800611aa..b635033ea771 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleExpandedView.java
@@ -70,8 +70,13 @@ import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
public class BubbleExpandedView extends LinearLayout implements View.OnClickListener {
private static final String TAG = "BubbleExpandedView";
+ // Configurable via bubble settings; just for testing
+ private boolean mUseFooter;
+ private boolean mShowOnTop;
+
// The triangle pointing to the expanded view
private View mPointerView;
+ private int mPointerMargin;
// Header
private View mHeaderView;
@@ -90,6 +95,8 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
private int mMinHeight;
private int mHeaderHeight;
+ private int mBubbleHeight;
+ private int mPermissionHeight;
private NotificationEntry mEntry;
private PackageManager mPm;
@@ -150,6 +157,7 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
mPm = context.getPackageManager();
mMinHeight = getResources().getDimensionPixelSize(
R.dimen.bubble_expanded_default_height);
+ mPointerMargin = getResources().getDimensionPixelSize(R.dimen.bubble_pointer_margin);
try {
mNotificationManagerService = INotificationManager.Stub.asInterface(
ServiceManager.getServiceOrThrow(Context.NOTIFICATION_SERVICE));
@@ -172,8 +180,11 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
int bgColor = ta.getColor(0, Color.WHITE);
ta.recycle();
+ mShowOnTop = BubbleController.showBubblesAtTop(getContext());
+ mUseFooter = BubbleController.useFooter(getContext());
+
ShapeDrawable triangleDrawable = new ShapeDrawable(
- TriangleShape.create(width, height, true /* pointUp */));
+ TriangleShape.create(width, height, mShowOnTop /* pointUp */));
triangleDrawable.setTint(bgColor);
mPointerView.setBackground(triangleDrawable);
@@ -195,6 +206,8 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
mHeaderHeight = getContext().getResources().getDimensionPixelSize(
R.dimen.bubble_expanded_header_height);
+ mPermissionHeight = getContext().getResources().getDimensionPixelSize(
+ R.dimen.bubble_permission_height);
mHeaderView = findViewById(R.id.header_layout);
mDeepLinkIcon = findViewById(R.id.deep_link_button);
mSettingsIcon = findViewById(R.id.settings_button);
@@ -226,6 +239,15 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
activityView.setForwardedInsets(Insets.of(0, 0, 0, insetsBottom));
return view.onApplyWindowInsets(insets);
});
+
+ if (!mShowOnTop) {
+ removeView(mPointerView);
+ if (mUseFooter) {
+ removeView(viewWrapper);
+ addView(viewWrapper);
+ }
+ addView(mPointerView);
+ }
}
/**
@@ -332,7 +354,11 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
// Use notification view
mNotifRow = mEntry.getRow();
- addView(mNotifRow);
+ if (mShowOnTop) {
+ addView(mNotifRow);
+ } else {
+ addView(mNotifRow, mUseFooter ? 0 : 1);
+ }
}
updateView();
}
@@ -345,6 +371,17 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
return true;
}
+ /**
+ * @return total height that the expanded view occupies.
+ */
+ int getExpandedSize() {
+ int chromeHeight = mPermissionView.getVisibility() != View.VISIBLE
+ ? mHeaderHeight
+ : mPermissionHeight;
+ return mBubbleHeight + mPointerView.getHeight() + mPointerMargin
+ + chromeHeight;
+ }
+
void updateHeight() {
if (usingActivityView()) {
Notification.BubbleMetadata data = mEntry.getBubbleMetadata();
@@ -358,12 +395,19 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
? data.getDesiredHeight()
: mMinHeight;
}
- int max = mStackView.getMaxExpandedHeight() - mHeaderHeight;
+ int chromeHeight = mPermissionView.getVisibility() != View.VISIBLE
+ ? mHeaderHeight
+ : mPermissionHeight;
+ int max = mStackView.getMaxExpandedHeight() - chromeHeight - mPointerView.getHeight()
+ - mPointerMargin;
int height = Math.min(desiredHeight, max);
height = Math.max(height, mMinHeight);
LayoutParams lp = (LayoutParams) mActivityView.getLayoutParams();
lp.height = height;
+ mBubbleHeight = height;
mActivityView.setLayoutParams(lp);
+ } else {
+ mBubbleHeight = mNotifRow != null ? mNotifRow.getIntrinsicHeight() : mMinHeight;
}
}
@@ -412,6 +456,7 @@ public class BubbleExpandedView extends LinearLayout implements View.OnClickList
} else if (mOnBubbleBlockedListener != null) {
mOnBubbleBlockedListener.onBubbleBlocked(mEntry);
}
+ mStackView.onExpandedHeightChanged();
logBubbleClickEvent(mEntry.notification,
allowed ? StatsLog.BUBBLE_UICHANGED__ACTION__PERMISSION_OPT_IN :
StatsLog.BUBBLE_UICHANGED__ACTION__PERMISSION_OPT_OUT);
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index e20be8e552df..167bf47664e0 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -173,7 +173,7 @@ public class BubbleStackView extends FrameLayout {
int elevation = res.getDimensionPixelSize(R.dimen.bubble_elevation);
mStackAnimationController = new StackAnimationController();
- mExpandedAnimationController = new ExpandedAnimationController();
+ mExpandedAnimationController = new ExpandedAnimationController(mDisplaySize);
mBubbleContainer = new PhysicsAnimationLayout(context);
mBubbleContainer.setMaxRenderedChildren(
@@ -513,8 +513,7 @@ public class BubbleStackView extends FrameLayout {
final float yStart = Math.min(
mStackAnimationController.getStackPosition().y,
mExpandedAnimateYDistance);
- final float yDest = getStatusBarHeight()
- + mExpandedBubble.iconView.getHeight() + mBubblePadding;
+ final float yDest = getYPositionForExpandedView();
if (shouldExpand) {
mExpandedViewContainer.setTranslationX(xStart);
@@ -668,13 +667,39 @@ public class BubbleStackView extends FrameLayout {
* y position when the bubbles are expanded as well as the bounds of the dismiss target.
*/
int getMaxExpandedHeight() {
+ boolean showOnTop = BubbleController.showBubblesAtTop(getContext());
int expandedY = (int) mExpandedAnimationController.getExpandedY();
- int bubbleContainerHeight = mBubbleContainer.getChildAt(0) != null
- ? mBubbleContainer.getChildAt(0).getHeight()
- : 0;
- // PIP dismiss view uses FLAG_LAYOUT_IN_SCREEN so we need to subtract the bottom inset
- int pipDismissHeight = mPipDismissHeight - getBottomInset();
- return mDisplaySize.y - expandedY - mBubbleSize - pipDismissHeight;
+ if (showOnTop) {
+ // PIP dismiss view uses FLAG_LAYOUT_IN_SCREEN so we need to subtract the bottom inset
+ int pipDismissHeight = mPipDismissHeight - getBottomInset();
+ return mDisplaySize.y - expandedY - mBubbleSize - pipDismissHeight;
+ } else {
+ return expandedY - getStatusBarHeight();
+ }
+ }
+
+ /**
+ * Calculates the y position of the expanded view when it is expanded.
+ */
+ float getYPositionForExpandedView() {
+ boolean showOnTop = BubbleController.showBubblesAtTop(getContext());
+ if (showOnTop) {
+ return getStatusBarHeight() + mBubbleSize + mBubblePadding;
+ } else {
+ return mExpandedAnimationController.getExpandedY()
+ - mExpandedBubble.expandedView.getExpandedSize() - mBubblePadding;
+ }
+ }
+
+ /**
+ * Called when the height of the currently expanded view has changed (not via an
+ * update to the bubble's desired height but for some other reason, e.g. permission view
+ * goes away).
+ */
+ void onExpandedHeightChanged() {
+ if (mIsExpanded) {
+ requestUpdate();
+ }
}
/**
@@ -751,6 +776,8 @@ public class BubbleStackView extends FrameLayout {
mExpandedViewContainer.setVisibility(mIsExpanded ? VISIBLE : GONE);
if (mIsExpanded) {
+ final float y = getYPositionForExpandedView();
+ mExpandedViewContainer.setTranslationY(y);
mExpandedBubble.expandedView.updateView();
}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
index f0d9be1e484a..f7896b0b1201 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/animation/ExpandedAnimationController.java
@@ -17,6 +17,7 @@
package com.android.systemui.bubbles.animation;
import android.content.res.Resources;
+import android.graphics.Point;
import android.graphics.PointF;
import android.view.View;
import android.view.WindowInsets;
@@ -25,6 +26,7 @@ import androidx.dynamicanimation.animation.DynamicAnimation;
import androidx.dynamicanimation.animation.SpringForce;
import com.android.systemui.R;
+import com.android.systemui.bubbles.BubbleController;
import com.google.android.collect.Sets;
@@ -61,6 +63,14 @@ public class ExpandedAnimationController
private float mBubbleSizePx;
/** Height of the status bar. */
private float mStatusBarHeight;
+ /** Size of display. */
+ private Point mDisplaySize;
+ /** Size of dismiss target at bottom of screen. */
+ private float mPipDismissHeight;
+
+ public ExpandedAnimationController(Point displaySize) {
+ mDisplaySize = displaySize;
+ }
/**
* Whether the individual bubble has been dragged out of the row of bubbles far enough to cause
@@ -88,6 +98,7 @@ public class ExpandedAnimationController
mBubbleSizePx = res.getDimensionPixelSize(R.dimen.individual_bubble_size);
mStatusBarHeight =
res.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+ mPipDismissHeight = res.getDimensionPixelSize(R.dimen.pip_dismiss_gradient_height);
}
/**
@@ -204,16 +215,19 @@ public class ExpandedAnimationController
/** The Y value of the row of expanded bubbles. */
public float getExpandedY() {
+ boolean showOnTop = mLayout != null
+ && BubbleController.showBubblesAtTop(mLayout.getContext());
final WindowInsets insets = mLayout != null ? mLayout.getRootWindowInsets() : null;
- if (insets != null) {
+ if (showOnTop && insets != null) {
return mBubblePaddingPx + Math.max(
mStatusBarHeight,
insets.getDisplayCutout() != null
? insets.getDisplayCutout().getSafeInsetTop()
: 0);
+ } else {
+ int bottomInset = insets != null ? insets.getSystemWindowInsetBottom() : 0;
+ return mDisplaySize.y - mBubbleSizePx - (mPipDismissHeight - bottomInset);
}
-
- return mBubblePaddingPx;
}
/** Runs the given Runnable after all translation-related animations have ended. */
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index 50dda1c1de6b..fdb0b36ee51e 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -16,6 +16,7 @@
package com.android.systemui.power;
+import android.app.KeyguardManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
@@ -41,6 +42,7 @@ import android.text.style.URLSpan;
import android.util.Log;
import android.util.Slog;
import android.view.View;
+import android.view.WindowManager;
import androidx.annotation.VisibleForTesting;
@@ -48,10 +50,13 @@ import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.settingslib.Utils;
import com.android.settingslib.fuelgauge.BatterySaverUtils;
import com.android.settingslib.utils.PowerUtil;
+import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.SystemUI;
+import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.statusbar.phone.SystemUIDialog;
import com.android.systemui.util.NotificationChannels;
+import com.android.systemui.volume.Events;
import java.io.PrintWriter;
import java.text.NumberFormat;
@@ -118,6 +123,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
private final Context mContext;
private final NotificationManager mNoMan;
private final PowerManager mPowerMan;
+ private final KeyguardManager mKeyguard;
private final Handler mHandler = new Handler(Looper.getMainLooper());
private final Receiver mReceiver = new Receiver();
private final Intent mOpenBatterySettings = settings(Intent.ACTION_POWER_USAGE_SUMMARY);
@@ -141,6 +147,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
private boolean mHighTempWarning;
private SystemUIDialog mHighTempDialog;
private SystemUIDialog mThermalShutdownDialog;
+ @VisibleForTesting SystemUIDialog mUsbHighTempDialog;
/**
*/
@@ -149,6 +156,7 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
mContext = context;
mNoMan = mContext.getSystemService(NotificationManager.class);
mPowerMan = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+ mKeyguard = mContext.getSystemService(KeyguardManager.class);
mReceiver.init();
}
@@ -165,6 +173,8 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
pw.print("mHighTempDialog="); pw.println(mHighTempDialog != null ? "not null" : null);
pw.print("mThermalShutdownDialog=");
pw.println(mThermalShutdownDialog != null ? "not null" : null);
+ pw.print("mUsbHighTempDialog=");
+ pw.println(mUsbHighTempDialog != null ? "not null" : null);
}
private int getLowBatteryAutoTriggerDefaultLevel() {
@@ -434,6 +444,53 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
}
@Override
+ public void showUsbHighTemperatureAlarm() {
+ mHandler.post(() -> showUsbHighTemperatureAlarmInternal());
+ }
+
+ private void showUsbHighTemperatureAlarmInternal() {
+ if (mUsbHighTempDialog != null) {
+ return;
+ }
+
+ final SystemUIDialog d = new SystemUIDialog(mContext, R.style.Theme_SystemUI_Dialog_Alert);
+ d.setCancelable(false);
+ d.setIconAttribute(android.R.attr.alertDialogIcon);
+ d.setTitle(R.string.high_temp_alarm_title);
+ d.setShowForAllUsers(true);
+ d.setMessage(mContext.getString(R.string.high_temp_alarm_notify_message, ""));
+ d.setPositiveButton((com.android.internal.R.string.ok),
+ (dialogInterface, which) -> mUsbHighTempDialog = null);
+ d.setNegativeButton((R.string.high_temp_alarm_help_care_steps),
+ (dialogInterface, which) -> {
+ final String contextString = mContext.getString(
+ R.string.high_temp_alarm_help_url);
+ final Intent helpIntent = new Intent();
+ helpIntent.setClassName("com.android.settings",
+ "com.android.settings.HelpTrampoline");
+ helpIntent.putExtra(Intent.EXTRA_TEXT, contextString);
+ Dependency.get(ActivityStarter.class).startActivity(helpIntent,
+ true /* dismissShade */, resultCode -> {
+ mUsbHighTempDialog = null;
+ });
+ });
+ d.setOnDismissListener(dialogInterface -> {
+ mUsbHighTempDialog = null;
+ Events.writeEvent(mContext, Events.EVENT_DISMISS_USB_OVERHEAT_ALARM,
+ Events.DISMISS_REASON_USB_OVERHEAD_ALARM_CHANGED,
+ mKeyguard.isKeyguardLocked());
+ });
+ d.getWindow().addFlags(WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
+ | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
+ d.show();
+ mUsbHighTempDialog = d;
+
+ Events.writeEvent(mContext, Events.EVENT_SHOW_USB_OVERHEAT_ALARM,
+ Events.SHOW_REASON_USB_OVERHEAD_ALARM_CHANGED,
+ mKeyguard.isKeyguardLocked());
+ }
+
+ @Override
public void updateLowBatteryWarning() {
updateNotification();
}
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
index c43f5728aaa2..e27c25efd88f 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerUI.java
@@ -27,7 +27,6 @@ import android.content.res.Resources;
import android.database.ContentObserver;
import android.os.BatteryManager;
import android.os.Handler;
-import android.os.HardwarePropertiesManager;
import android.os.IBinder;
import android.os.IThermalEventListener;
import android.os.IThermalService;
@@ -43,7 +42,6 @@ import android.util.Log;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.logging.MetricsLogger;
import com.android.settingslib.utils.ThreadUtils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
@@ -71,7 +69,6 @@ public class PowerUI extends SystemUI {
final Receiver mReceiver = new Receiver();
private PowerManager mPowerManager;
- private HardwarePropertiesManager mHardwarePropertiesManager;
private WarningsUI mWarnings;
private final Configuration mLastConfiguration = new Configuration();
private long mTimeRemaining = Long.MAX_VALUE;
@@ -82,30 +79,21 @@ public class PowerUI extends SystemUI {
private boolean mLowWarningShownThisChargeCycle;
private boolean mSevereWarningShownThisChargeCycle;
private Future mLastShowWarningTask;
+ private boolean mEnableSkinTemperatureWarning;
+ private boolean mEnableUsbTemperatureAlarm;
private int mLowBatteryAlertCloseLevel;
private final int[] mLowBatteryReminderLevels = new int[2];
private long mScreenOffTime = -1;
- private float mThresholdTemp;
- private float[] mRecentTemps = new float[MAX_RECENT_TEMPS];
- private int mNumTemps;
- private long mNextLogTime;
@VisibleForTesting IThermalService mThermalService;
@VisibleForTesting int mBatteryLevel = 100;
@VisibleForTesting int mBatteryStatus = BatteryManager.BATTERY_STATUS_UNKNOWN;
- // by using the same instance (method references are not guaranteed to be the same object
- // We create a method reference here so that we are guaranteed that we can remove a callback
- // each time they are created).
- private final Runnable mUpdateTempCallback = this::updateTemperatureWarning;
-
public void start() {
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
- mHardwarePropertiesManager = (HardwarePropertiesManager)
- mContext.getSystemService(Context.HARDWARE_PROPERTIES_SERVICE);
mScreenOffTime = mPowerManager.isScreenOn() ? -1 : SystemClock.elapsedRealtime();
mWarnings = Dependency.get(WarningsUI.class);
mEnhancedEstimates = Dependency.get(EnhancedEstimates.class);
@@ -128,7 +116,7 @@ public class PowerUI extends SystemUI {
// to the temperature being too high.
showThermalShutdownDialog();
- initTemperatureWarning();
+ initTemperature();
}
@Override
@@ -137,7 +125,7 @@ public class PowerUI extends SystemUI {
// Safe to modify mLastConfiguration here as it's only updated by the main thread (here).
if ((mLastConfiguration.updateFrom(newConfig) & mask) != 0) {
- mHandler.post(this::initTemperatureWarning);
+ mHandler.post(this::initTemperature);
}
}
@@ -383,30 +371,16 @@ public class PowerUI extends SystemUI {
return canShowWarning || canShowSevereWarning;
}
- private void initTemperatureWarning() {
+ private void initTemperature() {
ContentResolver resolver = mContext.getContentResolver();
Resources resources = mContext.getResources();
- if (Settings.Global.getInt(resolver, Settings.Global.SHOW_TEMPERATURE_WARNING,
- resources.getInteger(R.integer.config_showTemperatureWarning)) == 0) {
- return;
- }
- mThresholdTemp = Settings.Global.getFloat(resolver, Settings.Global.WARNING_TEMPERATURE,
- resources.getInteger(R.integer.config_warningTemperature));
-
- if (mThresholdTemp < 0f) {
- // Get the shutdown temperature, adjust for warning tolerance.
- float[] throttlingTemps = mHardwarePropertiesManager.getDeviceTemperatures(
- HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
- HardwarePropertiesManager.TEMPERATURE_SHUTDOWN);
- if (throttlingTemps == null
- || throttlingTemps.length == 0
- || throttlingTemps[0] == HardwarePropertiesManager.UNDEFINED_TEMPERATURE) {
- return;
- }
- mThresholdTemp = throttlingTemps[0] -
- resources.getInteger(R.integer.config_warningTemperatureTolerance);
- }
+ mEnableSkinTemperatureWarning = Settings.Global.getInt(resolver,
+ Settings.Global.SHOW_TEMPERATURE_WARNING,
+ resources.getInteger(R.integer.config_showTemperatureWarning)) != 0;
+ mEnableUsbTemperatureAlarm = Settings.Global.getInt(resolver,
+ Settings.Global.SHOW_USB_TEMPERATURE_ALARM,
+ resources.getInteger(R.integer.config_showUsbPortAlarm)) != 0;
if (mThermalService == null) {
// Enable push notifications of throttling from vendor thermal
@@ -416,103 +390,34 @@ public class PowerUI extends SystemUI {
if (b != null) {
mThermalService = IThermalService.Stub.asInterface(b);
- try {
- mThermalService.registerThermalEventListenerWithType(
- new ThermalEventListener(), Temperature.TYPE_SKIN);
- } catch (RemoteException e) {
- // Should never happen.
- }
+ registerThermalEventListener();
} else {
Slog.w(TAG, "cannot find thermalservice, no throttling push notifications");
}
}
-
- setNextLogTime();
-
- // We have passed all of the checks, start checking the temp
- mHandler.post(mUpdateTempCallback);
- }
-
- private void showThermalShutdownDialog() {
- if (mPowerManager.getLastShutdownReason()
- == PowerManager.SHUTDOWN_REASON_THERMAL_SHUTDOWN) {
- mWarnings.showThermalShutdownWarning();
- }
}
@VisibleForTesting
- protected void updateTemperatureWarning() {
- float[] temps = mHardwarePropertiesManager.getDeviceTemperatures(
- HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN,
- HardwarePropertiesManager.TEMPERATURE_CURRENT);
- if (temps.length != 0) {
- float temp = temps[0];
- mRecentTemps[mNumTemps++] = temp;
-
- StatusBar statusBar = getComponent(StatusBar.class);
- if (statusBar != null && !statusBar.isDeviceInVrMode()
- && temp >= mThresholdTemp) {
- logAtTemperatureThreshold(temp);
- mWarnings.showHighTemperatureWarning();
- } else {
- mWarnings.dismissHighTemperatureWarning();
+ void registerThermalEventListener() {
+ try {
+ if (mEnableSkinTemperatureWarning) {
+ mThermalService.registerThermalEventListenerWithType(
+ new ThermalEventSkinListener(), Temperature.TYPE_SKIN);
}
- }
-
- logTemperatureStats();
-
- // Remove any pending callbacks as we only want to enable one
- mHandler.removeCallbacks(mUpdateTempCallback);
- mHandler.postDelayed(mUpdateTempCallback, TEMPERATURE_INTERVAL);
- }
-
- private void logAtTemperatureThreshold(float temp) {
- StringBuilder sb = new StringBuilder();
- sb.append("currentTemp=").append(temp)
- .append(",thresholdTemp=").append(mThresholdTemp)
- .append(",batteryStatus=").append(mBatteryStatus)
- .append(",recentTemps=");
- for (int i = 0; i < mNumTemps; i++) {
- sb.append(mRecentTemps[i]).append(',');
- }
- Slog.i(TAG, sb.toString());
- }
-
- /**
- * Calculates and logs min, max, and average
- * {@link HardwarePropertiesManager#DEVICE_TEMPERATURE_SKIN} over the past
- * {@link #TEMPERATURE_LOGGING_INTERVAL}.
- */
- private void logTemperatureStats() {
- if (mNextLogTime > System.currentTimeMillis() && mNumTemps != MAX_RECENT_TEMPS) {
- return;
- }
-
- if (mNumTemps > 0) {
- float sum = mRecentTemps[0], min = mRecentTemps[0], max = mRecentTemps[0];
- for (int i = 1; i < mNumTemps; i++) {
- float temp = mRecentTemps[i];
- sum += temp;
- if (temp > max) {
- max = temp;
- }
- if (temp < min) {
- min = temp;
- }
+ if (mEnableUsbTemperatureAlarm) {
+ mThermalService.registerThermalEventListenerWithType(
+ new ThermalEventUsbListener(), Temperature.TYPE_USB_PORT);
}
-
- float avg = sum / mNumTemps;
- Slog.i(TAG, "avg=" + avg + ",min=" + min + ",max=" + max);
- MetricsLogger.histogram(mContext, "device_skin_temp_avg", (int) avg);
- MetricsLogger.histogram(mContext, "device_skin_temp_min", (int) min);
- MetricsLogger.histogram(mContext, "device_skin_temp_max", (int) max);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to register thermal callback.", e);
}
- setNextLogTime();
- mNumTemps = 0;
}
- private void setNextLogTime() {
- mNextLogTime = System.currentTimeMillis() + TEMPERATURE_LOGGING_INTERVAL;
+ private void showThermalShutdownDialog() {
+ if (mPowerManager.getLastShutdownReason()
+ == PowerManager.SHUTDOWN_REASON_THERMAL_SHUTDOWN) {
+ mWarnings.showThermalShutdownWarning();
+ }
}
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
@@ -541,34 +446,80 @@ public class PowerUI extends SystemUI {
Settings.Global.LOW_BATTERY_SOUND_TIMEOUT, 0));
pw.print("bucket: ");
pw.println(Integer.toString(findBatteryLevelBucket(mBatteryLevel)));
- pw.print("mThresholdTemp=");
- pw.println(Float.toString(mThresholdTemp));
- pw.print("mNextLogTime=");
- pw.println(Long.toString(mNextLogTime));
+ pw.print("mEnableSkinTemperatureWarning=");
+ pw.println(mEnableSkinTemperatureWarning);
+ pw.print("mEnableUsbTemperatureAlarm=");
+ pw.println(mEnableUsbTemperatureAlarm);
mWarnings.dump(pw);
}
public interface WarningsUI {
void update(int batteryLevel, int bucket, long screenOffTime);
+
void updateEstimate(Estimate estimate);
+
void updateThresholds(long lowThreshold, long severeThreshold);
+
void dismissLowBatteryWarning();
+
void showLowBatteryWarning(boolean playSound);
+
void dismissInvalidChargerWarning();
+
void showInvalidChargerWarning();
+
void updateLowBatteryWarning();
+
boolean isInvalidChargerWarningShowing();
+
void dismissHighTemperatureWarning();
+
void showHighTemperatureWarning();
+
+ /**
+ * Display USB overheat alarm
+ */
+ void showUsbHighTemperatureAlarm();
+
void showThermalShutdownWarning();
+
void dump(PrintWriter pw);
+
void userSwitched();
}
- // Thermal event received from vendor thermal management subsystem
- private final class ThermalEventListener extends IThermalEventListener.Stub {
+ // Thermal event received from thermal service manager subsystem
+ @VisibleForTesting
+ final class ThermalEventSkinListener extends IThermalEventListener.Stub {
@Override public void notifyThrottling(Temperature temp) {
- mHandler.post(mUpdateTempCallback);
+ int status = temp.getStatus();
+
+ if (status >= Temperature.THROTTLING_EMERGENCY) {
+ StatusBar statusBar = getComponent(StatusBar.class);
+ if (statusBar != null && !statusBar.isDeviceInVrMode()) {
+ mWarnings.showHighTemperatureWarning();
+ Slog.d(TAG, "ThermalEventSkinListener: notifyThrottling was called "
+ + ", current skin status = " + status
+ + ", temperature = " + temp.getValue());
+ }
+ } else {
+ mWarnings.dismissHighTemperatureWarning();
+ }
+ }
+ }
+
+ // Thermal event received from thermal service manager subsystem
+ @VisibleForTesting
+ final class ThermalEventUsbListener extends IThermalEventListener.Stub {
+ @Override public void notifyThrottling(Temperature temp) {
+ int status = temp.getStatus();
+
+ if (status >= Temperature.THROTTLING_EMERGENCY) {
+ mWarnings.showUsbHighTemperatureAlarm();
+ Slog.d(TAG, "ThermalEventUsbListener: notifyThrottling was called "
+ + ", current usb port status = " + status
+ + ", temperature = " + temp.getValue());
+ }
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 64ad95c6eaea..c209b315b197 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -38,7 +38,6 @@ import androidx.recyclerview.widget.RecyclerView;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
-import com.android.settingslib.Utils;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QS;
@@ -103,10 +102,6 @@ public class QSCustomizer extends LinearLayout implements OnMenuItemClickListene
mToolbar.getMenu().add(Menu.NONE, MENU_RESET, 0,
mContext.getString(com.android.internal.R.string.reset));
mToolbar.setTitle(R.string.qs_edit);
- int accentColor = Utils.getColorAttrDefaultColor(context, android.R.attr.colorAccent);
- mToolbar.setTitleTextColor(accentColor);
- mToolbar.getNavigationIcon().setTint(accentColor);
- mToolbar.getOverflowIcon().setTint(accentColor);
mRecyclerView = findViewById(android.R.id.list);
mTransparentView = findViewById(R.id.customizer_transparent_view);
mTileAdapter = new TileAdapter(getContext());
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
index a29e93a57c69..608f646e77a4 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileAdapter.java
@@ -19,9 +19,8 @@ import android.app.AlertDialog.Builder;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
-import android.content.res.TypedArray;
import android.graphics.Canvas;
-import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.view.LayoutInflater;
import android.view.View;
@@ -505,13 +504,10 @@ public class TileAdapter extends RecyclerView.Adapter<Holder> implements TileSta
};
private class TileItemDecoration extends ItemDecoration {
- private final ColorDrawable mDrawable;
+ private final Drawable mDrawable;
private TileItemDecoration(Context context) {
- TypedArray ta =
- context.obtainStyledAttributes(new int[]{android.R.attr.colorSecondary});
- mDrawable = new ColorDrawable(ta.getColor(0, 0));
- ta.recycle();
+ mDrawable = context.getDrawable(R.drawable.qs_customize_tile_decoration);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index 52a88145c7ed..3e40cfc0cda2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -22,6 +22,7 @@ import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.provider.Settings;
import android.service.quicksettings.Tile;
+import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
@@ -208,6 +209,9 @@ public class WifiTile extends QSTileImpl<SignalState> {
if (wifiConnected) {
minimalContentDescription.append(cb.wifiSignalContentDescription).append(",");
minimalContentDescription.append(removeDoubleQuotes(cb.ssid));
+ if (!TextUtils.isEmpty(state.secondaryLabel)) {
+ minimalContentDescription.append(",").append(state.secondaryLabel);
+ }
}
}
state.contentDescription = minimalContentDescription.toString();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java b/packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java
index 22d1d5b233ce..d4272605924f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/FlingAnimationUtils.java
@@ -32,6 +32,8 @@ import com.android.systemui.statusbar.phone.StatusBar;
*/
public class FlingAnimationUtils {
+ private static final String TAG = "FlingAnimationUtils";
+
private static final float LINEAR_OUT_SLOW_IN_X2 = 0.35f;
private static final float LINEAR_OUT_SLOW_IN_X2_MAX = 0.68f;
private static final float LINEAR_OUT_FASTER_IN_X2 = 0.5f;
@@ -195,6 +197,10 @@ public class FlingAnimationUtils {
}
private Interpolator getInterpolator(float startGradient, float velocityFactor) {
+ if (Float.isNaN(velocityFactor)) {
+ Log.e(TAG, "Invalid velocity factor", new Throwable());
+ return Interpolators.LINEAR_OUT_SLOW_IN;
+ }
if (startGradient != mCachedStartGradient
|| velocityFactor != mCachedVelocityFactor) {
float speedup = mSpeedUpFactor * (1.0f - velocityFactor);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
index c945afd1cb39..f34b912a255c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationPresenter.java
@@ -15,7 +15,6 @@
*/
package com.android.systemui.statusbar;
-import com.android.systemui.statusbar.notification.NotificationRowBinder;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -27,8 +26,7 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
* want to perform some action before doing so).
*/
public interface NotificationPresenter extends ExpandableNotificationRow.OnExpandClickListener,
- ActivatableNotificationView.OnActivatedListener,
- NotificationRowBinder.BindRowCallback {
+ ActivatableNotificationView.OnActivatedListener {
/**
* Returns true if the presenter is not visible. For example, it may not be necessary to do
* animations if this returns true.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 3fbc64163759..4ed9ae4d5142 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -35,6 +35,7 @@ import com.android.systemui.statusbar.NotificationUpdateHandler;
import com.android.systemui.statusbar.notification.collection.NotificationData;
import com.android.systemui.statusbar.notification.collection.NotificationData.KeyguardEnvironment;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationRowBinder;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
@@ -124,16 +125,7 @@ public class NotificationEntryManager implements
return mRemoteInputManager;
}
- private NotificationRowBinder getRowBinder() {
- if (mNotificationRowBinder == null) {
- mNotificationRowBinder = Dependency.get(NotificationRowBinder.class);
- }
- return mNotificationRowBinder;
- }
-
- // TODO: Remove this once we can always use a mocked row binder in our tests
- @VisibleForTesting
- void setRowBinder(NotificationRowBinder notificationRowBinder) {
+ public void setRowBinder(NotificationRowBinder notificationRowBinder) {
mNotificationRowBinder = notificationRowBinder;
}
@@ -345,7 +337,7 @@ public class NotificationEntryManager implements
Dependency.get(LeakDetector.class).trackInstance(entry);
// Construct the expanded view.
- getRowBinder().inflateViews(entry, () -> performRemoveNotification(notification));
+ requireBinder().inflateViews(entry, () -> performRemoveNotification(notification));
abortExistingInflation(key);
@@ -386,7 +378,7 @@ public class NotificationEntryManager implements
listener.onPreEntryUpdated(entry);
}
- getRowBinder().inflateViews(entry, () -> performRemoveNotification(notification));
+ requireBinder().inflateViews(entry, () -> performRemoveNotification(notification));
updateNotifications();
if (DEBUG) {
@@ -440,7 +432,7 @@ public class NotificationEntryManager implements
// By comparing the old and new UI adjustments, reinflate the view accordingly.
for (NotificationEntry entry : entries) {
- getRowBinder().onNotificationRankingUpdated(
+ requireBinder().onNotificationRankingUpdated(
entry,
oldImportances.get(entry.key),
oldAdjustments.get(entry.key),
@@ -486,4 +478,12 @@ public class NotificationEntryManager implements
activeExtender.setShouldManageLifetime(entry, false);
}
}
+
+ private NotificationRowBinder requireBinder() {
+ if (mNotificationRowBinder == null) {
+ throw new RuntimeException("You must initialize NotificationEntryManager by calling"
+ + "setRowBinder() before using.");
+ }
+ return mNotificationRowBinder;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinder.java
new file mode 100644
index 000000000000..7504e863ca73
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinder.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection;
+
+import android.annotation.Nullable;
+
+import com.android.systemui.statusbar.NotificationUiAdjustment;
+import com.android.systemui.statusbar.notification.InflationException;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+
+/**
+ * Used by the {@link NotificationEntryManager}. When notifications are added or updated, the binder
+ * is asked to (re)inflate and prepare their views. This inflation must occur off the main thread.
+ */
+public interface NotificationRowBinder {
+ /**
+ * Called when a notification has been added or updated. The binder must asynchronously inflate
+ * and bind the views associated with the notification.
+ *
+ * TODO: The caller is notified when the inflation completes, but this is currently a very
+ * roundabout business. Add an explicit completion/failure callback to this method.
+ */
+ void inflateViews(
+ NotificationEntry entry,
+ Runnable onDismissRunnable)
+ throws InflationException;
+
+ /**
+ * Called when the ranking has been updated (but not add or remove has been done). The binder
+ * should inspect the old and new adjustments and re-inflate the entry's views if necessary
+ * (e.g. if something important changed).
+ */
+ void onNotificationRankingUpdated(
+ NotificationEntry entry,
+ @Nullable Integer oldImportance,
+ NotificationUiAdjustment oldAdjustment,
+ NotificationUiAdjustment newAdjustment);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationRowBinder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
index 6f5baf9faf39..b91cdaf9ae80 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationRowBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRowBinderImpl.java
@@ -14,10 +14,9 @@
* limitations under the License.
*/
-package com.android.systemui.statusbar.notification;
+package com.android.systemui.statusbar.notification.collection;
import static com.android.internal.util.Preconditions.checkNotNull;
-import static com.android.systemui.Dependency.ALLOW_NOTIFICATION_LONG_PRESS_NAME;
import static com.android.systemui.statusbar.NotificationRemoteInputManager.ENABLE_REMOTE_INPUT;
import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_AMBIENT;
import static com.android.systemui.statusbar.notification.row.NotificationContentInflater.FLAG_CONTENT_VIEW_HEADS_UP;
@@ -39,7 +38,9 @@ import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.NotificationPresenter;
import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.NotificationUiAdjustment;
-import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.InflationException;
+import com.android.systemui.statusbar.notification.NotificationClicker;
+import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater;
@@ -50,13 +51,8 @@ import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.phone.StatusBar;
import com.android.systemui.statusbar.policy.HeadsUpManager;
-import javax.inject.Inject;
-import javax.inject.Named;
-import javax.inject.Singleton;
-
/** Handles inflating and updating views for notifications. */
-@Singleton
-public class NotificationRowBinder {
+public class NotificationRowBinderImpl implements NotificationRowBinder {
private static final String TAG = "NotificationViewManager";
@@ -84,9 +80,7 @@ public class NotificationRowBinder {
private NotificationClicker mNotificationClicker;
private final NotificationLogger mNotificationLogger = Dependency.get(NotificationLogger.class);
- @Inject
- public NotificationRowBinder(Context context,
- @Named(ALLOW_NOTIFICATION_LONG_PRESS_NAME) boolean allowLongPress) {
+ public NotificationRowBinderImpl(Context context, boolean allowLongPress) {
mContext = context;
mMessagingUtil = new NotificationMessagingUtil(context);
mAllowLongPress = allowLongPress;
@@ -122,6 +116,7 @@ public class NotificationRowBinder {
/**
* Inflates the views for the given entry (possibly asynchronously).
*/
+ @Override
public void inflateViews(
NotificationEntry entry,
Runnable onDismissRunnable)
@@ -192,6 +187,7 @@ public class NotificationRowBinder {
* Updates the views bound to an entry when the entry's ranking changes, either in-place or by
* reinflating them.
*/
+ @Override
public void onNotificationRankingUpdated(
NotificationEntry entry,
@Nullable Integer oldImportance,
@@ -264,7 +260,7 @@ public class NotificationRowBinder {
}
private void logNotificationExpansion(String key, boolean userAction, boolean expanded) {
- mNotificationLogger.onExpansionChanged(key, userAction, expanded);
+ mNotificationLogger.onExpansionChanged(key, userAction, expanded);
}
/** Callback for when a row is bound to an entry. */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java
index cf3f89ef8788..409d60fa6c17 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java
@@ -135,7 +135,7 @@ public class NavBarTintController {
final Bitmap hardBitmap = SurfaceControl
.screenshot(new Rect(), mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels,
mNavigationBarView.getContext().getDisplay().getRotation());
- if (cropRect.bottom <= hardBitmap.getHeight()
+ if (hardBitmap != null && cropRect.bottom <= hardBitmap.getHeight()
&& cropRect.left + cropRect.width() <= hardBitmap.getWidth()) {
final Bitmap cropBitmap = Bitmap.createBitmap(hardBitmap, cropRect.left, cropRect.top,
cropRect.width(), cropRect.height());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index c9fa89e7cb97..faa2ab105816 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -23,18 +23,15 @@ import android.graphics.drawable.Icon;
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
-import android.view.Display;
-import android.view.Display.Mode;
import android.view.Gravity;
import android.view.LayoutInflater;
-import android.view.Surface;
import android.view.View;
import android.view.ViewGroup;
-import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.Space;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.PluginListener;
@@ -84,21 +81,21 @@ public class NavigationBarInflaterView extends FrameLayout
private static final String WEIGHT_CENTERED_SUFFIX = "WC";
private final List<NavBarButtonProvider> mPlugins = new ArrayList<>();
- private final Display mDisplay;
protected LayoutInflater mLayoutInflater;
protected LayoutInflater mLandscapeInflater;
- protected FrameLayout mRot0;
- protected FrameLayout mRot90;
- private boolean isRot0Landscape;
+ protected FrameLayout mHorizontal;
+ protected FrameLayout mVertical;
- private SparseArray<ButtonDispatcher> mButtonDispatchers;
+ @VisibleForTesting
+ SparseArray<ButtonDispatcher> mButtonDispatchers;
private String mCurrentLayout;
private View mLastPortrait;
private View mLastLandscape;
+ private boolean mIsVertical;
private boolean mAlternativeOrder;
private boolean mUsingCustomLayout;
@@ -107,14 +104,11 @@ public class NavigationBarInflaterView extends FrameLayout
public NavigationBarInflaterView(Context context, AttributeSet attrs) {
super(context, attrs);
createInflaters();
- mDisplay = ((WindowManager)
- context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
- Mode displayMode = mDisplay.getMode();
- isRot0Landscape = displayMode.getPhysicalWidth() > displayMode.getPhysicalHeight();
mOverviewProxyService = Dependency.get(OverviewProxyService.class);
}
- private void createInflaters() {
+ @VisibleForTesting
+ void createInflaters() {
mLayoutInflater = LayoutInflater.from(mContext);
Configuration landscape = new Configuration();
landscape.setTo(mContext.getResources().getConfiguration());
@@ -132,13 +126,12 @@ public class NavigationBarInflaterView extends FrameLayout
private void inflateChildren() {
removeAllViews();
- mRot0 = (FrameLayout) mLayoutInflater.inflate(R.layout.navigation_layout, this, false);
- mRot0.setId(R.id.rot0);
- addView(mRot0);
- mRot90 = (FrameLayout) mLayoutInflater.inflate(R.layout.navigation_layout_rot90, this,
- false);
- mRot90.setId(R.id.rot90);
- addView(mRot90);
+ mHorizontal = (FrameLayout) mLayoutInflater.inflate(R.layout.navigation_layout,
+ this /* root */, false /* attachToRoot */);
+ addView(mHorizontal);
+ mVertical = (FrameLayout) mLayoutInflater.inflate(R.layout.navigation_layout_vertical,
+ this /* root */, false /* attachToRoot */);
+ addView(mVertical);
updateAlternativeOrder();
}
@@ -198,12 +191,9 @@ public class NavigationBarInflaterView extends FrameLayout
}
}
- public void updateButtonDispatchersCurrentView() {
+ void updateButtonDispatchersCurrentView() {
if (mButtonDispatchers != null) {
- final int rotation = mDisplay.getRotation();
- final boolean portrait = rotation == Surface.ROTATION_0
- || rotation == Surface.ROTATION_180;
- final View view = portrait ? mRot0 : mRot90;
+ View view = mIsVertical ? mVertical : mHorizontal;
for (int i = 0; i < mButtonDispatchers.size(); i++) {
final ButtonDispatcher dispatcher = mButtonDispatchers.valueAt(i);
dispatcher.setCurrentView(view);
@@ -211,7 +201,13 @@ public class NavigationBarInflaterView extends FrameLayout
}
}
- public void setAlternativeOrder(boolean alternativeOrder) {
+ void setVertical(boolean vertical) {
+ if (vertical != mIsVertical) {
+ mIsVertical = vertical;
+ }
+ }
+
+ void setAlternativeOrder(boolean alternativeOrder) {
if (alternativeOrder != mAlternativeOrder) {
mAlternativeOrder = alternativeOrder;
updateAlternativeOrder();
@@ -219,10 +215,10 @@ public class NavigationBarInflaterView extends FrameLayout
}
private void updateAlternativeOrder() {
- updateAlternativeOrder(mRot0.findViewById(R.id.ends_group));
- updateAlternativeOrder(mRot0.findViewById(R.id.center_group));
- updateAlternativeOrder(mRot90.findViewById(R.id.ends_group));
- updateAlternativeOrder(mRot90.findViewById(R.id.center_group));
+ updateAlternativeOrder(mHorizontal.findViewById(R.id.ends_group));
+ updateAlternativeOrder(mHorizontal.findViewById(R.id.center_group));
+ updateAlternativeOrder(mVertical.findViewById(R.id.ends_group));
+ updateAlternativeOrder(mVertical.findViewById(R.id.center_group));
}
private void updateAlternativeOrder(View v) {
@@ -232,10 +228,10 @@ public class NavigationBarInflaterView extends FrameLayout
}
private void initiallyFill(ButtonDispatcher buttonDispatcher) {
- addAll(buttonDispatcher, (ViewGroup) mRot0.findViewById(R.id.ends_group));
- addAll(buttonDispatcher, (ViewGroup) mRot0.findViewById(R.id.center_group));
- addAll(buttonDispatcher, (ViewGroup) mRot90.findViewById(R.id.ends_group));
- addAll(buttonDispatcher, (ViewGroup) mRot90.findViewById(R.id.center_group));
+ addAll(buttonDispatcher, mHorizontal.findViewById(R.id.ends_group));
+ addAll(buttonDispatcher, mHorizontal.findViewById(R.id.center_group));
+ addAll(buttonDispatcher, mVertical.findViewById(R.id.ends_group));
+ addAll(buttonDispatcher, mVertical.findViewById(R.id.center_group));
}
private void addAll(ButtonDispatcher buttonDispatcher, ViewGroup parent) {
@@ -267,17 +263,23 @@ public class NavigationBarInflaterView extends FrameLayout
String[] center = sets[1].split(BUTTON_SEPARATOR);
String[] end = sets[2].split(BUTTON_SEPARATOR);
// Inflate these in start to end order or accessibility traversal will be messed up.
- inflateButtons(start, mRot0.findViewById(R.id.ends_group), isRot0Landscape, true);
- inflateButtons(start, mRot90.findViewById(R.id.ends_group), !isRot0Landscape, true);
+ inflateButtons(start, mHorizontal.findViewById(R.id.ends_group),
+ false /* landscape */, true /* start */);
+ inflateButtons(start, mVertical.findViewById(R.id.ends_group),
+ true /* landscape */, true /* start */);
- inflateButtons(center, mRot0.findViewById(R.id.center_group), isRot0Landscape, false);
- inflateButtons(center, mRot90.findViewById(R.id.center_group), !isRot0Landscape, false);
+ inflateButtons(center, mHorizontal.findViewById(R.id.center_group),
+ false /* landscape */, false /* start */);
+ inflateButtons(center, mVertical.findViewById(R.id.center_group),
+ true /* landscape */, false /* start */);
- addGravitySpacer(mRot0.findViewById(R.id.ends_group));
- addGravitySpacer(mRot90.findViewById(R.id.ends_group));
+ addGravitySpacer(mHorizontal.findViewById(R.id.ends_group));
+ addGravitySpacer(mVertical.findViewById(R.id.ends_group));
- inflateButtons(end, mRot0.findViewById(R.id.ends_group), isRot0Landscape, false);
- inflateButtons(end, mRot90.findViewById(R.id.ends_group), !isRot0Landscape, false);
+ inflateButtons(end, mHorizontal.findViewById(R.id.ends_group),
+ false /* landscape */, false /* start */);
+ inflateButtons(end, mVertical.findViewById(R.id.ends_group),
+ true /* landscape */, false /* start */);
updateButtonDispatchersCurrentView();
}
@@ -472,8 +474,8 @@ public class NavigationBarInflaterView extends FrameLayout
mButtonDispatchers.valueAt(i).clear();
}
}
- clearAllChildren(mRot0.findViewById(R.id.nav_buttons));
- clearAllChildren(mRot90.findViewById(R.id.nav_buttons));
+ clearAllChildren(mHorizontal.findViewById(R.id.nav_buttons));
+ clearAllChildren(mVertical.findViewById(R.id.nav_buttons));
}
private void clearAllChildren(ViewGroup group) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index d6d3d0807659..f82b05e78ff9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -116,9 +116,11 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
final static boolean ALTERNATE_CAR_MODE_UI = false;
View mCurrentView = null;
- View[] mRotatedViews = new View[4];
+ private View mVertical;
+ private View mHorizontal;
- boolean mVertical;
+ /** Indicates that navigation bar is vertical. */
+ private boolean mIsVertical;
private int mCurrentRotation = -1;
boolean mLongClickableAccessibilityButton;
@@ -350,7 +352,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
public NavigationBarView(Context context, AttributeSet attrs) {
super(context, attrs);
- mVertical = false;
+ mIsVertical = false;
mLongClickableAccessibilityButton = false;
// Set up the context group of buttons
@@ -471,7 +473,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
public void setOnVerticalChangedListener(OnVerticalChangedListener onVerticalChangedListener) {
mOnVerticalChangedListener = onVerticalChangedListener;
- notifyVerticalChangedListener(mVertical);
+ notifyVerticalChangedListener(mIsVertical);
}
@Override
@@ -547,10 +549,6 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
return mCurrentView;
}
- public View[] getAllViews() {
- return mRotatedViews;
- }
-
public ButtonDispatcher getRecentsButton() {
return mButtonDispatchers.get(R.id.recent_apps);
}
@@ -657,7 +655,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
// Animate the back button's rotation to the new degrees and only in portrait move up the
// back button to line up with the other buttons
- float targetY = !mOverviewProxyService.shouldShowSwipeUpUI() && !mVertical && useAltBack
+ float targetY = !mOverviewProxyService.shouldShowSwipeUpUI() && !mIsVertical && useAltBack
? - getResources().getDimension(R.dimen.navbar_back_button_ime_offset)
: 0;
ObjectAnimator navBarAnimator = ObjectAnimator.ofPropertyValuesHolder(drawable,
@@ -669,7 +667,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
}
private void orientHomeButton(KeyButtonDrawable drawable) {
- drawable.setRotation(mVertical ? 90 : 0);
+ drawable.setRotation(mIsVertical ? 90 : 0);
}
private KeyButtonDrawable chooseNavigationIconDrawable(@DrawableRes int icon,
@@ -964,7 +962,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
DockedStackExistsListener.register(mDockedListener);
- updateRotatedViews();
+ updateOrientationViews();
reloadNavIcons();
}
@@ -1028,34 +1026,35 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
view.setTranslationY(posY);
}
- private void updateRotatedViews() {
- mRotatedViews[Surface.ROTATION_0] =
- mRotatedViews[Surface.ROTATION_180] = findViewById(R.id.rot0);
- mRotatedViews[Surface.ROTATION_270] =
- mRotatedViews[Surface.ROTATION_90] = findViewById(R.id.rot90);
+ private void updateOrientationViews() {
+ mHorizontal = findViewById(R.id.horizontal);
+ mVertical = findViewById(R.id.vertical);
updateCurrentView();
}
- public boolean needsReorient(int rotation) {
+ boolean needsReorient(int rotation) {
return mCurrentRotation != rotation;
}
private void updateCurrentView() {
- final int rot = getContextDisplay().getRotation();
- for (int i=0; i<4; i++) {
- mRotatedViews[i].setVisibility(View.GONE);
- }
- mCurrentView = mRotatedViews[rot];
+ resetViews();
+ mCurrentView = mIsVertical ? mVertical : mHorizontal;
mCurrentView.setVisibility(View.VISIBLE);
- mNavigationInflaterView.setAlternativeOrder(rot == Surface.ROTATION_90);
+ mNavigationInflaterView.setVertical(mIsVertical);
+ mCurrentRotation = getContextDisplay().getRotation();
+ mNavigationInflaterView.setAlternativeOrder(mCurrentRotation == Surface.ROTATION_90);
mNavigationInflaterView.updateButtonDispatchersCurrentView();
updateLayoutTransitionsEnabled();
- mCurrentRotation = rot;
+ }
+
+ private void resetViews() {
+ mHorizontal.setVisibility(View.GONE);
+ mVertical.setVisibility(View.GONE);
}
private void updateRecentsIcon() {
- mDockedIcon.setRotation(mDockedStackExists && mVertical ? 90 : 0);
+ mDockedIcon.setRotation(mDockedStackExists && mIsVertical ? 90 : 0);
getRecentsButton().setImageDrawable(mDockedStackExists ? mDockedIcon : mRecentIcon);
mBarTransitions.reapplyDarkIntensity();
}
@@ -1077,7 +1076,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
}
public boolean isVertical() {
- return mVertical;
+ return mIsVertical;
}
public void reorient() {
@@ -1101,7 +1100,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
updateTaskSwitchHelper();
updateNavButtonIcons();
- getHomeButton().setVertical(mVertical);
+ getHomeButton().setVertical(mIsVertical);
}
private void updateTaskSwitchHelper() {
@@ -1134,9 +1133,12 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
"onSizeChanged: (%dx%d) old: (%dx%d)", w, h, oldw, oldh));
final boolean newVertical = w > 0 && h > w;
- if (newVertical != mVertical) {
- mVertical = newVertical;
- //Log.v(TAG, String.format("onSizeChanged: h=%d, w=%d, vert=%s", h, w, mVertical?"y":"n"));
+ if (newVertical != mIsVertical) {
+ mIsVertical = newVertical;
+ if (DEBUG) {
+ Log.d(TAG, String.format("onSizeChanged: h=%d, w=%d, vert=%s", h, w,
+ mIsVertical ? "y" : "n"));
+ }
reorient();
notifyVerticalChangedListener(newVertical);
}
@@ -1347,7 +1349,7 @@ public class NavigationBarView extends FrameLayout implements PluginListener<Nav
pw.println(String.format(" disabled=0x%08x vertical=%s menu=%s darkIntensity=%.2f",
mDisabledFlags,
- mVertical ? "true" : "false",
+ mIsVertical ? "true" : "false",
getMenuButton().isVisible() ? "true" : "false",
getLightTransitionsController().getCurrentDarkIntensity()));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 13d448922ab1..41580f6146de 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -195,9 +195,9 @@ import com.android.systemui.statusbar.notification.NotificationClicker;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
import com.android.systemui.statusbar.notification.NotificationListController;
-import com.android.systemui.statusbar.notification.NotificationRowBinder;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
import com.android.systemui.statusbar.notification.logging.NotificationLogger;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
@@ -390,7 +390,6 @@ public class StatusBar extends SystemUI implements DemoMode,
protected NotificationEntryManager mEntryManager;
private NotificationListController mNotificationListController;
private NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
- private NotificationRowBinder mNotificationRowBinder;
protected NotificationViewHierarchyManager mViewHierarchyManager;
protected ForegroundServiceController mForegroundServiceController;
protected AppOpsController mAppOpsController;
@@ -620,7 +619,6 @@ public class StatusBar extends SystemUI implements DemoMode,
mEntryManager = Dependency.get(NotificationEntryManager.class);
mNotificationInterruptionStateProvider =
Dependency.get(NotificationInterruptionStateProvider.class);
- mNotificationRowBinder = Dependency.get(NotificationRowBinder.class);
mViewHierarchyManager = Dependency.get(NotificationViewHierarchyManager.class);
mForegroundServiceController = Dependency.get(ForegroundServiceController.class);
mAppOpsController = Dependency.get(AppOpsController.class);
@@ -1032,10 +1030,15 @@ public class StatusBar extends SystemUI implements DemoMode,
mStatusBarWindow, this, mNotificationPanel,
(NotificationListContainer) mStackScroller);
+ final NotificationRowBinderImpl rowBinder =
+ new NotificationRowBinderImpl(
+ mContext,
+ SystemUIFactory.getInstance().provideAllowNotificationLongPress());
+
mPresenter = new StatusBarNotificationPresenter(mContext, mNotificationPanel,
mHeadsUpManager, mStatusBarWindow, mStackScroller, mDozeScrimController,
mScrimController, mActivityLaunchAnimator, mStatusBarKeyguardViewManager,
- mNotificationAlertingManager);
+ mNotificationAlertingManager, rowBinder);
mNotificationListController =
new NotificationListController(
@@ -1051,7 +1054,9 @@ public class StatusBar extends SystemUI implements DemoMode,
mNotificationActivityStarter = new StatusBarNotificationActivityStarter(
mContext, mNotificationPanel, mPresenter, mHeadsUpManager, mActivityLaunchAnimator);
mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);
- mNotificationRowBinder.setNotificationClicker(new NotificationClicker(
+
+ mEntryManager.setRowBinder(rowBinder);
+ rowBinder.setNotificationClicker(new NotificationClicker(
this, Dependency.get(BubbleController.class), mNotificationActivityStarter));
mGroupAlertTransferHelper.bind(mEntryManager, mGroupManager);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index 3ce66c5de372..6fe89645ef19 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -64,9 +64,9 @@ import com.android.systemui.statusbar.notification.NotificationAlertingManager;
import com.android.systemui.statusbar.notification.NotificationEntryListener;
import com.android.systemui.statusbar.notification.NotificationEntryManager;
import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
-import com.android.systemui.statusbar.notification.NotificationRowBinder;
import com.android.systemui.statusbar.notification.VisualStabilityManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
@@ -79,7 +79,8 @@ import com.android.systemui.statusbar.policy.KeyguardMonitor;
import java.util.ArrayList;
public class StatusBarNotificationPresenter implements NotificationPresenter,
- ConfigurationController.ConfigurationListener {
+ ConfigurationController.ConfigurationListener,
+ NotificationRowBinderImpl.BindRowCallback {
private final LockscreenGestureLogger mLockscreenGestureLogger =
Dependency.get(LockscreenGestureLogger.class);
@@ -97,8 +98,6 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
(SysuiStatusBarStateController) Dependency.get(StatusBarStateController.class);
private final NotificationEntryManager mEntryManager =
Dependency.get(NotificationEntryManager.class);
- private final NotificationRowBinder mNotificationRowBinder =
- Dependency.get(NotificationRowBinder.class);
private final NotificationInterruptionStateProvider mNotificationInterruptionStateProvider =
Dependency.get(NotificationInterruptionStateProvider.class);
private final NotificationMediaManager mMediaManager =
@@ -140,7 +139,8 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
ScrimController scrimController,
ActivityLaunchAnimator activityLaunchAnimator,
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
- NotificationAlertingManager notificationAlertingManager) {
+ NotificationAlertingManager notificationAlertingManager,
+ NotificationRowBinderImpl notificationRowBinder) {
mContext = context;
mNotificationPanel = panel;
mHeadsUpManager = headsUp;
@@ -217,7 +217,7 @@ public class StatusBarNotificationPresenter implements NotificationPresenter,
mEntryManager.addNotificationLifetimeExtender(mGutsManager);
mEntryManager.addNotificationLifetimeExtenders(
remoteInputManager.getLifetimeExtenders());
- mNotificationRowBinder.setUpWithPresenter(this, notifListContainer, mHeadsUpManager,
+ notificationRowBinder.setUpWithPresenter(this, notifListContainer, mHeadsUpManager,
mEntryManager, this);
mNotificationInterruptionStateProvider.setUpWithPresenter(
this, mHeadsUpManager, this::canHeadsUp);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/Events.java b/packages/SystemUI/src/com/android/systemui/volume/Events.java
index ca55e1f23d20..1596ddbafda0 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/Events.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/Events.java
@@ -53,6 +53,8 @@ public class Events {
public static final int EVENT_TOUCH_LEVEL_DONE = 16; // (stream|int) (level|bool)
public static final int EVENT_ZEN_CONFIG_CHANGED = 17; // (allow/disallow|string)
public static final int EVENT_RINGER_TOGGLE = 18; // (ringer_mode)
+ public static final int EVENT_SHOW_USB_OVERHEAT_ALARM = 19; // (reason|int) (keyguard|bool)
+ public static final int EVENT_DISMISS_USB_OVERHEAT_ALARM = 20; // (reason|int) (keyguard|bool)
private static final String[] EVENT_TAGS = {
"show_dialog",
@@ -73,7 +75,9 @@ public class Events {
"mute_changed",
"touch_level_done",
"zen_mode_config_changed",
- "ringer_toggle"
+ "ringer_toggle",
+ "show_usb_overheat_alarm",
+ "dismiss_usb_overheat_alarm"
};
public static final int DISMISS_REASON_UNKNOWN = 0;
@@ -85,6 +89,7 @@ public class Events {
public static final int DISMISS_REASON_DONE_CLICKED = 6;
public static final int DISMISS_STREAM_GONE = 7;
public static final int DISMISS_REASON_OUTPUT_CHOOSER = 8;
+ public static final int DISMISS_REASON_USB_OVERHEAD_ALARM_CHANGED = 9;
public static final String[] DISMISS_REASONS = {
"unknown",
"touch_outside",
@@ -94,16 +99,19 @@ public class Events {
"settings_clicked",
"done_clicked",
"a11y_stream_changed",
- "output_chooser"
+ "output_chooser",
+ "usb_temperature_below_threshold"
};
public static final int SHOW_REASON_UNKNOWN = 0;
public static final int SHOW_REASON_VOLUME_CHANGED = 1;
public static final int SHOW_REASON_REMOTE_VOLUME_CHANGED = 2;
+ public static final int SHOW_REASON_USB_OVERHEAD_ALARM_CHANGED = 3;
public static final String[] SHOW_REASONS = {
"unknown",
"volume_changed",
- "remote_volume_changed"
+ "remote_volume_changed",
+ "usb_temperature_above_threshold"
};
public static final int ICON_STATE_UNKNOWN = 0;
@@ -181,6 +189,19 @@ public class Events {
case EVENT_SUPPRESSOR_CHANGED:
sb.append(list[0]).append(' ').append(list[1]);
break;
+ case EVENT_SHOW_USB_OVERHEAT_ALARM:
+ MetricsLogger.visible(context, MetricsEvent.POWER_OVERHEAT_ALARM);
+ MetricsLogger.histogram(context, "show_usb_overheat_alarm",
+ (Boolean) list[1] ? 1 : 0);
+ sb.append(SHOW_REASONS[(Integer) list[0]]).append(" keyguard=").append(list[1]);
+ break;
+ case EVENT_DISMISS_USB_OVERHEAT_ALARM:
+ MetricsLogger.hidden(context, MetricsEvent.POWER_OVERHEAT_ALARM);
+ MetricsLogger.histogram(context, "dismiss_usb_overheat_alarm",
+ (Boolean) list[1] ? 1 : 0);
+ sb.append(DISMISS_REASONS[(Integer) list[0]])
+ .append(" keyguard=").append(list[1]);
+ break;
default:
sb.append(Arrays.asList(list));
break;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 617b19104e37..f56727f3e0fa 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -431,8 +431,7 @@ public class VolumeDialogImpl implements VolumeDialog {
if (mSettingsIcon != null) {
mSettingsIcon.setOnClickListener(v -> {
Events.writeEvent(mContext, Events.EVENT_SETTINGS_CLICK);
- Intent intent = new Intent(Settings.ACTION_SOUND_SETTINGS);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ Intent intent = new Intent(Settings.Panel.ACTION_VOLUME);
dismissH(DISMISS_REASON_SETTINGS_CLICKED);
Dependency.get(ActivityStarter.class).startActivity(intent,
true /* dismissShade */);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
index 3bd582f955af..b4059c5db3b6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/animation/ExpandedAnimationControllerTest.java
@@ -19,6 +19,7 @@ package com.android.systemui.bubbles.animation;
import static org.junit.Assert.assertEquals;
import android.content.res.Resources;
+import android.graphics.Point;
import android.graphics.PointF;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
@@ -40,7 +41,8 @@ import org.mockito.Spy;
public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestCase {
@Spy
- private ExpandedAnimationController mExpandedController = new ExpandedAnimationController();
+ private ExpandedAnimationController mExpandedController =
+ new ExpandedAnimationController(new Point(500, 1000) /* displaySize */);
private int mStackOffset;
private float mBubblePadding;
@@ -167,7 +169,7 @@ public class ExpandedAnimationControllerTest extends PhysicsAnimationLayoutTestC
assertEquals(mBubblePadding + (i * (mBubbleSize + mBubblePadding)),
mLayout.getChildAt(i).getTranslationX(),
2f);
- assertEquals(mBubblePadding + mCutoutInsetSize,
+ assertEquals(mExpandedController.getExpandedY(),
mLayout.getChildAt(i).getTranslationY(), 2f);
if (i < mMaxRenderedBubbles) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
index bf6cc53aa5e9..cd500b4c38f9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerNotificationWarningsTest.java
@@ -16,9 +16,8 @@
package com.android.systemui.power;
-import static android.test.MoreAsserts.assertNotEqual;
+import static com.google.common.truth.Truth.assertThat;
-import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
@@ -38,7 +37,6 @@ import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.util.NotificationChannels;
-import java.util.concurrent.TimeUnit;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -151,4 +149,13 @@ public class PowerNotificationWarningsTest extends SysuiTestCase {
verify(mMockNotificationManager, times(1)).cancelAsUser(anyString(),
eq(SystemMessage.NOTE_THERMAL_SHUTDOWN), any());
}
+
+ @Test
+ public void testShowUsbHighTemperatureAlarm() {
+ mPowerNotificationWarnings.showUsbHighTemperatureAlarm();
+ waitForIdleSync(mContext.getMainThreadHandler());
+ assertThat(mPowerNotificationWarnings.mUsbHighTempDialog).isNotNull();
+
+ mPowerNotificationWarnings.mUsbHighTempDialog.dismiss();
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
index c28e74e7c6a1..0aed63d25112 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/power/PowerUITest.java
@@ -14,14 +14,14 @@
package com.android.systemui.power;
-import static android.os.HardwarePropertiesManager.DEVICE_TEMPERATURE_SKIN;
-import static android.os.HardwarePropertiesManager.TEMPERATURE_CURRENT;
-import static android.os.HardwarePropertiesManager.TEMPERATURE_SHUTDOWN;
import static android.provider.Settings.Global.SHOW_TEMPERATURE_WARNING;
+import static android.provider.Settings.Global.SHOW_USB_TEMPERATURE_ALARM;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.anyObject;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -31,9 +31,10 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.Intent;
import android.os.BatteryManager;
-import android.os.HardwarePropertiesManager;
+import android.os.IThermalEventListener;
import android.os.IThermalService;
import android.os.PowerManager;
+import android.os.Temperature;
import android.provider.Settings;
import android.test.suitebuilder.annotation.SmallTest;
import android.testing.AndroidTestingRunner;
@@ -74,97 +75,104 @@ public class PowerUITest extends SysuiTestCase {
private static final int OLD_BATTERY_LEVEL_NINE = 9;
private static final int OLD_BATTERY_LEVEL_10 = 10;
private static final long VERY_BELOW_SEVERE_HYBRID_THRESHOLD = TimeUnit.MINUTES.toMillis(15);
- private HardwarePropertiesManager mHardProps;
private WarningsUI mMockWarnings;
private PowerUI mPowerUI;
private EnhancedEstimates mEnhancedEstimates;
@Mock private PowerManager mPowerManager;
@Mock private IThermalService mThermalServiceMock;
+ private IThermalEventListener mThermalEventUsbListener;
+ private IThermalEventListener mThermalEventSkinListener;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mMockWarnings = mDependency.injectMockDependency(WarningsUI.class);
mEnhancedEstimates = mDependency.injectMockDependency(EnhancedEstimates.class);
- mHardProps = mock(HardwarePropertiesManager.class);
mContext.putComponent(StatusBar.class, mock(StatusBar.class));
- mContext.addMockSystemService(Context.HARDWARE_PROPERTIES_SERVICE, mHardProps);
mContext.addMockSystemService(Context.POWER_SERVICE, mPowerManager);
createPowerUi();
+ mThermalEventSkinListener = mPowerUI.new ThermalEventSkinListener();
+ mThermalEventUsbListener = mPowerUI.new ThermalEventUsbListener();
}
@Test
- public void testNoConfig_NoWarnings() {
- setOverThreshold();
- Settings.Global.putString(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, null);
- TestableResources resources = mContext.getOrCreateTestableResources();
- resources.addOverride(R.integer.config_showTemperatureWarning, 0);
- resources.addOverride(R.integer.config_warningTemperature, 55);
-
+ public void testSkinWarning_throttlingCritical() throws Exception {
mPowerUI.start();
+
+ final Temperature temp = getCriticalStatusTemp(Temperature.TYPE_SKIN, "skin1");
+ mThermalEventSkinListener.notifyThrottling(temp);
+
+ // dismiss skin high temperature warning when throttling status is critical
+ TestableLooper.get(this).processAllMessages();
verify(mMockWarnings, never()).showHighTemperatureWarning();
+ verify(mMockWarnings, times(1)).dismissHighTemperatureWarning();
}
@Test
- public void testConfig_NoWarnings() {
- setUnderThreshold();
- Settings.Global.putString(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, null);
- TestableResources resources = mContext.getOrCreateTestableResources();
- resources.addOverride(R.integer.config_showTemperatureWarning, 1);
- resources.addOverride(R.integer.config_warningTemperature, 55);
-
+ public void testSkinWarning_throttlingEmergency() throws Exception {
mPowerUI.start();
- verify(mMockWarnings, never()).showHighTemperatureWarning();
+
+ final Temperature temp = getEmergencyStatusTemp(Temperature.TYPE_SKIN, "skin2");
+ mThermalEventSkinListener.notifyThrottling(temp);
+
+ // show skin high temperature warning when throttling status is emergency
+ TestableLooper.get(this).processAllMessages();
+ verify(mMockWarnings, times(1)).showHighTemperatureWarning();
+ verify(mMockWarnings, never()).dismissHighTemperatureWarning();
}
@Test
- public void testConfig_Warnings() {
- setOverThreshold();
- Settings.Global.putString(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, null);
- TestableResources resources = mContext.getOrCreateTestableResources();
- resources.addOverride(R.integer.config_showTemperatureWarning, 1);
- resources.addOverride(R.integer.config_warningTemperature, 55);
+ public void testUsbAlarm_throttlingCritical() throws Exception {
+ mPowerUI.start();
+
+ final Temperature temp = getCriticalStatusTemp(Temperature.TYPE_USB_PORT, "usb1");
+ mThermalEventUsbListener.notifyThrottling(temp);
+ // not show usb high temperature alarm when throttling status is critical
+ TestableLooper.get(this).processAllMessages();
+ verify(mMockWarnings, never()).showUsbHighTemperatureAlarm();
+ }
+
+ @Test
+ public void testUsbAlarm_throttlingEmergency() throws Exception {
mPowerUI.start();
- // Guarantees mHandler has processed all messages.
+
+ final Temperature temp = getEmergencyStatusTemp(Temperature.TYPE_USB_PORT, "usb2");
+ mThermalEventUsbListener.notifyThrottling(temp);
+
+ // show usb high temperature alarm when throttling status is emergency
TestableLooper.get(this).processAllMessages();
- verify(mMockWarnings).showHighTemperatureWarning();
+ verify(mMockWarnings, times(1)).showUsbHighTemperatureAlarm();
}
@Test
- public void testSettingOverrideConfig() {
- setOverThreshold();
+ public void testSettingOverrideConfig_enableSkinTemperatureWarning() throws Exception {
Settings.Global.putInt(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, 1);
TestableResources resources = mContext.getOrCreateTestableResources();
resources.addOverride(R.integer.config_showTemperatureWarning, 0);
- resources.addOverride(R.integer.config_warningTemperature, 55);
mPowerUI.start();
- // Guarantees mHandler has processed all messages.
+ mPowerUI.registerThermalEventListener();
+
TestableLooper.get(this).processAllMessages();
- verify(mMockWarnings).showHighTemperatureWarning();
+ verify(mThermalServiceMock, times(1))
+ .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_SKIN));
}
@Test
- public void testShutdownBasedThreshold() {
- int tolerance = 2;
- Settings.Global.putString(mContext.getContentResolver(), SHOW_TEMPERATURE_WARNING, null);
+ public void testSettingOverrideConfig_enableUsbTemperatureAlarm() throws Exception {
+ Settings.Global.putInt(mContext.getContentResolver(), SHOW_USB_TEMPERATURE_ALARM, 1);
TestableResources resources = mContext.getOrCreateTestableResources();
- resources.addOverride(R.integer.config_showTemperatureWarning, 1);
- resources.addOverride(R.integer.config_warningTemperature, -1);
- resources.addOverride(R.integer.config_warningTemperatureTolerance, tolerance);
- when(mHardProps.getDeviceTemperatures(DEVICE_TEMPERATURE_SKIN, TEMPERATURE_SHUTDOWN))
- .thenReturn(new float[] { 55 + tolerance });
+ resources.addOverride(R.integer.config_showUsbPortAlarm, 0);
- setCurrentTemp(54); // Below threshold.
mPowerUI.start();
- verify(mMockWarnings, never()).showHighTemperatureWarning();
+ mPowerUI.registerThermalEventListener();
- setCurrentTemp(56); // Above threshold.
- mPowerUI.updateTemperatureWarning();
- verify(mMockWarnings).showHighTemperatureWarning();
+ TestableLooper.get(this).processAllMessages();
+ verify(mThermalServiceMock, times(1))
+ .registerThermalEventListenerWithType(anyObject(), eq(Temperature.TYPE_USB_PORT));
}
@Test
@@ -532,17 +540,14 @@ public class PowerUITest extends SysuiTestCase {
verify(mEnhancedEstimates, times(2)).getEstimate();
}
- private void setCurrentTemp(float temp) {
- when(mHardProps.getDeviceTemperatures(DEVICE_TEMPERATURE_SKIN, TEMPERATURE_CURRENT))
- .thenReturn(new float[] { temp });
- }
-
- private void setOverThreshold() {
- setCurrentTemp(50000);
+ private Temperature getEmergencyStatusTemp(int type, String name) {
+ final float value = 65;
+ return new Temperature(value, type, name, Temperature.THROTTLING_EMERGENCY);
}
- private void setUnderThreshold() {
- setCurrentTemp(5);
+ private Temperature getCriticalStatusTemp(int type, String name) {
+ final float value = 60;
+ return new Temperature(value, type, name, Temperature.THROTTLING_CRITICAL);
}
private void createPowerUi() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index 04e7cab406ea..0d4328f94a39 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -67,6 +67,8 @@ import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.collection.NotificationData;
import com.android.systemui.statusbar.notification.collection.NotificationData.KeyguardEnvironment;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationRowBinder;
+import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
@@ -102,10 +104,8 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
@Mock private KeyguardEnvironment mEnvironment;
@Mock private ExpandableNotificationRow mRow;
@Mock private NotificationListContainer mListContainer;
- @Mock
- private NotificationEntryListener mEntryListener;
- @Mock
- private NotificationRowBinder.BindRowCallback mBindCallback;
+ @Mock private NotificationEntryListener mEntryListener;
+ @Mock private NotificationRowBinderImpl.BindRowCallback mBindCallback;
@Mock private HeadsUpManager mHeadsUpManager;
@Mock private NotificationListenerService.RankingMap mRankingMap;
@Mock private RemoteInputController mRemoteInputController;
@@ -235,10 +235,12 @@ public class NotificationEntryManagerTest extends SysuiTestCase {
mEntryManager.setUpWithPresenter(mPresenter, mListContainer, mHeadsUpManager);
mEntryManager.addNotificationEntryListener(mEntryListener);
- NotificationRowBinder notificationRowBinder = Dependency.get(NotificationRowBinder.class);
+ NotificationRowBinderImpl notificationRowBinder =
+ new NotificationRowBinderImpl(mContext, true /* allowLongPress */);
notificationRowBinder.setUpWithPresenter(
mPresenter, mListContainer, mHeadsUpManager, mEntryManager, mBindCallback);
notificationRowBinder.setNotificationClicker(mock(NotificationClicker.class));
+ mEntryManager.setRowBinder(notificationRowBinder);
setUserSentiment(mEntry.key, NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL);
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarInflaterViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarInflaterViewTest.java
new file mode 100644
index 000000000000..093749adf1c3
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarInflaterViewTest.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.util.SparseArray;
+import android.view.View;
+import android.widget.FrameLayout;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.CommandQueue;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/** atest NavigationBarInflaterViewTest */
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+@SmallTest
+public class NavigationBarInflaterViewTest extends SysuiTestCase {
+
+ private NavigationBarInflaterView mNavBarInflaterView;
+
+ private static final int BUTTON_ID = 0;
+
+ @Before
+ public void setUp() {
+ mContext.putComponent(CommandQueue.class, mock(CommandQueue.class));
+
+ mNavBarInflaterView = spy(new NavigationBarInflaterView(mContext, null));
+ doNothing().when(mNavBarInflaterView).createInflaters();
+
+ mNavBarInflaterView.mButtonDispatchers = new SparseArray<>(1);
+ mNavBarInflaterView.mButtonDispatchers.put(BUTTON_ID, new ButtonDispatcher(BUTTON_ID));
+
+ initializeViews();
+ }
+
+ private void initializeViews() {
+ mNavBarInflaterView.mVertical = mock(FrameLayout.class);
+ mNavBarInflaterView.mHorizontal = mock(FrameLayout.class);
+ initializeLayout(mNavBarInflaterView.mVertical);
+ initializeLayout(mNavBarInflaterView.mHorizontal);
+ }
+
+ private void initializeLayout(FrameLayout layout) {
+ View verticalChildView = mock(View.class);
+ verticalChildView.setId(BUTTON_ID);
+ doReturn(layout).when(verticalChildView).getParent();
+ doReturn(verticalChildView).when(layout).findViewById(BUTTON_ID);
+ }
+
+ @After
+ public void tearDown() {
+ mNavBarInflaterView = null;
+ }
+
+ @Test
+ public void testUpdateButtonDispatchersCurrentView_isVerticalTrue() {
+ mNavBarInflaterView.setVertical(true);
+
+ mNavBarInflaterView.updateButtonDispatchersCurrentView();
+
+ ButtonDispatcher button = mNavBarInflaterView.mButtonDispatchers.get(BUTTON_ID);
+ assertEquals("Buttons need to be set to vertical layout",
+ mNavBarInflaterView.mVertical.getId(),
+ ((View) button.getCurrentView().getParent()).getId());
+ }
+
+ @Test
+ public void testUpdateButtonDispatchersCurrentView_isVerticalFalse() {
+ mNavBarInflaterView.setVertical(false);
+
+ mNavBarInflaterView.updateButtonDispatchersCurrentView();
+
+ ButtonDispatcher button = mNavBarInflaterView.mButtonDispatchers.get(BUTTON_ID);
+ assertEquals("Buttons need to be set to horizon layout",
+ mNavBarInflaterView.mHorizontal.getId(),
+ ((View) button.getCurrentView().getParent()).getId());
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
index e4da859946af..f72d4119b50c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/ScrimControllerTest.java
@@ -38,6 +38,7 @@ import android.app.AlarmManager;
import android.graphics.Color;
import android.os.Handler;
import android.os.Looper;
+import android.support.test.filters.FlakyTest;
import android.support.test.filters.SmallTest;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -251,6 +252,7 @@ public class ScrimControllerTest extends SysuiTestCase {
assertScrimTint(mScrimBehind, false /* tinted */);
}
+ @FlakyTest(bugId = 124858892)
@Test
public void transitionToUnlocked() {
mScrimController.setPanelExpansion(0f);
@@ -295,6 +297,7 @@ public class ScrimControllerTest extends SysuiTestCase {
Assert.assertEquals(mScrimState, ScrimState.BOUNCER_SCRIMMED);
}
+ @FlakyTest(bugId = 124858892)
@Test
public void panelExpansion() {
mScrimController.setPanelExpansion(0f);
@@ -317,6 +320,7 @@ public class ScrimControllerTest extends SysuiTestCase {
mScrimBehindAlpha, mScrimBehind.getViewAlpha(), 0.01f);
}
+ @FlakyTest(bugId = 124858892)
@Test
public void panelExpansionAffectsAlpha() {
mScrimController.setPanelExpansion(0f);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
index 12cb99575fb6..d2b0f7f95967 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
@@ -41,6 +41,7 @@ import com.android.systemui.statusbar.CommandQueue;
import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
import com.android.systemui.statusbar.notification.NotificationAlertingManager;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationRowBinderImpl;
import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
@@ -74,7 +75,8 @@ public class StatusBarNotificationPresenterTest extends SysuiTestCase {
statusBarWindowView, mock(NotificationListContainerViewGroup.class),
mock(DozeScrimController.class), mock(ScrimController.class),
mock(ActivityLaunchAnimator.class), mock(StatusBarKeyguardViewManager.class),
- mock(NotificationAlertingManager.class));
+ mock(NotificationAlertingManager.class),
+ mock(NotificationRowBinderImpl.class));
}
@Test
diff --git a/proto/Android.bp b/proto/Android.bp
index 817a54d93268..7b119a771ba4 100644
--- a/proto/Android.bp
+++ b/proto/Android.bp
@@ -6,6 +6,7 @@ java_library_static {
},
srcs: ["src/**/*.proto"],
no_framework_libs: true,
+ sdk_version: "9",
// Pin java_version until jarjar is certified to support later versions. http://b/72703434
java_version: "1.8",
target: {
@@ -27,14 +28,4 @@ java_library_static {
srcs: ["src/metrics_constants/metrics_constants.proto"],
no_framework_libs: true,
sdk_version: "system_current",
- // Pin java_version until jarjar is certified to support later versions. http://b/72703434
- java_version: "1.8",
- target: {
- android: {
- jarjar_rules: "jarjar-rules.txt",
- },
- host: {
- static_libs: ["libprotobuf-java-nano"],
- },
- },
}
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index 530d1156a5e4..b3e5f693d530 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -247,6 +247,12 @@ message MetricsEvent {
LOCATION_GONE = 6; // the view isn't laid out at all
}
+ // Subtypes for profile logging
+ enum ActiveUserProfile {
+ PARENT_PROFILE = 1;
+ MANAGED_PROFILE = 2;
+ }
+
// Known visual elements: views or controls.
enum View {
// Unknown view
@@ -3589,7 +3595,7 @@ message MetricsEvent {
// OPEN: Settings > Apps > Default Apps > Default sms
DEFAULT_SMS_PICKER = 789;
- // OPEN: Settings > Apps > Default Apps > Default notification assistant
+ // OPEN: Settings > Apps > Notification > Notification Assistant
DEFAULT_NOTIFICATION_ASSISTANT = 790;
// OPEN: Settings > Apps > Default Apps > Warning dialog to confirm selection
@@ -6162,6 +6168,11 @@ message MetricsEvent {
// OS: P
FIELD_AUTOFILL_SESSION_ID = 1456;
+ // FIELD: Device USB overheat alarm trigger.
+ // CATEGORY: GLOBAL_SYSTEM_UI
+ // OS: P
+ POWER_OVERHEAT_ALARM = 1457;
+
// ---- End P Constants, all P constants go above this line ----
// Time since this notification last interrupted (visibly or audible) the user
@@ -7002,6 +7013,10 @@ message MetricsEvent {
// Different display can have different orientations, so need to log display id
FIELD_DISPLAY_ID = 1660;
+ // ACTION: Changing from work to parent profile or vice versa
+ // OS: Q
+ ACTION_SWITCH_SHARE_PROFILE = 1661;
+
// ---- End Q Constants, all Q constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/proto/src/wifi.proto b/proto/src/wifi.proto
index ee3777db1e05..5fa7766ea510 100644
--- a/proto/src/wifi.proto
+++ b/proto/src/wifi.proto
@@ -521,6 +521,9 @@ message WifiLog {
// Total number of saved networks with mac randomization enabled.
optional int32 num_saved_networks_with_mac_randomization = 138;
+
+ // Link Probe metrics
+ optional LinkProbeStats link_probe_stats = 139;
}
// Information that gets logged for every WiFi connection.
@@ -1959,7 +1962,6 @@ message DeviceMobilityStatePnoScanStats {
// The total duration elapsed while in this mobility state, in ms
optional int64 total_duration_ms = 3;
-
// the total duration elapsed while in this mobility state with PNO scans running, in ms
optional int64 pno_duration_ms = 4;
}
@@ -2211,3 +2213,76 @@ message WifiConfigStoreIO {
optional int32 count = 3;
}
}
+
+// Histogram bucket counting with int32. Range is [start, end)
+message HistogramBucketInt32 {
+ // lower range of the bucket (inclusive)
+ optional int32 start = 1;
+
+ // upper range of the bucket (exclusive)
+ optional int32 end = 2;
+
+ // number of samples in the bucket
+ optional int32 count = 3;
+}
+
+// Single entry in a map from int32 => int32
+message MapEntryInt32Int32 {
+ // the key
+ optional int32 key = 1;
+
+ // the value
+ optional int32 value = 2;
+}
+
+message LinkProbeStats {
+ enum LinkProbeFailureReason {
+ // unknown reason
+ LINK_PROBE_FAILURE_REASON_UNKNOWN = 0;
+
+ // Specified MCS rate when it is unsupported by the driver.
+ LINK_PROBE_FAILURE_REASON_MCS_UNSUPPORTED = 1;
+
+ // Driver reported that no ACK was received for the transmitted probe.
+ LINK_PROBE_FAILURE_REASON_NO_ACK = 2;
+
+ // Driver failed to report on the status of the transmitted probe within the timeout.
+ LINK_PROBE_FAILURE_REASON_TIMEOUT = 3;
+
+ // An existing link probe is in progress.
+ LINK_PROBE_FAILURE_REASON_ALREADY_STARTED = 4;
+ }
+
+ // Counts the number of failures for each failure reason.
+ message LinkProbeFailureReasonCount {
+ // The failure reason.
+ optional LinkProbeFailureReason failure_reason = 1;
+
+ // The number of occurrences for this failure reason.
+ optional int32 count = 2;
+ }
+
+ // Counts the occurrences of RSSI values when a link probe succeeds.
+ repeated MapEntryInt32Int32 success_rssi_counts = 1;
+
+ // Counts the occurrences of RSSI values when a link probe fails.
+ repeated MapEntryInt32Int32 failure_rssi_counts = 2;
+
+ // Counts the occurrences of Link Speed values when a link probe succeeds.
+ repeated MapEntryInt32Int32 success_link_speed_counts = 3;
+
+ // Counts the occurrences of Link Speed values when a link probe fails.
+ repeated MapEntryInt32Int32 failure_link_speed_counts = 4;
+
+ // Histogram for the number of seconds since the last TX success when a link probe succeeds.
+ repeated HistogramBucketInt32 success_seconds_since_last_tx_success_histogram = 5;
+
+ // Histogram for the number of seconds since the last TX success when a link probe fails.
+ repeated HistogramBucketInt32 failure_seconds_since_last_tx_success_histogram = 6;
+
+ // Histogram for the elapsed time of successful link probes, in ms.
+ repeated HistogramBucketInt32 success_elapsed_time_ms_histogram = 7;
+
+ // Counts the occurrences of error codes for failed link probes.
+ repeated LinkProbeFailureReasonCount failure_reason_counts = 8;
+}
diff --git a/services/art-profile b/services/art-profile
index e7503806edfe..7892fcb79822 100644
--- a/services/art-profile
+++ b/services/art-profile
@@ -2942,7 +2942,7 @@ HSPLcom/android/server/policy/WindowManagerPolicy;->onConfigurationChanged()V
HSPLcom/android/server/policy/WindowManagerPolicy;->onKeyguardOccludedChangedLw(Z)V
HSPLcom/android/server/policy/WindowManagerPolicy;->onLockTaskStateChangedLw(I)V
HSPLcom/android/server/policy/WindowManagerPolicy;->onSystemUiStarted()V
-HSPLcom/android/server/policy/WindowManagerPolicy;->performHapticFeedbackLw(Lcom/android/server/policy/WindowManagerPolicy$WindowState;IZ)Z
+HSPLcom/android/server/policy/WindowManagerPolicy;->performHapticFeedback(ILjava/lang/String;IZ)Z
HSPLcom/android/server/policy/WindowManagerPolicy;->prepareAddWindowLw(Lcom/android/server/policy/WindowManagerPolicy$WindowState;Landroid/view/WindowManager$LayoutParams;)I
HSPLcom/android/server/policy/WindowManagerPolicy;->registerShortcutKey(JLcom/android/internal/policy/IShortcutService;)V
HSPLcom/android/server/policy/WindowManagerPolicy;->removeWindowLw(Lcom/android/server/policy/WindowManagerPolicy$WindowState;)V
@@ -15736,7 +15736,7 @@ PLcom/android/server/policy/PhoneWindowManager;->onConfigurationChanged()V
PLcom/android/server/policy/PhoneWindowManager;->onKeyguardOccludedChangedLw(Z)V
PLcom/android/server/policy/PhoneWindowManager;->onOverlayChangedLw()V
PLcom/android/server/policy/PhoneWindowManager;->onSystemUiStarted()V
-PLcom/android/server/policy/PhoneWindowManager;->performHapticFeedbackLw(Lcom/android/server/policy/WindowManagerPolicy$WindowState;IZ)Z
+PLcom/android/server/policy/PhoneWindowManager;->performHapticFeedback(ILjava/lang/String;IZ)Z
PLcom/android/server/policy/PhoneWindowManager;->powerPress(JZI)V
PLcom/android/server/policy/PhoneWindowManager;->prepareAddWindowLw(Lcom/android/server/policy/WindowManagerPolicy$WindowState;Landroid/view/WindowManager$LayoutParams;)I
PLcom/android/server/policy/PhoneWindowManager;->readCameraLensCoverState()V
@@ -18331,7 +18331,7 @@ PLcom/android/server/wm/Session;->getWindowId(Landroid/os/IBinder;)Landroid/view
PLcom/android/server/wm/Session;->killSessionLocked()V
PLcom/android/server/wm/Session;->onRectangleOnScreenRequested(Landroid/os/IBinder;Landroid/graphics/Rect;)V
PLcom/android/server/wm/Session;->onWindowSurfaceVisibilityChanged(Lcom/android/server/wm/WindowSurfaceController;ZI)V
-PLcom/android/server/wm/Session;->performHapticFeedback(Landroid/view/IWindow;IZ)Z
+PLcom/android/server/wm/Session;->performHapticFeedback(IZ)Z
PLcom/android/server/wm/Session;->relayout(Landroid/view/IWindow;ILandroid/view/WindowManager$LayoutParams;IIIIJLandroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/graphics/Rect;Landroid/view/DisplayCutout$ParcelableWrapper;Landroid/util/MergedConfiguration;Landroid/view/Surface;)I
PLcom/android/server/wm/Session;->remove(Landroid/view/IWindow;)V
PLcom/android/server/wm/Session;->sendWallpaperCommand(Landroid/os/IBinder;Ljava/lang/String;IIILandroid/os/Bundle;Z)Landroid/os/Bundle;
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index e0fb33799ff7..1cca813ece25 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -30,6 +30,7 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManagerInternal;
import android.app.ActivityThread;
+import android.content.AutofillOptions;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentResolver;
@@ -699,12 +700,31 @@ public final class AutofillManagerService
}
@Override
- public boolean isCompatibilityModeRequested(@NonNull String packageName,
+ public AutofillOptions getAutofillOptions(@NonNull String packageName,
long versionCode, @UserIdInt int userId) {
- return mAutofillCompatState.isCompatibilityModeRequested(
+ final int loggingLevel;
+ if (verbose) {
+ loggingLevel = AutofillManager.FLAG_ADD_CLIENT_VERBOSE
+ | AutofillManager.FLAG_ADD_CLIENT_DEBUG;
+ } else if (debug) {
+ loggingLevel = AutofillManager.FLAG_ADD_CLIENT_DEBUG;
+ } else {
+ loggingLevel = AutofillManager.NO_LOGGING;
+ }
+ final boolean compatModeEnabled = mAutofillCompatState.isCompatibilityModeRequested(
packageName, versionCode, userId);
- }
+ final AutofillOptions options = new AutofillOptions(loggingLevel, compatModeEnabled);
+ synchronized (mLock) {
+ final AutofillManagerServiceImpl service =
+ getServiceForUserLocked(UserHandle.getCallingUserId());
+ if (service != null) {
+ service.setAugmentedAutofillWhitelistLocked(options, packageName);
+ }
+ }
+
+ return options;
+ }
}
/**
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
index 15dce4af405b..b6d5b3de4c2d 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
@@ -28,6 +28,7 @@ import android.annotation.Nullable;
import android.app.ActivityManagerInternal;
import android.app.ActivityTaskManager;
import android.app.IActivityTaskManager;
+import android.content.AutofillOptions;
import android.content.ComponentName;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -1084,6 +1085,7 @@ final class AutofillManagerServiceImpl
if (remoteService != null) {
remoteService.destroy();
}
+ mRemoteAugmentedAutofillService = null;
}
}, mMaster.isInstantServiceAllowed(), mMaster.verbose);
}
@@ -1095,14 +1097,17 @@ final class AutofillManagerServiceImpl
* Called when the {@link #mAugmentedAutofillResolver} changed (among other places).
*/
private void updateRemoteAugmentedAutofillService(@Nullable String serviceName) {
- if (serviceName == null) {
- if (sVerbose) Slog.v(TAG, "updateRemoteAugmentedAutofillService(): time's up!");
- synchronized (mLock) {
- if (mRemoteAugmentedAutofillService != null) {
- mRemoteAugmentedAutofillService.destroy();
- mRemoteAugmentedAutofillService = null;
+ synchronized (mLock) {
+ if (mRemoteAugmentedAutofillService != null) {
+ if (sVerbose) {
+ Slog.v(TAG, "updateRemoteAugmentedAutofillService(): "
+ + "destroying old remote service");
}
+ mRemoteAugmentedAutofillService.destroy();
+ mRemoteAugmentedAutofillService = null;
}
+
+ mRemoteAugmentedAutofillService = getRemoteAugmentedAutofillServiceLocked();
}
}
@@ -1169,6 +1174,13 @@ final class AutofillManagerServiceImpl
return mWhitelistedAugmentAutofillPackages.contains(packageName);
}
+ @GuardedBy("mLock")
+ void setAugmentedAutofillWhitelistLocked(@NonNull AutofillOptions options,
+ @NonNull String packageName) {
+ // TODO(b/122595322): need to setwhitelisted activities as well.
+ options.augmentedEnabled = mWhitelistedAugmentAutofillPackages.contains(packageName);
+ }
+
private void whitelistForAugmentedAutofillPackages(@NonNull List<String> packages) {
// TODO(b/123100824): add CTS test for when it's null
synchronized (mLock) {
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 848f249d9a39..2b94d10d6dac 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -17,6 +17,7 @@
package com.android.server.autofill;
import static android.service.autofill.AutofillFieldClassificationService.EXTRA_SCORES;
+import static android.service.autofill.FillRequest.FLAG_AUGMENTED_AUTOFILL_REQUEST;
import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
import static android.service.autofill.FillRequest.INVALID_REQUEST_ID;
import static android.view.autofill.AutofillManager.ACTION_START_SESSION;
@@ -527,6 +528,16 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
*/
@GuardedBy("mLock")
private void requestNewFillResponseLocked(int flags) {
+
+ if ((flags & FLAG_AUGMENTED_AUTOFILL_REQUEST) != 0) {
+ // TODO(b/122858578): log metrics
+ if (sVerbose) {
+ Slog.v(TAG, "requestNewFillResponse(): triggering augmented autofill instead");
+ }
+ triggerAugmentedAutofillLocked();
+ return;
+ }
+
int requestId;
do {
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index d5713a1febfe..a8fd59add367 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -52,6 +52,7 @@ import android.view.contentcapture.IContentCaptureManager;
import android.view.contentcapture.UserDataRemovalRequest;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.infra.AbstractRemoteService;
import com.android.internal.os.IResultReceiver;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.Preconditions;
@@ -103,11 +104,12 @@ public final class ContentCaptureManagerService extends
private boolean mDisabledByDeviceConfig;
// Device-config settings that are cached and passed back to apps
- public int mDevCfgLoggingLevel;
- public int mDevCfgMaxBufferSize;
- public int mDevCfgIdleFlushingFrequencyMs;
- public int mDevCfgTextChangeFlushingFrequencyMs;
- public int mDevCfgLogHistorySize;
+ int mDevCfgLoggingLevel;
+ int mDevCfgMaxBufferSize;
+ int mDevCfgIdleFlushingFrequencyMs;
+ int mDevCfgTextChangeFlushingFrequencyMs;
+ int mDevCfgLogHistorySize;
+ int mDevCfgIdleUnbindTimeoutMs;
public ContentCaptureManagerService(@NonNull Context context) {
super(context, new FrameworkResourcesServiceNameResolver(context,
@@ -238,6 +240,7 @@ public final class ContentCaptureManagerService extends
case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_FLUSH_FREQUENCY:
case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE:
case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_TEXT_CHANGE_FLUSH_FREQUENCY:
+ case ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_UNBIND_TIMEOUT:
setFineTuneParamsFromDeviceConfig();
return;
default:
@@ -257,11 +260,15 @@ public final class ContentCaptureManagerService extends
ContentCaptureManager.DEFAULT_TEXT_CHANGE_FLUSHING_FREQUENCY_MS);
mDevCfgLogHistorySize = ContentCaptureHelper.getIntDeviceConfigProperty(
ContentCaptureManager.DEVICE_CONFIG_PROPERTY_LOG_HISTORY_SIZE, 20);
+ mDevCfgIdleUnbindTimeoutMs = ContentCaptureHelper.getIntDeviceConfigProperty(
+ ContentCaptureManager.DEVICE_CONFIG_PROPERTY_IDLE_UNBIND_TIMEOUT,
+ (int) AbstractRemoteService.PERMANENT_BOUND_TIMEOUT_MS);
if (verbose) {
Slog.v(mTag, "setFineTuneParamsFromDeviceConfig(): bufferSize=" + mDevCfgMaxBufferSize
+ ", idleFlush=" + mDevCfgIdleFlushingFrequencyMs
+ ", textFluxh=" + mDevCfgTextChangeFlushingFrequencyMs
- + ", logHistory=" + mDevCfgLogHistorySize);
+ + ", logHistory=" + mDevCfgLogHistorySize
+ + ", idleUnbindTimeoutMs=" + mDevCfgIdleUnbindTimeoutMs);
}
}
@@ -472,6 +479,8 @@ public final class ContentCaptureManagerService extends
pw.print(prefix2); pw.print("textChangeFlushingFrequencyMs: ");
pw.println(mDevCfgTextChangeFlushingFrequencyMs);
pw.print(prefix2); pw.print("logHistorySize: "); pw.println(mDevCfgLogHistorySize);
+ pw.print(prefix2); pw.print("idleUnbindTimeoutMs: ");
+ pw.println(mDevCfgIdleUnbindTimeoutMs);
}
final class ContentCaptureManagerServiceStub extends IContentCaptureManager.Stub {
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index 5b48046e3a4b..b33259d369a0 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -126,7 +126,7 @@ final class ContentCapturePerUserService
mRemoteService = new RemoteContentCaptureService(mMaster.getContext(),
ContentCaptureService.SERVICE_INTERFACE, serviceComponentName,
mRemoteServiceCallback, mUserId, this, mMaster.isBindInstantServiceAllowed(),
- mMaster.verbose);
+ mMaster.verbose, mMaster.mDevCfgIdleUnbindTimeoutMs);
}
}
diff --git a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
index de9896ecffa6..dc07c0ab0c76 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/RemoteContentCaptureService.java
@@ -26,7 +26,6 @@ import android.os.IBinder;
import android.service.contentcapture.IContentCaptureService;
import android.service.contentcapture.IContentCaptureServiceCallback;
import android.service.contentcapture.SnapshotData;
-import android.text.format.DateUtils;
import android.util.Slog;
import android.view.contentcapture.ContentCaptureContext;
import android.view.contentcapture.UserDataRemovalRequest;
@@ -38,17 +37,17 @@ final class RemoteContentCaptureService
extends AbstractMultiplePendingRequestsRemoteService<RemoteContentCaptureService,
IContentCaptureService> {
- private static final long TIMEOUT_REMOTE_REQUEST_MILLIS = 2 * DateUtils.SECOND_IN_MILLIS;
-
private final IBinder mServerCallback;
+ private final int mIdleUnbindTimeoutMs;
RemoteContentCaptureService(Context context, String serviceInterface,
ComponentName serviceComponentName, IContentCaptureServiceCallback callback, int userId,
ContentCaptureServiceCallbacks callbacks, boolean bindInstantServiceAllowed,
- boolean verbose) {
+ boolean verbose, int idleUnbindTimeoutMs) {
super(context, serviceInterface, serviceComponentName, userId, callbacks,
bindInstantServiceAllowed, verbose, /* initialCapacity= */ 2);
mServerCallback = callback.asBinder();
+ mIdleUnbindTimeoutMs = idleUnbindTimeoutMs;
// Bind right away, which will trigger a onConnected() on service's
scheduleBind();
@@ -61,14 +60,7 @@ final class RemoteContentCaptureService
@Override // from AbstractRemoteService
protected long getTimeoutIdleBindMillis() {
- // TODO(b/111276913): read from Settings so it can be changed in the field
- return PERMANENT_BOUND_TIMEOUT_MS;
- }
-
- @Override // from AbstractRemoteService
- protected long getRemoteRequestMillis() {
- // TODO(b/111276913): read from Settings so it can be changed in the field
- return TIMEOUT_REMOTE_REQUEST_MILLIS;
+ return mIdleUnbindTimeoutMs;
}
@Override // from RemoteService
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 915c131ff0fb..c37a805bc30c 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1060,7 +1060,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
handleRegisterNetworkRequest(new NetworkRequestInfo(
null, networkRequest, new Binder()));
} else {
- handleReleaseNetworkRequest(networkRequest, Process.SYSTEM_UID);
+ handleReleaseNetworkRequest(networkRequest, Process.SYSTEM_UID,
+ /* callOnUnavailable */ false);
}
}
@@ -2374,6 +2375,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
pw.decreaseIndent();
}
+
+ pw.println();
+ pw.println("NetworkStackClient logs:");
+ pw.increaseIndent();
+ NetworkStackClient.getInstance().dump(pw);
}
private void dumpNetworks(IndentingPrintWriter pw) {
@@ -2641,11 +2647,25 @@ public class ConnectivityService extends IConnectivityManager.Stub
return true;
}
+ private boolean maybeHandleNetworkFactoryMessage(Message msg) {
+ switch (msg.what) {
+ default:
+ return false;
+ case NetworkFactory.EVENT_UNFULFILLABLE_REQUEST: {
+ handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.sendingUid,
+ /* callOnUnavailable */ true);
+ break;
+ }
+ }
+ return true;
+ }
+
@Override
public void handleMessage(Message msg) {
- if (!maybeHandleAsyncChannelMessage(msg) &&
- !maybeHandleNetworkMonitorMessage(msg) &&
- !maybeHandleNetworkAgentInfoMessage(msg)) {
+ if (!maybeHandleAsyncChannelMessage(msg)
+ && !maybeHandleNetworkMonitorMessage(msg)
+ && !maybeHandleNetworkAgentInfoMessage(msg)
+ && !maybeHandleNetworkFactoryMessage(msg)) {
maybeHandleNetworkAgentMessage(msg);
}
}
@@ -2787,6 +2807,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (mNetworkFactoryInfos.containsKey(msg.replyTo)) {
if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
if (VDBG) log("NetworkFactory connected");
+ // Finish setting up the full connection
+ mNetworkFactoryInfos.get(msg.replyTo).asyncChannel.sendMessage(
+ AsyncChannel.CMD_CHANNEL_FULL_CONNECTION);
// A network factory has connected. Send it all current NetworkRequests.
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
if (nri.request.isListen()) continue;
@@ -2957,7 +2980,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (existingRequest != null) { // remove the existing request.
if (DBG) log("Replacing " + existingRequest.request + " with "
+ nri.request + " because their intents matched.");
- handleReleaseNetworkRequest(existingRequest.request, getCallingUid());
+ handleReleaseNetworkRequest(existingRequest.request, getCallingUid(),
+ /* callOnUnavailable */ false);
}
handleRegisterNetworkRequest(nri);
}
@@ -2983,7 +3007,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
int callingUid) {
NetworkRequestInfo nri = findExistingNetworkRequestInfo(pendingIntent);
if (nri != null) {
- handleReleaseNetworkRequest(nri.request, callingUid);
+ handleReleaseNetworkRequest(nri.request, callingUid, /* callOnUnavailable */ false);
}
}
@@ -3066,7 +3090,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_UNAVAIL, 0);
}
- private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid) {
+ private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid,
+ boolean callOnUnavailable) {
final NetworkRequestInfo nri =
getNriForAppRequest(request, callingUid, "release NetworkRequest");
if (nri == null) {
@@ -3076,6 +3101,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
log("releasing " + nri.request + " (release request)");
}
handleRemoveNetworkRequest(nri);
+ if (callOnUnavailable) {
+ callCallbackForRequest(nri, null, ConnectivityManager.CALLBACK_UNAVAIL, 0);
+ }
}
private void handleRemoveNetworkRequest(final NetworkRequestInfo nri) {
@@ -3507,7 +3535,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
break;
}
case EVENT_RELEASE_NETWORK_REQUEST: {
- handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.arg1);
+ handleReleaseNetworkRequest((NetworkRequest) msg.obj, msg.arg1,
+ /* callOnUnavailable */ false);
break;
}
case EVENT_SET_ACCEPT_UNVALIDATED: {
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 0ed5beb57f82..4d39f9ab8d78 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -145,7 +145,7 @@ option java_package com.android.server
# ---------------------------
# SystemServer.run() starts:
3010 boot_progress_system_run (time|2|3)
-
+3011 system_server_start (start_count|1),(uptime|2|3),(elapse_time|2|3)
# ---------------------------
# PackageManagerService.java
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 5989a46c5a0a..d8b96e43114a 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -1972,7 +1972,7 @@ public class LocationManagerService extends ILocationManager.Stub {
continue;
}
- // requests that ignore location settings will never provider notifications
+ // requests that ignore location settings will never provide notifications
if (isSettingsExemptLocked(record)) {
continue;
}
@@ -2010,19 +2010,22 @@ public class LocationManagerService extends ILocationManager.Stub {
WorkSource worksource = new WorkSource();
ProviderRequest providerRequest = new ProviderRequest();
- long backgroundThrottleInterval;
+ if (records != null && !records.isEmpty()) {
+ long backgroundThrottleInterval;
- long identity = Binder.clearCallingIdentity();
- try {
- backgroundThrottleInterval = Settings.Global.getLong(
- mContext.getContentResolver(),
- Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
- DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
+ long identity = Binder.clearCallingIdentity();
+ try {
+ backgroundThrottleInterval = Settings.Global.getLong(
+ mContext.getContentResolver(),
+ Settings.Global.LOCATION_BACKGROUND_THROTTLE_INTERVAL_MS,
+ DEFAULT_BACKGROUND_THROTTLE_INTERVAL_MS);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
- if (records != null && !records.isEmpty()) {
+ final boolean isForegroundOnlyMode =
+ mPowerManager.getLocationPowerSaveMode()
+ == PowerManager.LOCATION_MODE_FOREGROUND_ONLY;
// initialize the low power mode to true and set to false if any of the records requires
providerRequest.lowPowerMode = true;
for (UpdateRecord record : records) {
@@ -2037,7 +2040,9 @@ public class LocationManagerService extends ILocationManager.Stub {
record.mReceiver.mAllowedResolutionLevel)) {
continue;
}
- if (!provider.isUseableLocked()) {
+ final boolean isBatterySaverDisablingLocation =
+ isForegroundOnlyMode && !record.mIsForegroundUid;
+ if (!provider.isUseableLocked() || isBatterySaverDisablingLocation) {
if (isSettingsExemptLocked(record)) {
providerRequest.locationSettingsIgnored = true;
providerRequest.lowPowerMode = false;
diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java
index 526aebe2e3e3..097a7d614ab6 100644
--- a/services/core/java/com/android/server/PinnerService.java
+++ b/services/core/java/com/android/server/PinnerService.java
@@ -42,6 +42,7 @@ import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
+import android.os.SystemProperties;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.MediaStore;
@@ -235,9 +236,17 @@ public final class PinnerService extends SystemService {
* Handler for on start pinning message
*/
private void handlePinOnStart() {
- // Files to pin come from the overlay and can be specified per-device config
- String[] filesToPin = mContext.getResources().getStringArray(
- com.android.internal.R.array.config_defaultPinnerServiceFiles);
+ final String bootImage = SystemProperties.get("dalvik.vm.boot-image", "");
+ String[] filesToPin = null;
+ if (bootImage.endsWith("apex.art")) {
+ // Use the files listed for that specific boot image
+ filesToPin = mContext.getResources().getStringArray(
+ com.android.internal.R.array.config_apexBootImagePinnerServiceFiles);
+ } else {
+ // Files to pin come from the overlay and can be specified per-device config
+ filesToPin = mContext.getResources().getStringArray(
+ com.android.internal.R.array.config_defaultPinnerServiceFiles);
+ }
// Continue trying to pin each file even if we fail to pin some of them
for (String fileToPin : filesToPin) {
PinnedFile pf = pinFile(fileToPin,
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index cd9d84cca250..a5eab8550e71 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -2811,6 +2811,7 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public void unlockUserKey(int userId, int serialNumber, byte[] token, byte[] secret) {
+ Slog.d(TAG, "unlockUserKey: " + userId);
enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
if (StorageManager.isFileEncryptedNativeOrEmulated()) {
@@ -4056,6 +4057,11 @@ class StorageManagerService extends IStorageManager.Stub
@Override
public String[] getVisibleVolumesForUser(int userId) {
+ synchronized (mLock) {
+ if (!ArrayUtils.contains(mSystemUnlockedUsers, userId)) {
+ return EmptyArray.STRING;
+ }
+ }
final ArrayList<String> visibleVolsForUser = new ArrayList<>();
for (int i = mVisibleVols.size() - 1; i >= 0; --i) {
final VolumeInfo vol = mVisibleVols.get(i);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 7c46f1d70cb6..8f45df133663 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -187,6 +187,7 @@ import android.app.backup.IBackupManager;
import android.app.usage.UsageEvents;
import android.app.usage.UsageStatsManagerInternal;
import android.appwidget.AppWidgetManager;
+import android.content.AutofillOptions;
import android.content.BroadcastReceiver;
import android.content.ComponentCallbacks2;
import android.content.ComponentName;
@@ -1486,6 +1487,8 @@ public class ActivityManagerService extends IActivityManager.Stub
private static String sTheRealBuildSerial = Build.UNKNOWN;
+ private ParcelFileDescriptor[] mLifeMonitorFds;
+
final class UiHandler extends Handler {
public UiHandler() {
super(com.android.server.UiThread.get().getLooper(), null, true);
@@ -4741,12 +4744,12 @@ public class ActivityManagerService extends IActivityManager.Stub
// Figure out whether the app needs to run in autofill compat mode.
- boolean isAutofillCompatEnabled = false;
+ AutofillOptions autofillOptions = null;
if (UserHandle.getAppId(app.info.uid) >= Process.FIRST_APPLICATION_UID) {
final AutofillManagerInternal afm = LocalServices.getService(
AutofillManagerInternal.class);
if (afm != null) {
- isAutofillCompatEnabled = afm.isCompatibilityModeRequested(
+ autofillOptions = afm.getAutofillOptions(
app.info.packageName, app.info.versionCode, app.userId);
}
}
@@ -4779,7 +4782,7 @@ public class ActivityManagerService extends IActivityManager.Stub
new Configuration(app.getWindowProcessController().getConfiguration()),
app.compat, getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
- buildSerial, isAutofillCompatEnabled, contentCaptureOptions);
+ buildSerial, autofillOptions, contentCaptureOptions);
} else {
thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
null, null, null, testMode,
@@ -4788,7 +4791,7 @@ public class ActivityManagerService extends IActivityManager.Stub
new Configuration(app.getWindowProcessController().getConfiguration()),
app.compat, getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
- buildSerial, isAutofillCompatEnabled, contentCaptureOptions);
+ buildSerial, autofillOptions, contentCaptureOptions);
}
if (profilerInfo != null) {
profilerInfo.closeFd();
@@ -17107,6 +17110,13 @@ public class ActivityManagerService extends IActivityManager.Stub
}
@Override
+ public boolean startUserInForegroundWithListener(final int userId,
+ @Nullable IProgressListener unlockListener) {
+ // Permission check done inside UserController.
+ return mUserController.startUser(userId, /* foreground */ true, unlockListener);
+ }
+
+ @Override
public boolean unlockUser(int userId, byte[] token, byte[] secret, IProgressListener listener) {
return mUserController.unlockUser(userId, token, secret, listener);
}
@@ -18500,4 +18510,24 @@ public class ActivityManagerService extends IActivityManager.Stub
private boolean isOnOffloadQueue(int flags) {
return (mEnableOffloadQueue && ((flags & Intent.FLAG_RECEIVER_OFFLOAD) != 0));
}
+
+ @Override
+ public ParcelFileDescriptor getLifeMonitor() {
+ if (!isCallerShell()) {
+ throw new SecurityException("Only shell can call it");
+ }
+ synchronized (this) {
+ try {
+ if (mLifeMonitorFds == null) {
+ mLifeMonitorFds = ParcelFileDescriptor.createPipe();
+ }
+ // The returned FD will be closed, but we want to keep our reader open,
+ // so return a dup instead.
+ return mLifeMonitorFds[0].dup();
+ } catch (IOException e) {
+ Slog.w(TAG, "Unable to create pipe", e);
+ return null;
+ }
+ }
+ }
}
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index d902201df212..afdfbe328ae2 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -89,6 +89,8 @@ import android.media.audiopolicy.AudioMix;
import android.media.audiopolicy.AudioPolicy;
import android.media.audiopolicy.AudioPolicyConfig;
import android.media.audiopolicy.IAudioPolicyCallback;
+import android.media.projection.IMediaProjection;
+import android.media.projection.IMediaProjectionManager;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
@@ -99,6 +101,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
@@ -453,6 +456,8 @@ public class AudioService extends IAudioService.Stub
// Broadcast receiver for device connections intent broadcasts
private final BroadcastReceiver mReceiver = new AudioServiceBroadcastReceiver();
+ private IMediaProjectionManager mProjectionService; // to validate projection token
+
/** Interface for UserManagerService. */
private final UserManagerInternal mUserManagerInternal;
private final ActivityManagerInternal mActivityManagerInternal;
@@ -6186,22 +6191,21 @@ public class AudioService extends IAudioService.Stub
// Audio policy management
//==========================================================================================
public String registerAudioPolicy(AudioPolicyConfig policyConfig, IAudioPolicyCallback pcb,
- boolean hasFocusListener, boolean isFocusPolicy, boolean isVolumeController) {
+ boolean hasFocusListener, boolean isFocusPolicy, boolean isVolumeController,
+ IMediaProjection projection) {
AudioSystem.setDynamicPolicyCallback(mDynPolicyCallback);
- String regId = null;
- // error handling
- boolean hasPermissionForPolicy =
- (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
- android.Manifest.permission.MODIFY_AUDIO_ROUTING));
- if (!hasPermissionForPolicy) {
- Slog.w(TAG, "Can't register audio policy for pid " + Binder.getCallingPid() + " / uid "
- + Binder.getCallingUid() + ", need MODIFY_AUDIO_ROUTING");
+ if (!isPolicyRegisterAllowed(policyConfig, projection)) {
+ Slog.w(TAG, "Permission denied to register audio policy for pid "
+ + Binder.getCallingPid() + " / uid " + Binder.getCallingUid()
+ + ", need MODIFY_AUDIO_ROUTING or MediaProjection that can project audio");
return null;
}
mDynPolicyLogger.log((new AudioEventLogger.StringEvent("registerAudioPolicy for "
+ pcb.asBinder() + " with config:" + policyConfig)).printLog(TAG));
+
+ String regId = null;
synchronized (mAudioPolicies) {
try {
if (mAudioPolicies.containsKey(pcb.asBinder())) {
@@ -6223,6 +6227,76 @@ public class AudioService extends IAudioService.Stub
return regId;
}
+ /**
+ * Apps with MODIFY_AUDIO_ROUTING can register any policy.
+ * Apps with an audio capable MediaProjection are allowed to register a RENDER|LOOPBACK policy
+ * as those policy do not modify the audio routing.
+ */
+ private boolean isPolicyRegisterAllowed(AudioPolicyConfig policyConfig,
+ IMediaProjection projection) {
+
+ boolean isLoopbackRenderPolicy = policyConfig.getMixes().stream().allMatch(
+ mix -> mix.getRouteFlags() == (mix.ROUTE_FLAG_RENDER | mix.ROUTE_FLAG_LOOP_BACK));
+
+ // Policy that do not modify the audio routing only need an audio projection
+ if (isLoopbackRenderPolicy && canProjectAudio(projection)) {
+ return true;
+ }
+
+ boolean hasPermissionModifyAudioRouting =
+ (PackageManager.PERMISSION_GRANTED == mContext.checkCallingPermission(
+ android.Manifest.permission.MODIFY_AUDIO_ROUTING));
+ if (hasPermissionModifyAudioRouting) {
+ return true;
+ }
+ return false;
+ }
+
+ /** @return true if projection is a valid MediaProjection that can project audio. */
+ private boolean canProjectAudio(IMediaProjection projection) {
+ if (projection == null) {
+ return false;
+ }
+
+ IMediaProjectionManager projectionService = getProjectionService();
+ if (projectionService == null) {
+ Log.e(TAG, "Can't get service IMediaProjectionManager");
+ return false;
+ }
+
+ try {
+ if (!projectionService.isValidMediaProjection(projection)) {
+ Log.w(TAG, "App passed invalid MediaProjection token");
+ return false;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Can't call .isValidMediaProjection() on IMediaProjectionManager"
+ + projectionService.asBinder(), e);
+ return false;
+ }
+
+ try {
+ if (!projection.canProjectAudio()) {
+ Log.w(TAG, "App passed MediaProjection that can not project audio");
+ return false;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Can't call .canProjectAudio() on valid IMediaProjection"
+ + projection.asBinder(), e);
+ return false;
+ }
+
+ return true;
+ }
+
+ private IMediaProjectionManager getProjectionService() {
+ if (mProjectionService == null) {
+ IBinder b = ServiceManager.getService(Context.MEDIA_PROJECTION_SERVICE);
+ mProjectionService = IMediaProjectionManager.Stub.asInterface(b);
+ }
+ return mProjectionService;
+ }
+
public void unregisterAudioPolicyAsync(IAudioPolicyCallback pcb) {
mDynPolicyLogger.log((new AudioEventLogger.StringEvent("unregisterAudioPolicyAsync for "
+ pcb.asBinder()).printLog(TAG)));
diff --git a/services/core/java/com/android/server/biometrics/ClientMonitor.java b/services/core/java/com/android/server/biometrics/ClientMonitor.java
index e80b39ba9d1f..89fa2de92c1c 100644
--- a/services/core/java/com/android/server/biometrics/ClientMonitor.java
+++ b/services/core/java/com/android/server/biometrics/ClientMonitor.java
@@ -209,11 +209,7 @@ public abstract class ClientMonitor extends LoggableMonitor implements IBinder.D
public void binderDied() {
// If the current client dies we should cancel the current operation.
Slog.e(getLogTag(), "Binder died, cancelling client");
- try {
- getDaemonWrapper().cancel();
- } catch (RemoteException e) {
- Slog.e(getLogTag(), "Remote exception", e);
- }
+ stop(false /* initiatedByClient */);
mToken = null;
mListener = null;
}
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index 420b23e6a39f..d84a4d2db993 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -19,10 +19,11 @@ package com.android.server.connectivity;
import static android.Manifest.permission.CHANGE_NETWORK_STATE;
import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
+import static android.Manifest.permission.INTERNET;
import static android.Manifest.permission.NETWORK_STACK;
-import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
-import static android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
+import static android.Manifest.permission.UPDATE_DEVICE_STATS;
import static android.content.pm.PackageManager.GET_PERMISSIONS;
+import static android.content.pm.PackageManager.MATCH_ANY_USER;
import static android.os.Process.INVALID_UID;
import static android.os.Process.SYSTEM_UID;
@@ -32,23 +33,31 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManagerInternal;
import android.content.pm.UserInfo;
-import android.net.Uri;
+import android.net.INetd;
+import android.net.util.NetdService;
import android.os.Build;
import android.os.INetworkManagementService;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
+import android.util.Slog;
+import android.util.SparseIntArray;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
+import com.android.server.LocalServices;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
-import java.util.Map.Entry;
import java.util.Map;
+import java.util.Map.Entry;
import java.util.Set;
/**
@@ -75,6 +84,59 @@ public class PermissionMonitor {
// Keys are App IDs. Values are true for SYSTEM permission and false for NETWORK permission.
private final Map<Integer, Boolean> mApps = new HashMap<>();
+ // Keys are App packageNames, Values are app uids. . We need to keep track of this information
+ // because PackageListObserver#onPackageRemoved does not pass the UID.
+ @GuardedBy("mPackageNameUidMap")
+ private final Map<String, Integer> mPackageNameUidMap = new HashMap<>();
+
+ private class PackageListObserver implements PackageManagerInternal.PackageListObserver {
+ @Override
+ public void onPackageAdded(String packageName) {
+ final PackageInfo app = getPackageInfo(packageName);
+ if (app == null) {
+ Slog.wtf(TAG, "Failed to get information of installed package: " + packageName);
+ return;
+ }
+ int uid = (app.applicationInfo != null) ? app.applicationInfo.uid : INVALID_UID;
+ if (uid == INVALID_UID) {
+ Slog.wtf(TAG, "Failed to get the uid of installed package: " + packageName
+ + "uid: " + uid);
+ return;
+ }
+ if (app.requestedPermissions == null) {
+ return;
+ }
+ sendPackagePermissionsForUid(uid,
+ filterPermission(Arrays.asList(app.requestedPermissions)));
+ synchronized (mPackageNameUidMap) {
+ mPackageNameUidMap.put(packageName, uid);
+ }
+ }
+
+ @Override
+ public void onPackageRemoved(String packageName) {
+ int uid;
+ synchronized (mPackageNameUidMap) {
+ if (!mPackageNameUidMap.containsKey(packageName)) {
+ return;
+ }
+ uid = mPackageNameUidMap.get(packageName);
+ mPackageNameUidMap.remove(packageName);
+ }
+ int permission = 0;
+ String[] packages = mPackageManager.getPackagesForUid(uid);
+ if (packages != null && packages.length > 0) {
+ for (String name : packages) {
+ final PackageInfo app = getPackageInfo(name);
+ if (app != null && app.requestedPermissions != null) {
+ permission |= filterPermission(Arrays.asList(app.requestedPermissions));
+ }
+ }
+ }
+ sendPackagePermissionsForUid(uid, permission);
+ }
+ }
+
public PermissionMonitor(Context context, INetworkManagementService netd) {
mContext = context;
mPackageManager = context.getPackageManager();
@@ -87,12 +149,21 @@ public class PermissionMonitor {
public synchronized void startMonitoring() {
log("Monitoring");
- List<PackageInfo> apps = mPackageManager.getInstalledPackages(GET_PERMISSIONS);
+ PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
+ if (pmi != null) {
+ pmi.getPackageList(new PackageListObserver());
+ } else {
+ loge("failed to get the PackageManagerInternal service");
+ }
+ List<PackageInfo> apps = mPackageManager.getInstalledPackages(GET_PERMISSIONS
+ | MATCH_ANY_USER);
if (apps == null) {
loge("No apps");
return;
}
+ SparseIntArray netdPermsUids = new SparseIntArray();
+
for (PackageInfo app : apps) {
int uid = app.applicationInfo != null ? app.applicationInfo.uid : INVALID_UID;
if (uid < 0) {
@@ -110,6 +181,17 @@ public class PermissionMonitor {
mApps.put(uid, hasRestrictedPermission);
}
}
+
+ //TODO: unify the management of the permissions into one codepath.
+ if (app.requestedPermissions != null) {
+ int otherNetdPerms = filterPermission(Arrays.asList(app.requestedPermissions));
+ if (otherNetdPerms != 0) {
+ netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms);
+ synchronized (mPackageNameUidMap) {
+ mPackageNameUidMap.put(app.applicationInfo.packageName, uid);
+ }
+ }
+ }
}
List<UserInfo> users = mUserManager.getUsers(true); // exclude dying users
@@ -121,6 +203,7 @@ public class PermissionMonitor {
log("Users: " + mUsers.size() + ", Apps: " + mApps.size());
update(mUsers, mApps, true);
+ sendPackagePermissionsToNetd(netdPermsUids);
}
@VisibleForTesting
@@ -339,6 +422,107 @@ public class PermissionMonitor {
}
}
+ private static int filterPermission(List<String> requestedPermissions) {
+ int permissions = 0;
+ if (requestedPermissions.contains(INTERNET)) {
+ permissions |= INetd.PERMISSION_INTERNET;
+ }
+ if (requestedPermissions.contains(UPDATE_DEVICE_STATS)) {
+ permissions |= INetd.PERMISSION_UPDATE_DEVICE_STATS;
+ }
+ return permissions;
+ }
+
+ private PackageInfo getPackageInfo(String packageName) {
+ try {
+ PackageInfo app = mPackageManager.getPackageInfo(packageName, GET_PERMISSIONS
+ | MATCH_ANY_USER);
+ return app;
+ } catch (NameNotFoundException e) {
+ // App not found.
+ loge("NameNotFoundException " + packageName);
+ return null;
+ }
+ }
+
+ /**
+ * Called by PackageListObserver when a package is installed/uninstalled. Send the updated
+ * permission information to netd.
+ *
+ * @param uid the app uid of the package installed
+ * @param permissions the permissions the app requested and netd cares about.
+ *
+ * @hide
+ */
+ private void sendPackagePermissionsForUid(int uid, int permissions) {
+ SparseIntArray netdPermissionsAppIds = new SparseIntArray();
+ netdPermissionsAppIds.put(uid, permissions);
+ sendPackagePermissionsToNetd(netdPermissionsAppIds);
+ }
+
+ /**
+ * Called by packageManagerService to send IPC to netd. Grant or revoke the INTERNET
+ * and/or UPDATE_DEVICE_STATS permission of the uids in array.
+ *
+ * @param netdPermissionsAppIds integer pairs of uids and the permission granted to it. If the
+ * permission is 0, revoke all permissions of that uid.
+ *
+ * @hide
+ */
+ private void sendPackagePermissionsToNetd(SparseIntArray netdPermissionsAppIds) {
+ INetd netdService = NetdService.getInstance();
+ if (netdService == null) {
+ Log.e(TAG, "Failed to get the netd service");
+ return;
+ }
+ ArrayList<Integer> allPermissionAppIds = new ArrayList<>();
+ ArrayList<Integer> internetPermissionAppIds = new ArrayList<>();
+ ArrayList<Integer> updateStatsPermissionAppIds = new ArrayList<>();
+ ArrayList<Integer> uninstalledAppIds = new ArrayList<>();
+ for (int i = 0; i < netdPermissionsAppIds.size(); i++) {
+ int permissions = netdPermissionsAppIds.valueAt(i);
+ switch(permissions) {
+ case (INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS):
+ allPermissionAppIds.add(netdPermissionsAppIds.keyAt(i));
+ break;
+ case INetd.PERMISSION_INTERNET:
+ internetPermissionAppIds.add(netdPermissionsAppIds.keyAt(i));
+ break;
+ case INetd.PERMISSION_UPDATE_DEVICE_STATS:
+ updateStatsPermissionAppIds.add(netdPermissionsAppIds.keyAt(i));
+ break;
+ case INetd.NO_PERMISSIONS:
+ uninstalledAppIds.add(netdPermissionsAppIds.keyAt(i));
+ break;
+ default:
+ Log.e(TAG, "unknown permission type: " + permissions + "for uid: "
+ + netdPermissionsAppIds.keyAt(i));
+ }
+ }
+ try {
+ // TODO: add a lock inside netd to protect IPC trafficSetNetPermForUids()
+ if (allPermissionAppIds.size() != 0) {
+ netdService.trafficSetNetPermForUids(
+ INetd.PERMISSION_INTERNET | INetd.PERMISSION_UPDATE_DEVICE_STATS,
+ ArrayUtils.convertToIntArray(allPermissionAppIds));
+ }
+ if (internetPermissionAppIds.size() != 0) {
+ netdService.trafficSetNetPermForUids(INetd.PERMISSION_INTERNET,
+ ArrayUtils.convertToIntArray(internetPermissionAppIds));
+ }
+ if (updateStatsPermissionAppIds.size() != 0) {
+ netdService.trafficSetNetPermForUids(INetd.PERMISSION_UPDATE_DEVICE_STATS,
+ ArrayUtils.convertToIntArray(updateStatsPermissionAppIds));
+ }
+ if (uninstalledAppIds.size() != 0) {
+ netdService.trafficSetNetPermForUids(INetd.NO_PERMISSIONS,
+ ArrayUtils.convertToIntArray(uninstalledAppIds));
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Pass appId list of special permission failed." + e);
+ }
+ }
+
private static void log(String s) {
if (DBG) {
Log.d(TAG, s);
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index bfa7f9d439e3..4e4b15fc5b9b 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -19,6 +19,7 @@ package com.android.server.content;
import android.Manifest;
import android.accounts.Account;
import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.AppOpsManager;
@@ -1174,6 +1175,7 @@ public final class ContentService extends IContentService.Stub {
}
@Override
+ @RequiresPermission(android.Manifest.permission.CACHE_CONTENT)
public void putCache(String packageName, Uri key, Bundle value, int userId) {
Bundle.setDefusable(value, true);
enforceCrossUserPermission(userId, TAG);
@@ -1196,6 +1198,7 @@ public final class ContentService extends IContentService.Stub {
}
@Override
+ @RequiresPermission(android.Manifest.permission.CACHE_CONTENT)
public Bundle getCache(String packageName, Uri key, int userId) {
enforceCrossUserPermission(userId, TAG);
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CACHE_CONTENT, TAG);
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index b0209973edbf..01d19c04d97e 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -37,7 +37,9 @@ import android.content.pm.ParceledListSlice;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.ColorSpace;
+import android.graphics.GraphicBuffer;
import android.graphics.Point;
+import android.graphics.Rect;
import android.hardware.SensorManager;
import android.hardware.display.AmbientBrightnessDayStats;
import android.hardware.display.BrightnessChangeEvent;
@@ -1277,7 +1279,14 @@ public final class DisplayManagerService extends SystemService {
if (token == null) {
return false;
}
- SurfaceControl.screenshot(token, outSurface);
+ final GraphicBuffer gb = SurfaceControl.screenshotToBufferWithSecureLayersUnsafe(
+ token, new Rect(), 0 /* width */, 0 /* height */, false /* useIdentityTransform */,
+ 0 /* rotation */);
+ try {
+ outSurface.attachAndQueueBuffer(gb);
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Failed to take screenshot - " + e.getMessage());
+ }
return true;
}
diff --git a/services/core/java/com/android/server/gpu/GpuService.java b/services/core/java/com/android/server/gpu/GpuService.java
index 6899c3ffcbb1..647727f795da 100644
--- a/services/core/java/com/android/server/gpu/GpuService.java
+++ b/services/core/java/com/android/server/gpu/GpuService.java
@@ -62,6 +62,7 @@ public class GpuService extends SystemService {
private static final String PROPERTY_GFX_DRIVER = "ro.gfx.driver.0";
private static final String GAME_DRIVER_WHITELIST_FILENAME = "whitelist.txt";
+ private static final String GAME_DRIVER_SPHAL_LIBRARIES_FILENAME = "sphal_libraries.txt";
private static final int BASE64_FLAGS = Base64.NO_PADDING | Base64.NO_WRAP;
private final Context mContext;
@@ -162,6 +163,25 @@ public class GpuService extends SystemService {
}
}
+ private static void assetToSettingsGlobal(Context context, Context driverContext,
+ String fileName, String settingsGlobal, CharSequence delimiter) {
+ try {
+ final BufferedReader reader = new BufferedReader(
+ new InputStreamReader(driverContext.getAssets().open(fileName)));
+ final ArrayList<String> assetStrings = new ArrayList<>();
+ for (String assetString; (assetString = reader.readLine()) != null; ) {
+ assetStrings.add(assetString);
+ }
+ Settings.Global.putString(context.getContentResolver(),
+ settingsGlobal,
+ String.join(delimiter, assetStrings));
+ } catch (IOException e) {
+ if (DEBUG) {
+ Slog.w(TAG, "Failed to load " + fileName + ", abort.");
+ }
+ }
+ }
+
private void fetchGameDriverPackageProperties() {
final ApplicationInfo driverInfo;
try {
@@ -186,29 +206,25 @@ public class GpuService extends SystemService {
// Reset the whitelist.
Settings.Global.putString(mContentResolver,
Settings.Global.GAME_DRIVER_WHITELIST, "");
+ // Reset the sphal libraries
+ Settings.Global.putString(mContentResolver,
+ Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, "");
mGameDriverVersionCode = driverInfo.longVersionCode;
try {
final Context driverContext = mContext.createPackageContext(mDriverPackageName,
Context.CONTEXT_RESTRICTED);
- final BufferedReader reader = new BufferedReader(
- new InputStreamReader(driverContext.getAssets()
- .open(GAME_DRIVER_WHITELIST_FILENAME)));
- final ArrayList<String> whitelistedPackageNames = new ArrayList<>();
- for (String packageName; (packageName = reader.readLine()) != null; ) {
- whitelistedPackageNames.add(packageName);
- }
- Settings.Global.putString(mContentResolver,
- Settings.Global.GAME_DRIVER_WHITELIST,
- String.join(",", whitelistedPackageNames));
+
+ assetToSettingsGlobal(mContext, driverContext, GAME_DRIVER_WHITELIST_FILENAME,
+ Settings.Global.GAME_DRIVER_WHITELIST, ",");
+
+ assetToSettingsGlobal(mContext, driverContext, GAME_DRIVER_SPHAL_LIBRARIES_FILENAME,
+ Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, ":");
+
} catch (PackageManager.NameNotFoundException e) {
if (DEBUG) {
Slog.w(TAG, "driver package '" + mDriverPackageName + "' not installed");
}
- } catch (IOException e) {
- if (DEBUG) {
- Slog.w(TAG, "Failed to load whitelist driver package, abort.");
- }
}
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
index 67109867c074..6a4ccf2f5327 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
@@ -248,12 +248,8 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
}
if (mService.getPortInfo(portId).getType() == HdmiPortInfo.PORT_OUTPUT) {
mCecMessageCache.flushAll();
- } else {
- if (connected) {
- launchDeviceDiscovery();
- } else {
- // TODO(amyjojo): remove device from mDeviceInfo
- }
+ } else if (!connected){
+ // TODO(amyjojo): remove device from mDeviceInfo
}
}
@@ -996,6 +992,17 @@ public class HdmiCecLocalDeviceAudioSystem extends HdmiCecLocalDeviceSource {
}
// Wake up device
mService.wakeUp();
+ // If Audio device is the active source or is on the active path,
+ // enable system audio mode without querying TV's support on sam.
+ // This is per HDMI spec 1.4b CEC 13.15.4.2.
+ if (mService.pathToPortId(getActiveSource().physicalAddress)
+ != Constants.INVALID_PORT_ID) {
+ setSystemAudioMode(true);
+ mService.sendCecCommand(
+ HdmiCecMessageBuilder.buildSetSystemAudioMode(
+ mAddress, Constants.ADDR_BROADCAST, true));
+ return;
+ }
// Check if TV supports System Audio Control.
// Handle broadcasting setSystemAudioMode on or aborting message on callback.
queryTvSystemAudioModeSupport(new TvSystemAudioModeSupportedCallback() {
diff --git a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
index 2bfb31f6e74f..d2ccfcc732a9 100644
--- a/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
+++ b/services/core/java/com/android/server/infra/AbstractMasterSystemService.java
@@ -133,7 +133,8 @@ public abstract class AbstractMasterSystemService<M extends AbstractMasterSystem
* {@link com.android.internal.infra.AbstractRemoteService} instances, or
* {@code null} when the service doesn't bind to remote services.
* @param disallowProperty when not {@code null}, defines a {@link UserManager} restriction that
- * disables the service.
+ * disables the service. <b>NOTE: </b> you'll also need to add it to
+ * {@code UserRestrictionsUtils.USER_RESTRICTIONS}.
*/
protected AbstractMasterSystemService(@NonNull Context context,
@Nullable ServiceNameResolver serviceNameResolver,
diff --git a/services/core/java/com/android/server/job/controllers/StorageController.java b/services/core/java/com/android/server/job/controllers/StorageController.java
index c2ae53f69309..51187dff4d59 100644
--- a/services/core/java/com/android/server/job/controllers/StorageController.java
+++ b/services/core/java/com/android/server/job/controllers/StorageController.java
@@ -81,20 +81,16 @@ public final class StorageController extends StateController {
synchronized (mLock) {
for (int i = mTrackedTasks.size() - 1; i >= 0; i--) {
final JobStatus ts = mTrackedTasks.valueAt(i);
- boolean previous = ts.setStorageNotLowConstraintSatisfied(storageNotLow);
- if (previous != storageNotLow) {
- reportChange = true;
- }
+ reportChange |= ts.setStorageNotLowConstraintSatisfied(storageNotLow);
}
}
- // Let the scheduler know that state has changed. This may or may not result in an
- // execution.
- if (reportChange) {
- mStateChangedListener.onControllerStateChanged();
- }
- // Also tell the scheduler that any ready jobs should be flushed.
if (storageNotLow) {
+ // Tell the scheduler that any ready jobs should be flushed.
mStateChangedListener.onRunJobNow(null);
+ } else if (reportChange) {
+ // Let the scheduler know that state has changed. This may or may not result in an
+ // execution.
+ mStateChangedListener.onControllerStateChanged();
}
}
@@ -143,9 +139,10 @@ public final class StorageController extends StateController {
+ sElapsedRealtimeClock.millis());
}
mStorageLow = true;
+ maybeReportNewStorageState();
} else if (Intent.ACTION_DEVICE_STORAGE_OK.equals(action)) {
if (DEBUG) {
- Slog.d(TAG, "Available stoage high enough to do work. @ "
+ Slog.d(TAG, "Available storage high enough to do work. @ "
+ sElapsedRealtimeClock.millis());
}
mStorageLow = false;
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 243b6fe7a30e..28fdd95afb6a 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -527,6 +527,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
mPowerManager.getPowerSaveState(ServiceType.LOCATION);
switch (result.locationMode) {
case PowerManager.LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF:
+ case PowerManager.LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF:
// If we are in battery saver mode and the screen is off, disable GPS.
disableGps |= result.batterySaverEnabled && !mPowerManager.isInteractive();
break;
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 924018ea3a5a..aa85c835a5fd 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -407,6 +407,10 @@ public class LockSettingsService extends ILockSettings.Stub {
return new SyntheticPasswordManager(getContext(), storage, getUserManager());
}
+ public boolean hasBiometrics() {
+ return BiometricManager.hasBiometrics(mContext);
+ }
+
public int binderGetCallingUid() {
return Binder.getCallingUid();
}
@@ -2434,7 +2438,7 @@ public class LockSettingsService extends ILockSettings.Stub {
notifyActivePasswordMetricsAvailable(userCredential, userId);
unlockKeystore(authResult.authToken.deriveKeyStorePassword(), userId);
// Reset lockout
- if (BiometricManager.hasBiometrics(mContext)) {
+ if (mInjector.hasBiometrics()) {
BiometricManager bm = mContext.getSystemService(BiometricManager.class);
Slog.i(TAG, "Resetting lockout, length: "
+ authResult.gkResponse.getPayload().length);
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index b221241c25e2..152cf7fe7d41 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -77,6 +77,7 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
private final int mUserId;
private final String mPackageName;
private final String mTag;
+ private final Bundle mSessionInfo;
private final ControllerLink mController;
private final MediaSession.Token mSessionToken;
private final SessionLink mSession;
@@ -121,13 +122,14 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
private String mMetadataDescription;
public MediaSessionRecord(int ownerPid, int ownerUid, int userId, String ownerPackageName,
- SessionCallbackLink cb, String tag, MediaSessionService.ServiceImpl service,
- Looper handlerLooper) {
+ SessionCallbackLink cb, String tag, Bundle sessionInfo,
+ MediaSessionService.ServiceImpl service, Looper handlerLooper) {
mOwnerPid = ownerPid;
mOwnerUid = ownerUid;
mUserId = userId;
mPackageName = ownerPackageName;
mTag = tag;
+ mSessionInfo = sessionInfo;
mController = new ControllerLink(new ControllerStub());
mSessionToken = new MediaSession.Token(mController);
mSession = new SessionLink(new SessionStub());
@@ -1309,6 +1311,11 @@ public class MediaSessionRecord implements IBinder.DeathRecipient {
}
@Override
+ public Bundle getSessionInfo() {
+ return mSessionInfo;
+ }
+
+ @Override
public PendingIntent getLaunchPendingIntent() {
return mLaunchIntent;
}
diff --git a/services/core/java/com/android/server/media/MediaSessionServiceImpl.java b/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
index 62d9b20b636d..b86328b92869 100644
--- a/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaSessionServiceImpl.java
@@ -549,9 +549,11 @@ public class MediaSessionServiceImpl extends MediaSessionService.ServiceImpl {
}
private MediaSessionRecord createSessionInternal(int callerPid, int callerUid, int userId,
- String callerPackageName, SessionCallbackLink cb, String tag) throws RemoteException {
+ String callerPackageName, SessionCallbackLink cb, String tag, Bundle sessionInfo)
+ throws RemoteException {
synchronized (mLock) {
- return createSessionLocked(callerPid, callerUid, userId, callerPackageName, cb, tag);
+ return createSessionLocked(callerPid, callerUid, userId, callerPackageName, cb,
+ tag, sessionInfo);
}
}
@@ -563,7 +565,7 @@ public class MediaSessionServiceImpl extends MediaSessionService.ServiceImpl {
* 4. It needs to be added to the relevant user record.
*/
private MediaSessionRecord createSessionLocked(int callerPid, int callerUid, int userId,
- String callerPackageName, SessionCallbackLink cb, String tag) {
+ String callerPackageName, SessionCallbackLink cb, String tag, Bundle sessionInfo) {
FullUserRecord user = getFullUserRecordLocked(userId);
if (user == null) {
Log.w(TAG, "Request from invalid user: " + userId + ", pkg=" + callerPackageName);
@@ -571,7 +573,7 @@ public class MediaSessionServiceImpl extends MediaSessionService.ServiceImpl {
}
final MediaSessionRecord session = new MediaSessionRecord(callerPid, callerUid, userId,
- callerPackageName, cb, tag, this, mHandler.getLooper());
+ callerPackageName, cb, tag, sessionInfo, this, mHandler.getLooper());
try {
cb.getBinder().linkToDeath(session, 0);
} catch (RemoteException e) {
@@ -991,7 +993,7 @@ public class MediaSessionServiceImpl extends MediaSessionService.ServiceImpl {
@Override
public SessionLink createSession(String packageName, SessionCallbackLink cb, String tag,
- int userId) throws RemoteException {
+ Bundle sessionInfo, int userId) throws RemoteException {
final int pid = Binder.getCallingPid();
final int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
@@ -1002,8 +1004,8 @@ public class MediaSessionServiceImpl extends MediaSessionService.ServiceImpl {
if (cb == null) {
throw new IllegalArgumentException("Controller callback cannot be null");
}
- return createSessionInternal(pid, uid, resolvedUserId, packageName, cb, tag)
- .getSessionBinder();
+ return createSessionInternal(pid, uid, resolvedUserId, packageName, cb, tag,
+ sessionInfo).getSessionBinder();
} finally {
Binder.restoreCallingIdentity(token);
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 3557fcf35dbc..e8c402c770c7 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -594,8 +594,6 @@ public class NotificationManagerService extends SystemService {
mConditionProviders.migrateToXml();
handleSavePolicyFile();
}
-
- mAssistants.ensureAssistant();
}
private void loadPolicyFile() {
diff --git a/services/core/java/com/android/server/notification/NotificationShellCmd.java b/services/core/java/com/android/server/notification/NotificationShellCmd.java
index 2aaa1edcfad9..26cc0c10ccb3 100644
--- a/services/core/java/com/android/server/notification/NotificationShellCmd.java
+++ b/services/core/java/com/android/server/notification/NotificationShellCmd.java
@@ -16,6 +16,7 @@
package com.android.server.notification;
+import android.app.ActivityManager;
import android.app.INotificationManager;
import android.app.Notification;
import android.app.NotificationChannel;
@@ -49,12 +50,12 @@ public class NotificationShellCmd extends ShellCommand {
private static final String USAGE =
"usage: cmd notification SUBCMD [args]\n\n"
+ "SUBCMDs:\n"
- + " allow_listener COMPONENT [user_id]\n"
- + " disallow_listener COMPONENT [user_id]\n"
- + " allow_assistant COMPONENT\n"
- + " remove_assistant COMPONENT\n"
- + " allow_dnd PACKAGE\n"
- + " disallow_dnd PACKAGE\n"
+ + " allow_listener COMPONENT [user_id (current user if not specified)]\n"
+ + " disallow_listener COMPONENT [user_id (current user if not specified)]\n"
+ + " allow_assistant COMPONENT [user_id (current user if not specified)]\n"
+ + " remove_assistant COMPONENT [user_id (current user if not specified)]\n"
+ + " allow_dnd PACKAGE [user_id (current user if not specified)]\n"
+ + " disallow_dnd PACKAGE [user_id (current user if not specified)]\n"
+ " suspend_package PACKAGE\n"
+ " unsuspend_package PACKAGE\n"
+ " post [--help | flags] TAG TEXT";
@@ -109,14 +110,24 @@ public class NotificationShellCmd extends ShellCommand {
try {
switch (cmd.replace('-', '_')) {
case "allow_dnd": {
- mBinderService.setNotificationPolicyAccessGranted(
- getNextArgRequired(), true);
+ String packageName = getNextArgRequired();
+ int userId = ActivityManager.getCurrentUser();
+ if (peekNextArg() != null) {
+ userId = Integer.parseInt(getNextArgRequired());
+ }
+ mBinderService.setNotificationPolicyAccessGrantedForUser(
+ packageName, userId, true);
}
break;
case "disallow_dnd": {
- mBinderService.setNotificationPolicyAccessGranted(
- getNextArgRequired(), false);
+ String packageName = getNextArgRequired();
+ int userId = ActivityManager.getCurrentUser();
+ if (peekNextArg() != null) {
+ userId = Integer.parseInt(getNextArgRequired());
+ }
+ mBinderService.setNotificationPolicyAccessGrantedForUser(
+ packageName, userId, false);
}
break;
case "allow_listener": {
@@ -125,13 +136,11 @@ public class NotificationShellCmd extends ShellCommand {
pw.println("Invalid listener - must be a ComponentName");
return -1;
}
- String userId = getNextArg();
- if (userId == null) {
- mBinderService.setNotificationListenerAccessGranted(cn, true);
- } else {
- mBinderService.setNotificationListenerAccessGrantedForUser(
- cn, Integer.parseInt(userId), true);
+ int userId = ActivityManager.getCurrentUser();
+ if (peekNextArg() != null) {
+ userId = Integer.parseInt(getNextArgRequired());
}
+ mBinderService.setNotificationListenerAccessGrantedForUser(cn, userId, true);
}
break;
case "disallow_listener": {
@@ -140,13 +149,11 @@ public class NotificationShellCmd extends ShellCommand {
pw.println("Invalid listener - must be a ComponentName");
return -1;
}
- String userId = getNextArg();
- if (userId == null) {
- mBinderService.setNotificationListenerAccessGranted(cn, false);
- } else {
- mBinderService.setNotificationListenerAccessGrantedForUser(
- cn, Integer.parseInt(userId), false);
+ int userId = ActivityManager.getCurrentUser();
+ if (peekNextArg() != null) {
+ userId = Integer.parseInt(getNextArgRequired());
}
+ mBinderService.setNotificationListenerAccessGrantedForUser(cn, userId, false);
}
break;
case "allow_assistant": {
@@ -155,7 +162,11 @@ public class NotificationShellCmd extends ShellCommand {
pw.println("Invalid assistant - must be a ComponentName");
return -1;
}
- mBinderService.setNotificationAssistantAccessGranted(cn, true);
+ int userId = ActivityManager.getCurrentUser();
+ if (peekNextArg() != null) {
+ userId = Integer.parseInt(getNextArgRequired());
+ }
+ mBinderService.setNotificationAssistantAccessGrantedForUser(cn, userId, true);
}
break;
case "disallow_assistant": {
@@ -164,7 +175,11 @@ public class NotificationShellCmd extends ShellCommand {
pw.println("Invalid assistant - must be a ComponentName");
return -1;
}
- mBinderService.setNotificationAssistantAccessGranted(cn, false);
+ int userId = ActivityManager.getCurrentUser();
+ if (peekNextArg() != null) {
+ userId = Integer.parseInt(getNextArgRequired());
+ }
+ mBinderService.setNotificationAssistantAccessGrantedForUser(cn, userId, false);
}
break;
case "suspend_package": {
@@ -176,6 +191,7 @@ public class NotificationShellCmd extends ShellCommand {
// only use for testing
mDirectService.simulatePackageSuspendBroadcast(false, getNextArgRequired());
}
+ break;
case "distract_package": {
// only use for testing
// Flag values are in
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 2c47ec03f9fa..660309cd578d 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -722,7 +722,8 @@ public class PreferencesHelper implements RankingConfig {
if (!channel.equals(updatedChannel)) {
// only log if there are real changes
- MetricsLogger.action(getChannelLog(updatedChannel, pkg));
+ MetricsLogger.action(getChannelLog(updatedChannel, pkg)
+ .setSubtype(fromUser ? 1 : 0));
}
if (updatedChannel.canBypassDnd() != mAreChannelsBypassingDnd
diff --git a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
index 1dada92ab118..f4454ae2a180 100644
--- a/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
+++ b/services/core/java/com/android/server/os/BugreportManagerServiceImpl.java
@@ -146,8 +146,8 @@ class BugreportManagerServiceImpl extends IDumpstate.Stub {
if (isDumpstateBinderServiceRunningLocked()) {
Slog.w(TAG, "'dumpstate' is already running. Cannot start a new bugreport"
+ " while another one is currently in progress.");
- // TODO(b/111441001): Use a new error code; add this to the documentation of the API.
- reportError(listener, IDumpstateListener.BUGREPORT_ERROR_RUNTIME_ERROR);
+ reportError(listener,
+ IDumpstateListener.BUGREPORT_ERROR_ANOTHER_REPORT_IN_PROGRESS);
return;
}
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index dc990afd729b..4dd58e0b9969 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -30,6 +30,7 @@ import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
import android.util.Slog;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.IndentingPrintWriter;
import java.io.File;
@@ -48,7 +49,9 @@ import java.util.stream.Collectors;
class ApexManager {
static final String TAG = "ApexManager";
private final IApexService mApexService;
- private final Map<String, PackageInfo> mActivePackagesCache;
+ private final Object mLock = new Object();
+ @GuardedBy("mLock")
+ private Map<String, PackageInfo> mActivePackagesCache;
ApexManager() {
try {
@@ -57,31 +60,35 @@ class ApexManager {
} catch (ServiceNotFoundException e) {
throw new IllegalStateException("Required service apexservice not available");
}
- mActivePackagesCache = populateActivePackagesCache();
}
- @NonNull
- private Map<String, PackageInfo> populateActivePackagesCache() {
- try {
- List<PackageInfo> list = new ArrayList<>();
- final ApexInfo[] activePkgs = mApexService.getActivePackages();
- for (ApexInfo ai : activePkgs) {
- // If the device is using flattened APEX, don't report any APEX
- // packages since they won't be managed or updated by PackageManager.
- if ((new File(ai.packagePath)).isDirectory()) {
- break;
- }
- try {
- list.add(PackageParser.generatePackageInfoFromApex(
- new File(ai.packagePath), true /* collect certs */));
- } catch (PackageParserException pe) {
- throw new IllegalStateException("Unable to parse: " + ai, pe);
+ private void populateActivePackagesCacheIfNeeded() {
+ synchronized (mLock) {
+ if (mActivePackagesCache != null) {
+ return;
+ }
+ try {
+ List<PackageInfo> list = new ArrayList<>();
+ final ApexInfo[] activePkgs = mApexService.getActivePackages();
+ for (ApexInfo ai : activePkgs) {
+ // If the device is using flattened APEX, don't report any APEX
+ // packages since they won't be managed or updated by PackageManager.
+ if ((new File(ai.packagePath)).isDirectory()) {
+ break;
+ }
+ try {
+ list.add(PackageParser.generatePackageInfoFromApex(
+ new File(ai.packagePath), true /* collect certs */));
+ } catch (PackageParserException pe) {
+ throw new IllegalStateException("Unable to parse: " + ai, pe);
+ }
}
+ mActivePackagesCache = list.stream().collect(
+ Collectors.toMap(p -> p.packageName, Function.identity()));
+ } catch (RemoteException re) {
+ Slog.e(TAG, "Unable to retrieve packages from apexservice: " + re.toString());
+ throw new RuntimeException(re);
}
- return list.stream().collect(Collectors.toMap(p -> p.packageName, Function.identity()));
- } catch (RemoteException re) {
- Slog.e(TAG, "Unable to retrieve packages from apexservice: " + re.toString());
- throw new RuntimeException(re);
}
}
@@ -96,6 +103,7 @@ class ApexManager {
* is not found.
*/
@Nullable PackageInfo getActivePackage(String packageName) {
+ populateActivePackagesCacheIfNeeded();
return mActivePackagesCache.get(packageName);
}
@@ -106,6 +114,7 @@ class ApexManager {
* active package.
*/
Collection<PackageInfo> getActivePackages() {
+ populateActivePackagesCacheIfNeeded();
return mActivePackagesCache.values();
}
@@ -205,6 +214,21 @@ class ApexManager {
}
/**
+ * Abandons the (only) active session previously submitted.
+ *
+ * @return {@code true} upon success, {@code false} if any remote exception occurs
+ */
+ boolean abortActiveSession() {
+ try {
+ mApexService.abortActiveSession();
+ return true;
+ } catch (RemoteException re) {
+ Slog.e(TAG, "Unable to contact apexservice", re);
+ return false;
+ }
+ }
+
+ /**
* Dumps various state information to the provided {@link PrintWriter} object.
*
* @param pw the {@link PrintWriter} object to send information to.
@@ -217,7 +241,7 @@ class ApexManager {
ipw.println("Active APEX packages:");
ipw.increaseIndent();
try {
- populateActivePackagesCache();
+ populateActivePackagesCacheIfNeeded();
for (PackageInfo pi : mActivePackagesCache.values()) {
if (packageName != null && !packageName.equals(pi.packageName)) {
continue;
@@ -254,4 +278,8 @@ class ApexManager {
ipw.println("Couldn't communicate with apexd.");
}
}
+
+ public void onBootCompleted() {
+ populateActivePackagesCacheIfNeeded();
+ }
}
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 62c4815a7de0..9e9128430e01 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -20,7 +20,6 @@ import android.annotation.NonNull;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
-import android.app.AppDetailsActivity;
import android.app.AppGlobals;
import android.app.IApplicationThread;
import android.app.PendingIntent;
@@ -367,7 +366,8 @@ public class LauncherAppsService extends SystemService {
private ResolveInfo getHiddenAppActivityInfo(String packageName, int callingUid,
UserHandle user) {
Intent intent = new Intent();
- intent.setComponent(new ComponentName(packageName, AppDetailsActivity.class.getName()));
+ intent.setComponent(new ComponentName(packageName,
+ PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME));
final PackageManagerInternal pmInt =
LocalServices.getService(PackageManagerInternal.class);
List<ResolveInfo> apps = pmInt.queryIntentActivities(intent,
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index f06da49f5b94..cced0f4a7eb2 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -209,8 +209,10 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
mStagingManager = new StagingManager(pm, this, am);
}
- private void setBootCompleted() {
+ private void onBootCompleted() {
mBootCompleted = true;
+ // Tell APEX manager about it as well
+ mApexManager.onBootCompleted();
}
boolean isBootCompleted() {
@@ -223,7 +225,7 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
mContext.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- setBootCompleted();
+ onBootCompleted();
mContext.unregisterReceiver(this);
}
}, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
@@ -483,11 +485,12 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
}
}
- if (params.isStaged) {
+ boolean isApex = (params.installFlags & PackageManager.INSTALL_APEX) != 0;
+ if (params.isStaged || isApex) {
mContext.enforceCallingOrSelfPermission(Manifest.permission.INSTALL_PACKAGES, TAG);
}
- if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
+ if (isApex) {
if (!mApexManager.isApexSupported()) {
throw new IllegalArgumentException(
"This device doesn't support the installation of APEX files");
@@ -821,6 +824,13 @@ public class PackageInstallerService extends IPackageInstaller.Stub implements
}
@Override
+ public void installExistingPackage(String packageName, int installFlags, int installReason,
+ IntentSender statusReceiver, int userId) {
+ mPm.installExistingPackageAsUser(packageName, userId, installFlags, installReason,
+ statusReceiver);
+ }
+
+ @Override
public void setPermissionsResult(int sessionId, boolean accepted) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, TAG);
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 1b719048bc89..7ed49fccb88d 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -322,18 +322,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_COMMIT:
- synchronized (mLock) {
- try {
- commitLocked();
- } catch (PackageManagerException e) {
- final String completeMsg = ExceptionUtils.getCompleteMessage(e);
- Slog.e(TAG,
- "Commit of session " + sessionId + " failed: " + completeMsg);
- destroyInternal();
- dispatchSessionFinished(e.error, completeMsg, null);
- }
- }
-
+ handleCommit();
break;
case MSG_ON_PACKAGE_INSTALLED:
final SomeArgs args = (SomeArgs) msg.obj;
@@ -501,9 +490,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
if (info.childSessionIds == null) {
info.childSessionIds = EMPTY_CHILD_SESSION_ARRAY;
}
- info.isSessionApplied = mStagedSessionApplied;
- info.isSessionReady = mStagedSessionReady;
- info.isSessionFailed = mStagedSessionFailed;
+ info.isStagedSessionApplied = mStagedSessionApplied;
+ info.isStagedSessionReady = mStagedSessionReady;
+ info.isStagedSessionFailed = mStagedSessionFailed;
info.setStagedSessionErrorCode(mStagedSessionErrorCode, mStagedSessionErrorMessage);
}
return info;
@@ -1073,38 +1062,66 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
mCallback.onSessionSealedBlocking(this);
}
- @GuardedBy("mLock")
- private void commitLocked()
- throws PackageManagerException {
+ private void handleCommit() {
if (params.isStaged) {
mStagingManager.commitSession(this);
destroyInternal();
dispatchSessionFinished(PackageManager.INSTALL_SUCCEEDED, "Session staged", null);
return;
}
+
if ((params.installFlags & PackageManager.INSTALL_APEX) != 0) {
- throw new PackageManagerException(
- PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
- "APEX packages can only be installed using staged sessions.");
+ destroyInternal();
+ dispatchSessionFinished(PackageManager.INSTALL_FAILED_INTERNAL_ERROR,
+ "APEX packages can only be installed using staged sessions.", null);
+ return;
+ }
+
+ // For a multiPackage session, read the child sessions
+ // outside of the lock, because reading the child
+ // sessions with the lock held could lead to deadlock
+ // (b/123391593).
+ List<PackageInstallerSession> childSessions = null;
+ if (isMultiPackage()) {
+ final int[] childSessionIds = getChildSessionIds();
+ childSessions = new ArrayList<>(childSessionIds.length);
+ for (int childSessionId : childSessionIds) {
+ childSessions.add(mSessionProvider.getSession(childSessionId));
+ }
}
+
+ try {
+ synchronized (mLock) {
+ commitNonStagedLocked(childSessions);
+ }
+ } catch (PackageManagerException e) {
+ final String completeMsg = ExceptionUtils.getCompleteMessage(e);
+ Slog.e(TAG, "Commit of session " + sessionId + " failed: " + completeMsg);
+ destroyInternal();
+ dispatchSessionFinished(e.error, completeMsg, null);
+ }
+ }
+
+ @GuardedBy("mLock")
+ private void commitNonStagedLocked(List<PackageInstallerSession> childSessions)
+ throws PackageManagerException {
final PackageManagerService.ActiveInstallSession committingSession =
makeSessionActiveLocked();
if (committingSession == null) {
return;
}
if (isMultiPackage()) {
- final int[] childSessionIds = getChildSessionIds();
- List<PackageManagerService.ActiveInstallSession> childSessions =
- new ArrayList<>(childSessionIds.length);
+ List<PackageManagerService.ActiveInstallSession> activeChildSessions =
+ new ArrayList<>(childSessions.size());
boolean success = true;
PackageManagerException failure = null;
- for (int childSessionId : getChildSessionIds()) {
- final PackageInstallerSession session = mSessionProvider.getSession(childSessionId);
+ for (int i = 0; i < childSessions.size(); ++i) {
+ final PackageInstallerSession session = childSessions.get(i);
try {
final PackageManagerService.ActiveInstallSession activeSession =
session.makeSessionActiveLocked();
if (activeSession != null) {
- childSessions.add(activeSession);
+ activeChildSessions.add(activeSession);
}
} catch (PackageManagerException e) {
failure = e;
@@ -1119,7 +1136,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
return;
}
- mPm.installStage(childSessions);
+ mPm.installStage(activeChildSessions);
} else {
mPm.installStage(committingSession);
}
@@ -1474,12 +1491,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
// Inherit base if not overridden
if (mResolvedBaseFile == null) {
mResolvedBaseFile = new File(appInfo.getBaseCodePath());
- mResolvedInheritedFiles.add(mResolvedBaseFile);
+ resolveInheritedFile(mResolvedBaseFile);
// Inherit the dex metadata if present.
final File baseDexMetadataFile =
DexMetadataHelper.findDexMetadataForFile(mResolvedBaseFile);
if (baseDexMetadataFile != null) {
- mResolvedInheritedFiles.add(baseDexMetadataFile);
+ resolveInheritedFile(baseDexMetadataFile);
}
baseApk = existingBase;
}
@@ -1491,12 +1508,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
final File splitFile = new File(existing.splitCodePaths[i]);
final boolean splitRemoved = removeSplitList.contains(splitName);
if (!stagedSplits.contains(splitName) && !splitRemoved) {
- mResolvedInheritedFiles.add(splitFile);
+ resolveInheritedFile(splitFile);
// Inherit the dex metadata if present.
final File splitDexMetadataFile =
DexMetadataHelper.findDexMetadataForFile(splitFile);
if (splitDexMetadataFile != null) {
- mResolvedInheritedFiles.add(splitDexMetadataFile);
+ resolveInheritedFile(splitDexMetadataFile);
}
}
}
@@ -1610,6 +1627,17 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
mResolvedStagedFiles.add(stagedSignature);
}
+ private void resolveInheritedFile(File origFile) {
+ mResolvedInheritedFiles.add(origFile);
+
+ // Inherit the fsverity signature file if present.
+ final File fsveritySignatureFile = new File(
+ VerityUtils.getFsveritySignatureFilePath(origFile.getPath()));
+ if (fsveritySignatureFile.exists()) {
+ mResolvedInheritedFiles.add(fsveritySignatureFile);
+ }
+ }
+
@GuardedBy("mLock")
private void assertApkConsistentLocked(String tag, ApkLite apk)
throws PackageManagerException {
@@ -1839,6 +1867,15 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
synchronized (mLock) {
assertCallerIsOwnerOrRootLocked();
+ if (mCommitted && params.isStaged) {
+ synchronized (mLock) {
+ mDestroyed = true;
+ }
+ mStagingManager.abortCommittedSession(this);
+
+ //TODO(b/123624108): delete staging dir
+ }
+
if (mRelinquished) {
Slog.d(TAG, "Ignoring abandon after commit relinquished control");
return;
@@ -1869,7 +1906,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
@Override
- public void addChildSessionId(int childSessionId) {
+ public void addChildSessionId(int childSessionId) throws RemoteException {
final PackageInstallerSession childSession = mSessionProvider.getSession(childSessionId);
if (childSession == null) {
throw new RemoteException("Unable to add child.",
@@ -1884,9 +1921,12 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
new PackageManagerException("Child session " + childSessionId
+ " and parent session " + this.sessionId + " do not have consistent"
+ " staging session settings."),
- false, true).rethrowAsRuntimeException();
+ false, true);
}
synchronized (mLock) {
+ assertCallerIsOwnerOrRootLocked();
+ assertPreparedAndNotSealedLocked("addChildSessionId");
+
final int indexOfSession = mChildSessionIds.indexOfKey(childSessionId);
if (indexOfSession >= 0) {
return;
@@ -1998,6 +2038,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
mStagedSessionErrorMessage = errorMessage;
Slog.d(TAG, "Marking session " + sessionId + " as failed: " + errorMessage);
}
+ cleanStageDir();
mCallback.onStagedSessionChanged(this);
}
@@ -2009,7 +2050,9 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
mStagedSessionFailed = false;
mStagedSessionErrorCode = SessionInfo.STAGED_SESSION_NO_ERROR;
mStagedSessionErrorMessage = "";
+ Slog.d(TAG, "Marking session " + sessionId + " as applied");
}
+ cleanStageDir();
mCallback.onStagedSessionChanged(this);
}
@@ -2064,6 +2107,19 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
}
}
+ private void cleanStageDir() {
+ if (isMultiPackage()) {
+ for (int childSessionId : getChildSessionIds()) {
+ mSessionProvider.getSession(childSessionId).cleanStageDir();
+ }
+ } else {
+ try {
+ mPm.mInstaller.rmPackageDir(stageDir.getAbsolutePath());
+ } catch (InstallerException ignored) {
+ }
+ }
+ }
+
void dump(IndentingPrintWriter pw) {
synchronized (mLock) {
dumpLocked(pw);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 07d460edb2d2..e7e3e833d385 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -121,7 +121,6 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
-import android.app.AppDetailsActivity;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
import android.app.IActivityManager;
@@ -630,6 +629,7 @@ public class PackageManagerService extends IPackageManager.Stub
final boolean mIsUpgrade;
final boolean mIsPreNUpgrade;
final boolean mIsPreNMR1Upgrade;
+ final boolean mIsPreQUpgrade;
@GuardedBy("mPackages")
private boolean mDexOptDialogShown;
@@ -1303,12 +1303,14 @@ public class PackageManagerService extends IPackageManager.Stub
// Recordkeeping of restore-after-install operations that are currently in flight
// between the Package Manager and the Backup Manager
static class PostInstallData {
- public InstallArgs args;
- public PackageInstalledInfo res;
+ public final InstallArgs args;
+ public final PackageInstalledInfo res;
+ public final Runnable mPostInstallRunnable;
- PostInstallData(InstallArgs _a, PackageInstalledInfo _r) {
+ PostInstallData(InstallArgs _a, PackageInstalledInfo _r, Runnable postInstallRunnable) {
args = _a;
res = _r;
+ mPostInstallRunnable = postInstallRunnable;
}
}
@@ -1440,7 +1442,9 @@ public class PackageManagerService extends IPackageManager.Stub
final boolean didRestore = (msg.arg2 != 0);
mRunningInstalls.delete(msg.arg1);
- if (data != null) {
+ if (data != null && data.mPostInstallRunnable != null) {
+ data.mPostInstallRunnable.run();
+ } else if (data != null) {
InstallArgs args = data.args;
PackageInstalledInfo parentRes = data.res;
@@ -2396,6 +2400,7 @@ public class PackageManagerService extends IPackageManager.Stub
mIsPreNUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N;
mIsPreNMR1Upgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.N_MR1;
+ mIsPreQUpgrade = mIsUpgrade && ver.sdkVersion < Build.VERSION_CODES.Q;
int preUpgradeSdkVersion = ver.sdkVersion;
@@ -3022,6 +3027,21 @@ public class PackageManagerService extends IPackageManager.Stub
ver.fingerprint = Build.FINGERPRINT;
}
+ // Grandfather existing (installed before Q) non-system apps to hide
+ // their icons in launcher.
+ if (!onlyCore && mIsPreQUpgrade) {
+ Slog.i(TAG, "Whitelisting all existing apps to hide their icons");
+ int size = mSettings.mPackages.size();
+ for (int i = 0; i < size; i++) {
+ final PackageSetting ps = mSettings.mPackages.valueAt(i);
+ if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ continue;
+ }
+ ps.disableComponentLPw(PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME,
+ UserHandle.USER_SYSTEM);
+ }
+ }
+
// clear only after permissions and other defaults have been updated
mExistingSystemPackages.clear();
mPromoteSystemApps = false;
@@ -4212,6 +4232,55 @@ public class PackageManagerService extends IPackageManager.Stub
return -1;
}
+ /**
+ * Check if any package sharing/holding a uid has a low enough target SDK.
+ *
+ * @param uid The uid of the packages
+ * @param higherTargetSDK The target SDK that might be higher than the searched package
+ *
+ * @return {@code true} if there is a package sharing/holding the uid with
+ * {@code package.targetSDK < higherTargetSDK}
+ */
+ private boolean hasTargetSdkInUidLowerThan(int uid, int higherTargetSDK) {
+ int userId = UserHandle.getUserId(uid);
+
+ synchronized (mPackages) {
+ Object obj = mSettings.getSettingLPr(UserHandle.getAppId(uid));
+ if (obj == null) {
+ return false;
+ }
+
+ if (obj instanceof PackageSetting) {
+ final PackageSetting ps = (PackageSetting) obj;
+
+ if (!ps.getInstalled(userId)) {
+ return false;
+ }
+
+ return ps.pkg.applicationInfo.targetSdkVersion < higherTargetSDK;
+ } else if (obj instanceof SharedUserSetting) {
+ final SharedUserSetting sus = (SharedUserSetting) obj;
+
+ final int numPkgs = sus.packages.size();
+ for (int i = 0; i < numPkgs; i++) {
+ final PackageSetting ps = sus.packages.valueAt(i);
+
+ if (!ps.getInstalled(userId)) {
+ continue;
+ }
+
+ if (ps.pkg.applicationInfo.targetSdkVersion < higherTargetSDK) {
+ return true;
+ }
+ }
+
+ return false;
+ } else {
+ return false;
+ }
+ }
+ }
+
@Override
public int[] getPackageGids(String packageName, int flags, int userId) {
if (!sUserManager.exists(userId)) return null;
@@ -5280,13 +5349,21 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public void grantRuntimePermission(String packageName, String permName, final int userId) {
- mPermissionManager.grantRuntimePermission(permName, packageName, false /*overridePolicy*/,
+ boolean overridePolicy = (checkUidPermission(
+ Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, Binder.getCallingUid())
+ == PackageManager.PERMISSION_GRANTED);
+
+ mPermissionManager.grantRuntimePermission(permName, packageName, overridePolicy,
getCallingUid(), userId, mPermissionCallback);
}
@Override
public void revokeRuntimePermission(String packageName, String permName, int userId) {
- mPermissionManager.revokeRuntimePermission(permName, packageName, false /*overridePolicy*/,
+ boolean overridePolicy = (checkUidPermission(
+ Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, Binder.getCallingUid())
+ == PackageManager.PERMISSION_GRANTED);
+
+ mPermissionManager.revokeRuntimePermission(permName, packageName, overridePolicy,
getCallingUid(), userId, mPermissionCallback);
}
@@ -5329,10 +5406,37 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public void updatePermissionFlags(String permName, String packageName, int flagMask,
- int flagValues, int userId) {
+ int flagValues, boolean checkAdjustPolicyFlagPermission, int userId) {
+ int callingUid = getCallingUid();
+ boolean overridePolicy = false;
+
+ if (callingUid != Process.SYSTEM_UID && callingUid != Process.ROOT_UID) {
+ long callingIdentity = Binder.clearCallingIdentity();
+ try {
+ if ((flagMask & FLAG_PERMISSION_POLICY_FIXED) != 0) {
+ if (checkAdjustPolicyFlagPermission) {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY,
+ "Need " + Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY
+ + " to change policy flags");
+ } else if (!hasTargetSdkInUidLowerThan(callingUid, Build.VERSION_CODES.Q)) {
+ throw new IllegalArgumentException(
+ Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY + " needs "
+ + " to be checked for packages targeting "
+ + Build.VERSION_CODES.Q + " or later when changing policy "
+ + "flags");
+ }
+
+ overridePolicy = true;
+ }
+ } finally {
+ Binder.restoreCallingIdentity(callingIdentity);
+ }
+ }
+
mPermissionManager.updatePermissionFlags(
- permName, packageName, flagMask, flagValues, getCallingUid(), userId,
- mPermissionCallback);
+ permName, packageName, flagMask, flagValues, callingUid, userId,
+ overridePolicy, mPermissionCallback);
}
/**
@@ -12683,6 +12787,11 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public int installExistingPackageAsUser(String packageName, int userId, int installFlags,
int installReason) {
+ return installExistingPackageAsUser(packageName, userId, installFlags, installReason, null);
+ }
+
+ int installExistingPackageAsUser(String packageName, int userId, int installFlags,
+ int installReason, IntentSender intentSender) {
if (DEBUG_INSTALL) {
Log.v(TAG, "installExistingPackageAsUser package=" + packageName + " userId=" + userId
+ " installFlags=" + installFlags + " installReason=" + installReason);
@@ -12762,7 +12871,11 @@ public class PackageManagerService extends IPackageManager.Stub
PackageInstalledInfo res =
createPackageInstalledInfo(PackageManager.INSTALL_SUCCEEDED);
res.pkg = pkgSetting.pkg;
- restoreAndPostInstall(userId, res, null);
+ res.newUsers = new int[]{ userId };
+ PostInstallData postInstallData = intentSender == null ? null :
+ new PostInstallData(null, res, () -> onRestoreComplete(res.returnCode,
+ mContext, intentSender));
+ restoreAndPostInstall(userId, res, postInstallData);
}
} finally {
Binder.restoreCallingIdentity(callingId);
@@ -12771,6 +12884,16 @@ public class PackageManagerService extends IPackageManager.Stub
return PackageManager.INSTALL_SUCCEEDED;
}
+ static void onRestoreComplete(int returnCode, Context context, IntentSender target) {
+ Intent fillIn = new Intent();
+ fillIn.putExtra(PackageInstaller.EXTRA_STATUS,
+ PackageManager.installStatusToPublicStatus(returnCode));
+ try {
+ target.sendIntent(context, 0, fillIn, null, null);
+ } catch (SendIntentException ignored) {
+ }
+ }
+
static void setInstantAppForUser(PackageSetting pkgSetting, int userId,
boolean instantApp, boolean fullApp) {
// no state specified; do nothing
@@ -12867,8 +12990,14 @@ public class PackageManagerService extends IPackageManager.Stub
"setPackagesSuspendedAsUser");
final int callingUid = Binder.getCallingUid();
- if (callingUid != Process.ROOT_UID && callingUid != Process.SYSTEM_UID
- && getPackageUid(callingPackage, 0, userId) != callingUid) {
+ final int packageUid = getPackageUid(callingPackage, 0, userId);
+ final boolean allowedCallingUid = callingUid == Process.ROOT_UID
+ || callingUid == Process.SYSTEM_UID;
+ final boolean allowedPackageUid = packageUid == callingUid;
+ final boolean allowedShell = callingUid == SHELL_UID
+ && UserHandle.isSameApp(packageUid, callingUid);
+
+ if (!allowedCallingUid && !allowedShell && !allowedPackageUid) {
throw new SecurityException("Calling package " + callingPackage + " in user "
+ userId + " does not belong to calling uid " + callingUid);
}
@@ -13727,7 +13856,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
for (InstallRequest request : installRequests) {
restoreAndPostInstall(request.args.user.getIdentifier(), request.installResult,
- new PostInstallData(request.args, request.installResult));
+ new PostInstallData(request.args, request.installResult, null));
}
});
}
@@ -17041,7 +17170,7 @@ public class PackageManagerService extends IPackageManager.Stub
if (!legacyMode) {
// fs-verity is optional for now. Only set up if signature is provided.
- if (new File(signaturePath).exists()) {
+ if (new File(signaturePath).exists() && !VerityUtils.hasFsverity(filePath)) {
try {
VerityUtils.setUpFsverity(filePath, signaturePath);
} catch (IOException | DigestException | NoSuchAlgorithmException
@@ -19948,8 +20077,11 @@ public class PackageManagerService extends IPackageManager.Stub
private @Nullable String getDocumenterPackageName() {
final Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("*/*");
+ final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver());
- final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, null,
+ final List<ResolveInfo> matches = queryIntentActivitiesInternal(intent, resolvedType,
MATCH_SYSTEM_ONLY | MATCH_DIRECT_BOOT_AWARE | MATCH_DIRECT_BOOT_UNAWARE
| MATCH_DISABLED_COMPONENTS,
UserHandle.myUserId());
@@ -20104,13 +20236,9 @@ public class PackageManagerService extends IPackageManager.Stub
}
// Only allow apps with CHANGE_COMPONENT_ENABLED_STATE permission to change hidden
// app details activity
- if (AppDetailsActivity.class.getName().equals(className)) {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE)
- != PackageManager.PERMISSION_GRANTED) {
- Slog.e(TAG, "Cannot disable a protected component: " + packageName);
- return;
- }
+ if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(className)
+ && !allowedByPermission) {
+ throw new SecurityException("Cannot disable a system-generated component");
}
synchronized (mPackages) {
@@ -22997,7 +23125,7 @@ public class PackageManagerService extends IPackageManager.Stub
public void updatePermissionFlagsTEMP(String permName, String packageName, int flagMask,
int flagValues, int userId) {
PackageManagerService.this.updatePermissionFlags(
- permName, packageName, flagMask, flagValues, userId);
+ permName, packageName, flagMask, flagValues, true, userId);
}
@Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 2eb762b59be4..114810d9127b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -300,9 +300,9 @@ class PackageManagerShellCommand extends ShellCommand {
pw.println("appPackageName = " + session.getAppPackageName()
+ "; sessionId = " + session.getSessionId()
+ "; isStaged = " + session.isStaged()
- + "; isSessionReady = " + session.isSessionReady()
- + "; isSessionApplied = " + session.isSessionApplied()
- + "; isSessionFailed = " + session.isSessionFailed() + ";");
+ + "; isStagedSessionReady = " + session.isStagedSessionReady()
+ + "; isStagedSessionApplied = " + session.isStagedSessionApplied()
+ + "; isStagedSessionFailed = " + session.isStagedSessionFailed() + ";");
}
} catch (RemoteException e) {
pw.println("Failure ["
@@ -1114,6 +1114,7 @@ class PackageManagerShellCommand extends ShellCommand {
int userId = UserHandle.USER_SYSTEM;
int installFlags = 0;
String opt;
+ boolean waitTillComplete = false;
while ((opt = getNextOption()) != null) {
switch (opt) {
case "--user":
@@ -1128,6 +1129,9 @@ class PackageManagerShellCommand extends ShellCommand {
installFlags &= ~PackageManager.INSTALL_INSTANT_APP;
installFlags |= PackageManager.INSTALL_FULL_APP;
break;
+ case "--wait":
+ waitTillComplete = true;
+ break;
default:
pw.println("Error: Unknown option: " + opt);
return 1;
@@ -1140,9 +1144,23 @@ class PackageManagerShellCommand extends ShellCommand {
return 1;
}
+ int installReason = PackageManager.INSTALL_REASON_UNKNOWN;
try {
+ if (waitTillComplete) {
+ final LocalIntentReceiver receiver = new LocalIntentReceiver();
+ final IPackageInstaller installer = mInterface.getPackageInstaller();
+ pw.println("Installing package " + packageName + " for user: " + userId);
+ installer.installExistingPackage(packageName, installFlags, installReason,
+ receiver.getIntentSender(), userId);
+ final Intent result = receiver.getResult();
+ final int status = result.getIntExtra(PackageInstaller.EXTRA_STATUS,
+ PackageInstaller.STATUS_FAILURE);
+ pw.println("Received intent for package install");
+ return status == PackageInstaller.STATUS_SUCCESS ? 0 : 1;
+ }
+
final int res = mInterface.installExistingPackageAsUser(packageName, userId,
- installFlags, PackageManager.INSTALL_REASON_UNKNOWN);
+ installFlags, installReason);
if (res == PackageManager.INSTALL_FAILED_INVALID_URI) {
throw new NameNotFoundException("Package " + packageName + " doesn't exist");
}
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index ff6d7a888950..9deea9ec8622 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -2173,7 +2173,8 @@ public class ShortcutService extends IShortcutService.Stub {
public boolean hasShareTargets(String packageName, String packageToCheck,
@UserIdInt int userId) {
verifyCaller(packageName, userId);
- enforceSystem();
+ enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_APP_PREDICTIONS,
+ "hasShareTargets");
synchronized (mLock) {
throwIfUserLockedL(userId);
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 9dfd477a564d..e956b74cf214 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -419,7 +419,12 @@ public class StagingManager {
if (apkChildSession == null) {
return false;
}
- apkParentSession.addChildSessionId(apkChildSession.sessionId);
+ try {
+ apkParentSession.addChildSessionId(apkChildSession.sessionId);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to add a child session for installing the APK files", e);
+ return false;
+ }
}
return commitApkSession(apkParentSession, session.sessionId);
}
@@ -440,11 +445,32 @@ public class StagingManager {
void abortSession(@NonNull PackageInstallerSession session) {
synchronized (mStagedSessions) {
- updateStoredSession(session);
mStagedSessions.remove(session.sessionId);
}
}
+ void abortCommittedSession(@NonNull PackageInstallerSession session) {
+ if (session.isStagedSessionApplied()) {
+ Slog.w(TAG, "Cannot abort applied session!");
+ return;
+ }
+ if (isStagedSessionFinalized(session.sessionId)) {
+ Slog.w(TAG, "Cannot abort session because it is not active or APEXD is not reachable");
+ return;
+ }
+
+ mApexManager.abortActiveSession();
+
+ abortSession(session);
+ }
+
+ private boolean isStagedSessionFinalized(int sessionId) {
+ ApexSessionInfo session = mApexManager.getStagedSessionInfo(sessionId);
+
+ /* checking if the session is in a final state, i.e., not active anymore */
+ return session.isUnknown || session.isActivationFailed || session.isSuccess;
+ }
+
@GuardedBy("mStagedSessions")
private boolean isMultiPackageSessionComplete(@NonNull PackageInstallerSession session) {
// This method assumes that the argument is either a parent session of a multi-package
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index d0f192d597c6..3744f68afbfe 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1324,6 +1324,7 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public ParcelFileDescriptor getUserIcon(int targetUserId) {
+ checkManageUsersPermission("get user icon");
String iconPath;
synchronized (mPackagesLock) {
UserInfo targetUserInfo = getUserInfoNoChecks(targetUserId);
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 636917921652..447234ed290b 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -206,6 +206,11 @@ public final class DefaultPermissionGrantPolicy {
// STOPSHIP(b/112545973): remove once feature enabled by default
if (StorageManager.hasIsolatedStorage()) {
MEDIA_AURAL_PERMISSIONS.add(Manifest.permission.READ_MEDIA_AUDIO);
+
+ // STOPSHIP(b/124466734): remove these manual grants once the legacy
+ // permission logic is unified with PermissionController
+ MEDIA_AURAL_PERMISSIONS.add(Manifest.permission.READ_EXTERNAL_STORAGE);
+ MEDIA_AURAL_PERMISSIONS.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
}
@@ -215,6 +220,11 @@ public final class DefaultPermissionGrantPolicy {
if (StorageManager.hasIsolatedStorage()) {
MEDIA_VISUAL_PERMISSIONS.add(Manifest.permission.READ_MEDIA_VIDEO);
MEDIA_VISUAL_PERMISSIONS.add(Manifest.permission.READ_MEDIA_IMAGES);
+
+ // STOPSHIP(b/124466734): remove these manual grants once the legacy
+ // permission logic is unified with PermissionController
+ MEDIA_VISUAL_PERMISSIONS.add(Manifest.permission.READ_EXTERNAL_STORAGE);
+ MEDIA_VISUAL_PERMISSIONS.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
}
}
@@ -642,16 +652,10 @@ public final class DefaultPermissionGrantPolicy {
// Location
if (locationPackageNames != null) {
for (String packageName : locationPackageNames) {
- // STOPSHIP: remove this force-granting of legacy storage
- // permissions once b/124466734 is resolved
- final Set<String> storageWorkaround = new ArraySet<>();
- storageWorkaround.add(Manifest.permission.READ_EXTERNAL_STORAGE);
- storageWorkaround.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
-
grantPermissionsToSystemPackage(packageName, userId,
CONTACTS_PERMISSIONS, CALENDAR_PERMISSIONS, MICROPHONE_PERMISSIONS,
PHONE_PERMISSIONS, SMS_PERMISSIONS, CAMERA_PERMISSIONS,
- SENSORS_PERMISSIONS, STORAGE_PERMISSIONS, storageWorkaround);
+ SENSORS_PERMISSIONS, STORAGE_PERMISSIONS, MEDIA_AURAL_PERMISSIONS);
grantSystemFixedPermissionsToSystemPackage(packageName, userId,
LOCATION_PERMISSIONS, ACTIVITY_RECOGNITION_PERMISSIONS);
}
@@ -846,7 +850,7 @@ public final class DefaultPermissionGrantPolicy {
}
for (String packageName : packageNames) {
grantPermissionsToSystemPackage(packageName, userId,
- PHONE_PERMISSIONS, LOCATION_PERMISSIONS, SMS_PERMISSIONS);
+ PHONE_PERMISSIONS, ALWAYS_LOCATION_PERMISSIONS, SMS_PERMISSIONS);
}
}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 8df5a71de43e..03da962b6ac6 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -35,6 +35,7 @@ import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQU
import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
+import static android.content.pm.PackageManager.MASK_PERMISSION_FLAGS;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.os.UserHandle.getAppId;
import static android.os.UserHandle.getUid;
@@ -1031,7 +1032,8 @@ public class PermissionManagerService {
updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
}
- permissionsState.updatePermissionFlags(bp, userId, flags, flags);
+ permissionsState.updatePermissionFlags(bp, userId,
+ MASK_PERMISSION_FLAGS, flags);
}
} break;
@@ -1081,7 +1083,8 @@ public class PermissionManagerService {
updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
}
- permissionsState.updatePermissionFlags(bp, userId, flags, flags);
+ permissionsState.updatePermissionFlags(bp, userId,
+ MASK_PERMISSION_FLAGS, flags);
}
} break;
@@ -1198,29 +1201,23 @@ public class PermissionManagerService {
if ((flags & FLAG_PERMISSION_REVOKE_WHEN_REQUESTED) != 0) {
BasePermission bp = mSettings.getPermissionLocked(permission);
- ps.updatePermissionFlags(bp, userId,
- FLAG_PERMISSION_REVOKE_WHEN_REQUESTED
- | FLAG_PERMISSION_USER_FIXED | FLAG_PERMISSION_USER_SET,
- 0);
- updatedUserIds = ArrayUtils.appendInt(updatedUserIds,
- userId);
+ int flagsToRemove = FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
if ((flags & (FLAG_PERMISSION_GRANTED_BY_DEFAULT
| FLAG_PERMISSION_POLICY_FIXED | FLAG_PERMISSION_SYSTEM_FIXED))
- == 0) {
- if (supportsRuntimePermissions) {
- int revokeResult = ps.revokeRuntimePermission(bp, userId);
- if (revokeResult != PERMISSION_OPERATION_FAILURE) {
- if (DEBUG_PERMISSIONS) {
- Slog.i(TAG, "Revoking runtime permission "
- + permission + " for " + pkgName
- + " as it is now requested");
- }
+ == 0 && supportsRuntimePermissions) {
+ int revokeResult = ps.revokeRuntimePermission(bp, userId);
+ if (revokeResult != PERMISSION_OPERATION_FAILURE) {
+ if (DEBUG_PERMISSIONS) {
+ Slog.i(TAG, "Revoking runtime permission "
+ + permission + " for " + pkgName
+ + " as it is now requested");
}
- } else {
- setAppOpMode(permission, pkg, userId, MODE_IGNORED);
}
+ flagsToRemove |=
+ FLAG_PERMISSION_USER_FIXED | FLAG_PERMISSION_USER_SET;
+
List<String> fgPerms = mBackgroundPermissions.get(permission);
if (fgPerms != null) {
int numFgPerms = fgPerms.size();
@@ -1238,6 +1235,9 @@ public class PermissionManagerService {
}
}
}
+
+ ps.updatePermissionFlags(bp, userId, flagsToRemove, 0);
+ updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
}
}
}
@@ -1935,7 +1935,7 @@ public class PermissionManagerService {
if ((flags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
updatePermissionFlags(permission, pkg.packageName,
PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED, 0, callingUid,
- userId, callback);
+ userId, false, callback);
}
}
}
@@ -2441,7 +2441,8 @@ public class PermissionManagerService {
}
private void updatePermissionFlags(String permName, String packageName, int flagMask,
- int flagValues, int callingUid, int userId, PermissionCallback callback) {
+ int flagValues, int callingUid, int userId, boolean overridePolicy,
+ PermissionCallback callback) {
if (!mUserManagerInt.exists(userId)) {
return;
}
@@ -2454,6 +2455,11 @@ public class PermissionManagerService {
false, // requirePermissionWhenSameUser
"updatePermissionFlags");
+ if ((flagMask & FLAG_PERMISSION_POLICY_FIXED) != 0 && !overridePolicy) {
+ throw new SecurityException("updatePermissionFlags requires "
+ + Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY);
+ }
+
// Only the system can change these flags and nothing else.
if (callingUid != Process.SYSTEM_UID) {
flagMask &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
@@ -2745,9 +2751,11 @@ public class PermissionManagerService {
}
@Override
public void updatePermissionFlags(String permName, String packageName, int flagMask,
- int flagValues, int callingUid, int userId, PermissionCallback callback) {
+ int flagValues, int callingUid, int userId, boolean overridePolicy,
+ PermissionCallback callback) {
PermissionManagerService.this.updatePermissionFlags(
- permName, packageName, flagMask, flagValues, callingUid, userId, callback);
+ permName, packageName, flagMask, flagValues, callingUid, userId,
+ overridePolicy, callback);
}
@Override
public boolean updatePermissionFlagsForAllApps(int flagMask, int flagValues, int callingUid,
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index 1dd2408686c1..305f165ae85f 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -147,7 +147,7 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
*/
public abstract void updatePermissionFlags(@NonNull String permName,
@NonNull String packageName, int flagMask, int flagValues, int callingUid, int userId,
- @Nullable PermissionCallback callback);
+ boolean overridePolicy, @Nullable PermissionCallback callback);
/**
* Updates the flags for all applications by replacing the flags in the specified mask
* with the provided flag values.
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index c87a81db16e4..0759419be608 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -86,6 +86,9 @@ import static android.view.WindowManagerGlobal.ADD_PERMISSION_DENIED;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVERED;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_COVER_ABSENT;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.CAMERA_LENS_UNCOVERED;
+import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_BEHAVIOR_LOCK;
+import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_BEHAVIOR_NONE;
+import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_BEHAVIOR_SLEEP;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_CLOSED;
import static com.android.server.policy.WindowManagerPolicy.WindowManagerFuncs.LID_OPEN;
import static com.android.server.wm.WindowManagerPolicyProto.KEYGUARD_DELEGATE;
@@ -473,8 +476,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
int mLidKeyboardAccessibility;
int mLidNavigationAccessibility;
- boolean mLidControlsScreenLock;
- boolean mLidControlsSleep;
private boolean mLidControlsDisplayFold;
int mShortPressOnPowerBehavior;
int mLongPressOnPowerBehavior;
@@ -808,7 +809,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
public void onWakeUp() {
synchronized (mLock) {
if (shouldEnableWakeGestureLp()) {
- performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false,
+ performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, false,
"Wake Up");
wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture,
PowerManager.WAKE_REASON_GESTURE, "android.policy:GESTURE");
@@ -1195,6 +1196,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
+ private int getLidBehavior() {
+ return Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.LID_BEHAVIOR, LID_BEHAVIOR_NONE);
+ }
+
private int getMaxMultiPressPowerCount() {
if (mTriplePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
return 3;
@@ -1212,21 +1218,21 @@ public class PhoneWindowManager implements WindowManagerPolicy {
break;
case LONG_PRESS_POWER_GLOBAL_ACTIONS:
mPowerKeyHandled = true;
- performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false,
+ performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,
"Power - Long Press - Global Actions");
showGlobalActionsInternal();
break;
case LONG_PRESS_POWER_SHUT_OFF:
case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
mPowerKeyHandled = true;
- performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false,
+ performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,
"Power - Long Press - Shut Off");
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF);
break;
case LONG_PRESS_POWER_GO_TO_VOICE_ASSIST:
mPowerKeyHandled = true;
- performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false,
+ performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,
"Power - Long Press - Go To Voice Assist");
final boolean keyguardActive = mKeyguardDelegate == null
? false
@@ -1249,7 +1255,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
break;
case VERY_LONG_PRESS_POWER_GLOBAL_ACTIONS:
mPowerKeyHandled = true;
- performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false,
+ performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,
"Power - Very Long Press - Show Global Actions");
showGlobalActionsInternal();
break;
@@ -1400,7 +1406,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void run() {
mEndCallKeyHandled = true;
- performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false,
+ performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,
"End Call - Long Press - Show Global Actions");
showGlobalActionsInternal();
}
@@ -1667,7 +1673,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return;
}
mHomeConsumed = true;
- performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false,
+ performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,
"Home - Long Press");
switch (mLongPressOnHomeBehavior) {
case LONG_PRESS_HOME_ALL_APPS:
@@ -1796,10 +1802,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
com.android.internal.R.integer.config_lidKeyboardAccessibility);
mLidNavigationAccessibility = mContext.getResources().getInteger(
com.android.internal.R.integer.config_lidNavigationAccessibility);
- mLidControlsScreenLock = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_lidControlsScreenLock);
- mLidControlsSleep = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_lidControlsSleep);
mLidControlsDisplayFold = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_lidControlsDisplayFold);
@@ -2040,7 +2042,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private boolean shouldEnableWakeGestureLp() {
return mWakeGestureEnabledSetting && !mDefaultDisplayPolicy.isAwake()
- && (!mLidControlsSleep || mDefaultDisplayPolicy.getLidState() != LID_CLOSED)
+ && (getLidBehavior() != LID_BEHAVIOR_SLEEP
+ || mDefaultDisplayPolicy.getLidState() != LID_CLOSED)
&& mWakeGestureListener.isSupported();
}
@@ -2316,14 +2319,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean allowWhenLocked = (win.isInputMethodWindow() || imeTarget == this)
&& showImeOverKeyguard;
- if (isKeyguardLocked() && isKeyguardOccluded()) {
+ final boolean isKeyguardShowing = mKeyguardDelegate.isShowing();
+
+ if (isKeyguardShowing && isKeyguardOccluded()) {
// Show SHOW_WHEN_LOCKED windows if Keyguard is occluded.
allowWhenLocked |= win.canShowWhenLocked()
// Show error dialogs over apps that are shown on lockscreen
|| (attrs.privateFlags & PRIVATE_FLAG_SYSTEM_ERROR) != 0;
}
- boolean keyguardLocked = isKeyguardLocked();
boolean hideDockDivider = attrs.type == TYPE_DOCK_DIVIDER
&& !mWindowManagerInternal.isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
// If AOD is showing, the IME should be hidden. However, sometimes the AOD is considered
@@ -2333,7 +2337,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// now shown.
final boolean hideIme = win.isInputMethodWindow()
&& (mAodShowing || !mDefaultDisplayPolicy.isWindowManagerDrawComplete());
- return (keyguardLocked && !allowWhenLocked && win.getDisplayId() == DEFAULT_DISPLAY)
+ return (isKeyguardShowing && !allowWhenLocked && win.getDisplayId() == DEFAULT_DISPLAY)
|| hideDockDivider || hideIme;
}
@@ -3276,7 +3280,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
private void launchAssistLongPressAction() {
- performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false,
+ performHapticFeedback(HapticFeedbackConstants.LONG_PRESS, false,
"Assist - Long Press");
sendCloseSystemWindows(SYSTEM_DIALOG_REASON_ASSIST);
@@ -3545,7 +3549,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (lidOpen) {
wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch,
PowerManager.WAKE_REASON_LID, "android.policy:LID");
- } else if (!mLidControlsSleep) {
+ } else if (getLidBehavior() != LID_BEHAVIOR_SLEEP) {
mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
}
}
@@ -4038,7 +4042,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
if (useHapticFeedback) {
- performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false,
+ performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, false,
"Virtual Key - Press");
}
@@ -4759,7 +4763,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
public void setSafeMode(boolean safeMode) {
mSafeMode = safeMode;
if (safeMode) {
- performHapticFeedbackLw(null, HapticFeedbackConstants.SAFE_MODE_ENABLED, true,
+ performHapticFeedback(HapticFeedbackConstants.SAFE_MODE_ENABLED, true,
"Safe Mode Enabled");
}
}
@@ -5040,11 +5044,22 @@ public class PhoneWindowManager implements WindowManagerPolicy {
final int lidState = mDefaultDisplayPolicy.getLidState();
if (mLidControlsDisplayFold && mDisplayFoldController != null) {
mDisplayFoldController.requestDeviceFolded(lidState == LID_CLOSED);
- } else if (lidState == LID_CLOSED && mLidControlsSleep) {
- goToSleep(SystemClock.uptimeMillis(), PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
- PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
- } else if (lidState == LID_CLOSED && mLidControlsScreenLock) {
- mWindowManagerFuncs.lockDeviceNow();
+ } else if (lidState == LID_CLOSED) {
+ int lidBehavior = getLidBehavior();
+ switch (lidBehavior) {
+ case LID_BEHAVIOR_LOCK:
+ mWindowManagerFuncs.lockDeviceNow();
+ break;
+ case LID_BEHAVIOR_SLEEP:
+ goToSleep(SystemClock.uptimeMillis(),
+ PowerManager.GO_TO_SLEEP_REASON_LID_SWITCH,
+ PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
+ break;
+ case LID_BEHAVIOR_NONE:
+ // fall through
+ default:
+ break;
+ }
}
synchronized (mLock) {
@@ -5236,9 +5251,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Settings.Global.THEATER_MODE_ON, 0) == 1;
}
+ private boolean performHapticFeedback(int effectId, boolean always, String reason) {
+ return performHapticFeedback(Process.myUid(), mContext.getOpPackageName(),
+ effectId, always, reason);
+ }
+
@Override
- public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always,
- String reason) {
+ public boolean performHapticFeedback(int uid, String packageName, int effectId,
+ boolean always, String reason) {
if (!mVibrator.hasVibrator()) {
return false;
}
@@ -5253,16 +5273,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return false;
}
- int owningUid;
- String owningPackage;
- if (win != null) {
- owningUid = win.getOwningUid();
- owningPackage = win.getOwningPackage();
- } else {
- owningUid = android.os.Process.myUid();
- owningPackage = mContext.getOpPackageName();
- }
- mVibrator.vibrate(owningUid, owningPackage, effect, reason, VIBRATION_ATTRIBUTES);
+ mVibrator.vibrate(uid, packageName, effect, reason, VIBRATION_ATTRIBUTES);
return true;
}
@@ -5404,8 +5415,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
pw.print(prefix); pw.print("mLidKeyboardAccessibility=");
pw.print(mLidKeyboardAccessibility);
pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
- pw.print(" mLidControlsScreenLock="); pw.println(mLidControlsScreenLock);
- pw.print(prefix); pw.print("mLidControlsSleep="); pw.println(mLidControlsSleep);
+ pw.print(" getLidBehavior="); pw.println(lidBehaviorToString(getLidBehavior()));
pw.print(prefix);
pw.print("mLongPressOnBackBehavior=");
pw.println(longPressOnBackBehaviorToString(mLongPressOnBackBehavior));
@@ -5639,6 +5649,19 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
+ private static String lidBehaviorToString(int behavior) {
+ switch (behavior) {
+ case LID_BEHAVIOR_LOCK:
+ return "LID_BEHAVIOR_LOCK";
+ case LID_BEHAVIOR_SLEEP:
+ return "LID_BEHAVIOR_SLEEP";
+ case LID_BEHAVIOR_NONE:
+ return "LID_BEHAVIOR_NONE";
+ default:
+ return Integer.toString(behavior);
+ }
+ }
+
@Override
public boolean setAodShowing(boolean aodShowing) {
if (mAodShowing != aodShowing) {
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index d7e4b6cff4d8..5cd00145821e 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -518,6 +518,10 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
public static final int LID_CLOSED = 0;
public static final int LID_OPEN = 1;
+ public static final int LID_BEHAVIOR_NONE = 0;
+ public static final int LID_BEHAVIOR_SLEEP = 1;
+ public static final int LID_BEHAVIOR_LOCK = 2;
+
public static final int CAMERA_LENS_COVER_ABSENT = -1;
public static final int CAMERA_LENS_UNCOVERED = 0;
public static final int CAMERA_LENS_COVERED = 1;
@@ -1300,8 +1304,8 @@ public interface WindowManagerPolicy extends WindowManagerPolicyConstants {
/**
* Call from application to perform haptic feedback on its window.
*/
- public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always,
- String reason);
+ public boolean performHapticFeedback(int uid, String packageName, int effectId,
+ boolean always, String reason);
/**
* Called when we have started keeping the screen on because a window
diff --git a/services/core/java/com/android/server/role/TEST_MAPPING b/services/core/java/com/android/server/role/TEST_MAPPING
index 0b967be5169f..0d7bc1476bd1 100644
--- a/services/core/java/com/android/server/role/TEST_MAPPING
+++ b/services/core/java/com/android/server/role/TEST_MAPPING
@@ -7,11 +7,14 @@
"include-filter": "android.cts.statsd.atom.UidAtomTests#testRoleHolder"
}
]
- }
- ],
- "postsubmit": [
+ },
{
- "name": "CtsRoleTestCases"
+ "name": "CtsRoleTestCases",
+ "options": [
+ {
+ "exclude-annotation": "androidx.test.filters.FlakyTest"
+ }
+ ]
}
]
}
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index c14f1261cc76..d2c0ee3f5196 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -528,7 +528,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
PackageInstaller.SessionInfo session = installer.getSessionInfo(
data.stagedSessionId);
if (session != null) {
- if (session.isSessionApplied()) {
+ if (session.isStagedSessionApplied()) {
synchronized (mLock) {
data.isAvailable = true;
}
@@ -538,7 +538,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
Log.e(TAG, "Unable to save rollback info for : "
+ data.rollbackId, ioe);
}
- } else if (session.isSessionFailed()) {
+ } else if (session.isStagedSessionFailed()) {
// TODO: Do we need to remove this from
// mAvailableRollbacks, or is it okay to leave as
// unavailable until the next reboot when it will go
@@ -966,36 +966,45 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
}
getHandler().post(() -> {
- final RollbackData rollbackData = getRollbackForPackage(packageName);
- for (int userId : userIds) {
- if (rollbackData == null || !rollbackData.inProgress) {
- Log.e(TAG, "Request to restore userData for: " + packageName
- + ", but no rollback in progress.");
- continue;
- }
- final PackageRollbackInfo info = getPackageRollbackInfo(rollbackData, packageName);
- final boolean changedRollbackData = mAppDataRollbackHelper.restoreAppData(
- rollbackData.rollbackId, info, userId, appId, seInfo);
-
- // We've updated metadata about this rollback, so save it to flash.
- if (changedRollbackData) {
- try {
- mRollbackStore.saveAvailableRollback(rollbackData);
- } catch (IOException ioe) {
- // TODO(narayan): What is the right thing to do here ? This isn't a fatal
- // error, since it will only result in us trying to restore data again,
- // which will be a no-op if there's no data available.
- Log.e(TAG, "Unable to save available rollback: " + packageName, ioe);
- }
- }
- }
-
+ restoreUserDataInternal(packageName, userIds, appId, ceDataInode, seInfo, token);
final PackageManagerInternal pmi = LocalServices.getService(
PackageManagerInternal.class);
pmi.finishPackageInstall(token, false);
});
}
+ private void restoreUserDataInternal(String packageName, int[] userIds, int appId,
+ long ceDataInode, String seInfo, int token) {
+ final RollbackData rollbackData = getRollbackForPackage(packageName);
+ if (rollbackData == null) {
+ return;
+ }
+
+ if (!rollbackData.inProgress) {
+ Log.e(TAG, "Request to restore userData for: " + packageName
+ + ", but no rollback in progress.");
+ return;
+ }
+
+ for (int userId : userIds) {
+ final PackageRollbackInfo info = getPackageRollbackInfo(rollbackData, packageName);
+ final boolean changedRollbackData = mAppDataRollbackHelper.restoreAppData(
+ rollbackData.rollbackId, info, userId, appId, seInfo);
+
+ // We've updated metadata about this rollback, so save it to flash.
+ if (changedRollbackData) {
+ try {
+ mRollbackStore.saveAvailableRollback(rollbackData);
+ } catch (IOException ioe) {
+ // TODO(narayan): What is the right thing to do here ? This isn't a fatal
+ // error, since it will only result in us trying to restore data again,
+ // which will be a no-op if there's no data available.
+ Log.e(TAG, "Unable to save available rollback: " + packageName, ioe);
+ }
+ }
+ }
+ }
+
@Override
public boolean notifyStagedSession(int sessionId) {
final LinkedBlockingQueue<Boolean> result = new LinkedBlockingQueue<>();
@@ -1186,13 +1195,13 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
}
if (pi.isStaged()) {
- if (!pi.isSessionFailed()) {
+ if (!pi.isStagedSessionFailed()) {
// TODO: The session really isn't "enabled" at this point, since more work might
// be required post reboot.
// TODO: We need to make this case consistent with the call from onFinished.
// Ideally, we'd call completeEnableRollback excatly once per multi-package session
// with the parentSessionId only.
- completeEnableRollback(pi.sessionId, pi.isSessionReady());
+ completeEnableRollback(pi.sessionId, pi.isStagedSessionReady());
} else {
// TODO: Clean up the saved rollback when the session fails. This may need to be
// unified with the case where things fail post reboot.
diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index 3a2b69f8a6e1..d24f21781b39 100644
--- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -218,10 +218,10 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
&& (sessionId != PackageInstaller.SessionInfo.INVALID_ID)) {
PackageInstaller.SessionInfo sessionInfo =
packageInstaller.getSessionInfo(sessionId);
- if (sessionInfo.isSessionReady()) {
+ if (sessionInfo.isStagedSessionReady()) {
mContext.unregisterReceiver(listener);
mContext.getSystemService(PowerManager.class).reboot("Rollback staged install");
- } else if (sessionInfo.isSessionFailed()) {
+ } else if (sessionInfo.isStagedSessionFailed()) {
mContext.unregisterReceiver(listener);
}
}
diff --git a/services/core/java/com/android/server/timezone/RulesManagerService.java b/services/core/java/com/android/server/timezone/RulesManagerService.java
index 4b413e5f76bb..296a6526f5a6 100644
--- a/services/core/java/com/android/server/timezone/RulesManagerService.java
+++ b/services/core/java/com/android/server/timezone/RulesManagerService.java
@@ -16,14 +16,13 @@
package com.android.server.timezone;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.EventLogTags;
-import com.android.server.SystemService;
-import com.android.timezone.distro.DistroException;
-import com.android.timezone.distro.DistroVersion;
-import com.android.timezone.distro.StagedDistroOperation;
-import com.android.timezone.distro.TimeZoneDistro;
-import com.android.timezone.distro.installer.TimeZoneDistroInstaller;
+import static android.app.timezone.RulesState.DISTRO_STATUS_INSTALLED;
+import static android.app.timezone.RulesState.DISTRO_STATUS_NONE;
+import static android.app.timezone.RulesState.DISTRO_STATUS_UNKNOWN;
+import static android.app.timezone.RulesState.STAGED_OPERATION_INSTALL;
+import static android.app.timezone.RulesState.STAGED_OPERATION_NONE;
+import static android.app.timezone.RulesState.STAGED_OPERATION_UNINSTALL;
+import static android.app.timezone.RulesState.STAGED_OPERATION_UNKNOWN;
import android.app.timezone.Callback;
import android.app.timezone.DistroFormatVersion;
@@ -37,6 +36,21 @@ import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.Slog;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.EventLogTags;
+import com.android.server.SystemService;
+import com.android.timezone.distro.DistroException;
+import com.android.timezone.distro.DistroVersion;
+import com.android.timezone.distro.StagedDistroOperation;
+import com.android.timezone.distro.TimeZoneDistro;
+import com.android.timezone.distro.installer.TimeZoneDistroInstaller;
+
+import libcore.icu.ICU;
+import libcore.timezone.TimeZoneDataFiles;
+import libcore.timezone.TimeZoneFinder;
+import libcore.timezone.TzDataSetVersion;
+import libcore.timezone.ZoneInfoDB;
+
import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
@@ -46,18 +60,6 @@ import java.io.PrintWriter;
import java.util.Arrays;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
-import libcore.icu.ICU;
-import libcore.timezone.TzDataSetVersion;
-import libcore.timezone.TimeZoneFinder;
-import libcore.timezone.ZoneInfoDB;
-
-import static android.app.timezone.RulesState.DISTRO_STATUS_INSTALLED;
-import static android.app.timezone.RulesState.DISTRO_STATUS_NONE;
-import static android.app.timezone.RulesState.DISTRO_STATUS_UNKNOWN;
-import static android.app.timezone.RulesState.STAGED_OPERATION_INSTALL;
-import static android.app.timezone.RulesState.STAGED_OPERATION_NONE;
-import static android.app.timezone.RulesState.STAGED_OPERATION_UNINSTALL;
-import static android.app.timezone.RulesState.STAGED_OPERATION_UNKNOWN;
public final class RulesManagerService extends IRulesManager.Stub {
@@ -96,8 +98,6 @@ public final class RulesManagerService extends IRulesManager.Stub {
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
static final String REQUIRED_QUERY_PERMISSION =
android.Manifest.permission.QUERY_TIME_ZONE_RULES;
- private static final File SYSTEM_TZ_DATA_FILE = new File("/system/usr/share/zoneinfo/tzdata");
- private static final File TZ_DATA_DIR = new File("/data/misc/zoneinfo");
private final AtomicBoolean mOperationInProgress = new AtomicBoolean(false);
private final PermissionHelper mPermissionHelper;
@@ -108,12 +108,14 @@ public final class RulesManagerService extends IRulesManager.Stub {
private static RulesManagerService create(Context context) {
RulesManagerServiceHelperImpl helper = new RulesManagerServiceHelperImpl(context);
+ File baseVersionFile = new File(TimeZoneDataFiles.getRuntimeModuleTzVersionFile());
+ File tzDataDir = new File(TimeZoneDataFiles.getDataTimeZoneRootDir());
return new RulesManagerService(
helper /* permissionHelper */,
helper /* executor */,
helper /* intentHelper */,
PackageTracker.create(context),
- new TimeZoneDistroInstaller(TAG, SYSTEM_TZ_DATA_FILE, TZ_DATA_DIR));
+ new TimeZoneDistroInstaller(TAG, baseVersionFile, tzDataDir));
}
// A constructor that can be used by tests to supply mocked / faked dependencies.
@@ -143,11 +145,11 @@ public final class RulesManagerService extends IRulesManager.Stub {
/** Like {@link #getRulesState()} without the permission check. */
private RulesState getRulesStateInternal() {
synchronized(this) {
- String systemRulesVersion;
+ TzDataSetVersion baseVersion;
try {
- systemRulesVersion = mInstaller.getSystemRulesVersion();
+ baseVersion = mInstaller.readBaseVersion();
} catch (IOException e) {
- Slog.w(TAG, "Failed to read system rules", e);
+ Slog.w(TAG, "Failed to read base rules version", e);
return null;
}
@@ -196,7 +198,7 @@ public final class RulesManagerService extends IRulesManager.Stub {
Slog.w(TAG, "Failed to read staged distro.", e);
}
}
- return new RulesState(systemRulesVersion, DISTRO_FORMAT_VERSION_SUPPORTED,
+ return new RulesState(baseVersion.rulesVersion, DISTRO_FORMAT_VERSION_SUPPORTED,
operationInProgress, stagedOperationStatus, stagedDistroRulesVersion,
distroStatus, installedDistroRulesVersion);
}
@@ -454,13 +456,13 @@ public final class RulesManagerService extends IRulesManager.Stub {
pw.println("Operation in progress: " + value);
break;
}
- case 's': {
- // Report system image rules version
+ case 'b': {
+ // Report base rules version
String value = "Unknown";
if (rulesState != null) {
- value = rulesState.getSystemRulesVersion();
+ value = rulesState.getBaseRulesVersion();
}
- pw.println("System rules version: " + value);
+ pw.println("Base rules version: " + value);
break;
}
case 'c': {
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 9ea819ea8e16..9f04166ea4c0 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -46,6 +46,7 @@ import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT;
import static android.content.Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED;
import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
+import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
import static android.content.pm.ActivityInfo.DOCUMENT_LAUNCH_ALWAYS;
import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
@@ -1457,6 +1458,14 @@ class ActivityStarter {
// This task was started because of movement of the activity based on affinity...
// Now that we are actually launching it, we can assign the base intent.
reusedActivity.getTaskRecord().setIntent(mStartActivity);
+ } else {
+ final boolean taskOnHome =
+ (mStartActivity.intent.getFlags() & FLAG_ACTIVITY_TASK_ON_HOME) != 0;
+ if (taskOnHome) {
+ reusedActivity.getTaskRecord().intent.addFlags(FLAG_ACTIVITY_TASK_ON_HOME);
+ } else {
+ reusedActivity.getTaskRecord().intent.removeFlags(FLAG_ACTIVITY_TASK_ON_HOME);
+ }
}
// This code path leads to delivering a new intent, we want to make sure we schedule it
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 91d573defc16..f3f507f156be 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -3271,7 +3271,12 @@ public class DisplayPolicy {
}
final WindowState w = mTopFullscreenOpaqueWindowState;
- if (w != mFocusedWindow) {
+ if (w == null || w != mFocusedWindow) {
+ return false;
+ }
+ // If the bounds of activity window is different from its parent, then reject to be seamless
+ // because the window position may change after rotation that will look like a sudden jump.
+ if (w.mAppToken != null && !w.mAppToken.matchParentBounds()) {
return false;
}
@@ -3279,8 +3284,7 @@ public class DisplayPolicy {
// it and is in the fullscreen opaque state. Seamless rotation
// requires freezing various Surface states and won't work well
// with animations, so we disable it in the animation case for now.
- if (w != null && !w.isAnimatingLw()
- && w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS) {
+ if (!w.isAnimatingLw() && w.getAttrs().rotationAnimation == ROTATION_ANIMATION_SEAMLESS) {
return true;
}
return false;
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 543f19655350..34a480291863 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -21,6 +21,7 @@ import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import android.annotation.IntDef;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.content.ContentResolver;
@@ -49,6 +50,8 @@ import com.android.server.policy.WindowOrientationListener;
import com.android.server.statusbar.StatusBarManagerInternal;
import java.io.PrintWriter;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
/**
* Defines the mapping between orientation and rotation of a display.
@@ -96,11 +99,36 @@ public class DisplayRotation {
private int mUserRotation = Surface.ROTATION_0;
/**
+ * Flag that indicates this is a display that may run better when fixed to user rotation.
+ */
+ private boolean mDefaultFixedToUserRotation;
+
+ /**
+ * No overridden behavior is provided in terms of fixing rotation to user rotation. Use other
+ * flags to derive the default behavior, such as {@link WindowManagerService#mIsPc} and
+ * {@link WindowManagerService#mForceDesktopModeOnExternalDisplays}.
+ */
+ static final int FIXED_TO_USER_ROTATION_DEFAULT = 0;
+ /**
+ * Don't fix display rotation to {@link #mUserRotation} only. Always allow other factors to play
+ * a role in deciding display rotation.
+ */
+ static final int FIXED_TO_USER_ROTATION_DISABLED = 1;
+ /**
+ * Only use {@link #mUserRotation} as the display rotation.
+ */
+ static final int FIXED_TO_USER_ROTATION_ENABLED = 2;
+ @IntDef({ FIXED_TO_USER_ROTATION_DEFAULT, FIXED_TO_USER_ROTATION_DISABLED,
+ FIXED_TO_USER_ROTATION_ENABLED })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface FixedToUserRotation {}
+
+ /**
* A flag to indicate if the display rotation should be fixed to user specified rotation
* regardless of all other states (including app requrested orientation). {@code true} the
* display rotation should be fixed to user specified rotation, {@code false} otherwise.
*/
- private boolean mFixedToUserRotation;
+ private int mFixedToUserRotation = FIXED_TO_USER_ROTATION_DEFAULT;
private int mDemoHdmiRotation;
private int mDemoRotation;
@@ -208,31 +236,23 @@ public class DisplayRotation {
}
mDemoRotationLock = SystemProperties.getBoolean("persist.demo.rotationlock", false);
- // Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
- // http://developer.android.com/guide/practices/screens_support.html#range
- // For car, ignore the dp limitation. It's physically impossible to rotate the car's screen
- // so if the orientation is forced, we need to respect that no matter what.
+ // It's physically impossible to rotate the car's screen.
final boolean isCar = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_AUTOMOTIVE);
- // For TV, it's usually 960dp x 540dp, ignore the size limitation.
- // so if the orientation is forced, we need to respect that no matter what.
+ // It's also not likely to rotate a TV screen.
final boolean isTv = mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_LEANBACK);
+ // Not much of use to rotate the display since it's close to square.
final boolean isCloseToSquare =
isNonDecorDisplayCloseToSquare(Surface.ROTATION_0, width, height);
- final boolean forceDefaultOrientationInRes =
- res.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation);
- final boolean forceDefaultOrienation =
- ((longSizeDp >= 960 && shortSizeDp >= 720) || isCar || isTv || isCloseToSquare)
- && forceDefaultOrientationInRes
- // For debug purposes the next line turns this feature off with:
- // $ adb shell setprop config.override_forced_orient true
- // $ adb shell wm size reset
- && !"true".equals(SystemProperties.get("config.override_forced_orient"));
- // Configuration says we force to use the default orientation. We can fall back to fix
- // rotation to only user rotation. As long as OEM doesn't change user rotation then the
- // rotation of this display is effectively stuck at 0 deg.
- setFixedToUserRotation(forceDefaultOrienation);
+ final boolean forceDesktopMode =
+ mService.mForceDesktopModeOnExternalDisplays && !isDefaultDisplay;
+ mDefaultFixedToUserRotation =
+ (isCar || isTv || mService.mIsPc || forceDesktopMode || isCloseToSquare)
+ // For debug purposes the next line turns this feature off with:
+ // $ adb shell setprop config.override_forced_orient true
+ // $ adb shell wm size reset
+ && !"true".equals(SystemProperties.get("config.override_forced_orient"));
}
private boolean isNonDecorDisplayCloseToSquare(int rotation, int width, int height) {
@@ -263,7 +283,7 @@ public class DisplayRotation {
}
void restoreSettings(int userRotationMode, int userRotation,
- boolean fixedToUserRotation) {
+ @FixedToUserRotation int fixedToUserRotation) {
mFixedToUserRotation = fixedToUserRotation;
// We will retrieve user rotation and user rotation mode from settings for default display.
@@ -285,14 +305,13 @@ public class DisplayRotation {
mUserRotation = userRotation;
}
- void setFixedToUserRotation(boolean fixedToUserRotation) {
+ void setFixedToUserRotation(@FixedToUserRotation int fixedToUserRotation) {
if (mFixedToUserRotation == fixedToUserRotation) {
return;
}
mFixedToUserRotation = fixedToUserRotation;
- mDisplayWindowSettings.setFixedToUserRotation(mDisplayContent,
- fixedToUserRotation);
+ mDisplayWindowSettings.setFixedToUserRotation(mDisplayContent, fixedToUserRotation);
mService.updateRotation(true /* alwaysSendConfiguration */,
false /* forceRelayout */);
}
@@ -346,7 +365,14 @@ public class DisplayRotation {
}
boolean isFixedToUserRotation() {
- return mFixedToUserRotation;
+ switch (mFixedToUserRotation) {
+ case FIXED_TO_USER_ROTATION_DISABLED:
+ return false;
+ case FIXED_TO_USER_ROTATION_ENABLED:
+ return true;
+ default:
+ return mDefaultFixedToUserRotation;
+ }
}
/**
@@ -355,7 +381,7 @@ public class DisplayRotation {
* false} is when {@link #isFixedToUserRotation()} is {@code true}.
*/
boolean respectAppRequestedOrientation() {
- return !mFixedToUserRotation;
+ return !isFixedToUserRotation();
}
public int getLandscapeRotation() {
@@ -461,7 +487,7 @@ public class DisplayRotation {
* screen is switched off.
*/
private boolean needSensorRunning() {
- if (mFixedToUserRotation) {
+ if (isFixedToUserRotation()) {
// We are sure we only respect user rotation settings, so we are sure we will not
// support sensor rotation.
return false;
@@ -527,7 +553,7 @@ public class DisplayRotation {
);
}
- if (mFixedToUserRotation) {
+ if (isFixedToUserRotation()) {
return mUserRotation;
}
@@ -739,7 +765,7 @@ public class DisplayRotation {
// demo, hdmi, vr, etc mode.
// Determine if the rotation is currently forced.
- if (mFixedToUserRotation) {
+ if (isFixedToUserRotation()) {
return false; // Rotation is forced to user settings.
}
@@ -899,7 +925,7 @@ public class DisplayRotation {
pw.print(" mDemoHdmiRotationLock=" + mDemoHdmiRotationLock);
pw.println(" mUndockedHdmiRotation=" + Surface.rotationToString(mUndockedHdmiRotation));
pw.println(prefix + " mLidOpenRotation=" + Surface.rotationToString(mLidOpenRotation));
- pw.println(prefix + " mFixedToUserRotation=" + mFixedToUserRotation);
+ pw.println(prefix + " mFixedToUserRotation=" + isFixedToUserRotation());
}
private class OrientationListener extends WindowOrientationListener {
diff --git a/services/core/java/com/android/server/wm/DisplayWindowSettings.java b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
index 5cfa7dec386e..4617890be722 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowSettings.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowSettings.java
@@ -22,6 +22,7 @@ import static android.view.WindowManager.REMOVE_CONTENT_MODE_UNDEFINED;
import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_AUTO;
import static com.android.server.wm.DisplayContent.FORCE_SCALING_MODE_DISABLED;
+import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_DEFAULT;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
@@ -80,7 +81,8 @@ class DisplayWindowSettings {
private boolean mShouldShowWithInsecureKeyguard = false;
private boolean mShouldShowSystemDecors = false;
private boolean mShouldShowIme = false;
- private boolean mFixedToUserRotation;
+ private @DisplayRotation.FixedToUserRotation int mFixedToUserRotation =
+ FIXED_TO_USER_ROTATION_DEFAULT;
private Entry(String name) {
mName = name;
@@ -99,7 +101,7 @@ class DisplayWindowSettings {
&& !mShouldShowWithInsecureKeyguard
&& !mShouldShowSystemDecors
&& !mShouldShowIme
- && !mFixedToUserRotation;
+ && mFixedToUserRotation == FIXED_TO_USER_ROTATION_DEFAULT;
}
}
@@ -188,7 +190,8 @@ class DisplayWindowSettings {
writeSettingsIfNeeded(entry, displayInfo);
}
- void setFixedToUserRotation(DisplayContent displayContent, boolean fixedToUserRotation) {
+ void setFixedToUserRotation(DisplayContent displayContent,
+ @DisplayRotation.FixedToUserRotation int fixedToUserRotation) {
final DisplayInfo displayInfo = displayContent.getDisplayInfo();
final Entry entry = getOrCreateEntry(displayInfo);
entry.mFixedToUserRotation = fixedToUserRotation;
@@ -464,8 +467,7 @@ class DisplayWindowSettings {
"shouldShowWithInsecureKeyguard");
entry.mShouldShowSystemDecors = getBooleanAttribute(parser, "shouldShowSystemDecors");
entry.mShouldShowIme = getBooleanAttribute(parser, "shouldShowIme");
- entry.mFixedToUserRotation = getBooleanAttribute(parser,
- "fixedToUserRotation");
+ entry.mFixedToUserRotation = getIntAttribute(parser, "fixedToUserRotation");
mEntries.put(name, entry);
}
XmlUtils.skipCurrentTag(parser);
@@ -549,9 +551,9 @@ class DisplayWindowSettings {
if (entry.mShouldShowIme) {
out.attribute(null, "shouldShowIme", Boolean.toString(entry.mShouldShowIme));
}
- if (entry.mFixedToUserRotation) {
+ if (entry.mFixedToUserRotation != FIXED_TO_USER_ROTATION_DEFAULT) {
out.attribute(null, "fixedToUserRotation",
- Boolean.toString(entry.mFixedToUserRotation));
+ Integer.toString(entry.mFixedToUserRotation));
}
out.endTag(null, "display");
}
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index 84cd8d1632cf..2d5c97f9a3a5 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -257,7 +257,7 @@ class ScreenRotationAnimation {
mOriginalWidth = originalWidth;
mOriginalHeight = originalHeight;
- final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+ final SurfaceControl.Transaction t = mService.mTransactionFactory.make();
try {
mSurfaceControl = displayContent.makeOverlay()
.setName("ScreenshotSurface")
@@ -267,13 +267,13 @@ class ScreenRotationAnimation {
// In case display bounds change, screenshot buffer and surface may mismatch so set a
// scaling mode.
- SurfaceControl.Transaction t2 = new SurfaceControl.Transaction();
+ SurfaceControl.Transaction t2 = mService.mTransactionFactory.make();
t2.setOverrideScalingMode(mSurfaceControl, Surface.SCALING_MODE_SCALE_TO_WINDOW);
t2.apply(true /* sync */);
// Capture a screenshot into the surface we just created.
final int displayId = display.getDisplayId();
- final Surface surface = new Surface();
+ final Surface surface = mService.mSurfaceFactory.make();
surface.copyFrom(mSurfaceControl);
if (mService.mDisplayManagerInternal.screenshot(displayId, surface)) {
t.setLayer(mSurfaceControl, SCREEN_FREEZE_LAYER_SCREENSHOT);
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 58cf73a9a2bd..dc8c7b79feef 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -245,17 +245,13 @@ class Session extends IWindowSession.Stub implements IBinder.DeathRecipient {
}
@Override
- public boolean performHapticFeedback(IWindow window, int effectId,
- boolean always) {
- synchronized (mService.mGlobalLock) {
- long ident = Binder.clearCallingIdentity();
- try {
- return mService.mPolicy.performHapticFeedbackLw(
- mService.windowForClientLocked(this, window, true),
+ public boolean performHapticFeedback(int effectId, boolean always) {
+ long ident = Binder.clearCallingIdentity();
+ try {
+ return mService.mPolicy.performHapticFeedback(mUid, mPackageName,
effectId, always, null);
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
}
diff --git a/services/core/java/com/android/server/wm/SurfaceFactory.java b/services/core/java/com/android/server/wm/SurfaceFactory.java
new file mode 100644
index 000000000000..076b7df63c46
--- /dev/null
+++ b/services/core/java/com/android/server/wm/SurfaceFactory.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import android.view.Surface;
+
+/**
+ * Helper class to inject custom {@link Surface} objects into window manager.
+ */
+interface SurfaceFactory {
+ Surface make();
+};
+
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index 74fb3fa85f24..dddc6b755db0 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -50,6 +50,7 @@ import android.view.SurfaceControl;
import android.view.WindowManager;
import android.view.animation.Animation;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ToBooleanFunction;
import java.io.PrintWriter;
@@ -700,24 +701,37 @@ class WallpaperController {
mWallpaperTokens.remove(token);
}
- /**
- * Take a screenshot of the wallpaper if it's visible.
- *
- * @return Bitmap of the wallpaper
- */
- Bitmap screenshotWallpaperLocked() {
+
+ @VisibleForTesting
+ boolean canScreenshotWallpaper() {
+ return canScreenshotWallpaper(getTopVisibleWallpaper());
+ }
+
+ private boolean canScreenshotWallpaper(WindowState wallpaperWindowState) {
if (!mService.mPolicy.isScreenOn()) {
if (DEBUG_SCREENSHOT) {
Slog.i(TAG_WM, "Attempted to take screenshot while display was off.");
}
- return null;
+ return false;
}
- final WindowState wallpaperWindowState = getTopVisibleWallpaper();
if (wallpaperWindowState == null) {
if (DEBUG_SCREENSHOT) {
Slog.i(TAG_WM, "No visible wallpaper to screenshot");
}
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Take a screenshot of the wallpaper if it's visible.
+ *
+ * @return Bitmap of the wallpaper
+ */
+ Bitmap screenshotWallpaperLocked() {
+ final WindowState wallpaperWindowState = getTopVisibleWallpaper();
+ if (!canScreenshotWallpaper(wallpaperWindowState)) {
return null;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 39df0e42e27c..e19c7c66815c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -209,6 +209,7 @@ import android.view.IWindowSession;
import android.view.IWindowSessionCallback;
import android.view.InputChannel;
import android.view.InputDevice;
+import android.view.InputEvent;
import android.view.InputEventReceiver;
import android.view.InsetsState;
import android.view.KeyEvent;
@@ -814,8 +815,9 @@ public class WindowManagerService extends IWindowManager.Stub
SurfaceBuilderFactory mSurfaceBuilderFactory = SurfaceControl.Builder::new;
TransactionFactory mTransactionFactory = SurfaceControl.Transaction::new;
+ SurfaceFactory mSurfaceFactory = Surface::new;
- private final SurfaceControl.Transaction mTransaction = mTransactionFactory.make();
+ private final SurfaceControl.Transaction mTransaction;
static void boostPriorityForLockedSection() {
sThreadPriorityBooster.boost();
@@ -909,9 +911,21 @@ public class WindowManagerService extends IWindowManager.Stub
public static WindowManagerService main(final Context context, final InputManagerService im,
final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
ActivityTaskManagerService atm) {
+ return main(context, im, showBootMsgs, onlyCore, policy, atm,
+ SurfaceControl.Transaction::new);
+ }
+
+ /**
+ * Creates and returns an instance of the WindowManagerService. This call allows the caller
+ * to override the {@link TransactionFactory} to stub functionality under test.
+ */
+ @VisibleForTesting
+ public static WindowManagerService main(final Context context, final InputManagerService im,
+ final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
+ ActivityTaskManagerService atm, TransactionFactory transactionFactory) {
DisplayThread.getHandler().runWithScissors(() ->
sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
- atm), 0);
+ atm, transactionFactory), 0);
return sInstance;
}
@@ -933,7 +947,7 @@ public class WindowManagerService extends IWindowManager.Stub
private WindowManagerService(Context context, InputManagerService inputManager,
boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
- ActivityTaskManagerService atm) {
+ ActivityTaskManagerService atm, TransactionFactory transactionFactory) {
installLock(this, INDEX_WINDOW);
mGlobalLock = atm.getGlobalLock();
mAtmService = atm;
@@ -962,6 +976,9 @@ public class WindowManagerService extends IWindowManager.Stub
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
mDisplayWindowSettings = new DisplayWindowSettings(this);
+
+ mTransactionFactory = transactionFactory;
+ mTransaction = mTransactionFactory.make();
mPolicy = policy;
mAnimator = new WindowAnimator(this);
mRoot = new RootWindowContainer(this);
@@ -3503,14 +3520,15 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- void setRotateForApp(int displayId, boolean enabled) {
+ void setRotateForApp(int displayId,
+ @DisplayRotation.FixedToUserRotation int fixedToUserRotation) {
synchronized (mGlobalLock) {
final DisplayContent display = mRoot.getDisplayContent(displayId);
if (display == null) {
Slog.w(TAG, "Trying to set rotate for app for a missing display.");
return;
}
- display.getDisplayRotation().setFixedToUserRotation(enabled);
+ display.getDisplayRotation().setFixedToUserRotation(fixedToUserRotation);
}
}
@@ -7403,4 +7421,16 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
}
+
+ @Override
+ public boolean injectInputAfterTransactionsApplied(InputEvent ev, int mode) {
+ synchronized (mGlobalLock) {
+ mWindowPlacerLocked.performSurfacePlacementIfScheduled();
+ new SurfaceControl.Transaction()
+ .syncInputWindows()
+ .apply(true);
+ }
+
+ return mInputManager.injectInputEvent(ev, mode);
+ }
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
index d13ee459c115..7384bb7e1587 100644
--- a/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
+++ b/services/core/java/com/android/server/wm/WindowManagerShellCommand.java
@@ -342,21 +342,24 @@ public class WindowManagerShellCommand extends ShellCommand {
arg = getNextArgRequired();
}
- final boolean enabled;
+ final @DisplayRotation.FixedToUserRotation int fixedToUserRotation;
switch (arg) {
case "enabled":
- enabled = true;
+ fixedToUserRotation = DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED;
break;
case "disabled":
- enabled = false;
+ fixedToUserRotation = DisplayRotation.FIXED_TO_USER_ROTATION_DISABLED;
+ break;
+ case "default":
+ fixedToUserRotation = DisplayRotation.FIXED_TO_USER_ROTATION_DISABLED;
break;
default:
- getErrPrintWriter().println("Error: expecting enabled or disabled, but we get "
- + arg);
+ getErrPrintWriter().println("Error: expecting enabled, disabled or default, but we "
+ + "get " + arg);
return -1;
}
- mInternal.setRotateForApp(displayId, enabled);
+ mInternal.setRotateForApp(displayId, fixedToUserRotation);
return 0;
}
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 2ee58fe3f574..cc7917879634 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -85,6 +85,12 @@ class WindowSurfacePlacer {
return mDeferDepth > 0;
}
+ void performSurfacePlacementIfScheduled() {
+ if (mTraversalScheduled) {
+ performSurfacePlacement();
+ }
+ }
+
final void performSurfacePlacement() {
performSurfacePlacement(false /* force */);
}
diff --git a/services/core/java/com/android/server/wm/WindowTraceBuffer.java b/services/core/java/com/android/server/wm/WindowTraceBuffer.java
index 2ce6e6c1d049..a4ee9077c150 100644
--- a/services/core/java/com/android/server/wm/WindowTraceBuffer.java
+++ b/services/core/java/com/android/server/wm/WindowTraceBuffer.java
@@ -98,9 +98,8 @@ class WindowTraceBuffer {
ProtoOutputStream proto = new ProtoOutputStream();
proto.write(MAGIC_NUMBER, MAGIC_NUMBER_VALUE);
os.write(proto.getBytes());
- while (!mBuffer.isEmpty()) {
- proto = mBuffer.poll();
- mBufferUsedSize -= proto.getRawSize();
+ for (ProtoOutputStream protoOutputStream : mBuffer) {
+ proto = protoOutputStream;
byte[] protoBytes = proto.getBytes();
os.write(protoBytes);
}
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index d178c3abc906..fe941681a7be 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -2248,7 +2248,7 @@ static jboolean android_location_GnssMeasurementsProvider_inject_gnss_measuremen
measCorrClass, "getToaGpsNanosecondsOfWeek", "()J");
method_correctionsGetSingleSatCorrectionList = env->GetMethodID(
- measCorrClass, "getSingleSatCorrectionList", "()Ljava.util.List;");
+ measCorrClass, "getSingleSatelliteCorrectionList", "()Ljava.util.List;");
}
jdouble latitudeDegreesCorr = env->CallDoubleMethod(
@@ -2285,15 +2285,15 @@ static jboolean android_location_GnssMeasurementsProvider_inject_gnss_measuremen
if (firstGnssMeasurementCorrectionInjected == false) {
jclass singleSatCorrClass = env->GetObjectClass(singleSatCorrectionObj);
method_correctionSatFlags = env->GetMethodID(
- singleSatCorrClass, "getSingleSatCorrectionFlags", "()I");
+ singleSatCorrClass, "getSingleSatelliteCorrectionFlags", "()I");
method_correctionSatConstType = env->GetMethodID(
singleSatCorrClass, "getConstellationType", "()I");
method_correctionSatId= env->GetMethodID(
- singleSatCorrClass, "getSatId", "()I");
+ singleSatCorrClass, "getSatelliteId", "()I");
method_correctionSatCarrierFreq = env->GetMethodID(
singleSatCorrClass, "getCarrierFrequencyHz", "()F");
method_correctionSatIsLosProb = env->GetMethodID(
- singleSatCorrClass,"getProbSatIsLos", "()F");
+ singleSatCorrClass,"getProbabilityLineOfSight", "()F");
method_correctionSatEpl = env->GetMethodID(
singleSatCorrClass, "getExcessPathLengthMeters", "()F");
method_correctionSatEplUnc = env->GetMethodID(
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index ae48dad7b8f9..3070488cb713 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -134,6 +134,7 @@ import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.PermissionChecker;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageDataObserver;
@@ -171,6 +172,7 @@ import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.ParcelFileDescriptor;
+import android.os.ParcelableException;
import android.os.PersistableBundle;
import android.os.PowerManager;
import android.os.PowerManagerInternal;
@@ -187,6 +189,7 @@ import android.os.UserManager;
import android.os.UserManagerInternal;
import android.os.UserManagerInternal.UserRestrictionsListener;
import android.os.storage.StorageManager;
+import android.permission.PermissionControllerManager;
import android.provider.CalendarContract;
import android.provider.ContactsContract.QuickContact;
import android.provider.ContactsInternal;
@@ -1890,6 +1893,21 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return LocalServices.getService(ActivityTaskManagerInternal.class);
}
+ @NonNull PermissionControllerManager getPermissionControllerManager(
+ @NonNull UserHandle user) {
+ if (user.equals(mContext.getUser())) {
+ return mContext.getSystemService(PermissionControllerManager.class);
+ } else {
+ try {
+ return mContext.createPackageContextAsUser(mContext.getPackageName(), 0,
+ user).getSystemService(PermissionControllerManager.class);
+ } catch (NameNotFoundException notPossible) {
+ // not possible
+ throw new IllegalStateException(notPossible);
+ }
+ }
+ }
+
UsageStatsManagerInternal getUsageStatsManagerInternal() {
return LocalServices.getService(UsageStatsManagerInternal.class);
}
@@ -11582,8 +11600,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
@Override
- public boolean setPermissionGrantState(ComponentName admin, String callerPackage,
- String packageName, String permission, int grantState) throws RemoteException {
+ public void setPermissionGrantState(ComponentName admin, String callerPackage,
+ String packageName, String permission, int grantState, RemoteCallback callback)
+ throws RemoteException {
+ Preconditions.checkNotNull(callback);
+
UserHandle user = mInjector.binderGetCallingUserHandle();
synchronized (getLockObject()) {
// Ensure the caller is a DO/PO or a permission grant state delegate.
@@ -11591,53 +11612,60 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
DELEGATION_PERMISSION_GRANT);
long ident = mInjector.binderClearCallingIdentity();
try {
- if (getTargetSdk(packageName, user.getIdentifier())
- < android.os.Build.VERSION_CODES.M) {
- return false;
+ boolean isPostQAdmin = getTargetSdk(callerPackage, user.getIdentifier())
+ >= android.os.Build.VERSION_CODES.Q;
+ if (!isPostQAdmin) {
+ // Legacy admins assume that they cannot control pre-M apps
+ if (getTargetSdk(packageName, user.getIdentifier())
+ < android.os.Build.VERSION_CODES.M) {
+ callback.sendResult(null);
+ return;
+ }
}
- if (!isRuntimePermission(permission)) {
- return false;
+ try {
+ if (!isRuntimePermission(permission)) {
+ callback.sendResult(null);
+ return;
+ }
+ } catch (NameNotFoundException e) {
+ throw new RemoteException(
+ "Cannot check if " + permission + "is a runtime permission", e, false,
+ true);
+ }
+
+ if (grantState == DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED
+ || grantState == DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED
+ || grantState == DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT) {
+ mInjector.getPermissionControllerManager(user)
+ .setRuntimePermissionGrantStateByDeviceAdmin(callerPackage,
+ packageName, permission, grantState, mContext.getMainExecutor(),
+ (permissionWasSet) -> {
+ if (isPostQAdmin && !permissionWasSet) {
+ callback.sendResult(null);
+ return;
+ }
+
+ final boolean isDelegate = (admin == null);
+ DevicePolicyEventLogger
+ .createEvent(DevicePolicyEnums
+ .SET_PERMISSION_GRANT_STATE)
+ .setAdmin(callerPackage)
+ .setStrings(permission)
+ .setInt(grantState)
+ .setBoolean(isDelegate)
+ .write();
+
+ callback.sendResult(Bundle.EMPTY);
+ });
}
- final PackageManager packageManager = mInjector.getPackageManager();
- switch (grantState) {
- case DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED: {
- mInjector.getPackageManagerInternal().grantRuntimePermission(packageName,
- permission, user.getIdentifier(), true /* override policy */);
- packageManager.updatePermissionFlags(permission, packageName,
- PackageManager.FLAG_PERMISSION_POLICY_FIXED,
- PackageManager.FLAG_PERMISSION_POLICY_FIXED, user);
- } break;
-
- case DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED: {
- mInjector.getPackageManagerInternal().revokeRuntimePermission(packageName,
- permission, user.getIdentifier(), true /* override policy */);
- packageManager.updatePermissionFlags(permission, packageName,
- PackageManager.FLAG_PERMISSION_POLICY_FIXED,
- PackageManager.FLAG_PERMISSION_POLICY_FIXED, user);
- } break;
-
- case DevicePolicyManager.PERMISSION_GRANT_STATE_DEFAULT: {
- packageManager.updatePermissionFlags(permission, packageName,
- PackageManager.FLAG_PERMISSION_POLICY_FIXED, 0, user);
- } break;
- }
- } catch (SecurityException se) {
- return false;
- } catch (NameNotFoundException e) {
- return false;
+ } catch (SecurityException e) {
+ Slog.e(LOG_TAG, "Could not set permission grant state", e);
+
+ callback.sendResult(null);
} finally {
mInjector.binderRestoreCallingIdentity(ident);
}
}
- final boolean isDelegate = (admin == null);
- DevicePolicyEventLogger
- .createEvent(DevicePolicyEnums.SET_PERMISSION_GRANT_STATE)
- .setAdmin(callerPackage)
- .setStrings(permission)
- .setInt(grantState)
- .setBoolean(isDelegate)
- .write();
- return true;
}
@Override
@@ -11654,8 +11682,26 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
synchronized (getLockObject()) {
long ident = mInjector.binderClearCallingIdentity();
try {
- int granted = mIPackageManager.checkPermission(permission,
- packageName, user.getIdentifier());
+ int granted;
+ if (getTargetSdk(callerPackage, user.getIdentifier())
+ < android.os.Build.VERSION_CODES.Q) {
+ // The per-Q behavior was to not check the app-ops state.
+ granted = mIPackageManager.checkPermission(permission, packageName,
+ user.getIdentifier());
+ } else {
+ try {
+ int uid = packageManager.getPackageUidAsUser(packageName,
+ user.getIdentifier());
+
+ // TODO: Prevent noting the app-op
+ granted = PermissionChecker.checkPermission(mContext, permission, -1,
+ uid, packageName);
+ } catch (NameNotFoundException e) {
+ throw new RemoteException(
+ "Cannot check if " + permission + "is a runtime permission", e,
+ false, true);
+ }
+ }
int permFlags = packageManager.getPermissionFlags(permission, packageName, user);
if ((permFlags & PackageManager.FLAG_PERMISSION_POLICY_FIXED)
!= PackageManager.FLAG_PERMISSION_POLICY_FIXED) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 4700b9677a19..8d88c5a004a9 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -310,6 +310,7 @@ public final class SystemServer {
private boolean mOnlyCore;
private boolean mFirstBoot;
+ private final int mStartCount;
private final boolean mRuntimeRestart;
private final long mRuntimeStartElapsedTime;
private final long mRuntimeStartUptime;
@@ -317,6 +318,9 @@ public final class SystemServer {
private static final String START_SENSOR_SERVICE = "StartSensorService";
private static final String START_HIDL_SERVICES = "StartHidlServices";
+ private static final String SYSPROP_START_COUNT = "sys.system_server.start_count";
+ private static final String SYSPROP_START_ELAPSED = "sys.system_server.start_elapsed";
+ private static final String SYSPROP_START_UPTIME = "sys.system_server.start_uptime";
private Future<?> mSensorServiceStart;
private Future<?> mZygotePreload;
@@ -346,16 +350,33 @@ public final class SystemServer {
public SystemServer() {
// Check for factory test mode.
mFactoryTestMode = FactoryTest.getMode();
- // Remember if it's runtime restart(when sys.boot_completed is already set) or reboot
- mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed"));
+ // Record process start information.
+ // Note SYSPROP_START_COUNT will increment by *2* on a FDE device when it fully boots;
+ // one for the password screen, second for the actual boot.
+ mStartCount = SystemProperties.getInt(SYSPROP_START_COUNT, 0) + 1;
mRuntimeStartElapsedTime = SystemClock.elapsedRealtime();
mRuntimeStartUptime = SystemClock.uptimeMillis();
+
+ // Remember if it's runtime restart(when sys.boot_completed is already set) or reboot
+ // We don't use "mStartCount > 1" here because it'll be wrong on a FDE device.
+ // TODO: mRuntimeRestart will *not* be set to true if the proccess crashes before
+ // sys.boot_completed is set. Fix it.
+ mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed"));
}
private void run() {
try {
traceBeginAndSlog("InitBeforeStartServices");
+
+ // Record the process start information in sys props.
+ SystemProperties.set(SYSPROP_START_COUNT, String.valueOf(mStartCount));
+ SystemProperties.set(SYSPROP_START_ELAPSED, String.valueOf(mRuntimeStartElapsedTime));
+ SystemProperties.set(SYSPROP_START_UPTIME, String.valueOf(mRuntimeStartUptime));
+
+ EventLog.writeEvent(EventLogTags.SYSTEM_SERVER_START,
+ mStartCount, mRuntimeStartUptime, mRuntimeStartElapsedTime);
+
// If a device's clock is before 1970 (before 0), a lot of
// APIs crash dealing with negative numbers, notably
// java.io.File#setLastModified, so instead we fake it and
diff --git a/services/net/java/android/net/NetworkStackClient.java b/services/net/java/android/net/NetworkStackClient.java
index 1eb7b98d801a..830dbbe8b8c0 100644
--- a/services/net/java/android/net/NetworkStackClient.java
+++ b/services/net/java/android/net/NetworkStackClient.java
@@ -30,6 +30,7 @@ import android.content.pm.PackageManager;
import android.net.dhcp.DhcpServingParamsParcel;
import android.net.dhcp.IDhcpServerCallbacks;
import android.net.ip.IIpClientCallbacks;
+import android.net.util.SharedLog;
import android.os.Binder;
import android.os.IBinder;
import android.os.Process;
@@ -40,6 +41,7 @@ import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
+import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
@@ -61,6 +63,9 @@ public class NetworkStackClient {
@GuardedBy("mPendingNetStackRequests")
private INetworkStackConnector mConnector;
+ @GuardedBy("mLog")
+ private final SharedLog mLog = new SharedLog(TAG);
+
private volatile boolean mNetworkStackStartRequested = false;
private interface NetworkStackCallback {
@@ -129,13 +134,14 @@ public class NetworkStackClient {
private class NetworkStackConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
+ log("Network stack service connected");
registerNetworkStackService(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
// TODO: crash/reboot the system ?
- Slog.wtf(TAG, "Lost network stack connector");
+ logWtf("Lost network stack connector", null);
}
};
@@ -144,6 +150,7 @@ public class NetworkStackClient {
ServiceManager.addService(Context.NETWORK_STACK_SERVICE, service, false /* allowIsolated */,
DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
+ log("Network stack service registered");
final ArrayList<NetworkStackCallback> requests;
synchronized (mPendingNetStackRequests) {
@@ -166,6 +173,7 @@ public class NetworkStackClient {
* started.
*/
public void start(Context context) {
+ log("Starting network stack");
mNetworkStackStartRequested = true;
// Try to bind in-process if the library is available
IBinder connector = null;
@@ -177,7 +185,7 @@ public class NetworkStackClient {
connector = (IBinder) service.getMethod("makeConnector", Context.class)
.invoke(null, context);
} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
- Slog.wtf(TAG, "Could not create network stack connector from NetworkStackService");
+ logWtf("Could not create network stack connector from NetworkStackService", e);
// TODO: crash/reboot system here ?
return;
} catch (ClassNotFoundException e) {
@@ -186,26 +194,28 @@ public class NetworkStackClient {
// In-process network stack. Add the service to the service manager here.
if (connector != null) {
+ log("Registering in-process network stack connector");
registerNetworkStackService(connector);
return;
}
// Start the network stack process. The service will be added to the service manager in
// NetworkStackConnection.onServiceConnected().
+ log("Starting network stack process");
final Intent intent = new Intent(INetworkStackConnector.class.getName());
final ComponentName comp = intent.resolveSystemService(context.getPackageManager(), 0);
intent.setComponent(comp);
if (comp == null) {
- Slog.wtf(TAG, "Could not resolve the network stack with " + intent);
+ logWtf("Could not resolve the network stack with " + intent, null);
// TODO: crash/reboot system server ?
return;
}
final PackageManager pm = context.getPackageManager();
int uid = -1;
try {
- uid = pm.getPackageUid(comp.getPackageName(), UserHandle.USER_SYSTEM);
+ uid = pm.getPackageUidAsUser(comp.getPackageName(), UserHandle.USER_SYSTEM);
} catch (PackageManager.NameNotFoundException e) {
- Slog.wtf("Network stack package not found", e);
+ logWtf("Network stack package not found", e);
// Fall through
}
if (uid != Process.NETWORK_STACK_UID) {
@@ -221,10 +231,31 @@ public class NetworkStackClient {
if (!context.bindServiceAsUser(intent, new NetworkStackConnection(),
Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.SYSTEM)) {
- Slog.wtf(TAG,
- "Could not bind to network stack in-process, or in app with " + intent);
+ logWtf("Could not bind to network stack in-process, or in app with " + intent, null);
+ return;
// TODO: crash/reboot system server if no network stack after a timeout ?
}
+
+ log("Network stack service start requested");
+ }
+
+ private void log(@NonNull String message) {
+ synchronized (mLog) {
+ mLog.log(message);
+ }
+ }
+
+ private void logWtf(@NonNull String message, @Nullable Throwable e) {
+ Slog.wtf(TAG, message);
+ synchronized (mLog) {
+ mLog.e(message, e);
+ }
+ }
+
+ private void loge(@NonNull String message, @Nullable Throwable e) {
+ synchronized (mLog) {
+ mLog.e(message, e);
+ }
}
/**
@@ -243,12 +274,12 @@ public class NetworkStackClient {
while ((connector = ServiceManager.getService(Context.NETWORK_STACK_SERVICE)) == null) {
Thread.sleep(20);
if (System.currentTimeMillis() - before > NETWORKSTACK_TIMEOUT_MS) {
- Slog.e(TAG, "Timeout waiting for NetworkStack connector");
+ loge("Timeout waiting for NetworkStack connector", null);
return null;
}
}
} catch (InterruptedException e) {
- Slog.e(TAG, "Error waiting for NetworkStack connector", e);
+ loge("Error waiting for NetworkStack connector", e);
return null;
}
@@ -286,4 +317,20 @@ public class NetworkStackClient {
request.onNetworkStackConnected(connector);
}
+
+ /**
+ * Dump NetworkStackClient logs to the specified {@link PrintWriter}.
+ */
+ public void dump(PrintWriter pw) {
+ // dump is thread-safe on SharedLog
+ mLog.dump(null, pw, null);
+
+ final int requestsQueueLength;
+ synchronized (mPendingNetStackRequests) {
+ requestsQueueLength = mPendingNetStackRequests.size();
+ }
+
+ pw.println();
+ pw.println("pendingNetStackRequests length: " + requestsQueueLength);
+ }
}
diff --git a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
index 8e3023bc08d4..339607bbc73d 100644
--- a/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
+++ b/services/net/java/android/net/ip/RouterAdvertisementDaemon.java
@@ -275,6 +275,9 @@ public class RouterAdvertisementDaemon {
public void stop() {
closeSocket();
+ // Wake up mMulticastTransmitter thread to interrupt a potential 1 day sleep before
+ // the thread's termination.
+ maybeNotifyMulticastTransmitter();
mMulticastTransmitter = null;
mUnicastResponder = null;
}
diff --git a/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java b/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java
index 5cb6cbb93b5b..26b122411c6b 100644
--- a/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java
+++ b/services/tests/servicestests/src/com/android/server/backup/testutils/IPackageManagerStub.java
@@ -213,7 +213,8 @@ public class IPackageManagerStub implements IPackageManager {
@Override
public void updatePermissionFlags(String permissionName, String packageName, int flagMask,
- int flagValues, int userId) throws RemoteException {
+ int flagValues, boolean checkAdjustPolicyFlagPermission, int userId)
+ throws RemoteException {
}
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
index 74d473944779..bf71318cf50a 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
@@ -106,6 +106,11 @@ public class LockSettingsServiceTestable extends LockSettingsService {
}
@Override
+ public boolean hasBiometrics() {
+ return false;
+ }
+
+ @Override
public int binderGetCallingUid() {
return Process.SYSTEM_UID;
}
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 76beb8f99c18..7e6b7da4a058 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -6286,6 +6286,15 @@ public class ShortcutManagerTest1 extends BaseShortcutManagerTest {
mManager.getShareTargets(filter);
}
+ public void testHasShareTargets_permission() {
+ assertExpectException(SecurityException.class, "Missing permission", () ->
+ mManager.hasShareTargets(CALLING_PACKAGE_1));
+
+ // Has permission, now it should pass.
+ mCallerPermissions.add(permission.MANAGE_APP_PREDICTIONS);
+ mManager.hasShareTargets(CALLING_PACKAGE_1);
+ }
+
public void testDumpsys_crossProfile() {
prepareCrossProfileDataSet();
dumpsysOnLogcat("test1", /* force= */ true);
diff --git a/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java
index 1b106dd37163..5c6fe0fc4cad 100644
--- a/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java
@@ -16,34 +16,9 @@
package com.android.server.timezone;
-import com.android.timezone.distro.DistroVersion;
-import com.android.timezone.distro.StagedDistroOperation;
-import com.android.timezone.distro.TimeZoneDistro;
-import com.android.timezone.distro.installer.TimeZoneDistroInstaller;
-
-import org.junit.Before;
-import org.junit.Test;
-
-import android.app.timezone.Callback;
-import android.app.timezone.DistroRulesVersion;
-import android.app.timezone.ICallback;
-import android.app.timezone.RulesManager;
-import android.app.timezone.RulesState;
-import android.os.ParcelFileDescriptor;
-
-import java.io.File;
-import java.io.FileDescriptor;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.concurrent.Executor;
-import javax.annotation.Nullable;
-
-import libcore.io.IoUtils;
-import libcore.timezone.TzDataSetVersion;
-
import static com.android.server.timezone.RulesManagerService.REQUIRED_QUERY_PERMISSION;
import static com.android.server.timezone.RulesManagerService.REQUIRED_UPDATER_PERMISSION;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
@@ -61,11 +36,43 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
+import android.app.timezone.Callback;
+import android.app.timezone.DistroRulesVersion;
+import android.app.timezone.ICallback;
+import android.app.timezone.RulesManager;
+import android.app.timezone.RulesState;
+import android.os.ParcelFileDescriptor;
+
+import com.android.timezone.distro.DistroVersion;
+import com.android.timezone.distro.StagedDistroOperation;
+import com.android.timezone.distro.TimeZoneDistro;
+import com.android.timezone.distro.installer.TimeZoneDistroInstaller;
+
+import libcore.io.IoUtils;
+import libcore.timezone.TzDataSetVersion;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.FileDescriptor;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.concurrent.Executor;
+
+import javax.annotation.Nullable;
+
/**
* White box interaction / unit testing of the {@link RulesManagerService}.
*/
public class RulesManagerServiceTest {
+ private static final int CURRENT_FORMAT_MAJOR_VERSION =
+ TzDataSetVersion.currentFormatMajorVersion();
+ private static final int CURRENT_FORMAT_MINOR_VERSION =
+ TzDataSetVersion.currentFormatMinorVersion();
+
private RulesManagerService mRulesManagerService;
private FakeExecutor mFakeExecutor;
@@ -116,8 +123,8 @@ public class RulesManagerServiceTest {
}
@Test
- public void getRulesState_systemRulesError() throws Exception {
- configureDeviceCannotReadSystemRulesVersion();
+ public void getRulesState_baseVersionError() throws Exception {
+ configureDeviceCannotReadBaseVersion();
assertNull(mRulesManagerService.getRulesState());
}
@@ -126,18 +133,18 @@ public class RulesManagerServiceTest {
public void getRulesState_stagedInstall() throws Exception {
configureCallerHasPermission();
- configureDeviceSystemRulesVersion("2016a");
+ configureDeviceBaseVersion("2016a");
DistroVersion stagedDistroVersion = new DistroVersion(
- TzDataSetVersion.currentFormatMajorVersion(),
- TzDataSetVersion.currentFormatMinorVersion() - 1,
+ CURRENT_FORMAT_MAJOR_VERSION,
+ CURRENT_FORMAT_MINOR_VERSION - 1,
"2016c",
- 3);
+ 3 /* revision */);
configureStagedInstall(stagedDistroVersion);
DistroVersion installedDistroVersion = new DistroVersion(
- TzDataSetVersion.currentFormatMajorVersion(),
- TzDataSetVersion.currentFormatMinorVersion() - 1,
+ CURRENT_FORMAT_MAJOR_VERSION,
+ CURRENT_FORMAT_MINOR_VERSION - 1,
"2016b",
4);
configureInstalledDistroVersion(installedDistroVersion);
@@ -158,13 +165,13 @@ public class RulesManagerServiceTest {
public void getRulesState_nothingStaged() throws Exception {
configureCallerHasPermission();
- configureDeviceSystemRulesVersion("2016a");
+ configureDeviceBaseVersion("2016a");
configureNoStagedOperation();
DistroVersion installedDistroVersion = new DistroVersion(
- TzDataSetVersion.currentFormatMajorVersion(),
- TzDataSetVersion.currentFormatMinorVersion() - 1,
+ CURRENT_FORMAT_MAJOR_VERSION,
+ CURRENT_FORMAT_MINOR_VERSION - 1,
"2016b",
4);
configureInstalledDistroVersion(installedDistroVersion);
@@ -183,13 +190,13 @@ public class RulesManagerServiceTest {
public void getRulesState_uninstallStaged() throws Exception {
configureCallerHasPermission();
- configureDeviceSystemRulesVersion("2016a");
+ configureDeviceBaseVersion("2016a");
configureStagedUninstall();
DistroVersion installedDistroVersion = new DistroVersion(
- TzDataSetVersion.currentFormatMajorVersion(),
- TzDataSetVersion.currentFormatMinorVersion() - 1,
+ CURRENT_FORMAT_MAJOR_VERSION,
+ CURRENT_FORMAT_MINOR_VERSION - 1,
"2016b",
4);
configureInstalledDistroVersion(installedDistroVersion);
@@ -208,8 +215,8 @@ public class RulesManagerServiceTest {
public void getRulesState_installedRulesError() throws Exception {
configureCallerHasPermission();
- String systemRulesVersion = "2016a";
- configureDeviceSystemRulesVersion(systemRulesVersion);
+ String baseRulesVersion = "2016a";
+ configureDeviceBaseVersion(baseRulesVersion);
configureStagedUninstall();
configureDeviceCannotReadInstalledDistroVersion();
@@ -226,14 +233,14 @@ public class RulesManagerServiceTest {
public void getRulesState_stagedRulesError() throws Exception {
configureCallerHasPermission();
- String systemRulesVersion = "2016a";
- configureDeviceSystemRulesVersion(systemRulesVersion);
+ String baseRulesVersion = "2016a";
+ configureDeviceBaseVersion(baseRulesVersion);
configureDeviceCannotReadStagedDistroOperation();
DistroVersion installedDistroVersion = new DistroVersion(
- TzDataSetVersion.currentFormatMajorVersion(),
- TzDataSetVersion.currentFormatMinorVersion() - 1,
+ CURRENT_FORMAT_MAJOR_VERSION,
+ CURRENT_FORMAT_MINOR_VERSION - 1,
"2016b",
4);
configureInstalledDistroVersion(installedDistroVersion);
@@ -252,13 +259,13 @@ public class RulesManagerServiceTest {
public void getRulesState_noInstalledRules() throws Exception {
configureCallerHasPermission();
- String systemRulesVersion = "2016a";
- configureDeviceSystemRulesVersion(systemRulesVersion);
+ String baseRulesVersion = "2016a";
+ configureDeviceBaseVersion(baseRulesVersion);
configureNoStagedOperation();
configureInstalledDistroVersion(null);
RulesState expectedRuleState = new RulesState(
- systemRulesVersion, RulesManagerService.DISTRO_FORMAT_VERSION_SUPPORTED,
+ baseRulesVersion, RulesManagerService.DISTRO_FORMAT_VERSION_SUPPORTED,
false /* operationInProgress */,
RulesState.STAGED_OPERATION_NONE, null /* stagedDistroRulesVersion */,
RulesState.DISTRO_STATUS_NONE, null /* installedDistroRulesVersion */);
@@ -269,15 +276,15 @@ public class RulesManagerServiceTest {
public void getRulesState_operationInProgress() throws Exception {
configureCallerHasPermission();
- String systemRulesVersion = "2016a";
+ String baseRulesVersion = "2016a";
String installedRulesVersion = "2016b";
int revision = 3;
- configureDeviceSystemRulesVersion(systemRulesVersion);
+ configureDeviceBaseVersion(baseRulesVersion);
DistroVersion installedDistroVersion = new DistroVersion(
- TzDataSetVersion.currentFormatMajorVersion(),
- TzDataSetVersion.currentFormatMinorVersion() - 1,
+ CURRENT_FORMAT_MAJOR_VERSION,
+ CURRENT_FORMAT_MINOR_VERSION - 1,
installedRulesVersion,
revision);
configureInstalledDistroVersion(installedDistroVersion);
@@ -297,7 +304,7 @@ public class RulesManagerServiceTest {
DistroRulesVersion expectedInstalledDistroRulesVersion =
new DistroRulesVersion(installedRulesVersion, revision);
RulesState expectedRuleState = new RulesState(
- systemRulesVersion, RulesManagerService.DISTRO_FORMAT_VERSION_SUPPORTED,
+ baseRulesVersion, RulesManagerService.DISTRO_FORMAT_VERSION_SUPPORTED,
true /* operationInProgress */,
RulesState.STAGED_OPERATION_UNKNOWN, null /* stagedDistroRulesVersion */,
RulesState.DISTRO_STATUS_INSTALLED, expectedInstalledDistroRulesVersion);
@@ -858,11 +865,20 @@ public class RulesManagerServiceTest {
.thenReturn(true);
// Set up the mocks to return (arbitrary) information about the current device state.
- when(mMockTimeZoneDistroInstaller.getSystemRulesVersion()).thenReturn("2017a");
- when(mMockTimeZoneDistroInstaller.getInstalledDistroVersion()).thenReturn(
- new DistroVersion(2, 3, "2017b", 4));
+ TzDataSetVersion baseVersion = new TzDataSetVersion(
+ CURRENT_FORMAT_MAJOR_VERSION, CURRENT_FORMAT_MINOR_VERSION, "2017a",
+ 1 /* revision */);
+ when(mMockTimeZoneDistroInstaller.readBaseVersion()).thenReturn(baseVersion);
+ DistroVersion installedDistroVersion = new DistroVersion(
+ CURRENT_FORMAT_MAJOR_VERSION, CURRENT_FORMAT_MINOR_VERSION, "2017b",
+ 4 /* revision */);
+ when(mMockTimeZoneDistroInstaller.getInstalledDistroVersion())
+ .thenReturn(installedDistroVersion);
+ DistroVersion stagedDistroVersion = new DistroVersion(
+ CURRENT_FORMAT_MAJOR_VERSION, CURRENT_FORMAT_MINOR_VERSION, "2017c",
+ 7 /* revision */);
when(mMockTimeZoneDistroInstaller.getStagedDistroOperation()).thenReturn(
- StagedDistroOperation.install(new DistroVersion(5, 6, "2017c", 7)));
+ StagedDistroOperation.install(stagedDistroVersion));
// Do the dump call.
String dumpedOutput = doDumpCallAndCapture(rulesManagerService, args);
@@ -973,8 +989,11 @@ public class RulesManagerServiceTest {
return new CheckToken(1, new PackageVersions(1, 1));
}
- private void configureDeviceSystemRulesVersion(String systemRulesVersion) throws Exception {
- when(mMockTimeZoneDistroInstaller.getSystemRulesVersion()).thenReturn(systemRulesVersion);
+ private void configureDeviceBaseVersion(String baseRulesVersion) throws Exception {
+ TzDataSetVersion tzDataSetVersion = new TzDataSetVersion(
+ CURRENT_FORMAT_MAJOR_VERSION, CURRENT_FORMAT_MINOR_VERSION, baseRulesVersion,
+ 1 /* revision */);
+ when(mMockTimeZoneDistroInstaller.readBaseVersion()).thenReturn(tzDataSetVersion);
}
private void configureInstalledDistroVersion(@Nullable DistroVersion installedDistroVersion)
@@ -1002,8 +1021,8 @@ public class RulesManagerServiceTest {
.thenThrow(new IOException("Simulated failure"));
}
- private void configureDeviceCannotReadSystemRulesVersion() throws Exception {
- when(mMockTimeZoneDistroInstaller.getSystemRulesVersion())
+ private void configureDeviceCannotReadBaseVersion() throws Exception {
+ when(mMockTimeZoneDistroInstaller.readBaseVersion())
.thenThrow(new IOException("Simulated failure"));
}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index cc621387691a..31788ae9b194 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -99,7 +99,6 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.MediaStore;
-import android.provider.Settings.Secure;
import android.service.notification.Adjustment;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationStats;
@@ -2519,7 +2518,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
verify(mListeners, times(1)).migrateToXml();
verify(mConditionProviders, times(1)).migrateToXml();
verify(mAssistants, times(1)).migrateToXml();
- verify(mAssistants, times(2)).ensureAssistant();
+ verify(mAssistants, never()).ensureAssistant();
}
@Test
@@ -2539,7 +2538,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
verify(mListeners, times(2)).migrateToXml();
verify(mConditionProviders, times(2)).migrateToXml();
verify(mAssistants, times(2)).migrateToXml();
- verify(mAssistants, times(2)).ensureAssistant();
+ verify(mAssistants, never()).ensureAssistant();
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
index 2627ec762d7a..c072d4e28e81 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppChangeTransitionTests.java
@@ -59,8 +59,7 @@ public class AppChangeTransitionTests extends WindowTestsBase {
public void setUpOnDisplay(DisplayContent dc) {
mStack = createTaskStackOnDisplay(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, dc);
mTask = createTaskInStack(mStack, 0 /* userId */);
- mToken = WindowTestUtils.createTestAppWindowToken(dc);
- mToken.mSkipOnParentChanged = false;
+ mToken = WindowTestUtils.createTestAppWindowToken(dc, false /* skipOnParentChanged */);
mTask.addChild(mToken, 0);
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
index afadc7978b47..b91f3ecd78c2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionTests.java
@@ -55,8 +55,11 @@ public class AppTransitionTests extends WindowTestsBase {
@Before
public void setUp() throws Exception {
- spyOn(mWm.mRoot);
- doNothing().when(mWm.mRoot).performSurfacePlacement(anyBoolean());
+ synchronized (mWm.mGlobalLock) {
+ // Hold the lock to protect the stubbing from being accessed by other threads.
+ spyOn(mWm.mRoot);
+ doNothing().when(mWm.mRoot).performSurfacePlacement(anyBoolean());
+ }
mDc = mWm.getDefaultDisplayContentLocked();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
index 108ee180b4b7..a98a6046890d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenAnimationTests.java
@@ -18,7 +18,6 @@ package com.android.server.wm;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
-import static android.view.SurfaceControl.Transaction;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -30,6 +29,8 @@ import static org.mockito.ArgumentMatchers.eq;
import android.platform.test.annotations.Presubmit;
import android.view.SurfaceControl;
+import androidx.test.filters.SmallTest;
+
import com.android.server.wm.WindowTestUtils.TestAppWindowToken;
import org.junit.Before;
@@ -38,8 +39,6 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import androidx.test.filters.FlakyTest;
-import androidx.test.filters.SmallTest;
/**
* Animation related tests for the {@link AppWindowToken} class.
@@ -49,14 +48,11 @@ import androidx.test.filters.SmallTest;
*/
@SmallTest
@Presubmit
-@FlakyTest(bugId = 124357362)
public class AppWindowTokenAnimationTests extends WindowTestsBase {
private TestAppWindowToken mToken;
@Mock
- private Transaction mTransaction;
- @Mock
private AnimationAdapter mSpec;
@Before
@@ -65,7 +61,6 @@ public class AppWindowTokenAnimationTests extends WindowTestsBase {
mToken = createTestAppWindowToken(mDisplayContent, WINDOWING_MODE_FULLSCREEN,
ACTIVITY_TYPE_STANDARD, false /* skipOnParentChanged */);
- mToken.setPendingTransaction(mTransaction);
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index 1dd72ec4fd71..2c575f59a020 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -60,7 +60,7 @@ import org.junit.Test;
* Tests for the {@link AppWindowToken} class.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:AppWindowTokenTests
+ * atest WmTests:AppWindowTokenTests
*/
@SmallTest
@Presubmit
@@ -76,9 +76,9 @@ public class AppWindowTokenTests extends WindowTestsBase {
public void setUp() throws Exception {
mStack = createTaskStackOnDisplay(mDisplayContent);
mTask = createTaskInStack(mStack, 0 /* userId */);
- mToken = WindowTestUtils.createTestAppWindowToken(mDisplayContent);
+ mToken = WindowTestUtils.createTestAppWindowToken(mDisplayContent,
+ false /* skipOnParentChanged */);
- mToken.mSkipOnParentChanged = false;
mTask.addChild(mToken, 0);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index b1b8e8ca990c..b26aa050870a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -68,7 +68,6 @@ import android.view.Surface;
import android.view.ViewRootImpl;
import android.view.test.InsetsModeSession;
-import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
import com.android.dx.mockito.inline.extended.ExtendedMockito;
@@ -97,7 +96,6 @@ import java.util.List;
public class DisplayContentTests extends WindowTestsBase {
@Test
- @FlakyTest(detail = "Promote to presubmit when shown to be stable.")
public void testForAllWindows() {
final WindowState exitingAppWindow = createWindow(null, TYPE_BASE_APPLICATION,
mDisplayContent, "exiting app");
@@ -621,7 +619,8 @@ public class DisplayContentTests extends WindowTestsBase {
@Test
public void testOnDescendantOrientationRequestChanged_FrozenToUserRotation() {
final DisplayContent dc = createNewDisplay();
- dc.getDisplayRotation().setFixedToUserRotation(true);
+ dc.getDisplayRotation().setFixedToUserRotation(
+ DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED);
mWm.mAtmService.mRootActivityContainer = mock(RootActivityContainer.class);
final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
? SCREEN_ORIENTATION_PORTRAIT
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 8349ac7fc62c..07dd93c948d1 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTests.java
@@ -25,20 +25,27 @@ import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACK
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_BOTTOM;
import static com.android.server.policy.WindowManagerPolicy.NAV_BAR_RIGHT;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.graphics.PixelFormat;
import android.platform.test.annotations.Presubmit;
+import android.view.Surface;
import android.view.WindowManager;
import androidx.test.filters.SmallTest;
@@ -196,4 +203,33 @@ public class DisplayPolicyTests extends WindowTestsBase {
DisplayPolicy.updateLightNavigationBarLw(0, opaqueDarkNavBar,
opaqueDarkNavBar, imeDrawLightNavBar, imeDrawLightNavBar));
}
+
+ @Test
+ public void testShouldRotateSeamlessly() {
+ final DisplayPolicy policy = mDisplayContent.getDisplayPolicy();
+ final WindowManager.LayoutParams attrs = mAppWindow.mAttrs;
+ attrs.x = attrs.y = 0;
+ attrs.height = attrs.width = WindowManager.LayoutParams.MATCH_PARENT;
+ attrs.rotationAnimation = ROTATION_ANIMATION_SEAMLESS;
+ final DisplayRotation displayRotation = mock(DisplayRotation.class);
+ doReturn(Surface.ROTATION_180).when(displayRotation).getUpsideDownRotation();
+
+ synchronized (mWm.mGlobalLock) {
+ policy.focusChangedLw(null /* lastFocus */, mAppWindow);
+ policy.applyPostLayoutPolicyLw(
+ mAppWindow, attrs, null /* attached */, null /* imeTarget */);
+ spyOn(policy);
+ doReturn(true).when(policy).navigationBarCanMove();
+ // The focused fullscreen opaque window without override bounds should be able to be
+ // rotated seamlessly.
+ assertTrue(policy.shouldRotateSeamlessly(
+ displayRotation, Surface.ROTATION_0, Surface.ROTATION_90));
+
+ spyOn(mAppWindow.mAppToken);
+ doReturn(false).when(mAppWindow.mAppToken).matchParentBounds();
+ // No seamless rotation if the window may be positioned with offset after rotation.
+ assertFalse(policy.shouldRotateSeamlessly(
+ displayRotation, Surface.ROTATION_0, Surface.ROTATION_90));
+ }
+ }
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
index 87336745568e..1c10ffb01f8e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LOCKED;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -31,6 +32,9 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
+import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_DEFAULT;
+import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_DISABLED;
+import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -160,9 +164,7 @@ public class DisplayRotationTests {
@Test
public void testPersistsUserRotation_LockRotation_NonDefaultDisplay() throws Exception {
- mBuilder.mIsDefaultDisplay = false;
-
- mBuilder.build();
+ mBuilder.setIsDefaultDisplay(false).build();
freezeRotation(Surface.ROTATION_180);
@@ -187,9 +189,7 @@ public class DisplayRotationTests {
@Test
public void testPersistsUserRotation_UnlockRotation_NonDefaultDisplay() throws Exception {
- mBuilder.mIsDefaultDisplay = false;
-
- mBuilder.build();
+ mBuilder.setIsDefaultDisplay(false).build();
thawRotation();
@@ -203,14 +203,22 @@ public class DisplayRotationTests {
public void testPersistsFixedToUserRotation() throws Exception {
mBuilder.build();
- mTarget.setFixedToUserRotation(true);
+ mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_ENABLED);
- verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent, true);
+ verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent,
+ FIXED_TO_USER_ROTATION_ENABLED);
reset(mMockDisplayWindowSettings);
- mTarget.setFixedToUserRotation(false);
+ mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_DISABLED);
- verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent, false);
+ verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent,
+ FIXED_TO_USER_ROTATION_DISABLED);
+
+ reset(mMockDisplayWindowSettings);
+ mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_DEFAULT);
+
+ verify(mMockDisplayWindowSettings).setFixedToUserRotation(mMockDisplayContent,
+ FIXED_TO_USER_ROTATION_DEFAULT);
}
// ========================================
@@ -355,17 +363,15 @@ public class DisplayRotationTests {
when(mMockDisplayPolicy.isAwake()).thenReturn(true);
when(mMockDisplayPolicy.isKeyguardDrawComplete()).thenReturn(true);
when(mMockDisplayPolicy.isWindowManagerDrawComplete()).thenReturn(true);
- mTarget.setFixedToUserRotation(true);
+ mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_ENABLED);
mTarget.updateOrientationListener();
verifyOrientationListenerRegistration(0);
}
@Test
- public void testNotEnablesSensor_ForceDefaultRotation() throws Exception {
+ public void testNotEnablesSensor_ForceDefaultRotation_Car() throws Exception {
mBuilder.build();
- when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
- .thenReturn(true);
- configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, true, false);
when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
when(mMockDisplayPolicy.isAwake()).thenReturn(true);
@@ -376,11 +382,9 @@ public class DisplayRotationTests {
}
@Test
- public void testNotEnablesSensor_ForceDefaultRotation_Car() throws Exception {
+ public void testNotEnablesSensor_ForceDefaultRotation_Tv() throws Exception {
mBuilder.build();
- when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
- .thenReturn(true);
- configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, true, false);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, true);
when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
when(mMockDisplayPolicy.isAwake()).thenReturn(true);
@@ -391,11 +395,9 @@ public class DisplayRotationTests {
}
@Test
- public void testNotEnablesSensor_ForceDefaultRotation_Tv() throws Exception {
+ public void testNotEnablesSensor_ForceDefaultRotation_Squared() throws Exception {
mBuilder.build();
- when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
- .thenReturn(true);
- configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, true);
+ configureDisplayRotation(SCREEN_ORIENTATION_LOCKED, false, false);
when(mMockDisplayPolicy.isScreenOnEarly()).thenReturn(true);
when(mMockDisplayPolicy.isAwake()).thenReturn(true);
@@ -513,33 +515,27 @@ public class DisplayRotationTests {
// Tests for Policy based Rotation
// =================================
@Test
- public void testReturnsUserRotation_ForceDefaultRotation() throws Exception {
+ public void testReturnsUserRotation_ForceDefaultRotation_Car() throws Exception {
mBuilder.build();
- when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
- .thenReturn(true);
- configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, true, false);
assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT,
Surface.ROTATION_180));
}
@Test
- public void testReturnsUserRotation_ForceDefaultRotation_Car() throws Exception {
+ public void testReturnsUserRotation_ForceDefaultRotation_Tv() throws Exception {
mBuilder.build();
- when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
- .thenReturn(true);
- configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, true, false);
+ configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, true);
assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT,
Surface.ROTATION_180));
}
@Test
- public void testReturnsUserRotation_ForceDefaultRotation_Tv() throws Exception {
+ public void testReturnsUserRotation_ForceDefaultRotation_Squared() throws Exception {
mBuilder.build();
- when(mMockRes.getBoolean(com.android.internal.R.bool.config_forceDefaultOrientation))
- .thenReturn(true);
- configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, true);
+ configureDisplayRotation(SCREEN_ORIENTATION_LOCKED, false, false);
assertEquals(Surface.ROTATION_0, mTarget.rotationForOrientation(SCREEN_ORIENTATION_PORTRAIT,
Surface.ROTATION_180));
@@ -591,7 +587,7 @@ public class DisplayRotationTests {
mBuilder.build();
configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
- mTarget.setFixedToUserRotation(true);
+ mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_ENABLED);
freezeRotation(Surface.ROTATION_180);
@@ -625,7 +621,7 @@ public class DisplayRotationTests {
@Test
public void testNotRespectAppRequestedOrientation_FixedToUserRotation() throws Exception {
mBuilder.build();
- mTarget.setFixedToUserRotation(true);
+ mTarget.setFixedToUserRotation(FIXED_TO_USER_ROTATION_ENABLED);
assertFalse("Display rotation shouldn't respect app requested orientation if"
+ " fixed to user rotation.", mTarget.respectAppRequestedOrientation());
@@ -647,9 +643,14 @@ public class DisplayRotationTests {
width = 1080;
height = 1920;
break;
+ case SCREEN_ORIENTATION_LOCKED:
+ // We use locked for squared display.
+ width = 1080;
+ height = 1080;
+ break;
default:
- throw new IllegalArgumentException("displayOrientation needs to be either landscape"
- + " or portrait, but we got "
+ throw new IllegalArgumentException("displayOrientation needs to be landscape, "
+ + "portrait or locked, but we got "
+ ActivityInfo.screenOrientationToString(displayOrientation));
}
@@ -659,6 +660,10 @@ public class DisplayRotationTests {
.thenReturn(isCar);
when(mockPackageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK))
.thenReturn(isTv);
+ when(mMockDisplayPolicy.getNonDecorDisplayWidth(anyInt(), anyInt(), anyInt(), anyInt(),
+ any())).thenReturn(width);
+ when(mMockDisplayPolicy.getNonDecorDisplayHeight(anyInt(), anyInt(), anyInt(), anyInt(),
+ any())).thenReturn(height);
final int shortSizeDp = (isCar || isTv) ? 540 : 720;
final int longSizeDp = 960;
@@ -826,6 +831,9 @@ public class DisplayRotationTests {
.thenReturn(convertRotationToDegrees(mDeskDockRotation));
when(mMockRes.getInteger(com.android.internal.R.integer.config_undockedHdmiRotation))
.thenReturn(convertRotationToDegrees(mUndockedHdmiRotation));
+ when(mMockRes.getFloat(
+ com.android.internal.R.dimen.config_closeToSquareDisplayMaxAspectRatio))
+ .thenReturn(1.33f);
mMockSensorManager = mock(SensorManager.class);
when(mMockContext.getSystemService(Context.SENSOR_SERVICE))
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
index 992d01766344..2dad18708499 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayWindowSettingsTests.java
@@ -26,6 +26,9 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_DEFAULT;
+import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_DISABLED;
+import static com.android.server.wm.DisplayRotation.FIXED_TO_USER_ROTATION_ENABLED;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
@@ -407,7 +410,7 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
}
@Test
- public void testNotFixedToUserRotationByDefault() {
+ public void testFixedToUserRotationDefault() {
mTarget.setUserRotation(mPrimaryDisplay, WindowManagerPolicy.USER_ROTATION_LOCKED,
Surface.ROTATION_0);
@@ -419,13 +422,14 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
mTarget.applySettingsToDisplayLocked(mPrimaryDisplay);
- verify(displayRotation).restoreSettings(anyInt(), anyInt(), eq(false));
+ verify(displayRotation).restoreSettings(anyInt(), anyInt(),
+ eq(FIXED_TO_USER_ROTATION_DEFAULT));
mockitoSession.finishMocking();
}
@Test
- public void testSetFixedToUserRotation() {
- mTarget.setFixedToUserRotation(mPrimaryDisplay, true);
+ public void testSetFixedToUserRotationDisabled() {
+ mTarget.setFixedToUserRotation(mPrimaryDisplay, FIXED_TO_USER_ROTATION_DISABLED);
final MockitoSession mockitoSession = ExtendedMockito.mockitoSession()
.startMocking();
@@ -435,7 +439,25 @@ public class DisplayWindowSettingsTests extends WindowTestsBase {
applySettingsToDisplayByNewInstance(mPrimaryDisplay);
- verify(displayRotation).restoreSettings(anyInt(), anyInt(), eq(true));
+ verify(displayRotation).restoreSettings(anyInt(), anyInt(),
+ eq(FIXED_TO_USER_ROTATION_DISABLED));
+ mockitoSession.finishMocking();
+ }
+
+ @Test
+ public void testSetFixedToUserRotationEnabled() {
+ mTarget.setFixedToUserRotation(mPrimaryDisplay, FIXED_TO_USER_ROTATION_ENABLED);
+
+ final MockitoSession mockitoSession = ExtendedMockito.mockitoSession()
+ .startMocking();
+ final DisplayRotation displayRotation = mock(DisplayRotation.class);
+ spyOn(mPrimaryDisplay);
+ doReturn(displayRotation).when(mPrimaryDisplay).getDisplayRotation();
+
+ applySettingsToDisplayByNewInstance(mPrimaryDisplay);
+
+ verify(displayRotation).restoreSettings(anyInt(), anyInt(),
+ eq(FIXED_TO_USER_ROTATION_ENABLED));
mockitoSession.finishMocking();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/MockSurfaceControlBuilder.java b/services/tests/wmtests/src/com/android/server/wm/MockSurfaceControlBuilder.java
new file mode 100644
index 000000000000..66139e6b483a
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/MockSurfaceControlBuilder.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static org.mockito.Mockito.mock;
+
+import android.view.SurfaceControl;
+
+/**
+ * Stubbed {@link SurfaceControl.Builder} class that returns a mocked SurfaceControl instance
+ * that can be used for unit testing.
+ */
+class MockSurfaceControlBuilder extends SurfaceControl.Builder {
+ @Override
+ public SurfaceControl.Builder setParent(SurfaceControl sc) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl build() {
+ return mock(SurfaceControl.class);
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
new file mode 100644
index 000000000000..d919fc80fe0b
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
@@ -0,0 +1,251 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.view.InputWindowHandle;
+import android.view.Surface;
+import android.view.SurfaceControl;
+
+/**
+ * Stubbed {@link android.view.SurfaceControl.Transaction} class that can be used when unit
+ * testing to avoid calls to native code.
+ */
+public class StubTransaction extends SurfaceControl.Transaction {
+ @Override
+ public void apply() {
+ }
+
+ @Override
+ public void close() {
+ }
+
+ @Override
+ public void apply(boolean sync) {
+ }
+
+ @Override
+ public SurfaceControl.Transaction setVisibility(SurfaceControl sc, boolean visible) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction show(SurfaceControl sc) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction hide(SurfaceControl sc) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setPosition(SurfaceControl sc, float x, float y) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setBufferSize(SurfaceControl sc,
+ int w, int h) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setLayer(SurfaceControl sc, int z) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setRelativeLayer(SurfaceControl sc, SurfaceControl relativeTo,
+ int z) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setTransparentRegionHint(SurfaceControl sc,
+ Region transparentRegion) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setAlpha(SurfaceControl sc, float alpha) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setInputWindowInfo(SurfaceControl sc,
+ InputWindowHandle handle) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction transferTouchFocus(IBinder fromToken, IBinder toToken) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setGeometry(SurfaceControl sc, Rect sourceCrop,
+ Rect destFrame, @Surface.Rotation int orientation) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setMatrix(SurfaceControl sc,
+ float dsdx, float dtdx, float dtdy, float dsdy) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setMatrix(SurfaceControl sc, Matrix matrix, float[] float9) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setColorTransform(SurfaceControl sc, float[] matrix,
+ float[] translation) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setWindowCrop(SurfaceControl sc, Rect crop) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setWindowCrop(SurfaceControl sc, int width, int height) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setCornerRadius(SurfaceControl sc, float cornerRadius) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setLayerStack(SurfaceControl sc, int layerStack) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction deferTransactionUntil(SurfaceControl sc, IBinder handle,
+ long frameNumber) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction deferTransactionUntilSurface(SurfaceControl sc,
+ Surface barrierSurface,
+ long frameNumber) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction reparentChildren(SurfaceControl sc, IBinder newParentHandle) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction reparent(SurfaceControl sc, SurfaceControl newParent) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction detachChildren(SurfaceControl sc) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setOverrideScalingMode(SurfaceControl sc,
+ int overrideScalingMode) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setColor(SurfaceControl sc, float[] color) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setGeometryAppliesWithResize(SurfaceControl sc) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setSecure(SurfaceControl sc, boolean isSecure) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setOpaque(SurfaceControl sc, boolean isOpaque) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setDisplaySurface(IBinder displayToken, Surface surface) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setDisplayLayerStack(IBinder displayToken, int layerStack) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setDisplayProjection(IBinder displayToken,
+ int orientation, Rect layerStackRect, Rect displayRect) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setDisplaySize(IBinder displayToken, int width, int height) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setAnimationTransaction() {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setEarlyWakeup() {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setMetadata(int key, int data) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction setMetadata(int key, Parcel data) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction merge(SurfaceControl.Transaction other) {
+ return this;
+ }
+
+ @Override
+ public SurfaceControl.Transaction remove(SurfaceControl sc) {
+ return this;
+ }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 712cd1e5fdfa..366aceafd7bf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -167,7 +167,7 @@ public class SystemServicesTestRule implements TestRule {
mWindowManagerPolicy = new TestWindowManagerPolicy(this::getWindowManagerService);
mWindowManagerService = WindowManagerService.main(
- context, ims, false, false, mWindowManagerPolicy, atms);
+ context, ims, false, false, mWindowManagerPolicy, atms, StubTransaction::new);
mWindowManagerService.onInitReady();
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
index b1f942eb2261..70ed62a4a11e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
@@ -175,10 +175,14 @@ public class TaskStackTests extends WindowTestsBase {
@Test
public void testStackOutset() {
final TaskStack stack = createTaskStackOnDisplay(mDisplayContent);
- spyOn(stack);
-
final int stackOutset = 10;
- doReturn(stackOutset).when(stack).getStackOutset();
+ // Clear the handler and hold the lock for mock, to prevent multi-thread issue.
+ waitUntilHandlersIdle();
+ synchronized (mWm.mGlobalLock) {
+ spyOn(stack);
+
+ doReturn(stackOutset).when(stack).getStackOutset();
+ }
final Rect stackBounds = new Rect(200, 200, 800, 1000);
// Update surface position and size by the given bounds.
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 849772a4a26d..c3561f4bf6ab 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -313,8 +313,8 @@ class TestWindowManagerPolicy implements WindowManagerPolicy {
}
@Override
- public boolean performHapticFeedbackLw(WindowState win, int effectId, boolean always,
- String reason) {
+ public boolean performHapticFeedback(int uid, String packageName, int effectId,
+ boolean always, String reason) {
return false;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
index d07230ef2ca3..6249bde3cea6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WallpaperControllerTests.java
@@ -21,11 +21,9 @@ import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
-import static junit.framework.TestCase.assertNotNull;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.assertNull;
-
-import android.graphics.Bitmap;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
@@ -37,7 +35,7 @@ import org.junit.Test;
* Tests for the {@link WallpaperController} class.
*
* Build/Install/Run:
- * atest FrameworksServicesTests:WallpaperControllerTests
+ * atest WmTests:WallpaperControllerTests
*/
@SmallTest
@Presubmit
@@ -49,34 +47,29 @@ public class WallpaperControllerTests extends WindowTestsBase {
synchronized (mWm.mGlobalLock) {
// No wallpaper
final DisplayContent dc = createNewDisplay();
- Bitmap wallpaperBitmap = dc.mWallpaperController.screenshotWallpaperLocked();
- assertNull(wallpaperBitmap);
+ assertFalse(dc.mWallpaperController.canScreenshotWallpaper());
// No wallpaper WSA Surface
WindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm, mock(IBinder.class),
true, dc, true /* ownerCanManageAppTokens */);
WindowState wallpaperWindow = createWindow(null /* parent */, TYPE_WALLPAPER,
wallpaperWindowToken, "wallpaperWindow");
- wallpaperBitmap = dc.mWallpaperController.screenshotWallpaperLocked();
- assertNull(wallpaperBitmap);
+ assertFalse(dc.mWallpaperController.canScreenshotWallpaper());
// Wallpaper with not visible WSA surface.
wallpaperWindow.mWinAnimator.mSurfaceController = windowSurfaceController;
wallpaperWindow.mWinAnimator.mLastAlpha = 1;
- wallpaperBitmap = dc.mWallpaperController.screenshotWallpaperLocked();
- assertNull(wallpaperBitmap);
+ assertFalse(dc.mWallpaperController.canScreenshotWallpaper());
when(windowSurfaceController.getShown()).thenReturn(true);
// Wallpaper with WSA alpha set to 0.
wallpaperWindow.mWinAnimator.mLastAlpha = 0;
- wallpaperBitmap = dc.mWallpaperController.screenshotWallpaperLocked();
- assertNull(wallpaperBitmap);
+ assertFalse(dc.mWallpaperController.canScreenshotWallpaper());
// Wallpaper window with WSA Surface
wallpaperWindow.mWinAnimator.mLastAlpha = 1;
- wallpaperBitmap = dc.mWallpaperController.screenshotWallpaperLocked();
- assertNotNull(wallpaperBitmap);
+ assertTrue(dc.mWallpaperController.canScreenshotWallpaper());
}
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index b0e20b89b811..b03f63b9159f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -110,8 +110,11 @@ public class WindowStateTests extends WindowTestsBase {
// TODO: Let the insets source with new mode keep the visibility control, and remove this
// setup code. Now mTopFullscreenOpaqueWindowState will take back the control of insets
// visibility.
- spyOn(mDisplayContent);
- doNothing().when(mDisplayContent).layoutAndAssignWindowLayersIfNeeded();
+ // Hold the lock to protect the mock from accesssing by other threads.
+ synchronized (mWm.mGlobalLock) {
+ spyOn(mDisplayContent);
+ doNothing().when(mDisplayContent).layoutAndAssignWindowLayersIfNeeded();
+ }
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
index 5bfa0c6e0885..da1defabeaaf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestUtils.java
@@ -28,7 +28,6 @@ import android.os.Build;
import android.os.IBinder;
import android.view.IApplicationToken;
import android.view.IWindow;
-import android.view.SurfaceControl.Transaction;
import android.view.WindowManager;
/**
@@ -72,7 +71,6 @@ class WindowTestUtils {
static class TestAppWindowToken extends AppWindowToken {
boolean mOnTop = false;
private boolean mSkipPrepareSurfaces;
- private Transaction mPendingTransactionOverride;
boolean mSkipOnParentChanged = true;
private TestAppWindowToken(DisplayContent dc, boolean skipOnParentChanged) {
@@ -126,17 +124,6 @@ class WindowTestUtils {
void setSkipPrepareSurfaces(boolean ignore) {
mSkipPrepareSurfaces = ignore;
}
-
- void setPendingTransaction(Transaction transaction) {
- mPendingTransactionOverride = transaction;
- }
-
- @Override
- public Transaction getPendingTransaction() {
- return mPendingTransactionOverride == null
- ? super.getPendingTransaction()
- : mPendingTransactionOverride;
- }
}
/**
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index 0d7d085ab1b4..d202e16a5ff4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -37,7 +37,10 @@ import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
+
+import static org.mockito.Mockito.mock;
+
import android.content.Context;
import android.content.res.Configuration;
@@ -47,6 +50,8 @@ import android.util.Log;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.IWindow;
+import android.view.Surface;
+import android.view.SurfaceControl.Transaction;
import android.view.WindowManager;
import com.android.server.AttributeCache;
@@ -96,10 +101,9 @@ class WindowTestsBase {
private MockTracker mMockTracker;
/**
- * To restore the original SurfaceControl.Transaction factory if any tests changed
- * {@link WindowManagerService#mTransactionFactory}.
+ * Spied {@link Transaction} class than can be used to verify calls.
*/
- private TransactionFactory mOriginalTransactionFactory;
+ Transaction mTransaction;
@Rule
public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
@@ -129,11 +133,21 @@ class WindowTestsBase {
// in the set up are clear. This can be removed when b/37850063 is fixed.
try {
mMockSession = mock(Session.class);
+ mTransaction = spy(StubTransaction.class);
final Context context = getInstrumentation().getTargetContext();
mWm = mSystemServicesTestRule.getWindowManagerService();
- mOriginalTransactionFactory = mWm.mTransactionFactory;
+
+ // Setup factory classes to prevent calls to native code.
+
+ // Return a spied Transaction class than can be used to verify calls.
+ mWm.mTransactionFactory = () -> mTransaction;
+ // Return a SurfaceControl.Builder class that creates mocked SurfaceControl instances.
+ mWm.mSurfaceBuilderFactory = (unused) -> new MockSurfaceControlBuilder();
+ // Return mocked Surface instances.
+ mWm.mSurfaceFactory = () -> mock(Surface.class);
+
beforeCreateDisplay();
context.getDisplay().getDisplayInfo(mDisplayInfo);
@@ -183,7 +197,6 @@ class WindowTestsBase {
// stable state to clean up for consistency.
waitUntilHandlersIdle();
- mWm.mTransactionFactory = mOriginalTransactionFactory;
final LinkedList<WindowState> nonCommonWindows = new LinkedList<>();
synchronized (mWm.mGlobalLock) {
diff --git a/telecomm/java/android/telecom/CallIdentification.java b/telecomm/java/android/telecom/CallIdentification.java
index 87834fd5109d..cde7f608fa6a 100644
--- a/telecomm/java/android/telecom/CallIdentification.java
+++ b/telecomm/java/android/telecom/CallIdentification.java
@@ -45,13 +45,13 @@ public final class CallIdentification implements Parcelable {
* {@link CallIdentification} for a screened call.
*/
public static class Builder {
- private String mName;
- private String mDescription;
- private String mDetails;
+ private CharSequence mName;
+ private CharSequence mDescription;
+ private CharSequence mDetails;
private Icon mPhoto;
private int mNuisanceConfidence = CallIdentification.CONFIDENCE_UNKNOWN;
private String mPackageName;
- private String mAppName;
+ private CharSequence mAppName;
/**
* Default builder constructor.
@@ -67,7 +67,7 @@ public final class CallIdentification implements Parcelable {
* @param callIdAppName The app name.
* @hide
*/
- public Builder(String callIdPackageName, String callIdAppName) {
+ public Builder(String callIdPackageName, CharSequence callIdAppName) {
mPackageName = callIdPackageName;
mAppName = callIdAppName;
}
@@ -80,7 +80,7 @@ public final class CallIdentification implements Parcelable {
* @param name The name associated with the call, or {@code null} if none is provided.
* @return Builder instance.
*/
- public Builder setName(@Nullable String name) {
+ public Builder setName(@Nullable CharSequence name) {
mName = name;
return this;
}
@@ -97,7 +97,7 @@ public final class CallIdentification implements Parcelable {
* @param description The call description, or {@code null} if none is provided.
* @return Builder instance.
*/
- public Builder setDescription(@Nullable String description) {
+ public Builder setDescription(@Nullable CharSequence description) {
mDescription = description;
return this;
}
@@ -114,7 +114,7 @@ public final class CallIdentification implements Parcelable {
* @param details The call details, or {@code null} if none is provided.
* @return Builder instance.
*/
- public Builder setDetails(@Nullable String details) {
+ public Builder setDetails(@Nullable CharSequence details) {
mDetails = details;
return this;
}
@@ -241,10 +241,10 @@ public final class CallIdentification implements Parcelable {
* call identification.
* @hide
*/
- private CallIdentification(@Nullable String name, @Nullable String description,
- @Nullable String details, @Nullable Icon photo,
+ private CallIdentification(@Nullable CharSequence name, @Nullable CharSequence description,
+ @Nullable CharSequence details, @Nullable Icon photo,
@NuisanceConfidence int nuisanceConfidence, @NonNull String callScreeningPackageName,
- @NonNull String callScreeningAppName) {
+ @NonNull CharSequence callScreeningAppName) {
mName = name;
mDescription = description;
mDetails = details;
@@ -254,13 +254,13 @@ public final class CallIdentification implements Parcelable {
mCallScreeningPackageName = callScreeningPackageName;
}
- private String mName;
- private String mDescription;
- private String mDetails;
+ private CharSequence mName;
+ private CharSequence mDescription;
+ private CharSequence mDetails;
private Icon mPhoto;
private int mNuisanceConfidence;
private String mCallScreeningPackageName;
- private String mCallScreeningAppName;
+ private CharSequence mCallScreeningAppName;
@Override
public int describeContents() {
@@ -269,13 +269,13 @@ public final class CallIdentification implements Parcelable {
@Override
public void writeToParcel(Parcel parcel, int i) {
- parcel.writeString(mName);
- parcel.writeString(mDescription);
- parcel.writeString(mDetails);
+ parcel.writeCharSequence(mName);
+ parcel.writeCharSequence(mDescription);
+ parcel.writeCharSequence(mDetails);
parcel.writeParcelable(mPhoto, 0);
parcel.writeInt(mNuisanceConfidence);
parcel.writeString(mCallScreeningPackageName);
- parcel.writeString(mCallScreeningAppName);
+ parcel.writeCharSequence(mCallScreeningAppName);
}
/**
@@ -286,13 +286,13 @@ public final class CallIdentification implements Parcelable {
@Override
public CallIdentification createFromParcel(Parcel source) {
- String name = source.readString();
- String description = source.readString();
- String details = source.readString();
+ CharSequence name = source.readCharSequence();
+ CharSequence description = source.readCharSequence();
+ CharSequence details = source.readCharSequence();
Icon photo = source.readParcelable(ClassLoader.getSystemClassLoader());
int nuisanceConfidence = source.readInt();
String callScreeningPackageName = source.readString();
- String callScreeningAppName = source.readString();
+ CharSequence callScreeningAppName = source.readCharSequence();
return new CallIdentification(name, description, details, photo,
nuisanceConfidence, callScreeningPackageName, callScreeningAppName);
}
@@ -311,7 +311,7 @@ public final class CallIdentification implements Parcelable {
*
* @return The name associated with the number, or {@code null} if none was provided.
*/
- public final @Nullable String getName() {
+ public final @Nullable CharSequence getName() {
return mName;
}
@@ -325,7 +325,7 @@ public final class CallIdentification implements Parcelable {
*
* @return The call description, or {@code null} if none was provided.
*/
- public final @Nullable String getDescription() {
+ public final @Nullable CharSequence getDescription() {
return mDescription;
}
@@ -340,7 +340,7 @@ public final class CallIdentification implements Parcelable {
*
* @return The call details, or {@code null} if none was provided.
*/
- public final @Nullable String getDetails() {
+ public final @Nullable CharSequence getDetails() {
return mDetails;
}
@@ -363,8 +363,7 @@ public final class CallIdentification implements Parcelable {
*
* @return The nuisance confidence.
*/
- public final @NuisanceConfidence
- int getNuisanceConfidence() {
+ public final @NuisanceConfidence int getNuisanceConfidence() {
return mNuisanceConfidence;
}
@@ -387,7 +386,7 @@ public final class CallIdentification implements Parcelable {
*
* @return The name of the app.
*/
- public final @NonNull String getCallScreeningAppName() {
+ public final @NonNull CharSequence getCallScreeningAppName() {
return mCallScreeningAppName;
}
@@ -407,7 +406,7 @@ public final class CallIdentification implements Parcelable {
* @param callScreeningAppName The app name.
* @hide
*/
- public void setCallScreeningAppName(@NonNull String callScreeningAppName) {
+ public void setCallScreeningAppName(@NonNull CharSequence callScreeningAppName) {
mCallScreeningAppName = callScreeningAppName;
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index ad98e3676733..c0444bb17ac7 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2992,9 +2992,9 @@ public class CarrierConfigManager {
/* Default value is 1024 kbps */
sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_BANDWIDTH_INT, 1024);
/* Default value is 10 seconds */
- sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_OR_EXIT_HYSTERESIS_TIME_LONG, 10000);
+ sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_ENTRY_OR_EXIT_HYSTERESIS_TIME_LONG, 10000);
/* Default value is 10 seconds. */
- sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_HYSTERESIS_TIME_LONG, 10000);
+ sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_HYSTERESIS_TIME_LONG, 10000);
sDefaults.putAll(Gps.getDefaults());
sDefaults.putIntArray(KEY_CDMA_ENHANCED_ROAMING_INDICATOR_FOR_HOME_NETWORK_INT_ARRAY,
new int[] {
diff --git a/telephony/java/android/telephony/DisconnectCause.java b/telephony/java/android/telephony/DisconnectCause.java
index f53cb8224706..6e839ab0ad6b 100644
--- a/telephony/java/android/telephony/DisconnectCause.java
+++ b/telephony/java/android/telephony/DisconnectCause.java
@@ -26,7 +26,7 @@ import android.annotation.UnsupportedAppUsage;
* @hide
*/
@SystemApi
-public class DisconnectCause {
+public final class DisconnectCause {
/** The disconnect cause is not valid (Not received a disconnect cause) */
public static final int NOT_VALID = -1;
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index ffebc04c39e6..bb0673f921e3 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -176,26 +176,21 @@ public class PhoneStateListener {
/**
* Listen for {@link PreciseCallState.State} of ringing, background and foreground calls.
- * {@more}
- * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE
- * READ_PRECISE_PHONE_STATE}
*
* @hide
*/
+ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
@SystemApi
public static final int LISTEN_PRECISE_CALL_STATE = 0x00000800;
/**
* Listen for {@link PreciseDataConnectionState} on the data connection (cellular).
*
- * {@more}
- * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE
- * READ_PRECISE_PHONE_STATE}
- *
* @see #onPreciseDataConnectionStateChanged
*
* @hide
*/
+ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
@SystemApi
public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 0x00001000;
@@ -331,12 +326,10 @@ public class PhoneStateListener {
/**
* Listen for call disconnect causes which contains {@link DisconnectCause} and
* {@link PreciseDisconnectCause}.
- * {@more}
- * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE
- * READ_PRECISE_PHONE_STATE}
*
* @hide
*/
+ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
@SystemApi
public static final int LISTEN_CALL_DISCONNECT_CAUSES = 0x02000000;
@@ -356,13 +349,10 @@ public class PhoneStateListener {
* Listen for IMS call disconnect causes which contains
* {@link android.telephony.ims.ImsReasonInfo}
*
- * {@more}
- * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE
- * READ_PRECISE_PHONE_STATE}
- *
* @see #onImsCallDisconnectCauseChanged(ImsReasonInfo)
* @hide
*/
+ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
@SystemApi
public static final int LISTEN_IMS_CALL_DISCONNECT_CAUSES = 0x08000000;
@@ -579,8 +569,9 @@ public class PhoneStateListener {
* @param callState {@link PreciseCallState}
* @hide
*/
+ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
@SystemApi
- public void onPreciseCallStateChanged(PreciseCallState callState) {
+ public void onPreciseCallStateChanged(@NonNull PreciseCallState callState) {
// default implementation empty
}
@@ -591,6 +582,7 @@ public class PhoneStateListener {
*
* @hide
*/
+ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
@SystemApi
public void onCallDisconnectCauseChanged(int disconnectCause, int preciseDisconnectCause) {
// default implementation empty
@@ -602,6 +594,7 @@ public class PhoneStateListener {
*
* @hide
*/
+ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
@SystemApi
public void onImsCallDisconnectCauseChanged(@NonNull ImsReasonInfo imsReasonInfo) {
// default implementation empty
@@ -613,6 +606,7 @@ public class PhoneStateListener {
*
* @hide
*/
+ @RequiresPermission((android.Manifest.permission.READ_PRECISE_PHONE_STATE))
@SystemApi
public void onPreciseDataConnectionStateChanged(
PreciseDataConnectionState dataConnectionState) {
diff --git a/telephony/java/android/telephony/PreciseDisconnectCause.java b/telephony/java/android/telephony/PreciseDisconnectCause.java
index af88748af9e6..54980a29c0a6 100644
--- a/telephony/java/android/telephony/PreciseDisconnectCause.java
+++ b/telephony/java/android/telephony/PreciseDisconnectCause.java
@@ -23,7 +23,7 @@ import android.annotation.SystemApi;
* @hide
*/
@SystemApi
-public class PreciseDisconnectCause {
+public final class PreciseDisconnectCause {
/** The disconnect cause is not valid (Not received a disconnect cause).*/
public static final int NOT_VALID = -1;
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index a1aee6d8217f..3dc119950a59 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -1569,6 +1569,17 @@ public class ServiceState implements Parcelable {
/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
public @TelephonyManager.NetworkType int getDataNetworkType() {
+ final NetworkRegistrationState iwlanRegState = getNetworkRegistrationState(
+ NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WLAN);
+ if (iwlanRegState != null
+ && iwlanRegState.getRegState() == NetworkRegistrationState.REG_STATE_HOME) {
+ // If the device is on IWLAN, return IWLAN as the network type. This is to simulate the
+ // behavior of legacy mode device. In the future caller should use
+ // getNetworkRegistrationState() to retrieve the actual data network type on cellular
+ // or on IWLAN.
+ return iwlanRegState.getAccessNetworkTechnology();
+ }
+
final NetworkRegistrationState regState = getNetworkRegistrationState(
NetworkRegistrationState.DOMAIN_PS, AccessNetworkConstants.TransportType.WWAN);
if (regState != null) {
diff --git a/telephony/java/android/telephony/SignalStrength.java b/telephony/java/android/telephony/SignalStrength.java
index d2ae106b5545..d461bd0fee8a 100644
--- a/telephony/java/android/telephony/SignalStrength.java
+++ b/telephony/java/android/telephony/SignalStrength.java
@@ -215,13 +215,52 @@ public class SignalStrength implements Parcelable {
* @see android.telephony#CellSignalStrengthGsm
*/
public @NonNull List<CellSignalStrength> getCellSignalStrengths() {
- List<CellSignalStrength> cssList = new ArrayList<>(2); // Usually have 2 or fewer elems
- if (mLte.isValid()) cssList.add(mLte);
- if (mCdma.isValid()) cssList.add(mCdma);
- if (mTdscdma.isValid()) cssList.add(mTdscdma);
- if (mWcdma.isValid()) cssList.add(mWcdma);
- if (mGsm.isValid()) cssList.add(mGsm);
- if (mNr.isValid()) cssList.add(mNr);
+ return getCellSignalStrengths(CellSignalStrength.class);
+ }
+
+ /**
+ * Returns a List of CellSignalStrength Components of this SignalStrength Report.
+ *
+ * Use this API to access underlying
+ * {@link android.telephony#CellSignalStrength CellSignalStrength} objects that provide more
+ * granular information about the SignalStrength report. Only valid (non-empty)
+ * CellSignalStrengths will be returned. The order of any returned elements is not guaranteed,
+ * and the list may contain more than one instance of a CellSignalStrength type.
+ *
+ * @param clazz a class type that extends
+ * {@link android.telephony.CellSignalStrength CellSignalStrength} to filter possible
+ * return values.
+ * @return a List of CellSignalStrength or an empty List if there are no valid measurements.
+ *
+ * @see android.telephony#CellSignalStrength
+ * @see android.telephony#CellSignalStrengthNr
+ * @see android.telephony#CellSignalStrengthLte
+ * @see android.telephony#CellSignalStrengthTdscdma
+ * @see android.telephony#CellSignalStrengthWcdma
+ * @see android.telephony#CellSignalStrengthCdma
+ * @see android.telephony#CellSignalStrengthGsm
+ */
+ public <T extends CellSignalStrength> @NonNull List<T> getCellSignalStrengths(
+ @NonNull Class<T> clazz) {
+ List<T> cssList = new ArrayList<>(2); // Usually have 2 or fewer elems
+ if (mLte.isValid() && clazz.isAssignableFrom(CellSignalStrengthLte.class)) {
+ cssList.add((T) mLte);
+ }
+ if (mCdma.isValid() && clazz.isAssignableFrom(CellSignalStrengthCdma.class)) {
+ cssList.add((T) mCdma);
+ }
+ if (mTdscdma.isValid() && clazz.isAssignableFrom(CellSignalStrengthTdscdma.class)) {
+ cssList.add((T) mTdscdma);
+ }
+ if (mWcdma.isValid() && clazz.isAssignableFrom(CellSignalStrengthWcdma.class)) {
+ cssList.add((T) mWcdma);
+ }
+ if (mGsm.isValid() && clazz.isAssignableFrom(CellSignalStrengthGsm.class)) {
+ cssList.add((T) mGsm);
+ }
+ if (mNr.isValid() && clazz.isAssignableFrom(CellSignalStrengthNr.class)) {
+ cssList.add((T) mNr);
+ }
return cssList;
}
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 94f26a8a8d61..c28d1fb6d43e 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2081,7 +2081,7 @@ public class SubscriptionManager {
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
- subId = iSub.getActiveSubIdList();
+ subId = iSub.getActiveSubIdList(/*visibleOnly*/true);
}
} catch (RemoteException ex) {
// ignore it
@@ -2866,7 +2866,7 @@ public class SubscriptionManager {
*
* @hide
*/
- private boolean shouldHideSubscription(SubscriptionInfo info) {
+ public boolean shouldHideSubscription(SubscriptionInfo info) {
if (info == null) return false;
// If hasCarrierPrivileges or canManageSubscription returns true, it means caller
@@ -2874,8 +2874,14 @@ public class SubscriptionManager {
boolean hasCarrierPrivilegePermission = (info.isEmbedded() && canManageSubscription(info))
|| TelephonyManager.from(mContext).hasCarrierPrivileges(info.getSubscriptionId());
- return (!TextUtils.isEmpty(info.getGroupUuid()) && info.isOpportunistic()
- && !hasCarrierPrivilegePermission);
+ return isInvisibleSubscription(info) && !hasCarrierPrivilegePermission;
+ }
+
+ /**
+ * @hide
+ */
+ public static boolean isInvisibleSubscription(SubscriptionInfo info) {
+ return info != null && !TextUtils.isEmpty(info.getGroupUuid()) && info.isOpportunistic();
}
/**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 0b72679cdf2a..c1d14406dc40 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -8665,24 +8665,26 @@ public class TelephonyManager {
/**
- * Returns a well-formed IETF BCP 47 language tag representing the locale from the SIM, e.g,
- * en-US. Returns {@code null} if no locale could be derived from subscriptions.
+ * Returns a locale based on the country and language from the SIM. Returns {@code null} if
+ * no locale could be derived from subscriptions.
*
* <p>Requires Permission:
* {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE}
*
* @see Locale#toLanguageTag()
- * @see Locale#forLanguageTag(String)
*
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- @Nullable public String getSimLocale() {
+ @Nullable public Locale getSimLocale() {
try {
final ITelephony telephony = getITelephony();
if (telephony != null) {
- return telephony.getSimLocaleForSubscriber(getSubId());
+ String languageTag = telephony.getSimLocaleForSubscriber(getSubId());
+ if (!TextUtils.isEmpty(languageTag)) {
+ return Locale.forLanguageTag(languageTag);
+ }
}
} catch (RemoteException ex) {
}
@@ -10306,24 +10308,25 @@ public class TelephonyManager {
/**
* Returns if the usage of multiple SIM cards at the same time to register on the network
- * (e.g. Dual Standby or Dual Active) is restricted.
+ * (e.g. Dual Standby or Dual Active) is supported by the device and by the carrier.
*
- * @return true if usage of multiple SIMs is restricted, false otherwise.
+ * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE}
+ * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
*
- * @hide
+ * @return true if usage of multiple SIMs is supported, false otherwise.
*/
- @SystemApi
- @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public boolean isMultisimCarrierRestricted() {
+ @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges
+ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+ public boolean isMultisimSupported() {
try {
ITelephony service = getITelephony();
if (service != null) {
- return service.isMultisimCarrierRestricted();
+ return service.isMultisimSupported(getOpPackageName());
}
} catch (RemoteException e) {
- Log.e(TAG, "isMultisimCarrierRestricted RemoteException", e);
+ Log.e(TAG, "isMultisimSupported RemoteException", e);
}
- return true;
+ return false;
}
/**
@@ -10338,8 +10341,8 @@ public class TelephonyManager {
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void switchMultiSimConfig(int numOfSims) {
//only proceed if multi-sim is not restricted
- if (isMultisimCarrierRestricted()) {
- Rlog.e(TAG, "switchMultiSimConfig not possible. It is restricted.");
+ if (!isMultisimSupported()) {
+ Rlog.e(TAG, "switchMultiSimConfig not possible. It is restricted or not supported.");
return;
}
diff --git a/telephony/java/android/telephony/ims/Rcs1To1Thread.java b/telephony/java/android/telephony/ims/Rcs1To1Thread.java
index d4a78ffb77db..0bb1b4379679 100644
--- a/telephony/java/android/telephony/ims/Rcs1To1Thread.java
+++ b/telephony/java/android/telephony/ims/Rcs1To1Thread.java
@@ -22,6 +22,8 @@ import android.annotation.WorkerThread;
* Rcs1To1Thread represents a single RCS conversation thread with a total of two
* {@link RcsParticipant}s. Please see Section 5 (1-to-1 Messaging) - GSMA RCC.71 (RCS Universal
* Profile Service Definition Document)
+ *
+ * @hide
*/
public class Rcs1To1Thread extends RcsThread {
private int mThreadId;
diff --git a/telephony/java/android/telephony/ims/RcsEvent.java b/telephony/java/android/telephony/ims/RcsEvent.java
index a547c5c00141..994b27ab7405 100644
--- a/telephony/java/android/telephony/ims/RcsEvent.java
+++ b/telephony/java/android/telephony/ims/RcsEvent.java
@@ -17,6 +17,8 @@ package android.telephony.ims;
/**
* The base class for events that can happen on {@link RcsParticipant}s and {@link RcsThread}s.
+ *
+ * @hide
*/
public abstract class RcsEvent {
private final long mTimestamp;
diff --git a/telephony/java/android/telephony/ims/RcsEventQueryParams.java b/telephony/java/android/telephony/ims/RcsEventQueryParams.java
index 9dbfe4393213..5f8fa8003751 100644
--- a/telephony/java/android/telephony/ims/RcsEventQueryParams.java
+++ b/telephony/java/android/telephony/ims/RcsEventQueryParams.java
@@ -37,6 +37,8 @@ import java.security.InvalidParameterException;
* The parameters to pass into
* {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)} in order to select a
* subset of {@link RcsEvent}s present in the message store.
+ *
+ * @hide
*/
public final class RcsEventQueryParams implements Parcelable {
/**
diff --git a/telephony/java/android/telephony/ims/RcsEventQueryResult.java b/telephony/java/android/telephony/ims/RcsEventQueryResult.java
index 92bda813f93e..d6347e3ec693 100644
--- a/telephony/java/android/telephony/ims/RcsEventQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsEventQueryResult.java
@@ -22,6 +22,8 @@ import java.util.List;
* The result of a {@link RcsMessageStore#getRcsEvents(RcsEventQueryParams)}
* call. This class allows getting the token for querying the next batch of events in order to
* prevent handling large amounts of data at once.
+ *
+ * @hide
*/
public class RcsEventQueryResult {
private RcsQueryContinuationToken mContinuationToken;
diff --git a/telephony/java/android/telephony/ims/RcsFileTransferCreationParams.java b/telephony/java/android/telephony/ims/RcsFileTransferCreationParams.java
index 14af8ea63a67..4742ba2730b6 100644
--- a/telephony/java/android/telephony/ims/RcsFileTransferCreationParams.java
+++ b/telephony/java/android/telephony/ims/RcsFileTransferCreationParams.java
@@ -24,6 +24,8 @@ import android.os.Parcelable;
* Pass an instance of this class to
* {@link RcsMessage#insertFileTransfer(RcsFileTransferCreationParams)} create an
* {@link RcsFileTransferPart} and save it into storage.
+ *
+ * @hide
*/
public final class RcsFileTransferCreationParams implements Parcelable {
private String mRcsFileTransferSessionId;
diff --git a/telephony/java/android/telephony/ims/RcsFileTransferPart.java b/telephony/java/android/telephony/ims/RcsFileTransferPart.java
index 9531c2e2f981..3816cd413722 100644
--- a/telephony/java/android/telephony/ims/RcsFileTransferPart.java
+++ b/telephony/java/android/telephony/ims/RcsFileTransferPart.java
@@ -26,6 +26,8 @@ import java.lang.annotation.RetentionPolicy;
/**
* A part of a composite {@link RcsMessage} that holds a file transfer. Please see Section 7
* (File Transfer) - GSMA RCC.71 (RCS Universal Profile Service Definition Document)
+ *
+ * @hide
*/
public class RcsFileTransferPart {
/**
diff --git a/telephony/java/android/telephony/ims/RcsGroupThread.java b/telephony/java/android/telephony/ims/RcsGroupThread.java
index 6e17bc2a685f..8cd633ba1edf 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThread.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThread.java
@@ -29,6 +29,8 @@ import java.util.Set;
* RcsGroupThread represents a single RCS conversation thread where {@link RcsParticipant}s can join
* or leave. Please see Section 6 (Group Chat) - GSMA RCC.71 (RCS Universal Profile Service
* Definition Document)
+ *
+ * @hide
*/
public class RcsGroupThread extends RcsThread {
/**
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
index 99086aaef676..4a6b963a143a 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadEvent.java
@@ -19,6 +19,8 @@ import android.annotation.NonNull;
/**
* An event that happened on an {@link RcsGroupThread}.
+ *
+ * @hide
*/
public abstract class RcsGroupThreadEvent extends RcsEvent {
private final int mRcsGroupThreadId;
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
index cbd762d3032b..3c6c74fac8e2 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadIconChangedEvent.java
@@ -22,6 +22,8 @@ import android.net.Uri;
/**
* An event that indicates an {@link RcsGroupThread}'s icon was changed. Please see R6-2-5 - GSMA
* RCC.71 (RCS Universal Profile Service Definition Document)
+ *
+ * @hide
*/
public final class RcsGroupThreadIconChangedEvent extends RcsGroupThreadEvent {
private final Uri mNewIcon;
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
index a2a4fab4f3d2..54032536601e 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadNameChangedEvent.java
@@ -21,6 +21,8 @@ import android.annotation.Nullable;
/**
* An event that indicates an {@link RcsGroupThread}'s name was changed. Please see R6-2-5 - GSMA
* RCC.71 (RCS Universal Profile Service Definition Document)
+ *
+ * @hide
*/
public final class RcsGroupThreadNameChangedEvent extends RcsGroupThreadEvent {
private final String mNewName;
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
index 183cd9a81431..48be479a1ac6 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantJoinedEvent.java
@@ -20,6 +20,8 @@ import android.annotation.NonNull;
/**
* An event that indicates an RCS participant has joined an {@link RcsThread}. Please see US6-3 -
* GSMA RCC.71 (RCS Universal Profile Service Definition Document)
+ *
+ * @hide
*/
public final class RcsGroupThreadParticipantJoinedEvent extends RcsGroupThreadEvent {
private final RcsParticipant mJoinedParticipantId;
diff --git a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
index c12549b5acbf..b724a3f2159f 100644
--- a/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
+++ b/telephony/java/android/telephony/ims/RcsGroupThreadParticipantLeftEvent.java
@@ -20,6 +20,8 @@ import android.annotation.NonNull;
/**
* An event that indicates an RCS participant has left an {@link RcsThread}. Please see US6-23 -
* GSMA RCC.71 (RCS Universal Profile Service Definition Document)
+ *
+ * @hide
*/
public final class RcsGroupThreadParticipantLeftEvent extends RcsGroupThreadEvent {
private RcsParticipant mLeavingParticipant;
diff --git a/telephony/java/android/telephony/ims/RcsIncomingMessage.java b/telephony/java/android/telephony/ims/RcsIncomingMessage.java
index 61911abd00c5..06e2a41accee 100644
--- a/telephony/java/android/telephony/ims/RcsIncomingMessage.java
+++ b/telephony/java/android/telephony/ims/RcsIncomingMessage.java
@@ -19,6 +19,8 @@ import android.annotation.WorkerThread;
/**
* This is a single instance of a message received over RCS.
+ *
+ * @hide
*/
public class RcsIncomingMessage extends RcsMessage {
/**
diff --git a/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.java b/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.java
index 61dedbc1578a..58dc1bc70424 100644
--- a/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.java
+++ b/telephony/java/android/telephony/ims/RcsIncomingMessageCreationParams.java
@@ -24,6 +24,8 @@ import android.os.Parcelable;
* {@link RcsIncomingMessageCreationParams} is a collection of parameters that should be passed
* into {@link RcsThread#addIncomingMessage(RcsIncomingMessageCreationParams)} to generate an
* {@link RcsIncomingMessage} on that {@link RcsThread}
+ *
+ * @hide
*/
public final class RcsIncomingMessageCreationParams extends RcsMessageCreationParams implements
Parcelable {
diff --git a/telephony/java/android/telephony/ims/RcsManager.java b/telephony/java/android/telephony/ims/RcsManager.java
index 22e4b2249c36..63dc1ac568bf 100644
--- a/telephony/java/android/telephony/ims/RcsManager.java
+++ b/telephony/java/android/telephony/ims/RcsManager.java
@@ -20,6 +20,8 @@ import android.content.Context;
/**
* The manager class for RCS related utilities.
+ *
+ * @hide
*/
@SystemService(Context.TELEPHONY_RCS_SERVICE)
public class RcsManager {
diff --git a/telephony/java/android/telephony/ims/RcsMessage.java b/telephony/java/android/telephony/ims/RcsMessage.java
index 32274131a5ad..b0d0d5a6a9bb 100644
--- a/telephony/java/android/telephony/ims/RcsMessage.java
+++ b/telephony/java/android/telephony/ims/RcsMessage.java
@@ -27,6 +27,8 @@ import java.util.Set;
/**
* This is a single instance of a message sent or received over RCS.
+ *
+ * @hide
*/
public abstract class RcsMessage {
/**
diff --git a/telephony/java/android/telephony/ims/RcsMessageCreationParams.java b/telephony/java/android/telephony/ims/RcsMessageCreationParams.java
index c46c605d861d..f0eea88ac8a9 100644
--- a/telephony/java/android/telephony/ims/RcsMessageCreationParams.java
+++ b/telephony/java/android/telephony/ims/RcsMessageCreationParams.java
@@ -27,6 +27,8 @@ import android.os.Parcel;
* {@link RcsThread#addIncomingMessage(RcsIncomingMessageCreationParams)} and
* {@link RcsThread#addOutgoingMessage(RcsOutgoingMessageCreationParams)} to create and persist
* {@link RcsMessage}s on an {@link RcsThread}
+ *
+ * @hide
*/
public class RcsMessageCreationParams {
// The globally unique id of the RcsMessage to be created.
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryParams.java b/telephony/java/android/telephony/ims/RcsMessageQueryParams.java
index 535a597f5e1e..6491ac9fad5f 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryParams.java
+++ b/telephony/java/android/telephony/ims/RcsMessageQueryParams.java
@@ -31,6 +31,8 @@ import java.security.InvalidParameterException;
* The parameters to pass into
* {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)} in order to select a
* subset of {@link RcsMessage}s present in the message store.
+ *
+ * @hide
*/
public final class RcsMessageQueryParams implements Parcelable {
/**
diff --git a/telephony/java/android/telephony/ims/RcsMessageQueryResult.java b/telephony/java/android/telephony/ims/RcsMessageQueryResult.java
index 3514b48e80a1..e4020c185fa3 100644
--- a/telephony/java/android/telephony/ims/RcsMessageQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsMessageQueryResult.java
@@ -32,6 +32,8 @@ import java.util.List;
* The result of a {@link RcsMessageStore#getRcsMessages(RcsMessageQueryParams)}
* call. This class allows getting the token for querying the next batch of messages in order to
* prevent handling large amounts of data at once.
+ *
+ * @hide
*/
public final class RcsMessageQueryResult implements Parcelable {
// The token to continue the query to get the next batch of results
diff --git a/telephony/java/android/telephony/ims/RcsMessageSnippet.java b/telephony/java/android/telephony/ims/RcsMessageSnippet.java
index b0b930c56e91..9064251f5021 100644
--- a/telephony/java/android/telephony/ims/RcsMessageSnippet.java
+++ b/telephony/java/android/telephony/ims/RcsMessageSnippet.java
@@ -23,6 +23,8 @@ import android.telephony.ims.RcsMessage.RcsMessageStatus;
/**
* An immutable summary of the latest {@link RcsMessage} on an {@link RcsThread}
+ *
+ * @hide
*/
public final class RcsMessageSnippet implements Parcelable {
private final String mText;
diff --git a/telephony/java/android/telephony/ims/RcsMessageStore.java b/telephony/java/android/telephony/ims/RcsMessageStore.java
index 31f2983dcf93..311165232158 100644
--- a/telephony/java/android/telephony/ims/RcsMessageStore.java
+++ b/telephony/java/android/telephony/ims/RcsMessageStore.java
@@ -26,6 +26,8 @@ import java.util.List;
/**
* RcsMessageStore is the application interface to RcsProvider and provides access methods to
* RCS related database tables.
+ *
+ * @hide
*/
public class RcsMessageStore {
/**
diff --git a/telephony/java/android/telephony/ims/RcsMessageStoreException.java b/telephony/java/android/telephony/ims/RcsMessageStoreException.java
index f25bb173be37..3b3fcf21dd7a 100644
--- a/telephony/java/android/telephony/ims/RcsMessageStoreException.java
+++ b/telephony/java/android/telephony/ims/RcsMessageStoreException.java
@@ -19,6 +19,8 @@ package android.telephony.ims;
/**
* An exception that happened on {@link RcsMessageStore} or one of the derived storage classes in
* {@link android.telephony.ims}
+ *
+ * @hide
*/
public class RcsMessageStoreException extends Exception {
diff --git a/telephony/java/android/telephony/ims/RcsOutgoingMessage.java b/telephony/java/android/telephony/ims/RcsOutgoingMessage.java
index 06fb83268afb..1b4bfe576ac6 100644
--- a/telephony/java/android/telephony/ims/RcsOutgoingMessage.java
+++ b/telephony/java/android/telephony/ims/RcsOutgoingMessage.java
@@ -23,6 +23,8 @@ import java.util.List;
/**
* This is a single instance of a message sent over RCS.
+ *
+ * @hide
*/
public class RcsOutgoingMessage extends RcsMessage {
RcsOutgoingMessage(int id) {
diff --git a/telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.java b/telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.java
index 979634a069df..81e3244d57e8 100644
--- a/telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.java
+++ b/telephony/java/android/telephony/ims/RcsOutgoingMessageCreationParams.java
@@ -23,6 +23,8 @@ import android.os.Parcelable;
* {@link RcsOutgoingMessageCreationParams} is a collection of parameters that should be passed
* into {@link RcsThread#addOutgoingMessage(RcsOutgoingMessageCreationParams)} to generate an
* {@link RcsOutgoingMessage} on that {@link RcsThread}
+ *
+ * @hide
*/
public final class RcsOutgoingMessageCreationParams extends RcsMessageCreationParams
implements Parcelable {
diff --git a/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java b/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java
index 1c87b13f0dfb..2db49c6d0dce 100644
--- a/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java
+++ b/telephony/java/android/telephony/ims/RcsOutgoingMessageDelivery.java
@@ -21,6 +21,8 @@ import android.annotation.WorkerThread;
/**
* This class holds the delivery information of an {@link RcsOutgoingMessage} for each
* {@link RcsParticipant} that the message was intended for.
+ *
+ * @hide
*/
public class RcsOutgoingMessageDelivery {
// The participant that this delivery is intended for
diff --git a/telephony/java/android/telephony/ims/RcsParticipant.java b/telephony/java/android/telephony/ims/RcsParticipant.java
index 7ba5d8e65f76..bcf134a71ea3 100644
--- a/telephony/java/android/telephony/ims/RcsParticipant.java
+++ b/telephony/java/android/telephony/ims/RcsParticipant.java
@@ -20,6 +20,8 @@ import android.annotation.WorkerThread;
/**
* RcsParticipant is an RCS capable contact that can participate in {@link RcsThread}s.
+ *
+ * @hide
*/
public class RcsParticipant {
// The row ID of this participant in the database
diff --git a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
index cc2613f9e684..61801f3fbf2c 100644
--- a/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
+++ b/telephony/java/android/telephony/ims/RcsParticipantAliasChangedEvent.java
@@ -21,6 +21,8 @@ import android.annotation.Nullable;
/**
* An event that indicates an {@link RcsParticipant}'s alias was changed. Please see US18-2 - GSMA
* RCC.71 (RCS Universal Profile Service Definition Document)
+ *
+ * @hide
*/
public final class RcsParticipantAliasChangedEvent extends RcsEvent {
// The participant that changed their alias
diff --git a/telephony/java/android/telephony/ims/RcsParticipantQueryParams.java b/telephony/java/android/telephony/ims/RcsParticipantQueryParams.java
index d24d079d7038..ada9b8ae9d1a 100644
--- a/telephony/java/android/telephony/ims/RcsParticipantQueryParams.java
+++ b/telephony/java/android/telephony/ims/RcsParticipantQueryParams.java
@@ -30,6 +30,8 @@ import java.security.InvalidParameterException;
* The parameters to pass into
* {@link RcsMessageStore#getRcsParticipants(RcsParticipantQueryParams)} in order to select a
* subset of {@link RcsThread}s present in the message store.
+ *
+ * @hide
*/
public final class RcsParticipantQueryParams implements Parcelable {
/**
diff --git a/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java b/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java
index 505f1a55d1f0..92e2fa78526a 100644
--- a/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsParticipantQueryResult.java
@@ -28,6 +28,8 @@ import java.util.List;
* The result of a {@link RcsMessageStore#getRcsParticipants(RcsParticipantQueryParams)}
* call. This class allows getting the token for querying the next batch of participants in order to
* prevent handling large amounts of data at once.
+ *
+ * @hide
*/
public final class RcsParticipantQueryResult implements Parcelable {
// A token for the caller to continue their query for the next batch of results
diff --git a/telephony/java/android/telephony/ims/RcsQueryContinuationToken.java b/telephony/java/android/telephony/ims/RcsQueryContinuationToken.java
index 08643de51d40..970c11078772 100644
--- a/telephony/java/android/telephony/ims/RcsQueryContinuationToken.java
+++ b/telephony/java/android/telephony/ims/RcsQueryContinuationToken.java
@@ -31,6 +31,8 @@ import java.lang.annotation.RetentionPolicy;
* @see RcsMessageQueryResult#getContinuationToken()
* @see RcsParticipantQueryResult#getContinuationToken()
* @see RcsThreadQueryResult#getContinuationToken()
+ *
+ * @hide
*/
public final class RcsQueryContinuationToken implements Parcelable {
/**
diff --git a/telephony/java/android/telephony/ims/RcsThread.java b/telephony/java/android/telephony/ims/RcsThread.java
index e015dd3e9c0a..cf1dc76fedfb 100644
--- a/telephony/java/android/telephony/ims/RcsThread.java
+++ b/telephony/java/android/telephony/ims/RcsThread.java
@@ -27,6 +27,8 @@ import com.android.internal.annotations.VisibleForTesting;
/**
* RcsThread represents a single RCS conversation thread. It holds messages that were sent and
* received and events that occurred on that thread.
+ *
+ * @hide
*/
public abstract class RcsThread {
/**
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryParams.java b/telephony/java/android/telephony/ims/RcsThreadQueryParams.java
index 05a5a3917691..81eee4081ace 100644
--- a/telephony/java/android/telephony/ims/RcsThreadQueryParams.java
+++ b/telephony/java/android/telephony/ims/RcsThreadQueryParams.java
@@ -35,6 +35,8 @@ import java.util.Set;
/**
* The parameters to pass into {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParams)} in
* order to select a subset of {@link RcsThread}s present in the message store.
+ *
+ * @hide
*/
public final class RcsThreadQueryParams implements Parcelable {
/**
diff --git a/telephony/java/android/telephony/ims/RcsThreadQueryResult.java b/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
index 1cac61d1aa64..9f2fba5caab4 100644
--- a/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
+++ b/telephony/java/android/telephony/ims/RcsThreadQueryResult.java
@@ -32,6 +32,8 @@ import java.util.List;
* The result of a {@link RcsMessageStore#getRcsThreads(RcsThreadQueryParams)}
* call. This class allows getting the token for querying the next batch of threads in order to
* prevent handling large amounts of data at once.
+ *
+ * @hide
*/
public final class RcsThreadQueryResult implements Parcelable {
// A token for the caller to continue their query for the next batch of results
diff --git a/telephony/java/com/android/internal/telephony/ISub.aidl b/telephony/java/com/android/internal/telephony/ISub.aidl
index 75a4d8227e23..79e0aa15b6ab 100755
--- a/telephony/java/com/android/internal/telephony/ISub.aidl
+++ b/telephony/java/com/android/internal/telephony/ISub.aidl
@@ -275,7 +275,7 @@ interface ISub {
void clearDefaultsForInactiveSubIds();
- int[] getActiveSubIdList();
+ int[] getActiveSubIdList(boolean visibleOnly);
int setSubscriptionProperty(int subId, String propKey, String propValue);
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index c54a60629ecb..d1838370d023 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1834,10 +1834,12 @@ interface ITelephony {
void setMultisimCarrierRestriction(boolean isMultisimCarrierRestricted);
/**
- * Returns if the usage of multiple SIM cards at the same time is restricted.
- * @hide
+ * Returns if the usage of multiple SIM cards at the same time is supported.
+ *
+ * @param callingPackage The package making the call.
+ * @return true if multisim is supported, false otherwise.
*/
- boolean isMultisimCarrierRestricted();
+ boolean isMultisimSupported(String callingPackage);
/**
* Switch configs to enable multi-sim or switch back to single-sim
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index 603c4c2870d7..030c3f495d0f 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -188,18 +188,17 @@ public interface TelephonyProperties
*/
static final String PROPERTY_IGNORE_NITZ = "telephony.test.ignore.nitz";
- /**
+ /**
* Property to set multi sim feature.
* Type: String(dsds, dsda)
*/
static final String PROPERTY_MULTI_SIM_CONFIG = "persist.radio.multisim.config";
- /**
+ /**
* Property to indicate if reboot is required when changing modems configurations
* Type: String(true, false) default is false; most devices don't need reboot
*/
- String PROPERTY_REBOOT_REQUIRED_ON_MODEM_CHANGE =
- "persist.radio.reboot_on_modem_change";
+ String PROPERTY_REBOOT_REQUIRED_ON_MODEM_CHANGE = "persist.radio.reboot_on_modem_change";
/**
* Property to store default subscription.
diff --git a/test-mock/api/test-current.txt b/test-mock/api/test-current.txt
index 0cb8f22d8070..6765316a304b 100644
--- a/test-mock/api/test-current.txt
+++ b/test-mock/api/test-current.txt
@@ -1,6 +1,10 @@
// Signature format: 2.0
package android.test.mock {
+ public class MockContext extends android.content.Context {
+ method public android.view.Display getDisplay();
+ }
+
@Deprecated public class MockPackageManager extends android.content.pm.PackageManager {
method public boolean arePermissionsIndividuallyControlled();
method public String getDefaultBrowserPackageNameAsUser(int);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/CustomRenderer.java b/tests/HwAccelerationTest/src/com/android/test/hwui/CustomRenderer.java
index 60bd60f0bfd1..fece8babb400 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/CustomRenderer.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/CustomRenderer.java
@@ -49,7 +49,7 @@ public class CustomRenderer extends Activity {
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mContent.setLeftTopRightBottom(0, 0, width, height);
- RecordingCanvas canvas = mContent.startRecording();
+ RecordingCanvas canvas = mContent.beginRecording();
canvas.drawColor(Color.WHITE);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.BLACK);
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/MyLittleTextureView.java b/tests/HwAccelerationTest/src/com/android/test/hwui/MyLittleTextureView.java
index 8bd7d797aea3..08d5d4fff50a 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/MyLittleTextureView.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/MyLittleTextureView.java
@@ -60,14 +60,14 @@ public class MyLittleTextureView extends Activity {
outline.setAlpha(1f);
childNode.setOutline(outline);
{
- Canvas canvas = childNode.startRecording();
+ Canvas canvas = childNode.beginRecording();
canvas.drawColor(Color.BLUE);
}
childNode.endRecording();
childNode.setElevation(20f);
{
- Canvas canvas = mContent.startRecording();
+ Canvas canvas = mContent.beginRecording();
canvas.drawColor(Color.WHITE);
canvas.enableZ();
canvas.drawRenderNode(childNode);
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
index 097d33d729f3..def5b8ead283 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTestUtils.java
@@ -345,7 +345,7 @@ class RollbackTestUtils {
PackageInstaller.SessionInfo info =
intent.getParcelableExtra(PackageInstaller.EXTRA_SESSION);
if (info != null && info.getSessionId() == sessionId) {
- if (info.isSessionReady() || info.isSessionFailed()) {
+ if (info.isStagedSessionReady() || info.isStagedSessionFailed()) {
try {
sessionStatus.put(info);
} catch (InterruptedException e) {
@@ -365,13 +365,13 @@ class RollbackTestUtils {
PackageInstaller.SessionInfo info = installer.getSessionInfo(sessionId);
try {
- if (info.isSessionReady() || info.isSessionFailed()) {
+ if (info.isStagedSessionReady() || info.isStagedSessionFailed()) {
sessionStatus.put(info);
}
info = sessionStatus.take();
context.unregisterReceiver(sessionUpdatedReceiver);
- if (info.isSessionFailed()) {
+ if (info.isStagedSessionFailed()) {
throw new AssertionError(info.getStagedSessionErrorMessage());
}
} catch (InterruptedException e) {
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index a10fb4ee1305..ed524f61e3bc 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -154,6 +154,7 @@ import android.test.mock.MockContentResolver;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
+import android.util.SparseArray;
import com.android.internal.net.VpnConfig;
import com.android.internal.util.ArrayUtils;
@@ -748,6 +749,10 @@ public class ConnectivityServiceTest {
// mExpectations is non-empty.
private boolean mExpectingAdditions;
+ // Used to collect the networks requests managed by this factory. This is a duplicate of
+ // the internal information stored in the NetworkFactory (which is private).
+ private SparseArray<NetworkRequest> mNetworkRequests = new SparseArray<>();
+
public MockNetworkFactory(Looper looper, Context context, String logTag,
NetworkCapabilities filter) {
super(looper, context, logTag, filter);
@@ -800,6 +805,7 @@ public class ConnectivityServiceTest {
}
// Add the request.
+ mNetworkRequests.put(request.requestId, request);
super.handleAddRequest(request, score, factorySerialNumber);
mExpectations.notify();
}
@@ -817,11 +823,17 @@ public class ConnectivityServiceTest {
}
// Remove the request.
+ mNetworkRequests.remove(request.requestId);
super.handleRemoveRequest(request);
mExpectations.notify();
}
}
+ // Trigger releasing the request as unfulfillable
+ public void triggerUnfulfillable(NetworkRequest r) {
+ super.releaseRequestAsUnfulfillableByAnyFactory(r);
+ }
+
private void assertNoExpectations() {
if (mExpectations.size() != 0) {
fail("Can't add expectation, " + mExpectations.size() + " already pending");
@@ -861,9 +873,11 @@ public class ConnectivityServiceTest {
assertEquals(msg, 0, count);
}
- public void waitForNetworkRequests(final int count) throws InterruptedException {
+ public SparseArray<NetworkRequest> waitForNetworkRequests(final int count)
+ throws InterruptedException {
waitForRequests();
assertEquals(count, getMyRequestCount());
+ return mNetworkRequests;
}
}
@@ -3533,6 +3547,55 @@ public class ConnectivityServiceTest {
networkCallback.assertNoCallback();
}
+ /**
+ * Validate the callback flow for a factory releasing a request as unfulfillable.
+ */
+ @Test
+ public void testUnfulfillableNetworkRequest() throws Exception {
+ NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
+ NetworkCapabilities.TRANSPORT_WIFI).build();
+ final TestNetworkCallback networkCallback = new TestNetworkCallback();
+
+ final HandlerThread handlerThread = new HandlerThread("testUnfulfillableNetworkRequest");
+ handlerThread.start();
+ NetworkCapabilities filter = new NetworkCapabilities()
+ .addTransportType(TRANSPORT_WIFI)
+ .addCapability(NET_CAPABILITY_INTERNET);
+ final MockNetworkFactory testFactory = new MockNetworkFactory(handlerThread.getLooper(),
+ mServiceContext, "testFactory", filter);
+ testFactory.setScoreFilter(40);
+
+ // Register the factory and expect it to receive the default request.
+ testFactory.expectAddRequestsWithScores(0);
+ testFactory.register();
+ SparseArray<NetworkRequest> requests = testFactory.waitForNetworkRequests(1);
+
+ assertEquals(1, requests.size()); // have 1 request at this point
+ int origRequestId = requests.valueAt(0).requestId;
+
+ // Now file the test request and expect it.
+ testFactory.expectAddRequestsWithScores(0);
+ mCm.requestNetwork(nr, networkCallback);
+ requests = testFactory.waitForNetworkRequests(2); // have 2 requests at this point
+
+ int newRequestId = 0;
+ for (int i = 0; i < requests.size(); ++i) {
+ if (requests.valueAt(i).requestId != origRequestId) {
+ newRequestId = requests.valueAt(i).requestId;
+ break;
+ }
+ }
+
+ // Simulate the factory releasing the request as unfulfillable and expect onUnavailable!
+ testFactory.expectRemoveRequests(1);
+ testFactory.triggerUnfulfillable(requests.get(newRequestId));
+ networkCallback.expectCallback(CallbackState.UNAVAILABLE, null);
+ testFactory.waitForRequests();
+
+ testFactory.unregister();
+ handlerThread.quit();
+ }
+
private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index 0032960ff93e..ffc1a92a88b0 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -44,6 +44,7 @@ constexpr int32_t kNonBreakingSpace = 0xa0;
Maybe<ResourceName> ToResourceName(
const android::ResTable::resource_name& name_in) {
+ // TODO: Remove this when ResTable and AssetManager(1) are removed from AAPT2
ResourceName name_out;
if (!name_in.package) {
return {};
@@ -79,6 +80,41 @@ Maybe<ResourceName> ToResourceName(
return name_out;
}
+Maybe<ResourceName> ToResourceName(const android::AssetManager2::ResourceName& name_in) {
+ ResourceName name_out;
+ if (!name_in.package) {
+ return {};
+ }
+
+ name_out.package = std::string(name_in.package, name_in.package_len);
+
+ const ResourceType* type;
+ if (name_in.type16) {
+ type = ParseResourceType(
+ util::Utf16ToUtf8(StringPiece16(name_in.type16, name_in.type_len)));
+ } else if (name_in.type) {
+ type = ParseResourceType(StringPiece(name_in.type, name_in.type_len));
+ } else {
+ return {};
+ }
+
+ if (!type) {
+ return {};
+ }
+
+ name_out.type = *type;
+
+ if (name_in.entry16) {
+ name_out.entry =
+ util::Utf16ToUtf8(StringPiece16(name_in.entry16, name_in.entry_len));
+ } else if (name_in.entry) {
+ name_out.entry = std::string(name_in.entry, name_in.entry_len);
+ } else {
+ return {};
+ }
+ return name_out;
+}
+
bool ParseResourceName(const StringPiece& str, ResourceNameRef* out_ref,
bool* out_private) {
if (str.empty()) {
diff --git a/tools/aapt2/ResourceUtils.h b/tools/aapt2/ResourceUtils.h
index e282fd58d261..a8a312005e4e 100644
--- a/tools/aapt2/ResourceUtils.h
+++ b/tools/aapt2/ResourceUtils.h
@@ -20,6 +20,7 @@
#include <functional>
#include <memory>
+#include "androidfw/AssetManager2.h"
#include "androidfw/ConfigDescription.h"
#include "androidfw/ResourceTypes.h"
#include "androidfw/StringPiece.h"
@@ -78,6 +79,12 @@ Maybe<ResourceName> ToResourceName(
const android::ResTable::resource_name& name);
/**
+ * Convert an android::AssetManager2::ResourceName to an aapt::ResourceName struct.
+ */
+Maybe<ResourceName> ToResourceName(
+ const android::AssetManager2::ResourceName& name_in);
+
+/**
* Returns a boolean value if the string is equal to TRUE, true, True, FALSE,
* false, or False.
*/
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index 22edd2f2055a..a7b8d2535e79 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -717,28 +717,20 @@ static bool LoadStableIdMap(IDiagnostics* diag, const std::string& path,
return true;
}
-static int32_t FindFrameworkAssetManagerCookie(const android::AssetManager& assets) {
+static android::ApkAssetsCookie FindFrameworkAssetManagerCookie(
+ const android::AssetManager2& assets) {
using namespace android;
// Find the system package (0x01). AAPT always generates attributes with the type 0x01, so
// we're looking for the first attribute resource in the system package.
- const ResTable& table = assets.getResources(true);
- Res_value val;
- ssize_t idx = table.getResource(0x01010000, &val, true);
- if (idx != NO_ERROR) {
- // Try as a bag.
- const ResTable::bag_entry* entry;
- ssize_t cnt = table.lockBag(0x01010000, &entry);
- if (cnt >= 0) {
- idx = entry->stringBlock;
- }
- table.unlockBag(entry);
- }
-
- if (idx < 0) {
- return 0;
- }
- return table.getTableCookie(idx);
+ Res_value val{};
+ ResTable_config config{};
+ uint32_t type_spec_flags;
+ ApkAssetsCookie idx = assets.GetResource(0x01010000, true /** may_be_bag */,
+ 0 /** density_override */, &val, &config,
+ &type_spec_flags);
+
+ return idx;
}
class Linker {
@@ -750,17 +742,17 @@ class Linker {
file_collection_(util::make_unique<io::FileCollection>()) {
}
- void ExtractCompileSdkVersions(android::AssetManager* assets) {
+ void ExtractCompileSdkVersions(android::AssetManager2* assets) {
using namespace android;
- int32_t cookie = FindFrameworkAssetManagerCookie(*assets);
- if (cookie == 0) {
+ android::ApkAssetsCookie cookie = FindFrameworkAssetManagerCookie(*assets);
+ if (cookie == android::kInvalidCookie) {
// No Framework assets loaded. Not a failure.
return;
}
std::unique_ptr<Asset> manifest(
- assets->openNonAsset(cookie, kAndroidManifestPath, Asset::AccessMode::ACCESS_BUFFER));
+ assets->OpenNonAsset(kAndroidManifestPath, cookie, Asset::AccessMode::ACCESS_BUFFER));
if (manifest == nullptr) {
// No errors.
return;
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index a844a43698e5..78e00746f6cb 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -20,9 +20,11 @@
#include "android-base/logging.h"
#include "android-base/stringprintf.h"
-#include "androidfw/AssetManager.h"
+#include "androidfw/Asset.h"
+#include "androidfw/AssetManager2.h"
#include "androidfw/ConfigDescription.h"
#include "androidfw/ResourceTypes.h"
+#include "androidfw/ResourceUtils.h"
#include "NameMangler.h"
#include "Resource.h"
@@ -30,6 +32,7 @@
#include "ValueVisitor.h"
#include "util/Util.h"
+using ::android::ApkAssets;
using ::android::ConfigDescription;
using ::android::StringPiece;
using ::android::StringPiece16;
@@ -214,51 +217,75 @@ std::unique_ptr<SymbolTable::Symbol> ResourceTableSymbolSource::FindByName(
}
bool AssetManagerSymbolSource::AddAssetPath(const StringPiece& path) {
- int32_t cookie = 0;
- return assets_.addAssetPath(android::String8(path.data(), path.size()), &cookie);
+ if (std::unique_ptr<const ApkAssets> apk = ApkAssets::Load(path.data())) {
+ apk_assets_.push_back(std::move(apk));
+
+ std::vector<const ApkAssets*> apk_assets;
+ for (const std::unique_ptr<const ApkAssets>& apk_asset : apk_assets_) {
+ apk_assets.push_back(apk_asset.get());
+ }
+
+ asset_manager_.SetApkAssets(apk_assets, true /* invalidate_caches */,
+ false /* filter_incompatible_configs */);
+ return true;
+ }
+ return false;
}
std::map<size_t, std::string> AssetManagerSymbolSource::GetAssignedPackageIds() const {
std::map<size_t, std::string> package_map;
- const android::ResTable& table = assets_.getResources(false);
- const size_t package_count = table.getBasePackageCount();
- for (size_t i = 0; i < package_count; i++) {
- package_map[table.getBasePackageId(i)] =
- util::Utf16ToUtf8(android::StringPiece16(table.getBasePackageName(i).string()));
- }
+ asset_manager_.ForEachPackage([&package_map](const std::string& name, uint8_t id) -> bool {
+ package_map.insert(std::make_pair(id, name));
+ return true;
+ });
+
return package_map;
}
bool AssetManagerSymbolSource::IsPackageDynamic(uint32_t packageId) const {
- return assets_.getResources(false).isPackageDynamic(packageId);
+ if (packageId == 0) {
+ return true;
+ }
+
+ for (const std::unique_ptr<const ApkAssets>& assets : apk_assets_) {
+ for (const std::unique_ptr<const android::LoadedPackage>& loaded_package
+ : assets->GetLoadedArsc()->GetPackages()) {
+ if (packageId == loaded_package->GetPackageId() && loaded_package->IsDynamic()) {
+ return true;
+ }
+ }
+ }
+
+ return false;
}
static std::unique_ptr<SymbolTable::Symbol> LookupAttributeInTable(
- const android::ResTable& table, ResourceId id) {
- // Try as a bag.
- const android::ResTable::bag_entry* entry;
- ssize_t count = table.lockBag(id.id, &entry);
- if (count < 0) {
- table.unlockBag(entry);
+ android::AssetManager2& am, ResourceId id) {
+ if (am.GetApkAssets().empty()) {
+ return {};
+ }
+
+ const android::ResolvedBag* bag = am.GetBag(id.id);
+ if (bag == nullptr) {
return nullptr;
}
// We found a resource.
std::unique_ptr<SymbolTable::Symbol> s = util::make_unique<SymbolTable::Symbol>(id);
- // Check to see if it is an attribute.
- for (size_t i = 0; i < (size_t)count; i++) {
- if (entry[i].map.name.ident == android::ResTable_map::ATTR_TYPE) {
- s->attribute = std::make_shared<Attribute>(entry[i].map.value.data);
+ const size_t count = bag->entry_count;
+ for (uint32_t i = 0; i < count; i++) {
+ if (bag->entries[i].key == android::ResTable_map::ATTR_TYPE) {
+ s->attribute = std::make_shared<Attribute>(bag->entries[i].value.data);
break;
}
}
if (s->attribute) {
- for (size_t i = 0; i < (size_t)count; i++) {
- const android::ResTable_map& map_entry = entry[i].map;
- if (Res_INTERNALID(map_entry.name.ident)) {
- switch (map_entry.name.ident) {
+ for (size_t i = 0; i < count; i++) {
+ const android::ResolvedBag::Entry& map_entry = bag->entries[i];
+ if (Res_INTERNALID(map_entry.key)) {
+ switch (map_entry.key) {
case android::ResTable_map::ATTR_MIN:
s->attribute->min_int = static_cast<int32_t>(map_entry.value.data);
break;
@@ -269,74 +296,65 @@ static std::unique_ptr<SymbolTable::Symbol> LookupAttributeInTable(
continue;
}
- android::ResTable::resource_name entry_name;
- if (!table.getResourceName(map_entry.name.ident, false, &entry_name)) {
- table.unlockBag(entry);
+ android::AssetManager2::ResourceName name;
+ if (!am.GetResourceName(map_entry.key, &name)) {
return nullptr;
}
- Maybe<ResourceName> parsed_name = ResourceUtils::ToResourceName(entry_name);
+ Maybe<ResourceName> parsed_name = ResourceUtils::ToResourceName(name);
if (!parsed_name) {
return nullptr;
}
Attribute::Symbol symbol;
symbol.symbol.name = parsed_name.value();
- symbol.symbol.id = ResourceId(map_entry.name.ident);
+ symbol.symbol.id = ResourceId(map_entry.key);
symbol.value = map_entry.value.data;
s->attribute->symbols.push_back(std::move(symbol));
}
}
- table.unlockBag(entry);
+
return s;
}
std::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::FindByName(
const ResourceName& name) {
- const android::ResTable& table = assets_.getResources(false);
-
- const std::u16string package16 = util::Utf8ToUtf16(name.package);
- const std::u16string type16 = util::Utf8ToUtf16(to_string(name.type));
- const std::u16string entry16 = util::Utf8ToUtf16(name.entry);
- const std::u16string mangled_entry16 =
- util::Utf8ToUtf16(NameMangler::MangleEntry(name.package, name.entry));
+ const std::string mangled_entry = NameMangler::MangleEntry(name.package, name.entry);
+ bool found = false;
+ ResourceId res_id = 0;
uint32_t type_spec_flags;
- ResourceId res_id;
// There can be mangled resources embedded within other packages. Here we will
// look into each package and look-up the mangled name until we find the resource.
- const size_t count = table.getBasePackageCount();
- for (size_t i = 0; i < count; i++) {
- const android::String16 package_name = table.getBasePackageName(i);
- StringPiece16 real_package16 = package16;
- StringPiece16 real_entry16 = entry16;
- std::u16string scratch_entry16;
- if (StringPiece16(package_name) != package16) {
- real_entry16 = mangled_entry16;
- real_package16 = package_name.string();
+ asset_manager_.ForEachPackage([&](const std::string& package_name, uint8_t id) -> bool {
+ ResourceName real_name(name.package, name.type, name.entry);
+
+ if (package_name != name.package) {
+ real_name.entry = mangled_entry;
+ real_name.package = package_name;
}
- type_spec_flags = 0;
- res_id = table.identifierForName(real_entry16.data(), real_entry16.size(), type16.data(),
- type16.size(), real_package16.data(), real_package16.size(),
- &type_spec_flags);
- if (res_id.is_valid()) {
- break;
+ res_id = asset_manager_.GetResourceId(real_name.to_string());
+ if (res_id.is_valid() && asset_manager_.GetResourceFlags(res_id.id, &type_spec_flags)) {
+ found = true;
+ return false;
}
- }
- if (!res_id.is_valid()) {
+ return true;
+ });
+
+ if (!found) {
return {};
}
std::unique_ptr<SymbolTable::Symbol> s;
if (name.type == ResourceType::kAttr) {
- s = LookupAttributeInTable(table, res_id);
+ s = LookupAttributeInTable(asset_manager_, res_id);
} else {
s = util::make_unique<SymbolTable::Symbol>();
s->id = res_id;
- s->is_dynamic = table.isResourceDynamic(res_id.id);
+ s->is_dynamic = IsPackageDynamic(ResourceId(res_id).package_id());
}
if (s) {
@@ -346,13 +364,13 @@ std::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::FindByName(
return {};
}
-static Maybe<ResourceName> GetResourceName(const android::ResTable& table,
+static Maybe<ResourceName> GetResourceName(android::AssetManager2& am,
ResourceId id) {
- android::ResTable::resource_name res_name = {};
- if (!table.getResourceName(id.id, true, &res_name)) {
+ android::AssetManager2::ResourceName name;
+ if (!am.GetResourceName(id.id, &name)) {
return {};
}
- return ResourceUtils::ToResourceName(res_name);
+ return ResourceUtils::ToResourceName(name);
}
std::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::FindById(
@@ -361,22 +379,30 @@ std::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::FindById(
// Exit early and avoid the error logs from AssetManager.
return {};
}
- const android::ResTable& table = assets_.getResources(false);
- Maybe<ResourceName> maybe_name = GetResourceName(table, id);
+
+ if (apk_assets_.empty()) {
+ return {};
+ }
+
+ Maybe<ResourceName> maybe_name = GetResourceName(asset_manager_, id);
if (!maybe_name) {
return {};
}
+
uint32_t type_spec_flags = 0;
- table.getResourceFlags(id.id, &type_spec_flags);
+ if (!asset_manager_.GetResourceFlags(id.id, &type_spec_flags)) {
+ return {};
+ }
+ ResourceName& name = maybe_name.value();
std::unique_ptr<SymbolTable::Symbol> s;
- if (maybe_name.value().type == ResourceType::kAttr) {
- s = LookupAttributeInTable(table, id);
+ if (name.type == ResourceType::kAttr) {
+ s = LookupAttributeInTable(asset_manager_, id);
} else {
s = util::make_unique<SymbolTable::Symbol>();
s->id = id;
- s->is_dynamic = table.isResourceDynamic(id.id);
+ s->is_dynamic = IsPackageDynamic(ResourceId(id).package_id());
}
if (s) {
diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h
index 2d8bd02a3799..6997cd6714a8 100644
--- a/tools/aapt2/process/SymbolTable.h
+++ b/tools/aapt2/process/SymbolTable.h
@@ -22,7 +22,8 @@
#include <vector>
#include "android-base/macros.h"
-#include "androidfw/AssetManager.h"
+#include "androidfw/Asset.h"
+#include "androidfw/AssetManager2.h"
#include "utils/JenkinsHash.h"
#include "utils/LruCache.h"
@@ -201,12 +202,13 @@ class AssetManagerSymbolSource : public ISymbolSource {
std::unique_ptr<SymbolTable::Symbol> FindByReference(
const Reference& ref) override;
- android::AssetManager* GetAssetManager() {
- return &assets_;
+ android::AssetManager2* GetAssetManager() {
+ return &asset_manager_;
}
private:
- android::AssetManager assets_;
+ android::AssetManager2 asset_manager_;
+ std::vector<std::unique_ptr<const android::ApkAssets>> apk_assets_;
DISALLOW_COPY_AND_ASSIGN(AssetManagerSymbolSource);
};
diff --git a/tools/aapt2/process/SymbolTable_test.cpp b/tools/aapt2/process/SymbolTable_test.cpp
index 1f59d7034300..ddc210189793 100644
--- a/tools/aapt2/process/SymbolTable_test.cpp
+++ b/tools/aapt2/process/SymbolTable_test.cpp
@@ -76,40 +76,54 @@ TEST(SymbolTableTest, FindByName) {
EXPECT_THAT(symbol_table.FindByName(test::ParseNameOrDie("com.android.lib:id/foo")), NotNull());
}
-TEST(SymbolTableTest, FindByNameWhenSymbolIsMangledInResTable) {
+using SymbolTableTestFixture = CommandTestFixture;
+TEST_F(SymbolTableTestFixture, FindByNameWhenSymbolIsMangledInResTable) {
using namespace android;
-
- std::unique_ptr<IAaptContext> context =
- test::ContextBuilder()
- .SetCompilationPackage("com.android.app")
- .SetPackageId(0x7f)
- .SetPackageType(PackageType::kApp)
- .SetMinSdkVersion(SDK_LOLLIPOP_MR1)
- .SetNameManglerPolicy(NameManglerPolicy{"com.android.app"})
- .Build();
-
- // Create a ResourceTable with a mangled resource, simulating a static library being merged into
- // the main application package.
- std::unique_ptr<ResourceTable> table =
- test::ResourceTableBuilder()
- .AddSimple("com.android.app:id/" + NameMangler::MangleEntry("com.android.lib", "foo"),
- ResourceId(0x7f020000))
- .AddSimple("com.android.app:id/bar", ResourceId(0x7f020001))
- .Build();
-
- BigBuffer buffer(1024u);
- TableFlattener flattener({}, &buffer);
- ASSERT_TRUE(flattener.Consume(context.get(), table.get()));
-
- std::unique_ptr<uint8_t[]> data = util::Copy(buffer);
+ StdErrDiagnostics diag;
+
+ // Create a static library.
+ const std::string static_lib_compiled_files_dir = GetTestPath("static-lib-compiled");
+ ASSERT_TRUE(CompileFile(GetTestPath("res/values/values.xml"),
+ R"(<?xml version="1.0" encoding="utf-8"?>
+ <resources>
+ <item type="id" name="foo"/>
+ </resources>)",
+ static_lib_compiled_files_dir, &diag));
+
+ const std::string static_lib_apk = GetTestPath("static_lib.apk");
+ std::vector<std::string> link_args = {
+ "--manifest", GetDefaultManifest("com.android.lib"),
+ "--min-sdk-version", "22",
+ "--static-lib",
+ "-o", static_lib_apk,
+ };
+ ASSERT_TRUE(Link(link_args, static_lib_compiled_files_dir, &diag));
+
+ // Merge the static library into the main application package. The static library resources will
+ // be mangled with the library package name.
+ const std::string app_compiled_files_dir = GetTestPath("app-compiled");
+ ASSERT_TRUE(CompileFile(GetTestPath("res/values/values.xml"),
+ R"(<?xml version="1.0" encoding="utf-8"?>
+ <resources>
+ <item type="id" name="bar"/>
+ </resources>)",
+ app_compiled_files_dir, &diag));
+
+ const std::string out_apk = GetTestPath("out.apk");
+ link_args = {
+ "--manifest", GetDefaultManifest("com.android.app"),
+ "--min-sdk-version", "22",
+ "-o", out_apk,
+ static_lib_apk
+ };
+ ASSERT_TRUE(Link(link_args, app_compiled_files_dir, &diag));
// Construct the test AssetManager.
auto asset_manager_source = util::make_unique<AssetManagerSymbolSource>();
- ResTable& res_table = const_cast<ResTable&>(
- asset_manager_source->GetAssetManager()->getResources(false /*required*/));
- ASSERT_THAT(res_table.add(data.get(), buffer.size()), Eq(NO_ERROR));
+ asset_manager_source->AddAssetPath(out_apk);
- SymbolTable symbol_table(context->GetNameMangler());
+ NameMangler name_mangler(NameManglerPolicy{"com.android.app"});
+ SymbolTable symbol_table(&name_mangler);
symbol_table.AppendSource(std::move(asset_manager_source));
EXPECT_THAT(symbol_table.FindByName(test::ParseNameOrDie("com.android.lib:id/foo")), NotNull());
diff --git a/tools/aapt2/test/Fixture.cpp b/tools/aapt2/test/Fixture.cpp
index 3fcdfb70a524..a51b4a4649f1 100644
--- a/tools/aapt2/test/Fixture.cpp
+++ b/tools/aapt2/test/Fixture.cpp
@@ -37,6 +37,8 @@ using testing::Ne;
namespace aapt {
+const char* CommandTestFixture::kDefaultPackageName = "com.aapt.command.test";
+
void ClearDirectory(const android::StringPiece& path) {
const std::string root_dir = path.to_string();
std::unique_ptr<DIR, decltype(closedir)*> dir(opendir(root_dir.data()), closedir);
@@ -124,12 +126,12 @@ bool CommandTestFixture::Link(const std::vector<std::string>& args,
return LinkCommand(diag).Execute(link_args, &std::cerr) == 0;
}
-std::string CommandTestFixture::GetDefaultManifest() {
+std::string CommandTestFixture::GetDefaultManifest(const char* package_name) {
const std::string manifest_file = GetTestPath("AndroidManifest.xml");
- CHECK(WriteFile(manifest_file, R"(
+ CHECK(WriteFile(manifest_file, android::base::StringPrintf(R"(
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.aapt.command.test">
- </manifest>)"));
+ package="%s">
+ </manifest>)", package_name)));
return manifest_file;
}
diff --git a/tools/aapt2/test/Fixture.h b/tools/aapt2/test/Fixture.h
index 3079c757f61a..fce2aebfecaa 100644
--- a/tools/aapt2/test/Fixture.h
+++ b/tools/aapt2/test/Fixture.h
@@ -81,7 +81,7 @@ class CommandTestFixture : public TestDirectoryFixture {
IDiagnostics* diag);
// Creates a minimal android manifest within the test directory and returns the file path.
- std::string GetDefaultManifest();
+ std::string GetDefaultManifest(const char* package_name = kDefaultPackageName);
// Returns pointer to data inside APK files
std::unique_ptr<io::IData> OpenFileAsData(LoadedApk* apk,
@@ -91,6 +91,7 @@ class CommandTestFixture : public TestDirectoryFixture {
void AssertLoadXml(LoadedApk* apk, const io::IData* data,
android::ResXMLTree* out_tree);
+ static const char* kDefaultPackageName;
private:
DISALLOW_COPY_AND_ASSIGN(CommandTestFixture);
};
diff --git a/tools/aapt2/util/Files.cpp b/tools/aapt2/util/Files.cpp
index 604b2575daa1..5d57de6a9fb1 100644
--- a/tools/aapt2/util/Files.cpp
+++ b/tools/aapt2/util/Files.cpp
@@ -102,12 +102,21 @@ FileType GetFileType(const std::string& path) {
#endif
bool mkdirs(const std::string& path) {
- #ifdef _WIN32
- // Start after the drive path if present. Calling mkdir with only the drive will cause an error.
- size_t current_pos = 1u;
- if (path.size() >= 3 && path[1] == ':' &&
- (path[2] == '\\' || path[2] == '/')) {
- current_pos = 3u;
+ #ifdef _WIN32
+ // Start after the long path prefix if present.
+ bool require_drive = false;
+ size_t current_pos = 0u;
+ if (util::StartsWith(path, R"(\\?\)")) {
+ require_drive = true;
+ current_pos = 4u;
+ }
+
+ // Start after the drive path if present.
+ if (path.size() >= 3 && path[current_pos + 1] == ':' &&
+ (path[current_pos + 2] == '\\' || path[current_pos + 2] == '/')) {
+ current_pos += 3u;
+ } else if (require_drive) {
+ return false;
}
#else
// Start after the first character so that we don't consume the root '/'.
diff --git a/tools/aapt2/util/Files_test.cpp b/tools/aapt2/util/Files_test.cpp
index 202cc261ad89..6c380808c0df 100644
--- a/tools/aapt2/util/Files_test.cpp
+++ b/tools/aapt2/util/Files_test.cpp
@@ -19,6 +19,7 @@
#include <sstream>
#include "android-base/stringprintf.h"
+#include "android-base/utf8.h"
#include "test/Test.h"
@@ -65,5 +66,40 @@ TEST_F(FilesTest, AppendPathWithLeadingOrTrailingSeparators) {
EXPECT_EQ(expected_path_, base);
}
+#ifdef _WIN32
+TEST_F(FilesTest, WindowsMkdirsLongPath) {
+ // Creating directory paths longer than the Windows maximum path length (260 charatcers) should
+ // succeed.
+ const std::string kDirName = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+ const size_t kRecursiveDepth = 10u;
+
+ // Recursively create the test file path and clean up the created directories after the files have
+ // been created.
+ std::function<void(std::string, size_t)> CreateResursiveDirs =
+ [&kDirName, &CreateResursiveDirs](std::string current_path, const size_t n) -> void {
+ AppendPath(&current_path, kDirName);
+
+ if (n == 0) {
+ ASSERT_TRUE(file::mkdirs(current_path)) << "Failed to create path " << current_path;
+ } else {
+ CreateResursiveDirs(current_path, n - 1);
+ }
+
+ // Clean up the created directories.
+ _rmdir(current_path.data());
+ };
+
+ CreateResursiveDirs(
+ android::base::StringPrintf(R"(\\?\%s)", android::base::GetExecutableDirectory().data()),
+ kRecursiveDepth);
+}
+
+TEST_F(FilesTest, WindowsMkdirsLongPathMissingDrive) {
+ ASSERT_FALSE(file::mkdirs(R"(\\?\local\path\to\file)"));
+ ASSERT_FALSE(file::mkdirs(R"(\\?\:local\path\to\file)"));
+ ASSERT_FALSE(file::mkdirs(R"(\\?\\local\path\to\file)"));
+}
+#endif
+
} // namespace files
} // namespace aapt
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index af9fdfbd364d..089b59a2704c 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -137,6 +137,16 @@ public class WifiInfo implements Parcelable {
private boolean mOsuAp;
/**
+ * Fully qualified domain name of a Passpoint configuration
+ */
+ private String mFqdn;
+
+ /**
+ * Name of Passpoint credential provider
+ */
+ private String mProviderFriendlyName;
+
+ /**
* If connected to a network suggestion or specifier, store the package name of the app,
* else null.
*/
@@ -223,6 +233,8 @@ public class WifiInfo implements Parcelable {
setEphemeral(false);
setOsuAp(false);
setNetworkSuggestionOrSpecifierPackageName(null);
+ setFQDN(null);
+ setProviderFriendlyName(null);
txBad = 0;
txSuccess = 0;
rxSuccess = 0;
@@ -257,6 +269,8 @@ public class WifiInfo implements Parcelable {
mNetworkSuggestionOrSpecifierPackageName =
source.mNetworkSuggestionOrSpecifierPackageName;
mOsuAp = source.mOsuAp;
+ mFqdn = source.mFqdn;
+ mProviderFriendlyName = source.mProviderFriendlyName;
txBad = source.txBad;
txRetries = source.txRetries;
txSuccess = source.txSuccess;
@@ -504,6 +518,34 @@ public class WifiInfo implements Parcelable {
}
/** {@hide} */
+ @SystemApi
+ public boolean isPasspointAp() {
+ return mFqdn != null && mProviderFriendlyName != null;
+ }
+
+ /** {@hide} */
+ public void setFQDN(@Nullable String fqdn) {
+ mFqdn = fqdn;
+ }
+
+ /** {@hide} */
+ @SystemApi
+ public @Nullable String getFqdn() {
+ return mFqdn;
+ }
+
+ /** {@hide} */
+ public void setProviderFriendlyName(@Nullable String providerFriendlyName) {
+ mProviderFriendlyName = providerFriendlyName;
+ }
+
+ /** {@hide} */
+ @SystemApi
+ public @Nullable String getProviderFriendlyName() {
+ return mProviderFriendlyName;
+ }
+
+ /** {@hide} */
public void setNetworkSuggestionOrSpecifierPackageName(@Nullable String packageName) {
mNetworkSuggestionOrSpecifierPackageName = packageName;
}
@@ -677,6 +719,8 @@ public class WifiInfo implements Parcelable {
mSupplicantState.writeToParcel(dest, flags);
dest.writeInt(mOsuAp ? 1 : 0);
dest.writeString(mNetworkSuggestionOrSpecifierPackageName);
+ dest.writeString(mFqdn);
+ dest.writeString(mProviderFriendlyName);
}
/** Implement the Parcelable interface {@hide} */
@@ -716,6 +760,8 @@ public class WifiInfo implements Parcelable {
info.mSupplicantState = SupplicantState.CREATOR.createFromParcel(in);
info.mOsuAp = in.readInt() != 0;
info.mNetworkSuggestionOrSpecifierPackageName = in.readString();
+ info.mFqdn = in.readString();
+ info.mProviderFriendlyName = in.readString();
return info;
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 7caace6ec854..6c645fc8ce5d 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -1738,10 +1738,7 @@ public class WifiManager {
* @deprecated This is no longer supported.
*/
@Deprecated
- @RequiresPermission(anyOf = {
- android.Manifest.permission.NETWORK_SETTINGS,
- android.Manifest.permission.NETWORK_SETUP_WIZARD
- })
+ @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
public void removePasspointConfiguration(String fqdn) {
try {
if (!mService.removePasspointConfiguration(fqdn, mContext.getOpPackageName())) {
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
index 22dc2ed32083..ab7bb688f5ea 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pDevice.java
@@ -17,14 +17,13 @@
package android.net.wifi.p2p;
import android.annotation.UnsupportedAppUsage;
-import android.os.Parcelable;
import android.os.Parcel;
+import android.os.Parcelable;
import android.util.Log;
import java.util.Objects;
-
-import java.util.regex.Pattern;
import java.util.regex.Matcher;
+import java.util.regex.Pattern;
/**
* A class representing a Wi-Fi p2p device
@@ -360,7 +359,9 @@ public class WifiP2pDevice implements Parcelable {
deviceCapability = source.deviceCapability;
groupCapability = source.groupCapability;
status = source.status;
- wfdInfo = new WifiP2pWfdInfo(source.wfdInfo);
+ if (source.wfdInfo != null) {
+ wfdInfo = new WifiP2pWfdInfo(source.wfdInfo);
+ }
}
}
diff --git a/wifi/tests/src/android/net/wifi/WifiInfoTest.java b/wifi/tests/src/android/net/wifi/WifiInfoTest.java
index 948dcfa47f59..b3034965b5fc 100644
--- a/wifi/tests/src/android/net/wifi/WifiInfoTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiInfoTest.java
@@ -36,6 +36,8 @@ public class WifiInfoTest {
private static final long TEST_TX_BAD = 3;
private static final long TEST_RX_SUCCESS = 4;
private static final String TEST_PACKAGE_NAME = "com.test.example";
+ private static final String TEST_FQDN = "test.com";
+ private static final String TEST_PROVIDER_NAME = "test";
/**
* Verify parcel write/read with WifiInfo.
@@ -49,6 +51,8 @@ public class WifiInfoTest {
writeWifiInfo.rxSuccess = TEST_RX_SUCCESS;
writeWifiInfo.setTrusted(true);
writeWifiInfo.setOsuAp(true);
+ writeWifiInfo.setFQDN(TEST_FQDN);
+ writeWifiInfo.setProviderFriendlyName(TEST_PROVIDER_NAME);
writeWifiInfo.setNetworkSuggestionOrSpecifierPackageName(TEST_PACKAGE_NAME);
Parcel parcel = Parcel.obtain();
@@ -64,6 +68,9 @@ public class WifiInfoTest {
assertEquals(TEST_RX_SUCCESS, readWifiInfo.rxSuccess);
assertTrue(readWifiInfo.isTrusted());
assertTrue(readWifiInfo.isOsuAp());
+ assertTrue(readWifiInfo.isPasspointAp());
assertEquals(TEST_PACKAGE_NAME, readWifiInfo.getNetworkSuggestionOrSpecifierPackageName());
+ assertEquals(TEST_FQDN, readWifiInfo.getFqdn());
+ assertEquals(TEST_PROVIDER_NAME, readWifiInfo.getProviderFriendlyName());
}
}
diff --git a/wifi/tests/src/android/net/wifi/p2p/WifiP2pDeviceTest.java b/wifi/tests/src/android/net/wifi/p2p/WifiP2pDeviceTest.java
index f61e6b759085..17ee75594c2f 100644
--- a/wifi/tests/src/android/net/wifi/p2p/WifiP2pDeviceTest.java
+++ b/wifi/tests/src/android/net/wifi/p2p/WifiP2pDeviceTest.java
@@ -30,6 +30,31 @@ import org.junit.Test;
public class WifiP2pDeviceTest {
/**
+ * Compare two p2p devices.
+ *
+ * @param devA is the first device to be compared
+ * @param devB is the second device to be compared
+ */
+ private void compareWifiP2pDevices(WifiP2pDevice devA, WifiP2pDevice devB) {
+ assertEquals(devA.deviceName, devB.deviceName);
+ assertEquals(devA.deviceAddress, devB.deviceAddress);
+ assertEquals(devA.primaryDeviceType, devB.primaryDeviceType);
+ assertEquals(devA.secondaryDeviceType, devB.secondaryDeviceType);
+ assertEquals(devA.wpsConfigMethodsSupported, devB.wpsConfigMethodsSupported);
+ assertEquals(devA.deviceCapability, devB.deviceCapability);
+ assertEquals(devA.groupCapability, devB.groupCapability);
+ assertEquals(devA.status, devB.status);
+ if (devA.wfdInfo != null) {
+ assertEquals(devA.wfdInfo.isWfdEnabled(), devB.wfdInfo.isWfdEnabled());
+ assertEquals(devA.wfdInfo.getDeviceInfoHex(), devB.wfdInfo.getDeviceInfoHex());
+ assertEquals(devA.wfdInfo.getControlPort(), devB.wfdInfo.getControlPort());
+ assertEquals(devA.wfdInfo.getMaxThroughput(), devB.wfdInfo.getMaxThroughput());
+ } else {
+ assertEquals(devA.wfdInfo, devB.wfdInfo);
+ }
+ }
+
+ /**
* Check equals and hashCode consistency
*/
@Test
@@ -42,4 +67,52 @@ public class WifiP2pDeviceTest {
assertTrue(dev_a.equals(dev_b));
assertEquals(dev_a.hashCode(), dev_b.hashCode());
}
+
+ /**
+ * Check the copy constructor with default values.
+ */
+ @Test
+ public void testCopyConstructorWithDefaultValues() throws Exception {
+ WifiP2pDevice device = new WifiP2pDevice();
+ WifiP2pDevice copy = new WifiP2pDevice(device);
+ compareWifiP2pDevices(device, copy);
+ }
+
+ /**
+ * Check the copy constructor with updated values.
+ */
+ @Test
+ public void testCopyConstructorWithUpdatedValues() throws Exception {
+ WifiP2pDevice device = new WifiP2pDevice();
+ device.deviceName = "deviceName";
+ device.deviceAddress = "11:22:33:44:55:66";
+ device.primaryDeviceType = "primaryDeviceType";
+ device.secondaryDeviceType = "secondaryDeviceType";
+ device.wpsConfigMethodsSupported = 0x0008;
+ device.deviceCapability = 1;
+ device.groupCapability = 1;
+ device.status = WifiP2pDevice.CONNECTED;
+ device.wfdInfo = new WifiP2pWfdInfo();
+ WifiP2pDevice copy = new WifiP2pDevice(device);
+ compareWifiP2pDevices(device, copy);
+ }
+
+ /**
+ * Check the copy constructor when the wfdInfo of the source object is null.
+ */
+ @Test
+ public void testCopyConstructorWithNullWfdInfo() throws Exception {
+ WifiP2pDevice device = new WifiP2pDevice();
+ device.deviceName = "deviceName";
+ device.deviceAddress = "11:22:33:44:55:66";
+ device.primaryDeviceType = "primaryDeviceType";
+ device.secondaryDeviceType = "secondaryDeviceType";
+ device.wpsConfigMethodsSupported = 0x0008;
+ device.deviceCapability = 1;
+ device.groupCapability = 1;
+ device.status = WifiP2pDevice.CONNECTED;
+ device.wfdInfo = null;
+ WifiP2pDevice copy = new WifiP2pDevice(device);
+ compareWifiP2pDevices(device, copy);
+ }
}