summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt52
-rw-r--r--api/system-current.txt125
-rw-r--r--cmds/idmap2/Android.bp74
-rw-r--r--cmds/idmap2/idmap2/Create.cpp7
-rw-r--r--cmds/idmap2/idmap2/Lookup.cpp8
-rw-r--r--cmds/idmap2/idmap2/Main.cpp8
-rw-r--r--cmds/idmap2/idmap2/Scan.cpp8
-rw-r--r--cmds/idmap2/idmap2/Verify.cpp1
-rw-r--r--cmds/idmap2/idmap2d/Idmap2Service.cpp12
-rw-r--r--cmds/idmap2/idmap2d/Main.cpp2
-rw-r--r--cmds/idmap2/include/idmap2/FileUtils.h3
-rw-r--r--cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp12
-rw-r--r--cmds/idmap2/libidmap2/FileUtils.cpp8
-rw-r--r--cmds/idmap2/libidmap2/Idmap.cpp47
-rw-r--r--cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp11
-rw-r--r--cmds/idmap2/libidmap2/RawPrintVisitor.cpp21
-rw-r--r--cmds/idmap2/tests/BinaryStreamVisitorTests.cpp5
-rw-r--r--cmds/idmap2/tests/CommandLineOptionsTests.cpp29
-rw-r--r--cmds/idmap2/tests/FileUtilsTests.cpp6
-rw-r--r--cmds/idmap2/tests/Idmap2BinaryTests.cpp10
-rw-r--r--cmds/idmap2/tests/IdmapTests.cpp136
-rw-r--r--cmds/idmap2/tests/Main.cpp2
-rw-r--r--cmds/idmap2/tests/PrettyPrintVisitorTests.cpp1
-rw-r--r--cmds/idmap2/tests/RawPrintVisitorTests.cpp1
-rw-r--r--cmds/idmap2/tests/ResourceUtilsTests.cpp4
-rw-r--r--cmds/idmap2/tests/TestHelpers.h2
-rw-r--r--cmds/idmap2/tests/XmlTests.cpp4
-rw-r--r--cmds/incident_helper/src/TextParserBase.h2
-rw-r--r--cmds/incident_helper/src/ih_util.h4
-rw-r--r--cmds/incidentd/src/IncidentService.h2
-rw-r--r--cmds/incidentd/src/Privacy.h2
-rw-r--r--cmds/incidentd/src/Reporter.h2
-rw-r--r--cmds/incidentd/src/Section.cpp2
-rw-r--r--cmds/statsd/src/anomaly/AlarmMonitor.h2
-rw-r--r--cmds/statsd/src/condition/ConditionWizard.h2
-rw-r--r--cmds/statsd/src/config/ConfigKey.h2
-rw-r--r--cmds/statsd/src/external/ResourceHealthManagerPuller.h2
-rw-r--r--cmds/statsd/src/external/StatsCompanionServicePuller.h2
-rw-r--r--cmds/statsd/src/external/StatsPuller.h2
-rw-r--r--cmds/statsd/src/logd/LogEvent.h2
-rw-r--r--cmds/statsd/src/socket/StatsSocketListener.h4
-rw-r--r--cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java270
-rw-r--r--config/hiddenapi-greylist.txt1
-rw-r--r--core/java/android/annotation/Px.java2
-rw-r--r--core/java/android/app/AppOpsManager.java14
-rw-r--r--core/java/android/app/AppOpsManagerInternal.java6
-rw-r--r--core/java/android/content/pm/PackageInstaller.java9
-rw-r--r--core/java/android/content/pm/SharedLibraryInfo.java20
-rw-r--r--core/java/android/net/ConnectivityManager.java13
-rw-r--r--core/java/android/net/LinkProperties.java21
-rw-r--r--core/java/android/net/NetworkCapabilities.java2
-rw-r--r--core/java/android/net/NetworkInfo.java24
-rw-r--r--core/java/android/net/NetworkRequest.java3
-rw-r--r--core/java/android/service/contentcapture/ContentCaptureService.java34
-rw-r--r--core/java/android/service/euicc/DownloadSubscriptionResult.aidl19
-rw-r--r--core/java/android/service/euicc/DownloadSubscriptionResult.java99
-rw-r--r--core/java/android/service/euicc/EuiccService.java166
-rw-r--r--core/java/android/service/euicc/IDownloadSubscriptionCallback.aidl4
-rw-r--r--core/java/android/service/euicc/IEuiccService.aidl3
-rw-r--r--core/java/android/service/notification/NotificationAssistantService.java13
-rw-r--r--core/java/android/util/SparseSetArray.java7
-rw-r--r--core/java/android/view/IWindowManager.aidl6
-rw-r--r--core/java/android/view/InsetsAnimationControlImpl.java197
-rw-r--r--core/java/android/view/InsetsController.java33
-rw-r--r--core/java/android/view/InsetsSource.java3
-rw-r--r--core/java/android/view/InsetsState.java57
-rw-r--r--core/java/android/view/SyncRtSurfaceTransactionApplier.java (renamed from packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplier.java)82
-rw-r--r--core/java/android/view/View.java12
-rw-r--r--core/java/android/view/WindowInsetsAnimationControlListener.java50
-rw-r--r--core/java/android/view/WindowInsetsAnimationController.java81
-rw-r--r--core/java/android/view/WindowInsetsController.java12
-rw-r--r--core/java/android/view/contentcapture/ChildContentCaptureSession.java99
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureContext.java39
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureEvent.java74
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureManager.java42
-rw-r--r--core/java/android/view/contentcapture/ContentCaptureSession.java83
-rw-r--r--core/java/android/view/contentcapture/IContentCaptureManager.aidl3
-rw-r--r--core/java/android/view/contentcapture/MainContentCaptureSession.java (renamed from core/java/android/view/contentcapture/ActivityContentCaptureSession.java)94
-rw-r--r--core/java/android/view/textclassifier/ActionsSuggestionsHelper.java27
-rw-r--r--core/java/android/view/textclassifier/TextClassifierEvent.java22
-rw-r--r--core/java/android/view/textclassifier/TextClassifierImpl.java18
-rwxr-xr-xcore/jni/android/graphics/Bitmap.cpp2
-rw-r--r--core/jni/android/graphics/FontUtils.h2
-rw-r--r--core/jni/android/graphics/GIFMovie.cpp2
-rw-r--r--core/jni/android_media_AudioTrack.cpp1
-rw-r--r--core/jni/android_media_DeviceCallback.cpp1
-rw-r--r--core/jni/android_os_SharedMemory.cpp36
-rw-r--r--core/jni/android_util_jar_StrictJarFile.cpp41
-rw-r--r--core/jni/fd_utils.cpp2
-rw-r--r--core/jni/fd_utils.h2
-rw-r--r--core/res/AndroidManifest.xml3
-rw-r--r--core/res/res/values/styles_device_defaults.xml2
-rw-r--r--core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java121
-rw-r--r--core/tests/coretests/src/android/view/InsetsControllerTest.java1
-rw-r--r--core/tests/coretests/src/android/view/InsetsStateTest.java14
-rw-r--r--data/etc/privapp-permissions-platform.xml4
-rw-r--r--graphics/java/android/graphics/Insets.java35
-rw-r--r--keystore/java/android/security/KeyStore.java12
-rw-r--r--libs/hwui/pipeline/skia/SkiaPipeline.h2
-rw-r--r--libs/hwui/pipeline/skia/SkiaProfileRenderer.h2
-rw-r--r--libs/hwui/pipeline/skia/SkiaVulkanPipeline.h2
-rw-r--r--libs/hwui/pipeline/skia/VectorDrawableAtlas.h4
-rw-r--r--libs/hwui/renderthread/CacheManager.h2
-rw-r--r--libs/hwui/renderthread/VulkanManager.h1
-rw-r--r--libs/incident/include/android/os/IncidentReportArgs.h2
-rw-r--r--location/java/android/location/GnssMeasurementCallbackTransport.java34
-rw-r--r--location/java/android/location/GnssMeasurementCorrections.aidl19
-rw-r--r--location/java/android/location/GnssMeasurementCorrections.java210
-rw-r--r--location/java/android/location/GnssReflectingPlane.java159
-rw-r--r--location/java/android/location/GnssSingleSatCorrection.java346
-rw-r--r--location/java/android/location/ILocationManager.aidl4
-rw-r--r--location/java/android/location/LocationManager.java48
-rw-r--r--location/tests/locationtests/src/android/location/GnssMeasurementCorrectionsTest.java107
-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/AudioRecord.java55
-rw-r--r--media/java/android/media/AudioRecordingMonitor.java56
-rw-r--r--media/java/android/media/AudioRecordingMonitorClient.java28
-rw-r--r--media/java/android/media/AudioRecordingMonitorImpl.java250
-rw-r--r--media/java/android/media/MediaPlayer2.java2
-rw-r--r--media/java/android/media/MediaRecorder.java61
-rw-r--r--media/jni/android_media_MediaRecorder.cpp15
-rw-r--r--packages/CarSystemUI/res/values/config.xml2
-rw-r--r--packages/CompanionDeviceManager/AndroidManifest.xml2
-rw-r--r--packages/ExtServices/src/android/ext/services/notification/Assistant.java41
-rw-r--r--packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java18
-rw-r--r--packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java193
-rw-r--r--packages/ExtServices/tests/src/android/ext/services/notification/SmartActionHelperTest.java145
-rw-r--r--packages/ExternalStorageProvider/tests/Android.bp2
-rw-r--r--packages/ExternalStorageProvider/tests/AndroidManifest.xml2
-rw-r--r--packages/ExternalStorageProvider/tests/AndroidTest.xml2
-rw-r--r--packages/ExternalStorageProvider/tests/src/com/android/externalstorage/ExternalStorageProviderTest.java5
-rw-r--r--packages/OsuLogin/src/com/android/hotspot2/osu/OsuLoginActivity.java8
-rw-r--r--packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarChartPreference.java8
-rw-r--r--packages/SettingsLib/tests/integ/Android.mk4
-rw-r--r--packages/SettingsLib/tests/integ/AndroidManifest.xml2
-rw-r--r--packages/SettingsLib/tests/integ/AndroidTest.xml2
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/bluetooth/BluetoothEventManagerIntegTest.java14
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/drawable/UserIconDrawableTest.java5
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java27
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodPreferenceTest.java7
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodSubtypePreferenceTest.java7
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/users/UserManagerHelperTest.java6
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/NetworkPolicyEditorTest.java13
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/ZoneGetterTest.java14
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java9
-rw-r--r--packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java8
-rw-r--r--packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java25
-rw-r--r--packages/SimAppDialog/src/com/android/simappdialog/InstallCarrierAppActivity.java4
-rw-r--r--packages/SystemUI/docs/dagger.md10
-rw-r--r--packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java7
-rw-r--r--packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml5
-rw-r--r--packages/SystemUI/res/layout/status_bar_expanded.xml6
-rw-r--r--packages/SystemUI/res/values/strings.xml3
-rw-r--r--packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java103
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java53
-rw-r--r--packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/Dependency.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/DependencyBinder.java227
-rw-r--r--packages/SystemUI/src/com/android/systemui/DependencyProvider.java421
-rw-r--r--packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/InitController.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIFactory.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/UiOffloadThread.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java41
-rw-r--r--packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ScreenLifecycle.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/plugins/PluginDependencyProvider.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt6
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/DisplayNavigationBarController.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java26
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityController.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLoggerImpl.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/AsyncSensorManager.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java39
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java12
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt15
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt23
-rw-r--r--services/backup/java/com/android/server/backup/BackupManagerService.java45
-rw-r--r--services/backup/java/com/android/server/backup/Trampoline.java81
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java10
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java8
-rw-r--r--services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java8
-rw-r--r--services/core/java/com/android/server/AppOpsService.java18
-rw-r--r--services/core/java/com/android/server/DeviceIdleController.java245
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java25
-rw-r--r--services/core/java/com/android/server/StorageManagerService.java14
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java124
-rw-r--r--services/core/java/com/android/server/am/AppCompactor.java187
-rw-r--r--services/core/java/com/android/server/deviceidle/BluetoothConstraint.java135
-rw-r--r--services/core/java/com/android/server/deviceidle/ConstraintController.java32
-rw-r--r--services/core/java/com/android/server/deviceidle/DeviceIdleConstraintTracker.java57
-rw-r--r--services/core/java/com/android/server/deviceidle/IDeviceIdleConstraint.java67
-rw-r--r--services/core/java/com/android/server/deviceidle/TvConstraintController.java66
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodUtils.java4
-rw-r--r--services/core/java/com/android/server/location/GnssLocationProvider.java26
-rw-r--r--services/core/java/com/android/server/location/GnssMeasurementsProvider.java70
-rw-r--r--services/core/java/com/android/server/location/RemoteListenerHelper.java2
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageInstallerSession.java1
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java642
-rw-r--r--services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java11
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java14
-rw-r--r--services/core/java/com/android/server/textservices/TextServicesManagerInternal.java63
-rw-r--r--services/core/java/com/android/server/textservices/TextServicesManagerService.java48
-rw-r--r--services/core/java/com/android/server/wm/ActivityRecord.java24
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java84
-rw-r--r--services/core/java/com/android/server/wm/DisplayRotation.java9
-rw-r--r--services/core/java/com/android/server/wm/InputMonitor.java8
-rw-r--r--services/core/java/com/android/server/wm/RootActivityContainer.java21
-rw-r--r--services/core/java/com/android/server/wm/Task.java18
-rw-r--r--services/core/java/com/android/server/wm/TaskStack.java15
-rw-r--r--services/core/java/com/android/server/wm/TaskTapPointerEventListener.java7
-rw-r--r--services/core/java/com/android/server/wm/WindowContainer.java52
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java79
-rw-r--r--services/core/jni/com_android_server_location_GnssLocationProvider.cpp221
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java7
-rw-r--r--services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java26
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java87
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/deviceidle/BluetoothConstraintTest.java147
-rw-r--r--services/tests/servicestests/src/com/android/server/appops/AppOpsNotedWatcherTest.java16
-rw-r--r--services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java185
-rw-r--r--services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java22
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java10
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java61
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java23
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java4
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java19
-rw-r--r--services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java13
-rw-r--r--startop/view_compiler/dex_builder.h4
-rw-r--r--startop/view_compiler/main.cc2
-rw-r--r--telephony/java/android/provider/Telephony.java48
-rw-r--r--telephony/java/android/telephony/euicc/EuiccManager.java73
-rw-r--r--telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl2
-rw-r--r--tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java17
-rw-r--r--tools/incident_report/printer.h2
-rw-r--r--tools/stats_log_api_gen/Android.bp14
-rw-r--r--tools/stats_log_api_gen/main.cpp6
-rw-r--r--wifi/java/android/net/wifi/WifiConfiguration.java11
284 files changed, 7502 insertions, 2135 deletions
diff --git a/api/current.txt b/api/current.txt
index 96485a81fffb..bf3a1f42a535 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11302,6 +11302,7 @@ package android.content.pm {
method public void updateSessionAppLabel(int, java.lang.CharSequence);
field public static final java.lang.String ACTION_SESSION_COMMITTED = "android.content.pm.action.SESSION_COMMITTED";
field public static final java.lang.String ACTION_SESSION_DETAILS = "android.content.pm.action.SESSION_DETAILS";
+ field public static final java.lang.String ACTION_SESSION_UPDATED = "android.content.pm.action.SESSION_UPDATED";
field public static final java.lang.String EXTRA_OTHER_PACKAGE_NAME = "android.content.pm.extra.OTHER_PACKAGE_NAME";
field public static final java.lang.String EXTRA_PACKAGE_NAME = "android.content.pm.extra.PACKAGE_NAME";
field public static final java.lang.String EXTRA_SESSION = "android.content.pm.extra.SESSION";
@@ -14134,8 +14135,11 @@ package android.graphics {
public final class Insets {
method public static android.graphics.Insets add(android.graphics.Insets, android.graphics.Insets);
+ method public static android.graphics.Insets max(android.graphics.Insets, android.graphics.Insets);
+ method public static android.graphics.Insets min(android.graphics.Insets, android.graphics.Insets);
method public static android.graphics.Insets of(int, int, int, int);
method public static android.graphics.Insets of(android.graphics.Rect);
+ method public static android.graphics.Insets subtract(android.graphics.Insets, android.graphics.Insets);
field public static final android.graphics.Insets NONE;
field public final int bottom;
field public final int left;
@@ -23379,12 +23383,13 @@ package android.media {
method public android.media.AudioPresentation.Builder setProgramId(int);
}
- public class AudioRecord implements android.media.AudioRouting {
+ public class AudioRecord implements android.media.AudioRecordingMonitor android.media.AudioRouting {
ctor public AudioRecord(int, int, int, int, int) throws java.lang.IllegalArgumentException;
method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public deprecated void addOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener, android.os.Handler);
method protected void finalize();
method public java.util.List<android.media.MicrophoneInfo> getActiveMicrophones() throws java.io.IOException;
+ method public android.media.AudioRecordingConfiguration getActiveRecordingConfiguration();
method public int getAudioFormat();
method public int getAudioSessionId();
method public int getAudioSource();
@@ -23409,6 +23414,7 @@ package android.media {
method public int read(float[], int, int, int);
method public int read(java.nio.ByteBuffer, int);
method public int read(java.nio.ByteBuffer, int, int);
+ method public void registerAudioRecordingCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioRecordingCallback);
method public void release();
method public void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener);
method public deprecated void removeOnRoutingChangedListener(android.media.AudioRecord.OnRoutingChangedListener);
@@ -23420,6 +23426,7 @@ package android.media {
method public void startRecording() throws java.lang.IllegalStateException;
method public void startRecording(android.media.MediaSyncEvent) throws java.lang.IllegalStateException;
method public void stop() throws java.lang.IllegalStateException;
+ method public void unregisterAudioRecordingCallback(android.media.AudioManager.AudioRecordingCallback);
field public static final int ERROR = -1; // 0xffffffff
field public static final int ERROR_BAD_VALUE = -2; // 0xfffffffe
field public static final int ERROR_DEAD_OBJECT = -6; // 0xfffffffa
@@ -23474,6 +23481,12 @@ package android.media {
field public static final android.os.Parcelable.Creator<android.media.AudioRecordingConfiguration> CREATOR;
}
+ public abstract interface AudioRecordingMonitor {
+ method public abstract android.media.AudioRecordingConfiguration getActiveRecordingConfiguration();
+ method public abstract void registerAudioRecordingCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioRecordingCallback);
+ method public abstract void unregisterAudioRecordingCallback(android.media.AudioManager.AudioRecordingCallback);
+ }
+
public abstract interface AudioRouting {
method public abstract void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method public abstract android.media.AudioDeviceInfo getPreferredDevice();
@@ -25475,11 +25488,12 @@ package android.media {
field public static final int MEDIA_TRACK_TYPE_VIDEO = 1; // 0x1
}
- public class MediaRecorder implements android.media.AudioRouting {
+ public class MediaRecorder implements android.media.AudioRecordingMonitor android.media.AudioRouting {
ctor public MediaRecorder();
method public void addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler);
method protected void finalize();
method public java.util.List<android.media.MicrophoneInfo> getActiveMicrophones() throws java.io.IOException;
+ method public android.media.AudioRecordingConfiguration getActiveRecordingConfiguration();
method public static final int getAudioSourceMax();
method public int getMaxAmplitude() throws java.lang.IllegalStateException;
method public android.os.PersistableBundle getMetrics();
@@ -25488,6 +25502,7 @@ package android.media {
method public android.view.Surface getSurface();
method public void pause() throws java.lang.IllegalStateException;
method public void prepare() throws java.io.IOException, java.lang.IllegalStateException;
+ method public void registerAudioRecordingCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioRecordingCallback);
method public void release();
method public void removeOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener);
method public void reset();
@@ -25523,6 +25538,7 @@ package android.media {
method public void setVideoSource(int) throws java.lang.IllegalStateException;
method public void start() throws java.lang.IllegalStateException;
method public void stop() throws java.lang.IllegalStateException;
+ method public void unregisterAudioRecordingCallback(android.media.AudioManager.AudioRecordingCallback);
field public static final int MEDIA_ERROR_SERVER_DIED = 100; // 0x64
field public static final int MEDIA_RECORDER_ERROR_UNKNOWN = 1; // 0x1
field public static final int MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800; // 0x320
@@ -28228,7 +28244,7 @@ package android.net {
method public void addDefaultNetworkActiveListener(android.net.ConnectivityManager.OnNetworkActiveListener);
method public boolean bindProcessToNetwork(android.net.Network);
method public android.net.Network getActiveNetwork();
- method public android.net.NetworkInfo getActiveNetworkInfo();
+ method public deprecated android.net.NetworkInfo getActiveNetworkInfo();
method public deprecated android.net.NetworkInfo[] getAllNetworkInfo();
method public android.net.Network[] getAllNetworks();
method public deprecated boolean getBackgroundDataSetting();
@@ -28239,7 +28255,7 @@ package android.net {
method public int getMultipathPreference(android.net.Network);
method public android.net.NetworkCapabilities getNetworkCapabilities(android.net.Network);
method public deprecated android.net.NetworkInfo getNetworkInfo(int);
- method public android.net.NetworkInfo getNetworkInfo(android.net.Network);
+ method public deprecated android.net.NetworkInfo getNetworkInfo(android.net.Network);
method public deprecated int getNetworkPreference();
method public byte[] getNetworkWatchlistConfigHash();
method public static deprecated android.net.Network getProcessDefaultNetwork();
@@ -28273,14 +28289,14 @@ package android.net {
field public static final deprecated int DEFAULT_NETWORK_PREFERENCE = 1; // 0x1
field public static final java.lang.String EXTRA_CAPTIVE_PORTAL = "android.net.extra.CAPTIVE_PORTAL";
field public static final java.lang.String EXTRA_CAPTIVE_PORTAL_URL = "android.net.extra.CAPTIVE_PORTAL_URL";
- field public static final java.lang.String EXTRA_EXTRA_INFO = "extraInfo";
- field public static final java.lang.String EXTRA_IS_FAILOVER = "isFailover";
+ field public static final deprecated java.lang.String EXTRA_EXTRA_INFO = "extraInfo";
+ field public static final deprecated java.lang.String EXTRA_IS_FAILOVER = "isFailover";
field public static final java.lang.String EXTRA_NETWORK = "android.net.extra.NETWORK";
field public static final deprecated java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
field public static final java.lang.String EXTRA_NETWORK_REQUEST = "android.net.extra.NETWORK_REQUEST";
field public static final java.lang.String EXTRA_NETWORK_TYPE = "networkType";
field public static final java.lang.String EXTRA_NO_CONNECTIVITY = "noConnectivity";
- field public static final java.lang.String EXTRA_OTHER_NETWORK_INFO = "otherNetwork";
+ field public static final deprecated java.lang.String EXTRA_OTHER_NETWORK_INFO = "otherNetwork";
field public static final java.lang.String EXTRA_REASON = "reason";
field public static final int MULTIPATH_PREFERENCE_HANDOVER = 1; // 0x1
field public static final int MULTIPATH_PREFERENCE_PERFORMANCE = 4; // 0x4
@@ -28432,6 +28448,7 @@ package android.net {
method public android.net.ProxyInfo getHttpProxy();
method public java.lang.String getInterfaceName();
method public java.util.List<android.net.LinkAddress> getLinkAddresses();
+ method public int getMtu();
method public java.lang.String getPrivateDnsServerName();
method public java.util.List<android.net.RouteInfo> getRoutes();
method public boolean isPrivateDnsActive();
@@ -28580,10 +28597,10 @@ package android.net {
field public static final int TRANSPORT_WIFI_AWARE = 5; // 0x5
}
- public class NetworkInfo implements android.os.Parcelable {
+ public deprecated class NetworkInfo implements android.os.Parcelable {
method public int describeContents();
method public deprecated android.net.NetworkInfo.DetailedState getDetailedState();
- method public java.lang.String getExtraInfo();
+ method public deprecated java.lang.String getExtraInfo();
method public deprecated java.lang.String getReason();
method public deprecated android.net.NetworkInfo.State getState();
method public deprecated int getSubtype();
@@ -28599,7 +28616,7 @@ package android.net {
field public static final android.os.Parcelable.Creator<android.net.NetworkInfo> CREATOR;
}
- public static final class NetworkInfo.DetailedState extends java.lang.Enum {
+ public static final deprecated class NetworkInfo.DetailedState extends java.lang.Enum {
method public static android.net.NetworkInfo.DetailedState valueOf(java.lang.String);
method public static final android.net.NetworkInfo.DetailedState[] values();
enum_constant public static final android.net.NetworkInfo.DetailedState AUTHENTICATING;
@@ -28617,7 +28634,7 @@ package android.net {
enum_constant public static final android.net.NetworkInfo.DetailedState VERIFYING_POOR_LINK;
}
- public static final class NetworkInfo.State extends java.lang.Enum {
+ public static final deprecated class NetworkInfo.State extends java.lang.Enum {
method public static android.net.NetworkInfo.State valueOf(java.lang.String);
method public static final android.net.NetworkInfo.State[] values();
enum_constant public static final android.net.NetworkInfo.State CONNECTED;
@@ -38682,22 +38699,23 @@ package android.provider {
field public static final android.net.Uri CONTENT_URI;
field public static final java.lang.String CURRENT = "current";
field public static final java.lang.String DEFAULT_SORT_ORDER = "name ASC";
- field public static final java.lang.String MCC = "mcc";
+ field public static final deprecated java.lang.String MCC = "mcc";
field public static final java.lang.String MMSC = "mmsc";
field public static final java.lang.String MMSPORT = "mmsport";
field public static final java.lang.String MMSPROXY = "mmsproxy";
- field public static final java.lang.String MNC = "mnc";
- field public static final java.lang.String MVNO_MATCH_DATA = "mvno_match_data";
- field public static final java.lang.String MVNO_TYPE = "mvno_type";
+ field public static final deprecated java.lang.String MNC = "mnc";
+ field public static final deprecated java.lang.String MVNO_MATCH_DATA = "mvno_match_data";
+ field public static final deprecated java.lang.String MVNO_TYPE = "mvno_type";
field public static final java.lang.String NAME = "name";
field public static final java.lang.String NETWORK_TYPE_BITMASK = "network_type_bitmask";
- field public static final java.lang.String NUMERIC = "numeric";
+ field public static final deprecated java.lang.String NUMERIC = "numeric";
field public static final java.lang.String PASSWORD = "password";
field public static final java.lang.String PORT = "port";
field public static final java.lang.String PROTOCOL = "protocol";
field public static final java.lang.String PROXY = "proxy";
field public static final java.lang.String ROAMING_PROTOCOL = "roaming_protocol";
field public static final java.lang.String SERVER = "server";
+ field public static final android.net.Uri SIM_APN_URI;
field public static final java.lang.String SUBSCRIPTION_ID = "sub_id";
field public static final java.lang.String TYPE = "type";
field public static final java.lang.String USER = "user";
@@ -52228,7 +52246,6 @@ package android.view.contentcapture {
}
public final class ContentCaptureManager {
- method public android.view.contentcapture.ContentCaptureSession createContentCaptureSession(android.view.contentcapture.ContentCaptureContext);
method public android.content.ComponentName getServiceComponentName();
method public boolean isContentCaptureEnabled();
method public void removeUserData(android.view.contentcapture.UserDataRemovalRequest);
@@ -52237,6 +52254,7 @@ package android.view.contentcapture {
public abstract class ContentCaptureSession implements java.lang.AutoCloseable {
method public void close();
+ method public final android.view.contentcapture.ContentCaptureSession createContentCaptureSession(android.view.contentcapture.ContentCaptureContext);
method public final void destroy();
method public final android.view.contentcapture.ContentCaptureSessionId getContentCaptureSessionId();
method public final void notifyViewAppeared(android.view.ViewStructure);
diff --git a/api/system-current.txt b/api/system-current.txt
index 751ef34f0ae1..d98139933588 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -2577,6 +2577,81 @@ package android.location {
method public void onLocationBatch(java.util.List<android.location.Location>);
}
+ public final class GnssMeasurementCorrections implements android.os.Parcelable {
+ method public int describeContents();
+ method public double getAltitudeMeters();
+ method public double getLatitudeDegrees();
+ method public double getLongitudeDegrees();
+ method public java.util.List<android.location.GnssSingleSatCorrection> getSingleSatCorrectionList();
+ method public long getToaGpsNanosecondsOfWeek();
+ 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 {
+ ctor public GnssMeasurementCorrections.Builder();
+ method public android.location.GnssMeasurementCorrections build();
+ method public android.location.GnssMeasurementCorrections.Builder setAltitudeMeters(double);
+ method public android.location.GnssMeasurementCorrections.Builder setLatitudeDegrees(double);
+ method public android.location.GnssMeasurementCorrections.Builder setLongitudeDegrees(double);
+ method public android.location.GnssMeasurementCorrections.Builder setSingleSatCorrectionList(java.util.List<android.location.GnssSingleSatCorrection>);
+ method public android.location.GnssMeasurementCorrections.Builder setToaGpsNanosecondsOfWeek(long);
+ }
+
+ public final class GnssReflectingPlane implements android.os.Parcelable {
+ method public int describeContents();
+ method public double getAltitudeMeters();
+ method public double getAzimuthDegrees();
+ method public double getLatitudeDegrees();
+ method public double getLongitudeDegrees();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.location.GnssReflectingPlane> CREATOR;
+ }
+
+ public static class GnssReflectingPlane.Builder {
+ ctor public GnssReflectingPlane.Builder();
+ method public android.location.GnssReflectingPlane build();
+ method public android.location.GnssReflectingPlane.Builder setAltitudeMeters(double);
+ method public android.location.GnssReflectingPlane.Builder setAzimuthDegrees(double);
+ method public android.location.GnssReflectingPlane.Builder setLatitudeDegrees(double);
+ method public android.location.GnssReflectingPlane.Builder setLongitudeDegrees(double);
+ }
+
+ public final class GnssSingleSatCorrection implements android.os.Parcelable {
+ method public int describeContents();
+ method public float getCarrierFrequencyHz();
+ method public int getConstellationType();
+ method public float getExcessPathLengthMeters();
+ method public float getExcessPathLengthUncertaintyMeters();
+ method public android.location.GnssReflectingPlane getReflectingPlane();
+ method public int getSatId();
+ method public int getSingleSatCorrectionFlags();
+ method public boolean hasExcessPathLength();
+ method public boolean hasExcessPathLengthUncertainty();
+ method public boolean hasReflectingPlane();
+ method public boolean hasSatelliteLineOfSight();
+ method public boolean isSatelliteLineOfSight();
+ 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
+ field public static final int HAS_EXCESS_PATH_LENGTH_UNC_MASK = 4; // 0x4
+ field public static final int HAS_REFLECTING_PLANE_MASK = 8; // 0x8
+ field public static final int HAS_SAT_IS_LOS_MASK = 1; // 0x1
+ }
+
+ public static 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 setReflectingPlane(android.location.GnssReflectingPlane);
+ method public android.location.GnssSingleSatCorrection.Builder setSatId(int);
+ method public android.location.GnssSingleSatCorrection.Builder setSatIsLos(boolean);
+ method public android.location.GnssSingleSatCorrection.Builder setSingleSatCorrectionFlags(int);
+ }
+
public class GpsClock implements android.os.Parcelable {
method public int describeContents();
method public double getBiasInNs();
@@ -2813,8 +2888,10 @@ package android.location {
method public deprecated boolean addGpsNavigationMessageListener(android.location.GpsNavigationMessageEvent.Listener);
method public void flushGnssBatch();
method public int getGnssBatchSize();
+ method public int getGnssCapabilities();
method public java.lang.String getLocationControllerExtraPackage();
method public java.lang.String getNetworkProviderPackage();
+ method public void injectGnssMeasurementCorrections(android.location.GnssMeasurementCorrections);
method public boolean isLocationControllerExtraPackageEnabled();
method public boolean isLocationEnabledForUser(android.os.UserHandle);
method public boolean isProviderEnabledForUser(java.lang.String, android.os.UserHandle);
@@ -2953,7 +3030,7 @@ package android.media {
field public static final int PLAYER_TYPE_UNKNOWN = -1; // 0xffffffff
}
- public class AudioRecord implements android.media.AudioRouting {
+ public class AudioRecord implements android.media.AudioRecordingMonitor android.media.AudioRouting {
ctor public AudioRecord(android.media.AudioAttributes, android.media.AudioFormat, int, int) throws java.lang.IllegalArgumentException;
}
@@ -3441,7 +3518,20 @@ package android.net {
ctor public LinkAddress(java.lang.String);
}
+ public final class LinkProperties implements android.os.Parcelable {
+ ctor public LinkProperties();
+ method public boolean addRoute(android.net.RouteInfo);
+ method public void clear();
+ method public void setDnsServers(java.util.Collection<java.net.InetAddress>);
+ method public void setDomains(java.lang.String);
+ method public void setHttpProxy(android.net.ProxyInfo);
+ method public void setInterfaceName(java.lang.String);
+ method public void setLinkAddresses(java.util.Collection<android.net.LinkAddress>);
+ method public void setMtu(int);
+ }
+
public final class NetworkCapabilities implements android.os.Parcelable {
+ method public int getSignalStrength();
field public static final int NET_CAPABILITY_OEM_PAID = 22; // 0x16
}
@@ -3461,6 +3551,10 @@ package android.net {
method public abstract void onRequestScores(android.net.NetworkKey[]);
}
+ public static class NetworkRequest.Builder {
+ method public android.net.NetworkRequest.Builder setSignalStrength(int);
+ }
+
public class NetworkScoreManager {
method public boolean clearScores() throws java.lang.SecurityException;
method public void disableScoring() throws java.lang.SecurityException;
@@ -5085,6 +5179,16 @@ package android.service.contentcapture {
package android.service.euicc {
+ public final class DownloadSubscriptionResult implements android.os.Parcelable {
+ ctor public DownloadSubscriptionResult(int, int, int);
+ method public int describeContents();
+ method public int getCardId();
+ method public int getResolvableErrors();
+ method public int getResult();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.service.euicc.DownloadSubscriptionResult> CREATOR;
+ }
+
public final class EuiccProfileInfo implements android.os.Parcelable {
method public int describeContents();
method public android.service.carrier.CarrierIdentifier getCarrierIdentifier();
@@ -5138,7 +5242,8 @@ package android.service.euicc {
ctor public EuiccService();
method public android.os.IBinder onBind(android.content.Intent);
method public abstract int onDeleteSubscription(int, java.lang.String);
- method public abstract int onDownloadSubscription(int, android.telephony.euicc.DownloadableSubscription, boolean, boolean);
+ method public abstract android.service.euicc.DownloadSubscriptionResult onDownloadSubscription(int, android.telephony.euicc.DownloadableSubscription, boolean, boolean, android.os.Bundle);
+ method public deprecated int onDownloadSubscription(int, android.telephony.euicc.DownloadableSubscription, boolean, boolean);
method public abstract int onEraseSubscriptions(int);
method public abstract android.service.euicc.GetDefaultDownloadableSubscriptionListResult onGetDefaultDownloadableSubscriptionList(int, boolean);
method public abstract android.service.euicc.GetDownloadableSubscriptionMetadataResult onGetDownloadableSubscriptionMetadata(int, android.telephony.euicc.DownloadableSubscription, boolean);
@@ -5153,19 +5258,25 @@ package android.service.euicc {
field public static final java.lang.String ACTION_BIND_CARRIER_PROVISIONING_SERVICE = "android.service.euicc.action.BIND_CARRIER_PROVISIONING_SERVICE";
field public static final java.lang.String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS = "android.service.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS";
field public static final java.lang.String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION = "android.service.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION";
- field public static final java.lang.String ACTION_RESOLVE_CONFIRMATION_CODE = "android.service.euicc.action.RESOLVE_CONFIRMATION_CODE";
+ field public static final deprecated java.lang.String ACTION_RESOLVE_CONFIRMATION_CODE = "android.service.euicc.action.RESOLVE_CONFIRMATION_CODE";
field public static final java.lang.String ACTION_RESOLVE_DEACTIVATE_SIM = "android.service.euicc.action.RESOLVE_DEACTIVATE_SIM";
field public static final java.lang.String ACTION_RESOLVE_NO_PRIVILEGES = "android.service.euicc.action.RESOLVE_NO_PRIVILEGES";
+ field public static final java.lang.String ACTION_RESOLVE_RESOLVABLE_ERRORS = "android.service.euicc.action.RESOLVE_RESOLVABLE_ERRORS";
field public static final java.lang.String CATEGORY_EUICC_UI = "android.service.euicc.category.EUICC_UI";
field public static final java.lang.String EUICC_SERVICE_INTERFACE = "android.service.euicc.EuiccService";
+ field public static final java.lang.String EXTRA_RESOLUTION_ALLOW_POLICY_RULES = "android.service.euicc.extra.RESOLUTION_ALLOW_POLICY_RULES";
field public static final java.lang.String EXTRA_RESOLUTION_CALLING_PACKAGE = "android.service.euicc.extra.RESOLUTION_CALLING_PACKAGE";
field public static final java.lang.String EXTRA_RESOLUTION_CONFIRMATION_CODE = "android.service.euicc.extra.RESOLUTION_CONFIRMATION_CODE";
field public static final java.lang.String EXTRA_RESOLUTION_CONFIRMATION_CODE_RETRIED = "android.service.euicc.extra.RESOLUTION_CONFIRMATION_CODE_RETRIED";
field public static final java.lang.String EXTRA_RESOLUTION_CONSENT = "android.service.euicc.extra.RESOLUTION_CONSENT";
+ field public static final java.lang.String EXTRA_RESOLVABLE_ERRORS = "android.service.euicc.extra.RESOLVABLE_ERRORS";
+ field public static final int RESOLVABLE_ERROR_CONFIRMATION_CODE = 1; // 0x1
+ field public static final int RESOLVABLE_ERROR_POLICY_RULES = 2; // 0x2
field public static final int RESULT_FIRST_USER = 1; // 0x1
field public static final int RESULT_MUST_DEACTIVATE_SIM = -1; // 0xffffffff
- field public static final int RESULT_NEED_CONFIRMATION_CODE = -2; // 0xfffffffe
+ field public static final deprecated int RESULT_NEED_CONFIRMATION_CODE = -2; // 0xfffffffe
field public static final int RESULT_OK = 0; // 0x0
+ field public static final int RESULT_RESOLVABLE_ERRORS = -2; // 0xfffffffe
}
public static abstract class EuiccService.OtaStatusChangedCallback {
@@ -6464,12 +6575,17 @@ package android.telephony.euicc {
method public void getDownloadableSubscriptionMetadata(android.telephony.euicc.DownloadableSubscription, android.app.PendingIntent);
method public int getOtaStatus();
field public static final java.lang.String ACTION_OTA_STATUS_CHANGED = "android.telephony.euicc.action.OTA_STATUS_CHANGED";
+ field public static final java.lang.String ACTION_PROFILE_SELECTION = "android.telephony.euicc.action.PROFILE_SELECTION";
field public static final java.lang.String ACTION_PROVISION_EMBEDDED_SUBSCRIPTION = "android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION";
+ field public static final int EUICC_ACTIVATION_TYPE_BACKUP = 2; // 0x2
+ field public static final int EUICC_ACTIVATION_TYPE_DEFAULT = 1; // 0x1
+ field public static final int EUICC_ACTIVATION_TYPE_TRANSFER = 3; // 0x3
field public static final int EUICC_OTA_FAILED = 2; // 0x2
field public static final int EUICC_OTA_IN_PROGRESS = 1; // 0x1
field public static final int EUICC_OTA_NOT_NEEDED = 4; // 0x4
field public static final int EUICC_OTA_STATUS_UNAVAILABLE = 5; // 0x5
field public static final int EUICC_OTA_SUCCEEDED = 3; // 0x3
+ field public static final java.lang.String EXTRA_ACTIVATION_TYPE = "android.telephony.euicc.extra.ACTIVATION_TYPE";
field public static final java.lang.String EXTRA_EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS = "android.telephony.euicc.extra.EMBEDDED_SUBSCRIPTION_DOWNLOADABLE_SUBSCRIPTIONS";
field public static final java.lang.String EXTRA_FORCE_PROVISION = "android.telephony.euicc.extra.FORCE_PROVISION";
}
@@ -7553,6 +7669,7 @@ package android.view.contentcapture {
method public int getDisplayId();
method public android.os.Bundle getExtras();
method public int getFlags();
+ method public android.view.contentcapture.ContentCaptureSessionId getParentSessionId();
method public int getTaskId();
method public android.net.Uri getUri();
field public static final int FLAG_DISABLED_BY_APP = 1; // 0x1
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
index d7922bc08cea..fe7099b2f3ea 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -12,14 +12,26 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-cc_library {
- name: "libidmap2",
- host_supported: true,
+cc_defaults {
+ name: "idmap2_defaults",
tidy: true,
+ tidy_checks: [
+ "android-*",
+ "misc-*",
+ "modernize-*",
+ "readability-*",
+ ],
tidy_flags: [
"-system-headers",
-// b/120024673 "-warnings-as-errors=*",
],
+}
+
+cc_library {
+ name: "libidmap2",
+ defaults: [
+ "idmap2_defaults",
+ ],
+ host_supported: true,
srcs: [
"libidmap2/BinaryStreamVisitor.cpp",
"libidmap2/CommandLineOptions.cpp",
@@ -60,12 +72,13 @@ cc_library {
cc_test {
name: "idmap2_tests",
- host_supported: true,
- tidy: true,
- tidy_flags: [
- "-system-headers",
-// b/120024673 "-warnings-as-errors=*",
+ defaults: [
+ "idmap2_defaults",
+ ],
+ tidy_checks: [
+ "-readability-magic-numbers",
],
+ host_supported: true,
srcs: [
"tests/BinaryStreamVisitorTests.cpp",
"tests/CommandLineOptionsTests.cpp",
@@ -114,12 +127,10 @@ cc_test {
cc_binary {
name: "idmap2",
- host_supported: true,
- tidy: true,
- tidy_flags: [
- "-system-headers",
-// b/120024673 "-warnings-as-errors=*",
+ defaults: [
+ "idmap2_defaults",
],
+ host_supported: true,
srcs: [
"idmap2/Create.cpp",
"idmap2/Dump.cpp",
@@ -156,19 +167,11 @@ cc_binary {
cc_binary {
name: "idmap2d",
- host_supported: false,
- tidy: true,
- tidy_checks: [
- // remove google-default-arguments or clang-tidy will complain about
- // the auto-generated file IIdmap2.cpp
- "-google-default-arguments",
- ],
- tidy_flags: [
- "-system-headers",
-// b/120024673 "-warnings-as-errors=*",
+ defaults: [
+ "idmap2_defaults",
],
+ host_supported: false,
srcs: [
- ":idmap2_aidl",
"idmap2d/Idmap2Service.cpp",
"idmap2d/Main.cpp",
],
@@ -181,9 +184,30 @@ cc_binary {
"libutils",
"libziparchive",
],
+ static_libs: [
+ "libidmap2daidl",
+ ],
init_rc: ["idmap2d/idmap2d.rc"],
}
+cc_library_static {
+ name: "libidmap2daidl",
+ defaults: [
+ "idmap2_defaults",
+ ],
+ tidy: false,
+ host_supported: false,
+ srcs: [
+ ":idmap2_aidl",
+ ],
+ shared_libs: [
+ "libbase",
+ ],
+ aidl: {
+ export_aidl_headers: true,
+ },
+}
+
filegroup {
name: "idmap2_aidl",
srcs: [
diff --git a/cmds/idmap2/idmap2/Create.cpp b/cmds/idmap2/idmap2/Create.cpp
index 291eaeb9c211..b07567331e85 100644
--- a/cmds/idmap2/idmap2/Create.cpp
+++ b/cmds/idmap2/idmap2/Create.cpp
@@ -32,9 +32,12 @@ using android::ApkAssets;
using android::idmap2::BinaryStreamVisitor;
using android::idmap2::CommandLineOptions;
using android::idmap2::Idmap;
+using android::idmap2::utils::kIdmapFilePermissionMask;
bool Create(const std::vector<std::string>& args, std::ostream& out_error) {
- std::string target_apk_path, overlay_apk_path, idmap_path;
+ std::string target_apk_path;
+ std::string overlay_apk_path;
+ std::string idmap_path;
const CommandLineOptions opts =
CommandLineOptions("idmap2 create")
@@ -68,7 +71,7 @@ bool Create(const std::vector<std::string>& args, std::ostream& out_error) {
return false;
}
- umask(0133); // u=rw,g=r,o=r
+ umask(kIdmapFilePermissionMask);
std::ofstream fout(idmap_path);
if (fout.fail()) {
out_error << "failed to open idmap path " << idmap_path << std::endl;
diff --git a/cmds/idmap2/idmap2/Lookup.cpp b/cmds/idmap2/idmap2/Lookup.cpp
index 8d0cee5b938d..cfb5dd5b30a9 100644
--- a/cmds/idmap2/idmap2/Lookup.cpp
+++ b/cmds/idmap2/idmap2/Lookup.cpp
@@ -63,10 +63,12 @@ namespace {
Result<ResourceId> WARN_UNUSED ParseResReference(const AssetManager2& am, const std::string& res,
const std::string& fallback_package) {
+ static constexpr const int kBaseHex = 16;
+
// first, try to parse as a hex number
char* endptr = nullptr;
ResourceId resid;
- resid = strtol(res.c_str(), &endptr, 16);
+ resid = strtol(res.c_str(), &endptr, kBaseHex);
if (*endptr == '\0') {
return {resid};
}
@@ -155,7 +157,9 @@ Result<std::string> GetTargetPackageNameFromManifest(const std::string& apk_path
bool Lookup(const std::vector<std::string>& args, std::ostream& out_error) {
std::vector<std::string> idmap_paths;
- std::string config_str, resid_str;
+ std::string config_str;
+ std::string resid_str;
+
const CommandLineOptions opts =
CommandLineOptions("idmap2 lookup")
.MandatoryOption("--idmap-path", "input: path to idmap file to load", &idmap_paths)
diff --git a/cmds/idmap2/idmap2/Main.cpp b/cmds/idmap2/idmap2/Main.cpp
index 5d9ea778915a..4012555235a8 100644
--- a/cmds/idmap2/idmap2/Main.cpp
+++ b/cmds/idmap2/idmap2/Main.cpp
@@ -29,10 +29,12 @@
using android::idmap2::CommandLineOptions;
-typedef std::map<std::string, std::function<int(const std::vector<std::string>&, std::ostream&)>>
+typedef std::map<std::string, std::function<bool(const std::vector<std::string>&, std::ostream&)>>
NameToFunctionMap;
-static void PrintUsage(const NameToFunctionMap& commands, std::ostream& out) {
+namespace {
+
+void PrintUsage(const NameToFunctionMap& commands, std::ostream& out) {
out << "usage: idmap2 [";
for (auto iter = commands.cbegin(); iter != commands.cend(); iter++) {
if (iter != commands.cbegin()) {
@@ -43,6 +45,8 @@ static void PrintUsage(const NameToFunctionMap& commands, std::ostream& out) {
out << "]" << std::endl;
}
+} // namespace
+
int main(int argc, char** argv) {
const NameToFunctionMap commands = {
{"create", Create}, {"dump", Dump}, {"lookup", Lookup}, {"scan", Scan}, {"verify", Verify},
diff --git a/cmds/idmap2/idmap2/Scan.cpp b/cmds/idmap2/idmap2/Scan.cpp
index 00c49e38e8b2..ef560d1ee710 100644
--- a/cmds/idmap2/idmap2/Scan.cpp
+++ b/cmds/idmap2/idmap2/Scan.cpp
@@ -44,7 +44,7 @@ std::unique_ptr<std::vector<std::string>> FindApkFiles(const std::vector<std::st
const auto predicate = [](unsigned char type, const std::string& path) -> bool {
static constexpr size_t kExtLen = 4; // strlen(".apk")
return type == DT_REG && path.size() > kExtLen &&
- !path.compare(path.size() - kExtLen, kExtLen, ".apk");
+ path.compare(path.size() - kExtLen, kExtLen, ".apk") == 0;
};
// pass apk paths through a set to filter out duplicates
std::set<std::string> paths;
@@ -63,7 +63,9 @@ std::unique_ptr<std::vector<std::string>> FindApkFiles(const std::vector<std::st
bool Scan(const std::vector<std::string>& args, std::ostream& out_error) {
std::vector<std::string> input_directories;
- std::string target_package_name, target_apk_path, output_directory;
+ std::string target_package_name;
+ std::string target_apk_path;
+ std::string output_directory;
bool recursive = false;
const CommandLineOptions opts =
@@ -112,7 +114,7 @@ bool Scan(const std::vector<std::string>& args, std::ostream& out_error) {
}
auto iter = tag->find("isStatic");
- if (iter == tag->end() || std::stoul(iter->second) == 0u) {
+ if (iter == tag->end() || std::stoul(iter->second) == 0U) {
continue;
}
diff --git a/cmds/idmap2/idmap2/Verify.cpp b/cmds/idmap2/idmap2/Verify.cpp
index b5fa438b5b9f..4d4a0e769174 100644
--- a/cmds/idmap2/idmap2/Verify.cpp
+++ b/cmds/idmap2/idmap2/Verify.cpp
@@ -27,6 +27,7 @@ using android::idmap2::IdmapHeader;
bool Verify(const std::vector<std::string>& args, std::ostream& out_error) {
std::string idmap_path;
+
const CommandLineOptions opts =
CommandLineOptions("idmap2 verify")
.MandatoryOption("--idmap-path", "input: path to idmap file to verify", &idmap_path);
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp
index 86b00f1d6e95..7b16093434fb 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.cpp
+++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp
@@ -39,10 +39,11 @@ using android::binder::Status;
using android::idmap2::BinaryStreamVisitor;
using android::idmap2::Idmap;
using android::idmap2::IdmapHeader;
+using android::idmap2::utils::kIdmapFilePermissionMask;
namespace {
-static constexpr const char* kIdmapCacheDir = "/data/resource-cache";
+constexpr const char* kIdmapCacheDir = "/data/resource-cache";
Status ok() {
return Status::ok();
@@ -69,13 +70,12 @@ Status Idmap2Service::removeIdmap(const std::string& overlay_apk_path,
int32_t user_id ATTRIBUTE_UNUSED, bool* _aidl_return) {
assert(_aidl_return);
const std::string idmap_path = Idmap::CanonicalIdmapPathFor(kIdmapCacheDir, overlay_apk_path);
- if (unlink(idmap_path.c_str()) == 0) {
- *_aidl_return = true;
- return ok();
- } else {
+ if (unlink(idmap_path.c_str()) != 0) {
*_aidl_return = false;
return error("failed to unlink " + idmap_path + ": " + strerror(errno));
}
+ *_aidl_return = true;
+ return ok();
}
Status Idmap2Service::verifyIdmap(const std::string& overlay_apk_path,
@@ -119,7 +119,7 @@ Status Idmap2Service::createIdmap(const std::string& target_apk_path,
return error(err.str());
}
- umask(0133); // u=rw,g=r,o=r
+ umask(kIdmapFilePermissionMask);
const std::string idmap_path = Idmap::CanonicalIdmapPathFor(kIdmapCacheDir, overlay_apk_path);
std::ofstream fout(idmap_path);
if (fout.fail()) {
diff --git a/cmds/idmap2/idmap2d/Main.cpp b/cmds/idmap2/idmap2d/Main.cpp
index d64a87b8ee15..4393dcc130ec 100644
--- a/cmds/idmap2/idmap2d/Main.cpp
+++ b/cmds/idmap2/idmap2d/Main.cpp
@@ -37,7 +37,7 @@ using android::status_t;
using android::os::Idmap2Service;
int main(int argc ATTRIBUTE_UNUSED, char** argv ATTRIBUTE_UNUSED) {
- IPCThreadState::self()->disableBackgroundScheduling(true);
+ IPCThreadState::disableBackgroundScheduling(true);
status_t ret = BinderService<Idmap2Service>::publish();
if (ret != android::OK) {
return EXIT_FAILURE;
diff --git a/cmds/idmap2/include/idmap2/FileUtils.h b/cmds/idmap2/include/idmap2/FileUtils.h
index 05c6d31d395d..84cc69a95ac5 100644
--- a/cmds/idmap2/include/idmap2/FileUtils.h
+++ b/cmds/idmap2/include/idmap2/FileUtils.h
@@ -25,6 +25,9 @@
namespace android {
namespace idmap2 {
namespace utils {
+
+constexpr const mode_t kIdmapFilePermissionMask = 0133; // u=rw,g=r,o=r
+
typedef std::function<bool(unsigned char type /* DT_* from dirent.h */, const std::string& path)>
FindFilesPredicate;
std::unique_ptr<std::vector<std::string>> FindFiles(const std::string& root, bool recurse,
diff --git a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
index 29969a23250b..b7765bc3d836 100644
--- a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
+++ b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp
@@ -64,15 +64,15 @@ void BinaryStreamVisitor::visit(const IdmapData::Header& header) {
Write16(header.GetTypeCount());
}
-void BinaryStreamVisitor::visit(const IdmapData::TypeEntry& te) {
- const uint16_t entryCount = te.GetEntryCount();
+void BinaryStreamVisitor::visit(const IdmapData::TypeEntry& type_entry) {
+ const uint16_t entryCount = type_entry.GetEntryCount();
- Write16(te.GetTargetTypeId());
- Write16(te.GetOverlayTypeId());
+ Write16(type_entry.GetTargetTypeId());
+ Write16(type_entry.GetOverlayTypeId());
Write16(entryCount);
- Write16(te.GetEntryOffset());
+ Write16(type_entry.GetEntryOffset());
for (uint16_t i = 0; i < entryCount; i++) {
- EntryId entry_id = te.GetEntry(i);
+ EntryId entry_id = type_entry.GetEntry(i);
Write32(entry_id != kNoEntry ? static_cast<uint32_t>(entry_id) : kPadding);
}
}
diff --git a/cmds/idmap2/libidmap2/FileUtils.cpp b/cmds/idmap2/libidmap2/FileUtils.cpp
index 4ac4c04d0bfc..88d40d1f523d 100644
--- a/cmds/idmap2/libidmap2/FileUtils.cpp
+++ b/cmds/idmap2/libidmap2/FileUtils.cpp
@@ -34,12 +34,12 @@ namespace utils {
std::unique_ptr<std::vector<std::string>> FindFiles(const std::string& root, bool recurse,
const FindFilesPredicate& predicate) {
DIR* dir = opendir(root.c_str());
- if (!dir) {
+ if (dir == nullptr) {
return nullptr;
}
std::unique_ptr<std::vector<std::string>> vector(new std::vector<std::string>());
struct dirent* dirent;
- while ((dirent = readdir(dir))) {
+ while ((dirent = readdir(dir)) != nullptr) {
const std::string path = root + "/" + dirent->d_name;
if (predicate(dirent->d_type, path)) {
vector->push_back(path);
@@ -68,8 +68,10 @@ std::unique_ptr<std::string> ReadFile(const std::string& path) {
}
std::unique_ptr<std::string> ReadFile(int fd) {
+ static constexpr const size_t kBufSize = 1024;
+
std::unique_ptr<std::string> str(new std::string());
- char buf[1024];
+ char buf[kBufSize];
ssize_t r;
while ((r = read(fd, buf, sizeof(buf))) > 0) {
str->append(buf, r);
diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp
index 1ef326793cb4..5822745a95c3 100644
--- a/cmds/idmap2/libidmap2/Idmap.cpp
+++ b/cmds/idmap2/libidmap2/Idmap.cpp
@@ -39,24 +39,32 @@
namespace android {
namespace idmap2 {
+namespace {
+
#define EXTRACT_TYPE(resid) ((0x00ff0000 & (resid)) >> 16)
#define EXTRACT_ENTRY(resid) (0x0000ffff & (resid))
-struct MatchingResources {
+class MatchingResources {
+ public:
void Add(ResourceId target_resid, ResourceId overlay_resid) {
TypeId target_typeid = EXTRACT_TYPE(target_resid);
- if (map.find(target_typeid) == map.end()) {
- map.emplace(target_typeid, std::set<std::pair<ResourceId, ResourceId>>());
+ if (map_.find(target_typeid) == map_.end()) {
+ map_.emplace(target_typeid, std::set<std::pair<ResourceId, ResourceId>>());
}
- map[target_typeid].insert(std::make_pair(target_resid, overlay_resid));
+ map_[target_typeid].insert(std::make_pair(target_resid, overlay_resid));
+ }
+
+ inline const std::map<TypeId, std::set<std::pair<ResourceId, ResourceId>>>& Map() const {
+ return map_;
}
+ private:
// target type id -> set { pair { overlay entry id, overlay entry id } }
- std::map<TypeId, std::set<std::pair<ResourceId, ResourceId>>> map;
+ std::map<TypeId, std::set<std::pair<ResourceId, ResourceId>>> map_;
};
-static bool WARN_UNUSED Read16(std::istream& stream, uint16_t* out) {
+bool WARN_UNUSED Read16(std::istream& stream, uint16_t* out) {
uint16_t value;
if (stream.read(reinterpret_cast<char*>(&value), sizeof(uint16_t))) {
*out = dtohl(value);
@@ -65,7 +73,7 @@ static bool WARN_UNUSED Read16(std::istream& stream, uint16_t* out) {
return false;
}
-static bool WARN_UNUSED Read32(std::istream& stream, uint32_t* out) {
+bool WARN_UNUSED Read32(std::istream& stream, uint32_t* out) {
uint32_t value;
if (stream.read(reinterpret_cast<char*>(&value), sizeof(uint32_t))) {
*out = dtohl(value);
@@ -75,7 +83,7 @@ static bool WARN_UNUSED Read32(std::istream& stream, uint32_t* out) {
}
// a string is encoded as a kIdmapStringLength char array; the array is always null-terminated
-static bool WARN_UNUSED ReadString(std::istream& stream, char out[kIdmapStringLength]) {
+bool WARN_UNUSED ReadString(std::istream& stream, char out[kIdmapStringLength]) {
char buf[kIdmapStringLength];
memset(buf, 0, sizeof(buf));
if (!stream.read(buf, sizeof(buf))) {
@@ -88,7 +96,7 @@ static bool WARN_UNUSED ReadString(std::istream& stream, char out[kIdmapStringLe
return true;
}
-static ResourceId NameToResid(const AssetManager2& am, const std::string& name) {
+ResourceId NameToResid(const AssetManager2& am, const std::string& name) {
return am.GetResourceId(name);
}
@@ -101,7 +109,7 @@ static ResourceId NameToResid(const AssetManager2& am, const std::string& name)
// relying on a hard-coded index. This however requires storing the package name in the idmap
// header, which in turn requires incrementing the idmap version. Because the initial version of
// idmap2 is compatible with idmap, this will have to wait for now.
-static const LoadedPackage* GetPackageAtIndex0(const LoadedArsc& loaded_arsc) {
+const LoadedPackage* GetPackageAtIndex0(const LoadedArsc& loaded_arsc) {
const std::vector<std::unique_ptr<const LoadedPackage>>& packages = loaded_arsc.GetPackages();
if (packages.empty()) {
return nullptr;
@@ -110,6 +118,8 @@ static const LoadedPackage* GetPackageAtIndex0(const LoadedArsc& loaded_arsc) {
return loaded_arsc.GetPackageById(id);
}
+} // namespace
+
std::unique_ptr<const IdmapHeader> IdmapHeader::FromBinaryStream(std::istream& stream) {
std::unique_ptr<IdmapHeader> idmap_header(new IdmapHeader());
@@ -196,8 +206,9 @@ std::unique_ptr<const IdmapData::Header> IdmapData::Header::FromBinaryStream(std
std::unique_ptr<const IdmapData::TypeEntry> IdmapData::TypeEntry::FromBinaryStream(
std::istream& stream) {
std::unique_ptr<IdmapData::TypeEntry> data(new IdmapData::TypeEntry());
-
- uint16_t target_type16, overlay_type16, entry_count;
+ uint16_t target_type16;
+ uint16_t overlay_type16;
+ uint16_t entry_count;
if (!Read16(stream, &target_type16) || !Read16(stream, &overlay_type16) ||
!Read16(stream, &entry_count) || !Read16(stream, &data->entry_offset_)) {
return nullptr;
@@ -282,25 +293,25 @@ std::unique_ptr<const Idmap> Idmap::FromApkAssets(const std::string& target_apk_
}
const LoadedArsc* target_arsc = target_apk_assets.GetLoadedArsc();
- if (!target_arsc) {
+ if (target_arsc == nullptr) {
out_error << "error: failed to load target resources.arsc" << std::endl;
return nullptr;
}
const LoadedArsc* overlay_arsc = overlay_apk_assets.GetLoadedArsc();
- if (!overlay_arsc) {
+ if (overlay_arsc == nullptr) {
out_error << "error: failed to load overlay resources.arsc" << std::endl;
return nullptr;
}
const LoadedPackage* target_pkg = GetPackageAtIndex0(*target_arsc);
- if (!target_pkg) {
+ if (target_pkg == nullptr) {
out_error << "error: failed to load target package from resources.arsc" << std::endl;
return nullptr;
}
const LoadedPackage* overlay_pkg = GetPackageAtIndex0(*overlay_arsc);
- if (!overlay_pkg) {
+ if (overlay_pkg == nullptr) {
out_error << "error: failed to load overlay package from resources.arsc" << std::endl;
return nullptr;
}
@@ -375,8 +386,8 @@ std::unique_ptr<const Idmap> Idmap::FromApkAssets(const std::string& target_apk_
// encode idmap data
std::unique_ptr<IdmapData> data(new IdmapData());
- const auto types_end = matching_resources.map.cend();
- for (auto ti = matching_resources.map.cbegin(); ti != types_end; ++ti) {
+ const auto types_end = matching_resources.Map().cend();
+ for (auto ti = matching_resources.Map().cbegin(); ti != types_end; ++ti) {
auto ei = ti->second.cbegin();
std::unique_ptr<IdmapData::TypeEntry> type(new IdmapData::TypeEntry());
type->target_type_id_ = EXTRACT_TYPE(ei->first);
diff --git a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
index fb3bc5ba9ae8..b36df24a0da7 100644
--- a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp
@@ -49,17 +49,18 @@ void PrettyPrintVisitor::visit(const IdmapData::Header& header ATTRIBUTE_UNUSED)
last_seen_package_id_ = header.GetTargetPackageId();
}
-void PrettyPrintVisitor::visit(const IdmapData::TypeEntry& te) {
+void PrettyPrintVisitor::visit(const IdmapData::TypeEntry& type_entry) {
const bool target_package_loaded = !target_am_.GetApkAssets().empty();
- for (uint16_t i = 0; i < te.GetEntryCount(); i++) {
- const EntryId entry = te.GetEntry(i);
+ for (uint16_t i = 0; i < type_entry.GetEntryCount(); i++) {
+ const EntryId entry = type_entry.GetEntry(i);
if (entry == kNoEntry) {
continue;
}
const ResourceId target_resid =
- RESID(last_seen_package_id_, te.GetTargetTypeId(), te.GetEntryOffset() + i);
- const ResourceId overlay_resid = RESID(last_seen_package_id_, te.GetOverlayTypeId(), entry);
+ RESID(last_seen_package_id_, type_entry.GetTargetTypeId(), type_entry.GetEntryOffset() + i);
+ const ResourceId overlay_resid =
+ RESID(last_seen_package_id_, type_entry.GetOverlayTypeId(), entry);
stream_ << base::StringPrintf("0x%08x -> 0x%08x", target_resid, overlay_resid);
if (target_package_loaded) {
diff --git a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
index 7c24445ef902..a6bf5fb6e687 100644
--- a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
+++ b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp
@@ -59,22 +59,23 @@ void RawPrintVisitor::visit(const IdmapData::Header& header) {
last_seen_package_id_ = header.GetTargetPackageId();
}
-void RawPrintVisitor::visit(const IdmapData::TypeEntry& te) {
+void RawPrintVisitor::visit(const IdmapData::TypeEntry& type_entry) {
const bool target_package_loaded = !target_am_.GetApkAssets().empty();
- print(static_cast<uint16_t>(te.GetTargetTypeId()), "target type");
- print(static_cast<uint16_t>(te.GetOverlayTypeId()), "overlay type");
- print(static_cast<uint16_t>(te.GetEntryCount()), "entry count");
- print(static_cast<uint16_t>(te.GetEntryOffset()), "entry offset");
+ print(static_cast<uint16_t>(type_entry.GetTargetTypeId()), "target type");
+ print(static_cast<uint16_t>(type_entry.GetOverlayTypeId()), "overlay type");
+ print(static_cast<uint16_t>(type_entry.GetEntryCount()), "entry count");
+ print(static_cast<uint16_t>(type_entry.GetEntryOffset()), "entry offset");
- for (uint16_t i = 0; i < te.GetEntryCount(); i++) {
- const EntryId entry = te.GetEntry(i);
+ for (uint16_t i = 0; i < type_entry.GetEntryCount(); i++) {
+ const EntryId entry = type_entry.GetEntry(i);
if (entry == kNoEntry) {
print(kPadding, "no entry");
} else {
- const ResourceId target_resid =
- RESID(last_seen_package_id_, te.GetTargetTypeId(), te.GetEntryOffset() + i);
- const ResourceId overlay_resid = RESID(last_seen_package_id_, te.GetOverlayTypeId(), entry);
+ const ResourceId target_resid = RESID(last_seen_package_id_, type_entry.GetTargetTypeId(),
+ type_entry.GetEntryOffset() + i);
+ const ResourceId overlay_resid =
+ RESID(last_seen_package_id_, type_entry.GetOverlayTypeId(), entry);
Result<std::string> name;
if (target_package_loaded) {
name = utils::ResToTypeEntryName(target_am_, target_resid);
diff --git a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
index 8b552dcc1265..3b9dbe97e894 100644
--- a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
+++ b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp
@@ -29,7 +29,6 @@
#include "TestHelpers.h"
-using ::testing::IsNull;
using ::testing::NotNull;
namespace android {
@@ -52,14 +51,14 @@ TEST(BinaryStreamVisitorTests, CreateBinaryStreamViaBinaryStreamVisitor) {
ASSERT_EQ(idmap1->GetHeader()->GetTargetCrc(), idmap2->GetHeader()->GetTargetCrc());
ASSERT_EQ(idmap1->GetHeader()->GetTargetPath(), idmap2->GetHeader()->GetTargetPath());
- ASSERT_EQ(idmap1->GetData().size(), 1u);
+ ASSERT_EQ(idmap1->GetData().size(), 1U);
ASSERT_EQ(idmap1->GetData().size(), idmap2->GetData().size());
const auto& data1 = idmap1->GetData()[0];
const auto& data2 = idmap2->GetData()[0];
ASSERT_EQ(data1->GetHeader()->GetTargetPackageId(), data2->GetHeader()->GetTargetPackageId());
- ASSERT_EQ(data1->GetTypeEntries().size(), 2u);
+ ASSERT_EQ(data1->GetTypeEntries().size(), 2U);
ASSERT_EQ(data1->GetTypeEntries().size(), data2->GetTypeEntries().size());
ASSERT_EQ(data1->GetTypeEntries()[0]->GetEntry(0), data2->GetTypeEntries()[0]->GetEntry(0));
ASSERT_EQ(data1->GetTypeEntries()[0]->GetEntry(1), data2->GetTypeEntries()[0]->GetEntry(1));
diff --git a/cmds/idmap2/tests/CommandLineOptionsTests.cpp b/cmds/idmap2/tests/CommandLineOptionsTests.cpp
index b04b25660ee4..243d23a0f2db 100644
--- a/cmds/idmap2/tests/CommandLineOptionsTests.cpp
+++ b/cmds/idmap2/tests/CommandLineOptionsTests.cpp
@@ -38,14 +38,12 @@
#include "TestHelpers.h"
-using ::testing::NotNull;
-
namespace android {
namespace idmap2 {
TEST(CommandLineOptionsTests, Flag) {
- bool foo = true, bar = false;
-
+ bool foo = true;
+ bool bar = false;
CommandLineOptions opts =
CommandLineOptions("test").OptionalFlag("--foo", "", &foo).OptionalFlag("--bar", "", &bar);
@@ -63,7 +61,8 @@ TEST(CommandLineOptionsTests, Flag) {
}
TEST(CommandLineOptionsTests, MandatoryOption) {
- std::string foo, bar;
+ std::string foo;
+ std::string bar;
CommandLineOptions opts = CommandLineOptions("test")
.MandatoryOption("--foo", "", &foo)
.MandatoryOption("--bar", "", &bar);
@@ -92,13 +91,14 @@ TEST(CommandLineOptionsTests, MandatoryOptionMultipleArgsAndExpectedOnceOrMore)
std::ostream fakeStdErr(nullptr);
bool success = opts.Parse({"--foo", "FOO", "--foo", "BAR"}, fakeStdErr);
ASSERT_TRUE(success);
- ASSERT_EQ(args.size(), 2u);
+ ASSERT_EQ(args.size(), 2U);
ASSERT_EQ(args[0], "FOO");
ASSERT_EQ(args[1], "BAR");
}
TEST(CommandLineOptionsTests, OptionalOption) {
- std::string foo, bar;
+ std::string foo;
+ std::string bar;
CommandLineOptions opts = CommandLineOptions("test")
.OptionalOption("--foo", "", &foo)
.OptionalOption("--bar", "", &bar);
@@ -123,7 +123,8 @@ TEST(CommandLineOptionsTests, OptionalOption) {
}
TEST(CommandLineOptionsTests, CornerCases) {
- std::string foo, bar;
+ std::string foo;
+ std::string bar;
bool baz = false;
CommandLineOptions opts = CommandLineOptions("test")
.MandatoryOption("--foo", "", &foo)
@@ -150,7 +151,7 @@ TEST(CommandLineOptionsTests, ConvertArgvToVector) {
nullptr,
};
std::unique_ptr<std::vector<std::string>> v = CommandLineOptions::ConvertArgvToVector(3, argv);
- ASSERT_EQ(v->size(), 2ul);
+ ASSERT_EQ(v->size(), 2UL);
ASSERT_EQ((*v)[0], "--foo");
ASSERT_EQ((*v)[1], "FOO");
}
@@ -161,12 +162,16 @@ TEST(CommandLineOptionsTests, ConvertArgvToVectorNoArgs) {
nullptr,
};
std::unique_ptr<std::vector<std::string>> v = CommandLineOptions::ConvertArgvToVector(1, argv);
- ASSERT_EQ(v->size(), 0ul);
+ ASSERT_EQ(v->size(), 0UL);
}
TEST(CommandLineOptionsTests, Usage) {
- std::string arg1, arg2, arg3, arg4;
- bool arg5 = false, arg6 = false;
+ std::string arg1;
+ std::string arg2;
+ std::string arg3;
+ std::string arg4;
+ bool arg5 = false;
+ bool arg6 = false;
std::vector<std::string> arg7;
CommandLineOptions opts = CommandLineOptions("test")
.MandatoryOption("--aa", "description-aa", &arg1)
diff --git a/cmds/idmap2/tests/FileUtilsTests.cpp b/cmds/idmap2/tests/FileUtilsTests.cpp
index 0c6439ab8c0c..6584ee32a509 100644
--- a/cmds/idmap2/tests/FileUtilsTests.cpp
+++ b/cmds/idmap2/tests/FileUtilsTests.cpp
@@ -39,7 +39,7 @@ TEST(FileUtilsTests, FindFilesFindEverythingNonRecursive) {
[](unsigned char type ATTRIBUTE_UNUSED,
const std::string& path ATTRIBUTE_UNUSED) -> bool { return true; });
ASSERT_THAT(v, NotNull());
- ASSERT_EQ(v->size(), 4u);
+ ASSERT_EQ(v->size(), 4U);
ASSERT_EQ(
std::set<std::string>(v->begin(), v->end()),
std::set<std::string>({root + "/.", root + "/..", root + "/overlay", root + "/target"}));
@@ -48,10 +48,10 @@ TEST(FileUtilsTests, FindFilesFindEverythingNonRecursive) {
TEST(FileUtilsTests, FindFilesFindApkFilesRecursive) {
const auto& root = GetTestDataPath();
auto v = utils::FindFiles(root, true, [](unsigned char type, const std::string& path) -> bool {
- return type == DT_REG && path.size() > 4 && !path.compare(path.size() - 4, 4, ".apk");
+ return type == DT_REG && path.size() > 4 && path.compare(path.size() - 4, 4, ".apk") == 0;
});
ASSERT_THAT(v, NotNull());
- ASSERT_EQ(v->size(), 4u);
+ ASSERT_EQ(v->size(), 4U);
ASSERT_EQ(std::set<std::string>(v->begin(), v->end()),
std::set<std::string>({root + "/target/target.apk", root + "/overlay/overlay.apk",
root + "/overlay/overlay-static-1.apk",
diff --git a/cmds/idmap2/tests/Idmap2BinaryTests.cpp b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
index 5c4e8576985b..255f3c102b85 100644
--- a/cmds/idmap2/tests/Idmap2BinaryTests.cpp
+++ b/cmds/idmap2/tests/Idmap2BinaryTests.cpp
@@ -51,15 +51,17 @@ namespace idmap2 {
class Idmap2BinaryTests : public Idmap2Tests {};
-static void AssertIdmap(const Idmap& idmap, const std::string& target_apk_path,
- const std::string& overlay_apk_path) {
+namespace {
+
+void AssertIdmap(const Idmap& idmap, const std::string& target_apk_path,
+ const std::string& overlay_apk_path) {
// check that the idmap file looks reasonable (IdmapTests is responsible for
// more in-depth verification)
ASSERT_EQ(idmap.GetHeader()->GetMagic(), kIdmapMagic);
ASSERT_EQ(idmap.GetHeader()->GetVersion(), kIdmapCurrentVersion);
ASSERT_EQ(idmap.GetHeader()->GetTargetPath(), target_apk_path);
ASSERT_EQ(idmap.GetHeader()->GetOverlayPath(), overlay_apk_path);
- ASSERT_EQ(idmap.GetData().size(), 1u);
+ ASSERT_EQ(idmap.GetData().size(), 1U);
}
#define ASSERT_IDMAP(idmap_ref, target_apk_path, overlay_apk_path) \
@@ -67,6 +69,8 @@ static void AssertIdmap(const Idmap& idmap, const std::string& target_apk_path,
ASSERT_NO_FATAL_FAILURE(AssertIdmap(idmap_ref, target_apk_path, overlay_apk_path)); \
} while (0)
+} // namespace
+
TEST_F(Idmap2BinaryTests, Create) {
// clang-format off
auto result = ExecuteBinary({"idmap2",
diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp
index 0379aa491682..dc80e0e145ac 100644
--- a/cmds/idmap2/tests/IdmapTests.cpp
+++ b/cmds/idmap2/tests/IdmapTests.cpp
@@ -50,10 +50,10 @@ TEST(IdmapTests, CreateIdmapHeaderFromBinaryStream) {
std::istringstream stream(raw);
std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream);
ASSERT_THAT(header, NotNull());
- ASSERT_EQ(header->GetMagic(), 0x504d4449u);
- ASSERT_EQ(header->GetVersion(), 0x01u);
- ASSERT_EQ(header->GetTargetCrc(), 0x1234u);
- ASSERT_EQ(header->GetOverlayCrc(), 0x5678u);
+ ASSERT_EQ(header->GetMagic(), 0x504d4449U);
+ ASSERT_EQ(header->GetVersion(), 0x01U);
+ ASSERT_EQ(header->GetTargetCrc(), 0x1234U);
+ ASSERT_EQ(header->GetOverlayCrc(), 0x5678U);
ASSERT_EQ(header->GetTargetPath().to_string(), "target.apk");
ASSERT_EQ(header->GetOverlayPath().to_string(), "overlay.apk");
}
@@ -77,8 +77,8 @@ TEST(IdmapTests, CreateIdmapDataHeaderFromBinaryStream) {
std::unique_ptr<const IdmapData::Header> header = IdmapData::Header::FromBinaryStream(stream);
ASSERT_THAT(header, NotNull());
- ASSERT_EQ(header->GetTargetPackageId(), 0x7fu);
- ASSERT_EQ(header->GetTypeCount(), 2u);
+ ASSERT_EQ(header->GetTargetPackageId(), 0x7fU);
+ ASSERT_EQ(header->GetTypeCount(), 2U);
}
TEST(IdmapTests, CreateIdmapDataResourceTypeFromBinaryStream) {
@@ -89,11 +89,11 @@ TEST(IdmapTests, CreateIdmapDataResourceTypeFromBinaryStream) {
std::unique_ptr<const IdmapData::TypeEntry> data = IdmapData::TypeEntry::FromBinaryStream(stream);
ASSERT_THAT(data, NotNull());
- ASSERT_EQ(data->GetTargetTypeId(), 0x02u);
- ASSERT_EQ(data->GetOverlayTypeId(), 0x02u);
- ASSERT_EQ(data->GetEntryCount(), 1u);
- ASSERT_EQ(data->GetEntryOffset(), 0u);
- ASSERT_EQ(data->GetEntry(0), 0u);
+ ASSERT_EQ(data->GetTargetTypeId(), 0x02U);
+ ASSERT_EQ(data->GetOverlayTypeId(), 0x02U);
+ ASSERT_EQ(data->GetEntryCount(), 1U);
+ ASSERT_EQ(data->GetEntryOffset(), 0U);
+ ASSERT_EQ(data->GetEntry(0), 0U);
}
TEST(IdmapTests, CreateIdmapDataFromBinaryStream) {
@@ -104,24 +104,24 @@ TEST(IdmapTests, CreateIdmapDataFromBinaryStream) {
std::unique_ptr<const IdmapData> data = IdmapData::FromBinaryStream(stream);
ASSERT_THAT(data, NotNull());
- ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fu);
- ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2u);
+ ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
+ ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);
const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
- ASSERT_EQ(types.size(), 2u);
-
- ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02u);
- ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x02u);
- ASSERT_EQ(types[0]->GetEntryCount(), 1u);
- ASSERT_EQ(types[0]->GetEntryOffset(), 0u);
- ASSERT_EQ(types[0]->GetEntry(0), 0x0000u);
-
- ASSERT_EQ(types[1]->GetTargetTypeId(), 0x03u);
- ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x03u);
- ASSERT_EQ(types[1]->GetEntryCount(), 3u);
- ASSERT_EQ(types[1]->GetEntryOffset(), 3u);
- ASSERT_EQ(types[1]->GetEntry(0), 0x0000u);
+ ASSERT_EQ(types.size(), 2U);
+
+ ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
+ ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x02U);
+ ASSERT_EQ(types[0]->GetEntryCount(), 1U);
+ ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
+ ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);
+
+ ASSERT_EQ(types[1]->GetTargetTypeId(), 0x03U);
+ ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x03U);
+ ASSERT_EQ(types[1]->GetEntryCount(), 3U);
+ ASSERT_EQ(types[1]->GetEntryOffset(), 3U);
+ ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
- ASSERT_EQ(types[1]->GetEntry(2), 0x0001u);
+ ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
}
TEST(IdmapTests, CreateIdmapFromBinaryStream) {
@@ -133,35 +133,35 @@ TEST(IdmapTests, CreateIdmapFromBinaryStream) {
ASSERT_THAT(idmap, NotNull());
ASSERT_THAT(idmap->GetHeader(), NotNull());
- ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449u);
- ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x01u);
- ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x1234u);
- ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x5678u);
+ ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
+ ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x01U);
+ ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x1234U);
+ ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x5678U);
ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), "target.apk");
ASSERT_EQ(idmap->GetHeader()->GetOverlayPath().to_string(), "overlay.apk");
const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
- ASSERT_EQ(dataBlocks.size(), 1u);
+ ASSERT_EQ(dataBlocks.size(), 1U);
const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
- ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fu);
- ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2u);
+ ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
+ ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);
const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
- ASSERT_EQ(types.size(), 2u);
-
- ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02u);
- ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x02u);
- ASSERT_EQ(types[0]->GetEntryCount(), 1u);
- ASSERT_EQ(types[0]->GetEntryOffset(), 0u);
- ASSERT_EQ(types[0]->GetEntry(0), 0x0000u);
-
- ASSERT_EQ(types[1]->GetTargetTypeId(), 0x03u);
- ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x03u);
- ASSERT_EQ(types[1]->GetEntryCount(), 3u);
- ASSERT_EQ(types[1]->GetEntryOffset(), 3u);
- ASSERT_EQ(types[1]->GetEntry(0), 0x0000u);
+ ASSERT_EQ(types.size(), 2U);
+
+ ASSERT_EQ(types[0]->GetTargetTypeId(), 0x02U);
+ ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x02U);
+ ASSERT_EQ(types[0]->GetEntryCount(), 1U);
+ ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
+ ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);
+
+ ASSERT_EQ(types[1]->GetTargetTypeId(), 0x03U);
+ ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x03U);
+ ASSERT_EQ(types[1]->GetEntryCount(), 3U);
+ ASSERT_EQ(types[1]->GetEntryOffset(), 3U);
+ ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
- ASSERT_EQ(types[1]->GetEntry(2), 0x0001u);
+ ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
}
TEST(IdmapTests, GracefullyFailToCreateIdmapFromCorruptBinaryStream) {
@@ -189,8 +189,8 @@ TEST(IdmapTests, CreateIdmapFromApkAssets) {
ASSERT_THAT(idmap, NotNull());
ASSERT_THAT(idmap->GetHeader(), NotNull());
- ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449u);
- ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x01u);
+ ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U);
+ ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x01U);
ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0xf5ad1d1d);
ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0xd470336b);
ASSERT_EQ(idmap->GetHeader()->GetTargetPath().to_string(), target_apk_path);
@@ -198,30 +198,30 @@ TEST(IdmapTests, CreateIdmapFromApkAssets) {
ASSERT_EQ(idmap->GetHeader()->GetOverlayPath(), overlay_apk_path);
const std::vector<std::unique_ptr<const IdmapData>>& dataBlocks = idmap->GetData();
- ASSERT_EQ(dataBlocks.size(), 1u);
+ ASSERT_EQ(dataBlocks.size(), 1U);
const std::unique_ptr<const IdmapData>& data = dataBlocks[0];
- ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fu);
- ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2u);
+ ASSERT_EQ(data->GetHeader()->GetTargetPackageId(), 0x7fU);
+ ASSERT_EQ(data->GetHeader()->GetTypeCount(), 2U);
const std::vector<std::unique_ptr<const IdmapData::TypeEntry>>& types = data->GetTypeEntries();
- ASSERT_EQ(types.size(), 2u);
-
- ASSERT_EQ(types[0]->GetTargetTypeId(), 0x01u);
- ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01u);
- ASSERT_EQ(types[0]->GetEntryCount(), 1u);
- ASSERT_EQ(types[0]->GetEntryOffset(), 0u);
- ASSERT_EQ(types[0]->GetEntry(0), 0x0000u);
-
- ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02u);
- ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02u);
- ASSERT_EQ(types[1]->GetEntryCount(), 4u);
- ASSERT_EQ(types[1]->GetEntryOffset(), 3u);
- ASSERT_EQ(types[1]->GetEntry(0), 0x0000u);
+ ASSERT_EQ(types.size(), 2U);
+
+ ASSERT_EQ(types[0]->GetTargetTypeId(), 0x01U);
+ ASSERT_EQ(types[0]->GetOverlayTypeId(), 0x01U);
+ ASSERT_EQ(types[0]->GetEntryCount(), 1U);
+ ASSERT_EQ(types[0]->GetEntryOffset(), 0U);
+ ASSERT_EQ(types[0]->GetEntry(0), 0x0000U);
+
+ ASSERT_EQ(types[1]->GetTargetTypeId(), 0x02U);
+ ASSERT_EQ(types[1]->GetOverlayTypeId(), 0x02U);
+ ASSERT_EQ(types[1]->GetEntryCount(), 4U);
+ ASSERT_EQ(types[1]->GetEntryOffset(), 3U);
+ ASSERT_EQ(types[1]->GetEntry(0), 0x0000U);
ASSERT_EQ(types[1]->GetEntry(1), kNoEntry);
- ASSERT_EQ(types[1]->GetEntry(2), 0x0001u);
- ASSERT_EQ(types[1]->GetEntry(3), 0x0002u);
+ ASSERT_EQ(types[1]->GetEntry(2), 0x0001U);
+ ASSERT_EQ(types[1]->GetEntry(3), 0x0002U);
}
TEST(IdmapTests, FailToCreateIdmapFromApkAssetsIfPathTooLong) {
diff --git a/cmds/idmap2/tests/Main.cpp b/cmds/idmap2/tests/Main.cpp
index f2469eaf57cc..0f683ffd8eef 100644
--- a/cmds/idmap2/tests/Main.cpp
+++ b/cmds/idmap2/tests/Main.cpp
@@ -25,7 +25,7 @@
namespace android {
namespace idmap2 {
-const std::string GetTestDataPath() {
+std::string GetTestDataPath() {
return base::GetExecutableDirectory() + "/tests/data";
}
diff --git a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
index da9779211f81..0c4f493e9f6c 100644
--- a/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/PrettyPrintVisitorTests.cpp
@@ -29,7 +29,6 @@
#include "TestHelpers.h"
-using ::testing::IsNull;
using ::testing::NotNull;
using android::ApkAssets;
diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
index c28ce2e02ea9..6285f217b21e 100644
--- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp
+++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp
@@ -27,7 +27,6 @@
#include "TestHelpers.h"
-using ::testing::IsNull;
using ::testing::NotNull;
namespace android {
diff --git a/cmds/idmap2/tests/ResourceUtilsTests.cpp b/cmds/idmap2/tests/ResourceUtilsTests.cpp
index 7f60d7529a61..c8578d3b340a 100644
--- a/cmds/idmap2/tests/ResourceUtilsTests.cpp
+++ b/cmds/idmap2/tests/ResourceUtilsTests.cpp
@@ -52,13 +52,13 @@ class ResourceUtilsTests : public Idmap2Tests {
};
TEST_F(ResourceUtilsTests, ResToTypeEntryName) {
- Result<std::string> name = utils::ResToTypeEntryName(GetAssetManager(), 0x7f010000u);
+ Result<std::string> name = utils::ResToTypeEntryName(GetAssetManager(), 0x7f010000U);
ASSERT_TRUE(name);
ASSERT_EQ(*name, "integer/int1");
}
TEST_F(ResourceUtilsTests, ResToTypeEntryNameNoSuchResourceId) {
- Result<std::string> name = utils::ResToTypeEntryName(GetAssetManager(), 0x7f123456u);
+ Result<std::string> name = utils::ResToTypeEntryName(GetAssetManager(), 0x7f123456U);
ASSERT_FALSE(name);
}
diff --git a/cmds/idmap2/tests/TestHelpers.h b/cmds/idmap2/tests/TestHelpers.h
index 18dc541021c1..356db7af1385 100644
--- a/cmds/idmap2/tests/TestHelpers.h
+++ b/cmds/idmap2/tests/TestHelpers.h
@@ -117,7 +117,7 @@ const unsigned char idmap_raw_data[] = {
const unsigned int idmap_raw_data_len = 565;
-const std::string GetTestDataPath();
+std::string GetTestDataPath();
class Idmap2Tests : public testing::Test {
protected:
diff --git a/cmds/idmap2/tests/XmlTests.cpp b/cmds/idmap2/tests/XmlTests.cpp
index 97ff03e0f9e3..40758b42e1ff 100644
--- a/cmds/idmap2/tests/XmlTests.cpp
+++ b/cmds/idmap2/tests/XmlTests.cpp
@@ -58,11 +58,11 @@ TEST(XmlTests, FindTag) {
auto attrs = xml->FindTag("c");
ASSERT_THAT(attrs, NotNull());
- ASSERT_EQ(attrs->size(), 4u);
+ ASSERT_EQ(attrs->size(), 4U);
ASSERT_EQ(attrs->at("type_string"), "fortytwo");
ASSERT_EQ(std::stoi(attrs->at("type_int_dec")), 42);
ASSERT_EQ(std::stoi(attrs->at("type_int_hex")), 42);
- ASSERT_NE(std::stoul(attrs->at("type_int_boolean")), 0u);
+ ASSERT_NE(std::stoul(attrs->at("type_int_boolean")), 0U);
auto fail = xml->FindTag("does-not-exist");
ASSERT_THAT(fail, IsNull());
diff --git a/cmds/incident_helper/src/TextParserBase.h b/cmds/incident_helper/src/TextParserBase.h
index 784c181d9741..a6074e71c035 100644
--- a/cmds/incident_helper/src/TextParserBase.h
+++ b/cmds/incident_helper/src/TextParserBase.h
@@ -30,7 +30,7 @@ class TextParserBase {
public:
String8 name;
- TextParserBase(String8 name) : name(name) {};
+ explicit TextParserBase(String8 name) : name(name) {};
virtual ~TextParserBase() {};
virtual status_t Parse(const int in, const int out) const = 0;
diff --git a/cmds/incident_helper/src/ih_util.h b/cmds/incident_helper/src/ih_util.h
index c02a3493724a..09dc8e6fdbfc 100644
--- a/cmds/incident_helper/src/ih_util.h
+++ b/cmds/incident_helper/src/ih_util.h
@@ -109,7 +109,7 @@ double toDouble(const std::string& s);
class Reader
{
public:
- Reader(const int fd);
+ explicit Reader(const int fd);
~Reader();
bool readLine(std::string* line);
@@ -162,7 +162,7 @@ private:
class Message
{
public:
- Message(Table* table);
+ explicit Message(Table* table);
~Message();
// Reconstructs the typical proto message by adding its message fields.
diff --git a/cmds/incidentd/src/IncidentService.h b/cmds/incidentd/src/IncidentService.h
index 6252ad295224..c63a183b70b9 100644
--- a/cmds/incidentd/src/IncidentService.h
+++ b/cmds/incidentd/src/IncidentService.h
@@ -97,7 +97,7 @@ private:
// ================================================================================
class IncidentService : public BnIncidentManager {
public:
- IncidentService(const sp<Looper>& handlerLooper);
+ explicit IncidentService(const sp<Looper>& handlerLooper);
virtual ~IncidentService();
virtual Status reportIncident(const IncidentReportArgs& args);
diff --git a/cmds/incidentd/src/Privacy.h b/cmds/incidentd/src/Privacy.h
index a3df4903de45..a0159d9a8649 100644
--- a/cmds/incidentd/src/Privacy.h
+++ b/cmds/incidentd/src/Privacy.h
@@ -83,7 +83,7 @@ public:
static PrivacySpec new_spec(int dest);
private:
- PrivacySpec(uint8_t dest) : dest(dest) {}
+ explicit PrivacySpec(uint8_t dest) : dest(dest) {}
};
} // namespace incidentd
diff --git a/cmds/incidentd/src/Reporter.h b/cmds/incidentd/src/Reporter.h
index 45fd9443e9d0..2a3abd7b4d97 100644
--- a/cmds/incidentd/src/Reporter.h
+++ b/cmds/incidentd/src/Reporter.h
@@ -89,7 +89,7 @@ public:
ReportRequestSet batch;
Reporter(); // PROD must use this constructor.
- Reporter(const char* directory); // For testing purpose only.
+ explicit Reporter(const char* directory); // For testing purpose only.
virtual ~Reporter();
// Run the report as described in the batch and args parameters.
diff --git a/cmds/incidentd/src/Section.cpp b/cmds/incidentd/src/Section.cpp
index 10d226822331..32ec1ba90cda 100644
--- a/cmds/incidentd/src/Section.cpp
+++ b/cmds/incidentd/src/Section.cpp
@@ -415,7 +415,7 @@ struct WorkerThreadData : public virtual RefBase {
bool workerDone;
status_t workerError;
- WorkerThreadData(const WorkerThreadSection* section);
+ explicit WorkerThreadData(const WorkerThreadSection* section);
virtual ~WorkerThreadData();
};
diff --git a/cmds/statsd/src/anomaly/AlarmMonitor.h b/cmds/statsd/src/anomaly/AlarmMonitor.h
index 3badb1faece6..bca858e67f13 100644
--- a/cmds/statsd/src/anomaly/AlarmMonitor.h
+++ b/cmds/statsd/src/anomaly/AlarmMonitor.h
@@ -42,7 +42,7 @@ namespace statsd {
* Timestamps are in seconds since epoch in a uint32, so will fail in year 2106.
*/
struct InternalAlarm : public RefBase {
- InternalAlarm(uint32_t timestampSec) : timestampSec(timestampSec) {
+ explicit InternalAlarm(uint32_t timestampSec) : timestampSec(timestampSec) {
}
const uint32_t timestampSec;
diff --git a/cmds/statsd/src/condition/ConditionWizard.h b/cmds/statsd/src/condition/ConditionWizard.h
index a6f88af4b4d6..2c8814772839 100644
--- a/cmds/statsd/src/condition/ConditionWizard.h
+++ b/cmds/statsd/src/condition/ConditionWizard.h
@@ -29,7 +29,7 @@ namespace statsd {
class ConditionWizard : public virtual android::RefBase {
public:
ConditionWizard(){}; // for testing
- ConditionWizard(std::vector<sp<ConditionTracker>>& conditionTrackers)
+ explicit ConditionWizard(std::vector<sp<ConditionTracker>>& conditionTrackers)
: mAllConditions(conditionTrackers){};
virtual ~ConditionWizard(){};
diff --git a/cmds/statsd/src/config/ConfigKey.h b/cmds/statsd/src/config/ConfigKey.h
index dc79519d1f34..4cc9393fbd02 100644
--- a/cmds/statsd/src/config/ConfigKey.h
+++ b/cmds/statsd/src/config/ConfigKey.h
@@ -33,7 +33,7 @@ using std::string;
class ConfigKey {
public:
ConfigKey();
- explicit ConfigKey(const ConfigKey& that);
+ ConfigKey(const ConfigKey& that);
ConfigKey(int uid, const int64_t& id);
~ConfigKey();
diff --git a/cmds/statsd/src/external/ResourceHealthManagerPuller.h b/cmds/statsd/src/external/ResourceHealthManagerPuller.h
index 9b238eaf5f83..ba6e6c33b1a5 100644
--- a/cmds/statsd/src/external/ResourceHealthManagerPuller.h
+++ b/cmds/statsd/src/external/ResourceHealthManagerPuller.h
@@ -28,7 +28,7 @@ namespace statsd {
*/
class ResourceHealthManagerPuller : public StatsPuller {
public:
- ResourceHealthManagerPuller(int tagId);
+ explicit ResourceHealthManagerPuller(int tagId);
bool PullInternal(vector<std::shared_ptr<LogEvent>>* data) override;
};
diff --git a/cmds/statsd/src/external/StatsCompanionServicePuller.h b/cmds/statsd/src/external/StatsCompanionServicePuller.h
index 0a49732fe120..a16baf025a34 100644
--- a/cmds/statsd/src/external/StatsCompanionServicePuller.h
+++ b/cmds/statsd/src/external/StatsCompanionServicePuller.h
@@ -25,7 +25,7 @@ namespace statsd {
class StatsCompanionServicePuller : public StatsPuller {
public:
- StatsCompanionServicePuller(int tagId);
+ explicit StatsCompanionServicePuller(int tagId);
bool PullInternal(vector<std::shared_ptr<LogEvent> >* data) override;
void SetStatsCompanionService(sp<IStatsCompanionService> statsCompanionService) override;
diff --git a/cmds/statsd/src/external/StatsPuller.h b/cmds/statsd/src/external/StatsPuller.h
index cafd7979601a..f8ecb87eafd4 100644
--- a/cmds/statsd/src/external/StatsPuller.h
+++ b/cmds/statsd/src/external/StatsPuller.h
@@ -33,7 +33,7 @@ namespace statsd {
class StatsPuller : public virtual RefBase {
public:
- StatsPuller(const int tagId);
+ explicit StatsPuller(const int tagId);
virtual ~StatsPuller() {}
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index 5408d17b02b2..4e37e9b004ca 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -212,7 +212,7 @@ private:
* Don't copy, it's slower. If we really need this we can add it but let's try to
* avoid it.
*/
- explicit LogEvent(const LogEvent&);
+ LogEvent(const LogEvent&);
/**
* Parses a log_msg into a LogEvent object.
diff --git a/cmds/statsd/src/socket/StatsSocketListener.h b/cmds/statsd/src/socket/StatsSocketListener.h
index 73e4d33d3e18..b8185d2a32d2 100644
--- a/cmds/statsd/src/socket/StatsSocketListener.h
+++ b/cmds/statsd/src/socket/StatsSocketListener.h
@@ -35,7 +35,7 @@ namespace statsd {
class StatsSocketListener : public SocketListener, public virtual android::RefBase {
public:
- StatsSocketListener(const sp<LogListener>& listener);
+ explicit StatsSocketListener(const sp<LogListener>& listener);
virtual ~StatsSocketListener();
@@ -51,4 +51,4 @@ private:
};
} // namespace statsd
} // namespace os
-} // namespace android \ No newline at end of file
+} // namespace android
diff --git a/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java b/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java
index 02de7f05be7c..0775afeaeda4 100644
--- a/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java
+++ b/cmds/statsd/tools/localtools/src/com/android/statsd/shelltools/testdrive/TestDrive.java
@@ -16,209 +16,193 @@
package com.android.statsd.shelltools.testdrive;
import com.android.internal.os.StatsdConfigProto.AtomMatcher;
+import com.android.internal.os.StatsdConfigProto.EventMetric;
+import com.android.internal.os.StatsdConfigProto.FieldFilter;
+import com.android.internal.os.StatsdConfigProto.GaugeMetric;
import com.android.internal.os.StatsdConfigProto.SimpleAtomMatcher;
import com.android.internal.os.StatsdConfigProto.StatsdConfig;
+import com.android.internal.os.StatsdConfigProto.TimeUnit;
import com.android.os.AtomsProto.Atom;
import com.android.os.StatsLog.ConfigMetricsReport;
import com.android.os.StatsLog.ConfigMetricsReportList;
+import com.android.os.StatsLog.StatsLogReport;
import com.android.statsd.shelltools.Utils;
import com.google.common.io.Files;
-import com.google.protobuf.TextFormat;
-import com.google.protobuf.TextFormat.ParseException;
import java.io.File;
import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
public class TestDrive {
- public static final int PULL_ATOM_START = 10000;
- public static final long ATOM_MATCHER_ID = 1234567;
-
- public static final long CONFIG_ID = 54321;
-
- private static boolean mIsPushedAtom = false;
-
- private static final Logger logger = Logger.getLogger(TestDrive.class.getName());
+ private static final int METRIC_ID_BASE = 1111;
+ private static final long ATOM_MATCHER_ID_BASE = 1234567;
+ private static final int PULL_ATOM_START = 10000;
+ private static final long CONFIG_ID = 54321;
+ private static final String[] ALLOWED_LOG_SOURCES = {
+ "AID_GRAPHICS",
+ "AID_INCIDENTD",
+ "AID_STATSD",
+ "AID_RADIO",
+ "com.android.systemui",
+ "com.android.vending",
+ "AID_SYSTEM",
+ "AID_ROOT",
+ "AID_BLUETOOTH",
+ "AID_LMKD"
+ };
+ private static final Logger LOGGER = Logger.getLogger(TestDrive.class.getName());
+
+ private final Set<Long> mTrackedMetrics = new HashSet<>();
public static void main(String[] args) {
TestDrive testDrive = new TestDrive();
- Utils.setUpLogger(logger, false);
+ Set<Integer> trackedAtoms = new HashSet<>();
+ Utils.setUpLogger(LOGGER, false);
+ String remoteConfigPath = null;
- if (args.length != 1) {
- logger.log(Level.SEVERE, "Usage: ./test_drive <atomId>");
- return;
- }
- int atomId;
- try {
- atomId = Integer.valueOf(args[0]);
- } catch (NumberFormatException e) {
- logger.log(Level.SEVERE, "Bad atom id provided: " + args[0]);
- return;
- }
- if (Atom.getDescriptor().findFieldByNumber(atomId) == null) {
- logger.log(Level.SEVERE, "No such atom found: " + args[0]);
+ if (args.length < 1) {
+ LOGGER.log(Level.SEVERE, "Usage: ./test_drive <atomId1> <atomId2> ... <atomIdN>");
return;
}
- mIsPushedAtom = atomId < PULL_ATOM_START;
+ for (int i = 0; i < args.length; i++) {
+ try {
+ int atomId = Integer.valueOf(args[i]);
+ if (Atom.getDescriptor().findFieldByNumber(atomId) == null) {
+ LOGGER.log(Level.SEVERE, "No such atom found: " + args[i]);
+ continue;
+ }
+ trackedAtoms.add(atomId);
+ } catch (NumberFormatException e) {
+ LOGGER.log(Level.SEVERE, "Bad atom id provided: " + args[i]);
+ continue;
+ }
+ }
try {
- StatsdConfig config = testDrive.createConfig(atomId);
+ StatsdConfig config = testDrive.createConfig(trackedAtoms);
if (config == null) {
- logger.log(Level.SEVERE, "Failed to create valid config.");
+ LOGGER.log(Level.SEVERE, "Failed to create valid config.");
return;
}
- testDrive.pushConfig(config);
- logger.info("Pushed the following config to statsd:");
- logger.info(config.toString());
- if (mIsPushedAtom) {
- logger.info(
+ remoteConfigPath = testDrive.pushConfig(config);
+ LOGGER.info("Pushed the following config to statsd:");
+ LOGGER.info(config.toString());
+ if (!hasPulledAtom(trackedAtoms)) {
+ LOGGER.info(
"Now please play with the device to trigger the event. All events should "
+ "be dumped after 1 min ...");
Thread.sleep(60_000);
} else {
// wait for 2 min
- logger.info("Now wait for 2 minutes ...");
+ LOGGER.info("Now wait for 2 minutes ...");
Thread.sleep(120_000);
}
testDrive.dumpMetrics();
} catch (Exception e) {
- logger.log(Level.SEVERE, "Failed to test drive: " + e.getMessage());
+ LOGGER.log(Level.SEVERE, "Failed to test drive: " + e.getMessage(), e);
} finally {
testDrive.removeConfig();
+ if (remoteConfigPath != null) {
+ try {
+ Utils.runCommand(null, LOGGER, "adb", "shell", "rm", remoteConfigPath);
+ } catch (Exception e) {
+ LOGGER.log(Level.WARNING,
+ "Unable to remove remote config file: " + remoteConfigPath, e);
+ }
+ }
}
}
- private void pushConfig(StatsdConfig config) throws IOException, InterruptedException {
- File configFile = File.createTempFile("statsdconfig", ".config");
- configFile.deleteOnExit();
- Files.write(config.toByteArray(), configFile);
- String remotePath = "/data/local/tmp/" + configFile.getName();
- Utils.runCommand(null, logger, "adb", "push", configFile.getAbsolutePath(), remotePath);
- Utils.runCommand(null, logger,
- "adb", "shell", "cat", remotePath, "|", Utils.CMD_UPDATE_CONFIG,
- String.valueOf(CONFIG_ID));
- }
-
- private void removeConfig() {
- try {
- Utils.runCommand(null, logger,
- "adb", "shell", Utils.CMD_REMOVE_CONFIG, String.valueOf(CONFIG_ID));
- } catch (Exception e) {
- logger.log(Level.SEVERE, "Failed to remove config: " + e.getMessage());
+ private void dumpMetrics() throws Exception {
+ ConfigMetricsReportList reportList = Utils.getReportList(CONFIG_ID, true, false, LOGGER);
+ // We may get multiple reports. Take the last one.
+ ConfigMetricsReport report = reportList.getReports(reportList.getReportsCount() - 1);
+ for (StatsLogReport statsLog : report.getMetricsList()) {
+ if (mTrackedMetrics.contains(statsLog.getMetricId())) {
+ LOGGER.info(statsLog.toString());
+ }
}
}
- private StatsdConfig createConfig(int atomId) {
- try {
- if (mIsPushedAtom) {
- return createSimpleEventMetricConfig(atomId);
+ private StatsdConfig createConfig(Set<Integer> atomIds) {
+ long metricId = METRIC_ID_BASE;
+ long atomMatcherId = ATOM_MATCHER_ID_BASE;
+
+ StatsdConfig.Builder builder = StatsdConfig.newBuilder();
+ builder
+ .addAllAllowedLogSource(Arrays.asList(ALLOWED_LOG_SOURCES))
+ .setHashStringsInMetricReport(false);
+
+ for (int atomId : atomIds) {
+ if (isPulledAtom(atomId)) {
+ builder.addAtomMatcher(createAtomMatcher(atomId, atomMatcherId));
+ GaugeMetric.Builder gaugeMetricBuilder = GaugeMetric.newBuilder();
+ gaugeMetricBuilder
+ .setId(metricId)
+ .setWhat(atomMatcherId)
+ .setGaugeFieldsFilter(FieldFilter.newBuilder().setIncludeAll(true).build())
+ .setBucket(TimeUnit.ONE_MINUTE);
+ builder.addGaugeMetric(gaugeMetricBuilder.build());
} else {
- return createSimpleGaugeMetricConfig(atomId);
+ EventMetric.Builder eventMetricBuilder = EventMetric.newBuilder();
+ eventMetricBuilder
+ .setId(metricId)
+ .setWhat(atomMatcherId);
+ builder.addEventMetric(eventMetricBuilder.build());
+ builder.addAtomMatcher(createAtomMatcher(atomId, atomMatcherId));
}
- } catch (ParseException e) {
- logger.log(
- Level.SEVERE,
- "Failed to parse the config! line: "
- + e.getLine()
- + " col: "
- + e.getColumn()
- + " "
- + e.getMessage());
+ atomMatcherId++;
+ mTrackedMetrics.add(metricId++);
}
- return null;
- }
-
- private StatsdConfig createSimpleEventMetricConfig(int atomId) throws ParseException {
- StatsdConfig.Builder baseBuilder = getSimpleEventMetricBaseConfig();
- baseBuilder.addAtomMatcher(createAtomMatcher(atomId));
- return baseBuilder.build();
+ return builder.build();
}
- private StatsdConfig createSimpleGaugeMetricConfig(int atomId) throws ParseException {
- StatsdConfig.Builder baseBuilder = getSimpleGaugeMetricBaseConfig();
- baseBuilder.addAtomMatcher(createAtomMatcher(atomId));
- return baseBuilder.build();
- }
-
- private AtomMatcher createAtomMatcher(int atomId) {
+ private static AtomMatcher createAtomMatcher(int atomId, long matcherId) {
AtomMatcher.Builder atomMatcherBuilder = AtomMatcher.newBuilder();
atomMatcherBuilder
- .setId(ATOM_MATCHER_ID)
+ .setId(matcherId)
.setSimpleAtomMatcher(SimpleAtomMatcher.newBuilder().setAtomId(atomId));
return atomMatcherBuilder.build();
}
- private StatsdConfig.Builder getSimpleEventMetricBaseConfig() throws ParseException {
- StatsdConfig.Builder builder = StatsdConfig.newBuilder();
- TextFormat.merge(EVENT_BASE_CONFIG_SRTR, builder);
- return builder;
- }
-
- private StatsdConfig.Builder getSimpleGaugeMetricBaseConfig() throws ParseException {
- StatsdConfig.Builder builder = StatsdConfig.newBuilder();
- TextFormat.merge(GAUGE_BASE_CONFIG_STR, builder);
- return builder;
+ private static String pushConfig(StatsdConfig config) throws IOException, InterruptedException {
+ File configFile = File.createTempFile("statsdconfig", ".config");
+ configFile.deleteOnExit();
+ Files.write(config.toByteArray(), configFile);
+ String remotePath = "/data/local/tmp/" + configFile.getName();
+ Utils.runCommand(null, LOGGER, "adb", "push", configFile.getAbsolutePath(), remotePath);
+ Utils.runCommand(null, LOGGER,
+ "adb", "shell", "cat", remotePath, "|", Utils.CMD_UPDATE_CONFIG,
+ String.valueOf(CONFIG_ID));
+ return remotePath;
}
- private void dumpMetrics() throws Exception {
- ConfigMetricsReportList reportList = Utils.getReportList(CONFIG_ID, true, false, logger);
- // We may get multiple reports. Take the last one.
- ConfigMetricsReport report = reportList.getReports(reportList.getReportsCount() - 1);
- // Really should be only one metric.
- if (report.getMetricsCount() != 1) {
- logger.log(Level.SEVERE,
- "Only one report metric expected, got " + report.getMetricsCount());
- return;
+ private static void removeConfig() {
+ try {
+ Utils.runCommand(null, LOGGER,
+ "adb", "shell", Utils.CMD_REMOVE_CONFIG, String.valueOf(CONFIG_ID));
+ } catch (Exception e) {
+ LOGGER.log(Level.SEVERE, "Failed to remove config: " + e.getMessage());
}
-
- logger.info("Got following metric data dump:");
- logger.info(report.getMetrics(0).toString());
}
- private static final String EVENT_BASE_CONFIG_SRTR =
- "id: 12345\n"
- + "event_metric {\n"
- + " id: 1111\n"
- + " what: 1234567\n"
- + "}\n"
- + "allowed_log_source: \"AID_GRAPHICS\"\n"
- + "allowed_log_source: \"AID_INCIDENTD\"\n"
- + "allowed_log_source: \"AID_STATSD\"\n"
- + "allowed_log_source: \"AID_RADIO\"\n"
- + "allowed_log_source: \"com.android.systemui\"\n"
- + "allowed_log_source: \"com.android.vending\"\n"
- + "allowed_log_source: \"AID_SYSTEM\"\n"
- + "allowed_log_source: \"AID_ROOT\"\n"
- + "allowed_log_source: \"AID_BLUETOOTH\"\n"
- + "allowed_log_source: \"AID_LMKD\"\n"
- + "\n"
- + "hash_strings_in_metric_report: false";
-
- private static final String GAUGE_BASE_CONFIG_STR =
- "id: 56789\n"
- + "gauge_metric {\n"
- + " id: 2222\n"
- + " what: 1234567\n"
- + " gauge_fields_filter {\n"
- + " include_all: true\n"
- + " }\n"
- + " bucket: ONE_MINUTE\n"
- + "}\n"
- + "allowed_log_source: \"AID_GRAPHICS\"\n"
- + "allowed_log_source: \"AID_INCIDENTD\"\n"
- + "allowed_log_source: \"AID_STATSD\"\n"
- + "allowed_log_source: \"AID_RADIO\"\n"
- + "allowed_log_source: \"com.android.systemui\"\n"
- + "allowed_log_source: \"com.android.vending\"\n"
- + "allowed_log_source: \"AID_SYSTEM\"\n"
- + "allowed_log_source: \"AID_ROOT\"\n"
- + "allowed_log_source: \"AID_BLUETOOTH\"\n"
- + "allowed_log_source: \"AID_LMKD\"\n"
- + "\n"
- + "hash_strings_in_metric_report: false";
+ private static boolean isPulledAtom(int atomId) {
+ return atomId >= PULL_ATOM_START;
+ }
+ private static boolean hasPulledAtom(Set<Integer> atoms) {
+ for (Integer i : atoms) {
+ if (isPulledAtom(i)) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index 5cd3d5d4fa4d..7bbeb16b1b24 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -1474,7 +1474,6 @@ Landroid/service/dreams/IDreamManager;->getDreamComponents()[Landroid/content/Co
Landroid/service/dreams/IDreamManager;->isDreaming()Z
Landroid/service/dreams/IDreamManager;->setDreamComponents([Landroid/content/ComponentName;)V
Landroid/service/euicc/IDeleteSubscriptionCallback;->onComplete(I)V
-Landroid/service/euicc/IDownloadSubscriptionCallback;->onComplete(I)V
Landroid/service/euicc/IEraseSubscriptionsCallback;->onComplete(I)V
Landroid/service/euicc/IEuiccService$Stub;-><init>()V
Landroid/service/euicc/IGetDefaultDownloadableSubscriptionListCallback;->onComplete(Landroid/service/euicc/GetDefaultDownloadableSubscriptionListResult;)V
diff --git a/core/java/android/annotation/Px.java b/core/java/android/annotation/Px.java
index a0ef2244d5e4..ad99fdb7657e 100644
--- a/core/java/android/annotation/Px.java
+++ b/core/java/android/annotation/Px.java
@@ -29,6 +29,8 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
* Denotes that a numeric parameter, field or method return value is expected
* to represent a pixel dimension.
*
+ * @paramDoc This units of this value are pixels.
+ * @returnDoc This units of this value are pixels.
* {@hide}
*/
@Documented
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 791f3da0d5e8..78fe0024b0b0 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -2496,7 +2496,7 @@ public class AppOpsManager {
* @param packageName The package performing the operation.
* @param result The result of the note.
*/
- void onOpNoted(String code, int uid, String packageName, int result);
+ void onOpNoted(int code, int uid, String packageName, int result);
}
/**
@@ -2953,7 +2953,7 @@ public class AppOpsManager {
* @hide
*/
@RequiresPermission(value=Manifest.permission.WATCH_APPOPS, conditional=true)
- public void startWatchingNoted(@NonNull String[] ops, @NonNull OnOpNotedListener callback) {
+ public void startWatchingNoted(@NonNull int[] ops, @NonNull OnOpNotedListener callback) {
IAppOpsNotedCallback cb;
synchronized (mNotedWatchers) {
cb = mNotedWatchers.get(callback);
@@ -2963,17 +2963,13 @@ public class AppOpsManager {
cb = new IAppOpsNotedCallback.Stub() {
@Override
public void opNoted(int op, int uid, String packageName, int mode) {
- callback.onOpNoted(sOpToString[op], uid, packageName, mode);
+ callback.onOpNoted(op, uid, packageName, mode);
}
};
mNotedWatchers.put(callback, cb);
}
try {
- final int[] opCodes = new int[ops.length];
- for (int i = 0; i < opCodes.length; i++) {
- opCodes[i] = strOpToOp(ops[i]);
- }
- mService.startWatchingNoted(opCodes, cb);
+ mService.startWatchingNoted(ops, cb);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2983,7 +2979,7 @@ public class AppOpsManager {
* Stop watching for noted app ops. An app op may be immediate or long running.
* Unregistering a non-registered callback has no effect.
*
- * @see #startWatchingNoted(String[], OnOpNotedListener)
+ * @see #startWatchingNoted(int[], OnOpNotedListener)
* @see #noteOp(String, int, String)
*
* @hide
diff --git a/core/java/android/app/AppOpsManagerInternal.java b/core/java/android/app/AppOpsManagerInternal.java
index 139a39fe3a1d..b5560331e7aa 100644
--- a/core/java/android/app/AppOpsManagerInternal.java
+++ b/core/java/android/app/AppOpsManagerInternal.java
@@ -16,7 +16,6 @@
package android.app;
-import android.annotation.NonNull;
import android.util.SparseIntArray;
import com.android.internal.util.function.QuadFunction;
@@ -86,10 +85,7 @@ public abstract class AppOpsManagerInternal {
*
* @param code The op code to set.
* @param uid The UID for which to set.
- * @param packageName The package for which to set.
* @param mode The new mode to set.
- * @param isPrivileged If the package is privileged
*/
- public abstract void setMode(int code, int uid, @NonNull String packageName, int mode,
- boolean isPrivileged);
+ public abstract void setUidMode(int code, int uid, int mode);
}
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 623bdda93b7e..f06df3d4dfba 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -145,6 +145,15 @@ public class PackageInstaller {
public static final String ACTION_SESSION_COMMITTED =
"android.content.pm.action.SESSION_COMMITTED";
+ /**
+ * Broadcast Action: Send information about a staged install session when its state is updated.
+ * <p>
+ * The associated session information is defined in {@link #EXTRA_SESSION}.
+ */
+ @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+ public static final String ACTION_SESSION_UPDATED =
+ "android.content.pm.action.SESSION_UPDATED";
+
/** {@hide} */
public static final String ACTION_CONFIRM_INSTALL = "android.content.pm.action.CONFIRM_INSTALL";
diff --git a/core/java/android/content/pm/SharedLibraryInfo.java b/core/java/android/content/pm/SharedLibraryInfo.java
index ad82626dd6ad..35609c9a8926 100644
--- a/core/java/android/content/pm/SharedLibraryInfo.java
+++ b/core/java/android/content/pm/SharedLibraryInfo.java
@@ -33,11 +33,29 @@ import java.util.List;
* This class provides information for a shared library. There are
* three types of shared libraries: builtin - non-updatable part of
* the OS; dynamic - updatable backwards-compatible dynamically linked;
- * static - updatable non backwards-compatible emulating static linking.
+ * static - non backwards-compatible emulating static linking.
*/
public final class SharedLibraryInfo implements Parcelable {
/** @hide */
+ public static SharedLibraryInfo createForStatic(PackageParser.Package pkg) {
+ return new SharedLibraryInfo(null, pkg.packageName, pkg.getAllCodePaths(),
+ pkg.staticSharedLibName,
+ pkg.staticSharedLibVersion,
+ TYPE_STATIC,
+ new VersionedPackage(pkg.manifestPackageName, pkg.getLongVersionCode()),
+ null, null);
+ }
+
+ /** @hide */
+ public static SharedLibraryInfo createForDynamic(PackageParser.Package pkg, String name) {
+ return new SharedLibraryInfo(null, pkg.packageName, pkg.getAllCodePaths(), name,
+ (long) VERSION_UNDEFINED,
+ TYPE_DYNAMIC, new VersionedPackage(pkg.packageName, pkg.getLongVersionCode()),
+ null, null);
+ }
+
+ /** @hide */
@IntDef(flag = true, prefix = { "TYPE_" }, value = {
TYPE_BUILTIN,
TYPE_DYNAMIC,
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 47145874490f..49c3dc63e151 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -187,13 +187,19 @@ public class ConnectivityManager {
* is for a network to which the connectivity manager was failing over
* following a disconnect on another network.
* Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}.
+ *
+ * @deprecated See {@link NetworkInfo}.
*/
+ @Deprecated
public static final String EXTRA_IS_FAILOVER = "isFailover";
/**
* The lookup key for a {@link NetworkInfo} object. This is supplied when
* there is another network that it may be possible to connect to. Retrieve with
* {@link android.content.Intent#getParcelableExtra(String)}.
+ *
+ * @deprecated See {@link NetworkInfo}.
*/
+ @Deprecated
public static final String EXTRA_OTHER_NETWORK_INFO = "otherNetwork";
/**
* The lookup key for a boolean that indicates whether there is a
@@ -214,7 +220,10 @@ public class ConnectivityManager {
* may be passed up from the lower networking layers, and its
* meaning may be specific to a particular network type. Retrieve
* it with {@link android.content.Intent#getStringExtra(String)}.
+ *
+ * @deprecated See {@link NetworkInfo#getExtraInfo()}.
*/
+ @Deprecated
public static final String EXTRA_EXTRA_INFO = "extraInfo";
/**
* The lookup key for an int that provides information about
@@ -895,7 +904,9 @@ public class ConnectivityManager {
*
* @return a {@link NetworkInfo} object for the current default network
* or {@code null} if no default network is currently active
+ * @deprecated See {@link NetworkInfo}.
*/
+ @Deprecated
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
public NetworkInfo getActiveNetworkInfo() {
try {
@@ -1079,7 +1090,9 @@ public class ConnectivityManager {
* @return a {@link NetworkInfo} object for the requested
* network or {@code null} if the {@code Network}
* is not valid.
+ * @deprecated See {@link NetworkInfo}.
*/
+ @Deprecated
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
public NetworkInfo getNetworkInfo(Network network) {
return getNetworkInfoForUid(network, Process.myUid(), false);
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 1b9a66cd6ea7..80517ce28cda 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -18,6 +18,7 @@ package android.net;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.os.Parcel;
import android.os.Parcelable;
@@ -161,7 +162,7 @@ public final class LinkProperties implements Parcelable {
/**
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public LinkProperties() {
}
@@ -195,7 +196,7 @@ public final class LinkProperties implements Parcelable {
* @param iface The name of the network interface used for this link.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public void setInterfaceName(String iface) {
mIfaceName = iface;
ArrayList<RouteInfo> newRoutes = new ArrayList<>(mRoutes.size());
@@ -346,7 +347,7 @@ public final class LinkProperties implements Parcelable {
* object.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public void setLinkAddresses(Collection<LinkAddress> addresses) {
mLinkAddresses.clear();
for (LinkAddress address: addresses) {
@@ -392,7 +393,7 @@ public final class LinkProperties implements Parcelable {
* @param dnsServers The {@link Collection} of DNS servers to set in this object.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public void setDnsServers(Collection<InetAddress> dnsServers) {
mDnses.clear();
for (InetAddress dnsServer: dnsServers) {
@@ -529,7 +530,7 @@ public final class LinkProperties implements Parcelable {
* domains to search when resolving host names on this link.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public void setDomains(String domains) {
mDomains = domains;
}
@@ -552,7 +553,7 @@ public final class LinkProperties implements Parcelable {
* @param mtu The MTU to use for this link.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public void setMtu(int mtu) {
mMtu = mtu;
}
@@ -562,9 +563,7 @@ public final class LinkProperties implements Parcelable {
* this will return 0.
*
* @return The mtu value set for this link.
- * @hide
*/
- @UnsupportedAppUsage
public int getMtu() {
return mMtu;
}
@@ -613,7 +612,7 @@ public final class LinkProperties implements Parcelable {
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public boolean addRoute(RouteInfo route) {
if (route != null) {
String routeIface = route.getInterface();
@@ -688,7 +687,7 @@ public final class LinkProperties implements Parcelable {
* @param proxy A {@link ProxyInfo} defining the HTTP Proxy to use on this link.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public void setHttpProxy(ProxyInfo proxy) {
mHttpProxy = proxy;
}
@@ -760,7 +759,7 @@ public final class LinkProperties implements Parcelable {
* Clears this object to its initial state.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public void clear() {
mIfaceName = null;
mLinkAddresses.clear();
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index c41a56c7305f..1b44c920a205 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -1017,7 +1017,7 @@ public final class NetworkCapabilities implements Parcelable {
* @return The bearer-specific signal strength.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public int getSignalStrength() {
return mSignalStrength;
}
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index 1a1d2d33424c..89d99617dfbf 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -28,7 +28,20 @@ import java.util.EnumMap;
* Describes the status of a network interface.
* <p>Use {@link ConnectivityManager#getActiveNetworkInfo()} to get an instance that represents
* the current network connection.
+ *
+ * @deprecated Callers should instead use the {@link ConnectivityManager.NetworkCallback} API to
+ * learn about connectivity changes, or switch to use
+ * {@link ConnectivityManager#getNetworkCapabilities} or
+ * {@link ConnectivityManager#getLinkProperties} to get information synchronously. Keep
+ * in mind that while callbacks are guaranteed to be called for every event in order,
+ * synchronous calls have no such constraints, and as such it is unadvisable to use the
+ * synchronous methods inside the callbacks as they will often not offer a view of
+ * networking that is consistent (that is: they may return a past or a future state with
+ * respect to the event being processed by the callback). Instead, callers are advised
+ * to only use the arguments of the callbacks, possibly memorizing the specific bits of
+ * information they need to keep from one callback to another.
*/
+@Deprecated
public class NetworkInfo implements Parcelable {
/**
@@ -52,7 +65,10 @@ public class NetworkInfo implements Parcelable {
* <tr><td><code>FAILED</code></td><td><code>DISCONNECTED</code></td></tr>
* <tr><td><code>BLOCKED</code></td><td><code>DISCONNECTED</code></td></tr>
* </table>
+ *
+ * @deprecated See {@link NetworkInfo}.
*/
+ @Deprecated
public enum State {
CONNECTING, CONNECTED, SUSPENDED, DISCONNECTING, DISCONNECTED, UNKNOWN
}
@@ -61,7 +77,10 @@ public class NetworkInfo implements Parcelable {
* The fine-grained state of a network connection. This level of detail
* is probably of interest to few applications. Most should use
* {@link android.net.NetworkInfo.State State} instead.
+ *
+ * @deprecated See {@link NetworkInfo}.
*/
+ @Deprecated
public enum DetailedState {
/** Ready to start data connection setup. */
IDLE,
@@ -463,8 +482,10 @@ public class NetworkInfo implements Parcelable {
* Set the extraInfo field.
* @param extraInfo an optional {@code String} providing addditional network state
* information passed up from the lower networking layers.
+ * @deprecated See {@link NetworkInfo#getExtraInfo}.
* @hide
*/
+ @Deprecated
public void setExtraInfo(String extraInfo) {
synchronized (this) {
this.mExtraInfo = extraInfo;
@@ -488,7 +509,10 @@ public class NetworkInfo implements Parcelable {
* Report the extra information about the network state, if any was
* provided by the lower networking layers.
* @return the extra information, or null if not available
+ * @deprecated Use other services e.g. WifiManager to get additional information passed up from
+ * the lower networking layers.
*/
+ @Deprecated
public String getExtraInfo() {
synchronized (this) {
return mExtraInfo;
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 04b6b44013b9..3b01b03edd4e 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -17,6 +17,7 @@
package android.net;
import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.net.NetworkCapabilities.NetCapability;
import android.net.NetworkCapabilities.Transport;
@@ -344,7 +345,7 @@ public class NetworkRequest implements Parcelable {
* @param signalStrength the bearer-specific signal strength.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public Builder setSignalStrength(int signalStrength) {
mNetworkCapabilities.setSignalStrength(signalStrength);
return this;
diff --git a/core/java/android/service/contentcapture/ContentCaptureService.java b/core/java/android/service/contentcapture/ContentCaptureService.java
index c5e62f1dfe60..64f235546201 100644
--- a/core/java/android/service/contentcapture/ContentCaptureService.java
+++ b/core/java/android/service/contentcapture/ContentCaptureService.java
@@ -34,13 +34,13 @@ import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.Log;
import android.util.Slog;
-import android.view.contentcapture.ActivityContentCaptureSession;
import android.view.contentcapture.ContentCaptureContext;
import android.view.contentcapture.ContentCaptureEvent;
import android.view.contentcapture.ContentCaptureManager;
import android.view.contentcapture.ContentCaptureSession;
import android.view.contentcapture.ContentCaptureSessionId;
import android.view.contentcapture.IContentCaptureDirectManager;
+import android.view.contentcapture.MainContentCaptureSession;
import com.android.internal.os.IResultReceiver;
@@ -293,13 +293,26 @@ public abstract class ContentCaptureService extends Service {
final List<ContentCaptureEvent> events = parceledEvents.getList();
for (int i = 0; i < events.size(); i++) {
final ContentCaptureEvent event = events.get(i);
+ if (!handleIsRightCallerFor(event, uid)) continue;
String sessionIdString = event.getSessionId();
if (!sessionIdString.equals(lastSessionId)) {
- if (!handleIsRightCallerFor(sessionIdString, uid)) continue;
sessionId = new ContentCaptureSessionId(sessionIdString);
lastSessionId = sessionIdString;
}
- onContentCaptureEvent(sessionId, event);
+ switch (event.getType()) {
+ case ContentCaptureEvent.TYPE_SESSION_STARTED:
+ final ContentCaptureContext clientContext = event.getClientContext();
+ clientContext.setParentSessionId(event.getParentSessionId());
+ mSessionsByUid.put(sessionIdString, uid);
+ onCreateContentCaptureSession(clientContext, sessionId);
+ break;
+ case ContentCaptureEvent.TYPE_SESSION_FINISHED:
+ mSessionsByUid.remove(sessionIdString);
+ onDestroyContentCaptureSession(sessionId);
+ break;
+ default:
+ onContentCaptureEvent(sessionId, event);
+ }
}
}
@@ -314,9 +327,18 @@ public abstract class ContentCaptureService extends Service {
}
/**
- * Checks if the given {@code uid} owns the session.
+ * Checks if the given {@code uid} owns the session associated with the event.
*/
- private boolean handleIsRightCallerFor(@NonNull String sessionId, int uid) {
+ private boolean handleIsRightCallerFor(@NonNull ContentCaptureEvent event, int uid) {
+ final String sessionId;
+ switch (event.getType()) {
+ case ContentCaptureEvent.TYPE_SESSION_STARTED:
+ case ContentCaptureEvent.TYPE_SESSION_FINISHED:
+ sessionId = event.getParentSessionId();
+ break;
+ default:
+ sessionId = event.getSessionId();
+ }
final Integer rightUid = mSessionsByUid.get(sessionId);
if (rightUid == null) {
if (VERBOSE) Log.v(TAG, "No session for " + sessionId);
@@ -347,7 +369,7 @@ public abstract class ContentCaptureService extends Service {
final Bundle extras;
if (binder != null) {
extras = new Bundle();
- extras.putBinder(ActivityContentCaptureSession.EXTRA_BINDER, binder);
+ extras.putBinder(MainContentCaptureSession.EXTRA_BINDER, binder);
} else {
extras = null;
}
diff --git a/core/java/android/service/euicc/DownloadSubscriptionResult.aidl b/core/java/android/service/euicc/DownloadSubscriptionResult.aidl
new file mode 100644
index 000000000000..b625fd6d3cb4
--- /dev/null
+++ b/core/java/android/service/euicc/DownloadSubscriptionResult.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.service.euicc;
+
+parcelable DownloadSubscriptionResult;
diff --git a/core/java/android/service/euicc/DownloadSubscriptionResult.java b/core/java/android/service/euicc/DownloadSubscriptionResult.java
new file mode 100644
index 000000000000..b410e35f3f83
--- /dev/null
+++ b/core/java/android/service/euicc/DownloadSubscriptionResult.java
@@ -0,0 +1,99 @@
+/*
+ * 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.service.euicc;
+
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.service.euicc.EuiccService.ResolvableError;
+import android.service.euicc.EuiccService.Result;
+
+/**
+ * Result of a {@link EuiccService#onDownloadSubscription} operation.
+ * @hide
+ */
+@SystemApi
+public final class DownloadSubscriptionResult implements Parcelable {
+
+ public static final Creator<DownloadSubscriptionResult> CREATOR =
+ new Creator<DownloadSubscriptionResult>() {
+ @Override
+ public DownloadSubscriptionResult createFromParcel(Parcel in) {
+ return new DownloadSubscriptionResult(in);
+ }
+
+ @Override
+ public DownloadSubscriptionResult[] newArray(int size) {
+ return new DownloadSubscriptionResult[size];
+ }
+ };
+
+ private final @Result int mResult;
+ private final @ResolvableError int mResolvableErrors;
+ private final int mCardId;
+
+ public DownloadSubscriptionResult(@Result int result, @ResolvableError int resolvableErrors,
+ int cardId) {
+ this.mResult = result;
+ this.mResolvableErrors = resolvableErrors;
+ this.mCardId = cardId;
+ }
+
+ /** Gets the result of the operation. */
+ public @Result int getResult() {
+ return mResult;
+ }
+
+ /**
+ * Gets the bit map of resolvable errors.
+ *
+ * <p>The value is passed from EuiccService. The values can be
+ *
+ * <ul>
+ * <li>{@link EuiccService#RESOLVABLE_ERROR_CONFIRMATION_CODE}
+ * <li>{@link EuiccService#RESOLVABLE_ERROR_POLICY_RULES}
+ * </ul>
+ */
+ public @ResolvableError int getResolvableErrors() {
+ return mResolvableErrors;
+ }
+
+ /**
+ * Gets the card Id. This is used when resolving resolvable errors. The value is passed from
+ * EuiccService.
+ */
+ public int getCardId() {
+ return mCardId;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ dest.writeInt(mResult);
+ dest.writeInt(mResolvableErrors);
+ dest.writeInt(mCardId);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ private DownloadSubscriptionResult(Parcel in) {
+ this.mResult = in.readInt();
+ this.mResolvableErrors = in.readInt();
+ this.mCardId = in.readInt();
+ }
+}
diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java
index 49a7320dab6d..4be1f9cd6ae5 100644
--- a/core/java/android/service/euicc/EuiccService.java
+++ b/core/java/android/service/euicc/EuiccService.java
@@ -16,17 +16,24 @@
package android.service.euicc;
import android.annotation.CallSuper;
+import android.annotation.IntDef;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.app.Service;
import android.content.Intent;
+import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
+import android.telephony.TelephonyManager;
import android.telephony.euicc.DownloadableSubscription;
import android.telephony.euicc.EuiccInfo;
import android.telephony.euicc.EuiccManager.OtaStatus;
import android.util.ArraySet;
+import android.util.Log;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
@@ -73,6 +80,8 @@ import java.util.concurrent.atomic.AtomicInteger;
*/
@SystemApi
public abstract class EuiccService extends Service {
+ private static final String TAG = "EuiccService";
+
/** Action which must be included in this service's intent filter. */
public static final String EUICC_SERVICE_INTERFACE = "android.service.euicc.EuiccService";
@@ -115,30 +124,91 @@ public abstract class EuiccService extends Service {
public static final String ACTION_RESOLVE_NO_PRIVILEGES =
"android.service.euicc.action.RESOLVE_NO_PRIVILEGES";
- /** Ask the user to input carrier confirmation code. */
+ /**
+ * Ask the user to input carrier confirmation code.
+ *
+ * @deprecated From Q, the resolvable errors happened in the download step are presented as
+ * bit map in {@link #EXTRA_RESOLVABLE_ERRORS}. The corresponding action would be
+ * {@link #ACTION_RESOLVE_RESOLVABLE_ERRORS}.
+ */
+ @Deprecated
public static final String ACTION_RESOLVE_CONFIRMATION_CODE =
"android.service.euicc.action.RESOLVE_CONFIRMATION_CODE";
+ /** Ask the user to resolve all the resolvable errors. */
+ public static final String ACTION_RESOLVE_RESOLVABLE_ERRORS =
+ "android.service.euicc.action.RESOLVE_RESOLVABLE_ERRORS";
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(flag = true, prefix = { "RESOLVABLE_ERROR_" }, value = {
+ RESOLVABLE_ERROR_CONFIRMATION_CODE,
+ RESOLVABLE_ERROR_POLICY_RULES,
+ })
+ public @interface ResolvableError {}
+
+ /**
+ * Possible value for the bit map of resolvable errors indicating the download process needs
+ * the user to input confirmation code.
+ */
+ public static final int RESOLVABLE_ERROR_CONFIRMATION_CODE = 1 << 0;
+ /**
+ * Possible value for the bit map of resolvable errors indicating the download process needs
+ * the user's consent to allow profile policy rules.
+ */
+ public static final int RESOLVABLE_ERROR_POLICY_RULES = 1 << 1;
+
/**
* Intent extra set for resolution requests containing the package name of the calling app.
* This is used by the above actions including ACTION_RESOLVE_DEACTIVATE_SIM,
- * ACTION_RESOLVE_NO_PRIVILEGES and ACTION_RESOLVE_CONFIRMATION_CODE.
+ * ACTION_RESOLVE_NO_PRIVILEGES and ACTION_RESOLVE_RESOLVABLE_ERRORS.
*/
public static final String EXTRA_RESOLUTION_CALLING_PACKAGE =
"android.service.euicc.extra.RESOLUTION_CALLING_PACKAGE";
/**
+ * Intent extra set for resolution requests containing the list of resolvable errors to be
+ * resolved. Each resolvable error is an integer. Its possible values include:
+ * <UL>
+ * <LI>{@link #RESOLVABLE_ERROR_CONFIRMATION_CODE}
+ * <LI>{@link #RESOLVABLE_ERROR_POLICY_RULES}
+ * </UL>
+ */
+ public static final String EXTRA_RESOLVABLE_ERRORS =
+ "android.service.euicc.extra.RESOLVABLE_ERRORS";
+
+ /**
* Intent extra set for resolution requests containing a boolean indicating whether to ask the
* user to retry another confirmation code.
*/
public static final String EXTRA_RESOLUTION_CONFIRMATION_CODE_RETRIED =
"android.service.euicc.extra.RESOLUTION_CONFIRMATION_CODE_RETRIED";
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = { "RESULT_" }, value = {
+ RESULT_OK,
+ RESULT_MUST_DEACTIVATE_SIM,
+ RESULT_RESOLVABLE_ERRORS,
+ RESULT_NEED_CONFIRMATION_CODE,
+ RESULT_FIRST_USER,
+ })
+ public @interface Result {}
+
/** Result code for a successful operation. */
public static final int RESULT_OK = 0;
/** Result code indicating that an active SIM must be deactivated to perform the operation. */
public static final int RESULT_MUST_DEACTIVATE_SIM = -1;
- /** Result code indicating that the user must input a carrier confirmation code. */
+ /** Result code indicating that the user must resolve resolvable errors. */
+ public static final int RESULT_RESOLVABLE_ERRORS = -2;
+ /**
+ * Result code indicating that the user must input a carrier confirmation code.
+ *
+ * @deprecated From Q, the resolvable errors happened in the download step are presented as
+ * bit map in {@link #EXTRA_RESOLVABLE_ERRORS}. The corresponding result would be
+ * {@link #RESULT_RESOLVABLE_ERRORS}.
+ */
+ @Deprecated
public static final int RESULT_NEED_CONFIRMATION_CODE = -2;
// New predefined codes should have negative values.
@@ -154,7 +224,7 @@ public abstract class EuiccService extends Service {
RESOLUTION_ACTIONS = new ArraySet<>();
RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM);
RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_NO_PRIVILEGES);
- RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_CONFIRMATION_CODE);
+ RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_RESOLVABLE_ERRORS);
}
/**
@@ -169,6 +239,12 @@ public abstract class EuiccService extends Service {
*/
public static final String EXTRA_RESOLUTION_CONFIRMATION_CODE =
"android.service.euicc.extra.RESOLUTION_CONFIRMATION_CODE";
+ /**
+ * String extra for resolution actions indicating whether the user allows policy rules.
+ * This is used and set by the implementation and used in {@code EuiccOperation}.
+ */
+ public static final String EXTRA_RESOLUTION_ALLOW_POLICY_RULES =
+ "android.service.euicc.extra.RESOLUTION_ALLOW_POLICY_RULES";
private final IEuiccService.Stub mStubWrapper;
@@ -236,8 +312,7 @@ public abstract class EuiccService extends Service {
/**
* Return the EID of the eUICC.
*
- * @param slotId ID of the SIM slot being queried. This is currently not populated but is here
- * to future-proof the APIs.
+ * @param slotId ID of the SIM slot being queried.
* @return the EID.
* @see android.telephony.euicc.EuiccManager#getEid
*/
@@ -247,8 +322,7 @@ public abstract class EuiccService extends Service {
/**
* Return the status of OTA update.
*
- * @param slotId ID of the SIM slot to use for the operation. This is currently not populated
- * but is here to future-proof the APIs.
+ * @param slotId ID of the SIM slot to use for the operation.
* @return The status of Euicc OTA update.
* @see android.telephony.euicc.EuiccManager#getOtaStatus
*/
@@ -257,8 +331,7 @@ public abstract class EuiccService extends Service {
/**
* Perform OTA if current OS is not the latest one.
*
- * @param slotId ID of the SIM slot to use for the operation. This is currently not populated
- * but is here to future-proof the APIs.
+ * @param slotId ID of the SIM slot to use for the operation.
* @param statusChangedCallback Function called when OTA status changed.
*/
public abstract void onStartOtaIfNecessary(
@@ -281,8 +354,7 @@ public abstract class EuiccService extends Service {
/**
* Return metadata for subscriptions which are available for download for this device.
*
- * @param slotId ID of the SIM slot to use for the operation. This is currently not populated
- * but is here to future-proof the APIs.
+ * @param slotId ID of the SIM slot to use for the operation.
* @param forceDeactivateSim If true, and if an active SIM must be deactivated to access the
* eUICC, perform this action automatically. Otherwise, {@link #RESULT_MUST_DEACTIVATE_SIM)}
* should be returned to allow the user to consent to this operation first.
@@ -302,13 +374,44 @@ public abstract class EuiccService extends Service {
* @param forceDeactivateSim If true, and if an active SIM must be deactivated to access the
* eUICC, perform this action automatically. Otherwise, {@link #RESULT_MUST_DEACTIVATE_SIM}
* should be returned to allow the user to consent to this operation first.
+ * @param resolvedBundle The bundle containing information on resolved errors. It can contain
+ * a string of confirmation code for the key {@link #EXTRA_RESOLUTION_CONFIRMATION_CODE},
+ * and a boolean for key {@link #EXTRA_RESOLUTION_ALLOW_POLICY_RULES} indicating whether
+ * the user allows profile policy rules or not.
+ * @return a DownloadSubscriptionResult instance including a result code, a resolvable errors
+ * bit map, and original the card Id. The result code may be one of the predefined
+ * {@code RESULT_} constants or any implementation-specific code starting with
+ * {@link #RESULT_FIRST_USER}. The resolvable error bit map can be either 0 or values
+ * defined in {@code RESOLVABLE_ERROR_}.
+ * @see android.telephony.euicc.EuiccManager#downloadSubscription
+ */
+ public abstract DownloadSubscriptionResult onDownloadSubscription(int slotId,
+ @NonNull DownloadableSubscription subscription, boolean switchAfterDownload,
+ boolean forceDeactivateSim, @Nullable Bundle resolvedBundle);
+
+ /**
+ * Download the given subscription.
+ *
+ * @param slotId ID of the SIM slot to use for the operation.
+ * @param subscription The subscription to download.
+ * @param switchAfterDownload If true, the subscription should be enabled upon successful
+ * download.
+ * @param forceDeactivateSim If true, and if an active SIM must be deactivated to access the
+ * eUICC, perform this action automatically. Otherwise, {@link #RESULT_MUST_DEACTIVATE_SIM}
+ * should be returned to allow the user to consent to this operation first.
* @return the result of the download operation. May be one of the predefined {@code RESULT_}
* constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
* @see android.telephony.euicc.EuiccManager#downloadSubscription
+ *
+ * @deprecated From Q, please use the above
+ * {@link #onDownloadSubscription(int, DownloadableSubscription, boolean, boolean, Bundle)}.
*/
- public abstract int onDownloadSubscription(int slotId,
- DownloadableSubscription subscription, boolean switchAfterDownload,
- boolean forceDeactivateSim);
+ @Deprecated public @Result int onDownloadSubscription(int slotId,
+ @NonNull DownloadableSubscription subscription, boolean switchAfterDownload,
+ boolean forceDeactivateSim) {
+ throw new UnsupportedOperationException("onDownloadSubscription(int, "
+ + "DownloadableSubscription, boolean, boolean) is deprecated.");
+ }
/**
* Return a list of all @link EuiccProfileInfo}s.
@@ -318,7 +421,7 @@ public abstract class EuiccService extends Service {
* @see android.telephony.SubscriptionManager#getAvailableSubscriptionInfoList
* @see android.telephony.SubscriptionManager#getAccessibleSubscriptionInfoList
*/
- public abstract GetEuiccProfileInfoListResult onGetEuiccProfileInfoList(int slotId);
+ public abstract @NonNull GetEuiccProfileInfoListResult onGetEuiccProfileInfoList(int slotId);
/**
* Return info about the eUICC chip/device.
@@ -327,7 +430,7 @@ public abstract class EuiccService extends Service {
* @return the {@link EuiccInfo} for the eUICC chip/device.
* @see android.telephony.euicc.EuiccManager#getEuiccInfo
*/
- public abstract EuiccInfo onGetEuiccInfo(int slotId);
+ public abstract @NonNull EuiccInfo onGetEuiccInfo(int slotId);
/**
* Delete the given subscription.
@@ -341,7 +444,7 @@ public abstract class EuiccService extends Service {
* constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
* @see android.telephony.euicc.EuiccManager#deleteSubscription
*/
- public abstract int onDeleteSubscription(int slotId, String iccid);
+ public abstract @Result int onDeleteSubscription(int slotId, String iccid);
/**
* Switch to the given subscription.
@@ -357,7 +460,7 @@ public abstract class EuiccService extends Service {
* constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
* @see android.telephony.euicc.EuiccManager#switchToSubscription
*/
- public abstract int onSwitchToSubscription(int slotId, @Nullable String iccid,
+ public abstract @Result int onSwitchToSubscription(int slotId, @Nullable String iccid,
boolean forceDeactivateSim);
/**
@@ -379,8 +482,7 @@ public abstract class EuiccService extends Service {
* <p>This is intended to be used for device resets. As such, the reset should be performed even
* if an active SIM must be deactivated in order to access the eUICC.
*
- * @param slotId ID of the SIM slot to use for the operation. This is currently not populated
- * but is here to future-proof the APIs.
+ * @param slotId ID of the SIM slot to use for the operation.
* @return the result of the erase operation. May be one of the predefined {@code RESULT_}
* constants or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
* @see android.telephony.euicc.EuiccManager#eraseSubscriptions
@@ -395,8 +497,7 @@ public abstract class EuiccService extends Service {
* should persist some bit that will remain accessible after the factory reset to bypass this
* flow when this method is called.
*
- * @param slotId ID of the SIM slot to use for the operation. This is currently not populated
- * but is here to future-proof the APIs.
+ * @param slotId ID of the SIM slot to use for the operation.
* @return the result of the operation. May be one of the predefined {@code RESULT_} constants
* or any implementation-specific code starting with {@link #RESULT_FIRST_USER}.
*/
@@ -408,13 +509,26 @@ public abstract class EuiccService extends Service {
private class IEuiccServiceWrapper extends IEuiccService.Stub {
@Override
public void downloadSubscription(int slotId, DownloadableSubscription subscription,
- boolean switchAfterDownload, boolean forceDeactivateSim,
+ boolean switchAfterDownload, boolean forceDeactivateSim, Bundle resolvedBundle,
IDownloadSubscriptionCallback callback) {
mExecutor.execute(new Runnable() {
@Override
public void run() {
- int result = EuiccService.this.onDownloadSubscription(
- slotId, subscription, switchAfterDownload, forceDeactivateSim);
+ DownloadSubscriptionResult result;
+ try {
+ result =
+ EuiccService.this.onDownloadSubscription(
+ slotId, subscription, switchAfterDownload, forceDeactivateSim,
+ resolvedBundle);
+ } catch (AbstractMethodError e) {
+ Log.w(TAG, "The new onDownloadSubscription(int, "
+ + "DownloadableSubscription, boolean, boolean, Bundle) is not "
+ + "implemented. Fall back to the old one.", e);
+ int resultCode = EuiccService.this.onDownloadSubscription(
+ slotId, subscription, switchAfterDownload, forceDeactivateSim);
+ result = new DownloadSubscriptionResult(resultCode,
+ 0 /* resolvableErrors */, TelephonyManager.INVALID_CARD_ID);
+ }
try {
callback.onComplete(result);
} catch (RemoteException e) {
diff --git a/core/java/android/service/euicc/IDownloadSubscriptionCallback.aidl b/core/java/android/service/euicc/IDownloadSubscriptionCallback.aidl
index 6893c8559d9d..50ecbebf5e84 100644
--- a/core/java/android/service/euicc/IDownloadSubscriptionCallback.aidl
+++ b/core/java/android/service/euicc/IDownloadSubscriptionCallback.aidl
@@ -16,7 +16,9 @@
package android.service.euicc;
+import android.service.euicc.DownloadSubscriptionResult;
+
/** @hide */
oneway interface IDownloadSubscriptionCallback {
- void onComplete(int result);
+ void onComplete(in DownloadSubscriptionResult result);
} \ No newline at end of file
diff --git a/core/java/android/service/euicc/IEuiccService.aidl b/core/java/android/service/euicc/IEuiccService.aidl
index 45be52740f32..c2cdf093706f 100644
--- a/core/java/android/service/euicc/IEuiccService.aidl
+++ b/core/java/android/service/euicc/IEuiccService.aidl
@@ -30,11 +30,12 @@ import android.service.euicc.IRetainSubscriptionsForFactoryResetCallback;
import android.service.euicc.ISwitchToSubscriptionCallback;
import android.service.euicc.IUpdateSubscriptionNicknameCallback;
import android.telephony.euicc.DownloadableSubscription;
+import android.os.Bundle;
/** @hide */
oneway interface IEuiccService {
void downloadSubscription(int slotId, in DownloadableSubscription subscription,
- boolean switchAfterDownload, boolean forceDeactivateSim,
+ boolean switchAfterDownload, boolean forceDeactivateSim, in Bundle resolvedBundle,
in IDownloadSubscriptionCallback callback);
void getDownloadableSubscriptionMetadata(int slotId, in DownloadableSubscription subscription,
boolean forceDeactivateSim, in IGetDownloadableSubscriptionMetadataCallback callback);
diff --git a/core/java/android/service/notification/NotificationAssistantService.java b/core/java/android/service/notification/NotificationAssistantService.java
index c850a4e0f815..dd0242ae2dc8 100644
--- a/core/java/android/service/notification/NotificationAssistantService.java
+++ b/core/java/android/service/notification/NotificationAssistantService.java
@@ -19,7 +19,7 @@ package android.service.notification;
import static java.lang.annotation.RetentionPolicy.SOURCE;
import android.annotation.IntDef;
-import android.annotation.Nullable;
+import android.annotation.NonNull;
import android.annotation.SdkConstant;
import android.annotation.SystemApi;
import android.annotation.TestApi;
@@ -179,13 +179,13 @@ public abstract class NotificationAssistantService extends NotificationListenerS
* @param isExpanded whether the notification is expanded.
*/
public void onNotificationExpansionChanged(
- String key, boolean isUserAction, boolean isExpanded) {}
+ @NonNull String key, boolean isUserAction, boolean isExpanded) {}
/**
* Implement this to know when a direct reply is sent from a notification.
* @param key the notification key
*/
- public void onNotificationDirectReply(String key) {}
+ public void onNotificationDirectReply(@NonNull String key) {}
/**
* Implement this to know when a suggested reply is sent.
@@ -193,7 +193,9 @@ public abstract class NotificationAssistantService extends NotificationListenerS
* @param reply the reply that is just sent
* @param source the source that provided the reply, e.g. SOURCE_FROM_APP
*/
- public void onSuggestedReplySent(String key, CharSequence reply, @Source int source) {}
+ public void onSuggestedReplySent(@NonNull String key, @NonNull CharSequence reply,
+ @Source int source) {
+ }
/**
* Implement this to know when an action is clicked.
@@ -201,7 +203,8 @@ public abstract class NotificationAssistantService extends NotificationListenerS
* @param action the action that is just clicked
* @param source the source that provided the action, e.g. SOURCE_FROM_APP
*/
- public void onActionClicked(String key, @Nullable Notification.Action action, int source) {
+ public void onActionClicked(@NonNull String key, @NonNull Notification.Action action,
+ @Source int source) {
}
/**
diff --git a/core/java/android/util/SparseSetArray.java b/core/java/android/util/SparseSetArray.java
index d100f12ed026..680e85fa2ba8 100644
--- a/core/java/android/util/SparseSetArray.java
+++ b/core/java/android/util/SparseSetArray.java
@@ -55,6 +55,13 @@ public class SparseSetArray<T> {
}
/**
+ * @return the set of items at index n
+ */
+ public ArraySet<T> get(int n) {
+ return mData.get(n);
+ }
+
+ /**
* Remove a value from index n.
* @return TRUE when the value existed at the given index and removed, FALSE otherwise.
*/
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 9dfd43cde628..330d72f139db 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -107,12 +107,6 @@ interface IWindowManager
*/
void endProlongedAnimations();
- // Re-evaluate the current orientation from the caller's state.
- // If there is a change, the new Configuration is returned and the
- // caller must call setNewConfiguration() sometime later.
- Configuration updateOrientationFromAppTokens(in Configuration currentConfig,
- IBinder freezeThisOneIfNeeded, int displayId);
-
void startFreezingScreen(int exitAnim, int enterAnim);
void stopFreezingScreen();
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
new file mode 100644
index 000000000000..7b9f78e70050
--- /dev/null
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -0,0 +1,197 @@
+/*
+ * 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.view;
+
+import static android.view.InsetsState.INSET_SIDE_BOTTOM;
+import static android.view.InsetsState.INSET_SIDE_LEFT;
+import static android.view.InsetsState.INSET_SIDE_RIGHT;
+import static android.view.InsetsState.INSET_SIDE_TOP;
+
+import android.annotation.Nullable;
+import android.graphics.Insets;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.os.UidProto.Sync;
+import android.util.ArraySet;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
+import android.util.SparseSetArray;
+import android.view.InsetsState.InsetSide;
+import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams;
+import android.view.WindowInsets.Type.InsetType;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.util.ArrayList;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+/**
+ * Implements {@link WindowInsetsAnimationController}
+ * @hide
+ */
+@VisibleForTesting
+public class InsetsAnimationControlImpl implements WindowInsetsAnimationController {
+
+ private final WindowInsetsAnimationControlListener mListener;
+ private final SparseArray<InsetsSourceConsumer> mConsumers;
+ private final SparseIntArray mTypeSideMap = new SparseIntArray();
+ private final SparseSetArray<InsetsSourceConsumer> mSideSourceMap = new SparseSetArray<>();
+
+ /** @see WindowInsetsAnimationController#getHiddenStateInsets */
+ private final Insets mHiddenInsets;
+
+ /** @see WindowInsetsAnimationController#getShownStateInsets */
+ private final Insets mShownInsets;
+ private final Matrix mTmpMatrix = new Matrix();
+ private final InsetsState mInitialInsetsState;
+ private final @InsetType int mTypes;
+ private final Supplier<SyncRtSurfaceTransactionApplier> mTransactionApplierSupplier;
+
+ private Insets mCurrentInsets;
+
+ @VisibleForTesting
+ public InsetsAnimationControlImpl(SparseArray<InsetsSourceConsumer> consumers, Rect frame,
+ InsetsState state, WindowInsetsAnimationControlListener listener,
+ @InsetType int types,
+ Supplier<SyncRtSurfaceTransactionApplier> transactionApplierSupplier) {
+ mConsumers = consumers;
+ mListener = listener;
+ mTypes = types;
+ mTransactionApplierSupplier = transactionApplierSupplier;
+ mInitialInsetsState = new InsetsState(state);
+ mCurrentInsets = getInsetsFromState(mInitialInsetsState, frame, null /* typeSideMap */);
+ mHiddenInsets = calculateInsets(mInitialInsetsState, frame, consumers, false /* shown */,
+ null /* typeSideMap */);
+ mShownInsets = calculateInsets(mInitialInsetsState, frame, consumers, true /* shown */,
+ mTypeSideMap);
+ buildTypeSourcesMap(mTypeSideMap, mSideSourceMap, mConsumers);
+
+ // TODO: Check for controllability first and wait for IME if needed.
+ listener.onReady(this, types);
+ }
+
+ @Override
+ public Insets getHiddenStateInsets() {
+ return mHiddenInsets;
+ }
+
+ @Override
+ public Insets getShownStateInsets() {
+ return mShownInsets;
+ }
+
+ @Override
+ public Insets getCurrentInsets() {
+ return mCurrentInsets;
+ }
+
+ @Override
+ @InsetType
+ public int getTypes() {
+ return mTypes;
+ }
+
+ @Override
+ public void changeInsets(Insets insets) {
+ insets = sanitize(insets);
+ final Insets offset = Insets.subtract(mShownInsets, insets);
+ ArrayList<SurfaceParams> params = new ArrayList<>();
+ if (offset.left != 0) {
+ updateLeashesForSide(INSET_SIDE_LEFT, offset.left, params);
+ }
+ if (offset.top != 0) {
+ updateLeashesForSide(INSET_SIDE_TOP, offset.top, params);
+ }
+ if (offset.right != 0) {
+ updateLeashesForSide(INSET_SIDE_RIGHT, offset.right, params);
+ }
+ if (offset.bottom != 0) {
+ updateLeashesForSide(INSET_SIDE_BOTTOM, offset.bottom, params);
+ }
+ SyncRtSurfaceTransactionApplier applier = mTransactionApplierSupplier.get();
+ applier.scheduleApply(params.toArray(new SurfaceParams[params.size()]));
+ mCurrentInsets = insets;
+ }
+
+ @Override
+ public void finish(int shownTypes) {
+ // TODO
+ }
+
+ private Insets calculateInsets(InsetsState state, Rect frame,
+ SparseArray<InsetsSourceConsumer> consumers, boolean shown,
+ @Nullable @InsetSide SparseIntArray typeSideMap) {
+ for (int i = consumers.size() - 1; i >= 0; i--) {
+ state.getSource(consumers.valueAt(i).getType()).setVisible(shown);
+ }
+ return getInsetsFromState(state, frame, typeSideMap);
+ }
+
+ private Insets getInsetsFromState(InsetsState state, Rect frame,
+ @Nullable @InsetSide SparseIntArray typeSideMap) {
+ return state.calculateInsets(frame, false /* isScreenRound */,
+ false /* alwaysConsumerNavBar */, null /* displayCutout */, typeSideMap)
+ .getSystemWindowInsets();
+ }
+
+ private Insets sanitize(Insets insets) {
+ return Insets.max(Insets.min(insets, mShownInsets), mHiddenInsets);
+ }
+
+ private void updateLeashesForSide(@InsetSide int side, int inset,
+ ArrayList<SurfaceParams> surfaceParams) {
+ ArraySet<InsetsSourceConsumer> items = mSideSourceMap.get(side);
+ // TODO: Implement behavior when inset spans over multiple types
+ for (int i = items.size() - 1; i >= 0; i--) {
+ final InsetsSourceConsumer consumer = items.valueAt(i);
+ final InsetsSource source = mInitialInsetsState.getSource(consumer.getType());
+ final SurfaceControl leash = consumer.getControl().getLeash();
+ mTmpMatrix.setTranslate(source.getFrame().left, source.getFrame().top);
+ addTranslationToMatrix(side, inset, mTmpMatrix);
+ surfaceParams.add(new SurfaceParams(leash, 1f, mTmpMatrix, null, 0, 0f));
+ }
+ }
+
+ private void addTranslationToMatrix(@InsetSide int side, int inset, Matrix m) {
+ switch (side) {
+ case INSET_SIDE_LEFT:
+ m.postTranslate(-inset, 0);
+ break;
+ case INSET_SIDE_TOP:
+ m.postTranslate(0, -inset);
+ break;
+ case INSET_SIDE_RIGHT:
+ m.postTranslate(inset, 0);
+ break;
+ case INSET_SIDE_BOTTOM:
+ m.postTranslate(0, inset);
+ break;
+ }
+ }
+
+ private static void buildTypeSourcesMap(SparseIntArray typeSideMap,
+ SparseSetArray<InsetsSourceConsumer> sideSourcesMap,
+ SparseArray<InsetsSourceConsumer> consumers) {
+ for (int i = typeSideMap.size() - 1; i >= 0; i--) {
+ int type = typeSideMap.keyAt(i);
+ int side = typeSideMap.valueAt(i);
+ sideSourcesMap.add(side, consumers.get(type));
+ }
+ }
+}
+
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index fb4f9c03fa68..4ab1f266cc70 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -28,6 +28,7 @@ import android.view.InsetsState.InternalInsetType;
import com.android.internal.annotations.VisibleForTesting;
import java.io.PrintWriter;
+import java.util.ArrayList;
/**
* Implements {@link WindowInsetsController} on the client.
@@ -41,6 +42,7 @@ public class InsetsController implements WindowInsetsController {
private final ViewRootImpl mViewRoot;
private final SparseArray<InsetsSourceControl> mTmpControlArray = new SparseArray<>();
+ private final ArrayList<InsetsAnimationControlImpl> mAnimationControls = new ArrayList<>();
public InsetsController(ViewRootImpl viewRoot) {
mViewRoot = viewRoot;
@@ -67,9 +69,11 @@ public class InsetsController implements WindowInsetsController {
/**
* @see InsetsState#calculateInsets
*/
- WindowInsets calculateInsets(boolean isScreenRound,
+ @VisibleForTesting
+ public WindowInsets calculateInsets(boolean isScreenRound,
boolean alwaysConsumeNavBar, DisplayCutout cutout) {
- return mState.calculateInsets(mFrame, isScreenRound, alwaysConsumeNavBar, cutout);
+ return mState.calculateInsets(mFrame, isScreenRound, alwaysConsumeNavBar, cutout,
+ null /* typeSideMap */);
}
/**
@@ -116,6 +120,28 @@ public class InsetsController implements WindowInsetsController {
}
}
+ @Override
+ public void controlWindowInsetsAnimation(@InsetType int types,
+ WindowInsetsAnimationControlListener listener) {
+
+ // TODO: Check whether we already have a controller.
+ final ArraySet<Integer> internalTypes = mState.toInternalType(types);
+ final SparseArray<InsetsSourceConsumer> consumers = new SparseArray<>();
+ for (int i = internalTypes.size() - 1; i >= 0; i--) {
+ InsetsSourceConsumer consumer = getSourceConsumer(internalTypes.valueAt(i));
+ if (consumer.getControl() != null) {
+ consumers.put(consumer.getType(), consumer);
+ } else {
+ // TODO: Let calling app know it's not possible, or wait
+ // TODO: Remove it from types
+ }
+ }
+ final InsetsAnimationControlImpl controller = new InsetsAnimationControlImpl(consumers,
+ mFrame, mState, listener, types,
+ () -> new SyncRtSurfaceTransactionApplier(mViewRoot.mView));
+ mAnimationControls.add(controller);
+ }
+
private void applyLocalVisibilityOverride() {
for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
final InsetsSourceConsumer controller = mSourceConsumers.valueAt(i);
@@ -134,7 +160,8 @@ public class InsetsController implements WindowInsetsController {
return controller;
}
- void notifyVisibilityChanged() {
+ @VisibleForTesting
+ public void notifyVisibilityChanged() {
mViewRoot.notifyInsetsChanged();
}
diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java
index 0cb8ad72f102..f8148a906bb3 100644
--- a/core/java/android/view/InsetsSource.java
+++ b/core/java/android/view/InsetsSource.java
@@ -70,7 +70,8 @@ public class InsetsSource implements Parcelable {
*
* @param relativeFrame The frame to calculate the insets relative to.
* @param ignoreVisibility If true, always reports back insets even if source isn't visible.
- * @return The resulting insets.
+ * @return The resulting insets. The contract is that only one side will be occupied by a
+ * source.
*/
public Insets calculateInsets(Rect relativeFrame, boolean ignoreVisibility) {
if (!ignoreVisibility && !mVisible) {
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 689b14fe29c6..63025dc16f17 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -17,12 +17,15 @@
package android.view;
import android.annotation.IntDef;
+import android.annotation.Nullable;
import android.graphics.Insets;
import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.ArrayMap;
import android.util.ArraySet;
+import android.util.SparseArray;
+import android.util.SparseIntArray;
import android.view.WindowInsets.Type;
import android.view.WindowInsets.Type.InsetType;
@@ -77,11 +80,30 @@ public class InsetsState implements Parcelable {
/** A shelf is the same as the navigation bar. */
public static final int TYPE_SHELF = TYPE_NAVIGATION_BAR;
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = "INSET_SIDE", value = {
+ INSET_SIDE_LEFT,
+ INSET_SIDE_TOP,
+ INSET_SIDE_RIGHT,
+ INSET_SIDE_BOTTOM,
+ INSET_SIDE_UNKNWON
+ })
+ public @interface InsetSide {}
+ static final int INSET_SIDE_LEFT = 0;
+ static final int INSET_SIDE_TOP = 1;
+ static final int INSET_SIDE_RIGHT = 2;
+ static final int INSET_SIDE_BOTTOM = 3;
+ static final int INSET_SIDE_UNKNWON = 4;
+
private final ArrayMap<Integer, InsetsSource> mSources = new ArrayMap<>();
public InsetsState() {
}
+ public InsetsState(InsetsState copy) {
+ set(copy);
+ }
+
/**
* Calculates {@link WindowInsets} based on the current source configuration.
*
@@ -89,7 +111,8 @@ public class InsetsState implements Parcelable {
* @return The calculated insets.
*/
public WindowInsets calculateInsets(Rect frame, boolean isScreenRound,
- boolean alwaysConsumeNavBar, DisplayCutout cutout) {
+ boolean alwaysConsumeNavBar, DisplayCutout cutout,
+ @Nullable @InsetSide SparseIntArray typeSideMap) {
Insets systemInsets = Insets.NONE;
Insets maxInsets = Insets.NONE;
final Rect relativeFrame = new Rect(frame);
@@ -100,13 +123,13 @@ public class InsetsState implements Parcelable {
continue;
}
systemInsets = processSource(source, systemInsets, relativeFrame,
- false /* ignoreVisibility */);
+ false /* ignoreVisibility */, typeSideMap);
// IME won't be reported in max insets as the size depends on the EditorInfo of the IME
// target.
if (source.getType() != TYPE_IME) {
maxInsets = processSource(source, maxInsets, relativeFrameMax,
- true /* ignoreVisibility */);
+ true /* ignoreVisibility */, null /* typeSideMap */);
}
}
return new WindowInsets(new Rect(systemInsets), null, new Rect(maxInsets), isScreenRound,
@@ -114,13 +137,39 @@ public class InsetsState implements Parcelable {
}
private Insets processSource(InsetsSource source, Insets insets, Rect relativeFrame,
- boolean ignoreVisibility) {
+ boolean ignoreVisibility, @Nullable @InsetSide SparseIntArray typeSideMap) {
Insets currentInsets = source.calculateInsets(relativeFrame, ignoreVisibility);
insets = Insets.add(currentInsets, insets);
relativeFrame.inset(insets);
+ if (typeSideMap != null && !Insets.NONE.equals(currentInsets)) {
+ @InsetSide int insetSide = getInsetSide(currentInsets);
+ if (insetSide != INSET_SIDE_UNKNWON) {
+ typeSideMap.put(source.getType(), getInsetSide(currentInsets));
+ }
+ }
return insets;
}
+ /**
+ * Retrieves the side for a certain {@code insets}. It is required that only one field l/t/r/b
+ * is set in order that this method returns a meaningful result.
+ */
+ private @InsetSide int getInsetSide(Insets insets) {
+ if (insets.left != 0) {
+ return INSET_SIDE_LEFT;
+ }
+ if (insets.top != 0) {
+ return INSET_SIDE_TOP;
+ }
+ if (insets.right != 0) {
+ return INSET_SIDE_RIGHT;
+ }
+ if (insets.bottom != 0) {
+ return INSET_SIDE_BOTTOM;
+ }
+ return INSET_SIDE_UNKNWON;
+ }
+
public InsetsSource getSource(@InternalInsetType int type) {
return mSources.computeIfAbsent(type, InsetsSource::new);
}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplier.java b/core/java/android/view/SyncRtSurfaceTransactionApplier.java
index 807edf624db8..0270acb3aea7 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplier.java
+++ b/core/java/android/view/SyncRtSurfaceTransactionApplier.java
@@ -11,24 +11,22 @@
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
- * limitations under the License
+ * limitations under the License.
*/
-package com.android.systemui.shared.system;
+package android.view;
-import android.graphics.HardwareRenderer;
import android.graphics.Matrix;
import android.graphics.Rect;
-import android.view.Surface;
-import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
-import android.view.View;
-import android.view.ViewRootImpl;
+
+import com.android.internal.annotations.VisibleForTesting;
import java.util.function.Consumer;
/**
* Helper class to apply surface transactions in sync with RenderThread.
+ * @hide
*/
public class SyncRtSurfaceTransactionApplier {
@@ -54,30 +52,32 @@ public class SyncRtSurfaceTransactionApplier {
if (mTargetViewRootImpl == null) {
return;
}
- mTargetViewRootImpl.registerRtFrameCallback(new HardwareRenderer.FrameDrawingCallback() {
- @Override
- public void onFrameDraw(long frame) {
- if (mTargetSurface == null || !mTargetSurface.isValid()) {
- return;
- }
- Transaction t = new Transaction();
- for (int i = params.length - 1; i >= 0; i--) {
- SurfaceParams surfaceParams = params[i];
- SurfaceControl surface = surfaceParams.surface;
- t.deferTransactionUntilSurface(surface, mTargetSurface, frame);
- applyParams(t, surfaceParams, mTmpFloat9);
- }
- t.setEarlyWakeup();
- t.apply();
+ mTargetViewRootImpl.registerRtFrameCallback(frame -> {
+ if (mTargetSurface == null || !mTargetSurface.isValid()) {
+ return;
}
+ Transaction t = new Transaction();
+ for (int i = params.length - 1; i >= 0; i--) {
+ SurfaceParams surfaceParams = params[i];
+ SurfaceControl surface = surfaceParams.surface;
+ t.deferTransactionUntilSurface(surface, mTargetSurface, frame);
+ applyParams(t, surfaceParams, mTmpFloat9);
+ }
+ t.setEarlyWakeup();
+ t.apply();
});
// Make sure a frame gets scheduled.
mTargetViewRootImpl.getView().invalidate();
}
- public static void applyParams(TransactionCompat t, SurfaceParams params) {
- applyParams(t.mTransaction, params, t.mTmpValues);
+ public static void applyParams(Transaction t, SurfaceParams params, float[] tmpFloat9) {
+ t.setMatrix(params.surface, params.matrix, tmpFloat9);
+ t.setWindowCrop(params.surface, params.windowCrop);
+ t.setAlpha(params.surface, params.alpha);
+ t.setLayer(params.surface, params.layer);
+ t.setCornerRadius(params.surface, params.cornerRadius);
+ t.show(params.surface);
}
/**
@@ -109,15 +109,6 @@ public class SyncRtSurfaceTransactionApplier {
}
}
- private static void applyParams(Transaction t, SurfaceParams params, float[] tmpFloat9) {
- t.setMatrix(params.surface, params.matrix, tmpFloat9);
- t.setWindowCrop(params.surface, params.windowCrop);
- t.setAlpha(params.surface, params.alpha);
- t.setLayer(params.surface, params.layer);
- t.setCornerRadius(params.surface, params.cornerRadius);
- t.show(params.surface);
- }
-
public static class SurfaceParams {
/**
@@ -129,9 +120,9 @@ public class SyncRtSurfaceTransactionApplier {
* @param matrix Matrix to apply.
* @param windowCrop Crop to apply.
*/
- public SurfaceParams(SurfaceControlCompat surface, float alpha, Matrix matrix,
+ public SurfaceParams(SurfaceControl surface, float alpha, Matrix matrix,
Rect windowCrop, int layer, float cornerRadius) {
- this.surface = surface.mSurfaceControl;
+ this.surface = surface;
this.alpha = alpha;
this.matrix = new Matrix(matrix);
this.windowCrop = new Rect(windowCrop);
@@ -139,11 +130,22 @@ public class SyncRtSurfaceTransactionApplier {
this.cornerRadius = cornerRadius;
}
- final SurfaceControl surface;
- final float alpha;
- final Matrix matrix;
- final Rect windowCrop;
- final int layer;
+ @VisibleForTesting
+ public final SurfaceControl surface;
+
+ @VisibleForTesting
+ public final float alpha;
+
+ @VisibleForTesting
final float cornerRadius;
+
+ @VisibleForTesting
+ public final Matrix matrix;
+
+ @VisibleForTesting
+ public final Rect windowCrop;
+
+ @VisibleForTesting
+ public final int layer;
}
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 468d92290c13..57635efff72e 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -9046,17 +9046,16 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* {@code onCreate()} and associate it with the root view of the activity:
*
* <pre>
- * ContentCaptureManager mgr = getSystemService(ContentCaptureManager.class);
- * if (mgr != null && mgr.isContentCaptureEnabled()) {
- * View rootView = findViewById(R.my_root_view);
- * ContentCaptureSession session = mgr.createContentCaptureSession(new
+ * ContentCaptureSession oldSession = rootView.getContentCaptureSession();
+ * if (oldSession != null) {
+ * ContentCaptureSession newSession = oldSession.createContentCaptureSession(new
* ContentCaptureContext.Builder().setUri(myUrl).build());
- * rootView.setContentCaptureSession(session);
+ * rootView.setContentCaptureSession(newSession);
* }
* </pre>
*
* @param contentCaptureSession a session created by
- * {@link ContentCaptureManager#createContentCaptureSession(
+ * {@link ContentCaptureSession#createContentCaptureSession(
* android.view.contentcapture.ContentCaptureContext)}.
*/
public void setContentCaptureSession(@NonNull ContentCaptureSession contentCaptureSession) {
@@ -10489,6 +10488,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*
* @return The {@link WindowInsetsController} or {@code null} if the view isn't attached to a
* a window.
+ * @see Window#getInsetsController()
* @hide pending unhide
*/
public @Nullable WindowInsetsController getWindowInsetsController() {
diff --git a/core/java/android/view/WindowInsetsAnimationControlListener.java b/core/java/android/view/WindowInsetsAnimationControlListener.java
new file mode 100644
index 000000000000..b27a23da61b7
--- /dev/null
+++ b/core/java/android/view/WindowInsetsAnimationControlListener.java
@@ -0,0 +1,50 @@
+/*
+ * 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.view;
+
+import android.annotation.NonNull;
+import android.view.WindowInsets.Type.InsetType;
+import android.view.inputmethod.EditorInfo;
+
+/**
+ * Interface that informs the client about {@link WindowInsetsAnimationController} state changes.
+ * @hide pending unhide
+ */
+public interface WindowInsetsAnimationControlListener {
+
+ /**
+ * Gets called as soon as the animation is ready to be controlled. This may be
+ * delayed when the IME needs to redraw because of an {@link EditorInfo} change, or when the
+ * window is starting up.
+ *
+ * @param controller The controller to control the inset animation.
+ * @param types The {@link InsetType}s it was able to gain control over. Note that this may be
+ * different than the types passed into
+ * {@link WindowInsetsController#controlWindowInsetsAnimation} in case the window
+ * wasn't able to gain the controls because it wasn't the IME target or not
+ * currently the window that's controlling the system bars.
+ */
+ void onReady(@NonNull WindowInsetsAnimationController controller, @InsetType int types);
+
+ /**
+ * Called when the window no longer has control over the requested types. If it loses control
+ * over one type, the whole control will be cancelled. If none of the requested types were
+ * available when requesting the control, the animation control will be cancelled immediately
+ * without {@link #onReady} being called.
+ */
+ void onCancelled();
+}
diff --git a/core/java/android/view/WindowInsetsAnimationController.java b/core/java/android/view/WindowInsetsAnimationController.java
new file mode 100644
index 000000000000..9de517dac5de
--- /dev/null
+++ b/core/java/android/view/WindowInsetsAnimationController.java
@@ -0,0 +1,81 @@
+/*
+ * 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.view;
+
+import android.annotation.NonNull;
+import android.graphics.Insets;
+import android.view.WindowInsets.Type.InsetType;
+
+/**
+ * Interface to control a window inset animation frame-by-frame.
+ * @hide pending unhide
+ */
+public interface WindowInsetsAnimationController {
+
+ /**
+ * Retrieves the {@link Insets} when the windows this animation is controlling are fully hidden.
+ *
+ * @return Insets when the windows this animation is controlling are fully hidden.
+ */
+ @NonNull Insets getHiddenStateInsets();
+
+ /**
+ * Retrieves the {@link Insets} when the windows this animation is controlling are fully shown.
+ * <p>
+ * In case the size of a window causing insets is changing in the middle of the animation, we
+ * execute that height change after this animation has finished.
+ *
+ * @return Insets when the windows this animation is controlling are fully shown.
+ */
+ @NonNull Insets getShownStateInsets();
+
+ /**
+ * @return The current insets on the window. These will follow any animation changes.
+ */
+ @NonNull Insets getCurrentInsets();
+
+ /**
+ * @return The {@link InsetType}s this object is currently controlling.
+ */
+ @InsetType int getTypes();
+
+ /**
+ * Modifies the insets by indirectly moving the windows around in the system that are causing
+ * window insets.
+ * <p>
+ * Note that this will <b>not</b> inform the view system of a full inset change via
+ * {@link View#dispatchApplyWindowInsets} in order to avoid a full layout pass during the
+ * animation. If you'd like to animate views during a window inset animation, use
+ * TODO add link to animation listeners.
+ * <p>
+ * {@link View#dispatchApplyWindowInsets} will instead be called once the animation has
+ * finished, i.e. once {@link #finish} has been called.
+ *
+ * @param insets The new insets to apply. Based on the requested insets, the system will
+ * calculate the positions of the windows in the system causing insets such that
+ * the resulting insets of that configuration will match the passed in parameter.
+ * Note that these insets are being clamped to the range from
+ * {@link #getHiddenStateInsets} to {@link #getShownStateInsets}
+ */
+ void changeInsets(@NonNull Insets insets);
+
+ /**
+ * @param shownTypes The list of windows causing insets that should remain shown after finishing
+ * the animation.
+ */
+ void finish(@InsetType int shownTypes);
+}
diff --git a/core/java/android/view/WindowInsetsController.java b/core/java/android/view/WindowInsetsController.java
index 7be5f2e7a0b0..a35be273f3bf 100644
--- a/core/java/android/view/WindowInsetsController.java
+++ b/core/java/android/view/WindowInsetsController.java
@@ -16,6 +16,7 @@
package android.view;
+import android.annotation.NonNull;
import android.view.WindowInsets.Type.InsetType;
/**
@@ -51,4 +52,15 @@ public interface WindowInsetsController {
* would like to make disappear.
*/
void hide(@InsetType int types);
+
+ /**
+ * Lets the application control window inset animations in a frame-by-frame manner by modifying
+ * the position of the windows in the system causing insets directly.
+ *
+ * @param types The {@link InsetType}s the application has requested to control.
+ * @param listener The {@link WindowInsetsAnimationControlListener} that gets called when the
+ * windows are ready to be controlled, among other callbacks.
+ */
+ void controlWindowInsetsAnimation(@InsetType int types,
+ @NonNull WindowInsetsAnimationControlListener listener);
}
diff --git a/core/java/android/view/contentcapture/ChildContentCaptureSession.java b/core/java/android/view/contentcapture/ChildContentCaptureSession.java
new file mode 100644
index 000000000000..51668319cde2
--- /dev/null
+++ b/core/java/android/view/contentcapture/ChildContentCaptureSession.java
@@ -0,0 +1,99 @@
+/*
+ * 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.view.contentcapture;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.view.autofill.AutofillId;
+import android.view.contentcapture.ViewNode.ViewStructureImpl;
+
+import com.android.internal.util.Preconditions;
+
+import java.io.PrintWriter;
+
+/**
+ * A session that is explicitly created by the app (and hence is a descendant of
+ * {@link MainContentCaptureSession}).
+ *
+ * @hide
+ */
+final class ChildContentCaptureSession extends ContentCaptureSession {
+
+ @NonNull
+ private final MainContentCaptureSession mParent;
+
+ /**
+ * {@link ContentCaptureContext} set by client, or {@code null} when it's the
+ * {@link ContentCaptureManager#getMainContentCaptureSession() default session} for the
+ * context.
+ *
+ * @hide
+ */
+ @NonNull
+ private final ContentCaptureContext mClientContext;
+
+ /** @hide */
+ protected ChildContentCaptureSession(@NonNull MainContentCaptureSession parent,
+ @NonNull ContentCaptureContext clientContext) {
+ mParent = parent;
+ mClientContext = Preconditions.checkNotNull(clientContext);
+ }
+
+ @Override
+ ContentCaptureSession newChild(@NonNull ContentCaptureContext context) {
+ // TODO(b/121033016): implement it
+ throw new UnsupportedOperationException("grand-children not implemented yet");
+ }
+
+ @Override
+ void flush() {
+ mParent.flush();
+ }
+
+ @Override
+ void onDestroy() {
+ mParent.notifyChildSessionFinished(mParent.mId, mId);
+ }
+
+ @Override
+ void internalNotifyViewAppeared(@NonNull ViewStructureImpl node) {
+ mParent.notifyViewAppeared(mId, node);
+ }
+
+ @Override
+ void internalNotifyViewDisappeared(@NonNull AutofillId id) {
+ mParent.notifyViewDisappeared(mId, id);
+ }
+
+ @Override
+ void internalNotifyViewTextChanged(@NonNull AutofillId id, @Nullable CharSequence text,
+ int flags) {
+ mParent.notifyViewTextChanged(mId, id, text, flags);
+ }
+ @Override
+ boolean isContentCaptureEnabled() {
+ return mParent.isContentCaptureEnabled();
+ }
+
+ @Override
+ void dump(String prefix, PrintWriter pw) {
+ if (mClientContext != null) {
+ // NOTE: we don't dump clientContent because it could have PII
+ pw.print(prefix); pw.println("hasClientContext");
+ }
+ super.dump(prefix, pw);
+ }
+}
diff --git a/core/java/android/view/contentcapture/ContentCaptureContext.java b/core/java/android/view/contentcapture/ContentCaptureContext.java
index 9c11743fdf19..2d2987a035da 100644
--- a/core/java/android/view/contentcapture/ContentCaptureContext.java
+++ b/core/java/android/view/contentcapture/ContentCaptureContext.java
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.app.TaskInfo;
import android.content.ComponentName;
+import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcel;
@@ -76,7 +77,7 @@ public final class ContentCaptureContext implements Parcelable {
/**
* Flag indicating if this object has the app-provided context (which is set on
- * {@link ContentCaptureManager#createContentCaptureSession(ContentCaptureContext)}).
+ * {@link ContentCaptureSession#createContentCaptureSession(ContentCaptureContext)}).
*/
private final boolean mHasClientContext;
@@ -91,6 +92,9 @@ public final class ContentCaptureContext implements Parcelable {
private final int mDisplayId;
private final int mFlags;
+ // Fields below are set by the service upon "delivery" and are not marshalled in the parcel
+ private @Nullable String mParentSessionId;
+
/** @hide */
public ContentCaptureContext(@Nullable ContentCaptureContext clientContext,
@NonNull ComponentName componentName, int taskId, int displayId, int flags) {
@@ -153,16 +157,33 @@ public final class ContentCaptureContext implements Parcelable {
}
/**
- * Gets the activity associated with this context.
+ * Gets the activity associated with this context, or {@code null} when it is a child session.
*
* @hide
*/
@SystemApi
- public @NonNull ComponentName getActivityComponent() {
+ public @Nullable ComponentName getActivityComponent() {
return mComponentName;
}
/**
+ * Gets the id of the session that originated this session (through
+ * {@link ContentCaptureSession#createContentCaptureSession(ContentCaptureContext)}),
+ * or {@code null} if this is the main session associated with the Activity's {@link Context}.
+ *
+ * @hide
+ */
+ @SystemApi
+ public @Nullable ContentCaptureSessionId getParentSessionId() {
+ return mParentSessionId == null ? null : new ContentCaptureSessionId(mParentSessionId);
+ }
+
+ /** @hide */
+ public void setParentSessionId(@NonNull String parentSessionId) {
+ mParentSessionId = parentSessionId;
+ }
+
+ /**
* Gets the ID of the display associated with this context, as defined by
* {G android.hardware.display.DisplayManager#getDisplay(int) DisplayManager.getDisplay()}.
*
@@ -242,6 +263,9 @@ public final class ContentCaptureContext implements Parcelable {
pw.print("comp="); pw.print(ComponentName.flattenToShortString(mComponentName));
pw.print(", taskId="); pw.print(mTaskId);
pw.print(", displayId="); pw.print(mDisplayId);
+ if (mParentSessionId != null) {
+ pw.print(", parentId="); pw.print(mParentSessionId);
+ }
if (mFlags > 0) {
pw.print(", flags="); pw.print(mFlags);
}
@@ -262,6 +286,9 @@ public final class ContentCaptureContext implements Parcelable {
.append(", taskId=").append(mTaskId)
.append(", displayId=").append(mDisplayId)
.append(", flags=").append(mFlags);
+ if (mParentSessionId != null) {
+ builder.append(", parentId=").append(mParentSessionId);
+ }
if (mExtras != null) {
// NOTE: cannot print because it could contain PII
builder.append(", hasExtras");
@@ -320,9 +347,9 @@ public final class ContentCaptureContext implements Parcelable {
final int taskId = parcel.readInt();
final int displayId = parcel.readInt();
final int flags = parcel.readInt();
- return new ContentCaptureContext(clientContext, componentName, taskId,
- displayId, flags);
- }
+ return new ContentCaptureContext(clientContext, componentName, taskId, displayId,
+ flags);
+ }
}
@Override
diff --git a/core/java/android/view/contentcapture/ContentCaptureEvent.java b/core/java/android/view/contentcapture/ContentCaptureEvent.java
index 43c9699b54b8..9e3da9234b58 100644
--- a/core/java/android/view/contentcapture/ContentCaptureEvent.java
+++ b/core/java/android/view/contentcapture/ContentCaptureEvent.java
@@ -34,9 +34,9 @@ import java.lang.annotation.RetentionPolicy;
public final class ContentCaptureEvent implements Parcelable {
/** @hide */
- public static final int TYPE_ACTIVITY_DESTROYED = -2;
+ public static final int TYPE_SESSION_FINISHED = -2;
/** @hide */
- public static final int TYPE_ACTIVITY_CREATED = -1;
+ public static final int TYPE_SESSION_STARTED = -1;
/**
* Called when a node has been added to the screen and is visible to the user.
@@ -78,6 +78,8 @@ public final class ContentCaptureEvent implements Parcelable {
private @Nullable AutofillId mId;
private @Nullable ViewNode mNode;
private @Nullable CharSequence mText;
+ private @Nullable String mParentSessionId;
+ private @Nullable ContentCaptureContext mClientContext;
/** @hide */
public ContentCaptureEvent(@NonNull String sessionId, int type, long eventTime, int flags) {
@@ -103,12 +105,52 @@ public final class ContentCaptureEvent implements Parcelable {
return this;
}
+ /**
+ * Used by {@link #TYPE_SESSION_STARTED} and {@link #TYPE_SESSION_FINISHED}.
+ *
+ * @hide
+ */
+ public ContentCaptureEvent setParentSessionId(@NonNull String parentSessionId) {
+ mParentSessionId = parentSessionId;
+ return this;
+ }
+
+ /**
+ * Used by {@link #TYPE_SESSION_STARTED} and {@link #TYPE_SESSION_FINISHED}.
+ *
+ * @hide
+ */
+ public ContentCaptureEvent setClientContext(@NonNull ContentCaptureContext clientContext) {
+ mClientContext = clientContext;
+ return this;
+ }
+
/** @hide */
@NonNull
public String getSessionId() {
return mSessionId;
}
+ /**
+ * Used by {@link #TYPE_SESSION_STARTED} and {@link #TYPE_SESSION_FINISHED}.
+ *
+ * @hide
+ */
+ @Nullable
+ public String getParentSessionId() {
+ return mParentSessionId;
+ }
+
+ /**
+ * Used by {@link #TYPE_SESSION_STARTED}.
+ *
+ * @hide
+ */
+ @Nullable
+ public ContentCaptureContext getClientContext() {
+ return mClientContext;
+ }
+
/** @hide */
@NonNull
public ContentCaptureEvent setViewNode(@NonNull ViewNode node) {
@@ -191,7 +233,17 @@ public final class ContentCaptureEvent implements Parcelable {
pw.print(", id="); pw.print(mId);
}
if (mNode != null) {
- pw.print(", id="); pw.print(mNode.getAutofillId());
+ pw.print(", mNode.id="); pw.print(mNode.getAutofillId());
+ }
+ if (mSessionId != null) {
+ pw.print(", sessionId="); pw.print(mSessionId);
+ }
+ if (mParentSessionId != null) {
+ pw.print(", parentSessionId="); pw.print(mParentSessionId);
+ }
+ if (mText != null) {
+ // Cannot print content because could have PII
+ pw.print(", text="); pw.print(mText.length()); pw.print("_chars");
}
}
@@ -229,6 +281,12 @@ public final class ContentCaptureEvent implements Parcelable {
parcel.writeParcelable(mId, flags);
ViewNode.writeToParcel(parcel, mNode, flags);
parcel.writeCharSequence(mText);
+ if (mType == TYPE_SESSION_STARTED || mType == TYPE_SESSION_FINISHED) {
+ parcel.writeString(mParentSessionId);
+ }
+ if (mType == TYPE_SESSION_STARTED) {
+ parcel.writeParcelable(mClientContext, flags);
+ }
}
public static final Parcelable.Creator<ContentCaptureEvent> CREATOR =
@@ -251,6 +309,12 @@ public final class ContentCaptureEvent implements Parcelable {
event.setViewNode(node);
}
event.setText(parcel.readCharSequence());
+ if (type == TYPE_SESSION_STARTED || type == TYPE_SESSION_FINISHED) {
+ event.setParentSessionId(parcel.readString());
+ }
+ if (type == TYPE_SESSION_STARTED) {
+ event.setClientContext(parcel.readParcelable(null));
+ }
return event;
}
@@ -263,6 +327,10 @@ public final class ContentCaptureEvent implements Parcelable {
/** @hide */
public static String getTypeAsString(@EventType int type) {
switch (type) {
+ case TYPE_SESSION_STARTED:
+ return "SESSION_STARTED";
+ case TYPE_SESSION_FINISHED:
+ return "SESSION_FINISHED";
case TYPE_VIEW_APPEARED:
return "VIEW_APPEARED";
case TYPE_VIEW_DISAPPEARED:
diff --git a/core/java/android/view/contentcapture/ContentCaptureManager.java b/core/java/android/view/contentcapture/ContentCaptureManager.java
index fca2857d6e06..983079073d02 100644
--- a/core/java/android/view/contentcapture/ContentCaptureManager.java
+++ b/core/java/android/view/contentcapture/ContentCaptureManager.java
@@ -18,13 +18,13 @@ package android.view.contentcapture;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemService;
+import android.annotation.UiThread;
import android.content.ComponentName;
import android.content.Context;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.util.Log;
-import android.view.View;
import com.android.internal.util.Preconditions;
@@ -66,7 +66,7 @@ public final class ContentCaptureManager {
@NonNull
private final Handler mHandler;
- private ActivityContentCaptureSession mMainSession;
+ private MainContentCaptureSession mMainSession;
/** @hide */
public ContentCaptureManager(@NonNull Context context,
@@ -93,46 +93,20 @@ public final class ContentCaptureManager {
}
/**
- * Creates a new {@link ContentCaptureSession}.
- *
- * <p>See {@link View#setContentCaptureSession(ContentCaptureSession)} for more info.
- */
- @NonNull
- public ContentCaptureSession createContentCaptureSession(
- @NonNull ContentCaptureContext context) {
- if (DEBUG) Log.d(TAG, "createContentCaptureSession(): " + context);
- // TODO(b/121033016): for now we're updating the main session, but we need instead:
- // 1.Keep a list of sessions
- // 2.Making sure the applicationToken and componentName passed by
- // the activity is used on all of these sessions
- // 3.We might also need to delay the start of all of these sessions until
- // onActivityStarted() is called (and the main session is created).
- // 4.Close (and delete) these sessions when onActivityStopped() is called.
- // 5.Figure out whether each session will have its own mDisabled AtomicBoolean.
- if (mMainSession == null) {
- mMainSession = new ActivityContentCaptureSession(mContext, mHandler, mService,
- mDisabled, Preconditions.checkNotNull(context));
- } else {
- throw new IllegalStateException("Manager already has a session: " + mMainSession);
- }
- return mMainSession;
- }
-
- /**
* Gets the main session associated with the context.
*
* <p>By default there's just one (associated with the activity lifecycle), but apps could
- * explicitly add more using {@link #createContentCaptureSession(ContentCaptureContext)}.
+ * explicitly add more using
+ * {@link ContentCaptureSession#createContentCaptureSession(ContentCaptureContext)}.
*
* @hide
*/
@NonNull
- public ActivityContentCaptureSession getMainContentCaptureSession() {
- // TODO(b/121033016): figure out how to manage the "default" session when it support
- // multiple sessions (can't just be the first one, as it could be closed).
+ @UiThread
+ public MainContentCaptureSession getMainContentCaptureSession() {
if (mMainSession == null) {
- mMainSession = new ActivityContentCaptureSession(mContext, mHandler, mService,
- mDisabled, /* clientContext= */ null);
+ mMainSession = new MainContentCaptureSession(mContext, mHandler, mService,
+ mDisabled);
if (VERBOSE) {
Log.v(TAG, "getDefaultContentCaptureSession(): created " + mMainSession);
}
diff --git a/core/java/android/view/contentcapture/ContentCaptureSession.java b/core/java/android/view/contentcapture/ContentCaptureSession.java
index aedb7a94ff5d..9f666a40bef3 100644
--- a/core/java/android/view/contentcapture/ContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/ContentCaptureSession.java
@@ -15,8 +15,10 @@
*/
package android.view.contentcapture;
+import static android.view.contentcapture.ContentCaptureManager.DEBUG;
import static android.view.contentcapture.ContentCaptureManager.VERBOSE;
+import android.annotation.CallSuper;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.util.Log;
@@ -30,6 +32,7 @@ import com.android.internal.util.Preconditions;
import dalvik.system.CloseGuard;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.UUID;
/**
@@ -80,6 +83,8 @@ public abstract class ContentCaptureSession implements AutoCloseable {
*/
public static final int STATE_DISABLED_DUPLICATED_ID = 4;
+ private static final int INITIAL_CHILDREN_CAPACITY = 5;
+
/** @hide */
protected final String mTag = getClass().getSimpleName();
@@ -95,19 +100,17 @@ public abstract class ContentCaptureSession implements AutoCloseable {
private ContentCaptureSessionId mContentCaptureSessionId;
/**
- * {@link ContentCaptureContext} set by client, or {@code null} when it's the
- * {@link ContentCaptureManager#getMainContentCaptureSession() default session} for the
- * context.
- *
- * @hide
+ * List of children session.
*/
+ // TODO(b/121033016): need to synchonize access, either by changing on handler or UI thread
+ // (for now there's no handler on this class, so we need to wait for the next refactoring),
+ // most likely the former (as we have no guarantee that createContentCaptureSession()
+ // it will be called in the UiThread; for example, WebView most likely won't call on it)
@Nullable
- // TODO(b/121042846): move to ChildContentCaptureSession.java
- protected final ContentCaptureContext mClientContext;
+ private ArrayList<ContentCaptureSession> mChildren;
/** @hide */
- protected ContentCaptureSession(@Nullable ContentCaptureContext clientContext) {
- mClientContext = clientContext;
+ protected ContentCaptureSession() {
mCloseGuard.open("destroy");
}
@@ -122,6 +125,28 @@ public abstract class ContentCaptureSession implements AutoCloseable {
}
/**
+ * Creates a new {@link ContentCaptureSession}.
+ *
+ * <p>See {@link View#setContentCaptureSession(ContentCaptureSession)} for more info.
+ */
+ @NonNull
+ public final ContentCaptureSession createContentCaptureSession(
+ @NonNull ContentCaptureContext context) {
+ final ContentCaptureSession child = newChild(context);
+ if (DEBUG) {
+ Log.d(mTag, "createContentCaptureSession(" + context + ": parent=" + mId + ", child= "
+ + child.mId);
+ }
+ if (mChildren == null) {
+ mChildren = new ArrayList<>(INITIAL_CHILDREN_CAPACITY);
+ }
+ mChildren.add(child);
+ return child;
+ }
+
+ abstract ContentCaptureSession newChild(@NonNull ContentCaptureContext context);
+
+ /**
* Flushes the buffered events to the service.
*/
abstract void flush();
@@ -134,24 +159,40 @@ public abstract class ContentCaptureSession implements AutoCloseable {
public final void destroy() {
//TODO(b/111276913): mark it as destroyed so other methods are ignored (and test on CTS)
+ //TODO(b/111276913): probably shouldn't check for it
if (!isContentCaptureEnabled()) return;
+ mCloseGuard.close();
+
//TODO(b/111276913): check state (for example, how to handle if it's waiting for remote
// id) and send it to the cache of batched commands
if (VERBOSE) {
Log.v(mTag, "destroy(): state=" + getStateAsString(mState) + ", mId=" + mId);
}
- flush();
-
- onDestroy();
+ // Finish children first
+ if (mChildren != null) {
+ final int numberChildren = mChildren.size();
+ if (VERBOSE) Log.v(mTag, "Destroying " + numberChildren + " children first");
+ for (int i = 0; i < numberChildren; i++) {
+ final ContentCaptureSession child = mChildren.get(i);
+ try {
+ child.destroy();
+ } catch (Exception e) {
+ Log.w(mTag, "exception destroying child session #" + i + ": " + e);
+ }
+ }
+ }
- mCloseGuard.close();
+ try {
+ flush();
+ } finally {
+ onDestroy();
+ }
}
abstract void onDestroy();
-
/** @hide */
@Override
public void close() {
@@ -259,7 +300,19 @@ public abstract class ContentCaptureSession implements AutoCloseable {
abstract boolean isContentCaptureEnabled();
- abstract void dump(@NonNull String prefix, @NonNull PrintWriter pw);
+ @CallSuper
+ void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
+ if (mChildren != null && !mChildren.isEmpty()) {
+ final String prefix2 = prefix + " ";
+ final int numberChildren = mChildren.size();
+ pw.print(prefix); pw.print("number children: "); pw.print(numberChildren);
+ for (int i = 0; i < numberChildren; i++) {
+ final ContentCaptureSession child = mChildren.get(i);
+ pw.print(prefix); pw.print(i); pw.println(": "); child.dump(prefix2, pw);
+ }
+ }
+
+ }
@Override
public String toString() {
diff --git a/core/java/android/view/contentcapture/IContentCaptureManager.aidl b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
index cbd37017038e..01776f846434 100644
--- a/core/java/android/view/contentcapture/IContentCaptureManager.aidl
+++ b/core/java/android/view/contentcapture/IContentCaptureManager.aidl
@@ -33,7 +33,6 @@ import java.util.List;
*/
oneway interface IContentCaptureManager {
void startSession(int userId, IBinder activityToken, in ComponentName componentName,
- String sessionId, in ContentCaptureContext clientContext, int flags,
- in IResultReceiver result);
+ String sessionId, int flags, in IResultReceiver result);
void finishSession(int userId, String sessionId);
}
diff --git a/core/java/android/view/contentcapture/ActivityContentCaptureSession.java b/core/java/android/view/contentcapture/MainContentCaptureSession.java
index a8f3e0bbd45d..ea6f2fe16ef6 100644
--- a/core/java/android/view/contentcapture/ActivityContentCaptureSession.java
+++ b/core/java/android/view/contentcapture/MainContentCaptureSession.java
@@ -15,6 +15,8 @@
*/
package android.view.contentcapture;
+import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_FINISHED;
+import static android.view.contentcapture.ContentCaptureEvent.TYPE_SESSION_STARTED;
import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_APPEARED;
import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_DISAPPEARED;
import static android.view.contentcapture.ContentCaptureEvent.TYPE_VIEW_TEXT_CHANGED;
@@ -59,7 +61,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
*
* @hide
*/
-public final class ActivityContentCaptureSession extends ContentCaptureSession {
+public final class MainContentCaptureSession extends ContentCaptureSession {
/**
* Handler message used to flush the buffer.
@@ -129,18 +131,23 @@ public final class ActivityContentCaptureSession extends ContentCaptureSession {
// Lazily created on demand.
private ContentCaptureSessionId mContentCaptureSessionId;
- /**
- * @hide */
- protected ActivityContentCaptureSession(@NonNull Context context, @NonNull Handler handler,
- @Nullable IContentCaptureManager systemServerInterface, @NonNull AtomicBoolean disabled,
- @Nullable ContentCaptureContext clientContext) {
- super(clientContext);
+ /** @hide */
+ protected MainContentCaptureSession(@NonNull Context context, @NonNull Handler handler,
+ @Nullable IContentCaptureManager systemServerInterface,
+ @NonNull AtomicBoolean disabled) {
mContext = context;
mHandler = handler;
mSystemServerInterface = systemServerInterface;
mDisabled = disabled;
}
+ @Override
+ ContentCaptureSession newChild(@NonNull ContentCaptureContext clientContext) {
+ final ContentCaptureSession child = new ChildContentCaptureSession(this, clientContext);
+ notifyChildSessionStarted(mId, child.mId, clientContext);
+ return child;
+ }
+
/**
* Starts this session.
*
@@ -154,19 +161,19 @@ public final class ActivityContentCaptureSession extends ContentCaptureSession {
+ ComponentName.flattenToShortString(activityComponent));
}
- mHandler.sendMessage(obtainMessage(ActivityContentCaptureSession::handleStartSession, this,
+ mHandler.sendMessage(obtainMessage(MainContentCaptureSession::handleStartSession, this,
applicationToken, activityComponent));
}
@Override
void flush() {
- mHandler.sendMessage(obtainMessage(ActivityContentCaptureSession::handleForceFlush, this));
+ mHandler.sendMessage(obtainMessage(MainContentCaptureSession::handleForceFlush, this));
}
@Override
void onDestroy() {
mHandler.sendMessage(
- obtainMessage(ActivityContentCaptureSession::handleDestroySession, this));
+ obtainMessage(MainContentCaptureSession::handleDestroySession, this));
}
private void handleStartSession(@NonNull IBinder token, @NonNull ComponentName componentName) {
@@ -188,7 +195,7 @@ public final class ActivityContentCaptureSession extends ContentCaptureSession {
try {
mSystemServerInterface.startSession(mContext.getUserId(), mApplicationToken,
- componentName, mId, mClientContext, flags, new IResultReceiver.Stub() {
+ componentName, mId, flags, new IResultReceiver.Stub() {
@Override
public void send(int resultCode, Bundle resultData) {
IBinder binder = null;
@@ -296,7 +303,7 @@ public final class ActivityContentCaptureSession extends ContentCaptureSession {
Log.v(mTag, "Scheduled to flush in " + FLUSHING_FREQUENCY_MS + "ms: " + mNextFlush);
}
mHandler.sendMessageDelayed(
- obtainMessage(ActivityContentCaptureSession::handleFlushIfNeeded, this)
+ obtainMessage(MainContentCaptureSession::handleFlushIfNeeded, this)
.setWhat(MSG_FLUSH), FLUSHING_FREQUENCY_MS);
}
@@ -312,7 +319,7 @@ public final class ActivityContentCaptureSession extends ContentCaptureSession {
if (mEvents == null) return;
if (mDirectServiceInterface == null) {
- Log.w(mTag, "handleForceFlush(): client not available yet");
+ if (DEBUG) Log.d(mTag, "handleForceFlush(): hold your horses, client not ready yet!");
if (!mHandler.hasMessages(MSG_FLUSH)) {
handleScheduleFlush(/* checkExisting= */ false);
}
@@ -367,12 +374,15 @@ public final class ActivityContentCaptureSession extends ContentCaptureSession {
handleResetSession(/* resetState= */ true);
}
- // TODO(b/121042846): once we support multiple sessions, we might need to move some of these
+ // TODO(b/121033016): once we support multiple sessions, we might need to move some of these
// clearings out.
private void handleResetSession(boolean resetState) {
if (resetState) {
mState = STATE_UNKNOWN;
}
+
+ // TODO(b/121033016): must reset children (which currently is owned by superclass)
+
mContentCaptureSessionId = null;
mApplicationToken = null;
mComponentName = null;
@@ -386,24 +396,18 @@ public final class ActivityContentCaptureSession extends ContentCaptureSession {
@Override
void internalNotifyViewAppeared(@NonNull ViewStructureImpl node) {
- mHandler.sendMessage(obtainMessage(ActivityContentCaptureSession::handleSendEvent, this,
- new ContentCaptureEvent(mId, TYPE_VIEW_APPEARED)
- .setViewNode(node.mNode), /* forceFlush= */ false));
+ notifyViewAppeared(mId, node);
}
@Override
void internalNotifyViewDisappeared(@NonNull AutofillId id) {
- mHandler.sendMessage(obtainMessage(ActivityContentCaptureSession::handleSendEvent, this,
- new ContentCaptureEvent(mId, TYPE_VIEW_DISAPPEARED).setAutofillId(id),
- /* forceFlush= */ false));
+ notifyViewDisappeared(mId, id);
}
@Override
void internalNotifyViewTextChanged(@NonNull AutofillId id, @Nullable CharSequence text,
int flags) {
- mHandler.sendMessage(obtainMessage(ActivityContentCaptureSession::handleSendEvent, this,
- new ContentCaptureEvent(mId, TYPE_VIEW_TEXT_CHANGED, flags).setAutofillId(id)
- .setText(text), /* forceFlush= */ false));
+ notifyViewTextChanged(mId, id, text, flags);
}
@Override
@@ -411,6 +415,44 @@ public final class ActivityContentCaptureSession extends ContentCaptureSession {
return mSystemServerInterface != null && !mDisabled.get();
}
+ // TODO(b/121033016): refactor "notifyXXXX" methods below to a common "Buffer" object that is
+ // shared between ActivityContentCaptureSession and ChildContentCaptureSession objects. Such
+ // change should also get get rid of the "internalNotifyXXXX" methods above
+ void notifyChildSessionStarted(@NonNull String parentSessionId,
+ @NonNull String childSessionId, @NonNull ContentCaptureContext clientContext) {
+ mHandler.sendMessage(obtainMessage(MainContentCaptureSession::handleSendEvent, this,
+ new ContentCaptureEvent(childSessionId, TYPE_SESSION_STARTED)
+ .setParentSessionId(parentSessionId)
+ .setClientContext(clientContext),
+ /* forceFlush= */ false));
+ }
+
+ void notifyChildSessionFinished(@NonNull String parentSessionId,
+ @NonNull String childSessionId) {
+ mHandler.sendMessage(obtainMessage(MainContentCaptureSession::handleSendEvent, this,
+ new ContentCaptureEvent(childSessionId, TYPE_SESSION_FINISHED)
+ .setParentSessionId(parentSessionId), /* forceFlush= */ false));
+ }
+
+ void notifyViewAppeared(@NonNull String sessionId, @NonNull ViewStructureImpl node) {
+ mHandler.sendMessage(obtainMessage(MainContentCaptureSession::handleSendEvent, this,
+ new ContentCaptureEvent(sessionId, TYPE_VIEW_APPEARED)
+ .setViewNode(node.mNode), /* forceFlush= */ false));
+ }
+
+ void notifyViewDisappeared(@NonNull String sessionId, @NonNull AutofillId id) {
+ mHandler.sendMessage(obtainMessage(MainContentCaptureSession::handleSendEvent, this,
+ new ContentCaptureEvent(sessionId, TYPE_VIEW_DISAPPEARED).setAutofillId(id),
+ /* forceFlush= */ false));
+ }
+
+ void notifyViewTextChanged(@NonNull String sessionId, @NonNull AutofillId id,
+ @Nullable CharSequence text, int flags) {
+ mHandler.sendMessage(obtainMessage(MainContentCaptureSession::handleSendEvent, this,
+ new ContentCaptureEvent(sessionId, TYPE_VIEW_TEXT_CHANGED, flags).setAutofillId(id)
+ .setText(text), /* forceFlush= */ false));
+ }
+
@Override
void dump(@NonNull String prefix, @NonNull PrintWriter pw) {
pw.print(prefix); pw.print("id: "); pw.println(mId);
@@ -424,11 +466,6 @@ public final class ActivityContentCaptureSession extends ContentCaptureSession {
pw.print(prefix); pw.print("mDirectServiceInterface: ");
pw.println(mDirectServiceInterface);
}
- if (mClientContext != null) {
- // NOTE: we don't dump clientContent because it could have PII
- pw.print(prefix); pw.println("hasClientContext");
-
- }
pw.print(prefix); pw.print("mDisabled: "); pw.println(mDisabled.get());
pw.print(prefix); pw.print("isEnabled(): "); pw.println(isContentCaptureEnabled());
if (mContentCaptureSessionId != null) {
@@ -459,6 +496,7 @@ public final class ActivityContentCaptureSession extends ContentCaptureSession {
pw.print(prefix); pw.print("next flush: ");
TimeUtils.formatDuration(mNextFlush - SystemClock.elapsedRealtime(), pw); pw.println();
}
+ super.dump(prefix, pw);
}
/**
diff --git a/core/java/android/view/textclassifier/ActionsSuggestionsHelper.java b/core/java/android/view/textclassifier/ActionsSuggestionsHelper.java
index b41096c74bf7..77cb4cd28763 100644
--- a/core/java/android/view/textclassifier/ActionsSuggestionsHelper.java
+++ b/core/java/android/view/textclassifier/ActionsSuggestionsHelper.java
@@ -17,6 +17,7 @@
package android.view.textclassifier;
import android.app.Person;
+import android.content.Context;
import android.text.TextUtils;
import android.util.ArrayMap;
@@ -28,7 +29,10 @@ import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
+import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
+import java.util.StringJoiner;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -84,6 +88,29 @@ public final class ActionsSuggestionsHelper {
new ActionsSuggestionsModel.ConversationMessage[nativeMessages.size()]);
}
+ /**
+ * Returns the result id for logging.
+ */
+ public static String createResultId(
+ Context context,
+ List<ConversationActions.Message> messages,
+ int modelVersion,
+ List<Locale> modelLocales) {
+ final StringJoiner localesJoiner = new StringJoiner(",");
+ for (Locale locale : modelLocales) {
+ localesJoiner.add(locale.toLanguageTag());
+ }
+ final String modelName = String.format(
+ Locale.US, "%s_v%d", localesJoiner.toString(), modelVersion);
+ final int hash = Objects.hash(
+ messages.stream()
+ .map(ConversationActions.Message::getText)
+ .collect(Collectors.toList()),
+ context.getPackageName());
+ return SelectionSessionLogger.SignatureParser.createSignature(
+ SelectionSessionLogger.CLASSIFIER_ID, modelName, hash);
+ }
+
private static final class PersonEncoder {
private final Map<Person, Integer> mMapping = new ArrayMap<>();
private int mNextUserId = FIRST_NON_LOCAL_USER;
diff --git a/core/java/android/view/textclassifier/TextClassifierEvent.java b/core/java/android/view/textclassifier/TextClassifierEvent.java
index 3bb9ee88dae9..f2fea02171f9 100644
--- a/core/java/android/view/textclassifier/TextClassifierEvent.java
+++ b/core/java/android/view/textclassifier/TextClassifierEvent.java
@@ -27,6 +27,7 @@ import com.android.internal.util.Preconditions;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
/**
* A text classifier event.
@@ -498,4 +499,25 @@ public final class TextClassifierEvent implements Parcelable {
}
// TODO: Add build(boolean validate).
}
+
+ @Override
+ public String toString() {
+ StringBuilder out = new StringBuilder(128);
+ out.append("TextClassifierEvent{");
+ out.append("mEventCategory=").append(mEventCategory);
+ out.append(", mEventType=").append(mEventType);
+ out.append(", mEventContext=").append(mEventContext);
+ out.append(", mResultId=").append(mResultId);
+ out.append(", mEventIndex=").append(mEventIndex);
+ out.append(", mEventTime=").append(mEventTime);
+ out.append(", mExtras=").append(mExtras);
+ out.append(", mRelativeWordStartIndex=").append(mRelativeWordStartIndex);
+ out.append(", mRelativeWordEndIndex=").append(mRelativeWordEndIndex);
+ out.append(", mRelativeSuggestedWordStartIndex=").append(mRelativeSuggestedWordStartIndex);
+ out.append(", mRelativeSuggestedWordEndIndex=").append(mRelativeSuggestedWordEndIndex);
+ out.append(", mActionIndices=").append(Arrays.toString(mActionIndices));
+ out.append(", mLanguage=").append(mLanguage);
+ out.append("}");
+ return out.toString();
+ }
}
diff --git a/core/java/android/view/textclassifier/TextClassifierImpl.java b/core/java/android/view/textclassifier/TextClassifierImpl.java
index 9b0f9c6ee5e8..fcd06c384921 100644
--- a/core/java/android/view/textclassifier/TextClassifierImpl.java
+++ b/core/java/android/view/textclassifier/TextClassifierImpl.java
@@ -80,6 +80,8 @@ public final class TextClassifierImpl implements TextClassifier {
private static final String LOG_TAG = DEFAULT_LOG_TAG;
+ private static final boolean DEBUG = false;
+
private static final File FACTORY_MODEL_DIR = new File("/etc/textclassifier/");
// Annotator
private static final String ANNOTATOR_FACTORY_MODEL_FILENAME_REGEX =
@@ -109,6 +111,8 @@ public final class TextClassifierImpl implements TextClassifier {
@GuardedBy("mLock") // Do not access outside this lock.
private LangIdModel mLangIdImpl;
@GuardedBy("mLock") // Do not access outside this lock.
+ private ModelFileManager.ModelFile mActionModelInUse;
+ @GuardedBy("mLock") // Do not access outside this lock.
private ActionsSuggestionsModel mActionsImpl;
private final Object mLoggerLock = new Object();
@@ -342,8 +346,10 @@ public final class TextClassifierImpl implements TextClassifier {
}
@Override
- public void onTextClassifierEvent(@NonNull TextClassifierEvent event) {
- // TODO: Implement.
+ public void onTextClassifierEvent(TextClassifierEvent event) {
+ if (DEBUG) {
+ Log.d(DEFAULT_LOG_TAG, "onTextClassifierEvent() called with: event = [" + event + "]");
+ }
}
/** @inheritDoc */
@@ -408,7 +414,12 @@ public final class TextClassifierImpl implements TextClassifier {
.setConfidenceScore(nativeSuggestion.getScore())
.build());
}
- return new ConversationActions(conversationActions, /*id*/ null);
+ String resultId = ActionsSuggestionsHelper.createResultId(
+ mContext,
+ request.getConversation(),
+ mActionModelInUse.getVersion(),
+ mActionModelInUse.getSupportedLocales());
+ return new ConversationActions(conversationActions, resultId);
} catch (Throwable t) {
// Avoid throwing from this method. Log the error.
Log.e(LOG_TAG, "Error suggesting conversation actions.", t);
@@ -517,6 +528,7 @@ public final class TextClassifierImpl implements TextClassifier {
try {
if (pfd != null) {
mActionsImpl = new ActionsSuggestionsModel(pfd.getFd());
+ mActionModelInUse = bestModel;
}
} finally {
maybeCloseAndLogError(pfd);
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 12ca78a7ce92..eb7338a7ce58 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -45,7 +45,7 @@ namespace android {
class BitmapWrapper {
public:
- BitmapWrapper(Bitmap* bitmap)
+ explicit BitmapWrapper(Bitmap* bitmap)
: mBitmap(bitmap) { }
void freePixels() {
diff --git a/core/jni/android/graphics/FontUtils.h b/core/jni/android/graphics/FontUtils.h
index 9f6462e67050..b36b4e60e33a 100644
--- a/core/jni/android/graphics/FontUtils.h
+++ b/core/jni/android/graphics/FontUtils.h
@@ -29,7 +29,7 @@ class FontFamily;
namespace android {
struct FontFamilyWrapper {
- FontFamilyWrapper(std::shared_ptr<minikin::FontFamily>&& family) : family(family) {}
+ explicit FontFamilyWrapper(std::shared_ptr<minikin::FontFamily>&& family) : family(family) {}
std::shared_ptr<minikin::FontFamily> family;
};
diff --git a/core/jni/android/graphics/GIFMovie.cpp b/core/jni/android/graphics/GIFMovie.cpp
index dd99b377988f..f84a4bd09073 100644
--- a/core/jni/android/graphics/GIFMovie.cpp
+++ b/core/jni/android/graphics/GIFMovie.cpp
@@ -21,7 +21,7 @@
class GIFMovie : public Movie {
public:
- GIFMovie(SkStream* stream);
+ explicit GIFMovie(SkStream* stream);
virtual ~GIFMovie();
protected:
diff --git a/core/jni/android_media_AudioTrack.cpp b/core/jni/android_media_AudioTrack.cpp
index 516093e42691..1065738466e7 100644
--- a/core/jni/android_media_AudioTrack.cpp
+++ b/core/jni/android_media_AudioTrack.cpp
@@ -20,7 +20,6 @@
#include "android_media_AudioTrack.h"
#include <nativehelper/JNIHelp.h>
-#include <nativehelper/JniConstants.h>
#include "core_jni_helpers.h"
#include <utils/Log.h>
diff --git a/core/jni/android_media_DeviceCallback.cpp b/core/jni/android_media_DeviceCallback.cpp
index 108fa00fe510..a1a035110caf 100644
--- a/core/jni/android_media_DeviceCallback.cpp
+++ b/core/jni/android_media_DeviceCallback.cpp
@@ -20,7 +20,6 @@
#include <utils/Log.h>
#include <nativehelper/JNIHelp.h>
-#include <nativehelper/JniConstants.h>
#include "core_jni_helpers.h"
#include <media/AudioSystem.h>
diff --git a/core/jni/android_os_SharedMemory.cpp b/core/jni/android_os_SharedMemory.cpp
index f6e5c7a48c4c..c33405def25e 100644
--- a/core/jni/android_os_SharedMemory.cpp
+++ b/core/jni/android_os_SharedMemory.cpp
@@ -20,8 +20,9 @@
#include <cutils/ashmem.h>
#include <utils/Log.h>
+
+#include <nativehelper/jni_macros.h>
#include <nativehelper/JNIHelp.h>
-#include <nativehelper/JniConstants.h>
#include <nativehelper/ScopedLocalRef.h>
#include <algorithm>
@@ -31,10 +32,10 @@
namespace {
-static void throwErrnoException(JNIEnv* env, const char* functionName, int error) {
- static jmethodID ctor = env->GetMethodID(JniConstants::errnoExceptionClass,
- "<init>", "(Ljava/lang/String;I)V");
+jclass errnoExceptionClass;
+jmethodID errnoExceptionCtor; // MethodID for ErrnoException.<init>(String,I)
+void throwErrnoException(JNIEnv* env, const char* functionName, int error) {
ScopedLocalRef<jstring> detailMessage(env, env->NewStringUTF(functionName));
if (detailMessage.get() == NULL) {
// Not really much we can do here. We're probably dead in the water,
@@ -42,12 +43,14 @@ static void throwErrnoException(JNIEnv* env, const char* functionName, int error
env->ExceptionClear();
}
- jobject exception = env->NewObject(JniConstants::errnoExceptionClass, ctor,
- detailMessage.get(), error);
+ jobject exception = env->NewObject(errnoExceptionClass,
+ errnoExceptionCtor,
+ detailMessage.get(),
+ error);
env->Throw(reinterpret_cast<jthrowable>(exception));
}
-static jobject SharedMemory_create(JNIEnv* env, jobject, jstring jname, jint size) {
+jobject SharedMemory_nCreate(JNIEnv* env, jobject, jstring jname, jint size) {
// Name is optional so we can't use ScopedUtfChars for this as it throws NPE on null
const char* name = jname ? env->GetStringUTFChars(jname, nullptr) : nullptr;
@@ -69,7 +72,7 @@ static jobject SharedMemory_create(JNIEnv* env, jobject, jstring jname, jint siz
return jniCreateFileDescriptor(env, fd);
}
-static jint SharedMemory_getSize(JNIEnv* env, jobject, jobject fileDescriptor) {
+jint SharedMemory_nGetSize(JNIEnv* env, jobject, jobject fileDescriptor) {
int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
if (!ashmem_valid(fd)) {
return -1;
@@ -78,7 +81,7 @@ static jint SharedMemory_getSize(JNIEnv* env, jobject, jobject fileDescriptor) {
return static_cast<jint>(std::min(size, static_cast<size_t>(std::numeric_limits<jint>::max())));
}
-static jint SharedMemory_setProt(JNIEnv* env, jobject, jobject fileDescriptor, jint prot) {
+jint SharedMemory_nSetProt(JNIEnv* env, jobject, jobject fileDescriptor, jint prot) {
int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
int err = 0;
if (ashmem_set_prot_region(fd, prot)) {
@@ -87,18 +90,21 @@ static jint SharedMemory_setProt(JNIEnv* env, jobject, jobject fileDescriptor, j
return err;
}
-static const JNINativeMethod methods[] = {
- {"nCreate", "(Ljava/lang/String;I)Ljava/io/FileDescriptor;", (void*)SharedMemory_create},
- {"nGetSize", "(Ljava/io/FileDescriptor;)I", (void*)SharedMemory_getSize},
- {"nSetProt", "(Ljava/io/FileDescriptor;I)I", (void*)SharedMemory_setProt},
+const JNINativeMethod methods[] = {
+ NATIVE_METHOD(SharedMemory, nCreate, "(Ljava/lang/String;I)Ljava/io/FileDescriptor;"),
+ NATIVE_METHOD(SharedMemory, nGetSize, "(Ljava/io/FileDescriptor;)I"),
+ NATIVE_METHOD(SharedMemory, nSetProt, "(Ljava/io/FileDescriptor;I)I")
};
} // anonymous namespace
namespace android {
-int register_android_os_SharedMemory(JNIEnv* env)
-{
+int register_android_os_SharedMemory(JNIEnv* env) {
+ errnoExceptionClass =
+ MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/system/ErrnoException"));
+ errnoExceptionCtor =
+ GetMethodIDOrDie(env, errnoExceptionClass, "<init>", "(Ljava/lang/String;I)V");
return RegisterMethodsOrDie(env, "android/os/SharedMemory", methods, NELEM(methods));
}
diff --git a/core/jni/android_util_jar_StrictJarFile.cpp b/core/jni/android_util_jar_StrictJarFile.cpp
index 4ab8db4395f6..182a621c6978 100644
--- a/core/jni/android_util_jar_StrictJarFile.cpp
+++ b/core/jni/android_util_jar_StrictJarFile.cpp
@@ -22,24 +22,26 @@
#include <log/log.h>
+#include <nativehelper/jni_macros.h>
#include <nativehelper/JNIHelp.h>
-#include <nativehelper/JniConstants.h>
#include <nativehelper/ScopedLocalRef.h>
#include <nativehelper/ScopedUtfChars.h>
-#include "jni.h"
+
+#include "core_jni_helpers.h"
#include "ziparchive/zip_archive.h"
-namespace android {
+namespace {
+jclass zipEntryClass;
// The method ID for ZipEntry.<init>(String,String,JJJIII[BJJ)
-static jmethodID zipEntryCtor;
+jmethodID zipEntryCtor;
-static void throwIoException(JNIEnv* env, const int32_t errorCode) {
+void throwIoException(JNIEnv* env, const int32_t errorCode) {
jniThrowException(env, "java/io/IOException", ErrorCodeString(errorCode));
}
-static jobject newZipEntry(JNIEnv* env, const ZipEntry& entry, jstring entryName) {
- return env->NewObject(JniConstants::zipEntryClass,
+jobject newZipEntry(JNIEnv* env, const ZipEntry& entry, jstring entryName) {
+ return env->NewObject(zipEntryClass,
zipEntryCtor,
entryName,
NULL, // comment
@@ -52,7 +54,7 @@ static jobject newZipEntry(JNIEnv* env, const ZipEntry& entry, jstring entryName
static_cast<jlong>(entry.offset));
}
-static jlong StrictJarFile_nativeOpenJarFile(JNIEnv* env, jobject, jstring name, jint fd) {
+jlong StrictJarFile_nativeOpenJarFile(JNIEnv* env, jobject, jstring name, jint fd) {
// Name argument is used for logging, and can be any string.
ScopedUtfChars nameChars(env, name);
if (nameChars.c_str() == NULL) {
@@ -90,7 +92,7 @@ class IterationHandle {
};
-static jlong StrictJarFile_nativeStartIteration(JNIEnv* env, jobject, jlong nativeHandle,
+jlong StrictJarFile_nativeStartIteration(JNIEnv* env, jobject, jlong nativeHandle,
jstring prefix) {
ScopedUtfChars prefixChars(env, prefix);
if (prefixChars.c_str() == NULL) {
@@ -116,7 +118,7 @@ static jlong StrictJarFile_nativeStartIteration(JNIEnv* env, jobject, jlong nati
return reinterpret_cast<jlong>(handle);
}
-static jobject StrictJarFile_nativeNextEntry(JNIEnv* env, jobject, jlong iterationHandle) {
+jobject StrictJarFile_nativeNextEntry(JNIEnv* env, jobject, jlong iterationHandle) {
ZipEntry data;
ZipString entryName;
@@ -135,7 +137,7 @@ static jobject StrictJarFile_nativeNextEntry(JNIEnv* env, jobject, jlong iterati
return newZipEntry(env, data, entryNameString.get());
}
-static jobject StrictJarFile_nativeFindEntry(JNIEnv* env, jobject, jlong nativeHandle,
+jobject StrictJarFile_nativeFindEntry(JNIEnv* env, jobject, jlong nativeHandle,
jstring entryName) {
ScopedUtfChars entryNameChars(env, entryName);
if (entryNameChars.c_str() == NULL) {
@@ -152,11 +154,11 @@ static jobject StrictJarFile_nativeFindEntry(JNIEnv* env, jobject, jlong nativeH
return newZipEntry(env, data, entryName);
}
-static void StrictJarFile_nativeClose(JNIEnv*, jobject, jlong nativeHandle) {
+void StrictJarFile_nativeClose(JNIEnv*, jobject, jlong nativeHandle) {
CloseArchive(reinterpret_cast<ZipArchiveHandle>(nativeHandle));
}
-static JNINativeMethod gMethods[] = {
+JNINativeMethod gMethods[] = {
NATIVE_METHOD(StrictJarFile, nativeOpenJarFile, "(Ljava/lang/String;I)J"),
NATIVE_METHOD(StrictJarFile, nativeStartIteration, "(JLjava/lang/String;)J"),
NATIVE_METHOD(StrictJarFile, nativeNextEntry, "(J)Ljava/util/zip/ZipEntry;"),
@@ -164,14 +166,15 @@ static JNINativeMethod gMethods[] = {
NATIVE_METHOD(StrictJarFile, nativeClose, "(J)V"),
};
-int register_android_util_jar_StrictJarFile(JNIEnv* env) {
- jniRegisterNativeMethods(env, "android/util/jar/StrictJarFile", gMethods, NELEM(gMethods));
+} // namespace
- zipEntryCtor = env->GetMethodID(JniConstants::zipEntryClass, "<init>",
- "(Ljava/lang/String;Ljava/lang/String;JJJII[BJ)V");
- LOG_ALWAYS_FATAL_IF(zipEntryCtor == NULL, "Unable to find ZipEntry.<init>");
+namespace android {
- return 0;
+int register_android_util_jar_StrictJarFile(JNIEnv* env) {
+ zipEntryClass = MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/util/zip/ZipEntry"));
+ zipEntryCtor = GetMethodIDOrDie(env, zipEntryClass, "<init>",
+ "(Ljava/lang/String;Ljava/lang/String;JJJII[BJ)V");
+ return jniRegisterNativeMethods(env, "android/util/jar/StrictJarFile", gMethods, NELEM(gMethods));
}
}; // namespace android
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index 33b26899fe81..bd87dcc325a8 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -152,7 +152,7 @@ class FileDescriptorInfo {
const bool is_sock;
private:
- FileDescriptorInfo(int fd);
+ explicit FileDescriptorInfo(int fd);
FileDescriptorInfo(struct stat stat, const std::string& file_path, int fd, int open_flags,
int fd_flags, int fs_flags, off_t offset);
diff --git a/core/jni/fd_utils.h b/core/jni/fd_utils.h
index a3570d7ed1fb..09022a2e2408 100644
--- a/core/jni/fd_utils.h
+++ b/core/jni/fd_utils.h
@@ -86,7 +86,7 @@ class FileDescriptorTable {
bool ReopenOrDetach(std::string* error_msg);
private:
- FileDescriptorTable(const std::unordered_map<int, FileDescriptorInfo*>& map);
+ explicit FileDescriptorTable(const std::unordered_map<int, FileDescriptorInfo*>& map);
bool RestatInternal(std::set<int>& open_fds, std::string* error_msg);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 8b6f33fd97e7..c6343a8738d8 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -611,6 +611,7 @@
<protected-broadcast android:name="android.intent.action.DOCK_ACTIVE" />
<!-- Added in Q -->
+ <protected-broadcast android:name="android.content.pm.action.SESSION_UPDATED" />
<!-- For CarIdlenessTracker -->
<protected-broadcast android:name="com.android.server.jobscheduler.GARAGE_MODE_ON" />
@@ -4336,7 +4337,7 @@
<permission android:name="android.permission.SMS_FINANCIAL_TRANSACTIONS"
android:protectionLevel="signature|appop" />
- <!-- Required for apps targeting {@link android.os.Build.VERSION_CODES#P} that want to use
+ <!-- Required for apps targeting {@link android.os.Build.VERSION_CODES#Q} that want to use
{@link android.app.Notification.Builder#setFullScreenIntent notification full screen
intents}. -->
<permission android:name="android.permission.USE_FULL_SCREEN_INTENT"
diff --git a/core/res/res/values/styles_device_defaults.xml b/core/res/res/values/styles_device_defaults.xml
index 4b97fe754fea..7c95d1efb60d 100644
--- a/core/res/res/values/styles_device_defaults.xml
+++ b/core/res/res/values/styles_device_defaults.xml
@@ -42,7 +42,7 @@ easier.
<item name="textColor">@color/btn_colored_text_material</item>
</style>
<style name="Widget.DeviceDefault.TextView" parent="Widget.Material.TextView">
- <item name="textAppearance">@string/config_bodyFontFamily</item>
+ <item name="fontFamily">@string/config_bodyFontFamily</item>
</style>
<style name="Widget.DeviceDefault.CheckedTextView" parent="Widget.Material.CheckedTextView"/>
<style name="Widget.DeviceDefault.AutoCompleteTextView" parent="Widget.Material.AutoCompleteTextView"/>
diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
new file mode 100644
index 000000000000..d520f151c2fa
--- /dev/null
+++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java
@@ -0,0 +1,121 @@
+/*
+ * 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.view;
+
+import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.TYPE_TOP_BAR;
+import static junit.framework.Assert.assertEquals;
+import static org.mockito.Mockito.verify;
+
+import android.graphics.Insets;
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.FlakyTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.util.SparseArray;
+import android.view.SurfaceControl.Transaction;
+import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.List;
+
+@Presubmit
+@FlakyTest(detail = "Promote once confirmed non-flaky")
+@RunWith(AndroidJUnit4.class)
+public class InsetsAnimationControlImplTest {
+
+ private InsetsAnimationControlImpl mController;
+
+ private SurfaceSession mSession = new SurfaceSession();
+ private SurfaceControl mTopLeash;
+ private SurfaceControl mNavLeash;
+
+ @Mock Transaction mMockTransaction;
+ @Mock InsetsController mMockController;
+ @Mock WindowInsetsAnimationControlListener mMockListener;
+ @Mock SyncRtSurfaceTransactionApplier mMockTransactionApplier;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mTopLeash = new SurfaceControl.Builder(mSession)
+ .setName("testSurface")
+ .build();
+ mNavLeash = new SurfaceControl.Builder(mSession)
+ .setName("testSurface")
+ .build();
+ InsetsState state = new InsetsState();
+ state.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 500, 100));
+ state.getSource(TYPE_NAVIGATION_BAR).setFrame(new Rect(400, 0, 500, 500));
+ InsetsSourceConsumer topConsumer = new InsetsSourceConsumer(TYPE_TOP_BAR, state,
+ () -> mMockTransaction, mMockController);
+ topConsumer.setControl(new InsetsSourceControl(TYPE_TOP_BAR, mTopLeash));
+
+ InsetsSourceConsumer navConsumer = new InsetsSourceConsumer(TYPE_NAVIGATION_BAR, state,
+ () -> mMockTransaction, mMockController);
+ navConsumer.hide();
+ navConsumer.setControl(new InsetsSourceControl(TYPE_NAVIGATION_BAR, mNavLeash));
+
+ SparseArray<InsetsSourceConsumer> consumers = new SparseArray<>();
+ consumers.put(TYPE_TOP_BAR, topConsumer);
+ consumers.put(TYPE_NAVIGATION_BAR, navConsumer);
+ mController = new InsetsAnimationControlImpl(consumers,
+ new Rect(0, 0, 500, 500), state, mMockListener, WindowInsets.Type.systemBars(),
+ () -> mMockTransactionApplier);
+ }
+
+ @Test
+ public void testGetters() {
+ assertEquals(Insets.of(0, 100, 100, 0), mController.getShownStateInsets());
+ assertEquals(Insets.of(0, 0, 0, 0), mController.getHiddenStateInsets());
+ assertEquals(Insets.of(0, 100, 0, 0), mController.getCurrentInsets());
+ assertEquals(WindowInsets.Type.systemBars(), mController.getTypes());
+ }
+
+ @Test
+ public void testChangeInsets() {
+ mController.changeInsets(Insets.of(0, 30, 40, 0));
+ assertEquals(Insets.of(0, 30, 40, 0), mController.getCurrentInsets());
+
+ ArgumentCaptor<SurfaceParams> captor = ArgumentCaptor.forClass(SurfaceParams.class);
+ verify(mMockTransactionApplier).scheduleApply(captor.capture());
+ List<SurfaceParams> params = captor.getAllValues();
+ assertEquals(2, params.size());
+ SurfaceParams first = params.get(0);
+ SurfaceParams second = params.get(1);
+ SurfaceParams topParams = first.surface == mTopLeash ? first : second;
+ SurfaceParams navParams = first.surface == mNavLeash ? first : second;
+ assertPosition(topParams.matrix, new Rect(0, 0, 500, 100), new Rect(0, -70, 500, 30));
+ assertPosition(navParams.matrix, new Rect(400, 0, 500, 500), new Rect(460, 0, 560, 500));
+ }
+
+ private void assertPosition(Matrix m, Rect original, Rect transformed) {
+ RectF rect = new RectF(original);
+ rect.offsetTo(0, 0);
+ m.mapRect(rect);
+ rect.round(original);
+ assertEquals(original, transformed);
+ }
+}
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index 2ad6028960df..d3d274a64682 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -28,6 +28,7 @@ import android.support.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mockito;
@Presubmit
@FlakyTest(detail = "Promote once confirmed non-flaky")
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index 6bb9539e89bd..d41a718147f2 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -16,6 +16,8 @@
package android.view;
+import static android.view.InsetsState.INSET_SIDE_BOTTOM;
+import static android.view.InsetsState.INSET_SIDE_TOP;
import static android.view.InsetsState.TYPE_IME;
import static android.view.InsetsState.TYPE_NAVIGATION_BAR;
import static android.view.InsetsState.TYPE_TOP_BAR;
@@ -27,6 +29,7 @@ import android.os.Parcel;
import android.platform.test.annotations.Presubmit;
import android.support.test.filters.FlakyTest;
import android.support.test.runner.AndroidJUnit4;
+import android.util.SparseIntArray;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -45,9 +48,12 @@ public class InsetsStateTest {
mState.getSource(TYPE_TOP_BAR).setVisible(true);
mState.getSource(TYPE_IME).setFrame(new Rect(0, 200, 100, 300));
mState.getSource(TYPE_IME).setVisible(true);
+ SparseIntArray typeSideMap = new SparseIntArray();
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
- DisplayCutout.NO_CUTOUT);
+ DisplayCutout.NO_CUTOUT, typeSideMap);
assertEquals(new Rect(0, 100, 0, 100), insets.getSystemWindowInsets());
+ assertEquals(INSET_SIDE_TOP, typeSideMap.get(TYPE_TOP_BAR));
+ assertEquals(INSET_SIDE_BOTTOM, typeSideMap.get(TYPE_IME));
}
@Test
@@ -57,7 +63,7 @@ public class InsetsStateTest {
mState.getSource(TYPE_IME).setFrame(new Rect(0, 100, 100, 300));
mState.getSource(TYPE_IME).setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
- DisplayCutout.NO_CUTOUT);
+ DisplayCutout.NO_CUTOUT, null);
assertEquals(100, insets.getStableInsetBottom());
assertEquals(new Rect(0, 0, 0, 200), insets.getSystemWindowInsets());
}
@@ -69,7 +75,7 @@ public class InsetsStateTest {
mState.getSource(TYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
mState.getSource(TYPE_NAVIGATION_BAR).setVisible(true);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
- DisplayCutout.NO_CUTOUT);
+ DisplayCutout.NO_CUTOUT, null);
assertEquals(new Rect(0, 100, 20, 0), insets.getSystemWindowInsets());
}
@@ -81,7 +87,7 @@ public class InsetsStateTest {
mState.getSource(TYPE_IME).setVisible(true);
mState.removeSource(TYPE_IME);
WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
- DisplayCutout.NO_CUTOUT);
+ DisplayCutout.NO_CUTOUT, null);
assertEquals(0, insets.getSystemWindowInsetBottom());
}
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index c21642559bb9..58b57e5b7efd 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -33,6 +33,10 @@ applications that come with the platform
<permission name="android.permission.CRYPT_KEEPER"/>
</privapp-permissions>
+ <privapp-permissions package="com.android.carrierconfig">
+ <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
+ </privapp-permissions>
+
<privapp-permissions package="com.android.cellbroadcastreceiver">
<permission name="android.permission.INTERACT_ACROSS_USERS"/>
<permission name="android.permission.MANAGE_USERS"/>
diff --git a/graphics/java/android/graphics/Insets.java b/graphics/java/android/graphics/Insets.java
index d9da27c8b931..8258b575d63f 100644
--- a/graphics/java/android/graphics/Insets.java
+++ b/graphics/java/android/graphics/Insets.java
@@ -93,6 +93,41 @@ public final class Insets {
}
/**
+ * Subtract two Insets.
+ *
+ * @param a The minuend.
+ * @param b The subtrahend.
+ * @return a - b, i. e. all insets on every side are subtracted from each other.
+ */
+ public static @NonNull Insets subtract(@NonNull Insets a, @NonNull Insets b) {
+ return Insets.of(a.left - b.left, a.top - b.top, a.right - b.right, a.bottom - b.bottom);
+ }
+
+ /**
+ * Retrieves the maximum of two Insets.
+ *
+ * @param a The first Insets.
+ * @param b The second Insets.
+ * @return max(a, b), i. e. the larger of every inset on every side is taken for the result.
+ */
+ public static @NonNull Insets max(@NonNull Insets a, @NonNull Insets b) {
+ return Insets.of(Math.max(a.left, b.left), Math.max(a.top, b.top),
+ Math.max(a.right, b.right), Math.max(a.bottom, b.bottom));
+ }
+
+ /**
+ * Retrieves the minimum of two Insets.
+ *
+ * @param a The first Insets.
+ * @param b The second Insets.
+ * @return min(a, b), i. e. the smaller of every inset on every side is taken for the result.
+ */
+ public static @NonNull Insets min(@NonNull Insets a, @NonNull Insets b) {
+ return Insets.of(Math.min(a.left, b.left), Math.min(a.top, b.top),
+ Math.min(a.right, b.right), Math.min(a.bottom, b.bottom));
+ }
+
+ /**
* Two Insets instances are equal iff they belong to the same class and their fields are
* pairwise equal.
*
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 6e6ed30fef8c..9361c7c29bcb 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -55,6 +55,7 @@ import java.math.BigInteger;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
@@ -315,13 +316,14 @@ public class KeyStore {
}
/**
- * List uids of all keys that are auth bound to the current user.
+ * List uids of all keys that are auth bound to the current user.
* Only system is allowed to call this method.
*/
@UnsupportedAppUsage
public int[] listUidsOfAuthBoundKeys() {
- final int MAX_RESULT_SIZE = 100;
- int[] uidsOut = new int[MAX_RESULT_SIZE];
+ // uids are returned as a list of strings because list of integers
+ // as an output parameter is not supported by aidl-cpp.
+ List<String> uidsOut = new ArrayList<>();
try {
int rc = mBinder.listUidsOfAuthBoundKeys(uidsOut);
if (rc != NO_ERROR) {
@@ -335,8 +337,8 @@ public class KeyStore {
Log.w(TAG, "KeyStore exception", e);
return null;
}
- // Remove any 0 entries
- return Arrays.stream(uidsOut).filter(x -> x > 0).toArray();
+ // Turn list of strings into an array of uid integers.
+ return uidsOut.stream().mapToInt(Integer::parseInt).toArray();
}
public String[] list(String prefix) {
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h
index f2906de4d5a0..ff873133c6fb 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.h
@@ -30,7 +30,7 @@ namespace skiapipeline {
class SkiaPipeline : public renderthread::IRenderPipeline {
public:
- SkiaPipeline(renderthread::RenderThread& thread);
+ explicit SkiaPipeline(renderthread::RenderThread& thread);
virtual ~SkiaPipeline();
TaskManager* getTaskManager() override;
diff --git a/libs/hwui/pipeline/skia/SkiaProfileRenderer.h b/libs/hwui/pipeline/skia/SkiaProfileRenderer.h
index daa4c1839693..dc8420f4e01b 100644
--- a/libs/hwui/pipeline/skia/SkiaProfileRenderer.h
+++ b/libs/hwui/pipeline/skia/SkiaProfileRenderer.h
@@ -23,7 +23,7 @@ namespace uirenderer {
class SkiaProfileRenderer : public IProfileRenderer {
public:
- SkiaProfileRenderer(SkCanvas* canvas) : mCanvas(canvas) {}
+ explicit SkiaProfileRenderer(SkCanvas* canvas) : mCanvas(canvas) {}
void drawRect(float left, float top, float right, float bottom, const SkPaint& paint) override;
void drawRects(const float* rects, int count, const SkPaint& paint) override;
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
index 02874c7d2c69..53ffc4422fd7 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h
@@ -25,7 +25,7 @@ namespace skiapipeline {
class SkiaVulkanPipeline : public SkiaPipeline {
public:
- SkiaVulkanPipeline(renderthread::RenderThread& thread);
+ explicit SkiaVulkanPipeline(renderthread::RenderThread& thread);
virtual ~SkiaVulkanPipeline() {}
renderthread::MakeCurrentResult makeCurrent() override;
diff --git a/libs/hwui/pipeline/skia/VectorDrawableAtlas.h b/libs/hwui/pipeline/skia/VectorDrawableAtlas.h
index 74e48cea2a87..5e892aa7e92c 100644
--- a/libs/hwui/pipeline/skia/VectorDrawableAtlas.h
+++ b/libs/hwui/pipeline/skia/VectorDrawableAtlas.h
@@ -62,8 +62,8 @@ class VectorDrawableAtlas : public virtual RefBase {
public:
enum class StorageMode { allowSharedSurface, disallowSharedSurface };
- VectorDrawableAtlas(size_t surfaceArea,
- StorageMode storageMode = StorageMode::allowSharedSurface);
+ explicit VectorDrawableAtlas(size_t surfaceArea,
+ StorageMode storageMode = StorageMode::allowSharedSurface);
/**
* "prepareForDraw" may allocate a new surface if needed. It may schedule to repack the
diff --git a/libs/hwui/renderthread/CacheManager.h b/libs/hwui/renderthread/CacheManager.h
index 35fc91a42510..66f04f1ba266 100644
--- a/libs/hwui/renderthread/CacheManager.h
+++ b/libs/hwui/renderthread/CacheManager.h
@@ -59,7 +59,7 @@ public:
private:
friend class RenderThread;
- CacheManager(const DisplayInfo& display);
+ explicit CacheManager(const DisplayInfo& display);
void reset(sk_sp<GrContext> grContext);
void destroy();
diff --git a/libs/hwui/renderthread/VulkanManager.h b/libs/hwui/renderthread/VulkanManager.h
index 69ca23acb1fd..9eb942c9d6ee 100644
--- a/libs/hwui/renderthread/VulkanManager.h
+++ b/libs/hwui/renderthread/VulkanManager.h
@@ -160,6 +160,7 @@ private:
fPtr = ptr;
return *this;
}
+ // NOLINTNEXTLINE(google-explicit-constructor)
operator FNPTR_TYPE() const { return fPtr; }
private:
diff --git a/libs/incident/include/android/os/IncidentReportArgs.h b/libs/incident/include/android/os/IncidentReportArgs.h
index c56f689b7419..ee1e33c43b89 100644
--- a/libs/incident/include/android/os/IncidentReportArgs.h
+++ b/libs/incident/include/android/os/IncidentReportArgs.h
@@ -40,7 +40,7 @@ const uint8_t DEST_AUTOMATIC = 200;
class IncidentReportArgs : public Parcelable {
public:
IncidentReportArgs();
- explicit IncidentReportArgs(const IncidentReportArgs& that);
+ IncidentReportArgs(const IncidentReportArgs& that);
virtual ~IncidentReportArgs();
virtual status_t writeToParcel(Parcel* out) const;
diff --git a/location/java/android/location/GnssMeasurementCallbackTransport.java b/location/java/android/location/GnssMeasurementCallbackTransport.java
index 21f63068084e..1188b13b7841 100644
--- a/location/java/android/location/GnssMeasurementCallbackTransport.java
+++ b/location/java/android/location/GnssMeasurementCallbackTransport.java
@@ -19,6 +19,8 @@ package android.location;
import android.content.Context;
import android.os.RemoteException;
+import com.android.internal.util.Preconditions;
+
/**
* A handler class to manage transport callbacks for {@link GnssMeasurementsEvent.Callback}.
*
@@ -26,12 +28,13 @@ import android.os.RemoteException;
*/
class GnssMeasurementCallbackTransport
extends LocalListenerHelper<GnssMeasurementsEvent.Callback> {
+ private static final String TAG = "GnssMeasCbTransport";
private final ILocationManager mLocationManager;
private final IGnssMeasurementsListener mListenerTransport = new ListenerTransport();
public GnssMeasurementCallbackTransport(Context context, ILocationManager locationManager) {
- super(context, "GnssMeasurementListenerTransport");
+ super(context, TAG);
mLocationManager = locationManager;
}
@@ -47,17 +50,34 @@ class GnssMeasurementCallbackTransport
mLocationManager.removeGnssMeasurementsListener(mListenerTransport);
}
+ /**
+ * Injects GNSS measurement corrections into the GNSS chipset.
+ *
+ * @param measurementCorrections a {@link GnssMeasurementCorrections} object with the GNSS
+ * measurement corrections to be injected into the GNSS chipset.
+ */
+ protected void injectGnssMeasurementCorrections(
+ GnssMeasurementCorrections measurementCorrections) throws RemoteException {
+ Preconditions.checkNotNull(measurementCorrections);
+ mLocationManager.injectGnssMeasurementCorrections(
+ measurementCorrections, getContext().getPackageName());
+ }
+
+ protected int getGnssCapabilities() throws RemoteException {
+ return mLocationManager.getGnssCapabilities(getContext().getPackageName());
+ }
+
private class ListenerTransport extends IGnssMeasurementsListener.Stub {
@Override
public void onGnssMeasurementsReceived(final GnssMeasurementsEvent event) {
ListenerOperation<GnssMeasurementsEvent.Callback> operation =
new ListenerOperation<GnssMeasurementsEvent.Callback>() {
- @Override
- public void execute(GnssMeasurementsEvent.Callback callback)
- throws RemoteException {
- callback.onGnssMeasurementsReceived(event);
- }
- };
+ @Override
+ public void execute(GnssMeasurementsEvent.Callback callback)
+ throws RemoteException {
+ callback.onGnssMeasurementsReceived(event);
+ }
+ };
foreach(operation);
}
diff --git a/location/java/android/location/GnssMeasurementCorrections.aidl b/location/java/android/location/GnssMeasurementCorrections.aidl
new file mode 100644
index 000000000000..b05eb5455c82
--- /dev/null
+++ b/location/java/android/location/GnssMeasurementCorrections.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 208 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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;
+
+parcelable GnssMeasurementCorrections;
diff --git a/location/java/android/location/GnssMeasurementCorrections.java b/location/java/android/location/GnssMeasurementCorrections.java
new file mode 100644
index 000000000000..b81bf908053c
--- /dev/null
+++ b/location/java/android/location/GnssMeasurementCorrections.java
@@ -0,0 +1,210 @@
+/*
+ * 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.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * A class representing a GNSS measurement corrections for all used GNSS satellites at the location
+ * and time specified
+ *
+ * @hide
+ */
+@SystemApi
+public final class GnssMeasurementCorrections implements Parcelable {
+
+ /** Represents latitude in degrees at which the corrections are computed. */
+ private double mLatitudeDegrees;
+ /** Represents longitude in degrees at which the corrections are computed. */
+ private double mLongitudeDegrees;
+ /**
+ * Represents altitude in meters above the WGS 84 reference ellipsoid at which the corrections
+ * are computed.
+ */
+ private double mAltitudeMeters;
+
+ /** Time Of Applicability, GPS time of week */
+ private long mToaGpsNanosecondsOfWeek;
+
+ /**
+ * A set of {@link GnssSingleSatCorrection} each containing measurement corrections for a
+ * satellite in view
+ */
+ private @Nullable List<GnssSingleSatCorrection> mSingleSatCorrectionList;
+
+ private GnssMeasurementCorrections(Builder builder) {
+ mLatitudeDegrees = builder.mLatitudeDegrees;
+ mLongitudeDegrees = builder.mLongitudeDegrees;
+ mAltitudeMeters = builder.mAltitudeMeters;
+ mToaGpsNanosecondsOfWeek = builder.mToaGpsNanosecondsOfWeek;
+ mSingleSatCorrectionList =
+ builder.mSingleSatCorrectionList == null
+ ? null
+ : Collections.unmodifiableList(
+ new ArrayList<>(builder.mSingleSatCorrectionList));
+ }
+
+ /** Gets the latitude in degrees at which the corrections are computed. */
+ public double getLatitudeDegrees() {
+ return mLatitudeDegrees;
+ }
+
+ /** Gets the longitude in degrees at which the corrections are computed. */
+ public double getLongitudeDegrees() {
+ return mLongitudeDegrees;
+ }
+
+ /**
+ * Gets the altitude in meters above the WGS 84 reference ellipsoid at which the corrections are
+ * computed.
+ */
+ public double getAltitudeMeters() {
+ return mAltitudeMeters;
+ }
+
+ /** Gets the time of applicability, GPS time of week in nanoseconds. */
+ public long getToaGpsNanosecondsOfWeek() {
+ return mToaGpsNanosecondsOfWeek;
+ }
+
+ /**
+ * Gets a set of {@link GnssSingleSatCorrection} each containing measurement corrections for a
+ * satellite in view
+ */
+ public @Nullable List<GnssSingleSatCorrection> getSingleSatCorrectionList() {
+ return mSingleSatCorrectionList;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Creator<GnssMeasurementCorrections> CREATOR =
+ new Creator<GnssMeasurementCorrections>() {
+ @Override
+ public GnssMeasurementCorrections createFromParcel(Parcel parcel) {
+ GnssMeasurementCorrections.Builder gnssMeasurementCorrectons =
+ new Builder()
+ .setLatitudeDegrees(parcel.readDouble())
+ .setLongitudeDegrees(parcel.readDouble())
+ .setAltitudeMeters(parcel.readDouble())
+ .setToaGpsNanosecondsOfWeek(parcel.readLong());
+ List<GnssSingleSatCorrection> singleSatCorrectionList = new ArrayList<>();
+ parcel.readTypedList(singleSatCorrectionList, GnssSingleSatCorrection.CREATOR);
+ gnssMeasurementCorrectons.setSingleSatCorrectionList(
+ singleSatCorrectionList.isEmpty() ? null : singleSatCorrectionList);
+ return gnssMeasurementCorrectons.build();
+ }
+
+ @Override
+ public GnssMeasurementCorrections[] newArray(int i) {
+ return new GnssMeasurementCorrections[i];
+ }
+ };
+
+ @Override
+ public String toString() {
+ final String format = " %-29s = %s\n";
+ StringBuilder builder = new StringBuilder("GnssMeasurementCorrections:\n");
+ builder.append(String.format(format, "LatitudeDegrees = ", mLatitudeDegrees));
+ builder.append(String.format(format, "LongitudeDegrees = ", mLongitudeDegrees));
+ builder.append(String.format(format, "AltitudeMeters = ", mAltitudeMeters));
+ builder.append(
+ String.format(format, "ToaGpsNanosecondsOfWeek = ", mToaGpsNanosecondsOfWeek));
+ builder.append(
+ String.format(format, "mSingleSatCorrectionList = ", mSingleSatCorrectionList));
+ return builder.toString();
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeDouble(mLatitudeDegrees);
+ parcel.writeDouble(mLongitudeDegrees);
+ parcel.writeDouble(mAltitudeMeters);
+ parcel.writeLong(mToaGpsNanosecondsOfWeek);
+ parcel.writeTypedList(mSingleSatCorrectionList);
+ }
+
+ /** Builder for {@link GnssMeasurementCorrections} */
+ public static class Builder {
+ /**
+ * For documentation of below fields, see corresponding fields in {@link
+ * GnssMeasurementCorrections}.
+ */
+ private double mLatitudeDegrees;
+
+ private double mLongitudeDegrees;
+ private double mAltitudeMeters;
+ private long mToaGpsNanosecondsOfWeek;
+ private List<GnssSingleSatCorrection> mSingleSatCorrectionList;
+
+ /** Sets the latitude in degrees at which the corrections are computed. */
+ public Builder setLatitudeDegrees(double latitudeDegrees) {
+ mLatitudeDegrees = latitudeDegrees;
+ return this;
+ }
+
+ /** Sets the longitude in degrees at which the corrections are computed. */
+ public Builder setLongitudeDegrees(double longitudeDegrees) {
+ mLongitudeDegrees = longitudeDegrees;
+ return this;
+ }
+
+ /**
+ * Sets the altitude in meters above the WGS 84 reference ellipsoid at which the corrections
+ * are computed.
+ */
+ public Builder setAltitudeMeters(double altitudeMeters) {
+ mAltitudeMeters = altitudeMeters;
+ return this;
+ }
+
+ /** Sets the time of applicability, GPS time of week in nanoseconds. */
+ public Builder setToaGpsNanosecondsOfWeek(long toaGpsNanosecondsOfWeek) {
+ mToaGpsNanosecondsOfWeek = toaGpsNanosecondsOfWeek;
+ return this;
+ }
+
+ /**
+ * Sets a the list of {@link GnssSingleSatCorrection} containing measurement corrections for
+ * a satellite in view
+ */
+ public Builder setSingleSatCorrectionList(
+ @Nullable List<GnssSingleSatCorrection> singleSatCorrectionList) {
+ if (singleSatCorrectionList == null) {
+ mSingleSatCorrectionList = null;
+ } else {
+ mSingleSatCorrectionList =
+ Collections.unmodifiableList(new ArrayList<>(singleSatCorrectionList));
+ }
+ return this;
+ }
+
+ /** Builds a {@link GnssMeasurementCorrections} instance as specified by this builder. */
+ public GnssMeasurementCorrections build() {
+ return new GnssMeasurementCorrections(this);
+ }
+ }
+}
diff --git a/location/java/android/location/GnssReflectingPlane.java b/location/java/android/location/GnssReflectingPlane.java
new file mode 100644
index 000000000000..64b37524e37f
--- /dev/null
+++ b/location/java/android/location/GnssReflectingPlane.java
@@ -0,0 +1,159 @@
+/*
+ * 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.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Holds the characteristics of the reflecting plane that a satellite signal has bounced from.
+ *
+ * @hide
+ */
+@SystemApi
+public final class GnssReflectingPlane implements Parcelable {
+
+ /** Represents latitude in degrees of the reflecting plane */
+ private double mLatitudeDegrees;
+ /** Represents longitude in degrees of the reflecting plane. */
+ private double mLongitudeDegrees;
+ /**
+ * Represents altitude in meters above the WGS 84 reference ellipsoid of the reflection point in
+ * the plane
+ */
+ private double mAltitudeMeters;
+
+ /** Represents azimuth clockwise from north of the reflecting plane in degrees. */
+ private double mAzimuthDegrees;
+
+ private GnssReflectingPlane(Builder builder) {
+ mLatitudeDegrees = builder.mLatitudeDegrees;
+ mLongitudeDegrees = builder.mLongitudeDegrees;
+ mAltitudeMeters = builder.mAltitudeMeters;
+ mAzimuthDegrees = builder.mAzimuthDegrees;
+ }
+
+ /** Gets the latitude in degrees of the reflecting plane. */
+ public double getLatitudeDegrees() {
+ return mLatitudeDegrees;
+ }
+
+ /** Gets the longitude in degrees of the reflecting plane. */
+ public double getLongitudeDegrees() {
+ return mLongitudeDegrees;
+ }
+
+ /**
+ * Gets the altitude in meters above the WGS 84 reference ellipsoid of the reflecting point
+ * within the plane
+ */
+ public double getAltitudeMeters() {
+ return mAltitudeMeters;
+ }
+
+ /** Gets the azimuth clockwise from north of the reflecting plane in degrees. */
+ public double getAzimuthDegrees() {
+ return mAzimuthDegrees;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Creator<GnssReflectingPlane> CREATOR =
+ new Creator<GnssReflectingPlane>() {
+ @Override
+ public GnssReflectingPlane createFromParcel(Parcel parcel) {
+ GnssReflectingPlane reflectingPlane =
+ new Builder()
+ .setLatitudeDegrees(parcel.readDouble())
+ .setLongitudeDegrees(parcel.readDouble())
+ .setAltitudeMeters(parcel.readDouble())
+ .setAzimuthDegrees(parcel.readDouble())
+ .build();
+ return reflectingPlane;
+ }
+
+ @Override
+ public GnssReflectingPlane[] newArray(int i) {
+ return new GnssReflectingPlane[i];
+ }
+ };
+
+ @Override
+ public String toString() {
+ final String format = " %-29s = %s\n";
+ StringBuilder builder = new StringBuilder("ReflectingPlane:\n");
+ builder.append(String.format(format, "LatitudeDegrees = ", mLatitudeDegrees));
+ builder.append(String.format(format, "LongitudeDegrees = ", mLongitudeDegrees));
+ builder.append(String.format(format, "AltitudeMeters = ", mAltitudeMeters));
+ builder.append(String.format(format, "AzimuthDegrees = ", mAzimuthDegrees));
+ return builder.toString();
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeDouble(mLatitudeDegrees);
+ parcel.writeDouble(mLongitudeDegrees);
+ parcel.writeDouble(mAltitudeMeters);
+ parcel.writeDouble(mAzimuthDegrees);
+ }
+
+ /** Builder for {@link GnssReflectingPlane} */
+ public static class Builder {
+ /** For documentation, see corresponding fields in {@link GnssReflectingPlane}. */
+ private double mLatitudeDegrees;
+
+ private double mLongitudeDegrees;
+ private double mAltitudeMeters;
+ private double mAzimuthDegrees;
+
+ /** Sets the latitude in degrees of the reflecting plane. */
+ public Builder setLatitudeDegrees(double latitudeDegrees) {
+ mLatitudeDegrees = latitudeDegrees;
+ return this;
+ }
+
+ /** Sets the longitude in degrees of the reflecting plane. */
+ public Builder setLongitudeDegrees(double longitudeDegrees) {
+ mLongitudeDegrees = longitudeDegrees;
+ return this;
+ }
+
+ /**
+ * Sets the altitude in meters above the WGS 84 reference ellipsoid of the reflecting point
+ * within the plane
+ */
+ public Builder setAltitudeMeters(double altitudeMeters) {
+ mAltitudeMeters = altitudeMeters;
+ return this;
+ }
+
+ /** Sets the azimuth clockwise from north of the reflecting plane in degrees. */
+ public Builder setAzimuthDegrees(double azimuthDegrees) {
+ mAzimuthDegrees = azimuthDegrees;
+ return this;
+ }
+
+ /** Builds a {@link GnssReflectingPlane} object as specified by this builder. */
+ public GnssReflectingPlane build() {
+ return new GnssReflectingPlane(this);
+ }
+ }
+}
diff --git a/location/java/android/location/GnssSingleSatCorrection.java b/location/java/android/location/GnssSingleSatCorrection.java
new file mode 100644
index 000000000000..6c757f949f19
--- /dev/null
+++ b/location/java/android/location/GnssSingleSatCorrection.java
@@ -0,0 +1,346 @@
+/*
+ * 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.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * A container with measurement corrections for a single visible satellite
+ *
+ * @hide
+ */
+@SystemApi
+public final class GnssSingleSatCorrection implements Parcelable {
+
+ /**
+ * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link
+ * #mSatIsLos}.
+ */
+ public static final int HAS_SAT_IS_LOS_MASK = 1 << 0;
+
+ /**
+ * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link
+ * #mExcessPathLengthMeters}.
+ */
+ public static final int HAS_EXCESS_PATH_LENGTH_MASK = 1 << 1;
+
+ /**
+ * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link
+ * #mExcessPathLengthUncertaintyMeters}.
+ */
+ public static final int HAS_EXCESS_PATH_LENGTH_UNC_MASK = 1 << 2;
+
+ /**
+ * Bit mask for {@link #mSingleSatCorrectionFlags} indicating the presence of {@link
+ * #mReflectingPlane}.
+ */
+ public static final int HAS_REFLECTING_PLANE_MASK = 1 << 3;
+
+ /** A bitmask of fields present in this object (see HAS_* constants defined above) */
+ private int mSingleSatCorrectionFlags;
+
+ /** Defines the constellation of the given satellite as defined in {@link GnssStatus}. */
+ private int mConstellationType;
+
+ /**
+ * Satellite vehicle ID number
+ *
+ * <p>Interpretation depends on {@link GnssStatus#getSvid(int)}.
+ */
+ private int mSatId;
+
+ /**
+ * Carrier frequency of the signal to be corrected, for example it can be the GPS center
+ * frequency for L1 = 1,575,420,000 Hz, varying GLO channels, etc.
+ *
+ * <p>For an L1, L5 receiver tracking a satellite on L1 and L5 at the same time, two correction
+ * objects will be reported for this same satellite, in one of the correction objects, all the
+ * values related to L1 will be filled, and in the other all of the values related to L5 will be
+ * filled.
+ */
+ private float mCarrierFrequencyHz;
+
+ /**
+ * True if the satellite is estimated to be in Line-of-Sight condition at the given location.
+ */
+ private boolean mSatIsLos;
+
+ /**
+ * Excess path length to be subtracted from pseudorange before using it in calculating location.
+ */
+ private float mExcessPathLengthMeters;
+
+ /** Error estimate (1-sigma) for the Excess path length estimate */
+ private float mExcessPathLengthUncertaintyMeters;
+
+ /**
+ * Defines the reflecting plane location and azimuth information
+ *
+ * <p>The flag HAS_REFLECTING_PLANE will be used to set this value to invalid if the satellite
+ * signal goes through multiple reflections or if reflection plane serving is not supported.
+ */
+ private @Nullable GnssReflectingPlane mReflectingPlane;
+
+ private GnssSingleSatCorrection(Builder builder) {
+ mSingleSatCorrectionFlags = builder.mSingleSatCorrectionFlags;
+ mSatId = builder.mSatId;
+ mConstellationType = builder.mConstellationType;
+ mCarrierFrequencyHz = builder.mCarrierFrequencyHz;
+ mSatIsLos = builder.mSatIsLos;
+ mExcessPathLengthMeters = builder.mExcessPathLengthMeters;
+ mExcessPathLengthUncertaintyMeters = builder.mExcessPathLengthUncertaintyMeters;
+ mReflectingPlane = builder.mReflectingPlane;
+ }
+
+ /** Gets a bitmask of fields present in this object */
+ public int getSingleSatCorrectionFlags() {
+ return mSingleSatCorrectionFlags;
+ }
+
+ /**
+ * Gets the constellation type.
+ *
+ * <p>The return value is one of those constants with {@code CONSTELLATION_} prefix in {@link
+ * GnssStatus}.
+ */
+ @GnssStatus.ConstellationType
+ public int getConstellationType() {
+ return mConstellationType;
+ }
+
+ /**
+ * Gets the satellite ID.
+ *
+ * <p>Interpretation depends on {@link #getConstellationType()}. See {@link
+ * GnssStatus#getSvid(int)}.
+ */
+ public int getSatId() {
+ return mSatId;
+ }
+
+ /**
+ * Gets the carrier frequency of the tracked signal.
+ *
+ * <p>For example it can be the GPS central frequency for L1 = 1575.45 MHz, or L2 = 1227.60 MHz,
+ * L5 = 1176.45 MHz, varying GLO channels, etc.
+ *
+ * <p>For an L1, L5 receiver tracking a satellite on L1 and L5 at the same time, two correction
+ * objects will be reported for this same satellite, in one of the correction objects, all the
+ * values related to L1 will be filled, and in the other all of the values related to L5 will be
+ * filled.
+ *
+ * @return the carrier frequency of the signal tracked in Hz.
+ */
+ public float getCarrierFrequencyHz() {
+ return mCarrierFrequencyHz;
+ }
+
+ /** True if the satellite is line-of-sight */
+ public boolean isSatelliteLineOfSight() {
+ return mSatIsLos;
+ }
+
+ /**
+ * Returns the Excess path length to be subtracted from pseudorange before using it in
+ * calculating location.
+ */
+ public float getExcessPathLengthMeters() {
+ return mExcessPathLengthMeters;
+ }
+
+ /** Returns the error estimate (1-sigma) for the Excess path length estimate */
+ public float getExcessPathLengthUncertaintyMeters() {
+ return mExcessPathLengthUncertaintyMeters;
+ }
+
+ /**
+ * Returns the reflecting plane characteristics at which the signal has bounced
+ *
+ * <p>The flag HAS_REFLECTING_PLANE will be used to set this value to invalid if the satellite
+ * signal goes through multiple reflections or if reflection plane serving is not supported
+ */
+ public @Nullable GnssReflectingPlane getReflectingPlane() {
+ return mReflectingPlane;
+ }
+
+ /** Returns {@code true} if {@link #isSatelliteLineOfSight()} is valid. */
+ public boolean hasSatelliteLineOfSight() {
+ return (mSingleSatCorrectionFlags & HAS_SAT_IS_LOS_MASK) != 0;
+ }
+
+ /** Returns {@code true} if {@link #getExcessPathLengthMeters()} is valid. */
+ public boolean hasExcessPathLength() {
+ return (mSingleSatCorrectionFlags & HAS_EXCESS_PATH_LENGTH_MASK) != 0;
+ }
+
+ /** Returns {@code true} if {@link #getExcessPathLengthUncertaintyMeters()} is valid. */
+ public boolean hasExcessPathLengthUncertainty() {
+ return (mSingleSatCorrectionFlags & HAS_EXCESS_PATH_LENGTH_UNC_MASK) != 0;
+ }
+
+ /** Returns {@code true} if {@link #getReflectingPlane()} is valid. */
+ public boolean hasReflectingPlane() {
+ return (mSingleSatCorrectionFlags & HAS_REFLECTING_PLANE_MASK) != 0;
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ public static final Creator<GnssSingleSatCorrection> CREATOR =
+ new Creator<GnssSingleSatCorrection>() {
+ @Override
+ public GnssSingleSatCorrection createFromParcel(Parcel parcel) {
+ GnssSingleSatCorrection singleSatCorrection =
+ new Builder()
+ .setSingleSatCorrectionFlags(parcel.readInt())
+ .setConstellationType(parcel.readInt())
+ .setSatId(parcel.readInt())
+ .setCarrierFrequencyHz(parcel.readFloat())
+ .setSatIsLos(parcel.readBoolean())
+ .setExcessPathLengthMeters(parcel.readFloat())
+ .setExcessPathLengthUncertaintyMeters(parcel.readFloat())
+ .setReflectingPlane(
+ GnssReflectingPlane.CREATOR.createFromParcel(parcel))
+ .build();
+ return singleSatCorrection;
+ }
+
+ @Override
+ public GnssSingleSatCorrection[] newArray(int i) {
+ return new GnssSingleSatCorrection[i];
+ }
+ };
+
+ @Override
+ public String toString() {
+ final String format = " %-29s = %s\n";
+ StringBuilder builder = new StringBuilder("GnssSingleSatCorrection:\n");
+ builder.append(
+ String.format(format, "SingleSatCorrectionFlags = ", mSingleSatCorrectionFlags));
+ builder.append(String.format(format, "ConstellationType = ", mConstellationType));
+ builder.append(String.format(format, "SatId = ", mSatId));
+ builder.append(String.format(format, "CarrierFrequencyHz = ", mCarrierFrequencyHz));
+ builder.append(String.format(format, "SatIsLos = ", mSatIsLos));
+ builder.append(String.format(format, "ExcessPathLengthMeters = ", mExcessPathLengthMeters));
+ builder.append(
+ String.format(
+ format,
+ "ExcessPathLengthUncertaintyMeters = ",
+ mExcessPathLengthUncertaintyMeters));
+ builder.append(String.format(format, "ReflectingPlane = ", mReflectingPlane));
+ return builder.toString();
+ }
+
+ @Override
+ public void writeToParcel(Parcel parcel, int flags) {
+ parcel.writeInt(mSingleSatCorrectionFlags);
+ parcel.writeInt(mConstellationType);
+ parcel.writeInt(mSatId);
+ parcel.writeFloat(mCarrierFrequencyHz);
+ parcel.writeBoolean(mSatIsLos);
+ parcel.writeFloat(mExcessPathLengthMeters);
+ parcel.writeFloat(mExcessPathLengthUncertaintyMeters);
+ mReflectingPlane.writeToParcel(parcel, flags);
+ }
+
+ /** Builder for {@link GnssSingleSatCorrection} */
+ public static class Builder {
+
+ /**
+ * For documentation of below fields, see corresponding fields in {@link
+ * GnssSingleSatCorrection}.
+ */
+ private int mSingleSatCorrectionFlags;
+
+ private int mConstellationType;
+ private int mSatId;
+ private float mCarrierFrequencyHz;
+ private boolean mSatIsLos;
+ private float mExcessPathLengthMeters;
+ private float mExcessPathLengthUncertaintyMeters;
+ private GnssReflectingPlane mReflectingPlane;
+
+ /** Sets a bitmask of fields present in this object */
+ public Builder setSingleSatCorrectionFlags(int singleSatCorrectionFlags) {
+ mSingleSatCorrectionFlags = singleSatCorrectionFlags;
+ return this;
+ }
+
+ /** Sets the constellation type. */
+ public Builder setConstellationType(int constellationType) {
+ mConstellationType = constellationType;
+ return this;
+ }
+
+ /** Sets the Satellite ID. */
+ public Builder setSatId(int satId) {
+ mSatId = satId;
+ return this;
+ }
+
+ /** Sets the Carrier frequency in Hz. */
+ public Builder setCarrierFrequencyHz(float carrierFrequencyHz) {
+ mCarrierFrequencyHz = carrierFrequencyHz;
+ return this;
+ }
+
+ /** Sets the line=of-sight state of the satellite */
+ public Builder setSatIsLos(boolean satIsLos) {
+ mSatIsLos = satIsLos;
+ mSingleSatCorrectionFlags = (byte) (mSingleSatCorrectionFlags | HAS_SAT_IS_LOS_MASK);
+ return this;
+ }
+
+ /**
+ * Sets the Excess path length to be subtracted from pseudorange before using it in
+ * calculating location.
+ */
+ public Builder setExcessPathLengthMeters(float excessPathLengthMeters) {
+ mExcessPathLengthMeters = excessPathLengthMeters;
+ mSingleSatCorrectionFlags =
+ (byte) (mSingleSatCorrectionFlags | HAS_EXCESS_PATH_LENGTH_MASK);
+ return this;
+ }
+
+ /** Sets the error estimate (1-sigma) for the Excess path length estimate */
+ public Builder setExcessPathLengthUncertaintyMeters(
+ float excessPathLengthUncertaintyMeters) {
+ mExcessPathLengthUncertaintyMeters = excessPathLengthUncertaintyMeters;
+ mSingleSatCorrectionFlags =
+ (byte) (mSingleSatCorrectionFlags | HAS_EXCESS_PATH_LENGTH_UNC_MASK);
+ return this;
+ }
+
+ /** Sets the reflecting plane information */
+ public Builder setReflectingPlane(GnssReflectingPlane reflectingPlane) {
+ mReflectingPlane = reflectingPlane;
+ mSingleSatCorrectionFlags =
+ (byte) (mSingleSatCorrectionFlags | HAS_REFLECTING_PLANE_MASK);
+ return this;
+ }
+
+ /** Builds a {@link GnssSingleSatCorrection} instance as specified by this builder. */
+ public GnssSingleSatCorrection build() {
+ return new GnssSingleSatCorrection(this);
+ }
+ }
+}
diff --git a/location/java/android/location/ILocationManager.aidl b/location/java/android/location/ILocationManager.aidl
index 05d49e592747..bdc84da57799 100644
--- a/location/java/android/location/ILocationManager.aidl
+++ b/location/java/android/location/ILocationManager.aidl
@@ -21,6 +21,7 @@ import android.location.Address;
import android.location.Criteria;
import android.location.GeocoderParams;
import android.location.Geofence;
+import android.location.GnssMeasurementCorrections;
import android.location.IBatchedLocationCallback;
import android.location.IGnssMeasurementsListener;
import android.location.IGnssStatusListener;
@@ -63,6 +64,9 @@ interface ILocationManager
boolean sendNiResponse(int notifId, int userResponse);
boolean addGnssMeasurementsListener(in IGnssMeasurementsListener listener, in String packageName);
+ void injectGnssMeasurementCorrections(in GnssMeasurementCorrections corrections,
+ in String packageName);
+ int getGnssCapabilities(in String packageName);
void removeGnssMeasurementsListener(in IGnssMeasurementsListener listener);
boolean addGnssNavigationMessageListener(
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 1cd3d86a0c27..040e4f9f1bd0 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -22,6 +22,7 @@ import static android.Manifest.permission.LOCATION_HARDWARE;
import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
import android.Manifest;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresFeature;
import android.annotation.RequiresPermission;
@@ -2079,17 +2080,54 @@ public class LocationManager {
}
/**
- * No-op method to keep backward-compatibility.
- * Don't use it. Use {@link #unregisterGnssMeasurementsCallback} instead.
+ * Injects GNSS measurement corrections into the GNSS chipset.
+ *
+ * @param measurementCorrections a {@link GnssMeasurementCorrections} object with the GNSS
+ * measurement corrections to be injected into the GNSS chipset.
+ * @hide
+ */
+ @SystemApi
+ @RequiresPermission(ACCESS_FINE_LOCATION)
+ public void injectGnssMeasurementCorrections(
+ @NonNull GnssMeasurementCorrections measurementCorrections) {
+ try {
+ mGnssMeasurementCallbackTransport.injectGnssMeasurementCorrections(
+ measurementCorrections);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns an integer with flags representing the capabilities of the GNSS chipset.
+ *
+ * @hide
+ */
+ @SystemApi
+ /**
+ * Returns the integer capability flags of the GNSS chipset as defined in {@code
+ * IGnssCallback.hal}
+ */
+ public int getGnssCapabilities() {
+ try {
+ return mGnssMeasurementCallbackTransport.getGnssCapabilities();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * No-op method to keep backward-compatibility. Don't use it. Use {@link
+ * #unregisterGnssMeasurementsCallback} instead.
+ *
* @hide
* @deprecated use {@link #unregisterGnssMeasurementsCallback(GnssMeasurementsEvent.Callback)}
- * instead.
+ * instead.
*/
@Deprecated
@SystemApi
@SuppressLint("Doclava125")
- public void removeGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) {
- }
+ public void removeGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) {}
/**
* Unregisters a GPS Measurement callback.
diff --git a/location/tests/locationtests/src/android/location/GnssMeasurementCorrectionsTest.java b/location/tests/locationtests/src/android/location/GnssMeasurementCorrectionsTest.java
new file mode 100644
index 000000000000..c18d58f9a704
--- /dev/null
+++ b/location/tests/locationtests/src/android/location/GnssMeasurementCorrectionsTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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(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(false, singleSatCorrection.isSatelliteLineOfSight());
+ 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)
+ .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)
+ .setSatIsLos(false)
+ .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
new file mode 100644
index 000000000000..d7a3378e5a12
--- /dev/null
+++ b/location/tests/locationtests/src/android/location/GnssReflectingPlaneTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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
new file mode 100644
index 000000000000..2e54ae463595
--- /dev/null
+++ b/location/tests/locationtests/src/android/location/GnssSingleSatCorrectionsTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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(true, singleSatCorrection.isSatelliteLineOfSight());
+ 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())
+ .setSatIsLos(singleSatCorr.isSatelliteLineOfSight())
+ .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)
+ .setSatIsLos(true)
+ .setExcessPathLengthMeters(10.0f)
+ .setExcessPathLengthUncertaintyMeters(5.0f)
+ .setReflectingPlane(GnssReflectingPlaneTest.generateTestReflectingPlane());
+ return singleSatCorrection.build();
+ }
+}
diff --git a/media/java/android/media/AudioRecord.java b/media/java/android/media/AudioRecord.java
index 4b2353c992f2..33f81f1db69c 100644
--- a/media/java/android/media/AudioRecord.java
+++ b/media/java/android/media/AudioRecord.java
@@ -16,8 +16,10 @@
package android.media;
+import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.app.ActivityThread;
@@ -43,6 +45,7 @@ import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.concurrent.Executor;
/**
* The AudioRecord class manages the audio resources for Java applications
@@ -58,7 +61,7 @@ import java.util.List;
* been read yet. Data should be read from the audio hardware in chunks of sizes inferior to
* the total recording buffer size.
*/
-public class AudioRecord implements AudioRouting
+public class AudioRecord implements AudioRouting, AudioRecordingMonitor, AudioRecordingMonitorClient
{
//---------------------------------------------------------
// Constants
@@ -1654,6 +1657,56 @@ public class AudioRecord implements AudioRouting
return activeMicrophones;
}
+
+ //--------------------------------------------------------------------------
+ // Implementation of AudioRecordingMonitor interface
+ //--------------------
+
+ AudioRecordingMonitorImpl mRecordingInfoImpl =
+ new AudioRecordingMonitorImpl((AudioRecordingMonitorClient) this);
+
+ /**
+ * Register a callback to be notified of audio capture changes via a
+ * {@link AudioManager.AudioRecordingCallback}. A callback is received when the capture path
+ * configuration changes (pre-processing, format, sampling rate...) or capture is
+ * silenced/unsilenced by the system.
+ * @param executor {@link Executor} to handle the callbacks.
+ * @param cb non-null callback to register
+ */
+ public void registerAudioRecordingCallback(@NonNull @CallbackExecutor Executor executor,
+ @NonNull AudioManager.AudioRecordingCallback cb) {
+ mRecordingInfoImpl.registerAudioRecordingCallback(executor, cb);
+ }
+
+ /**
+ * Unregister an audio recording callback previously registered with
+ * {@link #registerAudioRecordingCallback(Executor, AudioManager.AudioRecordingCallback)}.
+ * @param cb non-null callback to unregister
+ */
+ public void unregisterAudioRecordingCallback(@NonNull AudioManager.AudioRecordingCallback cb) {
+ mRecordingInfoImpl.unregisterAudioRecordingCallback(cb);
+ }
+
+ /**
+ * Returns the current active audio recording for this audio recorder.
+ * @return a valid {@link AudioRecordingConfiguration} if this recorder is active
+ * or null otherwise.
+ * @see AudioRecordingConfiguration
+ */
+ public @Nullable AudioRecordingConfiguration getActiveRecordingConfiguration() {
+ return mRecordingInfoImpl.getActiveRecordingConfiguration();
+ }
+
+ //---------------------------------------------------------
+ // Implementation of AudioRecordingMonitorClient interface
+ //--------------------
+ /**
+ * @hide
+ */
+ public int getPortId() {
+ return native_getPortId();
+ }
+
//---------------------------------------------------------
// Interface definitions
//--------------------
diff --git a/media/java/android/media/AudioRecordingMonitor.java b/media/java/android/media/AudioRecordingMonitor.java
new file mode 100644
index 000000000000..e2605d074c86
--- /dev/null
+++ b/media/java/android/media/AudioRecordingMonitor.java
@@ -0,0 +1,56 @@
+/*
+ * 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.media;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import java.util.concurrent.Executor;
+
+/**
+ * AudioRecordingMonitor defines an interface implemented by {@link AudioRecord} and
+ * {@link MediaRecorder} allowing applications to install a callback and be notified of changes
+ * in the capture path while recoding is active.
+ */
+public interface AudioRecordingMonitor {
+ /**
+ * Register a callback to be notified of audio capture changes via a
+ * {@link AudioManager.AudioRecordingCallback}. A callback is received when the capture path
+ * configuration changes (pre-processing, format, sampling rate...) or capture is
+ * silenced/unsilenced by the system.
+ * @param executor {@link Executor} to handle the callbacks.
+ * @param cb non-null callback to register
+ */
+ void registerAudioRecordingCallback(@NonNull @CallbackExecutor Executor executor,
+ @NonNull AudioManager.AudioRecordingCallback cb);
+
+ /**
+ * Unregister an audio recording callback previously registered with
+ * {@link #registerAudioRecordingCallback(Executor, AudioManager.AudioRecordingCallback)}.
+ * @param cb non-null callback to unregister
+ */
+ void unregisterAudioRecordingCallback(@NonNull AudioManager.AudioRecordingCallback cb);
+
+ /**
+ * Returns the current active audio recording for this audio recorder.
+ * @return a valid {@link AudioRecordingConfiguration} if this recorder is active
+ * or null otherwise.
+ * @see AudioRecordingConfiguration
+ */
+ @Nullable AudioRecordingConfiguration getActiveRecordingConfiguration();
+}
diff --git a/media/java/android/media/AudioRecordingMonitorClient.java b/media/java/android/media/AudioRecordingMonitorClient.java
new file mode 100644
index 000000000000..7578d9b9a5fd
--- /dev/null
+++ b/media/java/android/media/AudioRecordingMonitorClient.java
@@ -0,0 +1,28 @@
+/*
+ * 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.media;
+
+/**
+ * Interface implemented by classes using { @link AudioRecordingMonitor} interface.
+ * @hide
+ */
+public interface AudioRecordingMonitorClient {
+ /**
+ * @return the unique port ID allocated by audio framework to this recorder
+ */
+ int getPortId();
+}
diff --git a/media/java/android/media/AudioRecordingMonitorImpl.java b/media/java/android/media/AudioRecordingMonitorImpl.java
new file mode 100644
index 000000000000..c2cd4bc0b7eb
--- /dev/null
+++ b/media/java/android/media/AudioRecordingMonitorImpl.java
@@ -0,0 +1,250 @@
+/*
+ * 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.media;
+
+import android.annotation.CallbackExecutor;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Context;
+import android.os.Binder;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.Executor;
+
+/**
+ * Implementation of AudioRecordingMonitor interface.
+ * @hide
+ */
+public class AudioRecordingMonitorImpl implements AudioRecordingMonitor {
+
+ private static final String TAG = "android.media.AudioRecordingMonitor";
+
+ private static IAudioService sService; //lazy initialization, use getService()
+
+ private final AudioRecordingMonitorClient mClient;
+
+ AudioRecordingMonitorImpl(@NonNull AudioRecordingMonitorClient client) {
+ mClient = client;
+ }
+
+ /**
+ * Register a callback to be notified of audio capture changes via a
+ * {@link AudioManager.AudioRecordingCallback}. A callback is received when the capture path
+ * configuration changes (pre-processing, format, sampling rate...) or capture is
+ * silenced/unsilenced by the system.
+ * @param executor {@link Executor} to handle the callbacks.
+ * @param cb non-null callback to register
+ */
+ public void registerAudioRecordingCallback(@NonNull @CallbackExecutor Executor executor,
+ @NonNull AudioManager.AudioRecordingCallback cb) {
+ if (cb == null) {
+ throw new IllegalArgumentException("Illegal null AudioRecordingCallback");
+ }
+ if (executor == null) {
+ throw new IllegalArgumentException("Illegal null Executor");
+ }
+ synchronized (mRecordCallbackLock) {
+ // check if eventCallback already in list
+ for (AudioRecordingCallbackInfo arci : mRecordCallbackList) {
+ if (arci.mCb == cb) {
+ throw new IllegalArgumentException(
+ "AudioRecordingCallback already registered");
+ }
+ }
+ beginRecordingCallbackHandling();
+ mRecordCallbackList.add(new AudioRecordingCallbackInfo(executor, cb));
+ }
+ }
+
+ /**
+ * Unregister an audio recording callback previously registered with
+ * {@link #registerAudioRecordingCallback(Executor, AudioManager.AudioRecordingCallback)}.
+ * @param cb non-null callback to unregister
+ */
+ public void unregisterAudioRecordingCallback(@NonNull AudioManager.AudioRecordingCallback cb) {
+ if (cb == null) {
+ throw new IllegalArgumentException("Illegal null AudioRecordingCallback argument");
+ }
+
+ synchronized (mRecordCallbackLock) {
+ for (AudioRecordingCallbackInfo arci : mRecordCallbackList) {
+ if (arci.mCb == cb) {
+ // ok to remove while iterating over list as we exit iteration
+ mRecordCallbackList.remove(arci);
+ if (mRecordCallbackList.size() == 0) {
+ endRecordingCallbackHandling();
+ }
+ return;
+ }
+ }
+ throw new IllegalArgumentException("AudioRecordingCallback was not registered");
+ }
+ }
+
+ /**
+ * Returns the current active audio recording for this audio recorder.
+ * @return a valid {@link AudioRecordingConfiguration} if this recorder is active
+ * or null otherwise.
+ * @see AudioRecordingConfiguration
+ */
+ public @Nullable AudioRecordingConfiguration getActiveRecordingConfiguration() {
+ final IAudioService service = getService();
+ try {
+ List<AudioRecordingConfiguration> configs = service.getActiveRecordingConfigurations();
+ return getMyConfig(configs);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ private static class AudioRecordingCallbackInfo {
+ final AudioManager.AudioRecordingCallback mCb;
+ final Executor mExecutor;
+ AudioRecordingCallbackInfo(Executor e, AudioManager.AudioRecordingCallback cb) {
+ mExecutor = e;
+ mCb = cb;
+ }
+ }
+
+ private static final int MSG_RECORDING_CONFIG_CHANGE = 1;
+
+ private final Object mRecordCallbackLock = new Object();
+ @GuardedBy("mRecordCallbackLock")
+ @NonNull private LinkedList<AudioRecordingCallbackInfo> mRecordCallbackList =
+ new LinkedList<AudioRecordingCallbackInfo>();
+ @GuardedBy("mRecordCallbackLock")
+ private @Nullable HandlerThread mRecordingCallbackHandlerThread;
+ @GuardedBy("mRecordCallbackLock")
+ private @Nullable volatile Handler mRecordingCallbackHandler;
+
+ @GuardedBy("mRecordCallbackLock")
+ private final IRecordingConfigDispatcher mRecordingCallback =
+ new IRecordingConfigDispatcher.Stub() {
+ @Override
+ public void dispatchRecordingConfigChange(List<AudioRecordingConfiguration> configs) {
+ AudioRecordingConfiguration config = getMyConfig(configs);
+ if (config != null) {
+ synchronized (mRecordCallbackLock) {
+ if (mRecordingCallbackHandler != null) {
+ final Message m = mRecordingCallbackHandler.obtainMessage(
+ MSG_RECORDING_CONFIG_CHANGE/*what*/, config /*obj*/);
+ mRecordingCallbackHandler.sendMessage(m);
+ }
+ }
+ }
+ }
+ };
+
+ @GuardedBy("mRecordCallbackLock")
+ private void beginRecordingCallbackHandling() {
+ if (mRecordingCallbackHandlerThread == null) {
+ mRecordingCallbackHandlerThread = new HandlerThread(TAG + ".RecordingCallback");
+ mRecordingCallbackHandlerThread.start();
+ final Looper looper = mRecordingCallbackHandlerThread.getLooper();
+ if (looper != null) {
+ mRecordingCallbackHandler = new Handler(looper) {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_RECORDING_CONFIG_CHANGE: {
+ if (msg.obj == null) {
+ return;
+ }
+ ArrayList<AudioRecordingConfiguration> configs =
+ new ArrayList<AudioRecordingConfiguration>();
+ configs.add((AudioRecordingConfiguration) msg.obj);
+
+ final LinkedList<AudioRecordingCallbackInfo> cbInfoList;
+ synchronized (mRecordCallbackLock) {
+ if (mRecordCallbackList.size() == 0) {
+ return;
+ }
+ cbInfoList = new LinkedList<AudioRecordingCallbackInfo>(
+ mRecordCallbackList);
+ }
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ for (AudioRecordingCallbackInfo cbi : cbInfoList) {
+ cbi.mExecutor.execute(() ->
+ cbi.mCb.onRecordingConfigChanged(configs));
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ } break;
+ default:
+ Log.e(TAG, "Unknown event " + msg.what);
+ break;
+ }
+ }
+ };
+ final IAudioService service = getService();
+ try {
+ service.registerRecordingCallback(mRecordingCallback);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+ }
+ }
+
+ @GuardedBy("mRecordCallbackLock")
+ private void endRecordingCallbackHandling() {
+ if (mRecordingCallbackHandlerThread != null) {
+ final IAudioService service = getService();
+ try {
+ service.unregisterRecordingCallback(mRecordingCallback);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ mRecordingCallbackHandlerThread.quit();
+ mRecordingCallbackHandlerThread = null;
+ }
+ }
+
+ AudioRecordingConfiguration getMyConfig(List<AudioRecordingConfiguration> configs) {
+ int portId = mClient.getPortId();
+ for (AudioRecordingConfiguration config : configs) {
+ if (config.getClientPortId() == portId) {
+ return config;
+ }
+ }
+ return null;
+ }
+
+ private static IAudioService getService() {
+ if (sService != null) {
+ return sService;
+ }
+ IBinder b = ServiceManager.getService(Context.AUDIO_SERVICE);
+ sService = IAudioService.Stub.asInterface(b);
+ return sService;
+ }
+}
diff --git a/media/java/android/media/MediaPlayer2.java b/media/java/android/media/MediaPlayer2.java
index a3702d68cc49..34345b31ded1 100644
--- a/media/java/android/media/MediaPlayer2.java
+++ b/media/java/android/media/MediaPlayer2.java
@@ -793,7 +793,7 @@ public class MediaPlayer2 implements AutoCloseable
// throws IllegalArgumentException if dsd is null or underline PFD of dsd has been closed.
private void checkDataSourceDesc(DataSourceDesc dsd) {
- if (dsd != null) {
+ if (dsd == null) {
throw new IllegalArgumentException("dsd is expected to be non null");
}
if (dsd instanceof FileDataSourceDesc) {
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 8ced021b1025..1cdc29102758 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -16,7 +16,9 @@
package android.media;
+import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
@@ -40,6 +42,8 @@ import java.io.RandomAccessFile;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.Executor;
+
/**
* Used to record audio and video. The recording control is based on a
@@ -83,7 +87,9 @@ import java.util.List;
* <a href="{@docRoot}guide/topics/media/audio-capture.html">Audio Capture</a> developer guide.</p>
* </div>
*/
-public class MediaRecorder implements AudioRouting
+public class MediaRecorder implements AudioRouting,
+ AudioRecordingMonitor,
+ AudioRecordingMonitorClient
{
static {
System.loadLibrary("media_jni");
@@ -304,7 +310,7 @@ public class MediaRecorder implements AudioRouting
/**
* Audio source for preemptible, low-priority software hotword detection
- * It presents the same gain and pre processing tuning as {@link #VOICE_RECOGNITION}.
+ * It presents the same gain and pre-processing tuning as {@link #VOICE_RECOGNITION}.
* <p>
* An application should use this audio source when it wishes to do
* always-on software hotword detection, while gracefully giving in to any other application
@@ -1471,6 +1477,57 @@ public class MediaRecorder implements AudioRouting
private native final int native_getActiveMicrophones(
ArrayList<MicrophoneInfo> activeMicrophones);
+ //--------------------------------------------------------------------------
+ // Implementation of AudioRecordingMonitor interface
+ //--------------------
+
+ AudioRecordingMonitorImpl mRecordingInfoImpl =
+ new AudioRecordingMonitorImpl((AudioRecordingMonitorClient) this);
+
+ /**
+ * Register a callback to be notified of audio capture changes via a
+ * {@link AudioManager.AudioRecordingCallback}. A callback is received when the capture path
+ * configuration changes (pre-processing, format, sampling rate...) or capture is
+ * silenced/unsilenced by the system.
+ * @param executor {@link Executor} to handle the callbacks.
+ * @param cb non-null callback to register
+ */
+ public void registerAudioRecordingCallback(@NonNull @CallbackExecutor Executor executor,
+ @NonNull AudioManager.AudioRecordingCallback cb) {
+ mRecordingInfoImpl.registerAudioRecordingCallback(executor, cb);
+ }
+
+ /**
+ * Unregister an audio recording callback previously registered with
+ * {@link #registerAudioRecordingCallback(Executor, AudioManager.AudioRecordingCallback)}.
+ * @param cb non-null callback to unregister
+ */
+ public void unregisterAudioRecordingCallback(@NonNull AudioManager.AudioRecordingCallback cb) {
+ mRecordingInfoImpl.unregisterAudioRecordingCallback(cb);
+ }
+
+ /**
+ * Returns the current active audio recording for this audio recorder.
+ * @return a valid {@link AudioRecordingConfiguration} if this recorder is active
+ * or null otherwise.
+ * @see AudioRecordingConfiguration
+ */
+ public @Nullable AudioRecordingConfiguration getActiveRecordingConfiguration() {
+ return mRecordingInfoImpl.getActiveRecordingConfiguration();
+ }
+
+ //---------------------------------------------------------
+ // Implementation of AudioRecordingMonitorClient interface
+ //--------------------
+ /**
+ * @hide
+ */
+ public int getPortId() {
+ return native_getPortId();
+ }
+
+ private native int native_getPortId();
+
/**
* Called from native code when an interesting event happens. This method
* just uses the EventHandler system to post the event back to the main app thread.
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index b3a8b21147c1..ca30f32ea438 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -763,6 +763,20 @@ android_media_MediaRecord_getActiveMicrophones(JNIEnv *env,
}
return jStatus;
}
+
+static jint android_media_MediaRecord_getPortId(JNIEnv *env, jobject thiz) {
+ sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
+ if (mr == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ return (jint)AUDIO_PORT_HANDLE_NONE;
+ }
+
+ audio_port_handle_t portId;
+ process_media_recorder_call(env, mr->getPortId(&portId),
+ "java/lang/RuntimeException", "getPortId failed.");
+ return (jint)portId;
+}
+
// ----------------------------------------------------------------------------
static const JNINativeMethod gMethods[] = {
@@ -801,6 +815,7 @@ static const JNINativeMethod gMethods[] = {
{"native_enableDeviceCallback", "(Z)V", (void *)android_media_MediaRecorder_enableDeviceCallback},
{"native_getActiveMicrophones", "(Ljava/util/ArrayList;)I", (void *)android_media_MediaRecord_getActiveMicrophones},
+ {"native_getPortId", "()I", (void *)android_media_MediaRecord_getPortId},
};
// This function only registers the native methods, and is called from
diff --git a/packages/CarSystemUI/res/values/config.xml b/packages/CarSystemUI/res/values/config.xml
index c527711f563f..2e05c382a35e 100644
--- a/packages/CarSystemUI/res/values/config.xml
+++ b/packages/CarSystemUI/res/values/config.xml
@@ -32,7 +32,7 @@
SystemUi b/c it can't be overlayed at this level for now
-->
<string-array name="config_systemUIServiceComponents" translatable="false">
- <item>com.android.systemui.Dependency</item>
+ <item>com.android.systemui.Dependency$DependencyCreator</item>
<item>com.android.systemui.util.NotificationChannels</item>
<item>com.android.systemui.statusbar.CommandQueue$CommandQueueStart</item>
<item>com.android.systemui.keyguard.KeyguardViewMediator</item>
diff --git a/packages/CompanionDeviceManager/AndroidManifest.xml b/packages/CompanionDeviceManager/AndroidManifest.xml
index 0be71e6d17b9..42885e8193a7 100644
--- a/packages/CompanionDeviceManager/AndroidManifest.xml
+++ b/packages/CompanionDeviceManager/AndroidManifest.xml
@@ -25,7 +25,7 @@
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
diff --git a/packages/ExtServices/src/android/ext/services/notification/Assistant.java b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
index 133d8ba8357b..af52c00388f3 100644
--- a/packages/ExtServices/src/android/ext/services/notification/Assistant.java
+++ b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
@@ -117,7 +117,7 @@ public class Assistant extends NotificationAssistantService {
mPackageManager = ActivityThread.getPackageManager();
mSettings = mSettingsFactory.createAndRegister(mHandler,
getApplicationContext().getContentResolver(), getUserId(), this::updateThresholds);
- mSmartActionsHelper = new SmartActionsHelper();
+ mSmartActionsHelper = new SmartActionsHelper(getContext(), mSettings);
mNotificationCategorizer = new NotificationCategorizer();
mAgingHelper = new AgingHelper(getContext(),
mNotificationCategorizer,
@@ -215,10 +215,8 @@ public class Assistant extends NotificationAssistantService {
return null;
}
NotificationEntry entry = new NotificationEntry(mPackageManager, sbn, channel);
- ArrayList<Notification.Action> actions =
- mSmartActionsHelper.suggestActions(this, entry, mSettings);
- ArrayList<CharSequence> replies =
- mSmartActionsHelper.suggestReplies(this, entry, mSettings);
+ ArrayList<Notification.Action> actions = mSmartActionsHelper.suggestActions(entry);
+ ArrayList<CharSequence> replies = mSmartActionsHelper.suggestReplies(entry);
return createEnqueuedNotificationAdjustment(entry, actions, replies);
}
@@ -294,7 +292,7 @@ public class Assistant extends NotificationAssistantService {
synchronized (mkeyToImpressions) {
ChannelImpressions ci = mkeyToImpressions.getOrDefault(key,
createChannelImpressionsWithThresholds());
- if (stats.hasSeen()) {
+ if (stats != null && stats.hasSeen()) {
ci.incrementViews();
updatedImpressions = true;
}
@@ -343,6 +341,7 @@ public class Assistant extends NotificationAssistantService {
if (entry != null) {
entry.setSeen();
mAgingHelper.onNotificationSeen(entry);
+ mSmartActionsHelper.onNotificationSeen(entry);
}
}
} catch (Throwable e) {
@@ -351,34 +350,46 @@ public class Assistant extends NotificationAssistantService {
}
@Override
- public void onNotificationExpansionChanged(String key, boolean isUserAction,
+ public void onNotificationExpansionChanged(@NonNull String key, boolean isUserAction,
boolean isExpanded) {
if (DEBUG) {
- Log.i(TAG,
- "onNotificationExpansionChanged " + key + ", isUserAction =" + isUserAction
- + ", isExpanded = isExpanded");
+ Log.d(TAG, "onNotificationExpansionChanged() called with: key = [" + key
+ + "], isUserAction = [" + isUserAction + "], isExpanded = [" + isExpanded
+ + "]");
+ }
+ NotificationEntry entry = mLiveNotifications.get(key);
+
+ if (entry != null) {
+ entry.setExpanded(isExpanded);
+ mSmartActionsHelper.onNotificationExpansionChanged(entry, isUserAction, isExpanded);
}
}
@Override
- public void onNotificationDirectReply(String key) {
+ public void onNotificationDirectReply(@NonNull String key) {
if (DEBUG) Log.i(TAG, "onNotificationDirectReply " + key);
+ mSmartActionsHelper.onNotificationDirectReply(key);
}
@Override
- public void onSuggestedReplySent(String key, CharSequence reply, int source) {
+ public void onSuggestedReplySent(@NonNull String key, @NonNull CharSequence reply,
+ @Source int source) {
if (DEBUG) {
Log.d(TAG, "onSuggestedReplySent() called with: key = [" + key + "], reply = [" + reply
+ "], source = [" + source + "]");
}
+ mSmartActionsHelper.onSuggestedReplySent(key, reply, source);
}
@Override
- public void onActionClicked(String key, Notification.Action action, int source) {
+ public void onActionClicked(@NonNull String key, @NonNull Notification.Action action,
+ @Source int source) {
if (DEBUG) {
- Log.d(TAG, "onActionClicked() called with: key = [" + key + "], action = [" + action.title
- + "], source = [" + source + "]");
+ Log.d(TAG,
+ "onActionClicked() called with: key = [" + key + "], action = [" + action.title
+ + "], source = [" + source + "]");
}
+ mSmartActionsHelper.onActionClicked(key, action, source);
}
@Override
diff --git a/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java b/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java
index 6f437bd5d96f..71fd9ce6e4af 100644
--- a/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java
+++ b/packages/ExtServices/src/android/ext/services/notification/NotificationEntry.java
@@ -52,6 +52,8 @@ public class NotificationEntry {
private NotificationChannel mChannel;
private int mImportance;
private boolean mSeen;
+ private boolean mExpanded;
+ private boolean mIsShowActionEventLogged;
public NotificationEntry(IPackageManager packageManager, StatusBarNotification sbn,
NotificationChannel channel) {
@@ -216,10 +218,26 @@ public class NotificationEntry {
mSeen = true;
}
+ public void setExpanded(boolean expanded) {
+ mExpanded = expanded;
+ }
+
+ public void setShowActionEventLogged() {
+ mIsShowActionEventLogged = true;
+ }
+
public boolean hasSeen() {
return mSeen;
}
+ public boolean isExpanded() {
+ return mExpanded;
+ }
+
+ public boolean isShowActionEventLogged() {
+ return mIsShowActionEventLogged;
+ }
+
public StatusBarNotification getSbn() {
return mSbn;
}
diff --git a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
index 38df9b0a6fdc..b041842c45b9 100644
--- a/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
+++ b/packages/ExtServices/src/android/ext/services/notification/SmartActionsHelper.java
@@ -24,12 +24,16 @@ import android.content.Context;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.Process;
+import android.service.notification.NotificationAssistantService;
import android.text.TextUtils;
import android.util.ArrayMap;
+import android.util.LruCache;
import android.view.textclassifier.ConversationActions;
import android.view.textclassifier.TextClassification;
+import android.view.textclassifier.TextClassificationContext;
import android.view.textclassifier.TextClassificationManager;
import android.view.textclassifier.TextClassifier;
+import android.view.textclassifier.TextClassifierEvent;
import android.view.textclassifier.TextLinks;
import java.time.Instant;
@@ -47,6 +51,7 @@ public class SmartActionsHelper {
private static final ArrayList<Notification.Action> EMPTY_ACTION_LIST = new ArrayList<>();
private static final ArrayList<CharSequence> EMPTY_REPLY_LIST = new ArrayList<>();
+ private static final String KEY_ACTION_TYPE = "action_type";
// If a notification has any of these flags set, it's inelgibile for actions being added.
private static final int FLAG_MASK_INELGIBILE_FOR_ACTIONS =
Notification.FLAG_ONGOING_EVENT
@@ -59,6 +64,7 @@ public class SmartActionsHelper {
private static final int MAX_SUGGESTED_REPLIES = 3;
// TODO: Make this configurable.
private static final int MAX_MESSAGES_TO_EXTRACT = 5;
+ private static final int MAX_RESULT_ID_TO_CACHE = 20;
private static final ConversationActions.TypeConfig TYPE_CONFIG =
new ConversationActions.TypeConfig.Builder().setIncludedTypes(
@@ -68,26 +74,36 @@ public class SmartActionsHelper {
private static final List<String> HINTS =
Collections.singletonList(ConversationActions.HINT_FOR_NOTIFICATION);
- SmartActionsHelper() {
+ private Context mContext;
+ @Nullable
+ private TextClassifier mTextClassifier;
+ @NonNull
+ private AssistantSettings mSettings;
+ private LruCache<String, String> mNotificationKeyToResultIdCache =
+ new LruCache<>(MAX_RESULT_ID_TO_CACHE);
+
+ SmartActionsHelper(Context context, AssistantSettings settings) {
+ mContext = context;
+ TextClassificationManager textClassificationManager =
+ mContext.getSystemService(TextClassificationManager.class);
+ if (textClassificationManager != null) {
+ mTextClassifier = textClassificationManager.getTextClassifier();
+ }
+ mSettings = settings;
}
/**
* Adds action adjustments based on the notification contents.
*/
@NonNull
- ArrayList<Notification.Action> suggestActions(@Nullable Context context,
- @NonNull NotificationEntry entry, @NonNull AssistantSettings settings) {
- if (!settings.mGenerateActions) {
+ ArrayList<Notification.Action> suggestActions(@NonNull NotificationEntry entry) {
+ if (!mSettings.mGenerateActions) {
return EMPTY_ACTION_LIST;
}
if (!isEligibleForActionAdjustment(entry)) {
return EMPTY_ACTION_LIST;
}
- if (context == null) {
- return EMPTY_ACTION_LIST;
- }
- TextClassificationManager tcm = context.getSystemService(TextClassificationManager.class);
- if (tcm == null) {
+ if (mTextClassifier == null) {
return EMPTY_ACTION_LIST;
}
List<ConversationActions.Message> messages = extractMessages(entry.getNotification());
@@ -96,22 +112,17 @@ public class SmartActionsHelper {
}
// TODO: Move to TextClassifier.suggestConversationActions once it is ready.
return suggestActionsFromText(
- tcm, messages.get(messages.size() - 1).getText(), MAX_SMART_ACTIONS);
+ messages.get(messages.size() - 1).getText(), MAX_SMART_ACTIONS);
}
- ArrayList<CharSequence> suggestReplies(@Nullable Context context,
- @NonNull NotificationEntry entry, @NonNull AssistantSettings settings) {
- if (!settings.mGenerateReplies) {
+ ArrayList<CharSequence> suggestReplies(@NonNull NotificationEntry entry) {
+ if (!mSettings.mGenerateReplies) {
return EMPTY_REPLY_LIST;
}
if (!isEligibleForReplyAdjustment(entry)) {
return EMPTY_REPLY_LIST;
}
- if (context == null) {
- return EMPTY_REPLY_LIST;
- }
- TextClassificationManager tcm = context.getSystemService(TextClassificationManager.class);
- if (tcm == null) {
+ if (mTextClassifier == null) {
return EMPTY_REPLY_LIST;
}
List<ConversationActions.Message> messages = extractMessages(entry.getNotification());
@@ -125,14 +136,122 @@ public class SmartActionsHelper {
.setTypeConfig(TYPE_CONFIG)
.build();
- TextClassifier textClassifier = tcm.getTextClassifier();
+ ConversationActions conversationActionsResult =
+ mTextClassifier.suggestConversationActions(request);
List<ConversationActions.ConversationAction> conversationActions =
- textClassifier.suggestConversationActions(request).getConversationActions();
-
- return conversationActions.stream()
+ conversationActionsResult.getConversationActions();
+ ArrayList<CharSequence> replies = conversationActions.stream()
.map(conversationAction -> conversationAction.getTextReply())
.filter(textReply -> !TextUtils.isEmpty(textReply))
.collect(Collectors.toCollection(ArrayList::new));
+
+ String resultId = conversationActionsResult.getId();
+ if (resultId != null && !replies.isEmpty()) {
+ mNotificationKeyToResultIdCache.put(entry.getSbn().getKey(), resultId);
+ }
+ return replies;
+ }
+
+ void onNotificationSeen(@NonNull NotificationEntry entry) {
+ if (entry.isExpanded()) {
+ maybeSendActionShownEvent(entry);
+ }
+ }
+
+ void onNotificationExpansionChanged(@NonNull NotificationEntry entry, boolean isUserAction,
+ boolean isExpanded) {
+ // Notification can be expanded in the background, and thus the isUserAction check.
+ if (isUserAction && isExpanded) {
+ maybeSendActionShownEvent(entry);
+ }
+ }
+
+ void onNotificationDirectReply(@NonNull String key) {
+ if (mTextClassifier == null) {
+ return;
+ }
+ String resultId = mNotificationKeyToResultIdCache.get(key);
+ if (resultId == null) {
+ return;
+ }
+ TextClassifierEvent textClassifierEvent =
+ createTextClassifierEventBuilder(TextClassifierEvent.TYPE_MANUAL_REPLY, resultId)
+ .build();
+ mTextClassifier.onTextClassifierEvent(textClassifierEvent);
+ }
+
+ void onSuggestedReplySent(@NonNull String key, @NonNull CharSequence reply,
+ @NotificationAssistantService.Source int source) {
+ if (mTextClassifier == null) {
+ return;
+ }
+ if (source != NotificationAssistantService.SOURCE_FROM_ASSISTANT) {
+ return;
+ }
+ String resultId = mNotificationKeyToResultIdCache.get(key);
+ if (resultId == null) {
+ return;
+ }
+ TextClassifierEvent textClassifierEvent =
+ createTextClassifierEventBuilder(TextClassifierEvent.TYPE_SMART_ACTION, resultId)
+ .setEntityType(ConversationActions.TYPE_TEXT_REPLY)
+ .build();
+ mTextClassifier.onTextClassifierEvent(textClassifierEvent);
+ }
+
+ void onActionClicked(@NonNull String key, @NonNull Notification.Action action,
+ @NotificationAssistantService.Source int source) {
+ if (mTextClassifier == null) {
+ return;
+ }
+ if (source != NotificationAssistantService.SOURCE_FROM_ASSISTANT) {
+ return;
+ }
+ String resultId = mNotificationKeyToResultIdCache.get(key);
+ if (resultId == null) {
+ return;
+ }
+ String actionType = action.getExtras().getString(KEY_ACTION_TYPE);
+ if (actionType == null) {
+ return;
+ }
+ TextClassifierEvent textClassifierEvent =
+ createTextClassifierEventBuilder(TextClassifierEvent.TYPE_SMART_ACTION, resultId)
+ .setEntityType(actionType)
+ .build();
+ mTextClassifier.onTextClassifierEvent(textClassifierEvent);
+ }
+
+ private TextClassifierEvent.Builder createTextClassifierEventBuilder(
+ int eventType, @NonNull String resultId) {
+ return new TextClassifierEvent.Builder(
+ TextClassifierEvent.CATEGORY_CONVERSATION_ACTIONS, eventType)
+ .setEventTime(System.currentTimeMillis())
+ .setEventContext(
+ new TextClassificationContext.Builder(
+ mContext.getPackageName(), TextClassifier.WIDGET_TYPE_NOTIFICATION)
+ .build())
+ .setResultId(resultId);
+ }
+
+ private void maybeSendActionShownEvent(@NonNull NotificationEntry entry) {
+ if (mTextClassifier == null) {
+ return;
+ }
+ String resultId = mNotificationKeyToResultIdCache.get(entry.getSbn().getKey());
+ if (resultId == null) {
+ return;
+ }
+ // Only report if this is the first time the user sees these suggestions.
+ if (entry.isShowActionEventLogged()) {
+ return;
+ }
+ entry.setShowActionEventLogged();
+ TextClassifierEvent textClassifierEvent =
+ createTextClassifierEventBuilder(TextClassifierEvent.TYPE_ACTIONS_SHOWN, resultId)
+ .build();
+ // TODO: If possible, report which replies / actions are actually seen by user.
+ mTextClassifier.onTextClassifierEvent(textClassifierEvent);
}
/**
@@ -220,13 +339,10 @@ public class SmartActionsHelper {
/** Returns a list of actions to act on entities in a given piece of text. */
@NonNull
private ArrayList<Notification.Action> suggestActionsFromText(
- @NonNull TextClassificationManager tcm, @Nullable CharSequence text,
- int maxSmartActions) {
+ @Nullable CharSequence text, int maxSmartActions) {
if (TextUtils.isEmpty(text)) {
return EMPTY_ACTION_LIST;
}
- TextClassifier textClassifier = tcm.getTextClassifier();
-
// We want to process only text visible to the user to avoid confusing suggestions, so we
// truncate the text to a reasonable length. This is particularly important for e.g.
// email apps that sometimes include the text for the entire thread.
@@ -239,7 +355,7 @@ public class SmartActionsHelper {
Collections.singletonList(
TextClassifier.HINT_TEXT_IS_NOT_EDITABLE)))
.build();
- TextLinks links = textClassifier.generateLinks(textLinksRequest);
+ TextLinks links = mTextClassifier.generateLinks(textLinksRequest);
ArrayMap<String, Integer> entityTypeFrequency = getEntityTypeFrequency(links);
ArrayList<Notification.Action> actions = new ArrayList<>();
@@ -254,19 +370,26 @@ public class SmartActionsHelper {
// Generate the actions, and add the most prominent ones to the action bar.
TextClassification classification =
- textClassifier.classifyText(
+ mTextClassifier.classifyText(
new TextClassification.Request.Builder(
text, link.getStart(), link.getEnd()).build());
+ if (classification.getEntityCount() == 0) {
+ continue;
+ }
int numOfActions = Math.min(
MAX_ACTIONS_PER_LINK, classification.getActions().size());
for (int i = 0; i < numOfActions; ++i) {
- RemoteAction action = classification.getActions().get(i);
- actions.add(
- new Notification.Action.Builder(
- action.getIcon(),
- action.getTitle(),
- action.getActionIntent())
- .build());
+ RemoteAction remoteAction = classification.getActions().get(i);
+ Notification.Action action = new Notification.Action.Builder(
+ remoteAction.getIcon(),
+ remoteAction.getTitle(),
+ remoteAction.getActionIntent())
+ .setSemanticAction(
+ Notification.Action.SEMANTIC_ACTION_CONTEXTUAL_SUGGESTION)
+ .addExtras(Bundle.forPair(KEY_ACTION_TYPE, classification.getEntity(0)))
+ .build();
+ actions.add(action);
+
// We have enough smart actions.
if (actions.size() >= maxSmartActions) {
return actions;
diff --git a/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionHelperTest.java b/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionHelperTest.java
index 0352ebcec8b3..da382a003621 100644
--- a/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionHelperTest.java
+++ b/packages/ExtServices/tests/src/android/ext/services/notification/SmartActionHelperTest.java
@@ -28,12 +28,14 @@ import android.app.Notification;
import android.app.Person;
import android.content.Context;
import android.os.Process;
+import android.service.notification.NotificationAssistantService;
import android.service.notification.StatusBarNotification;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.view.textclassifier.ConversationActions;
import android.view.textclassifier.TextClassificationManager;
import android.view.textclassifier.TextClassifier;
+import android.view.textclassifier.TextClassifierEvent;
import com.google.common.truth.FailureStrategy;
import com.google.common.truth.Subject;
@@ -44,12 +46,14 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
@@ -58,8 +62,14 @@ import javax.annotation.Nullable;
@RunWith(AndroidJUnit4.class)
public class SmartActionHelperTest {
+ private static final String NOTIFICATION_KEY = "key";
+ private static final String RESULT_ID = "id";
- private SmartActionsHelper mSmartActionsHelper = new SmartActionsHelper();
+ private static final ConversationActions.ConversationAction REPLY_ACTION =
+ new ConversationActions.ConversationAction.Builder(
+ ConversationActions.TYPE_TEXT_REPLY).setTextReply("Home").build();
+
+ private SmartActionsHelper mSmartActionsHelper;
private Context mContext;
@Mock private TextClassifier mTextClassifier;
@Mock private NotificationEntry mNotificationEntry;
@@ -75,7 +85,7 @@ public class SmartActionHelperTest {
mContext.getSystemService(TextClassificationManager.class)
.setTextClassifier(mTextClassifier);
when(mTextClassifier.suggestConversationActions(any(ConversationActions.Request.class)))
- .thenReturn(new ConversationActions(Collections.emptyList(), null));
+ .thenReturn(new ConversationActions(Arrays.asList(REPLY_ACTION), RESULT_ID));
when(mNotificationEntry.getSbn()).thenReturn(mStatusBarNotification);
// The notification is eligible to have smart suggestions.
@@ -83,18 +93,20 @@ public class SmartActionHelperTest {
when(mNotificationEntry.isMessaging()).thenReturn(true);
when(mStatusBarNotification.getPackageName()).thenReturn("random.app");
when(mStatusBarNotification.getUser()).thenReturn(Process.myUserHandle());
+ when(mStatusBarNotification.getKey()).thenReturn(NOTIFICATION_KEY);
mNotificationBuilder = new Notification.Builder(mContext, "channel");
mSettings = AssistantSettings.createForTesting(
null, null, Process.myUserHandle().getIdentifier(), null);
mSettings.mGenerateActions = true;
mSettings.mGenerateReplies = true;
+ mSmartActionsHelper = new SmartActionsHelper(mContext, mSettings);
}
@Test
public void testSuggestReplies_notMessagingApp() {
when(mNotificationEntry.isMessaging()).thenReturn(false);
ArrayList<CharSequence> textReplies =
- mSmartActionsHelper.suggestReplies(mContext, mNotificationEntry, mSettings);
+ mSmartActionsHelper.suggestReplies(mNotificationEntry);
assertThat(textReplies).isEmpty();
}
@@ -102,7 +114,7 @@ public class SmartActionHelperTest {
public void testSuggestReplies_noInlineReply() {
when(mNotificationEntry.hasInlineReply()).thenReturn(false);
ArrayList<CharSequence> textReplies =
- mSmartActionsHelper.suggestReplies(mContext, mNotificationEntry, mSettings);
+ mSmartActionsHelper.suggestReplies(mNotificationEntry);
assertThat(textReplies).isEmpty();
}
@@ -169,18 +181,128 @@ public class SmartActionHelperTest {
.build();
when(mNotificationEntry.getNotification()).thenReturn(notification);
- mSmartActionsHelper.suggestReplies(mContext, mNotificationEntry, mSettings);
+ mSmartActionsHelper.suggestReplies(mNotificationEntry);
verify(mTextClassifier, never())
.suggestConversationActions(any(ConversationActions.Request.class));
}
+ @Test
+ public void testOnSuggestedReplySent() {
+ final String message = "Where are you?";
+ Notification notification = mNotificationBuilder.setContentText(message).build();
+ when(mNotificationEntry.getNotification()).thenReturn(notification);
+
+ mSmartActionsHelper.suggestReplies(mNotificationEntry);
+ mSmartActionsHelper.onSuggestedReplySent(
+ NOTIFICATION_KEY, message, NotificationAssistantService.SOURCE_FROM_ASSISTANT);
+
+ ArgumentCaptor<TextClassifierEvent> argumentCaptor =
+ ArgumentCaptor.forClass(TextClassifierEvent.class);
+ verify(mTextClassifier).onTextClassifierEvent(argumentCaptor.capture());
+ TextClassifierEvent textClassifierEvent = argumentCaptor.getValue();
+ assertTextClassifierEvent(textClassifierEvent, TextClassifierEvent.TYPE_SMART_ACTION);
+ }
+
+ @Test
+ public void testOnSuggestedReplySent_anotherNotification() {
+ final String message = "Where are you?";
+ Notification notification = mNotificationBuilder.setContentText(message).build();
+ when(mNotificationEntry.getNotification()).thenReturn(notification);
+
+ mSmartActionsHelper.suggestReplies(mNotificationEntry);
+ mSmartActionsHelper.onSuggestedReplySent(
+ "something_else", message, NotificationAssistantService.SOURCE_FROM_ASSISTANT);
+
+ verify(mTextClassifier, never())
+ .onTextClassifierEvent(Mockito.any(TextClassifierEvent.class));
+ }
+
+ @Test
+ public void testOnSuggestedReplySent_missingResultId() {
+ when(mTextClassifier.suggestConversationActions(any(ConversationActions.Request.class)))
+ .thenReturn(new ConversationActions(Collections.emptyList(), null));
+
+ final String message = "Where are you?";
+ Notification notification = mNotificationBuilder.setContentText(message).build();
+ when(mNotificationEntry.getNotification()).thenReturn(notification);
+
+ mSmartActionsHelper.suggestReplies(mNotificationEntry);
+ mSmartActionsHelper.onSuggestedReplySent(
+ "something_else", message, NotificationAssistantService.SOURCE_FROM_ASSISTANT);
+
+ verify(mTextClassifier, never())
+ .onTextClassifierEvent(Mockito.any(TextClassifierEvent.class));
+ }
+
+ @Test
+ public void testOnNotificationDirectReply() {
+ Notification notification = mNotificationBuilder.setContentText("Where are you?").build();
+ when(mNotificationEntry.getNotification()).thenReturn(notification);
+
+ mSmartActionsHelper.suggestReplies(mNotificationEntry);
+ mSmartActionsHelper.onNotificationDirectReply(NOTIFICATION_KEY);
+
+ ArgumentCaptor<TextClassifierEvent> argumentCaptor =
+ ArgumentCaptor.forClass(TextClassifierEvent.class);
+ verify(mTextClassifier).onTextClassifierEvent(argumentCaptor.capture());
+ TextClassifierEvent textClassifierEvent = argumentCaptor.getValue();
+ assertTextClassifierEvent(textClassifierEvent, TextClassifierEvent.TYPE_MANUAL_REPLY);
+ }
+
+ @Test
+ public void testOnNotificationExpansionChanged() {
+ final String message = "Where are you?";
+ Notification notification = mNotificationBuilder.setContentText(message).build();
+ when(mNotificationEntry.getNotification()).thenReturn(notification);
+
+ mSmartActionsHelper.suggestReplies(mNotificationEntry);
+ mSmartActionsHelper.onNotificationExpansionChanged(mNotificationEntry, true, true);
+
+ ArgumentCaptor<TextClassifierEvent> argumentCaptor =
+ ArgumentCaptor.forClass(TextClassifierEvent.class);
+ verify(mTextClassifier).onTextClassifierEvent(argumentCaptor.capture());
+ TextClassifierEvent textClassifierEvent = argumentCaptor.getValue();
+ assertTextClassifierEvent(textClassifierEvent, TextClassifierEvent.TYPE_ACTIONS_SHOWN);
+ }
+
+ @Test
+ public void testOnNotificationsSeen_notExpanded() {
+ final String message = "Where are you?";
+ Notification notification = mNotificationBuilder.setContentText(message).build();
+ when(mNotificationEntry.getNotification()).thenReturn(notification);
+ when(mNotificationEntry.isExpanded()).thenReturn(false);
+
+ mSmartActionsHelper.suggestReplies(mNotificationEntry);
+ mSmartActionsHelper.onNotificationSeen(mNotificationEntry);
+
+ verify(mTextClassifier, never()).onTextClassifierEvent(
+ Mockito.any(TextClassifierEvent.class));
+ }
+
+ @Test
+ public void testOnNotificationsSeen_expanded() {
+ final String message = "Where are you?";
+ Notification notification = mNotificationBuilder.setContentText(message).build();
+ when(mNotificationEntry.getNotification()).thenReturn(notification);
+ when(mNotificationEntry.isExpanded()).thenReturn(true);
+
+ mSmartActionsHelper.suggestReplies(mNotificationEntry);
+ mSmartActionsHelper.onNotificationSeen(mNotificationEntry);
+
+ ArgumentCaptor<TextClassifierEvent> argumentCaptor =
+ ArgumentCaptor.forClass(TextClassifierEvent.class);
+ verify(mTextClassifier).onTextClassifierEvent(argumentCaptor.capture());
+ TextClassifierEvent textClassifierEvent = argumentCaptor.getValue();
+ assertTextClassifierEvent(textClassifierEvent, TextClassifierEvent.TYPE_ACTIONS_SHOWN);
+ }
+
private ZonedDateTime createZonedDateTimeFromMsUtc(long msUtc) {
return ZonedDateTime.ofInstant(Instant.ofEpochMilli(msUtc), ZoneOffset.systemDefault());
}
private List<ConversationActions.Message> getMessagesInRequest() {
- mSmartActionsHelper.suggestReplies(mContext, mNotificationEntry, mSettings);
+ mSmartActionsHelper.suggestReplies(mNotificationEntry);
ArgumentCaptor<ConversationActions.Request> argumentCaptor =
ArgumentCaptor.forClass(ConversationActions.Request.class);
@@ -189,6 +311,17 @@ public class SmartActionHelperTest {
return request.getConversation();
}
+ private void assertTextClassifierEvent(
+ TextClassifierEvent textClassifierEvent, int expectedEventType) {
+ assertThat(textClassifierEvent.getEventCategory())
+ .isEqualTo(TextClassifierEvent.CATEGORY_CONVERSATION_ACTIONS);
+ assertThat(textClassifierEvent.getEventContext().getPackageName())
+ .isEqualTo(InstrumentationRegistry.getTargetContext().getPackageName());
+ assertThat(textClassifierEvent.getEventContext().getWidgetType())
+ .isEqualTo(TextClassifier.WIDGET_TYPE_NOTIFICATION);
+ assertThat(textClassifierEvent.getEventType()).isEqualTo(expectedEventType);
+ }
+
private static final class MessageSubject
extends Subject<MessageSubject, ConversationActions.Message> {
diff --git a/packages/ExternalStorageProvider/tests/Android.bp b/packages/ExternalStorageProvider/tests/Android.bp
index 83427d4ebf00..04cf01af073a 100644
--- a/packages/ExternalStorageProvider/tests/Android.bp
+++ b/packages/ExternalStorageProvider/tests/Android.bp
@@ -14,7 +14,7 @@ android_test {
],
static_libs: [
- "android-support-test",
+ "androidx.test.rules",
"mockito-target",
"truth-prebuilt",
],
diff --git a/packages/ExternalStorageProvider/tests/AndroidManifest.xml b/packages/ExternalStorageProvider/tests/AndroidManifest.xml
index 58b6e86dfc77..f1a6af08ec4c 100644
--- a/packages/ExternalStorageProvider/tests/AndroidManifest.xml
+++ b/packages/ExternalStorageProvider/tests/AndroidManifest.xml
@@ -6,7 +6,7 @@
<uses-library android:name="android.test.runner" />
</application>
- <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.externalstorage"
android:label="ExternalStorageProvider Tests" />
</manifest>
diff --git a/packages/ExternalStorageProvider/tests/AndroidTest.xml b/packages/ExternalStorageProvider/tests/AndroidTest.xml
index e5fa73f59836..f8438b22b603 100644
--- a/packages/ExternalStorageProvider/tests/AndroidTest.xml
+++ b/packages/ExternalStorageProvider/tests/AndroidTest.xml
@@ -23,7 +23,7 @@
<option name="test-tag" value="ExternalStorageProviderTests" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.externalstorage.tests" />
- <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="hidden-api-checks" value="false"/>
</test>
</configuration>
diff --git a/packages/ExternalStorageProvider/tests/src/com/android/externalstorage/ExternalStorageProviderTest.java b/packages/ExternalStorageProvider/tests/src/com/android/externalstorage/ExternalStorageProviderTest.java
index a88b3e146ea1..fbf2e4b8ff19 100644
--- a/packages/ExternalStorageProvider/tests/src/com/android/externalstorage/ExternalStorageProviderTest.java
+++ b/packages/ExternalStorageProvider/tests/src/com/android/externalstorage/ExternalStorageProviderTest.java
@@ -23,8 +23,9 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.pm.ProviderInfo;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/packages/OsuLogin/src/com/android/hotspot2/osu/OsuLoginActivity.java b/packages/OsuLogin/src/com/android/hotspot2/osu/OsuLoginActivity.java
index 0312b81493be..28b05396acce 100644
--- a/packages/OsuLogin/src/com/android/hotspot2/osu/OsuLoginActivity.java
+++ b/packages/OsuLogin/src/com/android/hotspot2/osu/OsuLoginActivity.java
@@ -39,12 +39,14 @@ import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;
+import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
+
import com.android.hotspot2.R;
import java.net.MalformedURLException;
import java.net.URL;
-import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
+
/**
* Online Sign Up Login Web View launched during Provision Process of Hotspot 2.0 rel2.
@@ -252,6 +254,10 @@ public class OsuLoginActivity extends Activity {
@Override
public void onReceivedError(WebView view, WebResourceRequest request,
WebResourceError error) {
+ if (request.getUrl().toString().startsWith("http://127.0.0.1")) {
+ view.stopLoading();
+ }
+
if (request.isForMainFrame()) {
// This happens right after getting HTTP redirect response from an OSU server
// since no more Http request is allowed to send to the OSU server.
diff --git a/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarChartPreference.java b/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarChartPreference.java
index d400159984a6..305862af505b 100644
--- a/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarChartPreference.java
+++ b/packages/SettingsLib/BarChartPreference/src/com/android/settingslib/widget/BarChartPreference.java
@@ -165,8 +165,12 @@ public class BarChartPreference extends Preference {
private void bindChartDetailsView(PreferenceViewHolder holder) {
final Button detailsView = (Button) holder.findViewById(R.id.bar_chart_details);
- detailsView.setText(mDetailsId);
- detailsView.setOnClickListener(mDetailsOnClickListener);
+ if (mDetailsId == 0) {
+ detailsView.setVisibility(View.GONE);
+ } else {
+ detailsView.setText(mDetailsId);
+ detailsView.setOnClickListener(mDetailsOnClickListener);
+ }
}
private void updateBarChart(PreferenceViewHolder holder) {
diff --git a/packages/SettingsLib/tests/integ/Android.mk b/packages/SettingsLib/tests/integ/Android.mk
index c893b6dcffbf..4a814df1dfff 100644
--- a/packages/SettingsLib/tests/integ/Android.mk
+++ b/packages/SettingsLib/tests/integ/Android.mk
@@ -31,8 +31,8 @@ LOCAL_COMPATIBILITY_SUITE := device-tests
LOCAL_USE_AAPT2 := true
LOCAL_STATIC_JAVA_LIBRARIES := \
- android-support-test \
- espresso-core \
+ androidx.test.rules \
+ androidx.test.espresso.core \
mockito-target-minus-junit4 \
truth-prebuilt
diff --git a/packages/SettingsLib/tests/integ/AndroidManifest.xml b/packages/SettingsLib/tests/integ/AndroidManifest.xml
index e8e0b41ffd41..da808dd54141 100644
--- a/packages/SettingsLib/tests/integ/AndroidManifest.xml
+++ b/packages/SettingsLib/tests/integ/AndroidManifest.xml
@@ -31,7 +31,7 @@
<activity android:name=".drawer.SettingsDrawerActivityTest$TestActivity"/>
</application>
- <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
+ <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="com.android.settingslib"
android:label="Tests for SettingsLib">
</instrumentation>
diff --git a/packages/SettingsLib/tests/integ/AndroidTest.xml b/packages/SettingsLib/tests/integ/AndroidTest.xml
index d7ee618207a8..b5d09475269e 100644
--- a/packages/SettingsLib/tests/integ/AndroidTest.xml
+++ b/packages/SettingsLib/tests/integ/AndroidTest.xml
@@ -22,7 +22,7 @@
<option name="test-tag" value="SettingsLibTests" />
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="com.android.settingslib" />
- <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
<option name="hidden-api-checks" value="false"/>
</test>
</configuration>
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/bluetooth/BluetoothEventManagerIntegTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/bluetooth/BluetoothEventManagerIntegTest.java
index d0ab46a2f30d..50f5b9d81000 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/bluetooth/BluetoothEventManagerIntegTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/bluetooth/BluetoothEventManagerIntegTest.java
@@ -16,15 +16,10 @@
package com.android.settingslib.bluetooth;
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
-import static java.util.concurrent.TimeUnit.SECONDS;
-
import android.app.ActivityManager;
import android.content.Context;
import android.content.Intent;
@@ -32,15 +27,18 @@ import android.content.pm.UserInfo;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.LargeTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.LargeTest;
+import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
import java.util.concurrent.CountDownLatch;
/**
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawable/UserIconDrawableTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawable/UserIconDrawableTest.java
index 3fa2ce5f8312..a436cb515bb8 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawable/UserIconDrawableTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/drawable/UserIconDrawableTest.java
@@ -27,8 +27,9 @@ import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.PorterDuff.Mode;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
import com.android.settingslib.R;
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
index dddfa7a3a9b4..08484bceb1fb 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/graph/BatteryMeterDrawableBaseTest.java
@@ -1,26 +1,29 @@
package com.android.settingslib.graph;
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyFloat;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Rect;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
import com.android.settingslib.R;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static com.google.common.truth.Truth.assertThat;
-import static junit.framework.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyFloat;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.verify;
-
@SmallTest
@RunWith(AndroidJUnit4.class)
public class BatteryMeterDrawableBaseTest {
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodPreferenceTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodPreferenceTest.java
index 93b038e07b51..9962e1ca438a 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodPreferenceTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodPreferenceTest.java
@@ -20,12 +20,13 @@ import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodSubtypePreferenceTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodSubtypePreferenceTest.java
index e591d8cac9f2..f1c0beae0dc0 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodSubtypePreferenceTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/inputmethod/InputMethodSubtypePreferenceTest.java
@@ -16,11 +16,12 @@
package com.android.settingslib.inputmethod;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
import android.text.TextUtils;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
import org.junit.Test;
import org.junit.runner.RunWith;
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/UserManagerHelperTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/UserManagerHelperTest.java
index 54510b27e58d..46557d3106af 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/UserManagerHelperTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/users/UserManagerHelperTest.java
@@ -18,7 +18,6 @@ package com.android.settingslib.users;
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -33,8 +32,9 @@ import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.UserHandle;
import android.os.UserManager;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
import org.junit.Before;
import org.junit.Test;
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/NetworkPolicyEditorTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/NetworkPolicyEditorTest.java
index ee03d5024351..37f2600e9812 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/NetworkPolicyEditorTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/NetworkPolicyEditorTest.java
@@ -16,19 +16,22 @@
package com.android.settingslib.utils;
+import static junit.framework.Assert.assertEquals;
+
import android.net.NetworkPolicy;
import android.net.NetworkPolicyManager;
import android.net.NetworkTemplate;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
import com.android.settingslib.NetworkPolicyEditor;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static junit.framework.Assert.assertEquals;
-
@RunWith(AndroidJUnit4.class)
@SmallTest
public class NetworkPolicyEditorTest {
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/ZoneGetterTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/ZoneGetterTest.java
index 0ec75ecee066..ff8dbda360fc 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/ZoneGetterTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/utils/ZoneGetterTest.java
@@ -15,21 +15,23 @@
*/
package com.android.settingslib.utils;
+import static junit.framework.Assert.assertTrue;
+
import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
-import android.support.test.filters.SmallTest;
import android.text.Spanned;
import android.text.style.TtsSpan;
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.settingslib.datetime.ZoneGetter;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.*;
-import com.android.settingslib.datetime.ZoneGetter;
-
-import static junit.framework.Assert.assertTrue;
@RunWith(AndroidJUnit4.class)
@SmallTest
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index 032479990cae..fc3034efc08b 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -22,7 +22,6 @@ import static org.junit.Assert.fail;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -44,12 +43,12 @@ import android.net.wifi.hotspot2.pps.HomeSp;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.SystemClock;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
import android.text.SpannableString;
import android.text.format.DateUtils;
-import android.text.style.TtsSpan;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
import com.android.settingslib.R;
import com.android.settingslib.utils.ThreadUtils;
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index 1860b31081e1..42eb0b940938 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -53,9 +53,10 @@ import android.os.Handler;
import android.os.HandlerThread;
import android.os.SystemClock;
import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
import com.android.settingslib.utils.ThreadUtils;
@@ -79,7 +80,6 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
// TODO(sghuman): Change these to robolectric tests b/35766684.
-
@SmallTest
@RunWith(AndroidJUnit4.class)
public class WifiTrackerTest {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java
index d4e74810ea3f..375b45cf46d0 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/BarChartPreferenceTest.java
@@ -41,6 +41,7 @@ public class BarChartPreferenceTest {
private BarView mBarView2;
private BarView mBarView3;
private BarView mBarView4;
+ private TextView mDetailsView;
private PreferenceViewHolder mHolder;
private BarChartPreference mPreference;
@@ -51,14 +52,13 @@ public class BarChartPreferenceTest {
mHolder = PreferenceViewHolder.createInstanceForTests(mBarChartView);
mPreference = new BarChartPreference(mContext, null /* attrs */);
mPreference.setBarChartTitle(R.string.debug_app);
- mPreference.setBarChartDetails(R.string.debug_app);
-
mIcon = mContext.getDrawable(R.drawable.ic_menu);
mBarView1 = (BarView) mBarChartView.findViewById(R.id.bar_view1);
mBarView2 = (BarView) mBarChartView.findViewById(R.id.bar_view2);
mBarView3 = (BarView) mBarChartView.findViewById(R.id.bar_view3);
mBarView4 = (BarView) mBarChartView.findViewById(R.id.bar_view4);
+ mDetailsView = (TextView) mBarChartView.findViewById(R.id.bar_chart_details);
}
@Test
@@ -73,26 +73,31 @@ public class BarChartPreferenceTest {
}
@Test
- public void setBarChartDetailsRes_setDetailsRes_showInBarChartDetails() {
- final TextView detailsView = (TextView) mBarChartView.findViewById(R.id.bar_chart_details);
+ public void onBindViewHolder_notSetDetailsRes_barChartDetailsViewIsGone() {
+ // We don't call BarChartPreference#setBarChartDetails
+ mPreference.onBindViewHolder(mHolder);
+
+ assertThat(mDetailsView.getVisibility()).isEqualTo(View.GONE);
+ }
+ @Test
+ public void setBarChartDetailsRes_setDetailsRes_showInBarChartDetails() {
mPreference.setBarChartDetails(R.string.debug_app);
mPreference.onBindViewHolder(mHolder);
- assertThat(detailsView.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(detailsView.getText()).isEqualTo(mContext.getText(R.string.debug_app));
+ assertThat(mDetailsView.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mDetailsView.getText()).isEqualTo(mContext.getText(R.string.debug_app));
}
@Test
public void setBarChartDetailsClickListener_setClickListener_detailsViewAttachClickListener() {
- final TextView detailsView = (TextView) mBarChartView.findViewById(R.id.bar_chart_details);
-
+ mPreference.setBarChartDetails(R.string.debug_app);
mPreference.setBarChartDetailsClickListener(v -> {
});
mPreference.onBindViewHolder(mHolder);
- assertThat(detailsView.getVisibility()).isEqualTo(View.VISIBLE);
- assertThat(detailsView.hasOnClickListeners()).isTrue();
+ assertThat(mDetailsView.getVisibility()).isEqualTo(View.VISIBLE);
+ assertThat(mDetailsView.hasOnClickListeners()).isTrue();
}
@Test
diff --git a/packages/SimAppDialog/src/com/android/simappdialog/InstallCarrierAppActivity.java b/packages/SimAppDialog/src/com/android/simappdialog/InstallCarrierAppActivity.java
index 8e8d9f741a81..abe82a885a94 100644
--- a/packages/SimAppDialog/src/com/android/simappdialog/InstallCarrierAppActivity.java
+++ b/packages/SimAppDialog/src/com/android/simappdialog/InstallCarrierAppActivity.java
@@ -18,7 +18,7 @@ package com.android.simappdialog;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
-import android.os.SystemProperties;
+import android.sysprop.SetupWizardProperties;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
@@ -51,7 +51,7 @@ public class InstallCarrierAppActivity extends Activity implements View.OnClickL
// Setup theme for aosp/pixel
setTheme(
WizardManagerHelper.getThemeRes(
- SystemProperties.get("setupwizard.theme"),
+ SetupWizardProperties.theme().orElse(""),
R.style.SuwThemeGlif_Light
)
);
diff --git a/packages/SystemUI/docs/dagger.md b/packages/SystemUI/docs/dagger.md
index f81e8cce1f91..7751bb10c5ce 100644
--- a/packages/SystemUI/docs/dagger.md
+++ b/packages/SystemUI/docs/dagger.md
@@ -36,7 +36,8 @@ public interface SystemUIRootComponent {
The root modules are what provides the global singleton dependencies across
SystemUI. ContextHolder is just a wrapper that provides a context.
SystemUIFactory @Provide dependencies that need to be overridden by SystemUI
-variants (like other form factors). DependencyProvider provides or binds any
+variants (like other form factors). DependencyBinder creates the mapping from
+interfaces to implementation classes. DependencyProvider provides or binds any
remaining depedencies required.
### Adding injection to a new SystemUI object
@@ -195,10 +196,5 @@ public CustomView(@Named(VIEW_CONTEXT) Context themedViewContext, AttributeSet a
## TODO List
- - Eliminate usages of Depndency#get
- - Add support for Fragments to handle injection automatically
- - (this could be through dagger2-android or something custom)
- - Reduce number of things with @Provide in DependencyProvider (many can be
- @Inject instead)
- - Migrate as many remaining DependencyProvider instances to @Bind
+ - Eliminate usages of Dependency#get
- Add links in above TODO
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
index 6135aebb0587..ac6904300f71 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/ClockPlugin.java
@@ -36,6 +36,13 @@ public interface ClockPlugin extends Plugin {
View getView();
/**
+ * Get clock view for a large clock that appears behind NSSL.
+ */
+ default View getBigClockView() {
+ return null;
+ }
+
+ /**
* Set clock paint style.
* @param style The new style to set in the paint.
*/
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index ed18dc728402..4e0cbe093c49 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -24,13 +24,14 @@
android:layout_gravity="@integer/notification_panel_layout_gravity"
android:background="@android:color/transparent"
android:baselineAligned="false"
- android:clickable="false"
+ android:clickable="true"
android:clipChildren="false"
android:clipToPadding="false"
android:paddingTop="0dp"
android:paddingEnd="0dp"
android:paddingStart="0dp"
- android:elevation="4dp" >
+ android:elevation="4dp"
+ android:importantForAccessibility="no" >
<include layout="@layout/quick_status_bar_header_system_icons" />
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index 2674f07c21e4..75c0ec3ced43 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -25,6 +25,12 @@
android:layout_height="match_parent"
android:background="@android:color/transparent" >
+ <FrameLayout
+ android:id="@+id/big_clock_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:visibility="gone" />
+
<include
layout="@layout/keyguard_status_view"
android:visibility="gone" />
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 07375ad333ed..c94438fa74f1 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2330,4 +2330,7 @@
</plurals>
<!-- Text for the quick setting tile for sensor privacy [CHAR LIMIT=30] -->
<string name="sensor_privacy_mode">Sensors off</string>
+
+ <!-- Name for device services grouping system uid apps in Ongoing Privacy Dialog [CHAR_LIMIT=NONE] -->
+ <string name="device_services">Device Services</string>
</resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java
new file mode 100644
index 000000000000..c0a1d891cd5b
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.shared.system;
+
+import android.graphics.Matrix;
+import android.graphics.Rect;
+import android.view.Surface;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
+import android.view.SyncRtSurfaceTransactionApplier;
+import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams;
+import android.view.ThreadedRenderer;
+import android.view.View;
+import android.view.ViewRootImpl;
+
+import java.util.function.Consumer;
+
+/**
+ * Helper class to apply surface transactions in sync with RenderThread.
+ */
+public class SyncRtSurfaceTransactionApplierCompat {
+
+ private final SyncRtSurfaceTransactionApplier mApplier;
+
+ /**
+ * @param targetView The view in the surface that acts as synchronization anchor.
+ */
+ public SyncRtSurfaceTransactionApplierCompat(View targetView) {
+ mApplier = new SyncRtSurfaceTransactionApplier(targetView);
+ }
+
+ private SyncRtSurfaceTransactionApplierCompat(SyncRtSurfaceTransactionApplier applier) {
+ mApplier = applier;
+ }
+
+ /**
+ * Schedules applying surface parameters on the next frame.
+ *
+ * @param params The surface parameters to apply. DO NOT MODIFY the list after passing into
+ * this method to avoid synchronization issues.
+ */
+ public void scheduleApply(final SurfaceParams... params) {
+ mApplier.scheduleApply(convert(params));
+ }
+
+ private SyncRtSurfaceTransactionApplier.SurfaceParams[] convert(SurfaceParams[] params) {
+ SyncRtSurfaceTransactionApplier.SurfaceParams[] result =
+ new SyncRtSurfaceTransactionApplier.SurfaceParams[params.length];
+ for (int i = 0; i < params.length; i++) {
+ result[i] = params[i].mParams;
+ }
+ return result;
+ }
+
+ public static void applyParams(TransactionCompat t, SurfaceParams params) {
+ SyncRtSurfaceTransactionApplier.applyParams(t.mTransaction, params.mParams, t.mTmpValues);
+ }
+
+ public static void create(final View targetView,
+ final Consumer<SyncRtSurfaceTransactionApplierCompat> callback) {
+ SyncRtSurfaceTransactionApplier.create(targetView,
+ new Consumer<SyncRtSurfaceTransactionApplier>() {
+ @Override
+ public void accept(SyncRtSurfaceTransactionApplier applier) {
+ callback.accept(new SyncRtSurfaceTransactionApplierCompat(applier));
+ }
+ });
+ }
+
+ public static class SurfaceParams {
+
+ private final SyncRtSurfaceTransactionApplier.SurfaceParams mParams;
+
+ /**
+ * Constructs surface parameters to be applied when the current view state gets pushed to
+ * RenderThread.
+ *
+ * @param surface The surface to modify.
+ * @param alpha Alpha to apply.
+ * @param matrix Matrix to apply.
+ * @param windowCrop Crop to apply.
+ */
+ public SurfaceParams(SurfaceControlCompat surface, float alpha, Matrix matrix,
+ Rect windowCrop, int layer, float cornerRadius) {
+ mParams = new SyncRtSurfaceTransactionApplier.SurfaceParams(surface.mSurfaceControl,
+ alpha, matrix, windowCrop, layer, cornerRadius);
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 22a23a8f8a21..570d351a8b71 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -35,7 +35,11 @@ public class KeyguardClockSwitch extends RelativeLayout {
/**
* Frame for default and custom clock.
*/
- private FrameLayout mClockFrame;
+ private FrameLayout mSmallClockFrame;
+ /**
+ * Container for big custom clock.
+ */
+ private ViewGroup mBigClockContainer;
/**
* Status area (date and other stuff) shown below the clock. Plugin can decide whether
* or not to show it below the alternate clock.
@@ -46,22 +50,27 @@ public class KeyguardClockSwitch extends RelativeLayout {
new PluginListener<ClockPlugin>() {
@Override
public void onPluginConnected(ClockPlugin plugin, Context pluginContext) {
- View view = plugin.getView();
- if (view != null) {
- disconnectPlugin();
+ disconnectPlugin();
+ View smallClockView = plugin.getView();
+ if (smallClockView != null) {
// For now, assume that the most recently connected plugin is the
// selected clock face. In the future, the user should be able to
// pick a clock face from the available plugins.
- mClockPlugin = plugin;
- mClockFrame.addView(view, -1,
+ mSmallClockFrame.addView(smallClockView, -1,
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
initPluginParams();
mClockView.setVisibility(View.GONE);
- if (!plugin.shouldShowStatusArea()) {
- mKeyguardStatusArea.setVisibility(View.GONE);
- }
}
+ View bigClockView = plugin.getBigClockView();
+ if (bigClockView != null && mBigClockContainer != null) {
+ mBigClockContainer.addView(bigClockView);
+ mBigClockContainer.setVisibility(View.VISIBLE);
+ }
+ if (!plugin.shouldShowStatusArea()) {
+ mKeyguardStatusArea.setVisibility(View.GONE);
+ }
+ mClockPlugin = plugin;
}
@Override
@@ -86,7 +95,7 @@ public class KeyguardClockSwitch extends RelativeLayout {
protected void onFinishInflate() {
super.onFinishInflate();
mClockView = findViewById(R.id.default_clock_view);
- mClockFrame = findViewById(R.id.clock_view);
+ mSmallClockFrame = findViewById(R.id.clock_view);
mKeyguardStatusArea = findViewById(R.id.keyguard_status_area);
}
@@ -104,6 +113,20 @@ public class KeyguardClockSwitch extends RelativeLayout {
}
/**
+ * Set container for big clock face appearing behind NSSL and KeyguardStatusView.
+ */
+ public void setBigClockContainer(ViewGroup container) {
+ if (mClockPlugin != null && container != null) {
+ View bigClockView = mClockPlugin.getBigClockView();
+ if (bigClockView != null) {
+ container.addView(bigClockView);
+ container.setVisibility(View.VISIBLE);
+ }
+ }
+ mBigClockContainer = container;
+ }
+
+ /**
* It will also update plugin setStyle if plugin is connected.
*/
public void setStyle(Style style) {
@@ -199,9 +222,13 @@ public class KeyguardClockSwitch extends RelativeLayout {
private void disconnectPlugin() {
if (mClockPlugin != null) {
- View view = mClockPlugin.getView();
- if (view != null) {
- mClockFrame.removeView(view);
+ View smallClockView = mClockPlugin.getView();
+ if (smallClockView != null) {
+ mSmallClockFrame.removeView(smallClockView);
+ }
+ if (mBigClockContainer != null) {
+ mBigClockContainer.removeAllViews();
+ mBigClockContainer.setVisibility(View.GONE);
}
mClockPlugin = null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java b/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java
index 9e7c5ba1d66c..b461f69f10d6 100644
--- a/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/ActivityStarterDelegate.java
@@ -19,14 +19,22 @@ import android.content.Intent;
import com.android.systemui.plugins.ActivityStarter;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Single common instance of ActivityStarter that can be gotten and referenced from anywhere, but
* delegates to an actual implementation such as StatusBar, assuming it exists.
*/
+@Singleton
public class ActivityStarterDelegate implements ActivityStarter {
private ActivityStarter mActualStarter;
+ @Inject
+ public ActivityStarterDelegate() {
+ }
+
@Override
public void startPendingIntentDismissingKeyguard(PendingIntent intent) {
if (mActualStarter == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 6b4d07a44d34..443e389b1d02 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -220,6 +220,7 @@ public class Dependency extends SystemUI {
@Inject Lazy<FragmentService> mFragmentService;
@Inject Lazy<ExtensionController> mExtensionController;
@Inject Lazy<PluginDependencyProvider> mPluginDependencyProvider;
+ @Nullable
@Inject Lazy<LocalBluetoothManager> mLocalBluetoothManager;
@Inject Lazy<VolumeDialogController> mVolumeDialogController;
@Inject Lazy<MetricsLogger> mMetricsLogger;
diff --git a/packages/SystemUI/src/com/android/systemui/DependencyBinder.java b/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
new file mode 100644
index 000000000000..23ef0307feb1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/DependencyBinder.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import com.android.systemui.appops.AppOpsController;
+import com.android.systemui.appops.AppOpsControllerImpl;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.VolumeDialogController;
+import com.android.systemui.power.PowerNotificationWarnings;
+import com.android.systemui.power.PowerUI;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
+import com.android.systemui.statusbar.phone.ManagedProfileController;
+import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
+import com.android.systemui.statusbar.phone.StatusBarIconController;
+import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl;
+import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.BatteryControllerImpl;
+import com.android.systemui.statusbar.policy.BluetoothController;
+import com.android.systemui.statusbar.policy.BluetoothControllerImpl;
+import com.android.systemui.statusbar.policy.CastController;
+import com.android.systemui.statusbar.policy.CastControllerImpl;
+import com.android.systemui.statusbar.policy.DarkIconDispatcher;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
+import com.android.systemui.statusbar.policy.ExtensionController;
+import com.android.systemui.statusbar.policy.ExtensionControllerImpl;
+import com.android.systemui.statusbar.policy.FlashlightController;
+import com.android.systemui.statusbar.policy.FlashlightControllerImpl;
+import com.android.systemui.statusbar.policy.HotspotController;
+import com.android.systemui.statusbar.policy.HotspotControllerImpl;
+import com.android.systemui.statusbar.policy.IconLogger;
+import com.android.systemui.statusbar.policy.IconLoggerImpl;
+import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
+import com.android.systemui.statusbar.policy.LocationController;
+import com.android.systemui.statusbar.policy.LocationControllerImpl;
+import com.android.systemui.statusbar.policy.NetworkController;
+import com.android.systemui.statusbar.policy.NetworkControllerImpl;
+import com.android.systemui.statusbar.policy.NextAlarmController;
+import com.android.systemui.statusbar.policy.NextAlarmControllerImpl;
+import com.android.systemui.statusbar.policy.RotationLockController;
+import com.android.systemui.statusbar.policy.RotationLockControllerImpl;
+import com.android.systemui.statusbar.policy.SecurityController;
+import com.android.systemui.statusbar.policy.SecurityControllerImpl;
+import com.android.systemui.statusbar.policy.UserInfoController;
+import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
+import com.android.systemui.statusbar.policy.ZenModeController;
+import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
+import com.android.systemui.tuner.TunerService;
+import com.android.systemui.tuner.TunerServiceImpl;
+import com.android.systemui.volume.VolumeDialogControllerImpl;
+
+import dagger.Binds;
+import dagger.Module;
+
+/**
+ * Maps interfaces to implementations for use with Dagger.
+ */
+@Module
+public abstract class DependencyBinder {
+
+ /**
+ */
+ @Binds
+ public abstract ActivityStarter provideActivityStarter(ActivityStarterDelegate delegate);
+
+ /**
+ */
+ @Binds
+ public abstract BluetoothController provideBluetoothController(
+ BluetoothControllerImpl controllerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract LocationController provideLocationController(
+ LocationControllerImpl controllerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract RotationLockController provideRotationLockController(
+ RotationLockControllerImpl controllerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract NetworkController provideNetworkController(
+ NetworkControllerImpl controllerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract ZenModeController provideZenModeController(
+ ZenModeControllerImpl controllerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract HotspotController provideHotspotController(
+ HotspotControllerImpl controllerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract AppOpsController provideAppOpsController(
+ AppOpsControllerImpl controllerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract NotificationRemoteInputManager.Callback provideNotificationRemoteInputManager(
+ StatusBarRemoteInputCallback callbackImpl);
+
+ /**
+ */
+ @Binds
+ public abstract IconLogger provideIconLogger(IconLoggerImpl loggerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract CastController provideCastController(CastControllerImpl controllerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract FlashlightController provideFlashlightController(
+ FlashlightControllerImpl controllerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract KeyguardMonitor provideKeyguardMonitor(KeyguardMonitorImpl controllerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract UserInfoController provideUserInfoContrller(
+ UserInfoControllerImpl controllerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract BatteryController provideBatteryController(
+ BatteryControllerImpl controllerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract ManagedProfileController provideManagedProfileController(
+ ManagedProfileControllerImpl controllerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract NextAlarmController provideNextAlarmController(
+ NextAlarmControllerImpl controllerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract DeviceProvisionedController provideDeviceProvisionedController(
+ DeviceProvisionedControllerImpl controllerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract SecurityController provideSecurityController(
+ SecurityControllerImpl controllerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract TunerService provideTunerService(TunerServiceImpl controllerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract DarkIconDispatcher provideDarkIconDispatcher(
+ DarkIconDispatcherImpl controllerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract StatusBarIconController provideStatusBarIconController(
+ StatusBarIconControllerImpl controllerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract ExtensionController provideExtensionController(
+ ExtensionControllerImpl controllerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract VolumeDialogController provideVolumeDialogController(
+ VolumeDialogControllerImpl controllerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract ForegroundServiceController provideForegroundService(
+ ForegroundServiceControllerImpl controllerImpl);
+
+ /**
+ */
+ @Binds
+ public abstract PowerUI.WarningsUI provideWarningsUi(PowerNotificationWarnings controllerImpl);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/DependencyProvider.java b/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
index b11e189e3a9c..2b521c53a1e6 100644
--- a/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/DependencyProvider.java
@@ -18,13 +18,11 @@ package com.android.systemui;
import static com.android.systemui.Dependency.BG_HANDLER_NAME;
import static com.android.systemui.Dependency.BG_LOOPER_NAME;
-import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME;
import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME;
import android.annotation.Nullable;
import android.content.Context;
-import android.hardware.SensorManager;
import android.hardware.SensorPrivacyManager;
import android.os.Handler;
import android.os.HandlerThread;
@@ -40,82 +38,16 @@ import com.android.internal.app.ColorDisplayController;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.statusbar.IStatusBarService;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
-import com.android.systemui.appops.AppOpsController;
-import com.android.systemui.appops.AppOpsControllerImpl;
-import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.keyguard.ScreenLifecycle;
-import com.android.systemui.keyguard.WakefulnessLifecycle;
-import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.plugins.PluginInitializerImpl;
-import com.android.systemui.plugins.VolumeDialogController;
-import com.android.systemui.power.PowerNotificationWarnings;
-import com.android.systemui.power.PowerUI;
-import com.android.systemui.recents.OverviewProxyService;
import com.android.systemui.shared.plugins.PluginManager;
import com.android.systemui.shared.plugins.PluginManagerImpl;
-import com.android.systemui.statusbar.DisplayNavigationBarController;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
-import com.android.systemui.statusbar.VibratorHelper;
import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
-import com.android.systemui.statusbar.phone.DarkIconDispatcherImpl;
-import com.android.systemui.statusbar.phone.LightBarController;
-import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
-import com.android.systemui.statusbar.phone.ManagedProfileController;
-import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
import com.android.systemui.statusbar.phone.ShadeController;
import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.phone.StatusBarIconController;
-import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl;
-import com.android.systemui.statusbar.phone.StatusBarRemoteInputCallback;
-import com.android.systemui.statusbar.phone.StatusBarWindowController;
-import com.android.systemui.statusbar.policy.AccessibilityController;
-import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
-import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.BatteryControllerImpl;
-import com.android.systemui.statusbar.policy.BluetoothController;
-import com.android.systemui.statusbar.policy.BluetoothControllerImpl;
-import com.android.systemui.statusbar.policy.CastController;
-import com.android.systemui.statusbar.policy.CastControllerImpl;
import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import com.android.systemui.statusbar.policy.DataSaverController;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
-import com.android.systemui.statusbar.policy.ExtensionController;
-import com.android.systemui.statusbar.policy.ExtensionControllerImpl;
-import com.android.systemui.statusbar.policy.FlashlightController;
-import com.android.systemui.statusbar.policy.FlashlightControllerImpl;
-import com.android.systemui.statusbar.policy.HotspotController;
-import com.android.systemui.statusbar.policy.HotspotControllerImpl;
-import com.android.systemui.statusbar.policy.IconLogger;
-import com.android.systemui.statusbar.policy.IconLoggerImpl;
-import com.android.systemui.statusbar.policy.KeyguardMonitor;
-import com.android.systemui.statusbar.policy.KeyguardMonitorImpl;
-import com.android.systemui.statusbar.policy.LocationController;
-import com.android.systemui.statusbar.policy.LocationControllerImpl;
import com.android.systemui.statusbar.policy.NetworkController;
-import com.android.systemui.statusbar.policy.NetworkControllerImpl;
-import com.android.systemui.statusbar.policy.NextAlarmController;
-import com.android.systemui.statusbar.policy.NextAlarmControllerImpl;
-import com.android.systemui.statusbar.policy.RotationLockController;
-import com.android.systemui.statusbar.policy.RotationLockControllerImpl;
-import com.android.systemui.statusbar.policy.SecurityController;
-import com.android.systemui.statusbar.policy.SecurityControllerImpl;
-import com.android.systemui.statusbar.policy.UserInfoController;
-import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
-import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
-import com.android.systemui.tuner.TunablePadding;
-import com.android.systemui.tuner.TunablePadding.TunablePaddingService;
-import com.android.systemui.tuner.TunerService;
-import com.android.systemui.tuner.TunerServiceImpl;
-import com.android.systemui.util.AsyncSensorManager;
-import com.android.systemui.util.leak.GarbageMonitor;
import com.android.systemui.util.leak.LeakDetector;
-import com.android.systemui.util.leak.LeakReporter;
-import com.android.systemui.volume.VolumeDialogControllerImpl;
import javax.inject.Named;
import javax.inject.Singleton;
@@ -165,256 +97,13 @@ public class DependencyProvider {
@Singleton
@Provides
- public ActivityStarter provideActivityStarter() {
- return new ActivityStarterDelegate();
- }
-
- @Singleton
- @Provides
- public InitController provideInitController() {
- return new InitController();
- }
-
- @Singleton
- @Provides
- public ActivityStarterDelegate provideActivityStarterDelegate(ActivityStarter starter) {
- return (ActivityStarterDelegate) starter;
- }
-
- @Singleton
- @Provides
- public AsyncSensorManager provideAsyncSensorManager(Context context, PluginManager manager) {
- return new AsyncSensorManager(context.getSystemService(SensorManager.class),
- manager);
-
- }
-
- @Singleton
- @Provides
- public BluetoothController provideBluetoothController(Context context,
- @Named(BG_LOOPER_NAME) Looper looper) {
- return new BluetoothControllerImpl(context, looper);
-
- }
-
- @Singleton
- @Provides
- public LocationController provideLocationController(Context context,
- @Named(BG_LOOPER_NAME) Looper bgLooper) {
- return new LocationControllerImpl(context, bgLooper);
-
- }
-
- @Singleton
- @Provides
- public RotationLockController provideRotationLockController(Context context) {
- return new RotationLockControllerImpl(context);
-
- }
-
- @Singleton
- @Provides
- public NetworkController provideNetworkController(Context context,
- @Named(BG_LOOPER_NAME) Looper bgLooper, DeviceProvisionedController controller) {
- return new NetworkControllerImpl(context, bgLooper,
- controller);
-
- }
-
- @Singleton
- @Provides
- public ZenModeController provideZenModeController(Context context,
- @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
- return new ZenModeControllerImpl(context, mainHandler);
-
- }
-
- @Singleton
- @Provides
- public HotspotController provideHotspotController(Context context) {
- return new HotspotControllerImpl(context);
-
- }
-
- @Singleton
- @Provides
- public CastController provideCastController(Context context) {
- return new CastControllerImpl(context);
-
- }
-
- @Singleton
- @Provides
- public FlashlightController provideFlashlightController(Context context) {
- return new FlashlightControllerImpl(context);
-
- }
-
- @Singleton
- @Provides
- public KeyguardMonitor provideKeyguardMonitor(Context context) {
- return new KeyguardMonitorImpl(context);
-
- }
-
- @Singleton
- @Provides
- public UserSwitcherController provideUserSwitcherController(Context context,
- KeyguardMonitor keyguardMonitor, @Named(MAIN_HANDLER_NAME) Handler mainHandler,
- ActivityStarter activityStarter) {
- return new UserSwitcherController(context, keyguardMonitor, mainHandler, activityStarter);
- }
-
- @Singleton
- @Provides
- public UserInfoController provideUserInfoContrller(Context context) {
- return new UserInfoControllerImpl(context);
-
- }
-
- @Singleton
- @Provides
- public BatteryController provideBatteryController(Context context) {
- return new BatteryControllerImpl(context);
-
- }
-
- @Singleton
- @Provides
- public ColorDisplayController provideColorDisplayController(Context context) {
- return new ColorDisplayController(context);
-
- }
-
- @Singleton
- @Provides
- public ManagedProfileController provideManagedProfileController(Context context) {
- return new ManagedProfileControllerImpl(context);
-
- }
-
- @Singleton
- @Provides
- public NextAlarmController provideNextAlarmController(Context context) {
- return new NextAlarmControllerImpl(context);
-
- }
-
- @Singleton
- @Provides
public DataSaverController provideDataSaverController(NetworkController networkController) {
return networkController.getDataSaverController();
}
@Singleton
@Provides
- public AccessibilityController provideAccessibilityController(Context context) {
- return new AccessibilityController(context);
-
- }
-
- @Singleton
- @Provides
- public DeviceProvisionedController provideDeviceProvisionedController(Context context) {
- return new DeviceProvisionedControllerImpl(context);
-
- }
-
- @Singleton
- @Provides
- public PluginManager providePluginManager(Context context) {
- return new PluginManagerImpl(context, new PluginInitializerImpl());
-
- }
-
- @Singleton
- @Provides
- public SecurityController provideSecurityController(Context context) {
- return new SecurityControllerImpl(context);
-
- }
-
- @Singleton
- @Provides
- public LeakDetector provideLeakDetector() {
- return LeakDetector.create();
-
- }
-
- @Singleton
- @Provides
- public LeakReporter provideLeakReporter(Context context, LeakDetector detector,
- @Nullable @Named(LEAK_REPORT_EMAIL_NAME) String email) {
- return new LeakReporter(context, detector, email);
- }
-
- @Singleton
- @Provides
- public GarbageMonitor provideGarbageMonitor(Context context,
- @Named(BG_LOOPER_NAME) Looper bgLooper, LeakDetector detector, LeakReporter reporter) {
- return new GarbageMonitor(context, bgLooper, detector, reporter);
- }
-
- @Singleton
- @Provides
- public TunerService provideTunerService(Context context) {
- return new TunerServiceImpl(context);
-
- }
-
- @Singleton
- @Provides
- public StatusBarWindowController provideStatusBarWindowController(Context context) {
- return new StatusBarWindowController(context);
-
- }
-
- @Singleton
- @Provides
- public DarkIconDispatcher provideDarkIconDispatcher(Context context) {
- return new DarkIconDispatcherImpl(context);
- }
-
- @Singleton
- @Provides
- public ConfigurationController provideConfigurationController(Context context) {
- return new ConfigurationControllerImpl(context);
-
- }
-
- @Singleton
- @Provides
- public StatusBarIconController provideStatusBarIconController(Context context) {
- return new StatusBarIconControllerImpl(context);
-
- }
-
- @Singleton
- @Provides
- public ScreenLifecycle provideScreenLifecycle() {
- return new ScreenLifecycle();
- }
-
- @Singleton
- @Provides
- public WakefulnessLifecycle provideWakefulnessLifecycle() {
- return new WakefulnessLifecycle();
- }
-
- @Singleton
- @Provides
- public ExtensionController provideExtensionController(Context context) {
- return new ExtensionControllerImpl(context);
- }
-
- @Singleton
- @Provides
- public PluginDependencyProvider providePluginDependency(PluginManager pluginManager) {
- return new PluginDependencyProvider(pluginManager);
- }
-
- @Singleton
- @Provides
+ @Nullable
public LocalBluetoothManager provideLocalBluetoothController(Context context,
@Named(BG_HANDLER_NAME) Handler bgHandler) {
return LocalBluetoothManager.create(context, bgHandler,
@@ -423,72 +112,8 @@ public class DependencyProvider {
@Singleton
@Provides
- public VolumeDialogController provideVolumeDialogController(Context context) {
- return new VolumeDialogControllerImpl(context);
-
- }
-
- @Singleton
- @Provides
public MetricsLogger provideMetricsLogger() {
return new MetricsLogger();
-
- }
-
- @Singleton
- @Provides
- public AccessibilityManagerWrapper provideAccessibilityManagerWrapper(Context context) {
- return new AccessibilityManagerWrapper(context);
-
- }
-
- @Singleton
- @Provides
- // Creating a new instance will trigger color extraction.
- // Thankfully this only happens once - during boot - and WallpaperManagerService
- // loads colors from cache.
- public SysuiColorExtractor provideSysuiColorExtractor(Context context) {
- return new SysuiColorExtractor(context);
-
- }
-
- @Singleton
- @Provides
- public TunablePadding.TunablePaddingService provideTunablePaddingService() {
- return new TunablePaddingService();
-
- }
-
- @Singleton
- @Provides
- public ForegroundServiceController provideForegroundService(Context context) {
- return new ForegroundServiceControllerImpl(context);
-
- }
-
- @Singleton
- @Provides
- public UiOffloadThread provideUiOffloadThread() {
- return new UiOffloadThread();
- }
-
- @Singleton
- @Provides
- public PowerUI.WarningsUI provideWarningsUi(Context context) {
- return new PowerNotificationWarnings(context);
- }
-
- @Singleton
- @Provides
- public IconLogger provideIconLogger(Context context, @Named(BG_LOOPER_NAME) Looper bgLooper,
- MetricsLogger logger) {
- return new IconLoggerImpl(context, bgLooper, logger);
- }
-
- @Singleton
- @Provides
- public LightBarController provideLightBarController(Context context) {
- return new LightBarController(context);
}
@Singleton
@@ -499,19 +124,6 @@ public class DependencyProvider {
@Singleton
@Provides
- public OverviewProxyService provideOverviewProxyService(Context context) {
- return new OverviewProxyService(context);
- }
-
- @Singleton
- @Provides
- public VibratorHelper provideVibratorHelper(Context context) {
- return new VibratorHelper(context);
-
- }
-
- @Singleton
- @Provides
public IStatusBarService provideIStatusBarService() {
return IStatusBarService.Stub.asInterface(
ServiceManager.getService(Context.STATUS_BAR_SERVICE));
@@ -520,50 +132,45 @@ public class DependencyProvider {
@Singleton
@Provides
// Single instance of DisplayMetrics, gets updated by StatusBar, but can be used
-// anywhere it is needed.
+ // anywhere it is needed.
public DisplayMetrics provideDisplayMetrics() {
return new DisplayMetrics();
-
}
@Singleton
@Provides
- public LockscreenGestureLogger provideLockscreenGestureLogger() {
- return new LockscreenGestureLogger();
+ public ShadeController provideShadeController(Context context) {
+ return SysUiServiceProvider.getComponent(context, StatusBar.class);
}
@Singleton
@Provides
- public ShadeController provideShadeController(Context context) {
- return SysUiServiceProvider.getComponent(context, StatusBar.class);
+ public SensorPrivacyManager provideSensorPrivacyManager(Context context) {
+ return context.getSystemService(SensorPrivacyManager.class);
}
@Singleton
@Provides
- public NotificationRemoteInputManager.Callback provideNotificationRemoteInputManager(
- Context context) {
- return new StatusBarRemoteInputCallback(context);
+ public LeakDetector provideLeakDetector() {
+ return LeakDetector.create();
}
@Singleton
@Provides
- public AppOpsController provideAppOpsController(Context context,
- @Named(BG_LOOPER_NAME) Looper bgLooper) {
- return new AppOpsControllerImpl(context, bgLooper);
-
+ public ColorDisplayController provideColorDisplayController(Context context) {
+ return new ColorDisplayController(context);
}
@Singleton
@Provides
- public DisplayNavigationBarController provideDisplayNavigationBarController(Context context,
- @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
- return new DisplayNavigationBarController(context, mainHandler);
+ public PluginManager providePluginManager(Context context) {
+ return new PluginManagerImpl(context, new PluginInitializerImpl());
}
@Singleton
@Provides
- public SensorPrivacyManager provideSensorPrivacyManager(Context context) {
- return context.getSystemService(SensorPrivacyManager.class);
+ public ConfigurationController provideConfigurationController(Context context) {
+ return new ConfigurationControllerImpl(context);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java
index bab472c2e687..ae446ddc91ab 100644
--- a/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java
@@ -29,9 +29,13 @@ import com.android.internal.messages.nano.SystemMessageProto;
import java.util.Arrays;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Foreground service controller, a/k/a Dianne's Dungeon.
*/
+@Singleton
public class ForegroundServiceControllerImpl
implements ForegroundServiceController {
@@ -45,6 +49,7 @@ public class ForegroundServiceControllerImpl
private final SparseArray<UserServices> mUserServices = new SparseArray<>();
private final Object mMutex = new Object();
+ @Inject
public ForegroundServiceControllerImpl(Context context) {
mContext = context;
}
diff --git a/packages/SystemUI/src/com/android/systemui/InitController.java b/packages/SystemUI/src/com/android/systemui/InitController.java
index 81d32517b27a..a2dd12389fa9 100644
--- a/packages/SystemUI/src/com/android/systemui/InitController.java
+++ b/packages/SystemUI/src/com/android/systemui/InitController.java
@@ -16,10 +16,14 @@ package com.android.systemui;
import java.util.ArrayList;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Created by {@link Dependency} on SystemUI startup. Add tasks which need to be executed only
* after all other dependencies have been created.
*/
+@Singleton
public class InitController {
/**
@@ -29,6 +33,10 @@ public class InitController {
private final ArrayList<Runnable> mTasks = new ArrayList<>();
+ @Inject
+ public InitController() {
+ }
+
/**
* Add a task to be executed after {@link Dependency#start()}
* @param runnable the task to be executed
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 384a14c70e9c..8bac7c590249 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -221,7 +221,8 @@ public class SystemUIFactory {
}
@Singleton
- @Component(modules = {SystemUIFactory.class, DependencyProvider.class, ContextHolder.class})
+ @Component(modules = {SystemUIFactory.class, DependencyProvider.class, DependencyBinder.class,
+ ContextHolder.class})
public interface SystemUIRootComponent {
@Singleton
Dependency.DependencyInjector createDependency();
diff --git a/packages/SystemUI/src/com/android/systemui/UiOffloadThread.java b/packages/SystemUI/src/com/android/systemui/UiOffloadThread.java
index 82fd9b304195..a726b42f714f 100644
--- a/packages/SystemUI/src/com/android/systemui/UiOffloadThread.java
+++ b/packages/SystemUI/src/com/android/systemui/UiOffloadThread.java
@@ -20,14 +20,22 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Thread that offloads work from the UI thread but that is still perceptible to the user, so the
* priority is the same as the main thread.
*/
+@Singleton
public class UiOffloadThread {
private final ExecutorService mExecutorService = Executors.newSingleThreadExecutor();
+ @Inject
+ public UiOffloadThread() {
+ }
+
public Future<?> submit(Runnable runnable) {
return mExecutorService.submit(runnable);
}
diff --git a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
index 52d1260b4221..e3bcb37474db 100644
--- a/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/appops/AppOpsControllerImpl.java
@@ -16,6 +16,8 @@
package com.android.systemui.appops;
+import static com.android.systemui.Dependency.BG_LOOPER_NAME;
+
import android.app.AppOpsManager;
import android.content.Context;
import android.os.Handler;
@@ -32,12 +34,17 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Set;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
/**
* Controller to keep track of applications that have requested access to given App Ops
*
* It can be subscribed to with callbacks. Additionally, it passes on the information to
* NotificationPresenter to be displayed to the user.
*/
+@Singleton
public class AppOpsControllerImpl implements AppOpsController,
AppOpsManager.OnOpActiveChangedListener,
AppOpsManager.OnOpNotedListener {
@@ -57,23 +64,16 @@ public class AppOpsControllerImpl implements AppOpsController,
@GuardedBy("mNotedItems")
private final List<AppOpItem> mNotedItems = new ArrayList<>();
- protected static final int[] OPS;
- protected static final String[] OPS_STRING = new String[] {
- AppOpsManager.OPSTR_CAMERA,
- AppOpsManager.OPSTR_SYSTEM_ALERT_WINDOW,
- AppOpsManager.OPSTR_RECORD_AUDIO,
- AppOpsManager.OPSTR_COARSE_LOCATION,
- AppOpsManager.OPSTR_FINE_LOCATION};
-
- static {
- int numOps = OPS_STRING.length;
- OPS = new int[numOps];
- for (int i = 0; i < numOps; i++) {
- OPS[i] = AppOpsManager.strOpToOp(OPS_STRING[i]);
- }
- }
+ protected static final int[] OPS = new int[] {
+ AppOpsManager.OP_CAMERA,
+ AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
+ AppOpsManager.OP_RECORD_AUDIO,
+ AppOpsManager.OP_COARSE_LOCATION,
+ AppOpsManager.OP_FINE_LOCATION
+ };
- public AppOpsControllerImpl(Context context, Looper bgLooper) {
+ @Inject
+ public AppOpsControllerImpl(Context context, @Named(BG_LOOPER_NAME) Looper bgLooper) {
mContext = context;
mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
mBGHandler = new H(bgLooper);
@@ -92,7 +92,7 @@ public class AppOpsControllerImpl implements AppOpsController,
protected void setListening(boolean listening) {
if (listening) {
mAppOps.startWatchingActive(OPS, this);
- mAppOps.startWatchingNoted(OPS_STRING, this);
+ mAppOps.startWatchingNoted(OPS, this);
} else {
mAppOps.stopWatchingActive(this);
mAppOps.stopWatchingNoted(this);
@@ -254,14 +254,13 @@ public class AppOpsControllerImpl implements AppOpsController,
}
@Override
- public void onOpNoted(String code, int uid, String packageName, int result) {
+ public void onOpNoted(int code, int uid, String packageName, int result) {
if (DEBUG) {
Log.w(TAG, "Op: " + code + " with result " + AppOpsManager.MODE_NAMES[result]);
}
if (result != AppOpsManager.MODE_ALLOWED) return;
- int op_code = AppOpsManager.strOpToOp(code);
- addNoted(op_code, uid, packageName);
- notifySuscribers(op_code, uid, packageName, true);
+ addNoted(code, uid, packageName);
+ notifySuscribers(code, uid, packageName, true);
}
private void notifySuscribers(int code, int uid, String packageName, boolean active) {
diff --git a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
index 3c8a461d3f73..fdf18ce24f50 100644
--- a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
+++ b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
@@ -39,9 +39,13 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Arrays;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* ColorExtractor aware of wallpaper visibility
*/
+@Singleton
public class SysuiColorExtractor extends ColorExtractor implements Dumpable {
private static final String TAG = "SysuiColorExtractor";
private boolean mWallpaperVisible;
@@ -49,6 +53,7 @@ public class SysuiColorExtractor extends ColorExtractor implements Dumpable {
// Colors to return when the wallpaper isn't visible
private final GradientColors mWpHiddenColors;
+ @Inject
public SysuiColorExtractor(Context context) {
this(context, new Tonal(context), true);
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 201c7e69beaf..9a8a6d0c3c3a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -41,6 +41,8 @@ import androidx.slice.builders.ListBuilder.RowBuilder;
import androidx.slice.builders.SliceAction;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.systemui.R;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.NextAlarmControllerImpl;
@@ -49,6 +51,7 @@ import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
import java.util.Date;
import java.util.Locale;
+import java.util.TimeZone;
import java.util.concurrent.TimeUnit;
/**
@@ -100,21 +103,28 @@ public class KeyguardSliceProvider extends SliceProvider implements
@Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
- if (Intent.ACTION_TIME_TICK.equals(action)
- || Intent.ACTION_DATE_CHANGED.equals(action)
- || Intent.ACTION_TIME_CHANGED.equals(action)
- || Intent.ACTION_TIMEZONE_CHANGED.equals(action)
- || Intent.ACTION_LOCALE_CHANGED.equals(action)) {
- if (Intent.ACTION_LOCALE_CHANGED.equals(action)
- || Intent.ACTION_TIMEZONE_CHANGED.equals(action)) {
- // need to get a fresh date format
- mHandler.post(KeyguardSliceProvider.this::cleanDateFormat);
- }
+ if (Intent.ACTION_DATE_CHANGED.equals(action)) {
mHandler.post(KeyguardSliceProvider.this::updateClock);
+ } else if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {
+ mHandler.post(KeyguardSliceProvider.this::cleanDateFormat);
}
}
};
+ @VisibleForTesting
+ final KeyguardUpdateMonitorCallback mKeyguardUpdateMonitorCallback =
+ new KeyguardUpdateMonitorCallback() {
+ @Override
+ public void onTimeChanged() {
+ mHandler.post(KeyguardSliceProvider.this::updateClock);
+ }
+
+ @Override
+ public void onTimeZoneChanged(TimeZone timeZone) {
+ mHandler.post(KeyguardSliceProvider.this::cleanDateFormat);
+ }
+ };
+
public KeyguardSliceProvider() {
this(new Handler());
}
@@ -250,11 +260,10 @@ public class KeyguardSliceProvider extends SliceProvider implements
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_DATE_CHANGED);
- filter.addAction(Intent.ACTION_TIME_CHANGED);
- filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
filter.addAction(Intent.ACTION_LOCALE_CHANGED);
getContext().registerReceiver(mIntentReceiver, filter, null /* permission*/,
null /* scheduler */);
+ getKeyguardUpdateMonitor().registerCallback(mKeyguardUpdateMonitorCallback);
mRegistered = true;
}
@@ -300,4 +309,9 @@ public class KeyguardSliceProvider extends SliceProvider implements
}
updateNextAlarm();
}
+
+ @VisibleForTesting
+ protected KeyguardUpdateMonitor getKeyguardUpdateMonitor() {
+ return KeyguardUpdateMonitor.getInstance(getContext());
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ScreenLifecycle.java b/packages/SystemUI/src/com/android/systemui/keyguard/ScreenLifecycle.java
index b6fce4408bcf..834bca55103a 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ScreenLifecycle.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ScreenLifecycle.java
@@ -23,9 +23,13 @@ import com.android.systemui.Dumpable;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Tracks the screen lifecycle.
*/
+@Singleton
public class ScreenLifecycle extends Lifecycle<ScreenLifecycle.Observer> implements Dumpable {
public static final int SCREEN_OFF = 0;
@@ -35,6 +39,10 @@ public class ScreenLifecycle extends Lifecycle<ScreenLifecycle.Observer> impleme
private int mScreenState = SCREEN_OFF;
+ @Inject
+ public ScreenLifecycle() {
+ }
+
public int getScreenState() {
return mScreenState;
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java b/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java
index 59c7f236caf7..52a0214c492c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java
@@ -23,9 +23,13 @@ import com.android.systemui.Dumpable;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Tracks the wakefulness lifecycle.
*/
+@Singleton
public class WakefulnessLifecycle extends Lifecycle<WakefulnessLifecycle.Observer> implements
Dumpable {
@@ -36,6 +40,10 @@ public class WakefulnessLifecycle extends Lifecycle<WakefulnessLifecycle.Observe
private int mWakefulness = WAKEFULNESS_ASLEEP;
+ @Inject
+ public WakefulnessLifecycle() {
+ }
+
public int getWakefulness() {
return mWakefulness;
}
diff --git a/packages/SystemUI/src/com/android/systemui/plugins/PluginDependencyProvider.java b/packages/SystemUI/src/com/android/systemui/plugins/PluginDependencyProvider.java
index 03daa95567ee..69495319e060 100644
--- a/packages/SystemUI/src/com/android/systemui/plugins/PluginDependencyProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/plugins/PluginDependencyProvider.java
@@ -20,11 +20,20 @@ import com.android.systemui.Dependency;
import com.android.systemui.plugins.PluginDependency.DependencyProvider;
import com.android.systemui.shared.plugins.PluginManager;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ */
+@Singleton
public class PluginDependencyProvider extends DependencyProvider {
private final ArrayMap<Class<?>, Object> mDependencies = new ArrayMap<>();
private final PluginManager mManager;
+ /**
+ */
+ @Inject
public PluginDependencyProvider(PluginManager manager) {
mManager = manager;
PluginDependency.sProvider = this;
diff --git a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
index b722f9f1d1c1..50dda1c1de6b 100644
--- a/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
+++ b/packages/SystemUI/src/com/android/systemui/power/PowerNotificationWarnings.java
@@ -58,6 +58,12 @@ import java.text.NumberFormat;
import java.util.Locale;
import java.util.Objects;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ */
+@Singleton
public class PowerNotificationWarnings implements PowerUI.WarningsUI {
private static final String TAG = PowerUI.TAG + ".Notification";
private static final boolean DEBUG = PowerUI.DEBUG;
@@ -136,6 +142,9 @@ public class PowerNotificationWarnings implements PowerUI.WarningsUI {
private SystemUIDialog mHighTempDialog;
private SystemUIDialog mThermalShutdownDialog;
+ /**
+ */
+ @Inject
public PowerNotificationWarnings(Context context) {
mContext = context;
mNoMan = mContext.getSystemService(NotificationManager.class);
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
index bbdae291d81e..3991c19e4d05 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/OngoingPrivacyDialog.kt
@@ -106,12 +106,12 @@ class OngoingPrivacyDialog constructor(
val appName = item.findViewById(R.id.app_name) as TextView
val icons = item.findViewById(R.id.icons) as LinearLayout
- var lp = LinearLayout.LayoutParams(iconSize, iconSize).apply {
+ val lp = LinearLayout.LayoutParams(iconSize, iconSize).apply {
gravity = Gravity.CENTER_VERTICAL
marginStart = iconMargin
}
- app.icon?.let {
+ app.icon.let {
appIcon.setImageDrawable(it)
}
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt
index 519df19f0e20..2894621e7775 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialogBuilder.kt
@@ -29,7 +29,9 @@ class PrivacyDialogBuilder(val context: Context, itemsList: List<PrivacyItem>) {
init {
appsAndTypes = itemsList.groupBy({ it.application }, { it.privacyType })
.toList()
- .sortedWith(compareBy({ -it.second.size }, { it.first }))
+ .sortedWith(compareBy({ -it.second.size }, // Sort by number of AppOps
+ { it.second.min() }, // Sort by "smallest" AppOpp (Location is largest)
+ { it.first })) // Sort alphabetically bt App Name
types = itemsList.map { it.privacyType }.distinct().sorted()
val singleApp = appsAndTypes.size == 1
app = if (singleApp) appsAndTypes[0].first else null
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
index 85e99f05f895..9252167d02bd 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItem.kt
@@ -24,8 +24,8 @@ typealias Privacy = PrivacyType
enum class PrivacyType(val nameId: Int, val iconId: Int) {
TYPE_CAMERA(R.string.privacy_type_camera, R.drawable.stat_sys_camera),
- TYPE_LOCATION(R.string.privacy_type_location, R.drawable.stat_sys_location),
- TYPE_MICROPHONE(R.string.privacy_type_microphone, R.drawable.stat_sys_mic_none);
+ TYPE_MICROPHONE(R.string.privacy_type_microphone, R.drawable.stat_sys_mic_none),
+ TYPE_LOCATION(R.string.privacy_type_location, R.drawable.stat_sys_location);
fun getName(context: Context) = context.resources.getString(nameId)
@@ -44,7 +44,7 @@ data class PrivacyApplication(val packageName: String, val context: Context)
return applicationName.compareTo(other.applicationName)
}
- var icon: Drawable? = null
+ var icon: Drawable = context.getDrawable(android.R.drawable.sym_def_app_icon)
var applicationName: String
init {
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
index a87d634451cd..d5b807def21f 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyItemController.kt
@@ -29,6 +29,7 @@ import com.android.internal.annotations.VisibleForTesting
import com.android.systemui.Dependency
import com.android.systemui.appops.AppOpItem
import com.android.systemui.appops.AppOpsController
+import com.android.systemui.R
class PrivacyItemController(val context: Context, val callback: Callback) {
@@ -41,15 +42,17 @@ class PrivacyItemController(val context: Context, val callback: Callback) {
Intent.ACTION_MANAGED_PROFILE_ADDED,
Intent.ACTION_MANAGED_PROFILE_REMOVED)
const val TAG = "PrivacyItemController"
+ const val SYSTEM_UID = 1000
}
-
private var privacyList = emptyList<PrivacyItem>()
+
private val appOpsController = Dependency.get(AppOpsController::class.java)
private val userManager = context.getSystemService(UserManager::class.java)
private var currentUserIds = emptyList<Int>()
private val bgHandler = Handler(Dependency.get(Dependency.BG_LOOPER))
private val uiHandler = Dependency.get(Dependency.MAIN_HANDLER)
private var listening = false
+ val systemApp = PrivacyApplication(context.getString(R.string.device_services), context)
private val notifyChanges = Runnable {
callback.privacyChanged(privacyList)
@@ -126,6 +129,7 @@ class PrivacyItemController(val context: Context, val callback: Callback) {
AppOpsManager.OP_RECORD_AUDIO -> PrivacyType.TYPE_MICROPHONE
else -> return null
}
+ if (appOpItem.uid == SYSTEM_UID) return PrivacyItem(type, systemApp)
val app = PrivacyApplication(appOpItem.packageName, context)
return PrivacyItem(type, app)
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
index 8903a38dc600..aba9bb804619 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooterImpl.java
@@ -272,10 +272,17 @@ public class QSFooterImpl extends FrameLayout implements QSFooter,
public void updateEverything() {
post(() -> {
updateVisibilities();
+ updateClickabilities();
setClickable(false);
});
}
+ private void updateClickabilities() {
+ mMultiUserSwitch.setClickable(mMultiUserSwitch.getVisibility() == View.VISIBLE);
+ mEdit.setClickable(mEdit.getVisibility() == View.VISIBLE);
+ mSettingsButton.setClickable(mSettingsButton.getVisibility() == View.VISIBLE);
+ }
+
private void updateVisibilities() {
mSettingsContainer.setVisibility(mQsDisabled ? View.GONE : View.VISIBLE);
mSettingsContainer.findViewById(R.id.tuner_icon).setVisibility(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index f2f83c0e0aa5..bec027f902a0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -426,7 +426,6 @@ public class QuickStatusBarHeader extends RelativeLayout implements
if (mExpanded == expanded) return;
mExpanded = expanded;
mHeaderQsPanel.setExpanded(expanded);
- updateEverything();
}
/**
@@ -698,10 +697,6 @@ public class QuickStatusBarHeader extends RelativeLayout implements
.start();
}
- public void updateEverything() {
- post(() -> setClickable(false));
- }
-
public void setQSPanel(final QSPanel qsPanel) {
mQsPanel = qsPanel;
setupHost(qsPanel.getHost());
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 12b6f673de1c..538e0f0de415 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -63,9 +63,13 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Class to send information from overview to launcher with a binder.
*/
+@Singleton
public class OverviewProxyService implements CallbackController<OverviewProxyListener>, Dumpable {
private static final String ACTION_QUICKSTEP = "android.intent.action.QUICKSTEP_SERVICE";
@@ -338,6 +342,7 @@ public class OverviewProxyService implements CallbackController<OverviewProxyLis
private final IBinder.DeathRecipient mOverviewServiceDeathRcpt
= this::cleanupAfterDeath;
+ @Inject
public OverviewProxyService(Context context) {
mContext = context;
mHandler = new Handler();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DisplayNavigationBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/DisplayNavigationBarController.java
index 2f2610998b35..78172f19d291 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DisplayNavigationBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DisplayNavigationBarController.java
@@ -18,6 +18,8 @@ package com.android.systemui.statusbar;
import static android.view.Display.DEFAULT_DISPLAY;
+import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
+
import android.content.Context;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
@@ -32,9 +34,14 @@ import android.view.WindowManagerGlobal;
import com.android.systemui.statusbar.phone.NavigationBarFragment;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
/**
* A controller to handle external navigation bars
*/
+@Singleton
public class DisplayNavigationBarController implements DisplayListener {
private static final String TAG = DisplayNavigationBarController.class.getName();
@@ -46,7 +53,9 @@ public class DisplayNavigationBarController implements DisplayListener {
/** A displayId - nav bar mapping */
private SparseArray<NavigationBarFragment> mExternalNavigationBarMap = new SparseArray<>();
- public DisplayNavigationBarController(Context context, Handler handler) {
+ @Inject
+ public DisplayNavigationBarController(Context context,
+ @Named(MAIN_HANDLER_NAME) Handler handler) {
mContext = context;
mHandler = handler;
mDisplayManager = (DisplayManager) mContext.getSystemService(Context.DISPLAY_SERVICE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 7d1b640f7e40..158430f9ff92 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -19,10 +19,7 @@ package com.android.systemui.statusbar;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.app.admin.DevicePolicyManager;
-import android.content.BroadcastReceiver;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Color;
@@ -35,7 +32,6 @@ import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.UserHandle;
import android.os.UserManager;
import android.text.TextUtils;
import android.text.format.Formatter;
@@ -152,10 +148,7 @@ public class KeyguardIndicationController implements StateListener {
private void registerCallbacks(KeyguardUpdateMonitor monitor) {
monitor.registerCallback(getKeyguardCallback());
- mContext.registerReceiverAsUser(mTickReceiver, UserHandle.SYSTEM,
- new IntentFilter(Intent.ACTION_TIME_TICK), null,
- Dependency.get(Dependency.TIME_TICK_HANDLER));
-
+ KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mTickReceiver);
Dependency.get(StatusBarStateController.class).addCallback(this);
}
@@ -166,7 +159,7 @@ public class KeyguardIndicationController implements StateListener {
* //TODO: This can probably be converted to a fragment and not have to be manually recreated
*/
public void destroy() {
- mContext.unregisterReceiver(mTickReceiver);
+ KeyguardUpdateMonitor.getInstance(mContext).removeCallback(mTickReceiver);
Dependency.get(StatusBarStateController.class).removeCallback(this);
}
@@ -477,16 +470,15 @@ public class KeyguardIndicationController implements StateListener {
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
}
- private final BroadcastReceiver mTickReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- mHandler.post(() -> {
- if (mVisible) {
- updateIndication(false);
+ private final KeyguardUpdateMonitorCallback mTickReceiver =
+ new KeyguardUpdateMonitorCallback() {
+ @Override
+ public void onTimeChanged() {
+ if (mVisible) {
+ updateIndication(false /* animate */);
+ }
}
- });
- }
- };
+ };
private final Handler mHandler = new Handler() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java
index 6560f8f9c420..442416fd3bea 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/VibratorHelper.java
@@ -26,6 +26,12 @@ import android.os.VibrationEffect;
import android.os.Vibrator;
import android.provider.Settings;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ */
+@Singleton
public class VibratorHelper {
private final Vibrator mVibrator;
@@ -44,6 +50,9 @@ public class VibratorHelper {
}
};
+ /**
+ */
+ @Inject
public VibratorHelper(Context context) {
mContext = context;
mVibrator = context.getSystemService(Vibrator.class);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
index f899863dcc6b..e1b231b96693 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
@@ -28,12 +28,12 @@ import android.view.IRemoteAnimationFinishedCallback;
import android.view.IRemoteAnimationRunner;
import android.view.RemoteAnimationAdapter;
import android.view.RemoteAnimationTarget;
+import android.view.SyncRtSurfaceTransactionApplier;
+import android.view.SyncRtSurfaceTransactionApplier.SurfaceParams;
import com.android.internal.policy.ScreenDecorationsUtils;
import com.android.systemui.Interpolators;
import com.android.systemui.shared.system.SurfaceControlCompat;
-import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier;
-import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplier.SurfaceParams;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
@@ -267,8 +267,8 @@ public class ActivityLaunchAnimator {
Matrix m = new Matrix();
m.postTranslate(0, (float) (mParams.top - app.position.y));
mWindowCrop.set(mParams.left, 0, mParams.right, mParams.getHeight());
- SurfaceParams params = new SurfaceParams(new SurfaceControlCompat(app.leash),
- 1f /* alpha */, m, mWindowCrop, app.prefixOrderIndex, mCornerRadius);
+ SurfaceParams params = new SurfaceParams(app.leash, 1f /* alpha */, m, mWindowCrop,
+ app.prefixOrderIndex, mCornerRadius);
mSyncRtTransactionApplier.scheduleApply(params);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java
index 5906dc29fa08..5b44a77454b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DarkIconDispatcherImpl.java
@@ -29,6 +29,12 @@ import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ */
+@Singleton
public class DarkIconDispatcherImpl implements DarkIconDispatcher {
private final LightBarTransitionsController mTransitionsController;
@@ -40,6 +46,9 @@ public class DarkIconDispatcherImpl implements DarkIconDispatcher {
private int mDarkModeIconColorSingleTone;
private int mLightModeIconColorSingleTone;
+ /**
+ */
+ @Inject
public DarkIconDispatcherImpl(Context context) {
mDarkModeIconColorSingleTone = context.getColor(R.color.dark_mode_icon_color_single_tone);
mLightModeIconColorSingleTone = context.getColor(R.color.light_mode_icon_color_single_tone);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index 7c30e48f171a..e156e770cb72 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -34,9 +34,13 @@ import com.android.systemui.statusbar.policy.DarkIconDispatcher;
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Controls how light status bar flag applies to the icons.
*/
+@Singleton
public class LightBarController implements BatteryController.BatteryStateChangeCallback, Dumpable {
private static final float NAV_BAR_INVERSION_SCRIM_ALPHA_THRESHOLD = 0.1f;
@@ -78,6 +82,7 @@ public class LightBarController implements BatteryController.BatteryStateChangeC
private final Context mContext;
+ @Inject
public LightBarController(Context ctx) {
mDarkModeColor = Color.valueOf(ctx.getColor(R.color.dark_mode_icon_color_single_tone));
mStatusBarIconController = Dependency.get(DarkIconDispatcher.class);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
index 7876aa5d89d0..dd07ec4c27dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.phone;
+import static com.android.systemui.statusbar.phone.NavBarTintController.DEFAULT_COLOR_ADAPT_TRANSITION_TIME;
import static com.android.systemui.statusbar.phone.NavBarTintController.MIN_COLOR_ADAPT_TRANSITION_TIME;
import static com.android.systemui.statusbar.phone.NavBarTintController.NAV_COLOR_TRANSITION_TIME_SETTING;
@@ -161,7 +162,7 @@ public class LightBarTransitionsController implements Dumpable, Callbacks,
public long getTintAnimationDuration() {
if (NavBarTintController.isEnabled(mContext)) {
return Math.max(Settings.Global.getInt(mContext.getContentResolver(),
- NAV_COLOR_TRANSITION_TIME_SETTING, DEFAULT_TINT_ANIMATION_DURATION),
+ NAV_COLOR_TRANSITION_TIME_SETTING, DEFAULT_COLOR_ADAPT_TRANSITION_TIME),
MIN_COLOR_ADAPT_TRANSITION_TIME);
}
return DEFAULT_TINT_ANIMATION_DURATION;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java
index 7621887b4170..12819535cfb6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenGestureLogger.java
@@ -25,16 +25,21 @@ import com.android.systemui.Dependency;
import com.android.systemui.EventLogConstants;
import com.android.systemui.EventLogTags;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Wrapper that emits both new- and old-style gesture logs.
* TODO: delete this once the old logs are no longer needed.
*/
+@Singleton
public class LockscreenGestureLogger {
private ArrayMap<Integer, Integer> mLegacyMap;
private LogMaker mLogMaker = new LogMaker(MetricsEvent.VIEW_UNKNOWN)
.setType(MetricsEvent.TYPE_ACTION);
private final MetricsLogger mMetricsLogger = Dependency.get(MetricsLogger.class);
+ @Inject
public LockscreenGestureLogger() {
mLegacyMap = new ArrayMap<>(EventLogConstants.METRICS_GESTURE_TYPE_MAP.length);
for (int i = 0; i < EventLogConstants.METRICS_GESTURE_TYPE_MAP.length ; i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java
index 0f8d59b12ddb..fbd8d8a76d26 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ManagedProfileControllerImpl.java
@@ -28,6 +28,12 @@ import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ */
+@Singleton
public class ManagedProfileControllerImpl implements ManagedProfileController {
private final List<Callback> mCallbacks = new ArrayList<>();
@@ -38,6 +44,9 @@ public class ManagedProfileControllerImpl implements ManagedProfileController {
private boolean mListening;
private int mCurrentUser;
+ /**
+ */
+ @Inject
public ManagedProfileControllerImpl(Context context) {
mContext = context;
mUserManager = UserManager.get(mContext);
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 9ecee1825f07..b4f850b033e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavBarTintController.java
@@ -31,6 +31,7 @@ import android.view.SurfaceControl;
public class NavBarTintController {
public static final String NAV_COLOR_TRANSITION_TIME_SETTING = "navbar_color_adapt_transition";
public static final int MIN_COLOR_ADAPT_TRANSITION_TIME = 400;
+ public static final int DEFAULT_COLOR_ADAPT_TRANSITION_TIME = 1500;
private final HandlerThread mColorAdaptHandlerThread = new HandlerThread("ColorExtractThread");
private Handler mColorAdaptionHandler;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index c7e4d340b7d8..c0909e3e5bd2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -53,6 +53,7 @@ import android.widget.FrameLayout;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.keyguard.KeyguardClockSwitch;
import com.android.keyguard.KeyguardStatusView;
import com.android.systemui.DejankUtils;
import com.android.systemui.Dependency;
@@ -133,7 +134,7 @@ public class NotificationPanelView extends PanelView implements
public static final int FLING_COLLAPSE = 1;
/**
- * Fing until QS is completely hidden.
+ * Fling until QS is completely hidden.
*/
public static final int FLING_HIDE = 2;
@@ -359,6 +360,10 @@ public class NotificationPanelView extends PanelView implements
mKeyguardStatusBar = findViewById(R.id.keyguard_header);
mKeyguardStatusView = findViewById(R.id.keyguard_status_view);
+ KeyguardClockSwitch keyguardClockSwitch = findViewById(R.id.keyguard_clock_container);
+ ViewGroup bigClockContainer = findViewById(R.id.big_clock_container);
+ keyguardClockSwitch.setBigClockContainer(bigClockContainer);
+
mNotificationContainerParent = findViewById(R.id.notification_container_parent);
mNotificationStackScroller = findViewById(R.id.notification_stack_scroller);
mNotificationStackScroller.setOnHeightChangedListener(this);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index ee1eb42a07f0..d6f2fd7a4eee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -85,7 +85,6 @@ import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceP
import com.android.systemui.statusbar.policy.HotspotController;
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.LocationController;
-import com.android.systemui.statusbar.policy.LocationController.LocationChangeCallback;
import com.android.systemui.statusbar.policy.NextAlarmController;
import com.android.systemui.statusbar.policy.RotationLockController;
import com.android.systemui.statusbar.policy.RotationLockController.RotationLockControllerCallback;
@@ -102,9 +101,8 @@ import java.util.Locale;
* strictly doesn't need to.
*/
public class PhoneStatusBarPolicy implements Callback, Callbacks,
- RotationLockControllerCallback, Listener, LocationChangeCallback,
- ZenModeController.Callback, DeviceProvisionedListener, KeyguardMonitor.Callback,
- PrivacyItemController.Callback {
+ RotationLockControllerCallback, Listener, ZenModeController.Callback,
+ DeviceProvisionedListener, KeyguardMonitor.Callback, PrivacyItemController.Callback {
private static final String TAG = "PhoneStatusBarPolicy";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -255,6 +253,9 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
mIconController.setIconVisibility(mSlotMicrophone, false);
mIconController.setIcon(mSlotCamera, R.drawable.stat_sys_camera, null);
mIconController.setIconVisibility(mSlotCamera, false);
+ mIconController.setIcon(mSlotLocation, LOCATION_STATUS_ICON_ID,
+ mContext.getString(R.string.accessibility_location_active));
+ mIconController.setIconVisibility(mSlotLocation, false);
mRotationLockController.addCallback(this);
mBluetooth.addCallback(this);
@@ -265,7 +266,6 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
mNextAlarmController.addCallback(mNextAlarmCallback);
mDataSaver.addCallback(this);
mKeyguardMonitor.addCallback(this);
- mLocationController.addCallback(this);
mPrivacyItemController.setListening(true);
SysUiServiceProvider.getComponent(mContext, CommandQueue.class).addCallback(this);
@@ -294,7 +294,6 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
mNextAlarmController.removeCallback(mNextAlarmCallback);
mDataSaver.removeCallback(this);
mKeyguardMonitor.removeCallback(this);
- mLocationController.removeCallback(this);
mPrivacyItemController.setListening(false);
SysUiServiceProvider.getComponent(mContext, CommandQueue.class).removeCallback(this);
mContext.unregisterReceiver(mIntentReceiver);
@@ -314,21 +313,6 @@ public class PhoneStatusBarPolicy implements Callback, Callbacks,
updateVolumeZen();
}
- @Override
- public void onLocationActiveChanged(boolean active) {
- updateLocation();
- }
-
- // Updates the status view based on the current state of location requests.
- private void updateLocation() {
- if (mLocationController.isLocationActive()) {
- mIconController.setIcon(mSlotLocation, LOCATION_STATUS_ICON_ID,
- mContext.getString(R.string.accessibility_location_active));
- } else {
- mIconController.removeAllIconsForSlot(mSlotLocation);
- }
- }
-
private void updateAlarm() {
final AlarmClockInfo alarm = mAlarmManager.getNextAlarmClock(UserHandle.USER_CURRENT);
final boolean hasAlarm = alarm != null && alarm.getTriggerTime() > 0;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
index 4f25349ef7d2..db7589d0f333 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconControllerImpl.java
@@ -45,11 +45,15 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Receives the callbacks from CommandQueue related to icons and tracks the state of
* all the icons. Dispatches this state to any IconManagers that are currently
* registered with it.
*/
+@Singleton
public class StatusBarIconControllerImpl extends StatusBarIconList implements Tunable,
ConfigurationListener, Dumpable, CommandQueue.Callbacks, StatusBarIconController {
@@ -66,6 +70,7 @@ public class StatusBarIconControllerImpl extends StatusBarIconList implements Tu
private boolean mIsDark = false;
+ @Inject
public StatusBarIconControllerImpl(Context context) {
super(context.getResources().getStringArray(
com.android.internal.R.array.config_statusBarIcons));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
index 78f537459d0a..116ecc8ddeb5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarRemoteInputCallback.java
@@ -47,6 +47,12 @@ import com.android.systemui.statusbar.notification.stack.NotificationStackScroll
import com.android.systemui.statusbar.policy.KeyguardMonitor;
import com.android.systemui.statusbar.policy.PreviewInflater;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ */
+@Singleton
public class StatusBarRemoteInputCallback implements Callback, Callbacks {
private final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
@@ -65,6 +71,9 @@ public class StatusBarRemoteInputCallback implements Callback, Callbacks {
private int mDisabled2;
protected BroadcastReceiver mChallengeReceiver = new ChallengeReceiver();
+ /**
+ */
+ @Inject
public StatusBarRemoteInputCallback(Context context) {
mContext = context;
mContext.registerReceiverAsUser(mChallengeReceiver, UserHandle.ALL,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index cb6e30070fdd..88f904882c8f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -54,9 +54,13 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.reflect.Field;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Encapsulates all logic for the status bar window state management.
*/
+@Singleton
public class StatusBarWindowController implements Callback, Dumpable, ConfigurationListener {
private static final String TAG = "StatusBarWindowController";
@@ -78,6 +82,7 @@ public class StatusBarWindowController implements Callback, Dumpable, Configurat
private final SysuiColorExtractor mColorExtractor = Dependency.get(SysuiColorExtractor.class);
+ @Inject
public StatusBarWindowController(Context context) {
this(context, context.getSystemService(WindowManager.class), ActivityManager.getService(),
DozeParameters.getInstance(context));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityController.java
index cc431dd3c34a..ebfdb3f9aa76 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityController.java
@@ -23,6 +23,12 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ */
+@Singleton
public class AccessibilityController implements
AccessibilityManager.AccessibilityStateChangeListener,
AccessibilityManager.TouchExplorationStateChangeListener {
@@ -32,6 +38,9 @@ public class AccessibilityController implements
private boolean mAccessibilityEnabled;
private boolean mTouchExplorationEnabled;
+ /**
+ */
+ @Inject
public AccessibilityController(Context context) {
AccessibilityManager am =
(AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java
index 67da8a54b68a..1395e1377529 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/AccessibilityManagerWrapper.java
@@ -19,14 +19,19 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* For mocking because AccessibilityManager is final for some reason...
*/
+@Singleton
public class AccessibilityManagerWrapper implements
CallbackController<AccessibilityServicesStateChangeListener> {
private final AccessibilityManager mAccessibilityManager;
+ @Inject
public AccessibilityManagerWrapper(Context context) {
mAccessibilityManager = context.getSystemService(AccessibilityManager.class);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
index ddcfbf6f3c31..5d61f4aa7fcb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BatteryControllerImpl.java
@@ -39,10 +39,14 @@ import java.io.PrintWriter;
import java.text.NumberFormat;
import java.util.ArrayList;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Default implementation of a {@link BatteryController}. This controller monitors for battery
* level change events that are broadcasted by the system.
*/
+@Singleton
public class BatteryControllerImpl extends BroadcastReceiver implements BatteryController {
private static final String TAG = "BatteryController";
@@ -68,6 +72,7 @@ public class BatteryControllerImpl extends BroadcastReceiver implements BatteryC
private Estimate mEstimate;
private long mLastEstimateTimestamp = -1;
+ @Inject
public BatteryControllerImpl(Context context) {
this(context, context.getSystemService(PowerManager.class));
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
index 6f64a563289e..c8550003d2f4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BluetoothControllerImpl.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.policy;
+import static com.android.systemui.Dependency.BG_LOOPER_NAME;
+
import android.app.ActivityManager;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
@@ -42,6 +44,13 @@ import java.util.Collection;
import java.util.List;
import java.util.WeakHashMap;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+/**
+ */
+@Singleton
public class BluetoothControllerImpl implements BluetoothController, BluetoothCallback,
CachedBluetoothDevice.Callback, LocalBluetoothProfileManager.ServiceListener {
private static final String TAG = "BluetoothController";
@@ -61,7 +70,10 @@ public class BluetoothControllerImpl implements BluetoothController, BluetoothCa
private final H mHandler = new H(Looper.getMainLooper());
private int mState;
- public BluetoothControllerImpl(Context context, Looper bgLooper) {
+ /**
+ */
+ @Inject
+ public BluetoothControllerImpl(Context context, @Named(BG_LOOPER_NAME) Looper bgLooper) {
mLocalBluetoothManager = Dependency.get(LocalBluetoothManager.class);
mBgHandler = new Handler(bgLooper);
if (mLocalBluetoothManager != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
index ccfe073d5cb8..c7d337ad46d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
@@ -44,8 +44,12 @@ import java.util.Objects;
import java.util.Set;
import java.util.UUID;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/** Platform implementation of the cast controller. **/
+@Singleton
public class CastControllerImpl implements CastController {
private static final String TAG = "CastController";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -63,6 +67,7 @@ public class CastControllerImpl implements CastController {
private boolean mCallbackRegistered;
private MediaProjectionInfo mProjection;
+ @Inject
public CastControllerImpl(Context context) {
mContext = context;
mMediaRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
index f2283a53a608..c995162c8bb1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
@@ -27,6 +27,12 @@ import com.android.systemui.settings.CurrentUserTracker;
import java.util.ArrayList;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ */
+@Singleton
public class DeviceProvisionedControllerImpl extends CurrentUserTracker implements
DeviceProvisionedController {
@@ -36,6 +42,9 @@ public class DeviceProvisionedControllerImpl extends CurrentUserTracker implemen
private final Uri mDeviceProvisionedUri;
private final Uri mUserSetupUri;
+ /**
+ */
+ @Inject
public DeviceProvisionedControllerImpl(Context context) {
super(context);
mContext = context;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java
index a6146a625193..2305db0dbf8d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ExtensionControllerImpl.java
@@ -34,6 +34,12 @@ import java.util.Comparator;
import java.util.function.Consumer;
import java.util.function.Supplier;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ */
+@Singleton
public class ExtensionControllerImpl implements ExtensionController {
public static final int SORT_ORDER_PLUGIN = 0;
@@ -44,6 +50,9 @@ public class ExtensionControllerImpl implements ExtensionController {
private final Context mDefaultContext;
+ /**
+ */
+ @Inject
public ExtensionControllerImpl(Context context) {
mDefaultContext = context;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
index e23ce2d022b3..41ff9d1029b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/FlashlightControllerImpl.java
@@ -35,9 +35,13 @@ import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Manages the flashlight.
*/
+@Singleton
public class FlashlightControllerImpl implements FlashlightController {
private static final String TAG = "FlashlightController";
@@ -64,6 +68,7 @@ public class FlashlightControllerImpl implements FlashlightController {
private String mCameraId;
private boolean mTorchAvailable;
+ @Inject
public FlashlightControllerImpl(Context context) {
mContext = context;
mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
index 0a72c3f9e8d8..420abe88f455 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -29,6 +29,12 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ */
+@Singleton
public class HotspotControllerImpl implements HotspotController, WifiManager.SoftApCallback {
private static final String TAG = "HotspotController";
@@ -43,6 +49,9 @@ public class HotspotControllerImpl implements HotspotController, WifiManager.Sof
private int mNumConnectedDevices;
private boolean mWaitingForTerminalState;
+ /**
+ */
+ @Inject
public HotspotControllerImpl(Context context) {
mContext = context;
mConnectivityManager =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLoggerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLoggerImpl.java
index aee021ce4688..ba6369e2c90e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLoggerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/IconLoggerImpl.java
@@ -18,6 +18,7 @@ import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.FIELD_STATUS_ICONS;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.STATUS_BAR_ICONS_CHANGED;
import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.TYPE_ACTION;
+import static com.android.systemui.Dependency.BG_LOOPER_NAME;
import android.content.Context;
import android.metrics.LogMaker;
@@ -32,6 +33,9 @@ import com.android.internal.logging.MetricsLogger;
import java.util.Arrays;
import java.util.List;
+import javax.inject.Inject;
+import javax.inject.Named;
+
public class IconLoggerImpl implements IconLogger {
// Minimum ms between log statements.
@@ -46,7 +50,9 @@ public class IconLoggerImpl implements IconLogger {
private final List<String> mIconIndex;
private long mLastLog = System.currentTimeMillis();
- public IconLoggerImpl(Context context, Looper bgLooper, MetricsLogger logger) {
+ @Inject
+ public IconLoggerImpl(Context context, @Named(BG_LOOPER_NAME) Looper bgLooper,
+ MetricsLogger logger) {
mContext = context;
mHandler = new Handler(bgLooper);
mLogger = logger;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
index 5eb0fb76794d..3c8ed6ebf279 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
@@ -25,6 +25,12 @@ import com.android.systemui.settings.CurrentUserTracker;
import java.util.ArrayList;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ */
+@Singleton
public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback
implements KeyguardMonitor {
@@ -47,6 +53,9 @@ public class KeyguardMonitorImpl extends KeyguardUpdateMonitorCallback
private boolean mKeyguardGoingAway;
private boolean mLaunchTransitionFadingAway;
+ /**
+ */
+ @Inject
public KeyguardMonitorImpl(Context context) {
mContext = context;
mKeyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
index 840e77ea85a2..683cdbb326dc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/LocationControllerImpl.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.policy;
import static com.android.settingslib.Utils.updateLocationEnabled;
+import static com.android.systemui.Dependency.BG_LOOPER_NAME;
import android.app.ActivityManager;
import android.app.AppOpsManager;
@@ -40,9 +41,14 @@ import com.android.systemui.util.Utils;
import java.util.ArrayList;
import java.util.List;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
/**
* A controller to manage changes of location related states and update the views accordingly.
*/
+@Singleton
public class LocationControllerImpl extends BroadcastReceiver implements LocationController {
private static final int[] mHighPowerRequestAppOpArray
@@ -59,7 +65,8 @@ public class LocationControllerImpl extends BroadcastReceiver implements Locatio
new ArrayList<LocationChangeCallback>();
private final H mHandler = new H();
- public LocationControllerImpl(Context context, Looper bgLooper) {
+ @Inject
+ public LocationControllerImpl(Context context, @Named(BG_LOOPER_NAME) Looper bgLooper) {
mContext = context;
// Register to listen for changes in location settings.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index bc43120fcefa..9422101c76dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -22,6 +22,8 @@ import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_IN
import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_NONE;
import static android.net.wifi.WifiManager.TrafficStateCallback.DATA_ACTIVITY_OUT;
+import static com.android.systemui.Dependency.BG_LOOPER_NAME;
+
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -65,7 +67,6 @@ import com.android.systemui.statusbar.policy.MobileSignalController.MobileIconGr
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
import java.util.Comparator;
@@ -74,7 +75,12 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
/** Platform implementation of the network controller. **/
+@Singleton
public class NetworkControllerImpl extends BroadcastReceiver
implements NetworkController, DemoMode, DataUsageController.NetworkNameProvider,
ConfigurationChangedReceiver, Dumpable {
@@ -154,7 +160,8 @@ public class NetworkControllerImpl extends BroadcastReceiver
/**
* Construct this controller object and register for updates.
*/
- public NetworkControllerImpl(Context context, Looper bgLooper,
+ @Inject
+ public NetworkControllerImpl(Context context, @Named(BG_LOOPER_NAME) Looper bgLooper,
DeviceProvisionedController deviceProvisionedController) {
this(context, (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE),
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE),
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java
index dac878c69313..288b3aff2af6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NextAlarmControllerImpl.java
@@ -27,6 +27,13 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Implementation of {@link NextAlarmController}
+ */
+@Singleton
public class NextAlarmControllerImpl extends BroadcastReceiver
implements NextAlarmController {
@@ -35,6 +42,9 @@ public class NextAlarmControllerImpl extends BroadcastReceiver
private AlarmManager mAlarmManager;
private AlarmManager.AlarmClockInfo mNextAlarm;
+ /**
+ */
+ @Inject
public NextAlarmControllerImpl(Context context) {
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
IntentFilter filter = new IntentFilter();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java
index 5418dc14e0bb..1f368e164678 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RotationLockControllerImpl.java
@@ -23,7 +23,11 @@ import com.android.internal.view.RotationPolicy;
import java.util.concurrent.CopyOnWriteArrayList;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/** Platform implementation of the rotation lock controller. **/
+@Singleton
public final class RotationLockControllerImpl implements RotationLockController {
private final Context mContext;
private final CopyOnWriteArrayList<RotationLockControllerCallback> mCallbacks =
@@ -37,6 +41,7 @@ public final class RotationLockControllerImpl implements RotationLockController
}
};
+ @Inject
public RotationLockControllerImpl(Context context) {
mContext = context;
setListening(true);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
index 29a6b956ed1e..e0259c9f5af7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SecurityControllerImpl.java
@@ -55,6 +55,12 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ */
+@Singleton
public class SecurityControllerImpl extends CurrentUserTracker implements SecurityController {
private static final String TAG = "SecurityController";
@@ -90,6 +96,9 @@ public class SecurityControllerImpl extends CurrentUserTracker implements Securi
// Needs to be cached here since the query has to be asynchronous
private ArrayMap<Integer, Boolean> mHasCACerts = new ArrayMap<Integer, Boolean>();
+ /**
+ */
+ @Inject
public SecurityControllerImpl(Context context) {
this(context, null);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
index fed803217568..0ca6ff6ec66e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserInfoControllerImpl.java
@@ -40,6 +40,12 @@ import com.android.systemui.R;
import java.util.ArrayList;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ */
+@Singleton
public class UserInfoControllerImpl implements UserInfoController {
private static final String TAG = "UserInfoController";
@@ -53,6 +59,9 @@ public class UserInfoControllerImpl implements UserInfoController {
private Drawable mUserDrawable;
private String mUserAccount;
+ /**
+ */
+ @Inject
public UserInfoControllerImpl(Context context) {
mContext = context;
IntentFilter filter = new IntentFilter();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 15b2f2bcb755..e412e09fe519 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.policy;
import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
import android.app.ActivityManager;
import android.app.Dialog;
@@ -68,9 +69,14 @@ import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
/**
* Keeps a list of all users on the device for user switching.
*/
+@Singleton
public class UserSwitcherController implements Dumpable {
private static final String TAG = "UserSwitcherController";
@@ -102,8 +108,9 @@ public class UserSwitcherController implements Dumpable {
private Intent mSecondaryUserServiceIntent;
private SparseBooleanArray mForcePictureLoadForUserId = new SparseBooleanArray(2);
+ @Inject
public UserSwitcherController(Context context, KeyguardMonitor keyguardMonitor,
- Handler handler, ActivityStarter activityStarter) {
+ @Named(MAIN_HANDLER_NAME) Handler handler, ActivityStarter activityStarter) {
mContext = context;
mGuestResumeSessionReceiver.register(context);
mKeyguardMonitor = keyguardMonitor;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
index 89ccff03133d..7198165456c3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar.policy;
+import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
+
import android.app.ActivityManager;
import android.app.AlarmManager;
import android.app.NotificationManager;
@@ -48,7 +50,12 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Objects;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
/** Platform implementation of the zen mode controller. **/
+@Singleton
public class ZenModeControllerImpl extends CurrentUserTracker
implements ZenModeController, Dumpable {
private static final String TAG = "ZenModeController";
@@ -71,7 +78,8 @@ public class ZenModeControllerImpl extends CurrentUserTracker
private long mZenUpdateTime;
private NotificationManager.Policy mConsolidatedNotificationPolicy;
- public ZenModeControllerImpl(Context context, Handler handler) {
+ @Inject
+ public ZenModeControllerImpl(Context context, @Named(MAIN_HANDLER_NAME) Handler handler) {
super(context);
mContext = context;
mModeSetting = new GlobalSetting(mContext, handler, Global.ZEN_MODE) {
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java b/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java
index e85dee841715..81d77a64c1f0 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunablePadding.java
@@ -21,6 +21,9 @@ import android.view.WindowManager;
import com.android.systemui.Dependency;
import com.android.systemui.tuner.TunerService.Tunable;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Version of Space that can be resized by a tunable setting.
*/
@@ -69,8 +72,18 @@ public class TunablePadding implements Tunable {
Dependency.get(TunerService.class).removeTunable(this);
}
- // Exists for easy injecting in tests.
+ /**
+ * Exists for easy injecting in tests.
+ */
+ @Singleton
public static class TunablePaddingService {
+
+ /**
+ */
+ @Inject
+ public TunablePaddingService() {
+ }
+
public TunablePadding add(View view, String key, int defaultSize, int flags) {
if (view == null) {
throw new IllegalArgumentException();
diff --git a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
index 196d9bc32e75..0a47f19ac2f5 100644
--- a/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/tuner/TunerServiceImpl.java
@@ -43,7 +43,13 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ */
+@Singleton
public class TunerServiceImpl extends TunerService {
private static final String TUNER_VERSION = "sysui_tuner_version";
@@ -70,6 +76,9 @@ public class TunerServiceImpl extends TunerService {
private int mCurrentUser;
private CurrentUserTracker mUserTracker;
+ /**
+ */
+ @Inject
public TunerServiceImpl(Context context) {
mContext = context;
mContentResolver = mContext.getContentResolver();
diff --git a/packages/SystemUI/src/com/android/systemui/util/AsyncSensorManager.java b/packages/SystemUI/src/com/android/systemui/util/AsyncSensorManager.java
index 88cbbb574aff..31f4991a82b5 100644
--- a/packages/SystemUI/src/com/android/systemui/util/AsyncSensorManager.java
+++ b/packages/SystemUI/src/com/android/systemui/util/AsyncSensorManager.java
@@ -38,6 +38,9 @@ import com.android.systemui.shared.plugins.PluginManager;
import java.util.ArrayList;
import java.util.List;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Wrapper around sensor manager that hides potential sources of latency.
*
@@ -45,6 +48,7 @@ import java.util.List;
* without blocking. Note that this means registering listeners now always appears successful even
* if it is not.
*/
+@Singleton
public class AsyncSensorManager extends SensorManager
implements PluginListener<SensorManagerPlugin> {
@@ -56,8 +60,14 @@ public class AsyncSensorManager extends SensorManager
@VisibleForTesting final Handler mHandler;
private final List<SensorManagerPlugin> mPlugins;
- public AsyncSensorManager(SensorManager inner, PluginManager pluginManager) {
- mInner = inner;
+ @Inject
+ public AsyncSensorManager(Context context, PluginManager pluginManager) {
+ this(context.getSystemService(SensorManager.class), pluginManager);
+ }
+
+ @VisibleForTesting
+ AsyncSensorManager(SensorManager sensorManager, PluginManager pluginManager) {
+ mInner = sensorManager;
mHandlerThread.start();
mHandler = new Handler(mHandlerThread.getLooper());
mSensorCache = mInner.getSensorList(Sensor.TYPE_ALL);
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
index b2cc2694916e..7bc96261782d 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/GarbageMonitor.java
@@ -17,6 +17,7 @@
package com.android.systemui.util.leak;
import static com.android.internal.logging.MetricsLogger.VIEW_UNKNOWN;
+import static com.android.systemui.Dependency.BG_LOOPER_NAME;
import android.app.ActivityManager;
import android.content.Context;
@@ -51,6 +52,13 @@ import com.android.systemui.qs.tileimpl.QSTileImpl;
import java.util.ArrayList;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+/**
+ */
+@Singleton
public class GarbageMonitor {
private static final boolean LEAK_REPORTING_ENABLED =
Build.IS_DEBUGGABLE
@@ -85,9 +93,12 @@ public class GarbageMonitor {
private long mHeapLimit;
+ /**
+ */
+ @Inject
public GarbageMonitor(
Context context,
- Looper bgLooper,
+ @Named(BG_LOOPER_NAME) Looper bgLooper,
LeakDetector leakDetector,
LeakReporter leakReporter) {
mContext = context.getApplicationContext();
diff --git a/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java b/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java
index a47e99d1e84d..b25df5f9c07f 100644
--- a/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java
+++ b/packages/SystemUI/src/com/android/systemui/util/leak/LeakReporter.java
@@ -16,6 +16,9 @@
package com.android.systemui.util.leak;
+import static com.android.systemui.Dependency.LEAK_REPORT_EMAIL_NAME;
+
+import android.annotation.Nullable;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
@@ -39,9 +42,14 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
/**
* Dumps data to debug leaks and posts a notification to share the data.
*/
+@Singleton
public class LeakReporter {
static final String TAG = "LeakReporter";
@@ -56,7 +64,9 @@ public class LeakReporter {
private final LeakDetector mLeakDetector;
private final String mLeakReportEmail;
- public LeakReporter(Context context, LeakDetector leakDetector, String leakReportEmail) {
+ @Inject
+ public LeakReporter(Context context, LeakDetector leakDetector,
+ @Nullable @Named(LEAK_REPORT_EMAIL_NAME) String leakReportEmail) {
mContext = context;
mLeakDetector = leakDetector;
mLeakReportEmail = leakReportEmail;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
index e20e267336ea..a86970b90bff 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogControllerImpl.java
@@ -67,6 +67,9 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
/**
* Source of truth for all state / events related to the volume dialog. No presentation.
*
@@ -74,6 +77,7 @@ import java.util.Objects;
*
* Methods ending in "W" must be called on the worker thread.
*/
+@Singleton
public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpable {
private static final String TAG = Util.logTag(VolumeDialogControllerImpl.class);
@@ -131,6 +135,7 @@ public class VolumeDialogControllerImpl implements VolumeDialogController, Dumpa
protected final VC mVolumeController = new VC();
+ @Inject
public VolumeDialogControllerImpl(Context context) {
mContext = context.getApplicationContext();
mNotificationManager = (NotificationManager) mContext.getSystemService(
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
index fb2ceac4b810..415060244243 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchTest.java
@@ -107,6 +107,25 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
}
@Test
+ public void onPluginConnected_showPluginBigClock() {
+ // GIVEN that the container for the big clock has visibility GONE
+ FrameLayout bigClockContainer = new FrameLayout(getContext());
+ bigClockContainer.setVisibility(GONE);
+ mKeyguardClockSwitch.setBigClockContainer(bigClockContainer);
+ // AND the plugin returns a view for the big clock
+ ClockPlugin plugin = mock(ClockPlugin.class);
+ TextClock pluginView = new TextClock(getContext());
+ when(plugin.getBigClockView()).thenReturn(pluginView);
+ PluginListener listener = mKeyguardClockSwitch.getClockPluginListener();
+ // WHEN the plugin is connected
+ listener.onPluginConnected(plugin, null);
+ // THEN the big clock container is visible and it is the parent of the
+ // big clock view.
+ assertThat(bigClockContainer.getVisibility()).isEqualTo(VISIBLE);
+ assertThat(pluginView.getParent()).isEqualTo(bigClockContainer);
+ }
+
+ @Test
public void onPluginConnected_nullView() {
ClockPlugin plugin = mock(ClockPlugin.class);
PluginListener listener = mKeyguardClockSwitch.getClockPluginListener();
@@ -146,6 +165,26 @@ public class KeyguardClockSwitchTest extends SysuiTestCase {
}
@Test
+ public void onPluginDisconnected_hidePluginBigClock() {
+ // GIVEN that the big clock container is visible
+ FrameLayout bigClockContainer = new FrameLayout(getContext());
+ bigClockContainer.setVisibility(VISIBLE);
+ mKeyguardClockSwitch.setBigClockContainer(bigClockContainer);
+ // AND the plugin returns a view for the big clock
+ ClockPlugin plugin = mock(ClockPlugin.class);
+ TextClock pluginView = new TextClock(getContext());
+ when(plugin.getBigClockView()).thenReturn(pluginView);
+ PluginListener listener = mKeyguardClockSwitch.getClockPluginListener();
+ listener.onPluginConnected(plugin, null);
+ // WHEN the plugin is disconnected
+ listener.onPluginDisconnected(plugin);
+ // THEN the big lock container is GONE and the big clock view doesn't have
+ // a parent.
+ assertThat(bigClockContainer.getVisibility()).isEqualTo(GONE);
+ assertThat(pluginView.getParent()).isNull();
+ }
+
+ @Test
public void onPluginDisconnected_nullView() {
ClockPlugin plugin = mock(ClockPlugin.class);
PluginListener listener = mKeyguardClockSwitch.getClockPluginListener();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
index bb445483c966..2582946333c0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/appops/AppOpsControllerTest.java
@@ -86,7 +86,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
mCallback);
mController.onOpActiveChanged(
AppOpsManager.OP_RECORD_AUDIO, TEST_UID, TEST_PACKAGE_NAME, true);
- mController.onOpNoted(AppOpsManager.OPSTR_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
+ mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
AppOpsManager.MODE_ALLOWED);
verify(mCallback).onActiveStateChanged(AppOpsManager.OP_RECORD_AUDIO,
TEST_UID, TEST_PACKAGE_NAME, true);
@@ -136,7 +136,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
TEST_UID, TEST_PACKAGE_NAME, true);
mController.onOpActiveChanged(AppOpsManager.OP_CAMERA,
TEST_UID, TEST_PACKAGE_NAME, true);
- mController.onOpNoted(AppOpsManager.OPSTR_FINE_LOCATION,
+ mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION,
TEST_UID, TEST_PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
assertEquals(3, mController.getActiveAppOps().size());
}
@@ -147,7 +147,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
TEST_UID, TEST_PACKAGE_NAME, true);
mController.onOpActiveChanged(AppOpsManager.OP_CAMERA,
TEST_UID_OTHER, TEST_PACKAGE_NAME, true);
- mController.onOpNoted(AppOpsManager.OPSTR_FINE_LOCATION,
+ mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION,
TEST_UID, TEST_PACKAGE_NAME, AppOpsManager.MODE_ALLOWED);
assertEquals(2,
mController.getActiveAppOpsForUser(UserHandle.getUserId(TEST_UID)).size());
@@ -158,7 +158,7 @@ public class AppOpsControllerTest extends SysuiTestCase {
@Test
public void opNotedScheduledForRemoval() {
mController.setBGHandler(mMockHandler);
- mController.onOpNoted(AppOpsManager.OPSTR_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
+ mController.onOpNoted(AppOpsManager.OP_FINE_LOCATION, TEST_UID, TEST_PACKAGE_NAME,
AppOpsManager.MODE_ALLOWED);
verify(mMockHandler).scheduleRemoval(any(AppOpItem.class), anyLong());
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
index c1c80ce4a70a..7d94635ab548 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
@@ -19,13 +19,13 @@ package com.android.systemui.keyguard;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.app.AlarmManager;
import android.content.ContentResolver;
-import android.content.Intent;
import android.net.Uri;
import android.provider.Settings;
import android.support.test.filters.SmallTest;
@@ -40,6 +40,7 @@ import androidx.slice.SliceSpecs;
import androidx.slice.builders.ListBuilder;
import androidx.slice.core.SliceQuery;
+import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.systemui.SysuiTestCase;
import org.junit.Assert;
@@ -91,7 +92,7 @@ public class KeyguardSliceProviderTest extends SysuiTestCase {
@Test
public void cleansDateFormat() {
- mProvider.mIntentReceiver.onReceive(getContext(), new Intent(Intent.ACTION_TIMEZONE_CHANGED));
+ mProvider.mKeyguardUpdateMonitorCallback.onTimeZoneChanged(null);
TestableLooper.get(this).processAllMessages();
Assert.assertEquals("Date format should have been cleaned.", 1 /* expected */,
mProvider.mCleanDateFormatInvokations);
@@ -99,7 +100,7 @@ public class KeyguardSliceProviderTest extends SysuiTestCase {
@Test
public void updatesClock() {
- mProvider.mIntentReceiver.onReceive(getContext(), new Intent(Intent.ACTION_TIME_TICK));
+ mProvider.mKeyguardUpdateMonitorCallback.onTimeChanged();
TestableLooper.get(this).processAllMessages();
verify(mContentResolver).notifyChange(eq(mProvider.getUri()), eq(null));
}
@@ -171,6 +172,11 @@ public class KeyguardSliceProviderTest extends SysuiTestCase {
}
@Override
+ public KeyguardUpdateMonitor getKeyguardUpdateMonitor() {
+ return mock(KeyguardUpdateMonitor.class);
+ }
+
+ @Override
protected String getFormattedDate() {
return super.getFormattedDate() + mCounter++;
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt
index b23f667e4388..d3b3dae2c1cd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogBuilderTest.kt
@@ -51,4 +51,19 @@ class PrivacyDialogBuilderTest : SysuiTestCase() {
assertEquals(listOf(Privacy.TYPE_CAMERA), typesList[1])
assertEquals(listOf(Privacy.TYPE_CAMERA), typesList[2])
}
+
+ @Test
+ fun testOrder() {
+ // We want location to always go last, so it will go in the "+ other apps"
+ val appCamera = PrivacyItem(PrivacyType.TYPE_CAMERA, PrivacyApplication("Camera", context))
+ val appMicrophone =
+ PrivacyItem(PrivacyType.TYPE_MICROPHONE, PrivacyApplication("Microphone", context))
+ val appLocation =
+ PrivacyItem(PrivacyType.TYPE_LOCATION, PrivacyApplication("Location", context))
+
+ val items = listOf(appLocation, appMicrophone, appCamera)
+ val textBuilder = PrivacyDialogBuilder(context, items)
+ val appList = textBuilder.appsAndTypes.map { it.first }.map { it.packageName }
+ assertEquals(listOf("Camera", "Microphone", "Location"), appList)
+ }
} \ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
index 563599b32d60..e6d7ee7407d4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyItemControllerTest.kt
@@ -28,6 +28,7 @@ import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.testing.TestableLooper.RunWithLooper
import com.android.systemui.Dependency
+import com.android.systemui.R
import com.android.systemui.SysuiTestCase
import com.android.systemui.appops.AppOpItem
import com.android.systemui.appops.AppOpsController
@@ -56,6 +57,10 @@ class PrivacyItemControllerTest : SysuiTestCase() {
companion object {
val CURRENT_USER_ID = ActivityManager.getCurrentUser()
+ val TEST_UID = CURRENT_USER_ID * UserHandle.PER_USER_RANGE
+ const val SYSTEM_UID = 1000
+ const val TEST_PACKAGE_NAME = "test"
+ const val DEVICE_SERVICES_STRING = "Device services"
const val TAG = "PrivacyItemControllerTest"
fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
}
@@ -81,6 +86,8 @@ class PrivacyItemControllerTest : SysuiTestCase() {
mDependency.injectTestDependency(Dependency.BG_LOOPER, testableLooper.looper)
mDependency.injectTestDependency(Dependency.MAIN_HANDLER, Handler(testableLooper.looper))
mContext.addMockSystemService(UserManager::class.java, userManager)
+ mContext.getOrCreateTestableResources().addOverride(R.string.device_services,
+ DEVICE_SERVICES_STRING)
doReturn(listOf(object : UserInfo() {
init {
@@ -110,8 +117,8 @@ class PrivacyItemControllerTest : SysuiTestCase() {
@Test
fun testDistinctItems() {
- doReturn(listOf(AppOpItem(AppOpsManager.OP_CAMERA, CURRENT_USER_ID, "", 0),
- AppOpItem(AppOpsManager.OP_CAMERA, CURRENT_USER_ID, "", 1)))
+ doReturn(listOf(AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, "", 0),
+ AppOpItem(AppOpsManager.OP_CAMERA, TEST_UID, "", 1)))
.`when`(appOpsController).getActiveAppOpsForUser(anyInt())
privacyItemController.setListening(true)
@@ -121,6 +128,18 @@ class PrivacyItemControllerTest : SysuiTestCase() {
}
@Test
+ fun testSystemApps() {
+ doReturn(listOf(AppOpItem(AppOpsManager.OP_COARSE_LOCATION, SYSTEM_UID, TEST_PACKAGE_NAME,
+ 0))).`when`(appOpsController).getActiveAppOpsForUser(anyInt())
+ privacyItemController.setListening(true)
+ testableLooper.processAllMessages()
+ verify(callback).privacyChanged(capture(argCaptor))
+ assertEquals(1, argCaptor.value.size)
+ assertEquals(context.getString(R.string.device_services),
+ argCaptor.value[0].application.applicationName)
+ }
+
+ @Test
fun testRegisterReceiver_allUsers() {
val spiedContext = spy(mContext)
val itemController = PrivacyItemController(spiedContext, callback)
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index a9f4e46395f3..704974417f87 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -124,19 +124,9 @@ public class BackupManagerService {
}
}
- /**
- * Called through Trampoline from {@link Lifecycle#onUnlockUser(int)}. We run the heavy work on
- * a background thread to keep the unlock time down.
- */
- public void unlockSystemUser() {
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup enable");
- try {
- sInstance.setBackupEnabled(readBackupEnableState(UserHandle.USER_SYSTEM));
- } catch (RemoteException e) {
- // can't happen; it's a local object
- }
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- }
+ // ---------------------------------------------
+ // USER LIFECYCLE CALLBACKS
+ // ---------------------------------------------
/**
* Starts the backup service for user {@code userId} by creating a new instance of {@link
@@ -152,10 +142,25 @@ public class BackupManagerService {
/**
* Starts the backup service for user {@code userId} by registering its instance of {@link
- * UserBackupManagerService} with this service.
+ * UserBackupManagerService} with this service and setting enabled state.
*/
void startServiceForUser(int userId, UserBackupManagerService userBackupManagerService) {
mServiceUsers.put(userId, userBackupManagerService);
+
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup enable");
+ try {
+ // TODO(b/121198604): Make enable file per-user and clean up indirection.
+ mTrampoline.setBackupEnabledForUser(userId, readBackupEnableState(userId));
+ } catch (RemoteException e) {
+ // Can't happen, it's a local object.
+ }
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
+
+ /** Stops the backup service for user {@code userId} when the user is stopped. */
+ @VisibleForTesting
+ protected void stopServiceForUser(int userId) {
+ mServiceUsers.remove(userId);
}
SparseArray<UserBackupManagerService> getServiceUsers() {
@@ -171,7 +176,7 @@ public class BackupManagerService {
* UserBackupManagerService}.
* @param caller A {@link String} identifying the caller for logging purposes.
* @throws SecurityException if {@code userId} is different from the calling user id and the
- * caller does NOT have the android.permission.INTERACT_ACROSS_USERS_FULL permission.
+ * caller does NOT have the android.permission.INTERACT_ACROSS_USERS_FULL permission.
*/
@Nullable
@VisibleForTesting
@@ -821,10 +826,14 @@ public class BackupManagerService {
@Override
public void onUnlockUser(int userId) {
if (userId == UserHandle.USER_SYSTEM) {
- sInstance.initializeServiceAndUnlockSystemUser();
- } else {
- sInstance.unlockUser(userId);
+ sInstance.initializeService();
}
+ sInstance.unlockUser(userId);
+ }
+
+ @Override
+ public void onStopUser(int userId) {
+ sInstance.stopUser(userId);
}
}
}
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index d40368025c0c..8eb5207e4dca 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -150,61 +150,38 @@ public class Trampoline extends IBackupManager.Stub {
}
/**
- * Initialize {@link BackupManagerService} if the backup service is not disabled. Only the
- * system user can initialize the service.
- */
- /* package */ void initializeService(int userId) {
- if (mGlobalDisable) {
- Slog.i(TAG, "Backup service not supported");
- return;
- }
-
- if (userId != UserHandle.USER_SYSTEM) {
- Slog.i(TAG, "Cannot initialize backup service for non-system user: " + userId);
- return;
- }
-
- synchronized (mStateLock) {
- if (!mSuppressFile.exists()) {
- mService = createBackupManagerService();
- } else {
- Slog.i(TAG, "Backup service inactive");
- }
- }
- }
-
- /**
* Called from {@link BackupManagerService.Lifecycle} when the system user is unlocked. Attempts
- * to initialize {@link BackupManagerService} and set backup state for the system user.
+ * to initialize {@link BackupManagerService}. Offloads work onto the handler thread {@link
+ * #mHandlerThread} to keep unlock time low.
*/
- void initializeServiceAndUnlockSystemUser() {
+ void initializeService() {
postToHandler(
() -> {
- // Initialize the backup service.
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "backup init");
- initializeService(UserHandle.USER_SYSTEM);
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ if (mGlobalDisable) {
+ Slog.i(TAG, "Backup service not supported");
+ return;
+ }
- // Start the service for the system user.
- BackupManagerService service = mService;
- if (service != null) {
- Slog.i(TAG, "Starting service for system user");
- service.startServiceForUser(UserHandle.USER_SYSTEM);
- Slog.i(TAG, "Unlocking system user");
- service.unlockSystemUser();
+ synchronized (mStateLock) {
+ if (!mSuppressFile.exists()) {
+ mService = createBackupManagerService();
+ } else {
+ Slog.i(TAG, "Backup service inactive");
+ }
}
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
});
}
/**
- * Called from {@link BackupManagerService.Lifecycle} when a non-system user {@code userId} is
- * unlocked. Starts the backup service for this user if the service supports multi-user.
- * Offloads work onto the handler thread {@link #mHandlerThread} to keep unlock time low.
+ * Called from {@link BackupManagerService.Lifecycle} when a user {@code userId} is unlocked.
+ * Starts the backup service for this user if it's the system user or if the service supports
+ * multi-user. Offloads work onto the handler thread {@link #mHandlerThread} to keep unlock time
+ * low.
*/
- // TODO(b/120212806): Consolidate service start for system and non-system users when system
- // user-only logic is removed.
void unlockUser(int userId) {
- if (!isMultiUserEnabled()) {
+ if (userId != UserHandle.USER_SYSTEM && !isMultiUserEnabled()) {
Slog.i(TAG, "Multi-user disabled, cannot start service for user: " + userId);
return;
}
@@ -221,6 +198,26 @@ public class Trampoline extends IBackupManager.Stub {
}
/**
+ * Called from {@link BackupManagerService.Lifecycle} when a user {@code userId} is stopped.
+ * Offloads work onto the handler thread {@link #mHandlerThread} to keep stopping time low.
+ */
+ void stopUser(int userId) {
+ if (userId != UserHandle.USER_SYSTEM && !isMultiUserEnabled()) {
+ Slog.i(TAG, "Multi-user disabled, cannot stop service for user: " + userId);
+ return;
+ }
+
+ postToHandler(
+ () -> {
+ BackupManagerService service = mService;
+ if (service != null) {
+ Slog.i(TAG, "Stopping service for user: " + userId);
+ service.stopServiceForUser(userId);
+ }
+ });
+ }
+
+ /**
* Only privileged callers should be changing the backup state. This method only acts on {@link
* UserHandle#USER_SYSTEM} and is a no-op if passed non-system users. Deactivating backup in the
* system user also deactivates backup in all users.
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
index e8820ae4e32a..0b3fa0269bd3 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureManagerService.java
@@ -20,7 +20,6 @@ import static android.Manifest.permission.MANAGE_CONTENT_CAPTURE;
import static android.content.Context.CONTENT_CAPTURE_MANAGER_SERVICE;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManagerInternal;
import android.content.ComponentName;
@@ -34,7 +33,6 @@ import android.os.ShellCallback;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Slog;
-import android.view.contentcapture.ContentCaptureContext;
import android.view.contentcapture.IContentCaptureManager;
import com.android.internal.annotations.GuardedBy;
@@ -164,8 +162,7 @@ public final class ContentCaptureManagerService extends
@Override
public void startSession(@UserIdInt int userId, @NonNull IBinder activityToken,
- @NonNull ComponentName componentName, @NonNull String sessionId,
- @Nullable ContentCaptureContext clientContext, int flags,
+ @NonNull ComponentName componentName, @NonNull String sessionId, int flags,
@NonNull IResultReceiver result) {
Preconditions.checkNotNull(activityToken);
Preconditions.checkNotNull(componentName);
@@ -175,14 +172,13 @@ public final class ContentCaptureManagerService extends
// so we don't pass it on startSession (same for Autofill)
final int taskId = getAmInternal().getTaskIdForActivity(activityToken, false);
- // TODO(b/111276913): get from AM as well
+ // TODO(b/121260224): get from AM as well
final int displayId = 0;
synchronized (mLock) {
final ContentCapturePerUserService service = getServiceForUserLocked(userId);
service.startSessionLocked(activityToken, componentName, taskId, displayId,
- sessionId, Binder.getCallingUid(), clientContext, flags,
- mAllowInstantService, result);
+ sessionId, Binder.getCallingUid(), flags, mAllowInstantService, result);
}
}
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
index f21b0d810411..03257e3e8514 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCapturePerUserService.java
@@ -24,7 +24,6 @@ import static com.android.server.wm.ActivityTaskManagerInternal.ASSIST_KEY_STRUC
import android.Manifest;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.AppGlobals;
import android.app.assist.AssistContent;
@@ -39,7 +38,6 @@ import android.os.RemoteException;
import android.service.contentcapture.SnapshotData;
import android.util.ArrayMap;
import android.util.Slog;
-import android.view.contentcapture.ContentCaptureContext;
import android.view.contentcapture.ContentCaptureSession;
import com.android.internal.annotations.GuardedBy;
@@ -114,8 +112,8 @@ final class ContentCapturePerUserService
@GuardedBy("mLock")
public void startSessionLocked(@NonNull IBinder activityToken,
@NonNull ComponentName componentName, int taskId, int displayId,
- @NonNull String sessionId, int uid, @Nullable ContentCaptureContext clientContext,
- int flags, boolean bindInstantServiceAllowed, @NonNull IResultReceiver clientReceiver) {
+ @NonNull String sessionId, int uid, int flags, boolean bindInstantServiceAllowed,
+ @NonNull IResultReceiver clientReceiver) {
if (!isEnabledLocked()) {
setClientState(clientReceiver, ContentCaptureSession.STATE_DISABLED, /* binder=*/ null);
return;
@@ -142,7 +140,7 @@ final class ContentCapturePerUserService
final ContentCaptureServerSession newSession = new ContentCaptureServerSession(getContext(),
mUserId, mLock, activityToken, this, serviceComponentName, componentName, taskId,
- displayId, sessionId, uid, clientContext, flags, bindInstantServiceAllowed,
+ displayId, sessionId, uid, flags, bindInstantServiceAllowed,
mMaster.verbose);
if (mMaster.verbose) {
Slog.v(TAG, "startSession(): new session for "
diff --git a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
index ba98b95082f7..f59636b92278 100644
--- a/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
+++ b/services/contentcapture/java/com/android/server/contentcapture/ContentCaptureServerSession.java
@@ -16,7 +16,6 @@
package com.android.server.contentcapture;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.content.ComponentName;
import android.content.Context;
import android.os.IBinder;
@@ -56,8 +55,7 @@ final class ContentCaptureServerSession implements ContentCaptureServiceCallback
ContentCaptureServerSession(@NonNull Context context, int userId, @NonNull Object lock,
@NonNull IBinder activityToken, @NonNull ContentCapturePerUserService service,
@NonNull ComponentName serviceComponentName, @NonNull ComponentName appComponentName,
- int taskId, int displayId, @NonNull String sessionId, int uid,
- @Nullable ContentCaptureContext clientContext, int flags,
+ int taskId, int displayId, @NonNull String sessionId, int uid, int flags,
boolean bindInstantServiceAllowed, boolean verbose) {
mLock = lock;
mActivityToken = activityToken;
@@ -67,8 +65,8 @@ final class ContentCaptureServerSession implements ContentCaptureServiceCallback
mRemoteService = new RemoteContentCaptureService(context,
ContentCaptureService.SERVICE_INTERFACE, serviceComponentName, userId, this,
bindInstantServiceAllowed, verbose);
- mContentCaptureContext = new ContentCaptureContext(clientContext, appComponentName, taskId,
- displayId, flags);
+ mContentCaptureContext = new ContentCaptureContext(/* clientContext= */ null,
+ appComponentName, taskId, displayId, flags);
}
/**
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index f027253651ee..3cdf09e967fe 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -4096,10 +4096,15 @@ public class AppOpsService extends IAppOpsService.Stub {
private static String[] getPackagesForUid(int uid) {
String[] packageNames = null;
- try {
- packageNames = AppGlobals.getPackageManager().getPackagesForUid(uid);
- } catch (RemoteException e) {
- /* ignore - local call */
+
+ // Very early during boot the package manager is not yet or not yet fully started. At this
+ // time there are no packages yet.
+ if (AppGlobals.getPackageManager() != null) {
+ try {
+ packageNames = AppGlobals.getPackageManager().getPackagesForUid(uid);
+ } catch (RemoteException e) {
+ /* ignore - local call */
+ }
}
if (packageNames == null) {
return EmptyArray.STRING;
@@ -4269,9 +4274,8 @@ public class AppOpsService extends IAppOpsService.Stub {
}
@Override
- public void setMode(int code, int uid, @NonNull String packageName, int mode,
- boolean isPrivileged) {
- AppOpsService.this.setMode(code, uid, packageName, mode, false, isPrivileged);
+ public void setUidMode(int code, int uid, int mode) {
+ AppOpsService.this.setUidMode(code, uid, mode);
}
}
}
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index 08cb7a2f5047..121a830f05f5 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -87,6 +87,10 @@ import com.android.internal.util.DumpUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
import com.android.server.am.BatteryStatsService;
+import com.android.server.deviceidle.ConstraintController;
+import com.android.server.deviceidle.DeviceIdleConstraintTracker;
+import com.android.server.deviceidle.IDeviceIdleConstraint;
+import com.android.server.deviceidle.TvConstraintController;
import com.android.server.net.NetworkPolicyManagerInternal;
import com.android.server.wm.ActivityTaskManagerInternal;
@@ -104,6 +108,7 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
+import java.util.stream.Collectors;
/**
* Keeps track of device idleness and drives low power mode based on that.
@@ -296,6 +301,17 @@ public class DeviceIdleController extends SystemService
private Location mLastGpsLocation;
// Current locked state of the screen
private boolean mScreenLocked;
+ private int mNumBlockingConstraints = 0;
+
+ /**
+ * Constraints are the "handbrakes" that stop the device from moving into a lower state until
+ * every one is released at the same time.
+ *
+ * @see #registerDeviceIdleConstraintInternal(IDeviceIdleConstraint, String, int)
+ */
+ private final ArrayMap<IDeviceIdleConstraint, DeviceIdleConstraintTracker>
+ mConstraints = new ArrayMap<>();
+ private ConstraintController mConstraintController;
/** Device is currently active. */
@VisibleForTesting
@@ -703,8 +719,7 @@ public class DeviceIdleController extends SystemService
* global Settings. Any access to this class or its fields should be done while
* holding the DeviceIdleController lock.
*/
- @VisibleForTesting
- final class Constants extends ContentObserver {
+ public final class Constants extends ContentObserver {
// Key names stored in the settings value.
private static final String KEY_LIGHT_IDLE_AFTER_INACTIVE_TIMEOUT
= "light_after_inactive_to";
@@ -1031,9 +1046,9 @@ public class DeviceIdleController extends SystemService
INACTIVE_TIMEOUT = mParser.getDurationMillis(KEY_INACTIVE_TIMEOUT,
!COMPRESS_TIME ? inactiveTimeoutDefault : (inactiveTimeoutDefault / 10));
SENSING_TIMEOUT = mParser.getDurationMillis(KEY_SENSING_TIMEOUT,
- !DEBUG ? 4 * 60 * 1000L : 60 * 1000L);
+ !COMPRESS_TIME ? 4 * 60 * 1000L : 60 * 1000L);
LOCATING_TIMEOUT = mParser.getDurationMillis(KEY_LOCATING_TIMEOUT,
- !DEBUG ? 30 * 1000L : 15 * 1000L);
+ !COMPRESS_TIME ? 30 * 1000L : 15 * 1000L);
LOCATION_ACCURACY = mParser.getFloat(KEY_LOCATION_ACCURACY, 20);
MOTION_INACTIVE_TIMEOUT = mParser.getDurationMillis(KEY_MOTION_INACTIVE_TIMEOUT,
!COMPRESS_TIME ? 10 * 60 * 1000L : 60 * 1000L);
@@ -1228,6 +1243,7 @@ public class DeviceIdleController extends SystemService
private static final int MSG_REPORT_MAINTENANCE_ACTIVITY = 7;
private static final int MSG_FINISH_IDLE_OP = 8;
private static final int MSG_REPORT_TEMP_APP_WHITELIST_CHANGED = 9;
+ private static final int MSG_SEND_CONSTRAINT_MONITORING = 10;
final class MyHandler extends Handler {
MyHandler(Looper looper) {
@@ -1348,6 +1364,15 @@ public class DeviceIdleController extends SystemService
final boolean added = (msg.arg2 == 1);
mNetworkPolicyManagerInternal.onTempPowerSaveWhitelistChange(appId, added);
} break;
+ case MSG_SEND_CONSTRAINT_MONITORING: {
+ final IDeviceIdleConstraint constraint = (IDeviceIdleConstraint) msg.obj;
+ final boolean monitoring = (msg.arg1 == 1);
+ if (monitoring) {
+ constraint.startMonitoring();
+ } else {
+ constraint.stopMonitoring();
+ }
+ } break;
}
}
}
@@ -1512,6 +1537,25 @@ public class DeviceIdleController extends SystemService
}
public class LocalService {
+ public void onConstraintStateChanged(IDeviceIdleConstraint constraint, boolean active) {
+ synchronized (DeviceIdleController.this) {
+ onConstraintStateChangedLocked(constraint, active);
+ }
+ }
+
+ public void registerDeviceIdleConstraint(IDeviceIdleConstraint constraint, String name,
+ @IDeviceIdleConstraint.MinimumState int minState) {
+ registerDeviceIdleConstraintInternal(constraint, name, minState);
+ }
+
+ public void unregisterDeviceIdleConstraint(IDeviceIdleConstraint constraint) {
+ unregisterDeviceIdleConstraintInternal(constraint);
+ }
+
+ public void exitIdle(String reason) {
+ exitIdleInternal(reason);
+ }
+
// duration in milliseconds
public void addPowerSaveTempWhitelistApp(int callingUid, String packageName,
long duration, int userId, boolean sync, String reason) {
@@ -1562,6 +1606,7 @@ public class DeviceIdleController extends SystemService
static class Injector {
private final Context mContext;
private ConnectivityService mConnectivityService;
+ private Constants mConstants;
private LocationManager mLocationManager;
Injector(Context ctx) {
@@ -1591,7 +1636,10 @@ public class DeviceIdleController extends SystemService
Constants getConstants(DeviceIdleController controller, Handler handler,
ContentResolver resolver) {
- return controller.new Constants(handler, resolver);
+ if (mConstants == null) {
+ mConstants = controller.new Constants(handler, resolver);
+ }
+ return mConstants;
}
LocationManager getLocationManager() {
@@ -1608,6 +1656,23 @@ public class DeviceIdleController extends SystemService
PowerManager getPowerManager() {
return mContext.getSystemService(PowerManager.class);
}
+
+ SensorManager getSensorManager() {
+ return mContext.getSystemService(SensorManager.class);
+ }
+
+ ConstraintController getConstraintController(Handler handler, LocalService localService) {
+ if (mContext.getPackageManager()
+ .hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY)) {
+ return new TvConstraintController(mContext, handler);
+ }
+ return null;
+ }
+
+ boolean useMotionSensor() {
+ return mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_autoPowerModeUseMotionSensor);
+ }
}
private final Injector mInjector;
@@ -1632,9 +1697,7 @@ public class DeviceIdleController extends SystemService
mHandler = mInjector.getHandler(this);
mAppStateTracker = mInjector.getAppStateTracker(context, FgThread.get().getLooper());
LocalServices.addService(AppStateTracker.class, mAppStateTracker);
-
- mUseMotionSensor = context.getResources().getBoolean(
- com.android.internal.R.bool.config_autoPowerModeUseMotionSensor);
+ mUseMotionSensor = mInjector.useMotionSensor();
}
public DeviceIdleController(Context context) {
@@ -1734,7 +1797,7 @@ public class DeviceIdleController extends SystemService
mNetworkPolicyManager = INetworkPolicyManager.Stub.asInterface(
ServiceManager.getService(Context.NETWORK_POLICY_SERVICE));
mNetworkPolicyManagerInternal = getLocalService(NetworkPolicyManagerInternal.class);
- mSensorManager = (SensorManager) getContext().getSystemService(Context.SENSOR_SERVICE);
+ mSensorManager = mInjector.getSensorManager();
if (mUseMotionSensor) {
int sigMotionSensorId = getContext().getResources().getInteger(
@@ -1763,6 +1826,12 @@ public class DeviceIdleController extends SystemService
.setNumUpdates(1);
}
+ mConstraintController = mInjector.getConstraintController(
+ mHandler, getLocalService(LocalService.class));
+ if (mConstraintController != null) {
+ mConstraintController.start();
+ }
+
float angleThreshold = getContext().getResources().getInteger(
com.android.internal.R.integer.config_autoPowerModeThresholdAngle) / 100f;
mAnyMotionDetector = mInjector.getAnyMotionDetector(mHandler, mSensorManager, this,
@@ -1818,6 +1887,99 @@ public class DeviceIdleController extends SystemService
}
}
+ @VisibleForTesting
+ boolean hasMotionSensor() {
+ return mUseMotionSensor && mMotionSensor != null;
+ }
+
+ private void registerDeviceIdleConstraintInternal(IDeviceIdleConstraint constraint,
+ final String name, final int type) {
+ final int minState;
+ switch (type) {
+ case IDeviceIdleConstraint.ACTIVE:
+ minState = STATE_ACTIVE;
+ break;
+ case IDeviceIdleConstraint.SENSING_OR_ABOVE:
+ minState = STATE_SENSING;
+ break;
+ default:
+ Slog.wtf(TAG, "Registering device-idle constraint with invalid type: " + type);
+ return;
+ }
+ synchronized (this) {
+ if (mConstraints.containsKey(constraint)) {
+ Slog.e(TAG, "Re-registering device-idle constraint: " + constraint + ".");
+ return;
+ }
+ DeviceIdleConstraintTracker tracker = new DeviceIdleConstraintTracker(name, minState);
+ mConstraints.put(constraint, tracker);
+ updateActiveConstraintsLocked();
+ }
+ }
+
+ private void unregisterDeviceIdleConstraintInternal(IDeviceIdleConstraint constraint) {
+ synchronized (this) {
+ // Artifically force the constraint to inactive to unblock anything waiting for it.
+ onConstraintStateChangedLocked(constraint, /* active= */ false);
+
+ // Let the constraint know that we are not listening to it any more.
+ setConstraintMonitoringLocked(constraint, /* monitoring= */ false);
+ mConstraints.remove(constraint);
+ }
+ }
+
+ @GuardedBy("this")
+ private void onConstraintStateChangedLocked(IDeviceIdleConstraint constraint, boolean active) {
+ DeviceIdleConstraintTracker tracker = mConstraints.get(constraint);
+ if (tracker == null) {
+ Slog.e(TAG, "device-idle constraint " + constraint + " has not been registered.");
+ return;
+ }
+ if (active != tracker.active && tracker.monitoring) {
+ tracker.active = active;
+ mNumBlockingConstraints += (tracker.active ? +1 : -1);
+ if (mNumBlockingConstraints == 0) {
+ if (mState == STATE_ACTIVE) {
+ becomeInactiveIfAppropriateLocked();
+ } else if (mNextAlarmTime == 0 || mNextAlarmTime < SystemClock.elapsedRealtime()) {
+ stepIdleStateLocked("s:" + tracker.name);
+ }
+ }
+ }
+ }
+
+ @GuardedBy("this")
+ private void setConstraintMonitoringLocked(IDeviceIdleConstraint constraint, boolean monitor) {
+ DeviceIdleConstraintTracker tracker = mConstraints.get(constraint);
+ if (tracker.monitoring != monitor) {
+ tracker.monitoring = monitor;
+ updateActiveConstraintsLocked();
+ // We send the callback on a separate thread instead of just relying on oneway as
+ // the client could be in the system server with us and cause re-entry problems.
+ mHandler.obtainMessage(MSG_SEND_CONSTRAINT_MONITORING,
+ /* monitoring= */ monitor ? 1 : 0,
+ /* <not used>= */ -1,
+ /* constraint= */ constraint).sendToTarget();
+ }
+ }
+
+ @GuardedBy("this")
+ private void updateActiveConstraintsLocked() {
+ mNumBlockingConstraints = 0;
+ for (int i = 0; i < mConstraints.size(); i++) {
+ final IDeviceIdleConstraint constraint = mConstraints.keyAt(i);
+ final DeviceIdleConstraintTracker tracker = mConstraints.valueAt(i);
+ final boolean monitoring = (tracker.minState == mState);
+ if (monitoring != tracker.monitoring) {
+ setConstraintMonitoringLocked(constraint, monitoring);
+ tracker.active = monitoring;
+ }
+ if (tracker.monitoring && tracker.active) {
+ mNumBlockingConstraints++;
+ }
+ }
+ }
+
public boolean addPowerSaveWhitelistAppInternal(String name) {
synchronized (this) {
try {
@@ -2448,6 +2610,7 @@ public class DeviceIdleController extends SystemService
cancelLocatingLocked();
stopMonitoringMotionLocked();
mAnyMotionDetector.stop();
+ updateActiveConstraintsLocked();
}
private void resetLightIdleManagementLocked() {
@@ -2583,40 +2746,50 @@ public class DeviceIdleController extends SystemService
return;
}
+ if (mNumBlockingConstraints != 0 && !mForceIdle) {
+ // We have some constraints from other parts of the system server preventing
+ // us from moving to the next state.
+ if (DEBUG) {
+ Slog.i(TAG, "Cannot step idle state. Blocked by: " + mConstraints.values().stream()
+ .filter(x -> x.active)
+ .map(x -> x.name)
+ .collect(Collectors.joining(",")));
+ }
+ return;
+ }
+
switch (mState) {
case STATE_INACTIVE:
// We have now been inactive long enough, it is time to start looking
// for motion and sleep some more while doing so.
startMonitoringMotionLocked();
scheduleAlarmLocked(mConstants.IDLE_AFTER_INACTIVE_TIMEOUT, false);
- mState = STATE_IDLE_PENDING;
- if (DEBUG) Slog.d(TAG, "Moved from STATE_INACTIVE to STATE_IDLE_PENDING.");
- EventLogTags.writeDeviceIdle(mState, reason);
+ moveToStateLocked(STATE_IDLE_PENDING, reason);
break;
case STATE_IDLE_PENDING:
- mState = STATE_SENSING;
- if (DEBUG) Slog.d(TAG, "Moved from STATE_IDLE_PENDING to STATE_SENSING.");
- EventLogTags.writeDeviceIdle(mState, reason);
+ moveToStateLocked(STATE_SENSING, reason);
cancelLocatingLocked();
mLocated = false;
mLastGenericLocation = null;
mLastGpsLocation = null;
+ updateActiveConstraintsLocked();
- // If we have an accelerometer, wait to find out whether we are moving.
+ // Wait for open constraints and an accelerometer reading before moving on.
if (mUseMotionSensor && mAnyMotionDetector.hasSensor()) {
scheduleSensingTimeoutAlarmLocked(mConstants.SENSING_TIMEOUT);
mNotMoving = false;
mAnyMotionDetector.checkForAnyMotion();
break;
+ } else if (mNumBlockingConstraints != 0) {
+ cancelAlarmLocked();
+ break;
}
mNotMoving = true;
// Otherwise, fall through and check this off the list of requirements.
case STATE_SENSING:
cancelSensingTimeoutAlarmLocked();
- mState = STATE_LOCATING;
- if (DEBUG) Slog.d(TAG, "Moved from STATE_SENSING to STATE_LOCATING.");
- EventLogTags.writeDeviceIdle(mState, reason);
+ moveToStateLocked(STATE_LOCATING, reason);
scheduleAlarmLocked(mConstants.LOCATING_TIMEOUT, false);
LocationManager locationManager = mInjector.getLocationManager();
if (locationManager != null
@@ -2665,12 +2838,11 @@ public class DeviceIdleController extends SystemService
if (mNextIdleDelay < mConstants.IDLE_TIMEOUT) {
mNextIdleDelay = mConstants.IDLE_TIMEOUT;
}
- mState = STATE_IDLE;
+ moveToStateLocked(STATE_IDLE, reason);
if (mLightState != LIGHT_STATE_OVERRIDE) {
mLightState = LIGHT_STATE_OVERRIDE;
cancelLightAlarmLocked();
}
- EventLogTags.writeDeviceIdle(mState, reason);
addEvent(EVENT_DEEP_IDLE, null);
mGoingIdleWakeLock.acquire();
mHandler.sendEmptyMessage(MSG_REPORT_IDLE_ON);
@@ -2688,14 +2860,24 @@ public class DeviceIdleController extends SystemService
if (mNextIdlePendingDelay < mConstants.IDLE_PENDING_TIMEOUT) {
mNextIdlePendingDelay = mConstants.IDLE_PENDING_TIMEOUT;
}
- mState = STATE_IDLE_MAINTENANCE;
- EventLogTags.writeDeviceIdle(mState, reason);
+ moveToStateLocked(STATE_IDLE_MAINTENANCE, reason);
addEvent(EVENT_DEEP_MAINTENANCE, null);
mHandler.sendEmptyMessage(MSG_REPORT_IDLE_OFF);
break;
}
}
+ private void moveToStateLocked(int state, String reason) {
+ final int oldState = mState;
+ mState = state;
+ if (DEBUG) {
+ Slog.d(TAG, String.format("Moved from STATE_%s to STATE_%s.",
+ stateToString(oldState), stateToString(mState)));
+ }
+ EventLogTags.writeDeviceIdle(mState, reason);
+ updateActiveConstraintsLocked();
+ }
+
void incActiveIdleOps() {
synchronized (this) {
mActiveIdleOpCount++;
@@ -2818,6 +3000,7 @@ public class DeviceIdleController extends SystemService
mMaintenanceStartTime = 0;
EventLogTags.writeDeviceIdle(mState, type);
becomeInactive = true;
+ updateActiveConstraintsLocked();
}
if (mLightState == LIGHT_STATE_OVERRIDE) {
// We went out of light idle mode because we had started deep idle mode... let's
@@ -3794,8 +3977,22 @@ public class DeviceIdleController extends SystemService
pw.print(" mScreenLocked="); pw.println(mScreenLocked);
pw.print(" mNetworkConnected="); pw.println(mNetworkConnected);
pw.print(" mCharging="); pw.println(mCharging);
- pw.print(" mMotionActive="); pw.println(mMotionListener.active);
+ if (mConstraints.size() != 0) {
+ pw.println(" mConstraints={");
+ for (int i = 0; i < mConstraints.size(); i++) {
+ final DeviceIdleConstraintTracker tracker = mConstraints.valueAt(i);
+ pw.print(" \""); pw.print(tracker.name); pw.print("\"=");
+ if (tracker.minState == mState) {
+ pw.println(tracker.active);
+ } else {
+ pw.print("ignored <mMinState="); pw.print(stateToString(tracker.minState));
+ pw.println(">");
+ }
+ }
+ pw.println(" }");
+ }
if (mUseMotionSensor) {
+ pw.print(" mMotionActive="); pw.println(mMotionListener.active);
pw.print(" mNotMoving="); pw.println(mNotMoving);
}
pw.print(" mLocating="); pw.print(mLocating); pw.print(" mHasGps=");
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index d33b61757141..2346cfc07a83 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -47,6 +47,7 @@ import android.location.Address;
import android.location.Criteria;
import android.location.GeocoderParams;
import android.location.Geofence;
+import android.location.GnssMeasurementCorrections;
import android.location.IBatchedLocationCallback;
import android.location.IGnssMeasurementsListener;
import android.location.IGnssNavigationMessageListener;
@@ -2594,6 +2595,30 @@ public class LocationManagerService extends ILocationManager.Stub {
}
@Override
+ public void injectGnssMeasurementCorrections(
+ GnssMeasurementCorrections measurementCorrections, String packageName) {
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.LOCATION_HARDWARE,
+ "Location Hardware permission not granted to inject GNSS measurement corrections.");
+ if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) {
+ mGnssMeasurementsProvider.injectGnssMeasurementCorrections(measurementCorrections);
+ } else {
+ Slog.e(TAG, "Can not inject GNSS corrections due to no permission.");
+ }
+ }
+
+ @Override
+ public int getGnssCapabilities(String packageName) {
+ mContext.enforceCallingPermission(
+ android.Manifest.permission.LOCATION_HARDWARE,
+ "Location Hardware permission not granted to obrain GNSS chipset capabilities.");
+ if (!hasGnssPermissions(packageName) || mGnssMeasurementsProvider == null) {
+ return -1;
+ }
+ return mGnssMeasurementsProvider.getGnssCapabilities();
+ }
+
+ @Override
public void removeGnssMeasurementsListener(IGnssMeasurementsListener listener) {
if (mGnssMeasurementsProvider == null) {
return;
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 7adcabac26ee..2a806447d605 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -129,6 +129,7 @@ import android.util.TimeUtils;
import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
+import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
import com.android.internal.os.AppFuseMount;
import com.android.internal.os.BackgroundThread;
@@ -1709,6 +1710,10 @@ class StorageManagerService extends IStorageManager.Stub
ServiceManager.getService("package"));
mIAppOpsService = IAppOpsService.Stub.asInterface(
ServiceManager.getService(Context.APP_OPS_SERVICE));
+ try {
+ mIAppOpsService.startWatchingMode(OP_REQUEST_INSTALL_PACKAGES, null, mAppOpsCallback);
+ } catch (RemoteException e) {
+ }
mHandler.obtainMessage(H_SYSTEM_READY).sendToTarget();
}
@@ -3240,6 +3245,15 @@ class StorageManagerService extends IStorageManager.Stub
}
}
+ private IAppOpsCallback.Stub mAppOpsCallback = new IAppOpsCallback.Stub() {
+ @Override
+ public void opChanged(int op, int uid, String packageName) throws RemoteException {
+ if (!ENABLE_ISOLATED_STORAGE) return;
+
+ remountUidExternalStorage(uid, getMountMode(uid, packageName));
+ }
+ };
+
private static final Pattern PATTERN_TRANSLATE = Pattern.compile(
"(?i)^(/storage/[^/]+/(?:[0-9]+/)?)(.*)");
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 983ec4be328d..1a5dd90b918a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -647,6 +647,11 @@ public class ActivityManagerService extends IActivityManager.Stub
final ProcessStatsService mProcessStats;
/**
+ * Service for compacting background apps.
+ */
+ final AppCompactor mAppCompact;
+
+ /**
* Non-persistent appId whitelist for background restrictions
*/
int[] mBackgroundAppIdWhitelist = new int[] {
@@ -796,11 +801,6 @@ public class ActivityManagerService extends IActivityManager.Stub
*/
final ArrayList<ProcessRecord> mPendingPssProcesses = new ArrayList<ProcessRecord>();
- /**
- * Processes to compact.
- */
- final ArrayList<ProcessRecord> mPendingCompactionProcesses = new ArrayList<ProcessRecord>();
-
private boolean mBinderTransactionTrackingEnabled = false;
/**
@@ -1458,7 +1458,6 @@ public class ActivityManagerService extends IActivityManager.Stub
final Handler mUiHandler;
final ServiceThread mProcStartHandlerThread;
final Handler mProcStartHandler;
- final ServiceThread mCompactionThread;
final ActivityManagerConstants mConstants;
@@ -1796,11 +1795,6 @@ public class ActivityManagerService extends IActivityManager.Stub
}
};
- static final int COMPACT_PROCESS_SOME = 1;
- static final int COMPACT_PROCESS_FULL = 2;
- static final int COMPACT_PROCESS_MSG = 1;
- final Handler mCompactionHandler;
-
static final int COLLECT_PSS_BG_MSG = 1;
final Handler mBgHandler = new Handler(BackgroundThread.getHandler().getLooper()) {
@@ -2236,8 +2230,7 @@ public class ActivityManagerService extends IActivityManager.Stub
? new PendingIntentController(handlerThread.getLooper(), mUserController) : null;
mProcStartHandlerThread = null;
mProcStartHandler = null;
- mCompactionThread = null;
- mCompactionHandler = null;
+ mAppCompact = null;
mHiddenApiBlacklist = null;
mFactoryTest = FACTORY_TEST_OFF;
}
@@ -2266,95 +2259,6 @@ public class ActivityManagerService extends IActivityManager.Stub
mProcStartHandlerThread.start();
mProcStartHandler = new Handler(mProcStartHandlerThread.getLooper());
- mCompactionThread = new ServiceThread("CompactionThread",
- THREAD_PRIORITY_FOREGROUND, true);
- mCompactionThread.start();
- mCompactionHandler = new Handler(mCompactionThread.getLooper()) {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case COMPACT_PROCESS_MSG: {
- long start = SystemClock.uptimeMillis();
- ProcessRecord proc;
- int pid;
- String action;
- final String name;
- int pendingAction, lastCompactAction;
- long lastCompactTime;
- synchronized(ActivityManagerService.this) {
- proc = mPendingCompactionProcesses.remove(0);
-
- // don't compact if the process has returned to perceptible
- if (proc.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
- return;
- }
-
- pid = proc.pid;
- name = proc.processName;
- pendingAction = proc.reqCompactAction;
- lastCompactAction = proc.lastCompactAction;
- lastCompactTime = proc.lastCompactTime;
- }
- if (pid == 0) {
- // not a real process, either one being launched or one being killed
- return;
- }
-
- // basic throttling
- if (pendingAction == COMPACT_PROCESS_SOME) {
- // if we're compacting some, then compact if >10s after last full
- // or >5s after last some
- if ((lastCompactAction == COMPACT_PROCESS_SOME && (start - lastCompactTime < 5000)) ||
- (lastCompactAction == COMPACT_PROCESS_FULL && (start - lastCompactTime < 10000)))
- return;
- } else {
- // if we're compacting full, then compact if >10s after last full
- // or >.5s after last some
- if ((lastCompactAction == COMPACT_PROCESS_SOME && (start - lastCompactTime < 500)) ||
- (lastCompactAction == COMPACT_PROCESS_FULL && (start - lastCompactTime < 10000)))
- return;
- }
-
- try {
- Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Compact " +
- ((pendingAction == COMPACT_PROCESS_SOME) ? "some" : "full") +
- ": " + name);
- long[] rssBefore = Process.getRss(pid);
- FileOutputStream fos = new FileOutputStream("/proc/" + pid + "/reclaim");
- if (pendingAction == COMPACT_PROCESS_SOME) {
- action = "file";
- } else {
- action = "all";
- }
- fos.write(action.getBytes());
- fos.close();
- long[] rssAfter = Process.getRss(pid);
- long end = SystemClock.uptimeMillis();
- long time = end - start;
- EventLog.writeEvent(EventLogTags.AM_COMPACT, pid, name, action,
- rssBefore[0], rssBefore[1], rssBefore[2], rssBefore[3],
- rssAfter[0], rssAfter[1], rssAfter[2], rssAfter[3], time,
- lastCompactAction, lastCompactTime, msg.arg1, msg.arg2);
- StatsLog.write(StatsLog.APP_COMPACTED, pid, name, pendingAction,
- rssBefore[0], rssBefore[1], rssBefore[2], rssBefore[3],
- rssAfter[0], rssAfter[1], rssAfter[2], rssAfter[3], time,
- lastCompactAction, lastCompactTime, msg.arg1,
- ActivityManager.processStateAmToProto(msg.arg2));
- synchronized(ActivityManagerService.this) {
- proc.lastCompactTime = end;
- proc.lastCompactAction = pendingAction;
- }
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- } catch (Exception e) {
- // nothing to do, presumably the process died
- Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
- }
- }
- }
- }
- };
-
-
mConstants = new ActivityManagerConstants(this, mHandler);
mProcessList.init(this);
@@ -2409,6 +2313,8 @@ public class ActivityManagerService extends IActivityManager.Stub
DisplayThread.get().getLooper());
mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);
+ mAppCompact = new AppCompactor(this);
+
mProcessCpuThread = new Thread("CpuTracker") {
@Override
public void run() {
@@ -2455,7 +2361,7 @@ public class ActivityManagerService extends IActivityManager.Stub
try {
Process.setThreadGroupAndCpuset(BackgroundThread.get().getThreadId(),
Process.THREAD_GROUP_SYSTEM);
- Process.setThreadGroupAndCpuset(mCompactionThread.getThreadId(),
+ Process.setThreadGroupAndCpuset(mAppCompact.mCompactionThread.getThreadId(),
Process.THREAD_GROUP_SYSTEM);
} catch (Exception e) {
Slog.w(TAG, "Setting background thread cpuset failed");
@@ -17084,18 +16990,10 @@ public class ActivityManagerService extends IActivityManager.Stub
if (app.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ &&
(app.curAdj == ProcessList.PREVIOUS_APP_ADJ ||
app.curAdj == ProcessList.HOME_APP_ADJ)) {
- app.reqCompactAction = COMPACT_PROCESS_SOME;
- mPendingCompactionProcesses.add(app);
- mCompactionHandler.sendMessage(
- mCompactionHandler.obtainMessage(
- COMPACT_PROCESS_MSG, app.curAdj, app.setProcState));
+ mAppCompact.compactAppSome(app);
} else if (app.setAdj < ProcessList.CACHED_APP_MIN_ADJ &&
app.curAdj >= ProcessList.CACHED_APP_MIN_ADJ) {
- app.reqCompactAction = COMPACT_PROCESS_FULL;
- mPendingCompactionProcesses.add(app);
- mCompactionHandler.sendMessage(
- mCompactionHandler.obtainMessage(
- COMPACT_PROCESS_MSG, app.curAdj, app.setProcState));
+ mAppCompact.compactAppFull(app);
}
}
ProcessList.setOomAdj(app.pid, app.uid, app.curAdj);
diff --git a/services/core/java/com/android/server/am/AppCompactor.java b/services/core/java/com/android/server/am/AppCompactor.java
new file mode 100644
index 000000000000..aee16c3b9ddc
--- /dev/null
+++ b/services/core/java/com/android/server/am/AppCompactor.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import com.android.internal.annotations.GuardedBy;
+
+import android.app.ActivityManager;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Process;
+import android.os.SystemClock;
+import android.os.Trace;
+
+import android.util.EventLog;
+import android.util.StatsLog;
+
+import static android.os.Process.THREAD_PRIORITY_FOREGROUND;
+
+import com.android.server.ServiceThread;
+
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+
+public final class AppCompactor {
+ /**
+ * Processes to compact.
+ */
+ final ArrayList<ProcessRecord> mPendingCompactionProcesses = new ArrayList<ProcessRecord>();
+
+ /*
+ * This thread must be moved to the system background cpuset.
+ * If that doesn't happen, it's probably going to draw a lot of power.
+ * However, this has to happen after the first updateOomAdjLocked, because
+ * that will wipe out the cpuset assignment for system_server threads.
+ * Accordingly, this is in the AMS constructor.
+ */
+ final ServiceThread mCompactionThread;
+
+ static final int COMPACT_PROCESS_SOME = 1;
+ static final int COMPACT_PROCESS_FULL = 2;
+ static final int COMPACT_PROCESS_MSG = 1;
+ final Handler mCompactionHandler;
+
+ final ActivityManagerService mAm;
+ final ActivityManagerConstants mConstants;
+
+ public AppCompactor(ActivityManagerService am) {
+ mAm = am;
+ mConstants = am.mConstants;
+
+ mCompactionThread = new ServiceThread("CompactionThread",
+ THREAD_PRIORITY_FOREGROUND, true);
+ mCompactionThread.start();
+ mCompactionHandler = new MemCompactionHandler(this);
+ }
+
+ // Must be called while holding AMS lock.
+ final void compactAppSome(ProcessRecord app) {
+ app.reqCompactAction = COMPACT_PROCESS_SOME;
+ mPendingCompactionProcesses.add(app);
+ mCompactionHandler.sendMessage(
+ mCompactionHandler.obtainMessage(
+ COMPACT_PROCESS_MSG, app.curAdj, app.setProcState));
+ }
+
+ // Must be called while holding AMS lock.
+ final void compactAppFull(ProcessRecord app) {
+ app.reqCompactAction = COMPACT_PROCESS_FULL;
+ mPendingCompactionProcesses.add(app);
+ mCompactionHandler.sendMessage(
+ mCompactionHandler.obtainMessage(
+ COMPACT_PROCESS_MSG, app.curAdj, app.setProcState));
+
+ }
+ final class MemCompactionHandler extends Handler {
+ AppCompactor mAc;
+
+ private MemCompactionHandler(AppCompactor ac) {
+ super(ac.mCompactionThread.getLooper());
+ mAc = ac;
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case COMPACT_PROCESS_MSG: {
+ long start = SystemClock.uptimeMillis();
+ ProcessRecord proc;
+ int pid;
+ String action;
+ final String name;
+ int pendingAction, lastCompactAction;
+ long lastCompactTime;
+ synchronized(mAc.mAm) {
+ proc = mAc.mPendingCompactionProcesses.remove(0);
+
+ // don't compact if the process has returned to perceptible
+ if (proc.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ) {
+ return;
+ }
+
+ pid = proc.pid;
+ name = proc.processName;
+ pendingAction = proc.reqCompactAction;
+ lastCompactAction = proc.lastCompactAction;
+ lastCompactTime = proc.lastCompactTime;
+ }
+ if (pid == 0) {
+ // not a real process, either one being launched or one being killed
+ return;
+ }
+
+ // basic throttling
+ if (pendingAction == COMPACT_PROCESS_SOME) {
+ // if we're compacting some, then compact if >10s after last full
+ // or >5s after last some
+ if ((lastCompactAction == COMPACT_PROCESS_SOME && (start - lastCompactTime < 5000)) ||
+ (lastCompactAction == COMPACT_PROCESS_FULL && (start - lastCompactTime < 10000))) {
+ return;
+ }
+ } else {
+ // if we're compacting full, then compact if >10s after last full
+ // or >.5s after last some
+ if ((lastCompactAction == COMPACT_PROCESS_SOME && (start - lastCompactTime < 500)) ||
+ (lastCompactAction == COMPACT_PROCESS_FULL && (start - lastCompactTime < 10000))) {
+ return;
+ }
+ }
+
+ try {
+ Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Compact " +
+ ((pendingAction == COMPACT_PROCESS_SOME) ? "some" : "full") +
+ ": " + name);
+ long[] rssBefore = Process.getRss(pid);
+ FileOutputStream fos = new FileOutputStream("/proc/" + pid + "/reclaim");
+ if (pendingAction == COMPACT_PROCESS_SOME) {
+ action = "file";
+ } else {
+ action = "all";
+ }
+ fos.write(action.getBytes());
+ fos.close();
+ long[] rssAfter = Process.getRss(pid);
+ long end = SystemClock.uptimeMillis();
+ long time = end - start;
+ EventLog.writeEvent(EventLogTags.AM_COMPACT, pid, name, action,
+ rssBefore[0], rssBefore[1], rssBefore[2], rssBefore[3],
+ rssAfter[0], rssAfter[1], rssAfter[2], rssAfter[3], time,
+ lastCompactAction, lastCompactTime, msg.arg1, msg.arg2);
+ StatsLog.write(StatsLog.APP_COMPACTED, pid, name, pendingAction,
+ rssBefore[0], rssBefore[1], rssBefore[2], rssBefore[3],
+ rssAfter[0], rssAfter[1], rssAfter[2], rssAfter[3], time,
+ lastCompactAction, lastCompactTime, msg.arg1,
+ ActivityManager.processStateAmToProto(msg.arg2));
+ synchronized(mAc.mAm) {
+ proc.lastCompactTime = end;
+ proc.lastCompactAction = pendingAction;
+ }
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ } catch (Exception e) {
+ // nothing to do, presumably the process died
+ Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+ }
+ }
+ }
+ }
+ }
+
+
+}
diff --git a/services/core/java/com/android/server/deviceidle/BluetoothConstraint.java b/services/core/java/com/android/server/deviceidle/BluetoothConstraint.java
new file mode 100644
index 000000000000..cc319bf23ddd
--- /dev/null
+++ b/services/core/java/com/android/server/deviceidle/BluetoothConstraint.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.deviceidle;
+
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothProfile;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.Handler;
+import android.os.Message;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.DeviceIdleController;
+
+/**
+ * Track whether there are any active Bluetooth devices connected.
+ */
+public class BluetoothConstraint implements IDeviceIdleConstraint {
+ private static final String TAG = BluetoothConstraint.class.getSimpleName();
+ private static final long INACTIVITY_TIMEOUT_MS = 20 * 60 * 1000L;
+
+ private final Context mContext;
+ private final Handler mHandler;
+ private final DeviceIdleController.LocalService mLocalService;
+ private final BluetoothManager mBluetoothManager;
+
+ private volatile boolean mConnected = true;
+ private volatile boolean mMonitoring = false;
+
+ public BluetoothConstraint(
+ Context context, Handler handler, DeviceIdleController.LocalService localService) {
+ mContext = context;
+ mHandler = handler;
+ mLocalService = localService;
+ mBluetoothManager = mContext.getSystemService(BluetoothManager.class);
+ }
+
+ @Override
+ public synchronized void startMonitoring() {
+ // Start by assuming we have a connected bluetooth device.
+ mConnected = true;
+ mMonitoring = true;
+
+ // Register a receiver to get updates on bluetooth devices disconnecting or the
+ // adapter state changing.
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
+ filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
+ filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
+ mContext.registerReceiver(mReceiver, filter);
+
+ // Some devices will try to stay connected indefinitely. Set a timeout to ignore them.
+ mHandler.sendMessageDelayed(
+ Message.obtain(mHandler, mTimeoutCallback), INACTIVITY_TIMEOUT_MS);
+
+ // Now we have the receiver registered, make a direct check for connected devices.
+ updateAndReportActiveLocked();
+ }
+
+ @Override
+ public synchronized void stopMonitoring() {
+ mContext.unregisterReceiver(mReceiver);
+ mHandler.removeCallbacks(mTimeoutCallback);
+ mMonitoring = false;
+ }
+
+ private synchronized void cancelMonitoringDueToTimeout() {
+ if (mMonitoring) {
+ mMonitoring = false;
+ mLocalService.onConstraintStateChanged(this, /* active= */ false);
+ }
+ }
+
+ /**
+ * Check the latest data from BluetoothManager and let DeviceIdleController know whether we
+ * have connected devices (for example TV remotes / gamepads) and thus want to stay awake.
+ */
+ @GuardedBy("this")
+ private void updateAndReportActiveLocked() {
+ final boolean connected = isBluetoothConnected(mBluetoothManager);
+ if (connected != mConnected) {
+ mConnected = connected;
+ // If we lost all of our connections, we are on track to going into idle state.
+ mLocalService.onConstraintStateChanged(this, /* active= */ mConnected);
+ }
+ }
+
+ /**
+ * True if the bluetooth adapter exists, is enabled, and has at least one GATT device connected.
+ */
+ @VisibleForTesting
+ static boolean isBluetoothConnected(BluetoothManager bluetoothManager) {
+ BluetoothAdapter adapter = bluetoothManager.getAdapter();
+ if (adapter != null && adapter.isEnabled()) {
+ return bluetoothManager.getConnectedDevices(BluetoothProfile.GATT).size() > 0;
+ }
+ return false;
+ }
+
+ /**
+ * Registered in {@link #startMonitoring()}, unregistered in {@link #stopMonitoring()}.
+ */
+ @VisibleForTesting
+ final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(intent.getAction())) {
+ mLocalService.exitIdle("bluetooth");
+ } else {
+ updateAndReportActiveLocked();
+ }
+ }
+ };
+
+ private final Runnable mTimeoutCallback = () -> cancelMonitoringDueToTimeout();
+}
diff --git a/services/core/java/com/android/server/deviceidle/ConstraintController.java b/services/core/java/com/android/server/deviceidle/ConstraintController.java
new file mode 100644
index 000000000000..6d52f7188d99
--- /dev/null
+++ b/services/core/java/com/android/server/deviceidle/ConstraintController.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.deviceidle;
+
+/**
+ * Device idle constraints for a specific form factor or use-case.
+ */
+public interface ConstraintController {
+ /**
+ * Begin any general continuing work and register all constraints.
+ */
+ void start();
+
+ /**
+ * Unregister all constraints and stop any general work.
+ */
+ void stop();
+}
diff --git a/services/core/java/com/android/server/deviceidle/DeviceIdleConstraintTracker.java b/services/core/java/com/android/server/deviceidle/DeviceIdleConstraintTracker.java
new file mode 100644
index 000000000000..4d5760ef9c86
--- /dev/null
+++ b/services/core/java/com/android/server/deviceidle/DeviceIdleConstraintTracker.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.deviceidle;
+
+/**
+ * Current state of an {@link IDeviceIdleConstraint}.
+ *
+ * If the current doze state is between leastActive and mostActive, then startMonitoring() will
+ * be the most recent call. Otherwise, stopMonitoring() is the most recent call.
+ */
+public class DeviceIdleConstraintTracker {
+
+ /**
+ * Appears in "dumpsys deviceidle".
+ */
+ public final String name;
+
+ /**
+ * Whenever a constraint is active, it will keep the device at or above
+ * minState (provided the rule is currently in effect).
+ *
+ */
+ public final int minState;
+
+ /**
+ * Whether this constraint currently prevents going below {@link #minState}.
+ *
+ * When the state is set to exactly minState, active is automatically
+ * overwritten with {@code true}.
+ */
+ public boolean active = false;
+
+ /**
+ * Internal tracking for whether the {@link IDeviceIdleConstraint} on the other
+ * side has been told it needs to send updates.
+ */
+ public boolean monitoring = false;
+
+ public DeviceIdleConstraintTracker(final String name, int minState) {
+ this.name = name;
+ this.minState = minState;
+ }
+}
diff --git a/services/core/java/com/android/server/deviceidle/IDeviceIdleConstraint.java b/services/core/java/com/android/server/deviceidle/IDeviceIdleConstraint.java
new file mode 100644
index 000000000000..f1f957307716
--- /dev/null
+++ b/services/core/java/com/android/server/deviceidle/IDeviceIdleConstraint.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.deviceidle;
+
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Implemented by OEM and/or Form Factor. System ones are built into the
+ * image regardless of build flavour but may still be switched off at run time.
+ * Individual feature flags at build time control which are used. We may
+ * also explore a local override for quick testing.
+ */
+public interface IDeviceIdleConstraint {
+
+ /**
+ * A state for this constraint to block descent from.
+ *
+ * <p>These states are a subset of the states in DeviceIdleController that make sense for
+ * constraints to be able to block on. For example, {@link #SENSING_OR_ABOVE} clearly has
+ * defined "above" and "below" states. However, a hypothetical {@code QUICK_DOZE_OR_ABOVE}
+ * state would not have clear semantics as to what transitions should be blocked and which
+ * should be allowed.
+ */
+ @IntDef(flag = false, value = {
+ ACTIVE,
+ SENSING_OR_ABOVE,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ @interface MinimumState {}
+
+ int ACTIVE = 0;
+ int SENSING_OR_ABOVE = 1;
+
+ /**
+ * Begin tracking events for this constraint.
+ *
+ * <p>The device idle controller has reached a point where it is waiting for the all-clear
+ * from this tracker (possibly among others) in order to continue with progression into
+ * idle state. It will not proceed until one of the following happens:
+ * <ul>
+ * <li>The constraint reports inactive with {@code .setActive(false)}.</li>
+ * <li>The constraint is unregistered with {@code .unregisterDeviceIdleConstraint(this)}.</li>
+ * <li>A transition timeout in DeviceIdleController fires.
+ * </ul>
+ */
+ void startMonitoring();
+
+ /** Stop checking for new events and do not call into LocalService with updates any more. */
+ void stopMonitoring();
+}
diff --git a/services/core/java/com/android/server/deviceidle/TvConstraintController.java b/services/core/java/com/android/server/deviceidle/TvConstraintController.java
new file mode 100644
index 000000000000..2d472de6f5e1
--- /dev/null
+++ b/services/core/java/com/android/server/deviceidle/TvConstraintController.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.deviceidle;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Handler;
+
+import com.android.server.DeviceIdleController;
+import com.android.server.LocalServices;
+
+/**
+ * Device idle constraints for television devices.
+ *
+ * <p>Televisions are devices with {@code FEATURE_LEANBACK_ONLY}. Other devices might support
+ * some kind of leanback mode but they should not follow the same rules for idle state.
+ */
+public class TvConstraintController implements ConstraintController {
+ private final Context mContext;
+ private final Handler mHandler;
+ private final DeviceIdleController.LocalService mDeviceIdleService;
+
+ @Nullable
+ private final BluetoothConstraint mBluetoothConstraint;
+
+ public TvConstraintController(Context context, Handler handler) {
+ mContext = context;
+ mHandler = handler;
+ mDeviceIdleService = LocalServices.getService(DeviceIdleController.LocalService.class);
+
+ final PackageManager pm = context.getPackageManager();
+ mBluetoothConstraint = pm.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)
+ ? new BluetoothConstraint(mContext, mHandler, mDeviceIdleService)
+ : null;
+ }
+
+ @Override
+ public void start() {
+ if (mBluetoothConstraint != null) {
+ mDeviceIdleService.registerDeviceIdleConstraint(
+ mBluetoothConstraint, "bluetooth", IDeviceIdleConstraint.SENSING_OR_ABOVE);
+ }
+ }
+
+ @Override
+ public void stop() {
+ if (mBluetoothConstraint != null) {
+ mDeviceIdleService.unregisterDeviceIdleConstraint(mBluetoothConstraint);
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
index 8e3f35111268..918dc07835be 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodUtils.java
@@ -38,11 +38,11 @@ import android.util.Slog;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodSubtype;
import android.view.textservice.SpellCheckerInfo;
-import android.view.textservice.TextServicesManager;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.inputmethod.StartInputFlags;
+import com.android.server.textservices.TextServicesManagerInternal;
import java.util.ArrayList;
import java.util.Arrays;
@@ -641,7 +641,7 @@ final class InputMethodUtils {
}
// Only the current spell checker should be treated as an enabled one.
final SpellCheckerInfo currentSpellChecker =
- TextServicesManager.getInstance().getCurrentSpellChecker();
+ TextServicesManagerInternal.get().getCurrentSpellCheckerForUser(userId);
for (final String packageName : systemImesDisabledUntilUsed) {
if (DEBUG) {
Slog.d(TAG, "check " + packageName);
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 0f060fe09318..9c6cb20b88b6 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -170,7 +170,7 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
private static final int GPS_CAPABILITY_SINGLE_SHOT = 0x0000008;
private static final int GPS_CAPABILITY_ON_DEMAND_TIME = 0x0000010;
private static final int GPS_CAPABILITY_GEOFENCING = 0x0000020;
- private static final int GPS_CAPABILITY_MEASUREMENTS = 0x0000040;
+ public static final int GPS_CAPABILITY_MEASUREMENTS = 0x0000040;
private static final int GPS_CAPABILITY_NAV_MESSAGES = 0x0000080;
// The AGPS SUPL mode
@@ -1607,20 +1607,20 @@ public class GnssLocationProvider extends AbstractLocationProvider implements
@NativeEntryPoint
private void setEngineCapabilities(final int capabilities) {
// send to handler thread for fast native return, and in-order handling
- mHandler.post(() -> {
- mEngineCapabilities = capabilities;
+ mHandler.post(
+ () -> {
+ mEngineCapabilities = capabilities;
- if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) {
- mNtpTimeHelper.enablePeriodicTimeInjection();
- requestUtcTime();
- }
+ if (hasCapability(GPS_CAPABILITY_ON_DEMAND_TIME)) {
+ mNtpTimeHelper.enablePeriodicTimeInjection();
+ requestUtcTime();
+ }
- mGnssMeasurementsProvider.onCapabilitiesUpdated(hasCapability(
- GPS_CAPABILITY_MEASUREMENTS));
- mGnssNavigationMessageProvider.onCapabilitiesUpdated(hasCapability(
- GPS_CAPABILITY_NAV_MESSAGES));
- restartRequests();
- });
+ mGnssMeasurementsProvider.onCapabilitiesUpdated(capabilities);
+ mGnssNavigationMessageProvider.onCapabilitiesUpdated(
+ hasCapability(GPS_CAPABILITY_NAV_MESSAGES));
+ restartRequests();
+ });
}
private void restartRequests() {
diff --git a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
index 3e2ba87a033e..77dee8241bea 100644
--- a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
@@ -17,6 +17,7 @@
package com.android.server.location;
import android.content.Context;
+import android.location.GnssMeasurementCorrections;
import android.location.GnssMeasurementsEvent;
import android.location.IGnssMeasurementsListener;
import android.os.Handler;
@@ -27,14 +28,13 @@ import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
/**
- * An base implementation for GPS measurements provider.
- * It abstracts out the responsibility of handling listeners, while still allowing technology
- * specific implementations to be built.
+ * An base implementation for GPS measurements provider. It abstracts out the responsibility of
+ * handling listeners, while still allowing technology specific implementations to be built.
*
* @hide
*/
-public abstract class GnssMeasurementsProvider extends
- RemoteListenerHelper<IGnssMeasurementsListener> {
+public abstract class GnssMeasurementsProvider
+ extends RemoteListenerHelper<IGnssMeasurementsListener> {
private static final String TAG = "GnssMeasurementsProvider";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -42,19 +42,19 @@ public abstract class GnssMeasurementsProvider extends
private boolean mIsCollectionStarted;
private boolean mEnableFullTracking;
+ private int mGnssEngineCapabilities;
protected GnssMeasurementsProvider(Context context, Handler handler) {
this(context, handler, new GnssMeasurementProviderNative());
}
@VisibleForTesting
- GnssMeasurementsProvider(Context context, Handler handler,
- GnssMeasurementProviderNative aNative) {
+ GnssMeasurementsProvider(
+ Context context, Handler handler, GnssMeasurementProviderNative aNative) {
super(context, handler, TAG);
mNative = aNative;
}
- // TODO(b/37460011): Use this with death recovery logic.
void resumeIfStarted() {
if (DEBUG) {
Log.d(TAG, "resumeIfStarted");
@@ -87,6 +87,25 @@ public abstract class GnssMeasurementsProvider extends
}
}
+ /**
+ * Injects GNSS measurement corrections into the GNSS chipset.
+ *
+ * @param measurementCorrections a {@link GnssMeasurementCorrections} object with the GNSS
+ * measurement corrections to be injected into the GNSS chipset.
+ */
+ public void injectGnssMeasurementCorrections(
+ GnssMeasurementCorrections measurementCorrections) {
+ mHandler.post(
+ new Runnable() {
+ @Override
+ public void run() {
+ if (!mNative.injectGnssMeasurementCorrections(measurementCorrections)) {
+ Log.e(TAG, "Failure in injecting GNSS corrections.");
+ }
+ }
+ });
+ }
+
@Override
protected void unregisterFromService() {
boolean stopped = mNative.stopMeasurementCollection();
@@ -96,20 +115,31 @@ public abstract class GnssMeasurementsProvider extends
}
public void onMeasurementsAvailable(final GnssMeasurementsEvent event) {
- foreach((IGnssMeasurementsListener listener, int uid, String packageName) -> {
- if (!hasPermission(uid, packageName)) {
- logPermissionDisabledEventNotReported(TAG, packageName, "GNSS measurements");
- return;
- }
- listener.onGnssMeasurementsReceived(event);
- });
+ foreach(
+ (IGnssMeasurementsListener listener, int uid, String packageName) -> {
+ if (!hasPermission(uid, packageName)) {
+ logPermissionDisabledEventNotReported(
+ TAG, packageName, "GNSS measurements");
+ return;
+ }
+ listener.onGnssMeasurementsReceived(event);
+ });
}
- public void onCapabilitiesUpdated(boolean isGnssMeasurementsSupported) {
+ /** Updates the framework about the capabilities of the GNSS chipset */
+ public void onCapabilitiesUpdated(int capabilities) {
+ mGnssEngineCapabilities = capabilities;
+ boolean isGnssMeasurementsSupported =
+ (capabilities & GnssLocationProvider.GPS_CAPABILITY_MEASUREMENTS) != 0;
setSupported(isGnssMeasurementsSupported);
updateResult();
}
+ /** Obtains the GNSS engine capabilities. */
+ public int getGnssCapabilities() {
+ return mGnssEngineCapabilities;
+ }
+
public void onGpsEnabledChanged() {
tryUpdateRegistrationWithService();
updateResult();
@@ -170,6 +200,11 @@ public abstract class GnssMeasurementsProvider extends
public boolean stopMeasurementCollection() {
return native_stop_measurement_collection();
}
+
+ public boolean injectGnssMeasurementCorrections(
+ GnssMeasurementCorrections measurementCorrections) {
+ return native_inject_gnss_measurement_corrections(measurementCorrections);
+ }
}
private static native boolean native_is_measurement_supported();
@@ -177,4 +212,7 @@ public abstract class GnssMeasurementsProvider extends
private static native boolean native_start_measurement_collection(boolean enableFullTracking);
private static native boolean native_stop_measurement_collection();
+
+ private static native boolean native_inject_gnss_measurement_corrections(
+ GnssMeasurementCorrections measurementCorrections);
}
diff --git a/services/core/java/com/android/server/location/RemoteListenerHelper.java b/services/core/java/com/android/server/location/RemoteListenerHelper.java
index 37d43fc1da69..e69b2ec28ebc 100644
--- a/services/core/java/com/android/server/location/RemoteListenerHelper.java
+++ b/services/core/java/com/android/server/location/RemoteListenerHelper.java
@@ -43,7 +43,7 @@ abstract class RemoteListenerHelper<TListener extends IInterface> {
protected static final int RESULT_UNKNOWN = 5;
protected static final int RESULT_NOT_ALLOWED = 6;
- private final Handler mHandler;
+ protected final Handler mHandler;
private final String mTag;
private final Map<IBinder, LinkedListener> mListenerMap = new HashMap<>();
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 2359c2a02863..d961bad1cf59 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -4939,7 +4939,7 @@ public class NotificationManagerService extends SystemService {
Slog.e(TAG, "Not posting notification without small icon: " + notification);
if (old != null && !old.isCanceled) {
mListeners.notifyRemovedLocked(r,
- NotificationListenerService.REASON_ERROR, null);
+ NotificationListenerService.REASON_ERROR, r.getStats());
mHandler.post(new Runnable() {
@Override
public void run() {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 0d0db9457672..35ffe8d5fa95 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -1065,6 +1065,7 @@ public class PackageInstallerSession extends IPackageInstallerSession.Stub {
if (isStaged()) {
// STOPSHIP: implement staged sessions
mStagedSessionReady = true;
+ mPm.sendSessionUpdatedBroadcast(generateInfo(), userId);
dispatchSessionFinished(PackageManager.INSTALL_SUCCEEDED, "Session staged", null);
return;
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 6453db5db1b6..af1263321d5f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -325,7 +325,6 @@ import dalvik.system.VMRuntime;
import libcore.io.IoUtils;
import libcore.util.EmptyArray;
-import libcore.util.HexEncoding;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -2225,9 +2224,7 @@ public class PackageManagerService extends IPackageManager.Stub
for (int i = 0; i < builtInLibCount; i++) {
String name = libConfig.keyAt(i);
SystemConfig.SharedLibraryEntry entry = libConfig.valueAt(i);
- addSharedLibraryLPw(entry.filename, null, null, name,
- SharedLibraryInfo.VERSION_UNDEFINED, SharedLibraryInfo.TYPE_BUILTIN,
- PLATFORM_PACKAGE_NAME, 0);
+ addBuiltInSharedLibraryLocked(entry.filename, name);
}
// Now that we have added all the libraries, iterate again to add dependency
@@ -8744,8 +8741,15 @@ public class PackageManagerService extends IPackageManager.Stub
if (scanResult.success) {
synchronized (mPackages) {
try {
+ final Map<String, ReconciledPackage> reconcileResult =
+ reconcilePackagesLocked(new ReconcileRequest(
+ Collections.singletonMap(scanResult.pkgSetting.name,
+ scanResult),
+ mSharedLibraries,
+ mPackages));
prepareScanResultLocked(scanResult);
- commitScanResultLocked(scanResult);
+ commitReconciledScanResultLocked(
+ reconcileResult.get(scanResult.pkgSetting.name));
} catch (PackageManagerException e) {
unprepareScanResultLocked(scanResult);
throw e;
@@ -9352,8 +9356,26 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
- private @Nullable SharedLibraryInfo getSharedLibraryInfoLPr(String name, long version) {
- LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
+ @Nullable
+ private SharedLibraryInfo getSharedLibraryInfoLPr(String name, long version) {
+ return getSharedLibraryInfo(name, version, mSharedLibraries, null);
+ }
+
+ @Nullable
+ private static SharedLibraryInfo getSharedLibraryInfo(String name, long version,
+ Map<String, LongSparseArray<SharedLibraryInfo>> existingLibraries,
+ @Nullable Map<String, LongSparseArray<SharedLibraryInfo>> newLibraries) {
+ if (newLibraries != null) {
+ final LongSparseArray<SharedLibraryInfo> versionedLib = newLibraries.get(name);
+ SharedLibraryInfo info = null;
+ if (versionedLib != null) {
+ info = versionedLib.get(version);
+ }
+ if (info != null) {
+ return info;
+ }
+ }
+ final LongSparseArray<SharedLibraryInfo> versionedLib = existingLibraries.get(name);
if (versionedLib == null) {
return null;
}
@@ -9681,35 +9703,50 @@ public class PackageManagerService extends IPackageManager.Stub
@GuardedBy("mPackages")
private void updateSharedLibrariesLPr(PackageParser.Package pkg,
PackageParser.Package changingLib) throws PackageManagerException {
+ final ArrayList<SharedLibraryInfo> sharedLibraryInfos =
+ collectSharedLibraryInfos(pkg, Collections.unmodifiableMap(mPackages),
+ mSharedLibraries, null);
+ executeSharedLibrariesUpdateLPr(pkg, changingLib, sharedLibraryInfos);
+ }
+
+ private static ArrayList<SharedLibraryInfo> collectSharedLibraryInfos(PackageParser.Package pkg,
+ Map<String, PackageParser.Package> availablePackages,
+ @NonNull final Map<String, LongSparseArray<SharedLibraryInfo>> existingLibraries,
+ @Nullable final Map<String, LongSparseArray<SharedLibraryInfo>> newLibraries)
+ throws PackageManagerException {
if (pkg == null) {
- return;
+ return null;
}
-
- // If the package provides libraries, clear their old dependencies.
- // This method will set them up again.
- applyDefiningSharedLibraryUpdateLocked(pkg, null, (definingLibrary, dependency) -> {
- definingLibrary.clearDependencies();
- });
// The collection used here must maintain the order of addition (so
// that libraries are searched in the correct order) and must have no
// duplicates.
ArrayList<SharedLibraryInfo> usesLibraryInfos = null;
if (pkg.usesLibraries != null) {
- usesLibraryInfos = addSharedLibrariesLPw(pkg.usesLibraries,
- null, null, pkg.packageName, true,
- pkg.applicationInfo.targetSdkVersion, null);
+ usesLibraryInfos = collectSharedLibraryInfos(pkg.usesLibraries, null, null,
+ pkg.packageName, true, pkg.applicationInfo.targetSdkVersion, null,
+ availablePackages, existingLibraries, newLibraries);
}
if (pkg.usesStaticLibraries != null) {
- usesLibraryInfos = addSharedLibrariesLPw(pkg.usesStaticLibraries,
+ usesLibraryInfos = collectSharedLibraryInfos(pkg.usesStaticLibraries,
pkg.usesStaticLibrariesVersions, pkg.usesStaticLibrariesCertDigests,
- pkg.packageName, true,
- pkg.applicationInfo.targetSdkVersion, usesLibraryInfos);
+ pkg.packageName, true, pkg.applicationInfo.targetSdkVersion, usesLibraryInfos,
+ availablePackages, existingLibraries, newLibraries);
}
if (pkg.usesOptionalLibraries != null) {
- usesLibraryInfos = addSharedLibrariesLPw(pkg.usesOptionalLibraries,
- null, null, pkg.packageName, false,
- pkg.applicationInfo.targetSdkVersion, usesLibraryInfos);
+ usesLibraryInfos = collectSharedLibraryInfos(pkg.usesOptionalLibraries,
+ null, null, pkg.packageName, false, pkg.applicationInfo.targetSdkVersion,
+ usesLibraryInfos, availablePackages, existingLibraries, newLibraries);
}
+ return usesLibraryInfos;
+ }
+
+ private void executeSharedLibrariesUpdateLPr(PackageParser.Package pkg,
+ PackageParser.Package changingLib, ArrayList<SharedLibraryInfo> usesLibraryInfos) {
+ // If the package provides libraries, clear their old dependencies.
+ // This method will set them up again.
+ applyDefiningSharedLibraryUpdateLocked(pkg, null, (definingLibrary, dependency) -> {
+ definingLibrary.clearDependencies();
+ });
if (usesLibraryInfos != null) {
pkg.usesLibraryInfos = usesLibraryInfos;
// Use LinkedHashSet to preserve the order of files added to
@@ -9726,18 +9763,22 @@ public class PackageManagerService extends IPackageManager.Stub
}
@GuardedBy("mPackages")
- private ArrayList<SharedLibraryInfo> addSharedLibrariesLPw(
+ private static ArrayList<SharedLibraryInfo> collectSharedLibraryInfos(
@NonNull List<String> requestedLibraries,
@Nullable long[] requiredVersions, @Nullable String[][] requiredCertDigests,
@NonNull String packageName, boolean required, int targetSdk,
- @Nullable ArrayList<SharedLibraryInfo> outUsedLibraries)
+ @Nullable ArrayList<SharedLibraryInfo> outUsedLibraries,
+ @NonNull final Map<String, PackageParser.Package> availablePackages,
+ @NonNull final Map<String, LongSparseArray<SharedLibraryInfo>> existingLibraries,
+ @Nullable final Map<String, LongSparseArray<SharedLibraryInfo>> newLibraries)
throws PackageManagerException {
final int libCount = requestedLibraries.size();
for (int i = 0; i < libCount; i++) {
final String libName = requestedLibraries.get(i);
final long libVersion = requiredVersions != null ? requiredVersions[i]
: SharedLibraryInfo.VERSION_UNDEFINED;
- final SharedLibraryInfo libraryInfo = getSharedLibraryInfoLPr(libName, libVersion);
+ final SharedLibraryInfo libraryInfo = getSharedLibraryInfo(libName, libVersion,
+ existingLibraries, newLibraries);
if (libraryInfo == null) {
if (required) {
throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
@@ -9757,7 +9798,8 @@ public class PackageManagerService extends IPackageManager.Stub
+ libraryInfo.getLongVersion() + "; failing!");
}
- PackageParser.Package libPkg = mPackages.get(libraryInfo.getPackageName());
+ PackageParser.Package libPkg =
+ availablePackages.get(libraryInfo.getPackageName());
if (libPkg == null) {
throw new PackageManagerException(INSTALL_FAILED_MISSING_SHARED_LIBRARY,
"Package " + packageName + " requires unavailable static shared"
@@ -9930,15 +9972,24 @@ public class PackageManagerService extends IPackageManager.Stub
@Nullable public final PackageSetting pkgSetting;
/** ABI code paths that have changed in the package scan */
@Nullable public final List<String> changedAbiCodePath;
+
+ public final SharedLibraryInfo staticSharedLibraryInfo;
+
+ public final List<SharedLibraryInfo> dynamicSharedLibraryInfos;
+
public ScanResult(
ScanRequest request, boolean success,
@Nullable PackageSetting pkgSetting,
- @Nullable List<String> changedAbiCodePath, boolean existingSettingCopied) {
+ @Nullable List<String> changedAbiCodePath, boolean existingSettingCopied,
+ SharedLibraryInfo staticSharedLibraryInfo,
+ List<SharedLibraryInfo> dynamicSharedLibraryInfos) {
this.request = request;
this.success = success;
this.pkgSetting = pkgSetting;
this.changedAbiCodePath = changedAbiCodePath;
this.existingSettingCopied = existingSettingCopied;
+ this.staticSharedLibraryInfo = staticSharedLibraryInfo;
+ this.dynamicSharedLibraryInfos = dynamicSharedLibraryInfos;
}
}
@@ -10136,29 +10187,6 @@ public class PackageManagerService extends IPackageManager.Stub
}
- private void commitSuccessfulScanResults(@NonNull List<ScanResult> results)
- throws PackageManagerException {
- synchronized(mPackages) {
- for (ScanResult result : results) {
- // failures should have been caught earlier, but in case it wasn't,
- // let's double check
- if (!result.success) {
- throw new PackageManagerException(
- "Scan failed for " + result.request.pkg.packageName);
- }
- }
- for (ScanResult result : results) {
- try {
- prepareScanResultLocked(result);
- commitScanResultLocked(result);
- } catch (PackageManagerException e) {
- unprepareScanResultLocked(result);
- throw e;
- }
- }
- }
- }
-
/** Prepares the system to commit a {@link ScanResult} in a way that will not fail. */
private void prepareScanResultLocked(@NonNull ScanResult result)
throws PackageManagerException {
@@ -10191,7 +10219,9 @@ public class PackageManagerService extends IPackageManager.Stub
* possible and the system is not left in an inconsistent state.
*/
@GuardedBy({"mPackages", "mInstallLock"})
- private void commitScanResultLocked(@NonNull ScanResult result) throws PackageManagerException {
+ private void commitReconciledScanResultLocked(@NonNull ReconciledPackage reconciledPkg)
+ throws PackageManagerException {
+ final ScanResult result = reconciledPkg.scanResult;
final ScanRequest request = result.request;
final PackageParser.Package pkg = request.pkg;
final PackageParser.Package oldPkg = request.oldPkg;
@@ -10235,19 +10265,8 @@ public class PackageManagerService extends IPackageManager.Stub
mTransferedPackages.add(pkg.packageName);
}
- // THROWS: when requested libraries that can't be found. it only changes
- // the state of the passed in pkg object, so, move to the top of the method
- // and allow it to abort
- if ((scanFlags & SCAN_BOOTING) == 0
- && (parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
- // Check all shared libraries and map to their actual file path.
- // We only do this here for apps not on a system dir, because those
- // are the only ones that can fail an install due to this. We
- // will take care of the system apps by updating all of their
- // library paths after the scan is done. Also during the initial
- // scan don't update any libs as we do this wholesale after all
- // apps are scanned to avoid dependency based scanning.
- updateSharedLibrariesLPr(pkg, null);
+ if (reconciledPkg.collectedSharedLibraryInfos != null) {
+ executeSharedLibrariesUpdateLPr(pkg, null, reconciledPkg.collectedSharedLibraryInfos);
}
// All versions of a static shared library are referenced with the same
@@ -10396,8 +10415,8 @@ public class PackageManagerService extends IPackageManager.Stub
} else {
final int userId = user == null ? 0 : user.getIdentifier();
// Modify state for the given package setting
- commitPackageSettings(pkg, oldPkg, pkgSetting, user, scanFlags,
- (parseFlags & PackageParser.PARSE_CHATTY) != 0 /*chatty*/);
+ commitPackageSettings(pkg, oldPkg, pkgSetting, scanFlags,
+ (parseFlags & PackageParser.PARSE_CHATTY) != 0 /*chatty*/, reconciledPkg);
if (pkgSetting.getInstantApp(userId)) {
mInstantAppRegistry.addInstantAppLPw(userId, pkgSetting.appId);
}
@@ -10568,11 +10587,10 @@ public class PackageManagerService extends IPackageManager.Stub
UserManagerService.getInstance(), usesStaticLibraries,
pkg.usesStaticLibrariesVersions);
} else {
- if (!createNewPackage) {
- // make a deep copy to avoid modifying any existing system state.
- pkgSetting = new PackageSetting(pkgSetting);
- pkgSetting.pkg = pkg;
- }
+ // make a deep copy to avoid modifying any existing system state.
+ pkgSetting = new PackageSetting(pkgSetting);
+ pkgSetting.pkg = pkg;
+
// REMOVE SharedUserSetting from method; update in a separate call.
//
// TODO(narayan): This update is bogus. nativeLibraryDir & primaryCpuAbi,
@@ -10791,8 +10809,21 @@ public class PackageManagerService extends IPackageManager.Stub
pkgSetting.volumeUuid = volumeUuid;
}
+ SharedLibraryInfo staticSharedLibraryInfo = null;
+ if (!TextUtils.isEmpty(pkg.staticSharedLibName)) {
+ staticSharedLibraryInfo = SharedLibraryInfo.createForStatic(pkg);
+ }
+ List<SharedLibraryInfo> dynamicSharedLibraryInfos = null;
+ if (!ArrayUtils.isEmpty(pkg.libraryNames)) {
+ dynamicSharedLibraryInfos = new ArrayList<>(pkg.libraryNames.size());
+ for (String name : pkg.libraryNames) {
+ dynamicSharedLibraryInfos.add(SharedLibraryInfo.createForDynamic(pkg, name));
+ }
+ }
+
return new ScanResult(request, true, pkgSetting, changedAbiCodePath,
- !createNewPackage /* existingSettingCopied */);
+ !createNewPackage /* existingSettingCopied */, staticSharedLibraryInfo,
+ dynamicSharedLibraryInfos);
}
/**
@@ -11302,24 +11333,48 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
- private boolean addSharedLibraryLPw(String path, String apk, List<String> codePaths,
- String name, long version, int type, String declaringPackageName,
- long declaringVersionCode) {
+ @GuardedBy("mPackages")
+ private boolean addBuiltInSharedLibraryLocked(String path, String name) {
+ if (nonStaticSharedLibExistsLocked(name)) {
+ return false;
+ }
+
+ SharedLibraryInfo libraryInfo = new SharedLibraryInfo(path, null, null, name,
+ (long) SharedLibraryInfo.VERSION_UNDEFINED, SharedLibraryInfo.TYPE_BUILTIN,
+ new VersionedPackage(PLATFORM_PACKAGE_NAME, (long) 0),
+ null, null);
+
+ commitSharedLibraryInfoLocked(libraryInfo);
+ return true;
+ }
+
+ @GuardedBy("mPackages")
+ private boolean nonStaticSharedLibExistsLocked(String name) {
+ return sharedLibExists(name, SharedLibraryInfo.VERSION_UNDEFINED, mSharedLibraries);
+ }
+
+ private static boolean sharedLibExists(final String name, final long version,
+ Map<String, LongSparseArray<SharedLibraryInfo>> librarySource) {
+ LongSparseArray<SharedLibraryInfo> versionedLib = librarySource.get(name);
+ if (versionedLib != null && versionedLib.indexOfKey(version) >= 0) {
+ return true;
+ }
+ return false;
+ }
+
+ @GuardedBy("mPackages")
+ private void commitSharedLibraryInfoLocked(SharedLibraryInfo libraryInfo) {
+ final String name = libraryInfo.getName();
LongSparseArray<SharedLibraryInfo> versionedLib = mSharedLibraries.get(name);
if (versionedLib == null) {
versionedLib = new LongSparseArray<>();
mSharedLibraries.put(name, versionedLib);
- if (type == SharedLibraryInfo.TYPE_STATIC) {
- mStaticLibsByDeclaringPackage.put(declaringPackageName, versionedLib);
- }
- } else if (versionedLib.indexOfKey(version) >= 0) {
- return false;
}
- SharedLibraryInfo libraryInfo = new SharedLibraryInfo(path, apk, codePaths, name,
- version, type, new VersionedPackage(declaringPackageName, declaringVersionCode),
- null, null);
- versionedLib.put(version, libraryInfo);
- return true;
+ final String declaringPackageName = libraryInfo.getDeclaringPackage().getPackageName();
+ if (libraryInfo.getType() == SharedLibraryInfo.TYPE_STATIC) {
+ mStaticLibsByDeclaringPackage.put(declaringPackageName, versionedLib);
+ }
+ versionedLib.put(libraryInfo.getLongVersion(), libraryInfo);
}
private boolean removeSharedLibraryLPw(String name, long version) {
@@ -11348,8 +11403,8 @@ public class PackageManagerService extends IPackageManager.Stub
* be available for query, resolution, etc...
*/
private void commitPackageSettings(PackageParser.Package pkg,
- @Nullable PackageParser.Package oldPkg, PackageSetting pkgSetting, UserHandle user,
- final @ScanFlags int scanFlags, boolean chatty) {
+ @Nullable PackageParser.Package oldPkg, PackageSetting pkgSetting,
+ final @ScanFlags int scanFlags, boolean chatty, ReconciledPackage reconciledPkg) {
final String pkgName = pkg.packageName;
if (mCustomResolverComponentName != null &&
mCustomResolverComponentName.getPackageName().equals(pkg.packageName)) {
@@ -11396,91 +11451,24 @@ public class PackageManagerService extends IPackageManager.Stub
ArrayList<PackageParser.Package> clientLibPkgs = null;
// writer
synchronized (mPackages) {
- boolean hasStaticSharedLibs = false;
-
- // Any app can add new static shared libraries
- if (pkg.staticSharedLibName != null) {
- // Static shared libs don't allow renaming as they have synthetic package
- // names to allow install of multiple versions, so use name from manifest.
- if (addSharedLibraryLPw(null, pkg.packageName, pkg.getAllCodePaths(),
- pkg.staticSharedLibName,
- pkg.staticSharedLibVersion, SharedLibraryInfo.TYPE_STATIC,
- pkg.manifestPackageName, pkg.getLongVersionCode())) {
- hasStaticSharedLibs = true;
+ if (!ArrayUtils.isEmpty(reconciledPkg.allowedSharedLibraryInfos)) {
+ for (SharedLibraryInfo info : reconciledPkg.allowedSharedLibraryInfos) {
+ commitSharedLibraryInfoLocked(info);
+ }
+ try {
// Shared libraries for the package need to be updated.
- try {
- updateSharedLibrariesLPr(pkg, null);
- } catch (PackageManagerException e) {
- Slog.e(TAG, "updateSharedLibrariesLPr failed: ", e);
- }
- } else {
- Slog.w(TAG, "Package " + pkg.packageName + " library "
- + pkg.staticSharedLibName + " already exists; skipping");
- }
- // Static shared libs cannot be updated once installed since they
- // use synthetic package name which includes the version code, so
- // not need to update other packages's shared lib dependencies.
- }
-
- if (!hasStaticSharedLibs
- && (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
- // Only system apps can add new dynamic shared libraries.
- if (pkg.libraryNames != null) {
- for (int i = 0; i < pkg.libraryNames.size(); i++) {
- String name = pkg.libraryNames.get(i);
- boolean allowed = false;
- if (pkg.isUpdatedSystemApp()) {
- // New library entries can only be added through the
- // system image. This is important to get rid of a lot
- // of nasty edge cases: for example if we allowed a non-
- // system update of the app to add a library, then uninstalling
- // the update would make the library go away, and assumptions
- // we made such as through app install filtering would now
- // have allowed apps on the device which aren't compatible
- // with it. Better to just have the restriction here, be
- // conservative, and create many fewer cases that can negatively
- // impact the user experience.
- final PackageSetting sysPs = mSettings
- .getDisabledSystemPkgLPr(pkg.packageName);
- if (sysPs.pkg != null && sysPs.pkg.libraryNames != null) {
- for (int j = 0; j < sysPs.pkg.libraryNames.size(); j++) {
- if (name.equals(sysPs.pkg.libraryNames.get(j))) {
- allowed = true;
- break;
- }
- }
- }
- } else {
- allowed = true;
- }
- if (allowed) {
- if (!addSharedLibraryLPw(null, pkg.packageName, pkg.getAllCodePaths(),
- name, SharedLibraryInfo.VERSION_UNDEFINED,
- SharedLibraryInfo.TYPE_DYNAMIC,
- pkg.packageName, pkg.getLongVersionCode())) {
- Slog.w(TAG, "Package " + pkg.packageName + " library "
- + name + " already exists; skipping");
- }
- // Shared libraries for the package need to be updated.
- try {
- updateSharedLibrariesLPr(pkg, null);
- } catch (PackageManagerException e) {
- Slog.e(TAG, "updateSharedLibrariesLPr failed: ", e);
- }
- } else {
- Slog.w(TAG, "Package " + pkg.packageName + " declares lib "
- + name + " that is not declared on system image; skipping");
- }
- }
-
- if ((scanFlags & SCAN_BOOTING) == 0) {
- // If we are not booting, we need to update any applications
- // that are clients of our shared library. If we are booting,
- // this will all be done once the scan is complete.
- clientLibPkgs = updateAllSharedLibrariesLPw(pkg);
- }
+ updateSharedLibrariesLPr(pkg, null);
+ } catch (PackageManagerException e) {
+ Slog.e(TAG, "updateSharedLibrariesLPr failed: ", e);
}
}
+
+ if (reconciledPkg.hasDynamicSharedLibraries() && (scanFlags & SCAN_BOOTING) == 0) {
+ // If we are not booting, we need to update any applications
+ // that are clients of our shared library. If we are booting,
+ // this will all be done once the scan is complete.
+ clientLibPkgs = updateAllSharedLibrariesLPw(pkg);
+ }
}
if ((scanFlags & SCAN_BOOTING) != 0) {
@@ -15235,8 +15223,8 @@ public class PackageManagerService extends IPackageManager.Stub
private static class ReconcileRequest {
public final Map<String, ScanResult> scannedPackages;
- // TODO: Remove install-specific details from reconcile request; make them generic types
- // that can be used for scanDir for example.
+ public final Map<String, PackageParser.Package> allPackages;
+ public final Map<String, LongSparseArray<SharedLibraryInfo>> sharedLibrarySource;
public final Map<String, InstallArgs> installArgs;
public final Map<String, PackageInstalledInfo> installResults;
public final Map<String, PrepareResult> preparedPackages;
@@ -15244,11 +15232,22 @@ public class PackageManagerService extends IPackageManager.Stub
private ReconcileRequest(Map<String, ScanResult> scannedPackages,
Map<String, InstallArgs> installArgs,
Map<String, PackageInstalledInfo> installResults,
- Map<String, PrepareResult> preparedPackages) {
+ Map<String, PrepareResult> preparedPackages,
+ Map<String, LongSparseArray<SharedLibraryInfo>> sharedLibrarySource,
+ Map<String, PackageParser.Package> allPackages) {
this.scannedPackages = scannedPackages;
this.installArgs = installArgs;
this.installResults = installResults;
this.preparedPackages = preparedPackages;
+ this.sharedLibrarySource = sharedLibrarySource;
+ this.allPackages = allPackages;
+ }
+
+ private ReconcileRequest(Map<String, ScanResult> scannedPackages,
+ Map<String, LongSparseArray<SharedLibraryInfo>> sharedLibrarySource,
+ Map<String, PackageParser.Package> allPackages) {
+ this(scannedPackages, Collections.emptyMap(), Collections.emptyMap(),
+ Collections.emptyMap(), sharedLibrarySource, allPackages);
}
}
private static class ReconcileFailure extends PackageManagerException {
@@ -15267,29 +15266,31 @@ public class PackageManagerService extends IPackageManager.Stub
private static class ReconciledPackage {
public final PackageSetting pkgSetting;
public final ScanResult scanResult;
- public final UserHandle installForUser;
- public final String volumeUuid;
// TODO: Remove install-specific details from the reconcile result
public final PackageInstalledInfo installResult;
- public final PrepareResult prepareResult;
- @PackageManager.InstallFlags
- public final int installFlags;
- public final InstallArgs installArgs;
+ @Nullable public final PrepareResult prepareResult;
+ @Nullable public final InstallArgs installArgs;
public final DeletePackageAction deletePackageAction;
+ public final List<SharedLibraryInfo> allowedSharedLibraryInfos;
+ public ArrayList<SharedLibraryInfo> collectedSharedLibraryInfos;
private ReconciledPackage(InstallArgs installArgs, PackageSetting pkgSetting,
- UserHandle installForUser, PackageInstalledInfo installResult, int installFlags,
- String volumeUuid, PrepareResult prepareResult, ScanResult scanResult,
- DeletePackageAction deletePackageAction) {
+ PackageInstalledInfo installResult,
+ PrepareResult prepareResult, ScanResult scanResult,
+ DeletePackageAction deletePackageAction,
+ List<SharedLibraryInfo> allowedSharedLibraryInfos) {
this.installArgs = installArgs;
this.pkgSetting = pkgSetting;
- this.installForUser = installForUser;
this.installResult = installResult;
- this.installFlags = installFlags;
- this.volumeUuid = volumeUuid;
this.prepareResult = prepareResult;
this.scanResult = scanResult;
this.deletePackageAction = deletePackageAction;
+ this.allowedSharedLibraryInfos = allowedSharedLibraryInfos;
+ }
+
+ public boolean hasDynamicSharedLibraries() {
+ return !ArrayUtils.isEmpty(allowedSharedLibraryInfos)
+ && allowedSharedLibraryInfos.get(0).getType() != SharedLibraryInfo.TYPE_STATIC;
}
}
@@ -15297,19 +15298,50 @@ public class PackageManagerService extends IPackageManager.Stub
private static Map<String, ReconciledPackage> reconcilePackagesLocked(
final ReconcileRequest request)
throws ReconcileFailure {
- Map<String, ReconciledPackage> result = new ArrayMap<>(request.scannedPackages.size());
- for (String installPackageName : request.installArgs.keySet()) {
- final ScanResult scanResult = request.scannedPackages.get(installPackageName);
+ final Map<String, ScanResult> scannedPackages = request.scannedPackages;
+
+ final Map<String, ReconciledPackage> result = new ArrayMap<>(scannedPackages.size());
+
+ // make a copy of the existing set of packages so we can combine them with incoming packages
+ final ArrayMap<String, PackageParser.Package> combinedPackages =
+ new ArrayMap<>(request.allPackages.size() + scannedPackages.size());
+ combinedPackages.putAll(request.allPackages);
+
+ final Map<String, LongSparseArray<SharedLibraryInfo>> incomingSharedLibraries =
+ new ArrayMap<>();
+
+ for (String installPackageName : scannedPackages.keySet()) {
+ final ScanResult scanResult = scannedPackages.get(installPackageName);
+
+ // add / replace existing with incoming packages
+ combinedPackages.put(scanResult.pkgSetting.name, scanResult.request.pkg);
+
+ // in the first pass, we'll build up the set of incoming shared libraries
+ final List<SharedLibraryInfo> allowedSharedLibInfos =
+ getAllowedSharedLibInfos(scanResult, request.sharedLibrarySource);
+ final SharedLibraryInfo staticLib = scanResult.staticSharedLibraryInfo;
+ if (allowedSharedLibInfos != null) {
+ for (SharedLibraryInfo info : allowedSharedLibInfos) {
+ if (!addSharedLibraryToPackageVersionMap(incomingSharedLibraries, info)) {
+ throw new ReconcileFailure("Static Shared Library " + staticLib.getName()
+ + " is being installed twice in this set!");
+ }
+ }
+ }
+
+ // the following may be null if we're just reconciling on boot (and not during install)
final InstallArgs installArgs = request.installArgs.get(installPackageName);
final PackageInstalledInfo res = request.installResults.get(installPackageName);
final PrepareResult prepareResult = request.preparedPackages.get(installPackageName);
- if (scanResult == null || installArgs == null || res == null) {
- throw new ReconcileFailure(
- "inputs not balanced; missing argument for " + installPackageName);
+ final boolean isInstall = installArgs != null;
+ if (isInstall && (res == null || prepareResult == null)) {
+ throw new ReconcileFailure("Reconcile arguments are not balanced for "
+ + installPackageName + "!");
}
+
final DeletePackageAction deletePackageAction;
// we only want to try to delete for non system apps
- if (prepareResult.replace && !prepareResult.system) {
+ if (isInstall && prepareResult.replace && !prepareResult.system) {
final boolean killApp = (scanResult.request.scanFlags & SCAN_DONT_KILL_APP) == 0;
final int deleteFlags = PackageManager.DELETE_KEEP_DATA
| (killApp ? 0 : PackageManager.DELETE_DONT_KILL_APP);
@@ -15324,15 +15356,127 @@ public class PackageManagerService extends IPackageManager.Stub
} else {
deletePackageAction = null;
}
+
result.put(installPackageName,
- new ReconciledPackage(installArgs, scanResult.pkgSetting, installArgs.getUser(),
- res, installArgs.installFlags, installArgs.volumeUuid,
- request.preparedPackages.get(installPackageName), scanResult,
- deletePackageAction));
+ new ReconciledPackage(installArgs, scanResult.pkgSetting,
+ res, request.preparedPackages.get(installPackageName), scanResult,
+ deletePackageAction, allowedSharedLibInfos));
}
+
+ for (String installPackageName : scannedPackages.keySet()) {
+ // Check all shared libraries and map to their actual file path.
+ // We only do this here for apps not on a system dir, because those
+ // are the only ones that can fail an install due to this. We
+ // will take care of the system apps by updating all of their
+ // library paths after the scan is done. Also during the initial
+ // scan don't update any libs as we do this wholesale after all
+ // apps are scanned to avoid dependency based scanning.
+ final ScanResult scanResult = scannedPackages.get(installPackageName);
+ if ((scanResult.request.scanFlags & SCAN_BOOTING) != 0
+ || (scanResult.request.parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
+ continue;
+ }
+ try {
+ result.get(installPackageName).collectedSharedLibraryInfos =
+ collectSharedLibraryInfos(scanResult.request.pkg, combinedPackages,
+ request.sharedLibrarySource, incomingSharedLibraries);
+
+ } catch (PackageManagerException e) {
+ throw new ReconcileFailure(e.error, e.getMessage());
+ }
+ }
+
return result;
}
+ private static List<SharedLibraryInfo> getAllowedSharedLibInfos(
+ ScanResult scanResult,
+ Map<String, LongSparseArray<SharedLibraryInfo>> existingSharedLibraries) {
+ final PackageParser.Package pkg = scanResult.pkgSetting.pkg;
+ if (scanResult.staticSharedLibraryInfo == null
+ && scanResult.dynamicSharedLibraryInfos == null) {
+ return null;
+ }
+
+ // Any app can add new static shared libraries
+ if (scanResult.staticSharedLibraryInfo != null) {
+ return Collections.singletonList(scanResult.staticSharedLibraryInfo);
+ }
+ final boolean hasDynamicLibraries =
+ (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0
+ && scanResult.dynamicSharedLibraryInfos != null;
+ if (!hasDynamicLibraries) {
+ return null;
+ }
+ final ArrayList<SharedLibraryInfo> infos =
+ new ArrayList<>(scanResult.dynamicSharedLibraryInfos.size());
+ final boolean updatedSystemApp = pkg.isUpdatedSystemApp();
+ for (SharedLibraryInfo info : scanResult.dynamicSharedLibraryInfos) {
+ String name = info.getName();
+ boolean allowed = false;
+ if (updatedSystemApp) {
+ // New library entries can only be added through the
+ // system image. This is important to get rid of a lot
+ // of nasty edge cases: for example if we allowed a non-
+ // system update of the app to add a library, then uninstalling
+ // the update would make the library go away, and assumptions
+ // we made such as through app install filtering would now
+ // have allowed apps on the device which aren't compatible
+ // with it. Better to just have the restriction here, be
+ // conservative, and create many fewer cases that can negatively
+ // impact the user experience.
+ final PackageSetting sysPs = scanResult.request.disabledPkgSetting;
+ if (sysPs.pkg != null && sysPs.pkg.libraryNames != null) {
+ for (int j = 0; j < sysPs.pkg.libraryNames.size(); j++) {
+ if (name.equals(sysPs.pkg.libraryNames.get(j))) {
+ allowed = true;
+ break;
+ }
+ }
+ }
+ } else {
+ allowed = true;
+ }
+ if (allowed) {
+ if (sharedLibExists(
+ name, SharedLibraryInfo.VERSION_UNDEFINED, existingSharedLibraries)) {
+ Slog.w(TAG, "Package " + pkg.packageName + " library "
+ + name + " already exists; skipping");
+ continue;
+ }
+ infos.add(info);
+ } else {
+ Slog.w(TAG, "Package " + pkg.packageName + " declares lib "
+ + name + " that is not declared on system image; skipping");
+ continue;
+ }
+ }
+ return infos;
+ }
+
+ /**
+ * Returns false if the adding shared library already exists in the map and so could not be
+ * added.
+ */
+ private static boolean addSharedLibraryToPackageVersionMap(
+ Map<String, LongSparseArray<SharedLibraryInfo>> target,
+ SharedLibraryInfo library) {
+ final String name = library.getName();
+ if (target.containsKey(name)) {
+ if (library.getType() != SharedLibraryInfo.TYPE_STATIC) {
+ // We've already added this non-version-specific library to the map.
+ return false;
+ } else if (target.get(name).indexOfKey(library.getLongVersion()) >= 0) {
+ // We've already added this version of a version-specific library to the map.
+ return false;
+ }
+ } else {
+ target.put(name, new LongSparseArray<>());
+ }
+ target.get(name).put(library.getLongVersion(), library);
+ return true;
+ }
+
@GuardedBy("mPackages")
private boolean commitPackagesLocked(final CommitRequest request) {
// TODO: remove any expected failures from this method; this should only be able to fail due
@@ -15474,7 +15618,7 @@ public class PackageManagerService extends IPackageManager.Stub
try {
prepareScanResultLocked(scanResult);
- commitScanResultLocked(scanResult);
+ commitReconciledScanResultLocked(reconciledPkg);
} catch (PackageManagerException e) {
unprepareScanResultLocked(scanResult);
res.setReturnCode(INSTALL_FAILED_INTERNAL_ERROR);
@@ -15482,7 +15626,7 @@ public class PackageManagerService extends IPackageManager.Stub
return false;
}
updateSettingsLI(pkg, reconciledPkg.installArgs.installerPackageName, request.mAllUsers,
- res, reconciledPkg.installForUser, reconciledPkg.installArgs.installReason);
+ res, reconciledPkg.installArgs.user, reconciledPkg.installArgs.installReason);
final PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps != null) {
@@ -15579,7 +15723,9 @@ public class PackageManagerService extends IPackageManager.Stub
}
ReconcileRequest reconcileRequest = new ReconcileRequest(scans, installArgs,
installResults,
- prepareResults);
+ prepareResults,
+ mSharedLibraries,
+ Collections.unmodifiableMap(mPackages));
CommitRequest commitRequest = null;
synchronized (mPackages) {
Map<String, ReconciledPackage> reconciledPackages;
@@ -15631,8 +15777,8 @@ public class PackageManagerService extends IPackageManager.Stub
*/
private void executePostCommitSteps(CommitRequest commitRequest) {
for (ReconciledPackage reconciledPkg : commitRequest.reconciledPackages.values()) {
- final boolean instantApp =
- ((reconciledPkg.installFlags & PackageManager.INSTALL_INSTANT_APP) != 0);
+ final boolean instantApp = ((reconciledPkg.scanResult.request.scanFlags
+ & PackageManagerService.SCAN_AS_INSTANT_APP) != 0);
final PackageParser.Package pkg = reconciledPkg.pkgSetting.pkg;
final String packageName = pkg.packageName;
prepareAppDataAfterInstallLIF(pkg);
@@ -15650,7 +15796,7 @@ public class PackageManagerService extends IPackageManager.Stub
// can be used for optimizations.
mArtManagerService.prepareAppProfiles(
pkg,
- resolveUserIds(reconciledPkg.installForUser.getIdentifier()),
+ resolveUserIds(reconciledPkg.installArgs.user.getIdentifier()),
/* updateReferenceProfileContent= */ true);
// Check whether we need to dexopt the app.
@@ -15727,8 +15873,32 @@ public class PackageManagerService extends IPackageManager.Stub
try {
final List<ScanResult> restoreResults = scanPackageTracedLI(oldPackage,
reconciledPackage.prepareResult.parseFlags, SCAN_UPDATE_SIGNATURE, 0,
- reconciledPackage.installForUser);
- commitSuccessfulScanResults(restoreResults);
+ reconciledPackage.installArgs.user);
+ for (ScanResult result : restoreResults) {
+ // failures should have been caught earlier, but in case it wasn't,
+ // let's double check
+ if (!result.success) {
+ throw new PackageManagerException(
+ "Scan failed for " + result.request.pkg.packageName);
+ }
+ }
+ for (ScanResult result : restoreResults) {
+ try {
+ prepareScanResultLocked(result);
+ final Map<String, ReconciledPackage> reconcileResult =
+ reconcilePackagesLocked(new ReconcileRequest(
+ Collections.singletonMap(result.pkgSetting.name,
+ result),
+ mSharedLibraries,
+ mPackages
+ ));
+ commitReconciledScanResultLocked(
+ reconcileResult.get(result.pkgSetting.name));
+ } catch (PackageManagerException e) {
+ unprepareScanResultLocked(result);
+ throw e;
+ }
+ }
restoredPkg = restoreResults.get(0).pkgSetting.pkg;
} catch (PackageManagerException e) {
Slog.e(TAG, "Failed to restore original package: " + e.getMessage());
@@ -16284,15 +16454,6 @@ public class PackageManagerService extends IPackageManager.Stub
throw new PrepareFailure(INSTALL_FAILED_INTERNAL_ERROR,
"Error deriving application ABI");
}
-
- // Shared libraries for the package need to be updated.
- synchronized (mPackages) {
- try {
- updateSharedLibrariesLPr(pkg, null);
- } catch (PackageManagerException e) {
- Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());
- }
- }
}
if (!args.doRename(res.returnCode, pkg)) {
@@ -17856,21 +18017,14 @@ public class PackageManagerService extends IPackageManager.Stub
public final PackageRemovedInfo outInfo;
public final int flags;
public final UserHandle user;
- /**
- * True if this package is an unupdated system app that may be deleted by the system.
- * When true, disabledPs will be null.
- */
- public final boolean mayDeleteUnupdatedSystemApp;
private DeletePackageAction(PackageSetting deletingPs, PackageSetting disabledPs,
- PackageRemovedInfo outInfo, int flags, UserHandle user,
- boolean mayDeleteUnupdatedSystemApp) {
+ PackageRemovedInfo outInfo, int flags, UserHandle user) {
this.deletingPs = deletingPs;
this.disabledPs = disabledPs;
this.outInfo = outInfo;
this.flags = flags;
this.user = user;
- this.mayDeleteUnupdatedSystemApp = mayDeleteUnupdatedSystemApp;
}
}
@@ -17886,24 +18040,22 @@ public class PackageManagerService extends IPackageManager.Stub
if (ps == null) {
return null;
}
- boolean mayDeleteUnupdatedSystemApp = false;
if (isSystemApp(ps)) {
if (ps.parentPackageName != null) {
Slog.w(TAG, "Attempt to delete child system package " + ps.pkg.packageName);
return null;
}
- if (((flags & PackageManager.DELETE_SYSTEM_APP) != 0) && user != null
- && user.getIdentifier() != UserHandle.USER_ALL) {
- mayDeleteUnupdatedSystemApp = true;
- } else if (disabledPs == null) {
- // Confirmed if the system package has been updated
- // An updated system app can be deleted. This will also have to restore
- // the system pkg from system partition
- // reader
+ final boolean deleteSystem = (flags & PackageManager.DELETE_SYSTEM_APP) != 0;
+ final boolean deleteAllUsers =
+ user == null || user.getIdentifier() == UserHandle.USER_ALL;
+ if ((!deleteSystem || deleteAllUsers) && disabledPs == null) {
Slog.w(TAG, "Attempt to delete unknown system package " + ps.pkg.packageName);
return null;
}
+ // Confirmed if the system package has been updated
+ // An updated system app can be deleted. This will also have to restore
+ // the system pkg from system partition reader
}
final int parentReferenceCount =
(ps.childPackageNames != null) ? ps.childPackageNames.size() : 0;
@@ -17918,8 +18070,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
}
- return new DeletePackageAction(ps, disabledPs, outInfo, flags, user,
- mayDeleteUnupdatedSystemApp);
+ return new DeletePackageAction(ps, disabledPs, outInfo, flags, user);
}
/*
@@ -17993,8 +18144,8 @@ public class PackageManagerService extends IPackageManager.Stub
if (ps.getPermissionsState().hasPermission(Manifest.permission.SUSPEND_APPS, userId)) {
unsuspendForSuspendingPackage(packageName, userId);
}
-
- if (!systemApp || action.mayDeleteUnupdatedSystemApp) {
+ if ((!systemApp || (flags & PackageManager.DELETE_SYSTEM_APP) != 0)
+ && userId != UserHandle.USER_ALL) {
// The caller is asking that the package only be deleted for a single
// user. To do this, we just mark its uninstalled state and delete
// its data. If this is a system app, we only allow this to happen if
@@ -18017,13 +18168,7 @@ public class PackageManagerService extends IPackageManager.Stub
// We need to set it back to 'installed' so the uninstall
// broadcasts will be sent correctly.
if (DEBUG_REMOVE) Slog.d(TAG, "Not installed by other users, full delete");
- if (userId != UserHandle.USER_ALL) {
- ps.setInstalled(true, userId);
- } else {
- for (int origUserId : outInfo.origUsers) {
- ps.setInstalled(true, origUserId);
- }
- }
+ ps.setInstalled(true, userId);
mSettings.writeKernelMappingLPr(ps);
}
} else {
@@ -19484,6 +19629,17 @@ public class PackageManagerService extends IPackageManager.Stub
return getHomeActivitiesAsUser(allHomeCandidates, UserHandle.getCallingUserId());
}
+ /**
+ * Send a {@code PackageInstaller.ACTION_SESSION_UPDATED} broadcast intent, containing
+ * the {@code sessionInfo} in the extra field {@code PackageInstaller.EXTRA_SESSION}.
+ */
+ public void sendSessionUpdatedBroadcast(PackageInstaller.SessionInfo sessionInfo,
+ int userId) {
+ Intent sessionUpdatedIntent = new Intent(PackageInstaller.ACTION_SESSION_UPDATED)
+ .putExtra(PackageInstaller.EXTRA_SESSION, sessionInfo);
+ mContext.sendBroadcastAsUser(sessionUpdatedIntent, UserHandle.of(userId));
+ }
+
public void sendSessionCommitBroadcast(PackageInstaller.SessionInfo sessionInfo, int userId) {
UserManagerService ums = UserManagerService.getInstance();
if (ums != null) {
@@ -20124,10 +20280,10 @@ public class PackageManagerService extends IPackageManager.Stub
ContentObserver co = new ContentObserver(mHandler) {
@Override
public void onChange(boolean selfChange) {
- boolean ephemeralFeatureDisabled =
+ final boolean ephemeralFeatureDisabled =
Global.getInt(resolver, Global.ENABLE_EPHEMERAL_FEATURE, 1) == 0;
for (int userId : UserManagerService.getInstance().getUserIds()) {
- boolean instantAppsDisabledForUser =
+ final boolean instantAppsDisabledForUser =
ephemeralFeatureDisabled || Secure.getIntForUser(resolver,
Secure.INSTANT_APPS_ENABLED, 1, userId) == 0;
mWebInstantAppsDisabled.put(userId, instantAppsDisabledForUser);
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 164af38be5a6..789664d82332 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -1193,9 +1193,9 @@ public final class DefaultPermissionGrantPolicy {
if (pm.checkPermission(fgPerm, pkg.packageName)
== PackageManager.PERMISSION_GRANTED) {
// Upgrade the app-op state of the fg permission to allow bg access
- mContext.getSystemService(AppOpsManager.class).setMode(
+ mContext.getSystemService(AppOpsManager.class).setUidMode(
AppOpsManager.permissionToOp(fgPerm), uid,
- pkg.packageName, AppOpsManager.MODE_ALLOWED);
+ AppOpsManager.MODE_ALLOWED);
break;
}
@@ -1205,8 +1205,8 @@ public final class DefaultPermissionGrantPolicy {
String bgPerm = getBackgroundPermission(permission);
if (bgPerm == null) {
if (op != null) {
- mContext.getSystemService(AppOpsManager.class).setMode(op, uid,
- pkg.packageName, AppOpsManager.MODE_ALLOWED);
+ mContext.getSystemService(AppOpsManager.class).setUidMode(op, uid,
+ AppOpsManager.MODE_ALLOWED);
}
} else {
int mode;
@@ -1217,8 +1217,7 @@ public final class DefaultPermissionGrantPolicy {
mode = AppOpsManager.MODE_FOREGROUND;
}
- mContext.getSystemService(AppOpsManager.class).setMode(op, uid,
- pkg.packageName, mode);
+ mContext.getSystemService(AppOpsManager.class).setUidMode(op, uid, mode);
}
if (DEBUG) {
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 b58c811645f7..93964cb09ae6 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -27,7 +27,6 @@ import static android.app.AppOpsManager.MODE_IGNORED;
import static android.app.AppOpsManager.OP_NONE;
import static android.app.AppOpsManager.permissionToOp;
import static android.app.AppOpsManager.permissionToOpCode;
-import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
@@ -1073,9 +1072,8 @@ public class PermissionManagerService {
AppOpsManagerInternal appOpsInternal = LocalServices.getService(
AppOpsManagerInternal.class);
- appOpsInternal.setMode(permissionToOpCode(permission),
- getUid(userId, getAppId(pkg.applicationInfo.uid)), pkg.packageName, mode,
- (pkg.applicationInfo.privateFlags & PRIVATE_FLAG_PRIVILEGED) != 0);
+ appOpsInternal.setUidMode(permissionToOpCode(permission),
+ getUid(userId, getAppId(pkg.applicationInfo.uid)), mode);
}
/**
@@ -1345,8 +1343,12 @@ public class PermissionManagerService {
sourcePermNum++) {
String sourcePerm = sourcePerms.valueAt(sourcePermNum);
- if (appOpsManager.unsafeCheckOpNoThrow(permissionToOp(sourcePerm),
- getUid(userId, getAppId(pkg.applicationInfo.uid)), pkgName)
+ if (ps.hasRuntimePermission(sourcePerm, userId)
+ && ps.getRuntimePermissionState(sourcePerm, userId)
+ .isGranted()
+ && appOpsManager.unsafeCheckOpNoThrow(
+ permissionToOp(sourcePerm), getUid(userId,
+ getAppId(pkg.applicationInfo.uid)), pkgName)
== MODE_ALLOWED) {
setAppOpMode(sourcePerm, pkg, userId, MODE_FOREGROUND);
}
diff --git a/services/core/java/com/android/server/textservices/TextServicesManagerInternal.java b/services/core/java/com/android/server/textservices/TextServicesManagerInternal.java
new file mode 100644
index 000000000000..56bcdd9ec146
--- /dev/null
+++ b/services/core/java/com/android/server/textservices/TextServicesManagerInternal.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.textservices;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.view.textservice.SpellCheckerInfo;
+
+import com.android.server.LocalServices;
+
+/**
+ * Local interface of {@link TextServicesManagerService} inside system server process.
+ */
+public abstract class TextServicesManagerInternal {
+ /**
+ * Returns the list of installed input methods for the specified user.
+ *
+ * <p>CAVEAT: This method is not fully implemented yet. This may return an empty list if
+ * {@code userId} for a background user is specified. Check the implementation before starting
+ * this method.</p>
+ *
+ * @param userId The user ID to be queried.
+ * @return {@link SpellCheckerInfo} that is currently selected {@code userId}.
+ */
+ @Nullable
+ public abstract SpellCheckerInfo getCurrentSpellCheckerForUser(@UserIdInt int userId);
+
+ /**
+ * Fake implementation of {@link TextServicesManagerInternal}. All the methods do nothing.
+ */
+ private static final TextServicesManagerInternal NOP =
+ new TextServicesManagerInternal() {
+ @Override
+ public SpellCheckerInfo getCurrentSpellCheckerForUser(@UserIdInt int userId) {
+ return null;
+ }
+ };
+
+ /**
+ * @return Global instance if exists. Otherwise, a dummy no-op instance.
+ */
+ @NonNull
+ public static TextServicesManagerInternal get() {
+ final TextServicesManagerInternal instance =
+ LocalServices.getService(TextServicesManagerInternal.class);
+ return instance != null ? instance : NOP;
+ }
+}
diff --git a/services/core/java/com/android/server/textservices/TextServicesManagerService.java b/services/core/java/com/android/server/textservices/TextServicesManagerService.java
index 23c29f8f8997..65d5b10590fa 100644
--- a/services/core/java/com/android/server/textservices/TextServicesManagerService.java
+++ b/services/core/java/com/android/server/textservices/TextServicesManagerService.java
@@ -18,20 +18,6 @@ package com.android.server.textservices;
import static android.view.textservice.TextServicesManager.DISABLE_PER_PROFILE_SPELL_CHECKER;
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.content.PackageMonitor;
-import com.android.internal.inputmethod.SubtypeLocaleUtils;
-import com.android.internal.textservice.ISpellCheckerService;
-import com.android.internal.textservice.ISpellCheckerServiceCallback;
-import com.android.internal.textservice.ISpellCheckerSession;
-import com.android.internal.textservice.ISpellCheckerSessionListener;
-import com.android.internal.textservice.ITextServicesManager;
-import com.android.internal.textservice.ITextServicesSessionListener;
-import com.android.internal.util.DumpUtils;
-import com.android.server.SystemService;
-
-import org.xmlpull.v1.XmlPullParserException;
-
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
@@ -60,12 +46,27 @@ import android.util.SparseArray;
import android.view.textservice.SpellCheckerInfo;
import android.view.textservice.SpellCheckerSubtype;
+import com.android.internal.annotations.GuardedBy;
+import com.android.internal.content.PackageMonitor;
+import com.android.internal.inputmethod.SubtypeLocaleUtils;
+import com.android.internal.textservice.ISpellCheckerService;
+import com.android.internal.textservice.ISpellCheckerServiceCallback;
+import com.android.internal.textservice.ISpellCheckerSession;
+import com.android.internal.textservice.ISpellCheckerSessionListener;
+import com.android.internal.textservice.ITextServicesManager;
+import com.android.internal.textservice.ITextServicesSessionListener;
+import com.android.internal.util.DumpUtils;
+import com.android.server.LocalServices;
+import com.android.server.SystemService;
+
+import org.xmlpull.v1.XmlPullParserException;
+
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
-import java.util.Arrays;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
@@ -278,6 +279,14 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
@Override
public void onStart() {
+ LocalServices.addService(TextServicesManagerInternal.class,
+ new TextServicesManagerInternal() {
+ @Override
+ public SpellCheckerInfo getCurrentSpellCheckerForUser(
+ @UserIdInt int userId) {
+ return mService.getCurrentSpellCheckerForUser(userId);
+ }
+ });
publishBinderService(Context.TEXT_SERVICES_MANAGER_SERVICE, mService);
}
@@ -493,6 +502,15 @@ public class TextServicesManagerService extends ITextServicesManager.Stub {
return spellCheckerList.get(0);
}
+ @Nullable
+ private SpellCheckerInfo getCurrentSpellCheckerForUser(@UserIdInt int userId) {
+ synchronized (mLock) {
+ final int spellCheckerOwnerUserId = mSpellCheckerOwnerUserIdMap.get(userId);
+ final TextServicesData data = mUserData.get(spellCheckerOwnerUserId);
+ return data != null ? data.getCurrentSpellChecker() : null;
+ }
+ }
+
// TODO: Save SpellCheckerService by supported languages. Currently only one spell
// checker is saved.
@Override
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 4d8440a899a3..2cd0168aff42 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -2486,36 +2486,20 @@ final class ActivityRecord extends ConfigurationContainer {
}
void setRequestedOrientation(int requestedOrientation) {
- final int displayId = getDisplayId();
- final Configuration displayConfig =
- mRootActivityContainer.getDisplayOverrideConfiguration(displayId);
-
- final Configuration config = setOrientation(requestedOrientation,
- displayId, displayConfig, mayFreezeScreenLocked(app));
- if (config != null) {
- frozenBeforeDestroy = true;
- if (!mAtmService.updateDisplayOverrideConfigurationLocked(config, this,
- false /* deferResume */, displayId)) {
- mRootActivityContainer.resumeFocusedStacksTopActivities();
- }
- }
+ setOrientation(requestedOrientation, mayFreezeScreenLocked(app));
mAtmService.getTaskChangeNotificationController().notifyActivityRequestedOrientationChanged(
task.taskId, requestedOrientation);
}
- Configuration setOrientation(int requestedOrientation, int displayId,
- Configuration displayConfig, boolean freezeScreenIfNeeded) {
+ private void setOrientation(int requestedOrientation, boolean freezeScreenIfNeeded) {
if (mAppWindowToken == null) {
Slog.w(TAG_WM,
"Attempted to set orientation of non-existing app token: " + appToken);
- return null;
+ return;
}
- mAppWindowToken.setOrientation(requestedOrientation);
-
final IBinder binder = freezeScreenIfNeeded ? appToken.asBinder() : null;
- return mAtmService.mWindowManager.updateOrientationFromAppTokens(displayConfig, binder,
- displayId);
+ mAppWindowToken.setOrientation(requestedOrientation, binder, this);
}
int getOrientation() {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 1943efca8ad0..a5ceee268fa2 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -397,10 +397,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
private final Matrix mTmpMatrix = new Matrix();
private final Region mTmpRegion = new Region();
-
/** Used for handing back size of display */
private final Rect mTmpBounds = new Rect();
+ private final Configuration mTmpConfiguration = new Configuration();
+
/** Remove this display when animation on it has completed. */
private boolean mDeferredRemoval;
@@ -1156,6 +1157,36 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mWmService.mH.obtainMessage(SEND_NEW_CONFIGURATION, this).sendToTarget();
}
+ @Override
+ boolean onDescendantOrientationChanged(IBinder freezeDisplayToken,
+ ConfigurationContainer requestingContainer) {
+ final Configuration config = updateOrientationFromAppTokens(
+ getRequestedOverrideConfiguration(), freezeDisplayToken, false);
+ // If display rotation class tells us that it doesn't consider app requested orientation,
+ // this display won't rotate just because of an app changes its requested orientation. Thus
+ // it indicates that this display chooses not to handle this request.
+ final boolean handled = getDisplayRotation().respectAppRequestedOrientation();
+ if (config == null) {
+ return handled;
+ }
+
+ if (handled && requestingContainer instanceof ActivityRecord) {
+ final ActivityRecord activityRecord = (ActivityRecord) requestingContainer;
+ final boolean kept = mWmService.mAtmService.updateDisplayOverrideConfigurationLocked(
+ config, activityRecord, false /* deferResume */, getDisplayId());
+ activityRecord.frozenBeforeDestroy = true;
+ if (!kept) {
+ mWmService.mAtmService.mRootActivityContainer.resumeFocusedStacksTopActivities();
+ }
+ } else {
+ // We have a new configuration to push so we need to update ATMS for now.
+ // TODO: Clean up display configuration push between ATMS and WMS after unification.
+ mWmService.mAtmService.updateDisplayOverrideConfigurationLocked(
+ config, null /* starting */, false /* deferResume */, getDisplayId());
+ }
+ return handled;
+ }
+
/**
* Determine the new desired orientation of this display.
*
@@ -1169,7 +1200,56 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
return updateOrientationFromAppTokens(false /* forceUpdate */);
}
- boolean updateOrientationFromAppTokens(boolean forceUpdate) {
+ /**
+ * Update orientation of the target display, returning a non-null new Configuration if it has
+ * changed from the current orientation. If a non-null configuration is returned, someone must
+ * call {@link WindowManagerService#setNewDisplayOverrideConfiguration(Configuration,
+ * DisplayContent)} to tell the window manager it can unfreeze the screen. This will typically
+ * be done by calling {@link WindowManagerService#sendNewConfiguration(int)}.
+ */
+ Configuration updateOrientationFromAppTokens(Configuration currentConfig,
+ IBinder freezeDisplayToken, boolean forceUpdate) {
+ if (!mDisplayReady) {
+ return null;
+ }
+
+ Configuration config = null;
+ if (updateOrientationFromAppTokens(forceUpdate)) {
+ // If we changed the orientation but mOrientationChangeComplete is already true,
+ // we used seamless rotation, and we don't need to freeze the screen.
+ if (freezeDisplayToken != null && !mWmService.mRoot.mOrientationChangeComplete) {
+ final AppWindowToken atoken = getAppWindowToken(freezeDisplayToken);
+ if (atoken != null) {
+ atoken.startFreezingScreen();
+ }
+ }
+ config = new Configuration();
+ computeScreenConfiguration(config);
+ } else if (currentConfig != null) {
+ // No obvious action we need to take, but if our current state mismatches the
+ // activity manager's, update it, disregarding font scale, which should remain set
+ // to the value of the previous configuration.
+ // Here we're calling Configuration#unset() instead of setToDefaults() because we
+ // need to keep override configs clear of non-empty values (e.g. fontSize).
+ mTmpConfiguration.unset();
+ mTmpConfiguration.updateFrom(currentConfig);
+ computeScreenConfiguration(mTmpConfiguration);
+ if (currentConfig.diff(mTmpConfiguration) != 0) {
+ mWaitingForConfig = true;
+ setLayoutNeeded();
+ int[] anim = new int[2];
+ getDisplayPolicy().selectRotationAnimationLw(anim);
+
+ mWmService.startFreezingDisplayLocked(anim[0], anim[1], this);
+ config = new Configuration(mTmpConfiguration);
+ }
+ }
+
+ return config;
+ }
+
+
+ private boolean updateOrientationFromAppTokens(boolean forceUpdate) {
final int req = getOrientation();
if (req != mLastOrientation || forceUpdate) {
mLastOrientation = req;
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 7aabc15d9860..bcc7be42333b 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -329,6 +329,15 @@ public class DisplayRotation {
return mFixedToUserRotation;
}
+ /**
+ * Returns {@code true} if this display rotation takes app requested orientation into
+ * consideration; {@code false} otherwise. For the time being the only case where this is {@code
+ * false} is when {@link #isFixedToUserRotation()} is {@code true}.
+ */
+ boolean respectAppRequestedOrientation() {
+ return !mFixedToUserRotation;
+ }
+
public int getLandscapeRotation() {
return mLandscapeRotation;
}
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index c1e9a7353fd5..fc1c65cf5807 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -49,7 +49,6 @@ import android.view.SurfaceControl;
import com.android.server.policy.WindowManagerPolicy;
import java.io.PrintWriter;
-import java.util.Arrays;
import java.util.Set;
import java.util.function.Consumer;
@@ -70,9 +69,9 @@ final class InputMonitor {
private final UpdateInputForAllWindowsConsumer mUpdateInputForAllWindowsConsumer =
new UpdateInputForAllWindowsConsumer();
- private int mDisplayId;
+ private final int mDisplayId;
- SurfaceControl.Transaction mInputTransaction = new SurfaceControl.Transaction();
+ private final SurfaceControl.Transaction mInputTransaction;
/**
* The set of input consumer added to the window manager by name, which consumes input events
@@ -109,6 +108,7 @@ final class InputMonitor {
public InputMonitor(WindowManagerService service, int displayId) {
mService = service;
mDisplayId = displayId;
+ mInputTransaction = mService.mRoot.getDisplayContent(mDisplayId).getPendingTransaction();
}
private void addInputConsumer(String name, InputConsumerImpl consumer) {
@@ -397,7 +397,7 @@ final class InputMonitor {
wallpaperInputConsumer.show(mInputTransaction, 0);
}
- mInputTransaction.apply();
+ dc.scheduleAnimation();
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
}
diff --git a/services/core/java/com/android/server/wm/RootActivityContainer.java b/services/core/java/com/android/server/wm/RootActivityContainer.java
index 8ec97c5117f1..6f92e647d301 100644
--- a/services/core/java/com/android/server/wm/RootActivityContainer.java
+++ b/services/core/java/com/android/server/wm/RootActivityContainer.java
@@ -597,11 +597,15 @@ class RootActivityContainer extends ConfigurationContainer
// Force-update the orientation from the WindowManager, since we need the true configuration
// to send to the client now.
- final Configuration config = mWindowManager.updateOrientationFromAppTokens(
- getDisplayOverrideConfiguration(displayId),
- starting != null && starting.mayFreezeScreenLocked(starting.app)
- ? starting.appToken : null,
- displayId, true /* forceUpdate */);
+ final DisplayContent displayContent = mRootWindowContainer.getDisplayContent(displayId);
+ Configuration config = null;
+ if (displayContent != null) {
+ config = displayContent.updateOrientationFromAppTokens(
+ getDisplayOverrideConfiguration(displayId),
+ starting != null && starting.mayFreezeScreenLocked(starting.app)
+ ? starting.appToken : null,
+ true /* forceUpdate */);
+ }
if (starting != null && markFrozenIfConfigChanged && config != null) {
starting.frozenBeforeDestroy = true;
}
@@ -1519,6 +1523,13 @@ class RootActivityContainer extends ConfigurationContainer
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ActivityDisplay display = mActivityDisplays.get(displayNdx);
for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
+ // Stacks and activities could be removed while putting activities to sleep if
+ // the app process was gone. This prevents us getting exception by accessing an
+ // invalid stack index.
+ if (stackNdx >= display.getChildCount()) {
+ continue;
+ }
+
final ActivityStack stack = display.getChildAt(stackNdx);
if (allowDelay) {
allSleep &= stack.goToSleepIfPossible(shuttingDown);
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index b10fd31ba7ad..d334bd298ada 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -44,6 +44,7 @@ import android.app.ActivityManager.TaskDescription;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.os.IBinder;
import android.util.EventLog;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
@@ -328,6 +329,23 @@ class Task extends WindowContainer<AppWindowToken> implements ConfigurationConta
return boundsChange;
}
+ @Override
+ public boolean onDescendantOrientationChanged(IBinder freezeDisplayToken,
+ ConfigurationContainer requestingContainer) {
+ if (super.onDescendantOrientationChanged(freezeDisplayToken, requestingContainer)) {
+ return true;
+ }
+
+ // No one in higher hierarchy handles this request, let's adjust our bounds to fulfill
+ // it if possible.
+ // TODO: Move to TaskRecord after unification is done.
+ if (mTaskRecord != null) {
+ mTaskRecord.onConfigurationChanged(mTaskRecord.getParent().getConfiguration());
+ return true;
+ }
+ return false;
+ }
+
void resize(boolean relayout, boolean forced) {
if (setBounds(getRequestedOverrideBounds(), forced) != BOUNDS_CHANGE_NONE && relayout) {
getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 11d9ebb59db0..ee74bdfaa113 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -996,15 +996,20 @@ public class TaskStack extends WindowContainer<Task> implements
* Adjusts the stack bounds if the IME is visible.
*
* @param imeWin The IME window.
+ * @param keepLastAmount Use {@code true} to keep the last adjusted amount from
+ * {@link DockedStackDividerController} for adjusting the stack bounds,
+ * Use {@code false} to reset adjusted amount as 0.
+ * @see #updateAdjustForIme(float, float, boolean)
*/
- void setAdjustedForIme(WindowState imeWin, boolean forceUpdate) {
+ void setAdjustedForIme(WindowState imeWin, boolean keepLastAmount) {
mImeWin = imeWin;
mImeGoingAway = false;
- if (!mAdjustedForIme || forceUpdate) {
+ if (!mAdjustedForIme || keepLastAmount) {
mAdjustedForIme = true;
- mAdjustImeAmount = 0f;
- mAdjustDividerAmount = 0f;
- updateAdjustForIme(0f, 0f, true /* force */);
+ DockedStackDividerController controller = getDisplayContent().mDividerControllerLocked;
+ final float adjustImeAmount = keepLastAmount ? controller.mLastAnimationProgress : 0f;
+ final float adjustDividerAmount = keepLastAmount ? controller.mLastDividerProgress : 0f;
+ updateAdjustForIme(adjustImeAmount, adjustDividerAmount, true /* force */);
}
}
diff --git a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
index c006a7ba44d7..b2194190f4f4 100644
--- a/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
+++ b/services/core/java/com/android/server/wm/TaskTapPointerEventListener.java
@@ -66,8 +66,11 @@ public class TaskTapPointerEventListener implements PointerEventListener {
// method target window will lose the focus.
return;
}
- mDisplayContent.getParent().positionChildAt(WindowContainer.POSITION_TOP,
- mDisplayContent, true /* includingParents */);
+ WindowContainer parent = mDisplayContent.getParent();
+ if (parent != null) {
+ parent.positionChildAt(WindowContainer.POSITION_TOP, mDisplayContent,
+ true /* includingParents */);
+ }
}
};
}
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 651089d6ce10..32c5a3b8688e 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -31,10 +31,12 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.annotation.CallSuper;
import android.annotation.IntDef;
+import android.annotation.Nullable;
import android.app.WindowConfiguration;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.Rect;
+import android.os.IBinder;
import android.util.Pools;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
@@ -698,8 +700,58 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
}
}
+ /**
+ * Called when this container or one of its descendants changed its requested orientation, and
+ * wants this container to handle it or pass it to its parent.
+ *
+ * @param freezeDisplayToken freeze this app window token if display needs to freeze
+ * @param requestingContainer the container which orientation request has changed
+ * @return {@code true} if handled; {@code false} otherwise.
+ */
+ boolean onDescendantOrientationChanged(@Nullable IBinder freezeDisplayToken,
+ @Nullable ConfigurationContainer requestingContainer) {
+ final WindowContainer parent = getParent();
+ if (parent == null) {
+ return false;
+ }
+ return parent.onDescendantOrientationChanged(freezeDisplayToken,
+ requestingContainer);
+ }
+
+ /**
+ * Calls {@link #setOrientation(int, IBinder, ActivityRecord)} with {@code null} to the last 2
+ * parameters.
+ *
+ * @param orientation the specified orientation.
+ */
void setOrientation(int orientation) {
+ setOrientation(orientation, null /* freezeDisplayToken */,
+ null /* ActivityRecord */);
+ }
+
+ /**
+ * Sets the specified orientation of this container. It percolates this change upward along the
+ * hierarchy to let each level of the hierarchy a chance to respond to it.
+ *
+ * @param orientation the specified orientation. Needs to be one of {@link
+ * android.content.pm.ActivityInfo.ScreenOrientation}.
+ * @param freezeDisplayToken uses this token to freeze display if orientation change is not
+ * done. Display will not be frozen if this is {@code null}, which
+ * should only happen in tests.
+ * @param requestingContainer the container which orientation request has changed. Mostly used
+ * to ensure it gets correct configuration.
+ */
+ void setOrientation(int orientation, @Nullable IBinder freezeDisplayToken,
+ @Nullable ConfigurationContainer requestingContainer) {
+ final boolean changed = mOrientation != orientation;
mOrientation = orientation;
+ if (!changed) {
+ return;
+ }
+ final WindowContainer parent = getParent();
+ if (parent != null) {
+ onDescendantOrientationChanged(freezeDisplayToken, requestingContainer);
+ }
}
int getOrientation() {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e3ced8350f0d..b6a4a51c41f2 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2383,85 +2383,6 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
- @Override
- public Configuration updateOrientationFromAppTokens(Configuration currentConfig,
- IBinder freezeThisOneIfNeeded, int displayId) {
- return updateOrientationFromAppTokens(currentConfig, freezeThisOneIfNeeded, displayId,
- false /* forceUpdate */);
- }
-
- public Configuration updateOrientationFromAppTokens(Configuration currentConfig,
- IBinder freezeThisOneIfNeeded, int displayId, boolean forceUpdate) {
- if (!checkCallingPermission(MANAGE_APP_TOKENS, "updateOrientationFromAppTokens()")) {
- throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
- }
-
- final Configuration config;
- final long ident = Binder.clearCallingIdentity();
- try {
- synchronized (mGlobalLock) {
- config = updateOrientationFromAppTokensLocked(currentConfig, freezeThisOneIfNeeded,
- displayId, forceUpdate);
- }
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
-
- return config;
- }
-
- /**
- * Update orientation of the target display, returning a non-null new Configuration if it has
- * changed from the current orientation. If a non-null configuration is returned, someone must
- * call {@link #setNewDisplayOverrideConfiguration(Configuration, int)} to tell the window
- * manager it can unfreeze the screen. This will typically be done by calling
- * {@link #sendNewConfiguration(int)}.
- *
- * @see android.view.IWindowManager#updateOrientationFromAppTokens(Configuration, IBinder, int)
- */
- private Configuration updateOrientationFromAppTokensLocked(Configuration currentConfig,
- IBinder freezeThisOneIfNeeded, int displayId, boolean forceUpdate) {
- if (!mDisplayReady) {
- return null;
- }
- Configuration config = null;
-
- final DisplayContent dc = mRoot.getDisplayContent(displayId);
- if (dc != null && dc.updateOrientationFromAppTokens(forceUpdate)) {
- // If we changed the orientation but mOrientationChangeComplete is already true,
- // we used seamless rotation, and we don't need to freeze the screen.
- if (freezeThisOneIfNeeded != null && !mRoot.mOrientationChangeComplete) {
- final AppWindowToken atoken = mRoot.getAppWindowToken(freezeThisOneIfNeeded);
- if (atoken != null) {
- atoken.startFreezingScreen();
- }
- }
- config = computeNewConfigurationLocked(displayId);
-
- } else if (currentConfig != null) {
- // No obvious action we need to take, but if our current state mismatches the activity
- // manager's, update it, disregarding font scale, which should remain set to the value
- // of the previous configuration.
- // Here we're calling Configuration#unset() instead of setToDefaults() because we need
- // to keep override configs clear of non-empty values (e.g. fontSize).
- mTempConfiguration.unset();
- mTempConfiguration.updateFrom(currentConfig);
- final DisplayContent displayContent = mRoot.getDisplayContent(displayId);
- displayContent.computeScreenConfiguration(mTempConfiguration);
- if (currentConfig.diff(mTempConfiguration) != 0) {
- displayContent.mWaitingForConfig = true;
- displayContent.setLayoutNeeded();
- int anim[] = new int[2];
- displayContent.getDisplayPolicy().selectRotationAnimationLw(anim);
-
- startFreezingDisplayLocked(anim[0], anim[1], displayContent);
- config = new Configuration(mTempConfiguration);
- }
- }
-
- return config;
- }
-
void setNewDisplayOverrideConfiguration(Configuration overrideConfig,
@NonNull DisplayContent dc) {
if (dc.mWaitingForConfig) {
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index 58fd30e225c1..729aed171ab1 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -25,6 +25,7 @@
#include <android/hardware/gnss/1.0/IGnssMeasurement.h>
#include <android/hardware/gnss/1.1/IGnssMeasurement.h>
#include <android/hardware/gnss/2.0/IGnssMeasurement.h>
+#include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrections.h>
#include <nativehelper/JNIHelp.h>
#include "jni.h"
#include "hardware_legacy/power.h"
@@ -68,6 +69,25 @@ static jmethodID method_reportMeasurementData;
static jmethodID method_reportNavigationMessages;
static jmethodID method_reportLocationBatch;
static jmethodID method_reportGnssServiceDied;
+static jmethodID method_correctionsGetLatitudeDegrees;
+static jmethodID method_correctionsGetLongitudeDegrees;
+static jmethodID method_correctionsGetAltitudeMeters;
+static jmethodID method_correctionsGetToaGpsNanosecondsOfWeek;
+static jmethodID method_correctionsGetSingleSatCorrectionList;
+static jmethodID method_listSize;
+static jmethodID method_correctionListGet;
+static jmethodID method_correctionSatFlags;
+static jmethodID method_correctionSatConstType;
+static jmethodID method_correctionSatId;
+static jmethodID method_correctionSatCarrierFreq;
+static jmethodID method_correctionSatIsLos;
+static jmethodID method_correctionSatEpl;
+static jmethodID method_correctionSatEplUnc;
+static jmethodID method_correctionSatRefPlane;
+static jmethodID method_correctionPlaneLatDeg;
+static jmethodID method_correctionPlaneLngDeg;
+static jmethodID method_correctionPlaneAltDeg;
+static jmethodID method_correctionPlaneAzimDeg;
/*
* Save a pointer to JavaVm to attach/detach threads executing
@@ -105,7 +125,10 @@ using android::hardware::gnss::V1_0::IGnssNiCallback;
using android::hardware::gnss::V1_0::IGnssXtra;
using android::hardware::gnss::V1_0::IGnssXtraCallback;
-using android::hardware::gnss::V1_1::IGnssCallback;
+using android::hardware::gnss::V2_0::IGnssCallback;
+using android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections;
+using android::hardware::gnss::measurement_corrections::V1_0::SingleSatCorrection;
+using android::hardware::gnss::measurement_corrections::V1_0::ReflectingPlane;
using android::hidl::base::V1_0::IBase;
@@ -123,6 +146,9 @@ using IGnssMeasurementCallback_V2_0 = android::hardware::gnss::V2_0::IGnssMeasur
using IAGnssRil_V1_0 = android::hardware::gnss::V1_0::IAGnssRil;
using IAGnssRil_V2_0 = android::hardware::gnss::V2_0::IAGnssRil;
+using IMeasurementCorrections =
+ android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrections;
+
struct GnssDeathRecipient : virtual public hidl_death_recipient
{
// hidl_death_recipient interface
@@ -155,6 +181,11 @@ sp<IGnssMeasurement_V1_0> gnssMeasurementIface = nullptr;
sp<IGnssMeasurement_V1_1> gnssMeasurementIface_V1_1 = nullptr;
sp<IGnssMeasurement_V2_0> gnssMeasurementIface_V2_0 = nullptr;
sp<IGnssNavigationMessage> gnssNavigationMessageIface = nullptr;
+sp<IMeasurementCorrections> gnssCorrectionsIface = nullptr;
+// This boolean is needed to ensure that Gnsss Measurement Corrections related method are only
+// initalized when needed which will be few devices initially
+bool firstGnssMeasurementCorrectionInjected = false;
+
#define WAKE_LOCK_NAME "GPS"
@@ -415,6 +446,8 @@ struct GnssCallback : public IGnssCallback {
// New in 1.1
Return<void> gnssNameCb(const android::hardware::hidl_string& name) override;
+ Return<void> gnssSetCapabilitiesCb_2_0(uint32_t capabilities) override;
+
// TODO(b/73306084): Reconsider allocation cost vs threadsafety on these statics
static const char* sNmeaString;
static size_t sNmeaStringLength;
@@ -537,6 +570,10 @@ Return<void> GnssCallback::gnssSetCapabilitesCb(uint32_t capabilities) {
return Void();
}
+Return<void> GnssCallback::gnssSetCapabilitiesCb_2_0(uint32_t capabilities) {
+ return GnssCallback::gnssSetCapabilitesCb(capabilities);
+}
+
Return<void> GnssCallback::gnssAcquireWakelockCb() {
acquire_wake_lock(PARTIAL_WAKE_LOCK, WAKE_LOCK_NAME);
return Void();
@@ -1283,6 +1320,12 @@ static void android_location_GnssLocationProvider_init_once(JNIEnv* env, jclass
if (gnssHal_V2_0 != nullptr) {
// TODO(b/119638366): getExtensionGnssMeasurement_1_1 from gnssHal_V2_0
auto gnssMeasurement = gnssHal_V2_0->getExtensionGnssMeasurement_2_0();
+ auto gnssCorrections = gnssHal_V2_0->getExtensionMeasurementCorrections();
+ if (!gnssCorrections.isOk()) {
+ ALOGD("Unable to get a handle to GnssMeasurementCorrections interface");
+ } else {
+ gnssCorrectionsIface = gnssCorrections;
+ }
if (!gnssMeasurement.isOk()) {
ALOGD("Unable to get a handle to GnssMeasurement_V2_0");
} else {
@@ -1386,11 +1429,14 @@ static jboolean android_location_GnssLocationProvider_init(JNIEnv* env, jobject
sp<IGnssCallback> gnssCbIface = new GnssCallback();
Return<bool> result = false;
- if (gnssHal_V1_1 != nullptr) {
+ if (gnssHal_V2_0 != nullptr) {
+ result = gnssHal_V2_0->setCallback_2_0(gnssCbIface);
+ } else if (gnssHal_V1_1 != nullptr) {
result = gnssHal_V1_1->setCallback_1_1(gnssCbIface);
} else {
result = gnssHal->setCallback(gnssCbIface);
}
+
if (!result.isOk() || !result) {
ALOGE("SetCallback for Gnss Interface fails\n");
return JNI_FALSE;
@@ -1933,6 +1979,150 @@ static jboolean android_location_GnssMeasurementsProvider_stop_measurement_colle
return boolToJbool(result.isOk());
}
+static jboolean android_location_GnssMeasurementsProvider_inject_gnss_measurement_corrections(
+ JNIEnv* env,
+ jobject obj /* clazz*/,
+ jobject correctionsObj) {
+
+ if (gnssCorrectionsIface == nullptr) {
+ ALOGW("Trying to inject GNSS corrections on a chipset that does not support them.");
+ return JNI_FALSE;
+ }
+ if (firstGnssMeasurementCorrectionInjected == false) {
+ jclass measCorrClass = env->GetObjectClass(correctionsObj);
+ method_correctionsGetLatitudeDegrees = env->GetMethodID(
+ measCorrClass,"getLatitudeDegrees", "()D");
+
+ method_correctionsGetLongitudeDegrees = env->GetMethodID(
+ measCorrClass, "getLongitudeDegrees", "()D");
+
+ method_correctionsGetAltitudeMeters = env->GetMethodID(
+ measCorrClass, "getAltitudeMeters", "()D");
+
+ method_correctionsGetToaGpsNanosecondsOfWeek = env->GetMethodID(
+ measCorrClass, "getToaGpsNanosecondsOfWeek", "()J");
+
+ method_correctionsGetSingleSatCorrectionList = env->GetMethodID(
+ measCorrClass, "getSingleSatCorrectionList", "()Ljava.util.List;");
+ }
+
+ jdouble latitudeDegreesCorr = env->CallDoubleMethod(
+ correctionsObj, method_correctionsGetLatitudeDegrees);
+ jdouble longitudeDegreesCorr = env->CallDoubleMethod(
+ correctionsObj, method_correctionsGetLongitudeDegrees);
+ jdouble altitudeDegreesCorr = env->CallDoubleMethod(
+ correctionsObj, method_correctionsGetAltitudeMeters);
+ jlong toaGpsNanosOfWeek = env->CallLongMethod(
+ correctionsObj, method_correctionsGetToaGpsNanosecondsOfWeek);
+ jobject singleSatCorrectionList = env->CallObjectMethod(correctionsObj,
+ method_correctionsGetSingleSatCorrectionList);
+
+ if (firstGnssMeasurementCorrectionInjected == false) {
+ jclass corrListClass = env->GetObjectClass(singleSatCorrectionList);
+ method_listSize = env->GetMethodID(corrListClass, "size", "()I");
+ method_correctionListGet = env->GetMethodID(
+ corrListClass, "get", "(I)Landroid/location/GnssSingleSatCorrection;");
+ }
+
+ auto len = (singleSatCorrectionList == nullptr)
+ ? 0
+ : env->CallIntMethod(singleSatCorrectionList, method_listSize);
+ hidl_vec<SingleSatCorrection> list(len);
+
+ for (uint16_t i = 0; i < len; ++i) {
+ jobject singleSatCorrectionObj = env->CallObjectMethod(
+ singleSatCorrectionList, method_correctionListGet, i);
+
+ if (firstGnssMeasurementCorrectionInjected == false) {
+ jclass singleSatCorrClass = env->GetObjectClass(singleSatCorrectionObj);
+ method_correctionSatFlags = env->GetMethodID(
+ singleSatCorrClass, "getSingleSatCorrectionFlags", "()I");
+ method_correctionSatConstType = env->GetMethodID(
+ singleSatCorrClass, "getConstellationType", "()I");
+ method_correctionSatId= env->GetMethodID(
+ singleSatCorrClass, "getSatId", "()I");
+ method_correctionSatCarrierFreq = env->GetMethodID(
+ singleSatCorrClass, "getCarrierFrequencyHz", "()F");
+ method_correctionSatIsLos = env->GetMethodID(
+ singleSatCorrClass,"getSatIsLos", "()Z");
+ method_correctionSatEpl = env->GetMethodID(
+ singleSatCorrClass, "getExcessPathLengthMeters", "()F");
+ method_correctionSatEplUnc = env->GetMethodID(
+ singleSatCorrClass, "getExcessPathLengthUncertaintyMeters", "()F");
+ method_correctionSatRefPlane = env->GetMethodID(
+ singleSatCorrClass, "getReflectingPlane",
+ "()Landroid/location/GnssReflectingPlane;");
+ }
+
+ jint correctionFlags =
+ env->CallIntMethod(singleSatCorrectionObj, method_correctionSatFlags);
+ jint constType = env->CallIntMethod(singleSatCorrectionObj,
+ method_correctionSatConstType);
+ jint satId =
+ env->CallIntMethod(singleSatCorrectionObj, method_correctionSatId);
+ jfloat carrierFreqHz = env->CallFloatMethod(
+ singleSatCorrectionObj, method_correctionSatCarrierFreq);
+ jboolean satIsLos = env->CallBooleanMethod(singleSatCorrectionObj,
+ method_correctionSatIsLos);
+ jfloat eplMeters =
+ env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatEpl);
+ jfloat eplUncMeters = env->CallFloatMethod(singleSatCorrectionObj,
+ method_correctionSatEplUnc);
+ jobject reflectingPlaneObj = env->CallObjectMethod(
+ singleSatCorrectionObj, method_correctionSatRefPlane);
+
+ if (firstGnssMeasurementCorrectionInjected == false) {
+ jclass refPlaneClass = env->GetObjectClass(reflectingPlaneObj);
+ method_correctionPlaneLatDeg = env->GetMethodID(
+ refPlaneClass, "getLatitudeDegrees", "()D");
+ method_correctionPlaneLngDeg = env->GetMethodID(
+ refPlaneClass, "getLongitudeDegrees", "()D");
+ method_correctionPlaneAltDeg = env->GetMethodID(
+ refPlaneClass, "getAltitudeMeters", "()D");
+ method_correctionPlaneAzimDeg = env->GetMethodID(
+ refPlaneClass, "getAzimuthDegrees", "()D");
+ }
+
+ jdouble latitudeDegreesRefPlane = env->CallDoubleMethod(
+ reflectingPlaneObj, method_correctionPlaneLatDeg);
+ jdouble longitudeDegreesRefPlane = env->CallDoubleMethod(
+ reflectingPlaneObj, method_correctionPlaneLngDeg);
+ jdouble altitudeDegreesRefPlane = env->CallDoubleMethod(
+ reflectingPlaneObj, method_correctionPlaneAltDeg);
+ jdouble azimuthDegreeRefPlane = env->CallDoubleMethod(
+ reflectingPlaneObj, method_correctionPlaneAzimDeg);
+ ReflectingPlane reflectingPlane = {
+ .latitudeDegrees = latitudeDegreesRefPlane,
+ .longitudeDegrees = longitudeDegreesRefPlane,
+ .altitudeMeters = altitudeDegreesRefPlane,
+ .azimuthDegrees = azimuthDegreeRefPlane,
+ };
+
+ SingleSatCorrection singleSatCorrection = {
+ .singleSatCorrectionFlags = static_cast<uint16_t>(correctionFlags),
+ .constellation = static_cast<GnssConstellationType>(constType),
+ .svid = static_cast<uint16_t>(satId),
+ .carrierFrequencyHz = carrierFreqHz,
+ .satIsLos = static_cast<bool>(satIsLos),
+ .excessPathLengthMeters = eplMeters,
+ .excessPathLengthUncertaintyMeters = eplUncMeters,
+ .reflectingPlane = reflectingPlane,
+ };
+ list[i] = singleSatCorrection;
+ }
+ MeasurementCorrections measurementCorrections = {
+ .latitudeDegrees = latitudeDegreesCorr,
+ .longitudeDegrees = longitudeDegreesCorr,
+ .altitudeMeters = altitudeDegreesCorr,
+ .toaGpsNanosecondsOfWeek = static_cast<uint64_t>(toaGpsNanosOfWeek),
+ .satCorrections = list,
+ };
+
+ gnssCorrectionsIface->setCorrections(measurementCorrections);
+ firstGnssMeasurementCorrectionInjected = true;
+ return JNI_TRUE;
+}
+
static jboolean android_location_GnssNavigationMessageProvider_is_navigation_message_supported(
JNIEnv* env,
jclass clazz) {
@@ -2310,19 +2500,20 @@ static const JNINativeMethod sGeofenceMethods[] = {
};
static const JNINativeMethod sMeasurementMethods[] = {
- /* name, signature, funcPtr */
- {"native_is_measurement_supported",
- "()Z",
- reinterpret_cast<void *>(
- android_location_GnssMeasurementsProvider_is_measurement_supported)},
- {"native_start_measurement_collection",
- "(Z)Z",
- reinterpret_cast<void *>(
- android_location_GnssMeasurementsProvider_start_measurement_collection)},
- {"native_stop_measurement_collection",
- "()Z",
- reinterpret_cast<void *>(
- android_location_GnssMeasurementsProvider_stop_measurement_collection)},
+ /* name, signature, funcPtr */
+ {"native_is_measurement_supported", "()Z",
+ reinterpret_cast<void*>(
+ android_location_GnssMeasurementsProvider_is_measurement_supported)},
+ {"native_start_measurement_collection", "(Z)Z",
+ reinterpret_cast<void*>(
+ android_location_GnssMeasurementsProvider_start_measurement_collection)},
+ {"native_stop_measurement_collection", "()Z",
+ reinterpret_cast<void*>(
+ android_location_GnssMeasurementsProvider_stop_measurement_collection)},
+ {"native_inject_gnss_measurement_corrections",
+ "(Landroid/location/GnssMeasurementCorrections;)Z",
+ reinterpret_cast<void*>(
+ android_location_GnssMeasurementsProvider_inject_gnss_measurement_corrections)},
};
static const JNINativeMethod sNavigationMessageMethods[] = {
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index bd3dfe96a67e..409e7f4d6bdb 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -2105,6 +2105,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
return Settings.Global.getInt(mContext.getContentResolver(), name, def);
}
+ @Nullable
String settingsGlobalGetString(String name) {
return Settings.Global.getString(mContext.getContentResolver(), name);
}
@@ -13901,7 +13902,11 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
Preconditions.checkNotNull(who, "ComponentName is null");
enforceDeviceOwner(who);
- switch (mInjector.settingsGlobalGetString(PRIVATE_DNS_MODE)) {
+ String currentMode = mInjector.settingsGlobalGetString(PRIVATE_DNS_MODE);
+ if (currentMode == null) {
+ currentMode = ConnectivityManager.PRIVATE_DNS_DEFAULT_MODE_FALLBACK;
+ }
+ switch (currentMode) {
case ConnectivityManager.PRIVATE_DNS_MODE_OFF:
return PRIVATE_DNS_MODE_OFF;
case ConnectivityManager.PRIVATE_DNS_MODE_OPPORTUNISTIC:
diff --git a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java
index b253e0ae0a40..b8723c520cf8 100644
--- a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -175,6 +175,32 @@ public class BackupManagerServiceTest {
assertThat(serviceUsers.get(mUserOneId)).isEqualTo(mUserOneService);
}
+ /** Test that the service unregisters users when stopped. */
+ @Test
+ public void testStopServiceForUser_forRegisteredUser_unregistersCorrectUser() throws Exception {
+ BackupManagerService backupManagerService =
+ createServiceAndRegisterUser(mUserOneId, mUserOneService);
+ backupManagerService.startServiceForUser(mUserTwoId, mUserTwoService);
+
+ backupManagerService.stopServiceForUser(mUserOneId);
+
+ SparseArray<UserBackupManagerService> serviceUsers = backupManagerService.getServiceUsers();
+ assertThat(serviceUsers.size()).isEqualTo(1);
+ assertThat(serviceUsers.get(mUserOneId)).isNull();
+ assertThat(serviceUsers.get(mUserTwoId)).isEqualTo(mUserTwoService);
+ }
+
+ /** Test that the service unregisters users when stopped. */
+ @Test
+ public void testStopServiceForUser_forUnknownUser_doesNothing() throws Exception {
+ BackupManagerService backupManagerService = createService();
+
+ backupManagerService.stopServiceForUser(mUserOneId);
+
+ SparseArray<UserBackupManagerService> serviceUsers = backupManagerService.getServiceUsers();
+ assertThat(serviceUsers.size()).isEqualTo(0);
+ }
+
/**
* Test that the backup services throws a {@link SecurityException} if the caller does not have
* INTERACT_ACROSS_USERS_FULL permission and passes a different user id.
diff --git a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
index cff0521bba50..1a16e568ca53 100644
--- a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
@@ -46,9 +46,11 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
import android.app.ActivityManagerInternal;
import android.app.AlarmManager;
@@ -56,6 +58,7 @@ import android.app.IActivityManager;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
+import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.location.LocationManager;
import android.location.LocationProvider;
@@ -70,6 +73,7 @@ import android.os.SystemClock;
import androidx.test.runner.AndroidJUnit4;
+import com.android.server.deviceidle.ConstraintController;
import com.android.server.net.NetworkPolicyManagerInternal;
import com.android.server.wm.ActivityTaskManagerInternal;
@@ -77,6 +81,7 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoSession;
import org.mockito.quality.Strictness;
@@ -89,6 +94,7 @@ public class DeviceIdleControllerTest {
private DeviceIdleController mDeviceIdleController;
private AnyMotionDetectorForTest mAnyMotionDetector;
private AppStateTrackerForTest mAppStateTracker;
+ private DeviceIdleController.Constants mConstants;
private InjectorForTest mInjector;
private MockitoSession mMockingSession;
@@ -97,7 +103,7 @@ public class DeviceIdleControllerTest {
@Mock
private ConnectivityService mConnectivityService;
@Mock
- private DeviceIdleController.Constants mConstants;
+ private ContentResolver mContentResolver;
@Mock
private IActivityManager mIActivityManager;
@Mock
@@ -108,10 +114,13 @@ public class DeviceIdleControllerTest {
private PowerManager.WakeLock mWakeLock;
@Mock
private PowerManagerInternal mPowerManagerInternal;
+ @Mock
+ private SensorManager mSensorManager;
class InjectorForTest extends DeviceIdleController.Injector {
ConnectivityService connectivityService;
LocationManager locationManager;
+ ConstraintController constraintController;
InjectorForTest(Context ctx) {
super(ctx);
@@ -139,37 +148,51 @@ public class DeviceIdleControllerTest {
}
@Override
- DeviceIdleController.Constants getConstants(DeviceIdleController controller,
- Handler handler,
- ContentResolver resolver) {
- return mConstants;
- }
-
- @Override
LocationManager getLocationManager() {
return locationManager;
}
@Override
DeviceIdleController.MyHandler getHandler(DeviceIdleController controller) {
- return mock(DeviceIdleController.MyHandler.class);
+ return mock(DeviceIdleController.MyHandler.class, Answers.RETURNS_DEEP_STUBS);
}
@Override
PowerManager getPowerManager() {
return mPowerManager;
}
+
+ @Override
+ SensorManager getSensorManager() {
+ return mSensorManager;
+ }
+
+ @Override
+ ConstraintController getConstraintController(
+ Handler handler, DeviceIdleController.LocalService localService) {
+ return constraintController;
+ }
+
+ @Override
+ boolean useMotionSensor() {
+ return true;
+ }
}
private class AnyMotionDetectorForTest extends AnyMotionDetector {
boolean isMonitoring = false;
AnyMotionDetectorForTest() {
- super(mPowerManager, mock(Handler.class), mock(SensorManager.class),
+ super(mPowerManager, mock(Handler.class), mSensorManager,
mock(DeviceIdleCallback.class), 0.5f);
}
@Override
+ public boolean hasSensor() {
+ return true;
+ }
+
+ @Override
public void checkForAnyMotion() {
isMonitoring = true;
}
@@ -201,7 +224,7 @@ public class DeviceIdleControllerTest {
mMockingSession = mockitoSession()
.initMocks(this)
.strictness(Strictness.LENIENT)
- .mockStatic(LocalServices.class)
+ .spyStatic(LocalServices.class)
.startMocking();
spyOn(getContext());
doReturn(null).when(getContext()).registerReceiver(any(), any());
@@ -218,9 +241,13 @@ public class DeviceIdleControllerTest {
when(mPowerManager.newWakeLock(anyInt(), anyString())).thenReturn(mWakeLock);
doNothing().when(mWakeLock).acquire();
doNothing().when(mAlarmManager).set(anyInt(), anyLong(), anyString(), any(), any());
+ doReturn(mock(Sensor.class)).when(mSensorManager)
+ .getDefaultSensor(eq(Sensor.TYPE_SIGNIFICANT_MOTION), eq(true));
+ doReturn(true).when(mSensorManager).registerListener(any(), any(), anyInt());
mAppStateTracker = new AppStateTrackerForTest(getContext(), Looper.getMainLooper());
mAnyMotionDetector = new AnyMotionDetectorForTest();
mInjector = new InjectorForTest(getContext());
+ doNothing().when(mContentResolver).registerContentObserver(any(), anyBoolean(), any());
mDeviceIdleController = new DeviceIdleController(getContext(), mInjector);
spyOn(mDeviceIdleController);
doNothing().when(mDeviceIdleController).publishBinderService(any(), any());
@@ -228,6 +255,10 @@ public class DeviceIdleControllerTest {
mDeviceIdleController.onBootPhase(SystemService.PHASE_SYSTEM_SERVICES_READY);
mDeviceIdleController.setDeepEnabledForTest(true);
mDeviceIdleController.setLightEnabledForTest(true);
+
+ // Get the same Constants object that mDeviceIdleController got.
+ mConstants = mInjector.getConstants(mDeviceIdleController,
+ mInjector.getHandler(mDeviceIdleController), mContentResolver);
}
@After
@@ -235,9 +266,10 @@ public class DeviceIdleControllerTest {
if (mMockingSession != null) {
mMockingSession.finishMocking();
}
- // DeviceIdleController adds this to LocalServices in the constructor, so we have to remove
- // it after each test, otherwise, subsequent tests will fail.
+ // DeviceIdleController adds these to LocalServices in the constructor, so we have to remove
+ // them after each test, otherwise, subsequent tests will fail.
LocalServices.removeServiceForTest(AppStateTracker.class);
+ LocalServices.removeServiceForTest(DeviceIdleController.LocalService.class);
}
@Test
@@ -1456,8 +1488,8 @@ public class DeviceIdleControllerTest {
private void setAlarmSoon(boolean isSoon) {
if (isSoon) {
- doReturn(SystemClock.elapsedRealtime() + mConstants.MIN_TIME_TO_ALARM / 2).when(
- mAlarmManager).getNextWakeFromIdleTime();
+ doReturn(SystemClock.elapsedRealtime() + mConstants.MIN_TIME_TO_ALARM / 2)
+ .when(mAlarmManager).getNextWakeFromIdleTime();
} else {
doReturn(Long.MAX_VALUE).when(mAlarmManager).getNextWakeFromIdleTime();
}
@@ -1481,27 +1513,36 @@ public class DeviceIdleControllerTest {
assertFalse(mDeviceIdleController.isScreenOn());
break;
case STATE_IDLE_PENDING:
- assertTrue(mDeviceIdleController.mMotionListener.isActive());
+ assertEquals(
+ mDeviceIdleController.hasMotionSensor(),
+ mDeviceIdleController.mMotionListener.isActive());
assertFalse(mAnyMotionDetector.isMonitoring);
assertFalse(mDeviceIdleController.isCharging());
assertFalse(mDeviceIdleController.isScreenOn());
break;
case STATE_SENSING:
- assertTrue(mDeviceIdleController.mMotionListener.isActive());
- assertTrue(mAnyMotionDetector.isMonitoring);
+ assertEquals(
+ mDeviceIdleController.hasMotionSensor(),
+ mDeviceIdleController.mMotionListener.isActive());
+ assertEquals(
+ mDeviceIdleController.hasMotionSensor(),
+ mAnyMotionDetector.isMonitoring);
assertFalse(mDeviceIdleController.isCharging());
assertFalse(mDeviceIdleController.isScreenOn());
break;
case STATE_LOCATING:
- assertTrue(mDeviceIdleController.mMotionListener.isActive());
- assertTrue(mAnyMotionDetector.isMonitoring);
+ assertEquals(
+ mDeviceIdleController.hasMotionSensor(),
+ mDeviceIdleController.mMotionListener.isActive());
assertFalse(mDeviceIdleController.isCharging());
assertFalse(mDeviceIdleController.isScreenOn());
break;
case STATE_IDLE:
- assertTrue(mDeviceIdleController.mMotionListener.isActive()
+ if (mDeviceIdleController.hasMotionSensor()) {
+ assertTrue(mDeviceIdleController.mMotionListener.isActive()
// If quick doze is enabled, the motion listener should NOT be active.
|| mDeviceIdleController.isQuickDozeEnabled());
+ }
assertFalse(mAnyMotionDetector.isMonitoring);
assertFalse(mDeviceIdleController.isCharging());
assertFalse(mDeviceIdleController.isScreenOn());
@@ -1509,9 +1550,11 @@ public class DeviceIdleControllerTest {
verifyLightStateConditions(LIGHT_STATE_OVERRIDE);
break;
case STATE_IDLE_MAINTENANCE:
- assertTrue(mDeviceIdleController.mMotionListener.isActive()
+ if (mDeviceIdleController.hasMotionSensor()) {
+ assertTrue(mDeviceIdleController.mMotionListener.isActive()
// If quick doze is enabled, the motion listener should NOT be active.
|| mDeviceIdleController.isQuickDozeEnabled());
+ }
assertFalse(mAnyMotionDetector.isMonitoring);
assertFalse(mDeviceIdleController.isCharging());
assertFalse(mDeviceIdleController.isScreenOn());
diff --git a/services/tests/mockingservicestests/src/com/android/server/deviceidle/BluetoothConstraintTest.java b/services/tests/mockingservicestests/src/com/android/server/deviceidle/BluetoothConstraintTest.java
new file mode 100644
index 000000000000..f74ac1f5317f
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/deviceidle/BluetoothConstraintTest.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.deviceidle;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.inOrder;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+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 org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+
+import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothProfile;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.server.DeviceIdleController;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+import java.util.Arrays;
+
+/**
+ * Tests for {@link com.android.server.deviceidle.BluetoothConstraint}.
+ */
+@RunWith(AndroidJUnit4.class)
+public class BluetoothConstraintTest {
+
+ private MockitoSession mMockingSession;
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private Context mContext;
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private Handler mHandler;
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private BluetoothManager mBluetoothManager;
+
+ @Mock
+ private DeviceIdleController.LocalService mDeviceIdleService;
+
+ private BluetoothConstraint mConstraint;
+
+ @Before
+ public void setUp() {
+ mMockingSession = mockitoSession()
+ .initMocks(this)
+ .strictness(Strictness.LENIENT)
+ .startMocking();
+ doReturn(mBluetoothManager)
+ .when(mContext).getSystemService(BluetoothManager.class);
+ mConstraint = new BluetoothConstraint(mContext, mHandler, mDeviceIdleService);
+ }
+
+ @After
+ public void tearDown() {
+ if (mMockingSession != null) {
+ mMockingSession.finishMocking();
+ }
+ }
+
+ @Test
+ public void testIsConnected_noBluetoothAdapter() {
+ doReturn(null).when(mBluetoothManager).getAdapter();
+ assertFalse(BluetoothConstraint.isBluetoothConnected(mBluetoothManager));
+ }
+
+ @Test
+ public void testIsConnected_noConnectedDevice() {
+ enableBluetooth(true);
+ assertFalse(BluetoothConstraint.isBluetoothConnected(mBluetoothManager));
+ }
+
+ @Test
+ public void testIsConnected_twoConnectedDevices() {
+ enableBluetooth(true, mock(BluetoothDevice.class), mock(BluetoothDevice.class));
+ assertTrue(BluetoothConstraint.isBluetoothConnected(mBluetoothManager));
+ }
+
+ @Test
+ public void testStartMonitoring_updatesActiveAtCorrectTimes() {
+ // First setup -> no callbacks should fire.
+ BluetoothConstraint constraint = mConstraint;
+ verify(mDeviceIdleService, never()).onConstraintStateChanged(any(), anyBoolean());
+ verify(mContext, never()).registerReceiver(eq(constraint.mReceiver), any());
+
+ InOrder order = inOrder(mDeviceIdleService);
+
+ // No devices -> active=false should be triggered.
+ enableBluetooth(true);
+ constraint.startMonitoring();
+ order.verify(mDeviceIdleService, times(1)).onConstraintStateChanged(any(), eq(false));
+
+ // One device -> active=true should be triggered.
+ enableBluetooth(true, mock(BluetoothDevice.class));
+ constraint.mReceiver.onReceive(
+ mContext, new Intent(BluetoothDevice.ACTION_ACL_CONNECTED));
+ constraint.startMonitoring();
+ order.verify(mDeviceIdleService, times(1)).exitIdle(eq("bluetooth"));
+
+ // Stop monitoring -> broadcast receiver should be unregistered.
+ constraint.stopMonitoring();
+ verify(mContext, times(1)).unregisterReceiver(eq(constraint.mReceiver));
+ order.verifyNoMoreInteractions();
+
+ }
+
+ private void enableBluetooth(boolean enabled, BluetoothDevice... devices) {
+ when(mBluetoothManager.getAdapter().isEnabled()).thenReturn(enabled);
+ when(mBluetoothManager.getConnectedDevices(eq(BluetoothProfile.GATT)))
+ .thenReturn(Arrays.asList(devices));
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/appops/AppOpsNotedWatcherTest.java b/services/tests/servicestests/src/com/android/server/appops/AppOpsNotedWatcherTest.java
index 52f434db3be3..edd89f9e61d1 100644
--- a/services/tests/servicestests/src/com/android/server/appops/AppOpsNotedWatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/appops/AppOpsNotedWatcherTest.java
@@ -52,8 +52,8 @@ public class AppOpsNotedWatcherTest {
// Try to start watching noted ops
final AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
try {
- appOpsManager.startWatchingNoted(new String[]{AppOpsManager.OPSTR_FINE_LOCATION,
- AppOpsManager.OPSTR_RECORD_AUDIO}, listener);
+ appOpsManager.startWatchingNoted(new int[]{AppOpsManager.OP_FINE_LOCATION,
+ AppOpsManager.OP_RECORD_AUDIO}, listener);
fail("Watching noted ops shoudl require " + Manifest.permission.WATCH_APPOPS);
} catch (SecurityException expected) {
/*ignored*/
@@ -67,23 +67,23 @@ public class AppOpsNotedWatcherTest {
// Start watching noted ops
final AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
- appOpsManager.startWatchingNoted(new String[]{AppOpsManager.OPSTR_FINE_LOCATION,
- AppOpsManager.OPSTR_CAMERA}, listener);
+ appOpsManager.startWatchingNoted(new int[]{AppOpsManager.OP_FINE_LOCATION,
+ AppOpsManager.OP_CAMERA}, listener);
// Note some ops
- appOpsManager.noteOp(AppOpsManager.OPSTR_FINE_LOCATION, Process.myUid(),
+ appOpsManager.noteOp(AppOpsManager.OP_FINE_LOCATION, Process.myUid(),
getContext().getPackageName());
- appOpsManager.noteOp(AppOpsManager.OPSTR_CAMERA, Process.myUid(),
+ appOpsManager.noteOp(AppOpsManager.OP_CAMERA, Process.myUid(),
getContext().getPackageName());
// Verify that we got called for the ops being noted
final InOrder inOrder = inOrder(listener);
inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
- .times(1)).onOpNoted(eq(AppOpsManager.OPSTR_FINE_LOCATION),
+ .times(1)).onOpNoted(eq(AppOpsManager.OP_FINE_LOCATION),
eq(Process.myUid()), eq(getContext().getPackageName()),
eq(AppOpsManager.MODE_ALLOWED));
inOrder.verify(listener, timeout(NOTIFICATION_TIMEOUT_MILLIS)
- .times(1)).onOpNoted(eq(AppOpsManager.OPSTR_CAMERA),
+ .times(1)).onOpNoted(eq(AppOpsManager.OP_CAMERA),
eq(Process.myUid()), eq(getContext().getPackageName()),
eq(AppOpsManager.MODE_ALLOWED));
diff --git a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
index 0851cf3bc4c0..e02a30def3dc 100644
--- a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
@@ -23,6 +23,7 @@ import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
+import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
@@ -132,9 +133,19 @@ public class TrampolineTest {
}
@Test
+ public void unlockUser_whenMultiUserSettingDisabled_callsBackupManagerServiceForSystemUser() {
+ Settings.Global.putInt(mContentResolver, Settings.Global.BACKUP_MULTI_USER_ENABLED, 0);
+ mTrampoline.initializeService();
+
+ mTrampoline.unlockUser(UserHandle.USER_SYSTEM);
+
+ verify(mBackupManagerServiceMock).startServiceForUser(UserHandle.USER_SYSTEM);
+ }
+
+ @Test
public void unlockUser_whenMultiUserSettingDisabled_isIgnoredForNonSystemUser() {
Settings.Global.putInt(mContentResolver, Settings.Global.BACKUP_MULTI_USER_ENABLED, 0);
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.unlockUser(10);
@@ -144,7 +155,7 @@ public class TrampolineTest {
@Test
public void unlockUser_whenMultiUserSettingEnabled_callsBackupManagerServiceForNonSystemUser() {
Settings.Global.putInt(mContentResolver, Settings.Global.BACKUP_MULTI_USER_ENABLED, 1);
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.unlockUser(10);
@@ -152,27 +163,48 @@ public class TrampolineTest {
}
@Test
- public void initializeService_forUserSystem_successfullyInitialized() {
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ public void stopUser_whenMultiUserSettingDisabled_callsBackupManagerServiceForSystemUser() {
+ Settings.Global.putInt(mContentResolver, Settings.Global.BACKUP_MULTI_USER_ENABLED, 0);
+ mTrampoline.initializeService();
- assertTrue(mTrampoline.isBackupServiceActive(UserHandle.USER_SYSTEM));
+ mTrampoline.stopUser(UserHandle.USER_SYSTEM);
+
+ verify(mBackupManagerServiceMock).stopServiceForUser(UserHandle.USER_SYSTEM);
}
- // The BackupManagerService can only be initialized by USER_SYSTEM, so we check that if any
- // other user trying to initialize it leaves it non-active.
@Test
- public void initializeService_forNonUserSystem_nonInitialized() {
- mTrampoline.initializeService(NON_USER_SYSTEM);
+ public void stopUser_whenMultiUserSettingDisabled_isIgnoredForNonSystemUser() {
+ Settings.Global.putInt(mContentResolver, Settings.Global.BACKUP_MULTI_USER_ENABLED, 0);
+ mTrampoline.initializeService();
- assertFalse(mTrampoline.isBackupServiceActive(NON_USER_SYSTEM));
+ mTrampoline.stopUser(10);
+
+ verify(mBackupManagerServiceMock, never()).stopServiceForUser(10);
+ }
+
+ @Test
+ public void stopUser_whenMultiUserSettingEnabled_callsBackupManagerServiceForNonSystemUser() {
+ Settings.Global.putInt(mContentResolver, Settings.Global.BACKUP_MULTI_USER_ENABLED, 1);
+ mTrampoline.initializeService();
+
+ mTrampoline.stopUser(10);
+
+ verify(mBackupManagerServiceMock).stopServiceForUser(10);
+ }
+
+ @Test
+ public void initializeService_successfullyInitializesBackupService() {
+ mTrampoline.initializeService();
+
+ assertTrue(mTrampoline.isBackupServiceActive(UserHandle.USER_SYSTEM));
}
@Test
public void initializeService_globallyDisabled_nonInitialized() {
TrampolineTestable.sBackupDisabled = true;
-
TrampolineTestable trampoline = new TrampolineTestable(mContextMock);
- trampoline.initializeService(UserHandle.USER_SYSTEM);
+
+ trampoline.initializeService();
assertFalse(trampoline.isBackupServiceActive(UserHandle.USER_SYSTEM));
}
@@ -181,14 +213,21 @@ public class TrampolineTest {
@Test
public void initializeService_suppressFileExists_nonInitialized() {
when(mSuppressFileMock.exists()).thenReturn(true);
-
TrampolineTestable trampoline = new TrampolineTestable(mContextMock);
- trampoline.initializeService(UserHandle.USER_SYSTEM);
+
+ trampoline.initializeService();
assertFalse(trampoline.isBackupServiceActive(UserHandle.USER_SYSTEM));
}
@Test
+ public void initializeService_doesNotStartServiceForUsers() {
+ mTrampoline.initializeService();
+
+ verify(mBackupManagerServiceMock, never()).startServiceForUser(anyInt());
+ }
+
+ @Test
public void isBackupServiceActive_calledBeforeInitialize_returnsFalse() {
assertFalse(mTrampoline.isBackupServiceActive(UserHandle.USER_SYSTEM));
}
@@ -263,7 +302,7 @@ public class TrampolineTest {
@Test
public void setBackupServiceActive_makeNonActive_serviceDeletedAndSuppressFileCreated()
throws IOException {
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
assertTrue(mTrampoline.isBackupServiceActive(UserHandle.USER_SYSTEM));
mTrampoline.setBackupServiceActive(UserHandle.USER_SYSTEM, false);
@@ -277,7 +316,7 @@ public class TrampolineTest {
setBackupServiceActive_makeNonActive_serviceDeletedAndSuppressFileCreated_ioExceptionHandled()
throws IOException {
when(mSuppressFileMock.createNewFile()).thenThrow(new IOException());
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
assertTrue(mTrampoline.isBackupServiceActive(UserHandle.USER_SYSTEM));
mTrampoline.setBackupServiceActive(UserHandle.USER_SYSTEM, false);
@@ -303,7 +342,7 @@ public class TrampolineTest {
@Test
public void dataChangedForUser_forwarded() throws RemoteException {
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.dataChangedForUser(mUserId, PACKAGE_NAME);
@@ -313,7 +352,7 @@ public class TrampolineTest {
@Test
public void dataChanged_forwarded() throws RemoteException {
TrampolineTestable.sCallingUserId = mUserId;
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.dataChanged(PACKAGE_NAME);
@@ -328,7 +367,7 @@ public class TrampolineTest {
@Test
public void clearBackupDataForUser_forwarded() throws RemoteException {
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.clearBackupDataForUser(mUserId, TRANSPORT_NAME, PACKAGE_NAME);
@@ -338,7 +377,7 @@ public class TrampolineTest {
@Test
public void clearBackupData_forwarded() throws RemoteException {
TrampolineTestable.sCallingUserId = mUserId;
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.clearBackupData(TRANSPORT_NAME, PACKAGE_NAME);
@@ -353,7 +392,7 @@ public class TrampolineTest {
@Test
public void agentConnectedForUser_forwarded() throws RemoteException {
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.agentConnectedForUser(mUserId, PACKAGE_NAME, mAgentMock);
@@ -363,7 +402,7 @@ public class TrampolineTest {
@Test
public void agentConnected_forwarded() throws RemoteException {
TrampolineTestable.sCallingUserId = mUserId;
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.agentConnected(PACKAGE_NAME, mAgentMock);
@@ -378,7 +417,7 @@ public class TrampolineTest {
@Test
public void agentDisconnectedForUser_forwarded() throws RemoteException {
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.agentDisconnectedForUser(mUserId, PACKAGE_NAME);
@@ -388,7 +427,7 @@ public class TrampolineTest {
@Test
public void agentDisconnected_forwarded() throws RemoteException {
TrampolineTestable.sCallingUserId = mUserId;
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.agentDisconnected(PACKAGE_NAME);
@@ -403,7 +442,7 @@ public class TrampolineTest {
@Test
public void restoreAtInstallForUser_forwarded() throws RemoteException {
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.restoreAtInstallForUser(mUserId, PACKAGE_NAME, 123);
@@ -413,7 +452,7 @@ public class TrampolineTest {
@Test
public void restoreAtInstall_forwarded() throws RemoteException {
TrampolineTestable.sCallingUserId = mUserId;
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.restoreAtInstall(PACKAGE_NAME, 123);
@@ -428,7 +467,7 @@ public class TrampolineTest {
@Test
public void setBackupEnabledForUser_forwarded() throws RemoteException {
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.setBackupEnabledForUser(mUserId, true);
@@ -438,7 +477,7 @@ public class TrampolineTest {
@Test
public void setBackupEnabled_forwardedToCallingUserId() throws RemoteException {
TrampolineTestable.sCallingUserId = mUserId;
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.setBackupEnabled(true);
@@ -453,7 +492,7 @@ public class TrampolineTest {
@Test
public void setAutoRestoreForUser_forwarded() throws RemoteException {
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.setAutoRestoreForUser(mUserId, true);
@@ -463,7 +502,7 @@ public class TrampolineTest {
@Test
public void setAutoRestore_forwarded() throws RemoteException {
TrampolineTestable.sCallingUserId = mUserId;
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.setAutoRestore(true);
@@ -478,7 +517,7 @@ public class TrampolineTest {
@Test
public void setBackupProvisioned_forwarded() throws RemoteException {
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.setBackupProvisioned(true);
verifyNoMoreInteractions(mBackupManagerServiceMock);
}
@@ -491,7 +530,7 @@ public class TrampolineTest {
@Test
public void isBackupEnabledForUser_forwarded() throws RemoteException {
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.isBackupEnabledForUser(mUserId);
@@ -501,7 +540,7 @@ public class TrampolineTest {
@Test
public void isBackupEnabled_forwardedToCallingUserId() throws RemoteException {
TrampolineTestable.sCallingUserId = mUserId;
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.isBackupEnabled();
@@ -516,7 +555,7 @@ public class TrampolineTest {
@Test
public void setBackupPassword_forwarded() throws RemoteException {
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.setBackupPassword(CURRENT_PASSWORD, NEW_PASSWORD);
verify(mBackupManagerServiceMock).setBackupPassword(CURRENT_PASSWORD, NEW_PASSWORD);
}
@@ -529,7 +568,7 @@ public class TrampolineTest {
@Test
public void hasBackupPassword_forwarded() throws RemoteException {
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.hasBackupPassword();
verify(mBackupManagerServiceMock).hasBackupPassword();
}
@@ -542,7 +581,7 @@ public class TrampolineTest {
@Test
public void backupNowForUser_forwarded() throws RemoteException {
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.backupNowForUser(mUserId);
@@ -552,7 +591,7 @@ public class TrampolineTest {
@Test
public void backupNow_forwardedToCallingUserId() throws RemoteException {
TrampolineTestable.sCallingUserId = mUserId;
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.backupNow();
@@ -569,7 +608,7 @@ public class TrampolineTest {
@Test
public void adbBackup_forwarded() throws RemoteException {
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.adbBackup(mUserId, mParcelFileDescriptorMock, true, true,
true, true, true, true, true, true,
PACKAGE_NAMES);
@@ -585,7 +624,7 @@ public class TrampolineTest {
@Test
public void fullTransportBackupForUser_forwarded() throws RemoteException {
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.fullTransportBackupForUser(mUserId, PACKAGE_NAMES);
@@ -600,7 +639,7 @@ public class TrampolineTest {
@Test
public void adbRestore_forwarded() throws RemoteException {
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.adbRestore(mUserId, mParcelFileDescriptorMock);
verify(mBackupManagerServiceMock).adbRestore(mUserId, mParcelFileDescriptorMock);
}
@@ -615,7 +654,7 @@ public class TrampolineTest {
@Test
public void acknowledgeFullBackupOrRestoreForUser_forwarded() throws RemoteException {
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.acknowledgeFullBackupOrRestoreForUser(
mUserId,
@@ -638,7 +677,7 @@ public class TrampolineTest {
@Test
public void acknowledgeFullBackupOrRestore_forwarded() throws RemoteException {
TrampolineTestable.sCallingUserId = mUserId;
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.acknowledgeFullBackupOrRestore(123, true, CURRENT_PASSWORD, ENCRYPTION_PASSWORD,
mFullBackupRestoreObserverMock);
@@ -662,7 +701,7 @@ public class TrampolineTest {
@Test
public void getCurrentTransportForUser_forwarded() throws RemoteException {
when(mBackupManagerServiceMock.getCurrentTransport(mUserId)).thenReturn(TRANSPORT_NAME);
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
assertEquals(TRANSPORT_NAME, mTrampoline.getCurrentTransportForUser(mUserId));
verify(mBackupManagerServiceMock).getCurrentTransport(mUserId);
@@ -672,7 +711,7 @@ public class TrampolineTest {
public void getCurrentTransport_forwarded() throws RemoteException {
TrampolineTestable.sCallingUserId = mUserId;
when(mBackupManagerServiceMock.getCurrentTransport(mUserId)).thenReturn(TRANSPORT_NAME);
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
assertEquals(TRANSPORT_NAME, mTrampoline.getCurrentTransport());
verify(mBackupManagerServiceMock).getCurrentTransport(mUserId);
@@ -687,7 +726,7 @@ public class TrampolineTest {
@Test
public void listAllTransportsForUser_forwarded() throws RemoteException {
when(mBackupManagerServiceMock.listAllTransports(mUserId)).thenReturn(TRANSPORTS);
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
assertEquals(TRANSPORTS, mTrampoline.listAllTransportsForUser(mUserId));
verify(mBackupManagerServiceMock).listAllTransports(mUserId);
@@ -698,7 +737,7 @@ public class TrampolineTest {
public void listAllTransports_forwarded() throws RemoteException {
TrampolineTestable.sCallingUserId = mUserId;
when(mBackupManagerServiceMock.listAllTransports(mUserId)).thenReturn(TRANSPORTS);
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
assertEquals(TRANSPORTS, mTrampoline.listAllTransports());
verify(mBackupManagerServiceMock).listAllTransports(mUserId);
@@ -715,7 +754,7 @@ public class TrampolineTest {
public void listAllTransportComponentsForUser_forwarded() throws RemoteException {
when(mBackupManagerServiceMock.listAllTransportComponents(mUserId)).thenReturn(
TRANSPORT_COMPONENTS);
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
assertEquals(TRANSPORT_COMPONENTS, mTrampoline.listAllTransportComponentsForUser(mUserId));
verify(mBackupManagerServiceMock).listAllTransportComponents(mUserId);
@@ -730,8 +769,8 @@ public class TrampolineTest {
@Test
public void getTransportWhitelist_forwarded() throws RemoteException {
when(mBackupManagerServiceMock.getTransportWhitelist()).thenReturn(TRANSPORTS);
+ mTrampoline.initializeService();
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
assertEquals(TRANSPORTS, mTrampoline.getTransportWhitelist());
verify(mBackupManagerServiceMock).getTransportWhitelist();
}
@@ -754,7 +793,7 @@ public class TrampolineTest {
@Test
public void updateTransportAttributesForUser_forwarded() throws RemoteException {
when(mBackupManagerServiceMock.getTransportWhitelist()).thenReturn(TRANSPORTS);
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.updateTransportAttributesForUser(
mUserId,
@@ -784,7 +823,7 @@ public class TrampolineTest {
@Test
public void selectBackupTransportForUser_forwarded() throws RemoteException {
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.selectBackupTransportForUser(mUserId, TRANSPORT_NAME);
@@ -794,7 +833,7 @@ public class TrampolineTest {
@Test
public void selectBackupTransport_forwarded() throws RemoteException {
TrampolineTestable.sCallingUserId = mUserId;
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.selectBackupTransport(TRANSPORT_NAME);
@@ -870,7 +909,7 @@ public class TrampolineTest {
@Test
public void selectBackupTransportAsyncForUser_forwarded() throws RemoteException {
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.selectBackupTransportAsyncForUser(mUserId, TRANSPORT_COMPONENT_NAME, null);
@@ -889,7 +928,7 @@ public class TrampolineTest {
Intent configurationIntentStub = new Intent();
when(mBackupManagerServiceMock.getConfigurationIntent(mUserId, TRANSPORT_NAME)).thenReturn(
configurationIntentStub);
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
assertEquals(
configurationIntentStub,
@@ -903,7 +942,7 @@ public class TrampolineTest {
Intent configurationIntentStub = new Intent();
when(mBackupManagerServiceMock.getConfigurationIntent(mUserId, TRANSPORT_NAME)).thenReturn(
configurationIntentStub);
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
assertEquals(configurationIntentStub, mTrampoline.getConfigurationIntent(TRANSPORT_NAME));
verify(mBackupManagerServiceMock).getConfigurationIntent(mUserId, TRANSPORT_NAME);
@@ -919,7 +958,7 @@ public class TrampolineTest {
public void getDestinationStringForUser_forwarded() throws RemoteException {
when(mBackupManagerServiceMock.getDestinationString(mUserId, TRANSPORT_NAME)).thenReturn(
DESTINATION_STRING);
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
assertEquals(
DESTINATION_STRING,
@@ -933,7 +972,7 @@ public class TrampolineTest {
when(mBackupManagerServiceMock.getDestinationString(mUserId, TRANSPORT_NAME)).thenReturn(
DESTINATION_STRING);
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
assertEquals(DESTINATION_STRING, mTrampoline.getDestinationString(TRANSPORT_NAME));
verify(mBackupManagerServiceMock).getDestinationString(mUserId, TRANSPORT_NAME);
}
@@ -949,7 +988,7 @@ public class TrampolineTest {
Intent dataManagementIntent = new Intent();
when(mBackupManagerServiceMock.getDataManagementIntent(mUserId, TRANSPORT_NAME)).thenReturn(
dataManagementIntent);
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
assertEquals(
dataManagementIntent,
@@ -963,7 +1002,7 @@ public class TrampolineTest {
Intent dataManagementIntent = new Intent();
when(mBackupManagerServiceMock.getDataManagementIntent(mUserId, TRANSPORT_NAME)).thenReturn(
dataManagementIntent);
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
assertEquals(dataManagementIntent, mTrampoline.getDataManagementIntent(TRANSPORT_NAME));
verify(mBackupManagerServiceMock).getDataManagementIntent(mUserId, TRANSPORT_NAME);
@@ -979,7 +1018,7 @@ public class TrampolineTest {
public void getDataManagementLabelForUser_forwarded() throws RemoteException {
when(mBackupManagerServiceMock.getDataManagementLabel(mUserId, TRANSPORT_NAME)).thenReturn(
DATA_MANAGEMENT_LABEL);
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
assertEquals(
DATA_MANAGEMENT_LABEL,
@@ -992,7 +1031,7 @@ public class TrampolineTest {
TrampolineTestable.sCallingUserId = mUserId;
when(mBackupManagerServiceMock.getDataManagementLabel(mUserId, TRANSPORT_NAME)).thenReturn(
DATA_MANAGEMENT_LABEL);
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
assertEquals(DATA_MANAGEMENT_LABEL, mTrampoline.getDataManagementLabel(TRANSPORT_NAME));
verify(mBackupManagerServiceMock).getDataManagementLabel(mUserId, TRANSPORT_NAME);
@@ -1006,7 +1045,7 @@ public class TrampolineTest {
@Test
public void beginRestoreSessionForUser_forwarded() throws RemoteException {
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.beginRestoreSessionForUser(mUserId, PACKAGE_NAME, TRANSPORT_NAME);
@@ -1023,7 +1062,7 @@ public class TrampolineTest {
@Test
public void opComplete_forwarded() throws RemoteException {
TrampolineTestable.sCallingUserId = mUserId;
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.opComplete(1, 2);
@@ -1041,7 +1080,7 @@ public class TrampolineTest {
public void getAvailableRestoreTokenForUser_forwarded() throws RemoteException {
when(mBackupManagerServiceMock.getAvailableRestoreToken(mUserId, PACKAGE_NAME))
.thenReturn(123L);
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
assertEquals(123, mTrampoline.getAvailableRestoreTokenForUser(mUserId, PACKAGE_NAME));
verify(mBackupManagerServiceMock).getAvailableRestoreToken(mUserId, PACKAGE_NAME);
@@ -1058,7 +1097,7 @@ public class TrampolineTest {
public void isAppEligibleForBackupForUser_forwarded() throws RemoteException {
when(mBackupManagerServiceMock.isAppEligibleForBackup(mUserId, PACKAGE_NAME))
.thenReturn(true);
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
assertTrue(mTrampoline.isAppEligibleForBackupForUser(mUserId, PACKAGE_NAME));
verify(mBackupManagerServiceMock).isAppEligibleForBackup(mUserId, PACKAGE_NAME);
@@ -1075,7 +1114,7 @@ public class TrampolineTest {
public void requestBackupForUser_forwarded() throws RemoteException {
when(mBackupManagerServiceMock.requestBackup(mUserId, PACKAGE_NAMES,
mBackupObserverMock, mBackupManagerMonitorMock, 123)).thenReturn(456);
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
assertEquals(456, mTrampoline.requestBackupForUser(mUserId, PACKAGE_NAMES,
mBackupObserverMock, mBackupManagerMonitorMock, 123));
@@ -1088,7 +1127,7 @@ public class TrampolineTest {
TrampolineTestable.sCallingUserId = mUserId;
when(mBackupManagerServiceMock.requestBackup(NON_USER_SYSTEM, PACKAGE_NAMES,
mBackupObserverMock, mBackupManagerMonitorMock, 123)).thenReturn(456);
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
assertEquals(456, mTrampoline.requestBackup(PACKAGE_NAMES,
mBackupObserverMock, mBackupManagerMonitorMock, 123));
@@ -1104,7 +1143,7 @@ public class TrampolineTest {
@Test
public void cancelBackupsForUser_forwarded() throws RemoteException {
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.cancelBackupsForUser(mUserId);
@@ -1114,7 +1153,7 @@ public class TrampolineTest {
@Test
public void cancelBackups_forwardedToCallingUserId() throws RemoteException {
TrampolineTestable.sCallingUserId = mUserId;
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.cancelBackups();
@@ -1132,7 +1171,7 @@ public class TrampolineTest {
FullBackupJob fullBackupJob = new FullBackupJob();
when(mBackupManagerServiceMock.beginFullBackup(fullBackupJob)).thenReturn(true);
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
assertTrue(mTrampoline.beginFullBackup(fullBackupJob));
verify(mBackupManagerServiceMock).beginFullBackup(fullBackupJob);
}
@@ -1145,7 +1184,7 @@ public class TrampolineTest {
@Test
public void endFullBackup_forwarded() throws RemoteException {
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.endFullBackup();
verify(mBackupManagerServiceMock).endFullBackup();
}
@@ -1155,8 +1194,7 @@ public class TrampolineTest {
when(mContextMock.checkCallingOrSelfPermission(
android.Manifest.permission.DUMP)).thenReturn(
PackageManager.PERMISSION_DENIED);
-
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.dump(mFileDescriptorStub, mPrintWriterMock, new String[0]);
@@ -1179,8 +1217,7 @@ public class TrampolineTest {
when(mContextMock.checkCallingOrSelfPermission(
android.Manifest.permission.DUMP)).thenReturn(
PackageManager.PERMISSION_GRANTED);
-
- mTrampoline.initializeService(UserHandle.USER_SYSTEM);
+ mTrampoline.initializeService();
mTrampoline.dump(mFileDescriptorStub, mPrintWriterMock, null);
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 371e8f4db9de..83c1c7670338 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -3849,4 +3849,26 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mService.reportSeen(r);
verify(mAppUsageStats, times(1)).reportEvent(anyString(), anyInt(), anyInt());
}
+
+ @Test
+ public void testNotificationStats_notificationError() {
+ NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
+ mService.addNotification(r);
+
+ StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
+ new Notification.Builder(mContext, mTestNotificationChannel.getId()).build(),
+ new UserHandle(mUid), null, 0);
+ NotificationRecord update = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
+ mService.addEnqueuedNotification(update);
+ assertNull(update.sbn.getNotification().getSmallIcon());
+
+ NotificationManagerService.PostNotificationRunnable runnable =
+ mService.new PostNotificationRunnable(update.getKey());
+ runnable.run();
+ waitForIdle();
+
+ ArgumentCaptor<NotificationStats> captor = ArgumentCaptor.forClass(NotificationStats.class);
+ verify(mListeners).notifyRemovedLocked(any(), anyInt(), captor.capture());
+ assertNotNull(captor.getValue());
+ }
}
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 92b4dbb5076b..bc62de12373d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -155,15 +155,17 @@ public class AppWindowTokenTests extends WindowTestsBase {
// Set initial orientation and update.
mToken.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
- mWm.updateOrientationFromAppTokens(mDisplayContent.getRequestedOverrideConfiguration(),
- null, mDisplayContent.getDisplayId());
+ mDisplayContent.updateOrientationFromAppTokens(
+ mDisplayContent.getRequestedOverrideConfiguration(),
+ null /* freezeThisOneIfNeeded */, false /* forceUpdate */);
assertEquals(SCREEN_ORIENTATION_LANDSCAPE, mDisplayContent.getLastOrientation());
appWindow.mResizeReported = false;
// Update the orientation to perform 180 degree rotation and check that resize was reported.
mToken.setOrientation(SCREEN_ORIENTATION_REVERSE_LANDSCAPE);
- mWm.updateOrientationFromAppTokens(mDisplayContent.getRequestedOverrideConfiguration(),
- null, mDisplayContent.getDisplayId());
+ mDisplayContent.updateOrientationFromAppTokens(
+ mDisplayContent.getRequestedOverrideConfiguration(),
+ null /* freezeThisOneIfNeeded */, false /* forceUpdate */);
mWm.mRoot.performSurfacePlacement(false /* recoveringMemory */);
assertEquals(SCREEN_ORIENTATION_REVERSE_LANDSCAPE, mDisplayContent.getLastOrientation());
assertTrue(appWindow.mResizeReported);
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 8430616731d2..3826fac22b05 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -31,7 +31,13 @@ import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.any;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.same;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
@@ -60,9 +66,11 @@ import android.view.Surface;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.server.wm.utils.WmDisplayCutout;
import org.junit.Test;
+import org.mockito.ArgumentCaptor;
import java.util.ArrayList;
import java.util.Arrays;
@@ -475,6 +483,13 @@ public class DisplayContentTests extends WindowTestsBase {
@SuppressLint("InlinedApi")
public void testOrientationDefinedByKeyguard() {
final DisplayContent dc = createNewDisplay();
+
+ // When display content is created its configuration is not yet initialized, which could
+ // cause unnecessary configuration propagation, so initialize it here.
+ final Configuration config = new Configuration();
+ dc.computeScreenConfiguration(config);
+ dc.onRequestedOverrideConfigurationChanged(config);
+
// Create a window that requests landscape orientation. It will define device orientation
// by default.
final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
@@ -567,6 +582,52 @@ public class DisplayContentTests extends WindowTestsBase {
assertNull("default display Ime target: ", mDisplayContent.mInputMethodTarget);
}
+ @Test
+ public void testOnDescendantOrientationRequestChanged() {
+ final DisplayContent dc = createNewDisplay();
+ mWm.mAtmService.mRootActivityContainer = mock(RootActivityContainer.class);
+ final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
+ ? SCREEN_ORIENTATION_PORTRAIT
+ : SCREEN_ORIENTATION_LANDSCAPE;
+
+ final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
+ window.getTask().mTaskRecord = mock(TaskRecord.class, ExtendedMockito.RETURNS_DEEP_STUBS);
+ window.mAppToken.setOrientation(newOrientation);
+
+ ActivityRecord activityRecord = mock(ActivityRecord.class);
+
+ assertTrue("Display should rotate to handle orientation request by default.",
+ dc.onDescendantOrientationChanged(window.mToken.token, activityRecord));
+
+ final ArgumentCaptor<Configuration> captor = ArgumentCaptor.forClass(Configuration.class);
+ verify(mWm.mAtmService).updateDisplayOverrideConfigurationLocked(captor.capture(),
+ same(activityRecord), anyBoolean(), eq(dc.getDisplayId()));
+ final Configuration newDisplayConfig = captor.getValue();
+ assertEquals(Configuration.ORIENTATION_PORTRAIT, newDisplayConfig.orientation);
+ }
+
+ @Test
+ public void testOnDescendantOrientationRequestChanged_FrozenToUserRotation() {
+ final DisplayContent dc = createNewDisplay();
+ dc.getDisplayRotation().setFixedToUserRotation(true);
+ mWm.mAtmService.mRootActivityContainer = mock(RootActivityContainer.class);
+ final int newOrientation = dc.getLastOrientation() == SCREEN_ORIENTATION_LANDSCAPE
+ ? SCREEN_ORIENTATION_PORTRAIT
+ : SCREEN_ORIENTATION_LANDSCAPE;
+
+ final WindowState window = createWindow(null /* parent */, TYPE_BASE_APPLICATION, dc, "w");
+ window.getTask().mTaskRecord = mock(TaskRecord.class, ExtendedMockito.RETURNS_DEEP_STUBS);
+ window.mAppToken.setOrientation(newOrientation);
+
+ ActivityRecord activityRecord = mock(ActivityRecord.class);
+
+ assertFalse("Display shouldn't rotate to handle orientation request if fixed to"
+ + " user rotation.",
+ dc.onDescendantOrientationChanged(window.mToken.token, activityRecord));
+ verify(mWm.mAtmService, never()).updateDisplayOverrideConfigurationLocked(any(),
+ eq(activityRecord), anyBoolean(), eq(dc.getDisplayId()));
+ }
+
private boolean isOptionsPanelAtRight(int displayId) {
return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
}
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 bf4b52eb72aa..6b31e6fdbd28 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -33,6 +33,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.content.ContentResolver;
@@ -234,7 +235,7 @@ public class DisplayRotationTests {
}
@Test
- public void testReturnsSidesays_UserRotationLocked_IncompatibleAppRequest()
+ public void testReturnsSideways_UserRotationLocked_IncompatibleAppRequest()
throws Exception {
mBuilder.build();
configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
@@ -604,6 +605,26 @@ public class DisplayRotationTests {
SCREEN_ORIENTATION_UNSPECIFIED, Surface.ROTATION_0));
}
+ // ========================
+ // Non-rotation API Tests
+ // ========================
+ @Test
+ public void testRespectsAppRequestedOrientationByDefault() throws Exception {
+ mBuilder.build();
+
+ assertTrue("Display rotation should respect app requested orientation by"
+ + " default.", mTarget.respectAppRequestedOrientation());
+ }
+
+ @Test
+ public void testNotRespectAppRequestedOrientation_FixedToUserRotation() throws Exception {
+ mBuilder.build();
+ mTarget.setFixedToUserRotation(true);
+
+ assertFalse("Display rotation shouldn't respect app requested orientation if"
+ + " fixed to user rotation.", mTarget.respectAppRequestedOrientation());
+ }
+
/**
* Call {@link DisplayRotation#configure(int, int, int, int)} to configure {@link #mTarget}
* according to given parameters.
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
index 83e7ee711831..dfdbf323365f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimationRunnerTest.java
@@ -49,12 +49,9 @@ import androidx.test.filters.SmallTest;
import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
import java.util.concurrent.CountDownLatch;
@@ -72,7 +69,6 @@ public class SurfaceAnimationRunnerTest extends WindowTestsBase {
@Mock Transaction mMockTransaction;
@Mock AnimationSpec mMockAnimationSpec;
@Mock PowerManagerInternal mMockPowerManager;
- @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
private SurfaceAnimationRunner mSurfaceAnimationRunner;
private CountDownLatch mFinishCallbackLatch;
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index 60f957f8f569..e1561436c022 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -27,6 +27,7 @@ import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyFloat;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.eq;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.WindowContainer.POSITION_BOTTOM;
@@ -38,8 +39,10 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
+import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
@@ -559,8 +562,7 @@ public class WindowContainerTests extends WindowTestsBase {
builder.setLayer(2).setIsVisible(true);
final TestWindowContainer visibleUnspecifiedRootChildChildFillsParent =
visibleUnspecifiedRootChild.addChildWindow(builder);
- visibleUnspecifiedRootChildChildFillsParent.setOrientation(
- SCREEN_ORIENTATION_PORTRAIT);
+ visibleUnspecifiedRootChildChildFillsParent.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
assertEquals(SCREEN_ORIENTATION_PORTRAIT,
visibleUnspecifiedRootChildChildFillsParent.getOrientation());
assertEquals(SCREEN_ORIENTATION_UNSET, visibleUnspecifiedRootChild.getOrientation());
@@ -724,6 +726,19 @@ public class WindowContainerTests extends WindowTestsBase {
verify(grandChild, times(1)).onParentResize();
}
+ @Test
+ public void testOnDescendantOrientationRequestChangedPropagation() {
+ final TestWindowContainerBuilder builder = new TestWindowContainerBuilder(mWm);
+ final TestWindowContainer root = spy(builder.build());
+
+ final IBinder binder = mock(IBinder.class);
+ final ActivityRecord activityRecord = mock(ActivityRecord.class);
+ final TestWindowContainer child = root.addChildWindow();
+
+ child.setOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED, binder, activityRecord);
+ verify(root).onDescendantOrientationChanged(binder, activityRecord);
+ }
+
/* Used so we can gain access to some protected members of the {@link WindowContainer} class */
private static class TestWindowContainer extends WindowContainer<TestWindowContainer> {
private final int mLayer;
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
index d6b40aecf52e..38efc743fe34 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerHelper.java
@@ -622,6 +622,7 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
onRecognitionFailureLocked();
break;
case SoundTrigger.RECOGNITION_STATUS_SUCCESS:
+ case SoundTrigger.RECOGNITION_STATUS_GET_STATE_RESPONSE:
if (isKeyphraseRecognitionEvent(event)) {
onKeyphraseRecognitionSuccessLocked((KeyphraseRecognitionEvent) event);
} else {
@@ -638,7 +639,8 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
private void onGenericRecognitionSuccessLocked(GenericRecognitionEvent event) {
MetricsLogger.count(mContext, "sth_generic_recognition_event", 1);
- if (event.status != SoundTrigger.RECOGNITION_STATUS_SUCCESS) {
+ if (event.status != SoundTrigger.RECOGNITION_STATUS_SUCCESS
+ && event.status != SoundTrigger.RECOGNITION_STATUS_GET_STATE_RESPONSE) {
return;
}
ModelData model = getModelDataForLocked(event.soundModelHandle);
@@ -655,7 +657,9 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
return;
}
- model.setStopped();
+ if (event.status != SoundTrigger.RECOGNITION_STATUS_GET_STATE_RESPONSE) {
+ model.setStopped();
+ }
try {
callback.onGenericSoundTriggerDetected((GenericRecognitionEvent) event);
} catch (DeadObjectException e) {
@@ -797,7 +801,10 @@ public class SoundTriggerHelper implements SoundTrigger.StatusListener {
Slog.w(TAG, "Received onRecognition event without callback for keyphrase model.");
return;
}
- modelData.setStopped();
+
+ if (event.status != SoundTrigger.RECOGNITION_STATUS_GET_STATE_RESPONSE) {
+ modelData.setStopped();
+ }
try {
modelData.getCallback().onKeyphraseDetected((KeyphraseRecognitionEvent) event);
diff --git a/startop/view_compiler/dex_builder.h b/startop/view_compiler/dex_builder.h
index 06059c8c6e56..757d863461f0 100644
--- a/startop/view_compiler/dex_builder.h
+++ b/startop/view_compiler/dex_builder.h
@@ -73,7 +73,7 @@ class TypeDescriptor {
bool operator<(const TypeDescriptor& rhs) const { return descriptor_ < rhs.descriptor_; }
private:
- TypeDescriptor(std::string descriptor) : descriptor_{descriptor} {}
+ explicit TypeDescriptor(std::string descriptor) : descriptor_{descriptor} {}
const std::string descriptor_;
};
@@ -83,7 +83,7 @@ class TypeDescriptor {
class Prototype {
public:
template <typename... TypeDescriptors>
- Prototype(TypeDescriptor return_type, TypeDescriptors... param_types)
+ explicit Prototype(TypeDescriptor return_type, TypeDescriptors... param_types)
: return_type_{return_type}, param_types_{param_types...} {}
// Encode this prototype into the dex file.
diff --git a/startop/view_compiler/main.cc b/startop/view_compiler/main.cc
index 9351dc34ea54..55bfdc78ec1b 100644
--- a/startop/view_compiler/main.cc
+++ b/startop/view_compiler/main.cc
@@ -42,7 +42,7 @@ DEFINE_string(package, "", "The package name for the generated class (required)"
class ViewCompilerXmlVisitor : public XMLVisitor {
public:
- ViewCompilerXmlVisitor(JavaLangViewBuilder* builder) : builder_(builder) {}
+ explicit ViewCompilerXmlVisitor(JavaLangViewBuilder* builder) : builder_(builder) {}
bool VisitEnter(const XMLDocument& /*doc*/) override {
builder_->Start();
diff --git a/telephony/java/android/provider/Telephony.java b/telephony/java/android/provider/Telephony.java
index 1cbe5a26caed..c115a4bd2a10 100644
--- a/telephony/java/android/provider/Telephony.java
+++ b/telephony/java/android/provider/Telephony.java
@@ -2732,10 +2732,26 @@ public final class Telephony {
/**
* The {@code content://} style URL for this table.
+ * For MSIM, this will return APNs for the default subscription
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}. To specify subId for MSIM,
+ * use {@link Uri#withAppendedPath(Uri, String)} to append with subscription id.
*/
public static final Uri CONTENT_URI = Uri.parse("content://telephony/carriers");
/**
+ * The {@code content://} style URL for this table. Used for APN query based on current
+ * subscription. Instead of specifying carrier matching information in the selection,
+ * this API will return all matching APNs from current subscription carrier and queries
+ * will be applied on top of that. If there is no match for MVNO (Mobile Virtual Network
+ * Operator) APNs, return APNs from its MNO (based on mccmnc) instead. For MSIM, this will
+ * return APNs for the default subscription
+ * {@link SubscriptionManager#getDefaultSubscriptionId()}. To specify subId for MSIM,
+ * use {@link Uri#withAppendedPath(Uri, String)} to append with subscription id.
+ */
+ public static final Uri SIM_APN_URI = Uri.parse(
+ "content://telephony/carriers/sim_apn_list");
+
+ /**
* The {@code content://} style URL to be called from DevicePolicyManagerService,
* can manage DPC-owned APNs.
* @hide
@@ -2745,7 +2761,9 @@ public final class Telephony {
/**
* The {@code content://} style URL to be called from Telephony to query APNs.
* When DPC-owned APNs are enforced, only DPC-owned APNs are returned, otherwise only
- * non-DPC-owned APNs are returned.
+ * non-DPC-owned APNs are returned. For MSIM, this will return APNs for the default
+ * subscription {@link SubscriptionManager#getDefaultSubscriptionId()}. To specify subId
+ * for MSIM, use {@link Uri#withAppendedPath(Uri, String)} to append with subscription id.
* @hide
*/
public static final Uri FILTERED_URI = Uri.parse("content://telephony/carriers/filtered");
@@ -2759,13 +2777,6 @@ public final class Telephony {
"content://telephony/carriers/enforce_managed");
/**
- * The {@code content://} style URL to be called from Telephony to query current APNs.
- * @hide
- */
- public static final Uri SIM_APN_LIST = Uri.parse(
- "content://telephony/carriers/sim_apn_list");
-
- /**
* The column name for ENFORCE_MANAGED_URI, indicates whether DPC-owned APNs are enforced.
* @hide
*/
@@ -2839,18 +2850,30 @@ public final class Telephony {
/**
* Mobile Country Code (MCC).
* <P>Type: TEXT</P>
+ * @deprecated Use {@link #SIM_APN_URI} to query APN instead, this API will return
+ * matching APNs based on current subscription carrier, thus no need to specify MCC and
+ * other carrier matching information. In the future, Android will not support MCC for
+ * APN query.
*/
public static final String MCC = "mcc";
/**
* Mobile Network Code (MNC).
* <P>Type: TEXT</P>
+ * @deprecated Use {@link #SIM_APN_URI} to query APN instead, this API will return
+ * matching APNs based on current subscription carrier, thus no need to specify MNC and
+ * other carrier matching information. In the future, Android will not support MNC for
+ * APN query.
*/
public static final String MNC = "mnc";
/**
* Numeric operator ID (as String). Usually {@code MCC + MNC}.
* <P>Type: TEXT</P>
+ * @deprecated Use {@link #SIM_APN_URI} to query APN instead, this API will return
+ * matching APNs based on current subscription carrier, thus no need to specify Numeric
+ * and other carrier matching information. In the future, Android will not support Numeric
+ * for APN query.
*/
public static final String NUMERIC = "numeric";
@@ -2931,6 +2954,10 @@ public final class Telephony {
* MVNO type:
* {@code SPN (Service Provider Name), IMSI, GID (Group Identifier Level 1)}.
* <P>Type: TEXT</P>
+ * @deprecated Use {@link #SIM_APN_URI} to query APN instead, this API will return
+ * matching APNs based on current subscription carrier, thus no need to specify MVNO_TYPE
+ * and other carrier matching information. In the future, Android will not support MVNO_TYPE
+ * for APN query.
*/
public static final String MVNO_TYPE = "mvno_type";
@@ -2943,6 +2970,10 @@ public final class Telephony {
* <li>GID: 4E, 33, ...</li>
* </ul>
* <P>Type: TEXT</P>
+ * @deprecated Use {@link #SIM_APN_URI} to query APN instead, this API will return
+ * matching APNs based on current subscription carrier, thus no need to specify
+ * MVNO_MATCH_DATA and other carrier matching information. In the future, Android will not
+ * support MVNO_MATCH_DATA for APN query.
*/
public static final String MVNO_MATCH_DATA = "mvno_match_data";
@@ -3151,7 +3182,6 @@ public final class Telephony {
})
@Retention(RetentionPolicy.SOURCE)
public @interface EditStatus {}
-
}
/**
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index ebf198702bb9..6326cc688914 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -61,7 +61,6 @@ public class EuiccManager {
public static final String ACTION_MANAGE_EMBEDDED_SUBSCRIPTIONS =
"android.telephony.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS";
-
/**
* Broadcast Action: The eUICC OTA status is changed.
* <p class="note">
@@ -87,6 +86,20 @@ public class EuiccManager {
"android.telephony.euicc.action.NOTIFY_CARRIER_SETUP_INCOMPLETE";
/**
+ * Intent action to select a profile to enable before download a new eSIM profile.
+ *
+ * May be called during device provisioning when there are multiple slots having profiles on
+ * them. This Intent launches a screen for all the current existing profiles and let users to
+ * choose which one they want to enable. In this case, the slot contains the profile will be
+ * activated.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String ACTION_PROFILE_SELECTION =
+ "android.telephony.euicc.action.PROFILE_SELECTION";
+
+ /**
* Intent action to provision an embedded subscription.
*
* <p>May be called during device provisioning to launch a screen to perform embedded SIM
@@ -132,6 +145,16 @@ public class EuiccManager {
public static final int EMBEDDED_SUBSCRIPTION_RESULT_ERROR = 2;
/**
+ * Key for an extra set on the {@link #ACTION_PROVISION_EMBEDDED_SUBSCRIPTION} intent for which
+ * kind of activation flow will be evolved. (see {@code EUICC_ACTIVATION_})
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String EXTRA_ACTIVATION_TYPE =
+ "android.telephony.euicc.extra.ACTIVATION_TYPE";
+
+ /**
* Key for an extra set on {@link PendingIntent} result callbacks providing a detailed result
* code.
*
@@ -197,6 +220,52 @@ public class EuiccManager {
public static final String META_DATA_CARRIER_ICON = "android.telephony.euicc.carriericon";
/**
+ * Euicc activation type which will be included in {@link #EXTRA_ACTIVATION_TYPE} and used to
+ * decide which kind of activation flow should be lauched.
+ *
+ * @hide
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"EUICC_ACTIVATION_"}, value = {
+ EUICC_ACTIVATION_TYPE_DEFAULT,
+ EUICC_ACTIVATION_TYPE_BACKUP,
+ EUICC_ACTIVATION_TYPE_TRANSFER
+
+ })
+ public @interface EuiccActivationType{}
+
+
+ /**
+ * The default euicc activation type which includes checking server side and downloading the
+ * profile based on carrier's download configuration.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int EUICC_ACTIVATION_TYPE_DEFAULT = 1;
+
+ /**
+ * The euicc activation type used when the default download process failed. LPA will start the
+ * backup flow and try to download the profile for the carrier.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int EUICC_ACTIVATION_TYPE_BACKUP = 2;
+
+ /**
+ * The activation flow of eSIM seamless transfer will be used. LPA will start normal eSIM
+ * activation flow and if it's failed, the name of the carrier selected will be recorded. After
+ * the future device pairing, LPA will contact this carrier to transfer it from the other device
+ * to this device.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final int EUICC_ACTIVATION_TYPE_TRANSFER = 3;
+
+
+ /**
* Euicc OTA update status which can be got by {@link #getOtaStatus}
* @hide
*/
@@ -336,7 +405,7 @@ public class EuiccManager {
}
try {
getIEuiccController().downloadSubscription(subscription, switchAfterDownload,
- mContext.getOpPackageName(), callbackIntent);
+ mContext.getOpPackageName(), null /* resolvedBundle */, callbackIntent);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
index 0a0ad90b5954..870a689f85b1 100644
--- a/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
+++ b/telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl
@@ -32,7 +32,7 @@ interface IEuiccController {
String getEid();
int getOtaStatus();
oneway void downloadSubscription(in DownloadableSubscription subscription,
- boolean switchAfterDownload, String callingPackage, in PendingIntent callbackIntent);
+ boolean switchAfterDownload, String callingPackage, in Bundle resolvedBundle, in PendingIntent callbackIntent);
EuiccInfo getEuiccInfo();
oneway void deleteSubscription(int subscriptionId, String callingPackage,
in PendingIntent callbackIntent);
diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
index 369a002fa273..4c2a984f8198 100644
--- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
@@ -16,16 +16,16 @@
package com.android.framework.permission.tests;
-import android.content.res.Configuration;
+import static android.view.Display.DEFAULT_DISPLAY;
+
import android.os.Binder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.test.suitebuilder.annotation.SmallTest;
import android.view.IWindowManager;
-import junit.framework.TestCase;
-import static android.view.Display.DEFAULT_DISPLAY;
+import junit.framework.TestCase;
/**
* TODO: Remove this. This is only a placeholder, need to implement this.
@@ -73,17 +73,6 @@ public class WindowManagerPermissionTests extends TestCase {
}
try {
- mWm.updateOrientationFromAppTokens(new Configuration(),
- null /* freezeThisOneIfNeeded */, DEFAULT_DISPLAY);
- fail("IWindowManager.updateOrientationFromAppTokens did not throw SecurityException as"
- + " expected");
- } catch (SecurityException e) {
- // expected
- } catch (RemoteException e) {
- fail("Unexpected remote exception");
- }
-
- try {
mWm.prepareAppTransition(0, false);
fail("IWindowManager.prepareAppTransition did not throw SecurityException as"
+ " expected");
diff --git a/tools/incident_report/printer.h b/tools/incident_report/printer.h
index ed93fa19542c..63e276b367ca 100644
--- a/tools/incident_report/printer.h
+++ b/tools/incident_report/printer.h
@@ -22,7 +22,7 @@
class Out
{
public:
- Out(int fd);
+ explicit Out(int fd);
~Out();
void printf(const char* format, ...);
diff --git a/tools/stats_log_api_gen/Android.bp b/tools/stats_log_api_gen/Android.bp
index 703a67b791be..5725f0cdae6e 100644
--- a/tools/stats_log_api_gen/Android.bp
+++ b/tools/stats_log_api_gen/Android.bp
@@ -96,6 +96,7 @@ genrule {
cc_library_shared {
name: "libstatslog",
+ host_supported: true,
generated_sources: ["statslog.cpp"],
generated_headers: ["statslog.h"],
cflags: [
@@ -105,8 +106,19 @@ cc_library_shared {
export_generated_headers: ["statslog.h"],
shared_libs: [
"liblog",
- "libutils",
"libcutils",
],
static_libs: ["libstatssocket"],
+ target: {
+ android: {
+ shared_libs: [
+ "libutils",
+ ],
+ },
+ host: {
+ static_libs: [
+ "libutils",
+ ],
+ },
+ },
}
diff --git a/tools/stats_log_api_gen/main.cpp b/tools/stats_log_api_gen/main.cpp
index 5192a0e7bf19..11b408fb8b9e 100644
--- a/tools/stats_log_api_gen/main.cpp
+++ b/tools/stats_log_api_gen/main.cpp
@@ -106,7 +106,9 @@ static int write_stats_log_cpp(FILE *out, const Atoms &atoms,
fprintf(out, "#include <mutex>\n");
fprintf(out, "#include <chrono>\n");
fprintf(out, "#include <thread>\n");
+ fprintf(out, "#ifdef __ANDROID__\n");
fprintf(out, "#include <cutils/properties.h>\n");
+ fprintf(out, "#endif\n");
fprintf(out, "#include <stats_event_list.h>\n");
fprintf(out, "#include <log/log.h>\n");
fprintf(out, "#include <statslog.h>\n");
@@ -117,7 +119,11 @@ static int write_stats_log_cpp(FILE *out, const Atoms &atoms,
fprintf(out, "namespace util {\n");
fprintf(out, "// the single event tag id for all stats logs\n");
fprintf(out, "const static int kStatsEventTag = 1937006964;\n");
+ fprintf(out, "#ifdef __ANDROID__\n");
fprintf(out, "const static bool kStatsdEnabled = property_get_bool(\"ro.statsd.enable\", true);\n");
+ fprintf(out, "#else\n");
+ fprintf(out, "const static bool kStatsdEnabled = false;\n");
+ fprintf(out, "#endif\n");
std::set<string> kTruncatingAtomNames = {"mobile_radio_power_state_changed",
"audio_state_changed",
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index 64f8adb36a93..d023b58437af 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -708,6 +708,12 @@ public class WifiConfiguration implements Parcelable {
}
/**
+ * This Wifi configuration is expected for OSU(Online Sign Up) of Passpoint Release 2.
+ * @hide
+ */
+ public boolean osu;
+
+ /**
* @hide
* Last time the system was connected to this configuration.
*/
@@ -1645,6 +1651,7 @@ public class WifiConfiguration implements Parcelable {
selfAdded = false;
didSelfAdd = false;
ephemeral = false;
+ osu = false;
trusted = true; // Networks are considered trusted by default.
meteredHint = false;
meteredOverride = METERED_OVERRIDE_NONE;
@@ -1755,6 +1762,7 @@ public class WifiConfiguration implements Parcelable {
if (this.selfAdded) sbuf.append(" selfAdded");
if (this.validatedInternetAccess) sbuf.append(" validatedInternetAccess");
if (this.ephemeral) sbuf.append(" ephemeral");
+ if (this.osu) sbuf.append(" osu");
if (this.trusted) sbuf.append(" trusted");
if (this.meteredHint) sbuf.append(" meteredHint");
if (this.useExternalScores) sbuf.append(" useExternalScores");
@@ -2244,6 +2252,7 @@ public class WifiConfiguration implements Parcelable {
validatedInternetAccess = source.validatedInternetAccess;
isLegacyPasspointConfig = source.isLegacyPasspointConfig;
ephemeral = source.ephemeral;
+ osu = source.osu;
trusted = source.trusted;
meteredHint = source.meteredHint;
meteredOverride = source.meteredOverride;
@@ -2340,6 +2349,7 @@ public class WifiConfiguration implements Parcelable {
dest.writeInt(recentFailure.getAssociationStatus());
dest.writeParcelable(mRandomizedMacAddress, flags);
dest.writeInt(macRandomizationSetting);
+ dest.writeInt(osu ? 1 : 0);
}
/** Implement the Parcelable interface {@hide} */
@@ -2410,6 +2420,7 @@ public class WifiConfiguration implements Parcelable {
config.recentFailure.setAssociationStatus(in.readInt());
config.mRandomizedMacAddress = in.readParcelable(null);
config.macRandomizationSetting = in.readInt();
+ config.osu = in.readInt() != 0;
return config;
}