Merge "Add @UnsupportedAppUsage annotations to telephony-common."
diff --git a/Android.bp b/Android.bp
index ecf567c..b80ef88 100644
--- a/Android.bp
+++ b/Android.bp
@@ -25,30 +25,105 @@
//
// READ ME: ########################################################
+// TODO(b/70046217): make these as filegroups where the base directory for aidl files
+// is given as 'path'. Eliminate the need for aidl_local_include_dirs.
+framework_srcs = [
+ // java sources under this directory
+ "core/java/**/*.java",
+ "drm/java/**/*.java",
+ "graphics/java/**/*.java",
+ "keystore/java/**/*.java",
+ "location/java/**/*.java",
+ "lowpan/java/**/*.java",
+ "media/java/**/*.java",
+ "media/mca/effect/java/**/*.java",
+ "media/mca/filterfw/java/**/*.java",
+ "media/mca/filterpacks/java/**/*.java",
+ "opengl/java/**/*.java",
+ "rs/java/**/*.java",
+ "sax/java/**/*.java",
+ "telecomm/java/**/*.java",
+ "telephony/java/**/*.java",
+ "wifi/java/**/*.java",
+
+ // aidl under this directory
+ // b/70046217#comment15 These MUST come after all java srcs.
+ // TODO(b/70046217) remove the above requirement
+ "core/java/**/*.aidl",
+ "graphics/java/**/*.aidl",
+ "keystore/java/**/*.aidl",
+ "location/java/**/*.aidl",
+ "lowpan/java/**/*.aidl",
+ "media/java/**/*.aidl",
+ "packages/services/PacProcessor/**/*.aidl",
+ "packages/services/Proxy/**/*.aidl",
+ "telecomm/java/**/*.aidl",
+ "telephony/java/**/*.aidl",
+ "wifi/java/**/*.aidl",
+
+ // aidl from external directories
+ ":dumpstate_aidl",
+ ":gatekeeper_aidl",
+ ":gsiservice_aidl",
+ ":incidentcompanion_aidl",
+ ":installd_aidl",
+ ":keystore_aidl",
+ ":libaudioclient_aidl",
+ ":libbinder_aidl",
+ ":libbluetooth-binder-aidl",
+ ":libcamera_client_aidl",
+ ":libcamera_client_framework_aidl",
+ ":libupdate_engine_aidl",
+ ":storaged_aidl",
+ ":vold_aidl",
+
+ // etc.
+ "core/java/**/*.logtags",
+ ":framework-javastream-protos",
+ ":framework-statslog-gen",
+]
+
+framework_aidl_local_include_dirs = [
+ "core/java",
+ "drm/java",
+ "graphics/java",
+ "keystore/java",
+ "location/java",
+ "lowpan/java",
+ "media/java",
+ "media/apex/java",
+ "media/mca/effect/java",
+ "media/mca/filterfw/java",
+ "media/mca/filterpacks/java",
+ "opengl/java",
+ "rs/java",
+ "sax/java",
+ "telecomm/java",
+ "telephony/java",
+ "wifi/java",
+]
+
+framework_aidl_external_include_dirs = [
+ "frameworks/av/camera/aidl",
+ "frameworks/av/media/libaudioclient/aidl",
+ "frameworks/native/aidl/binder",
+ "frameworks/native/aidl/gui",
+ "frameworks/native/cmds/dumpstate/binder",
+ "frameworks/native/libs/incidentcompanion/binder",
+ "system/bt/binder",
+ "system/core/gatekeeperd/binder",
+ "system/core/storaged/binder",
+ "system/gsid/aidl",
+ "system/security/keystore/binder",
+ "system/update_engine/binder_bindings",
+ "system/vold/binder",
+]
+
java_defaults {
name: "framework-aidl-export-defaults",
aidl: {
- export_include_dirs: [
- // From build/make/core/pathmap.mk FRAMEWORK_BASE_SUBDIRS
- "core/java",
- "graphics/java",
- "location/java",
- "lowpan/java",
- "media/java",
- "media/apex/java",
- "media/mca/effect/java",
- "media/mca/filterfw/java",
- "media/mca/filterpacks/java",
- "drm/java",
- "opengl/java",
- "sax/java",
- "telecomm/java",
- "telephony/java",
- "wifi/java",
- "keystore/java",
- "rs/java",
- ],
+ export_include_dirs: framework_aidl_local_include_dirs,
},
}
@@ -57,691 +132,11 @@
defaults: ["framework-aidl-export-defaults"],
installable: true,
- srcs: [
- // From build/make/core/pathmap.mk FRAMEWORK_BASE_SUBDIRS
- "core/java/**/*.java",
- "graphics/java/**/*.java",
- "location/java/**/*.java",
- "lowpan/java/**/*.java",
- "media/java/**/*.java",
- "media/mca/effect/java/**/*.java",
- "media/mca/filterfw/java/**/*.java",
- "media/mca/filterpacks/java/**/*.java",
- "drm/java/**/*.java",
- "opengl/java/**/*.java",
- "sax/java/**/*.java",
- "telecomm/java/**/*.java",
- "telephony/java/**/*.java",
- "wifi/java/**/*.java",
- "keystore/java/**/*.java",
- "rs/java/**/*.java",
-
- ":framework-javastream-protos",
-
- "core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl",
- "core/java/android/accessibilityservice/IAccessibilityServiceClient.aidl",
- "core/java/android/accounts/IAccountManager.aidl",
- "core/java/android/accounts/IAccountManagerResponse.aidl",
- "core/java/android/accounts/IAccountAuthenticator.aidl",
- "core/java/android/accounts/IAccountAuthenticatorResponse.aidl",
- "core/java/android/app/IActivityController.aidl",
- "core/java/android/app/IActivityManager.aidl",
- "core/java/android/app/IActivityPendingResult.aidl",
- "core/java/android/app/IActivityTaskManager.aidl",
- "core/java/android/app/IAlarmCompleteListener.aidl",
- "core/java/android/app/IAlarmListener.aidl",
- "core/java/android/app/IAlarmManager.aidl",
- "core/java/android/app/IAppTask.aidl",
- "core/java/android/app/IApplicationThread.aidl",
- "core/java/android/app/IAssistDataReceiver.aidl",
- "core/java/android/app/ITaskStackListener.aidl",
- "core/java/android/app/IBackupAgent.aidl",
- "core/java/android/app/IEphemeralResolver.aidl",
- "core/java/android/app/IInstantAppResolver.aidl",
- "core/java/android/app/IInstrumentationWatcher.aidl",
- "core/java/android/app/INotificationManager.aidl",
- "core/java/android/app/IProcessObserver.aidl",
- "core/java/android/app/IRequestFinishCallback.aidl",
- "core/java/android/app/ISearchManager.aidl",
- "core/java/android/app/ISearchManagerCallback.aidl",
- "core/java/android/app/IServiceConnection.aidl",
- "core/java/android/app/IStopUserCallback.aidl",
- "core/java/android/app/ITransientNotification.aidl",
- "core/java/android/app/IUidObserver.aidl",
- "core/java/android/app/IUiAutomationConnection.aidl",
- "core/java/android/app/IUiModeManager.aidl",
- "core/java/android/app/IUriGrantsManager.aidl",
- "core/java/android/app/IUserSwitchObserver.aidl",
- "core/java/android/app/IWallpaperManager.aidl",
- "core/java/android/app/IWallpaperManagerCallback.aidl",
- "core/java/android/app/admin/IDeviceAdminService.aidl",
- "core/java/android/app/admin/IDevicePolicyManager.aidl",
- "core/java/android/app/admin/StartInstallingUpdateCallback.aidl",
- "core/java/android/app/trust/IStrongAuthTracker.aidl",
- "core/java/android/app/trust/ITrustManager.aidl",
- "core/java/android/app/trust/ITrustListener.aidl",
- "core/java/android/app/backup/IBackupCallback.aidl",
- "core/java/android/app/backup/IBackupManager.aidl",
- "core/java/android/app/backup/IBackupObserver.aidl",
- "core/java/android/app/backup/IBackupManagerMonitor.aidl",
- "core/java/android/app/backup/IFullBackupRestoreObserver.aidl",
- "core/java/android/app/backup/IRestoreObserver.aidl",
- "core/java/android/app/backup/IRestoreSession.aidl",
- "core/java/android/app/backup/ISelectBackupTransportCallback.aidl",
- "core/java/android/app/contentsuggestions/IClassificationsCallback.aidl",
- "core/java/android/app/contentsuggestions/IContentSuggestionsManager.aidl",
- "core/java/android/app/contentsuggestions/ISelectionsCallback.aidl",
- "core/java/android/app/prediction/IPredictionCallback.aidl",
- "core/java/android/app/prediction/IPredictionManager.aidl",
- "core/java/android/app/role/IOnRoleHoldersChangedListener.aidl",
- "core/java/android/app/role/IRoleController.aidl",
- "core/java/android/app/role/IRoleManager.aidl",
- "core/java/android/app/slice/ISliceManager.aidl",
- "core/java/android/app/slice/ISliceListener.aidl",
- "core/java/android/app/timedetector/ITimeDetectorService.aidl",
- "core/java/android/app/timezone/ICallback.aidl",
- "core/java/android/app/timezone/IRulesManager.aidl",
- "core/java/android/app/usage/ICacheQuotaService.aidl",
- "core/java/android/app/usage/IStorageStatsManager.aidl",
- "core/java/android/app/usage/IUsageStatsManager.aidl",
- ":libbluetooth-binder-aidl",
- "core/java/android/content/IClipboard.aidl",
- "core/java/android/content/IContentService.aidl",
- "core/java/android/content/IIntentReceiver.aidl",
- "core/java/android/content/IIntentSender.aidl",
- "core/java/android/content/IOnPrimaryClipChangedListener.aidl",
- "core/java/android/content/IRestrictionsManager.aidl",
- "core/java/android/content/ISyncAdapter.aidl",
- "core/java/android/content/ISyncAdapterUnsyncableAccountCallback.aidl",
- "core/java/android/content/ISyncContext.aidl",
- "core/java/android/content/ISyncServiceAdapter.aidl",
- "core/java/android/content/ISyncStatusObserver.aidl",
- "core/java/android/content/om/IOverlayManager.aidl",
- "core/java/android/content/pm/ICrossProfileApps.aidl",
- "core/java/android/content/pm/IDexModuleRegisterCallback.aidl",
- "core/java/android/content/pm/ILauncherApps.aidl",
- "core/java/android/content/pm/IOnAppsChangedListener.aidl",
- "core/java/android/content/pm/IOtaDexopt.aidl",
- "core/java/android/content/pm/IPackageDataObserver.aidl",
- "core/java/android/content/pm/IPackageDeleteObserver.aidl",
- "core/java/android/content/pm/IPackageDeleteObserver2.aidl",
- "core/java/android/content/pm/IPackageInstallObserver2.aidl",
- "core/java/android/content/pm/IPackageInstaller.aidl",
- "core/java/android/content/pm/IPackageInstallerCallback.aidl",
- "core/java/android/content/pm/IPackageInstallerSession.aidl",
- "core/java/android/content/pm/IPackageManager.aidl",
- ":libbinder_aidl",
- "core/java/android/content/pm/IPackageMoveObserver.aidl",
- "core/java/android/content/pm/IPackageStatsObserver.aidl",
- "core/java/android/content/pm/IPinItemRequest.aidl",
- "core/java/android/content/pm/IShortcutService.aidl",
- "core/java/android/content/pm/dex/IArtManager.aidl",
- "core/java/android/content/pm/dex/ISnapshotRuntimeProfileCallback.aidl",
- "core/java/android/content/pm/permission/IRuntimePermissionPresenter.aidl",
- "core/java/android/content/rollback/IRollbackManager.aidl",
- "core/java/android/database/IContentObserver.aidl",
- "core/java/android/debug/IAdbManager.aidl",
- "core/java/android/debug/IAdbTransport.aidl",
- ":libcamera_client_aidl",
- ":libcamera_client_framework_aidl",
- "core/java/android/hardware/IConsumerIrService.aidl",
- "core/java/android/hardware/ISerialManager.aidl",
- "core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl",
- "core/java/android/hardware/biometrics/IBiometricEnabledOnKeyguardCallback.aidl",
- "core/java/android/hardware/biometrics/IBiometricService.aidl",
- "core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl",
- "core/java/android/hardware/biometrics/IBiometricServiceReceiverInternal.aidl",
- "core/java/android/hardware/biometrics/IBiometricServiceLockoutResetCallback.aidl",
- "core/java/android/hardware/display/IColorDisplayManager.aidl",
- "core/java/android/hardware/display/IDisplayManager.aidl",
- "core/java/android/hardware/display/IDisplayManagerCallback.aidl",
- "core/java/android/hardware/display/IVirtualDisplayCallback.aidl",
- "core/java/android/hardware/fingerprint/IFingerprintClientActiveCallback.aidl",
- "core/java/android/hardware/face/IFaceService.aidl",
- "core/java/android/hardware/face/IFaceServiceReceiver.aidl",
- "core/java/android/hardware/fingerprint/IFingerprintService.aidl",
- "core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl",
- "core/java/android/hardware/hdmi/IHdmiControlCallback.aidl",
- "core/java/android/hardware/hdmi/IHdmiControlService.aidl",
- "core/java/android/hardware/hdmi/IHdmiDeviceEventListener.aidl",
- "core/java/android/hardware/hdmi/IHdmiHotplugEventListener.aidl",
- "core/java/android/hardware/hdmi/IHdmiInputChangeListener.aidl",
- "core/java/android/hardware/hdmi/IHdmiMhlVendorCommandListener.aidl",
- "core/java/android/hardware/hdmi/IHdmiRecordListener.aidl",
- "core/java/android/hardware/hdmi/IHdmiSystemAudioModeChangeListener.aidl",
- "core/java/android/hardware/hdmi/IHdmiVendorCommandListener.aidl",
- "core/java/android/hardware/input/IInputManager.aidl",
- "core/java/android/hardware/input/IInputDevicesChangedListener.aidl",
- "core/java/android/hardware/input/ITabletModeChangedListener.aidl",
- "core/java/android/hardware/iris/IIrisService.aidl",
- "core/java/android/hardware/location/IActivityRecognitionHardware.aidl",
- "core/java/android/hardware/location/IActivityRecognitionHardwareClient.aidl",
- "core/java/android/hardware/location/IActivityRecognitionHardwareSink.aidl",
- "core/java/android/hardware/location/IActivityRecognitionHardwareWatcher.aidl",
- "core/java/android/hardware/location/IGeofenceHardware.aidl",
- "core/java/android/hardware/location/IGeofenceHardwareCallback.aidl",
- "core/java/android/hardware/location/IGeofenceHardwareMonitorCallback.aidl",
- "core/java/android/hardware/location/IContextHubCallback.aidl",
- "core/java/android/hardware/location/IContextHubClient.aidl",
- "core/java/android/hardware/location/IContextHubClientCallback.aidl",
- "core/java/android/hardware/location/IContextHubService.aidl",
- "core/java/android/hardware/location/IContextHubTransactionCallback.aidl",
- "core/java/android/hardware/radio/IAnnouncementListener.aidl",
- "core/java/android/hardware/radio/ICloseHandle.aidl",
- "core/java/android/hardware/radio/IRadioService.aidl",
- "core/java/android/hardware/radio/ITuner.aidl",
- "core/java/android/hardware/radio/ITunerCallback.aidl",
- "core/java/android/hardware/soundtrigger/IRecognitionStatusCallback.aidl",
- "core/java/android/hardware/usb/IUsbManager.aidl",
- "core/java/android/hardware/usb/IUsbSerialReader.aidl",
- "core/java/android/net/ICaptivePortal.aidl",
- "core/java/android/net/IConnectivityManager.aidl",
- "core/java/android/hardware/ISensorPrivacyListener.aidl",
- "core/java/android/hardware/ISensorPrivacyManager.aidl",
- "core/java/android/net/IIpConnectivityMetrics.aidl",
- "core/java/android/net/IEthernetManager.aidl",
- "core/java/android/net/IEthernetServiceListener.aidl",
- "core/java/android/net/INetdEventCallback.aidl",
- "core/java/android/net/IIpSecService.aidl",
- "core/java/android/net/INetworkManagementEventObserver.aidl",
- "core/java/android/net/INetworkPolicyListener.aidl",
- "core/java/android/net/INetworkPolicyManager.aidl",
- "core/java/android/net/INetworkRecommendationProvider.aidl",
- "core/java/android/net/INetworkScoreCache.aidl",
- "core/java/android/net/INetworkScoreService.aidl",
- "core/java/android/net/INetworkStatsService.aidl",
- "core/java/android/net/INetworkStatsSession.aidl",
- "core/java/android/net/ISocketKeepaliveCallback.aidl",
- "core/java/android/net/ITestNetworkManager.aidl",
- "core/java/android/net/ITetheringEventCallback.aidl",
- "core/java/android/net/ITetheringStatsProvider.aidl",
- "core/java/android/net/nsd/INsdManager.aidl",
- "core/java/android/nfc/IAppCallback.aidl",
- "core/java/android/nfc/INfcAdapter.aidl",
- "core/java/android/nfc/INfcAdapterExtras.aidl",
- "core/java/android/nfc/INfcTag.aidl",
- "core/java/android/nfc/INfcCardEmulation.aidl",
- "core/java/android/nfc/INfcFCardEmulation.aidl",
- "core/java/android/nfc/INfcUnlockHandler.aidl",
- "core/java/android/nfc/INfcDta.aidl",
- "core/java/android/nfc/ITagRemovedCallback.aidl",
- "core/java/android/se/omapi/ISecureElementService.aidl",
- "core/java/android/se/omapi/ISecureElementListener.aidl",
- "core/java/android/se/omapi/ISecureElementChannel.aidl",
- "core/java/android/se/omapi/ISecureElementReader.aidl",
- "core/java/android/se/omapi/ISecureElementSession.aidl",
- "core/java/android/os/IBatteryPropertiesRegistrar.aidl",
- "core/java/android/os/ICancellationSignal.aidl",
- "core/java/android/os/IDeviceIdentifiersPolicyService.aidl",
- "core/java/android/os/IDeviceIdleController.aidl",
- "core/java/android/os/IHardwarePropertiesManager.aidl",
- ":libincident_aidl",
- "core/java/android/os/IMaintenanceActivityListener.aidl",
- "core/java/android/os/IMessenger.aidl",
- "core/java/android/os/INetworkActivityListener.aidl",
- "core/java/android/os/INetworkManagementService.aidl",
- "core/java/android/os/IPermissionController.aidl",
- "core/java/android/os/IProcessInfoService.aidl",
- "core/java/android/os/IProgressListener.aidl",
- "core/java/android/os/IPowerManager.aidl",
- "core/java/android/os/IRecoverySystem.aidl",
- "core/java/android/os/IRecoverySystemProgressListener.aidl",
- "core/java/android/os/IRemoteCallback.aidl",
- "core/java/android/os/ISchedulingPolicyService.aidl",
- ":statsd_aidl",
- "core/java/android/os/ISystemUpdateManager.aidl",
- "core/java/android/os/IThermalEventListener.aidl",
- "core/java/android/os/IThermalStatusListener.aidl",
- "core/java/android/os/IThermalService.aidl",
- "core/java/android/os/IUpdateLock.aidl",
- "core/java/android/os/IUserManager.aidl",
- ":libvibrator_aidl",
- "core/java/android/os/IVibratorService.aidl",
- "core/java/android/os/image/IDynamicSystemService.aidl",
- "core/java/android/os/storage/IStorageManager.aidl",
- "core/java/android/os/storage/IStorageEventListener.aidl",
- "core/java/android/os/storage/IStorageShutdownObserver.aidl",
- "core/java/android/os/storage/IObbActionListener.aidl",
- "core/java/android/permission/IOnPermissionsChangeListener.aidl",
- "core/java/android/permission/IPermissionController.aidl",
- "core/java/android/permission/IPermissionManager.aidl",
- ":keystore_aidl",
- "core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl",
- "core/java/android/service/appprediction/IPredictionService.aidl",
- "core/java/android/service/autofill/augmented/IAugmentedAutofillService.aidl",
- "core/java/android/service/autofill/augmented/IFillCallback.aidl",
- "core/java/android/service/autofill/IAutoFillService.aidl",
- "core/java/android/service/autofill/IAutofillFieldClassificationService.aidl",
- "core/java/android/service/autofill/IFillCallback.aidl",
- "core/java/android/service/autofill/ISaveCallback.aidl",
- "core/java/android/service/carrier/ICarrierService.aidl",
- "core/java/android/service/carrier/ICarrierMessagingCallback.aidl",
- "core/java/android/service/carrier/ICarrierMessagingService.aidl",
- "core/java/android/service/carrier/ICarrierMessagingClientService.aidl",
- "core/java/android/service/contentsuggestions/IContentSuggestionsService.aidl",
- "core/java/android/service/euicc/IDeleteSubscriptionCallback.aidl",
- "core/java/android/service/euicc/IDownloadSubscriptionCallback.aidl",
- "core/java/android/service/euicc/IEraseSubscriptionsCallback.aidl",
- "core/java/android/service/euicc/IEuiccService.aidl",
- "core/java/android/service/euicc/IGetDefaultDownloadableSubscriptionListCallback.aidl",
- "core/java/android/service/euicc/IGetDownloadableSubscriptionMetadataCallback.aidl",
- "core/java/android/service/euicc/IGetEidCallback.aidl",
- "core/java/android/service/euicc/IGetEuiccInfoCallback.aidl",
- "core/java/android/service/euicc/IGetEuiccProfileInfoListCallback.aidl",
- "core/java/android/service/euicc/IGetOtaStatusCallback.aidl",
- "core/java/android/service/euicc/IOtaStatusChangedCallback.aidl",
- "core/java/android/service/euicc/IRetainSubscriptionsForFactoryResetCallback.aidl",
- "core/java/android/service/euicc/ISwitchToSubscriptionCallback.aidl",
- "core/java/android/service/euicc/IUpdateSubscriptionNicknameCallback.aidl",
- ":gatekeeper_aidl",
- "core/java/android/service/contentcapture/IContentCaptureService.aidl",
- "core/java/android/service/contentcapture/IContentCaptureServiceCallback.aidl",
- "core/java/android/service/notification/INotificationListener.aidl",
- "core/java/android/service/notification/IStatusBarNotificationHolder.aidl",
- "core/java/android/service/notification/IConditionListener.aidl",
- "core/java/android/service/notification/IConditionProvider.aidl",
- "core/java/android/service/settings/suggestions/ISuggestionService.aidl",
- "core/java/android/service/sms/IFinancialSmsService.aidl",
- "core/java/android/service/vr/IPersistentVrStateCallbacks.aidl",
- "core/java/android/service/vr/IVrListener.aidl",
- "core/java/android/service/vr/IVrManager.aidl",
- "core/java/android/service/vr/IVrStateCallbacks.aidl",
- "core/java/android/service/watchdog/IExplicitHealthCheckService.aidl",
- "core/java/android/service/watchdog/PackageConfig.aidl",
- "core/java/android/print/ILayoutResultCallback.aidl",
- "core/java/android/print/IPrinterDiscoveryObserver.aidl",
- "core/java/android/print/IPrintDocumentAdapter.aidl",
- "core/java/android/print/IPrintDocumentAdapterObserver.aidl",
- "core/java/android/print/IPrintJobStateChangeListener.aidl",
- "core/java/android/print/IPrintServicesChangeListener.aidl",
- "core/java/android/printservice/recommendation/IRecommendationsChangeListener.aidl",
- "core/java/android/print/IPrintManager.aidl",
- "core/java/android/print/IPrintSpooler.aidl",
- "core/java/android/print/IPrintSpoolerCallbacks.aidl",
- "core/java/android/print/IPrintSpoolerClient.aidl",
- "core/java/android/printservice/recommendation/IRecommendationServiceCallbacks.aidl",
- "core/java/android/printservice/recommendation/IRecommendationService.aidl",
- "core/java/android/print/IWriteResultCallback.aidl",
- "core/java/android/printservice/IPrintService.aidl",
- "core/java/android/printservice/IPrintServiceClient.aidl",
- "core/java/android/companion/ICompanionDeviceManager.aidl",
- "core/java/android/companion/ICompanionDeviceDiscoveryService.aidl",
- "core/java/android/companion/ICompanionDeviceDiscoveryServiceCallback.aidl",
- "core/java/android/companion/IFindDeviceCallback.aidl",
- "core/java/android/service/dreams/IDreamManager.aidl",
- "core/java/android/service/dreams/IDreamService.aidl",
- "core/java/android/service/oemlock/IOemLockService.aidl",
- "core/java/android/service/persistentdata/IPersistentDataBlockService.aidl",
- "core/java/android/service/trust/ITrustAgentService.aidl",
- "core/java/android/service/trust/ITrustAgentServiceCallback.aidl",
- "core/java/android/service/voice/IVoiceInteractionService.aidl",
- "core/java/android/service/voice/IVoiceInteractionSession.aidl",
- "core/java/android/service/voice/IVoiceInteractionSessionService.aidl",
- "core/java/android/service/wallpaper/IWallpaperConnection.aidl",
- "core/java/android/service/wallpaper/IWallpaperEngine.aidl",
- "core/java/android/service/wallpaper/IWallpaperService.aidl",
- "core/java/android/service/chooser/IChooserTargetService.aidl",
- "core/java/android/service/chooser/IChooserTargetResult.aidl",
- "core/java/android/service/resolver/IResolverRankerService.aidl",
- "core/java/android/service/resolver/IResolverRankerResult.aidl",
- "core/java/android/service/textclassifier/ITextClassifierCallback.aidl",
- "core/java/android/service/textclassifier/ITextClassifierService.aidl",
- "core/java/android/service/attention/IAttentionService.aidl",
- "core/java/android/service/attention/IAttentionCallback.aidl",
- "core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl",
- "core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl",
- "core/java/android/view/accessibility/IAccessibilityManager.aidl",
- "core/java/android/view/accessibility/IAccessibilityManagerClient.aidl",
- "core/java/android/view/autofill/IAutoFillManager.aidl",
- "core/java/android/view/autofill/IAutoFillManagerClient.aidl",
- "core/java/android/view/autofill/IAugmentedAutofillManagerClient.aidl",
- "core/java/android/view/autofill/IAutofillWindowPresenter.aidl",
- "core/java/android/view/contentcapture/IContentCaptureDirectManager.aidl",
- "core/java/android/view/contentcapture/IContentCaptureManager.aidl",
- "core/java/android/view/IApplicationToken.aidl",
- "core/java/android/view/IAppTransitionAnimationSpecsFuture.aidl",
- "core/java/android/view/IDockedStackListener.aidl",
- "core/java/android/view/IDisplayFoldListener.aidl",
- "core/java/android/view/IGraphicsStats.aidl",
- "core/java/android/view/IGraphicsStatsCallback.aidl",
- "core/java/android/view/IInputMonitorHost.aidl",
- "core/java/android/view/IInputFilter.aidl",
- "core/java/android/view/IInputFilterHost.aidl",
- "core/java/android/view/IOnKeyguardExitResult.aidl",
- "core/java/android/view/IPinnedStackController.aidl",
- "core/java/android/view/IPinnedStackListener.aidl",
- "core/java/android/view/IRemoteAnimationRunner.aidl",
- "core/java/android/view/IRecentsAnimationController.aidl",
- "core/java/android/view/IRecentsAnimationRunner.aidl",
- "core/java/android/view/IRemoteAnimationFinishedCallback.aidl",
- "core/java/android/view/IRotationWatcher.aidl",
- "core/java/android/view/ISystemGestureExclusionListener.aidl",
- "core/java/android/view/IWallpaperVisibilityListener.aidl",
- "core/java/android/view/IWindow.aidl",
- "core/java/android/view/IWindowFocusObserver.aidl",
- "core/java/android/view/IWindowId.aidl",
- "core/java/android/view/IWindowManager.aidl",
- "core/java/android/view/IWindowSession.aidl",
- "core/java/android/view/IWindowSessionCallback.aidl",
- "core/java/android/webkit/IWebViewUpdateService.aidl",
- "core/java/android/speech/IRecognitionListener.aidl",
- "core/java/android/speech/IRecognitionService.aidl",
- "core/java/android/speech/tts/ITextToSpeechCallback.aidl",
- "core/java/android/speech/tts/ITextToSpeechService.aidl",
- "core/java/com/android/internal/app/IAppOpsActiveCallback.aidl",
- "core/java/com/android/internal/app/IAppOpsCallback.aidl",
- "core/java/com/android/internal/app/IAppOpsNotedCallback.aidl",
- "core/java/com/android/internal/app/IAppOpsService.aidl",
- "core/java/com/android/internal/app/IBatteryStats.aidl",
- "core/java/com/android/internal/app/ISoundTriggerService.aidl",
- "core/java/com/android/internal/app/IVoiceActionCheckCallback.aidl",
- "core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl",
- "core/java/com/android/internal/app/IVoiceInteractionSessionListener.aidl",
- "core/java/com/android/internal/app/IVoiceInteractionSessionShowCallback.aidl",
- "core/java/com/android/internal/app/IVoiceInteractor.aidl",
- "core/java/com/android/internal/app/IVoiceInteractorCallback.aidl",
- "core/java/com/android/internal/app/IVoiceInteractorRequest.aidl",
- "core/java/com/android/internal/app/IMediaContainerService.aidl",
- "core/java/com/android/internal/app/procstats/IProcessStats.aidl",
- "core/java/com/android/internal/appwidget/IAppWidgetService.aidl",
- "core/java/com/android/internal/appwidget/IAppWidgetHost.aidl",
- "core/java/com/android/internal/backup/IBackupTransport.aidl",
- "core/java/com/android/internal/backup/IObbBackupService.aidl",
- "core/java/com/android/internal/infra/IAndroidFuture.aidl",
- "core/java/com/android/internal/inputmethod/IInputContentUriToken.aidl",
- "core/java/com/android/internal/inputmethod/IInputMethodPrivilegedOperations.aidl",
- "core/java/com/android/internal/inputmethod/IMultiClientInputMethod.aidl",
- "core/java/com/android/internal/inputmethod/IMultiClientInputMethodPrivilegedOperations.aidl",
- "core/java/com/android/internal/inputmethod/IMultiClientInputMethodSession.aidl",
- "core/java/com/android/internal/net/INetworkWatchlistManager.aidl",
- "core/java/com/android/internal/policy/IKeyguardDrawnCallback.aidl",
- "core/java/com/android/internal/policy/IKeyguardDismissCallback.aidl",
- "core/java/com/android/internal/policy/IKeyguardExitCallback.aidl",
- "core/java/com/android/internal/policy/IKeyguardService.aidl",
- "core/java/com/android/internal/policy/IKeyguardStateCallback.aidl",
- "core/java/com/android/internal/policy/IShortcutService.aidl",
- "core/java/com/android/internal/os/IDropBoxManagerService.aidl",
- "core/java/com/android/internal/os/IParcelFileDescriptorFactory.aidl",
- "core/java/com/android/internal/os/IResultReceiver.aidl",
- "core/java/com/android/internal/os/IShellCallback.aidl",
- "core/java/com/android/internal/statusbar/IStatusBar.aidl",
- "core/java/com/android/internal/statusbar/IStatusBarService.aidl",
- "core/java/com/android/internal/statusbar/RegisterStatusBarResult.aidl",
- "core/java/com/android/internal/textservice/ISpellCheckerService.aidl",
- "core/java/com/android/internal/textservice/ISpellCheckerServiceCallback.aidl",
- "core/java/com/android/internal/textservice/ISpellCheckerSession.aidl",
- "core/java/com/android/internal/textservice/ISpellCheckerSessionListener.aidl",
- "core/java/com/android/internal/textservice/ITextServicesManager.aidl",
- "core/java/com/android/internal/textservice/ITextServicesSessionListener.aidl",
- "core/java/com/android/internal/view/IDragAndDropPermissions.aidl",
- "core/java/com/android/internal/view/IInputContext.aidl",
- "core/java/com/android/internal/view/IInputContextCallback.aidl",
- "core/java/com/android/internal/view/IInputMethod.aidl",
- "core/java/com/android/internal/view/IInputMethodClient.aidl",
- "core/java/com/android/internal/view/IInputMethodManager.aidl",
- "core/java/com/android/internal/view/IInputMethodSession.aidl",
- "core/java/com/android/internal/view/IInputSessionCallback.aidl",
- "core/java/com/android/internal/widget/ICheckCredentialProgressCallback.aidl",
- "core/java/com/android/internal/widget/ILockSettings.aidl",
- "core/java/com/android/internal/widget/IRemoteViewsFactory.aidl",
- "keystore/java/android/security/IKeyChainAliasCallback.aidl",
- "keystore/java/android/security/IKeyChainService.aidl",
- "location/java/android/location/IBatchedLocationCallback.aidl",
- "location/java/android/location/ICountryDetector.aidl",
- "location/java/android/location/ICountryListener.aidl",
- "location/java/android/location/IGeocodeProvider.aidl",
- "location/java/android/location/IGeofenceProvider.aidl",
- "location/java/android/location/IGnssStatusListener.aidl",
- "location/java/android/location/IGnssMeasurementsListener.aidl",
- "location/java/android/location/IGnssNavigationMessageListener.aidl",
- "location/java/android/location/ILocationListener.aidl",
- "location/java/android/location/ILocationManager.aidl",
- "location/java/android/location/IFusedGeofenceHardware.aidl",
- "location/java/android/location/IGpsGeofenceHardware.aidl",
- "location/java/android/location/INetInitiatedListener.aidl",
- "location/java/com/android/internal/location/ILocationProvider.aidl",
- "location/java/com/android/internal/location/ILocationProviderManager.aidl",
- "media/java/android/media/IAudioFocusDispatcher.aidl",
- "media/java/android/media/IAudioRoutesObserver.aidl",
- "media/java/android/media/IAudioService.aidl",
- "media/java/android/media/IAudioServerStateDispatcher.aidl",
- "media/java/android/media/IMediaHTTPConnection.aidl",
- "media/java/android/media/IMediaHTTPService.aidl",
- "media/java/android/media/IMediaResourceMonitor.aidl",
- "media/java/android/media/IMediaRoute2Provider.aidl",
- "media/java/android/media/IMediaRoute2ProviderClient.aidl",
- "media/java/android/media/IMediaRouter2Client.aidl",
- "media/java/android/media/IMediaRouter2Manager.aidl",
- "media/java/android/media/IMediaRouterClient.aidl",
- "media/java/android/media/IMediaRouterService.aidl",
- "media/java/android/media/IMediaScannerListener.aidl",
- "media/java/android/media/IMediaScannerService.aidl",
- "media/java/android/media/IPlaybackConfigDispatcher.aidl",
- ":libaudioclient_aidl",
- "media/java/android/media/IRecordingConfigDispatcher.aidl",
- "media/java/android/media/IRemoteDisplayCallback.aidl",
- "media/java/android/media/IRemoteDisplayProvider.aidl",
- "media/java/android/media/IRemoteVolumeController.aidl",
- "media/java/android/media/IRemoteVolumeObserver.aidl",
- "media/java/android/media/IRingtonePlayer.aidl",
- "media/java/android/media/IVolumeController.aidl",
- "media/java/android/media/audiopolicy/IAudioPolicyCallback.aidl",
- "media/java/android/media/midi/IBluetoothMidiService.aidl",
- "media/java/android/media/midi/IMidiDeviceListener.aidl",
- "media/java/android/media/midi/IMidiDeviceOpenCallback.aidl",
- "media/java/android/media/midi/IMidiDeviceServer.aidl",
- "media/java/android/media/midi/IMidiManager.aidl",
- "media/java/android/media/projection/IMediaProjection.aidl",
- "media/java/android/media/projection/IMediaProjectionCallback.aidl",
- "media/java/android/media/projection/IMediaProjectionManager.aidl",
- "media/java/android/media/projection/IMediaProjectionWatcherCallback.aidl",
- "media/java/android/media/session/IActiveSessionsListener.aidl",
- "media/java/android/media/session/ICallback.aidl",
- "media/java/android/media/session/IOnMediaKeyListener.aidl",
- "media/java/android/media/session/IOnVolumeKeyLongPressListener.aidl",
- "media/java/android/media/session/ISession.aidl",
- "media/java/android/media/session/ISession2TokensListener.aidl",
- "media/java/android/media/session/ISessionCallback.aidl",
- "media/java/android/media/session/ISessionController.aidl",
- "media/java/android/media/session/ISessionControllerCallback.aidl",
- "media/java/android/media/session/ISessionManager.aidl",
- "media/java/android/media/soundtrigger/ISoundTriggerDetectionService.aidl",
- "media/java/android/media/soundtrigger/ISoundTriggerDetectionServiceClient.aidl",
- "media/java/android/media/tv/ITvInputClient.aidl",
- "media/java/android/media/tv/ITvInputHardware.aidl",
- "media/java/android/media/tv/ITvInputHardwareCallback.aidl",
- "media/java/android/media/tv/ITvInputManager.aidl",
- "media/java/android/media/tv/ITvInputManagerCallback.aidl",
- "media/java/android/media/tv/ITvInputService.aidl",
- "media/java/android/media/tv/ITvInputServiceCallback.aidl",
- "media/java/android/media/tv/ITvInputSession.aidl",
- "media/java/android/media/tv/ITvInputSessionCallback.aidl",
- "media/java/android/media/tv/ITvRemoteProvider.aidl",
- "media/java/android/media/tv/ITvRemoteServiceInput.aidl",
- "media/java/android/service/media/IMediaBrowserService.aidl",
- "media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl",
- "telecomm/java/com/android/internal/telecom/ICallRedirectionAdapter.aidl",
- "telecomm/java/com/android/internal/telecom/ICallRedirectionService.aidl",
- "telecomm/java/com/android/internal/telecom/ICallScreeningAdapter.aidl",
- "telecomm/java/com/android/internal/telecom/ICallScreeningService.aidl",
- "telecomm/java/com/android/internal/telecom/IVideoCallback.aidl",
- "telecomm/java/com/android/internal/telecom/IVideoProvider.aidl",
- "telecomm/java/com/android/internal/telecom/IConnectionService.aidl",
- "telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl",
- "telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl",
- "telecomm/java/com/android/internal/telecom/IInCallService.aidl",
- "telecomm/java/com/android/internal/telecom/IPhoneAccountSuggestionCallback.aidl",
- "telecomm/java/com/android/internal/telecom/IPhoneAccountSuggestionService.aidl",
- "telecomm/java/com/android/internal/telecom/ITelecomService.aidl",
- "telecomm/java/com/android/internal/telecom/RemoteServiceCallback.aidl",
- "telephony/java/android/telephony/data/IDataService.aidl",
- "telephony/java/android/telephony/data/IDataServiceCallback.aidl",
- "telephony/java/android/telephony/data/IQualifiedNetworksService.aidl",
- "telephony/java/android/telephony/data/IQualifiedNetworksServiceCallback.aidl",
- "telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl",
- "telephony/java/android/telephony/ims/aidl/IImsCapabilityCallback.aidl",
- "telephony/java/android/telephony/ims/aidl/IImsConfig.aidl",
- "telephony/java/android/telephony/ims/aidl/IImsConfigCallback.aidl",
- "telephony/java/android/telephony/ims/aidl/IImsMmTelFeature.aidl",
- "telephony/java/android/telephony/ims/aidl/IImsMmTelListener.aidl",
- "telephony/java/android/telephony/ims/aidl/IImsRegistration.aidl",
- "telephony/java/android/telephony/ims/aidl/IImsRegistrationCallback.aidl",
- "telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl",
- "telephony/java/android/telephony/ims/aidl/IImsServiceController.aidl",
- "telephony/java/android/telephony/ims/aidl/IImsServiceControllerListener.aidl",
- "telephony/java/android/telephony/ims/aidl/IImsSmsListener.aidl",
- "telephony/java/android/telephony/ims/aidl/IRcsMessage.aidl",
- "telephony/java/android/telephony/ims/aidl/IRcsFeatureListener.aidl",
- "telephony/java/android/telephony/mbms/IMbmsDownloadSessionCallback.aidl",
- "telephony/java/android/telephony/mbms/IMbmsStreamingSessionCallback.aidl",
- "telephony/java/android/telephony/mbms/IMbmsGroupCallSessionCallback.aidl",
- "telephony/java/android/telephony/mbms/IDownloadStatusListener.aidl",
- "telephony/java/android/telephony/mbms/IDownloadProgressListener.aidl",
- "telephony/java/android/telephony/mbms/IStreamingServiceCallback.aidl",
- "telephony/java/android/telephony/mbms/IGroupCallCallback.aidl",
- "telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl",
- "telephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.aidl",
- "telephony/java/android/telephony/mbms/vendor/IMbmsGroupCallService.aidl",
- "telephony/java/android/telephony/ICellInfoCallback.aidl",
- "telephony/java/android/telephony/IFinancialSmsCallback.aidl",
- "telephony/java/android/telephony/INetworkService.aidl",
- "telephony/java/android/telephony/INetworkServiceCallback.aidl",
- "telephony/java/com/android/ims/internal/IImsCallSession.aidl",
- "telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl",
- "telephony/java/com/android/ims/internal/IImsConfig.aidl",
- "telephony/java/com/android/ims/internal/IImsRegistrationListener.aidl",
- "telephony/java/com/android/ims/internal/IImsEcbm.aidl",
- "telephony/java/com/android/ims/internal/IImsEcbmListener.aidl",
- "telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl",
- "telephony/java/com/android/ims/internal/IImsFeatureStatusCallback.aidl",
- "telephony/java/com/android/ims/internal/IImsMMTelFeature.aidl",
- "telephony/java/com/android/ims/internal/IImsMultiEndpoint.aidl",
- "telephony/java/com/android/ims/internal/IImsRcsFeature.aidl",
- "telephony/java/com/android/ims/internal/IImsService.aidl",
- "telephony/java/com/android/ims/internal/IImsServiceController.aidl",
- "telephony/java/com/android/ims/internal/IImsServiceFeatureCallback.aidl",
- "telephony/java/com/android/ims/internal/IImsStreamMediaSession.aidl",
- "telephony/java/com/android/ims/internal/IImsUt.aidl",
- "telephony/java/com/android/ims/internal/IImsUtListener.aidl",
- "telephony/java/com/android/ims/internal/IImsVideoCallCallback.aidl",
- "telephony/java/com/android/ims/internal/IImsVideoCallProvider.aidl",
- "telephony/java/com/android/ims/internal/uce/uceservice/IUceService.aidl",
- "telephony/java/com/android/ims/internal/uce/uceservice/IUceListener.aidl",
- "telephony/java/com/android/ims/internal/uce/options/IOptionsService.aidl",
- "telephony/java/com/android/ims/internal/uce/options/IOptionsListener.aidl",
- "telephony/java/com/android/ims/internal/uce/presence/IPresenceService.aidl",
- "telephony/java/com/android/ims/internal/uce/presence/IPresenceListener.aidl",
- "telephony/java/com/android/ims/ImsConfigListener.aidl",
- "telephony/java/com/android/internal/telephony/IApnSourceService.aidl",
- "telephony/java/com/android/internal/telephony/ICarrierConfigLoader.aidl",
- "telephony/java/com/android/internal/telephony/IIntegerConsumer.aidl",
- "telephony/java/com/android/internal/telephony/IMms.aidl",
- "telephony/java/com/android/internal/telephony/INumberVerificationCallback.aidl",
- "telephony/java/com/android/internal/telephony/IOnSubscriptionsChangedListener.aidl",
- "telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl",
- "telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl",
- "telephony/java/com/android/internal/telephony/ISetOpportunisticDataCallback.aidl",
- "telephony/java/com/android/internal/telephony/ISms.aidl",
- "telephony/java/com/android/internal/telephony/ISub.aidl",
- "telephony/java/com/android/internal/telephony/IOns.aidl",
- "telephony/java/com/android/internal/telephony/ITelephony.aidl",
- "telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl",
- "telephony/java/com/android/internal/telephony/IUpdateAvailableNetworksCallback.aidl",
- "telephony/java/com/android/internal/telephony/IWapPushManager.aidl",
- "telephony/java/com/android/internal/telephony/euicc/IAuthenticateServerCallback.aidl",
- "telephony/java/com/android/internal/telephony/euicc/ICancelSessionCallback.aidl",
- "telephony/java/com/android/internal/telephony/euicc/IDeleteProfileCallback.aidl",
- "telephony/java/com/android/internal/telephony/euicc/IDisableProfileCallback.aidl",
- "telephony/java/com/android/internal/telephony/euicc/IEuiccCardController.aidl",
- "telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl",
- "telephony/java/com/android/internal/telephony/euicc/IGetAllProfilesCallback.aidl",
- "telephony/java/com/android/internal/telephony/euicc/IGetDefaultSmdpAddressCallback.aidl",
- "telephony/java/com/android/internal/telephony/euicc/IGetEuiccChallengeCallback.aidl",
- "telephony/java/com/android/internal/telephony/euicc/IGetEuiccInfo1Callback.aidl",
- "telephony/java/com/android/internal/telephony/euicc/IGetEuiccInfo2Callback.aidl",
- "telephony/java/com/android/internal/telephony/euicc/IGetProfileCallback.aidl",
- "telephony/java/com/android/internal/telephony/euicc/IGetRulesAuthTableCallback.aidl",
- "telephony/java/com/android/internal/telephony/euicc/IGetSmdsAddressCallback.aidl",
- "telephony/java/com/android/internal/telephony/euicc/IListNotificationsCallback.aidl",
- "telephony/java/com/android/internal/telephony/euicc/ILoadBoundProfilePackageCallback.aidl",
- "telephony/java/com/android/internal/telephony/euicc/IPrepareDownloadCallback.aidl",
- "telephony/java/com/android/internal/telephony/euicc/IRemoveNotificationFromListCallback.aidl",
- "telephony/java/com/android/internal/telephony/euicc/IResetMemoryCallback.aidl",
- "telephony/java/com/android/internal/telephony/euicc/IRetrieveNotificationCallback.aidl",
- "telephony/java/com/android/internal/telephony/euicc/IRetrieveNotificationListCallback.aidl",
- "telephony/java/com/android/internal/telephony/euicc/ISetDefaultSmdpAddressCallback.aidl",
- "telephony/java/com/android/internal/telephony/euicc/ISetNicknameCallback.aidl",
- "telephony/java/com/android/internal/telephony/euicc/ISwitchToProfileCallback.aidl",
- "wifi/java/android/net/wifi/INetworkRequestMatchCallback.aidl",
- "wifi/java/android/net/wifi/INetworkRequestUserSelectionCallback.aidl",
- "wifi/java/android/net/wifi/ISoftApCallback.aidl",
- "wifi/java/android/net/wifi/ITrafficStateCallback.aidl",
- "wifi/java/android/net/wifi/IWifiManager.aidl",
- "wifi/java/android/net/wifi/IOnWifiUsabilityStatsListener.aidl",
- "wifi/java/android/net/wifi/aware/IWifiAwareDiscoverySessionCallback.aidl",
- "wifi/java/android/net/wifi/aware/IWifiAwareEventCallback.aidl",
- "wifi/java/android/net/wifi/aware/IWifiAwareMacAddressProvider.aidl",
- "wifi/java/android/net/wifi/aware/IWifiAwareManager.aidl",
- "wifi/java/android/net/wifi/p2p/IWifiP2pManager.aidl",
- "wifi/java/android/net/wifi/rtt/IRttCallback.aidl",
- "wifi/java/android/net/wifi/rtt/IWifiRttManager.aidl",
- "wifi/java/android/net/wifi/hotspot2/IProvisioningCallback.aidl",
- "wifi/java/android/net/wifi/IDppCallback.aidl",
- "wifi/java/android/net/wifi/IWifiScanner.aidl",
- "packages/services/PacProcessor/com/android/net/IProxyService.aidl",
- "packages/services/Proxy/com/android/net/IProxyCallback.aidl",
- "packages/services/Proxy/com/android/net/IProxyPortListener.aidl",
- "core/java/android/service/quicksettings/IQSService.aidl",
- "core/java/android/service/quicksettings/IQSTileService.aidl",
-
- ":libupdate_engine_aidl",
-
- ":storaged_aidl",
- ":vold_aidl",
- ":gsiservice_aidl",
- ":installd_aidl",
- ":dumpstate_aidl",
- ":incidentcompanion_aidl",
-
- "lowpan/java/android/net/lowpan/ILowpanEnergyScanCallback.aidl",
- "lowpan/java/android/net/lowpan/ILowpanNetScanCallback.aidl",
- "lowpan/java/android/net/lowpan/ILowpanInterfaceListener.aidl",
- "lowpan/java/android/net/lowpan/ILowpanInterface.aidl",
- "lowpan/java/android/net/lowpan/ILowpanManagerListener.aidl",
- "lowpan/java/android/net/lowpan/ILowpanManager.aidl",
-
- "core/java/android/app/admin/SecurityLogTags.logtags",
- "core/java/android/content/EventLogTags.logtags",
- "core/java/android/speech/tts/EventLogTags.logtags",
- "core/java/android/net/EventLogTags.logtags",
- "core/java/android/os/EventLogTags.logtags",
- "core/java/android/webkit/EventLogTags.logtags",
- "core/java/com/android/internal/app/EventLogTags.logtags",
- "core/java/com/android/internal/logging/EventLogTags.logtags",
- "core/java/com/android/server/DropboxLogTags.logtags",
- "core/java/org/chromium/arc/EventLogTags.logtags",
-
- ":framework-statslog-gen",
- ],
+ srcs: framework_srcs,
aidl: {
- include_dirs: [
- "system/update_engine/binder_bindings",
- "frameworks/native/aidl/binder",
- "frameworks/native/cmds/dumpstate/binder",
- "frameworks/native/libs/incidentcompanion/binder",
- "frameworks/av/camera/aidl",
- "frameworks/av/media/libaudioclient/aidl",
- "frameworks/native/aidl/gui",
- "frameworks/native/libs/incidentcompanion/binder",
- "system/core/gatekeeperd/binder",
- "system/core/storaged/binder",
- "system/vold/binder",
- "system/gsid/aidl",
- "system/bt/binder",
- "system/security/keystore/binder",
- ],
-
+ local_include_dirs: framework_aidl_local_include_dirs,
+ include_dirs: framework_aidl_external_include_dirs,
generate_get_transaction_name: true,
},
@@ -1828,6 +1223,7 @@
last_released: {
api_file: ":last-released-public-api",
removed_api_file: "api/removed.txt",
+ baseline_file: ":public-api-incompatibilities-with-last-released",
},
},
jdiff_enabled: true,
@@ -1853,6 +1249,7 @@
last_released: {
api_file: ":last-released-system-api",
removed_api_file: "api/system-removed.txt",
+ baseline_file: ":system-api-incompatibilities-with-last-released"
},
},
jdiff_enabled: true,
@@ -1907,7 +1304,9 @@
// annotations to private apis
aidl_mapping {
name: "framework-aidl-mappings",
- srcs: [":framework-defaults"],
+ srcs: framework_srcs,
+ local_include_dirs: framework_aidl_local_include_dirs,
+ include_dirs: framework_aidl_external_include_dirs,
output: "framework-aidl-mappings.txt",
}
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index 5ba563c..4e424c3 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -89,7 +89,7 @@
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.server.AppStateTracker;
-import com.android.server.DeviceIdleController;
+import com.android.server.DeviceIdleInternal;
import com.android.server.FgThread;
import com.android.server.LocalServices;
import com.android.server.job.JobSchedulerServiceDumpProto.ActiveJob;
@@ -207,7 +207,7 @@
PackageManagerInternal mLocalPM;
ActivityManagerInternal mActivityManagerInternal;
IBatteryStats mBatteryStats;
- DeviceIdleController.LocalService mLocalDeviceIdleController;
+ DeviceIdleInternal mLocalDeviceIdleController;
AppStateTracker mAppStateTracker;
final UsageStatsManagerInternal mUsageStats;
@@ -1399,8 +1399,8 @@
mReadyToRock = true;
mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService(
BatteryStats.SERVICE_NAME));
- mLocalDeviceIdleController
- = LocalServices.getService(DeviceIdleController.LocalService.class);
+ mLocalDeviceIdleController =
+ LocalServices.getService(DeviceIdleInternal.class);
// Create the "runners".
for (int i = 0; i < MAX_JOB_CONTEXTS_COUNT; i++) {
mActiveServices.add(
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java
index 0b67971..01f5fa6 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/DeviceIdleJobsController.java
@@ -34,7 +34,7 @@
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
-import com.android.server.DeviceIdleController;
+import com.android.server.DeviceIdleInternal;
import com.android.server.LocalServices;
import com.android.server.job.JobSchedulerService;
import com.android.server.job.StateControllerProto;
@@ -66,7 +66,7 @@
private final DeviceIdleUpdateFunctor mDeviceIdleUpdateFunctor;
private final DeviceIdleJobsDelayHandler mHandler;
private final PowerManager mPowerManager;
- private final DeviceIdleController.LocalService mLocalDeviceIdleController;
+ private final DeviceIdleInternal mLocalDeviceIdleController;
/**
* True when in device idle mode, so we don't want to schedule any jobs.
@@ -123,7 +123,7 @@
// Register for device idle mode changes
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mLocalDeviceIdleController =
- LocalServices.getService(DeviceIdleController.LocalService.class);
+ LocalServices.getService(DeviceIdleInternal.class);
mDeviceIdleWhitelistAppIds = mLocalDeviceIdleController.getPowerSaveWhitelistUserAppIds();
mPowerSaveTempWhitelistAppIds =
mLocalDeviceIdleController.getPowerSaveTempWhitelistAppIds();
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
index 3bb9929..d4d5871 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -18,6 +18,7 @@
tidy_checks: [
"modernize-*",
"-modernize-avoid-c-arrays",
+ "-modernize-use-trailing-return-type",
"android-*",
"misc-*",
"readability-*",
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 663cd55..96522f7 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -6875,6 +6875,9 @@
// Relative word (exclusive) index of the end of the smart selection.
optional int32 relative_suggested_word_end_index = 10;
+
+ // Name of source package.
+ optional string package_name = 11;
}
/**
@@ -6912,6 +6915,9 @@
// Time spent on generating links in ms.
optional int64 latency_millis = 10;
+
+ // Name of source package.
+ optional string package_name = 11;
}
/**
@@ -6943,6 +6949,9 @@
// The score of the first entity type.
optional float score = 8;
+
+ // Name of source package.
+ optional string package_name = 9;
}
/**
@@ -6971,6 +6980,9 @@
// Position of this action.
optional int32 action_index = 7;
+
+ // Name of source package.
+ optional string package_name = 8;
}
/**
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 553ef69..a6784780 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -191,6 +191,8 @@
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.net.InetAddress;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
@@ -6435,6 +6437,26 @@
NetworkSecurityConfigProvider.install(appContext);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+
+ if (isAppDebuggable) {
+ try {
+ // Load all the agents in the code_cache/startup_agents directory.
+ // We pass the absolute path to the data_dir as an argument.
+ Path startup_path = appContext.getCodeCacheDir().toPath().resolve("startup_agents");
+ if (Files.exists(startup_path)) {
+ for (Path p : Files.newDirectoryStream(startup_path)) {
+ handleAttachAgent(
+ p.toAbsolutePath().toString()
+ + "="
+ + appContext.getDataDir().toPath().toAbsolutePath().toString(),
+ data.info);
+ }
+ }
+ } catch (Exception e) {
+ // Ignored.
+ }
+ }
+
// Continue loading instrumentation.
if (ii != null) {
ApplicationInfo instrApp;
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index c58972e..635b9b0 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -112,7 +112,6 @@
import android.net.lowpan.LowpanManager;
import android.net.nsd.INsdManager;
import android.net.nsd.NsdManager;
-import android.net.wifi.IWifiManager;
import android.net.wifi.IWifiScanner;
import android.net.wifi.RttManager;
import android.net.wifi.WifiManager;
@@ -730,10 +729,8 @@
registerService(Context.WIFI_SERVICE, WifiManager.class,
new CachedServiceFetcher<WifiManager>() {
@Override
- public WifiManager createService(ContextImpl ctx) throws ServiceNotFoundException {
- IBinder b = ServiceManager.getServiceOrThrow(Context.WIFI_SERVICE);
- IWifiManager service = IWifiManager.Stub.asInterface(b);
- return new WifiManager(ctx.getOuterContext(), service,
+ public WifiManager createService(ContextImpl ctx) {
+ return new WifiManager(ctx.getOuterContext(),
ConnectivityThread.getInstanceLooper());
}});
@@ -1166,7 +1163,8 @@
@Override
public AppPredictionManager createService(ContextImpl ctx)
throws ServiceNotFoundException {
- return new AppPredictionManager(ctx);
+ IBinder b = ServiceManager.getService(Context.APP_PREDICTION_SERVICE);
+ return b == null ? null : new AppPredictionManager(ctx);
}
});
diff --git a/services/core/java/com/android/server/compat/IPlatformCompat.aidl b/core/java/android/compat/IPlatformCompat.aidl
similarity index 90%
rename from services/core/java/com/android/server/compat/IPlatformCompat.aidl
rename to core/java/android/compat/IPlatformCompat.aidl
index 8ab08f9..3d8a9d5 100644
--- a/services/core/java/com/android/server/compat/IPlatformCompat.aidl
+++ b/core/java/android/compat/IPlatformCompat.aidl
@@ -14,12 +14,16 @@
* limitations under the License.
*/
-package com.android.server.compat;
+package android.compat;
import android.content.pm.ApplicationInfo;
/**
- * System private API for talking with the PlatformCompat service.
+ * Platform private API for talking with the PlatformCompat service.
+ *
+ * <p> Should be used for gating and logging from non-app processes.
+ * For app processes please use android.compat.Compatibility API.
+ *
* {@hide}
*/
interface IPlatformCompat
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 73bc908..bb5ced56 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3735,6 +3735,14 @@
public static final String NETWORK_STACK_SERVICE = "network_stack";
/**
+ * Use with {@link android.os.ServiceManager.getService()} to retrieve a
+ * {@link android.net.WifiStackClient} IBinder for communicating with the network stack
+ * @hide
+ * @see android.net.WifiStackClient
+ */
+ public static final String WIFI_STACK_SERVICE = "wifi_stack";
+
+ /**
* Use with {@link #getSystemService(String)} to retrieve a
* {@link android.net.IpSecManager} for encrypting Sockets or Networks with
* IPSec.
@@ -4109,6 +4117,9 @@
/**
* Official published name of the app prediction service.
*
+ * <p><b>NOTE: </b> this service is optional; callers of
+ * {@code Context.getSystemServiceName(APP_PREDICTION_SERVICE)} should check for {@code null}.
+ *
* @hide
* @see #getSystemService(String)
*/
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 2f198ac..f50502e 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -675,12 +675,6 @@
"android.content.pm.extra.ENABLE_ROLLBACK_INSTALL_FLAGS";
/**
- * Extra field name for the set of installed users for a given rollback package.
- */
- public static final String EXTRA_ENABLE_ROLLBACK_INSTALLED_USERS =
- "android.content.pm.extra.ENABLE_ROLLBACK_INSTALLED_USERS";
-
- /**
* Extra field name for the user id an install is associated with when
* enabling rollback.
*/
diff --git a/core/java/android/content/rollback/PackageRollbackInfo.java b/core/java/android/content/rollback/PackageRollbackInfo.java
index 2014751..c89796d 100644
--- a/core/java/android/content/rollback/PackageRollbackInfo.java
+++ b/core/java/android/content/rollback/PackageRollbackInfo.java
@@ -76,10 +76,10 @@
private final boolean mIsApex;
/*
- * The list of users the package is installed for.
+ * The list of users for which snapshots have been saved.
*/
// NOTE: Not a part of the Parcelable representation of this object.
- private final IntArray mInstalledUsers;
+ private final IntArray mSnapshottedUsers;
/**
* A mapping between user and an inode of theirs CE data snapshot.
@@ -148,8 +148,8 @@
}
/** @hide */
- public IntArray getInstalledUsers() {
- return mInstalledUsers;
+ public IntArray getSnapshottedUsers() {
+ return mSnapshottedUsers;
}
/** @hide */
@@ -179,14 +179,14 @@
public PackageRollbackInfo(VersionedPackage packageRolledBackFrom,
VersionedPackage packageRolledBackTo,
@NonNull IntArray pendingBackups, @NonNull ArrayList<RestoreInfo> pendingRestores,
- boolean isApex, @NonNull IntArray installedUsers,
+ boolean isApex, @NonNull IntArray snapshottedUsers,
@NonNull SparseLongArray ceSnapshotInodes) {
this.mVersionRolledBackFrom = packageRolledBackFrom;
this.mVersionRolledBackTo = packageRolledBackTo;
this.mPendingBackups = pendingBackups;
this.mPendingRestores = pendingRestores;
this.mIsApex = isApex;
- this.mInstalledUsers = installedUsers;
+ this.mSnapshottedUsers = snapshottedUsers;
this.mCeSnapshotInodes = ceSnapshotInodes;
}
@@ -196,7 +196,7 @@
this.mIsApex = in.readBoolean();
this.mPendingRestores = null;
this.mPendingBackups = null;
- this.mInstalledUsers = null;
+ this.mSnapshottedUsers = null;
this.mCeSnapshotInodes = null;
}
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index 099ae29..e78fb7f 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -339,6 +339,8 @@
* for {@link #TYPE_STEP_COUNTER} instead. It is defined as a
* {@link Sensor#REPORTING_MODE_SPECIAL_TRIGGER} sensor.
* <p>
+ * This sensor requires permission {@code android.permission.ACTIVITY_RECOGNITION}.
+ * <p>
* See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details.
*/
public static final int TYPE_STEP_DETECTOR = 18;
@@ -384,8 +386,6 @@
* gyroscope. This sensor uses lower power than the other rotation vectors, because it doesn't
* use the gyroscope. However, it is more noisy and will work best outdoors.
* <p>
- * This sensor requires permission {@code android.permission.ACTIVITY_RECOGNITION}.
- * <p>
* See {@link android.hardware.SensorEvent#values SensorEvent.values} for more details.
*/
public static final int TYPE_GEOMAGNETIC_ROTATION_VECTOR = 20;
diff --git a/core/java/android/net/util/MultinetworkPolicyTracker.java b/core/java/android/net/util/MultinetworkPolicyTracker.java
index 30c5cd9..f7e494d 100644
--- a/core/java/android/net/util/MultinetworkPolicyTracker.java
+++ b/core/java/android/net/util/MultinetworkPolicyTracker.java
@@ -16,29 +16,32 @@
package android.net.util;
+import static android.provider.Settings.Global.NETWORK_AVOID_BAD_WIFI;
+import static android.provider.Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
+
+import android.annotation.NonNull;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.res.Resources;
import android.database.ContentObserver;
-import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.Handler;
-import android.os.Message;
import android.os.UserHandle;
import android.provider.Settings;
+import android.telephony.PhoneStateListener;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
import android.util.Slog;
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.util.Arrays;
import java.util.List;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.R;
-
-import static android.provider.Settings.Global.NETWORK_AVOID_BAD_WIFI;
-import static android.provider.Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
-
/**
* A class to encapsulate management of the "Smart Networking" capability of
* avoiding bad Wi-Fi when, for example upstream connectivity is lost or
@@ -69,6 +72,7 @@
private volatile boolean mAvoidBadWifi = true;
private volatile int mMeteredMultipathPreference;
+ private int mActiveSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
public MultinetworkPolicyTracker(Context ctx, Handler handler) {
this(ctx, handler, null);
@@ -95,6 +99,14 @@
}
};
+ TelephonyManager.from(ctx).listen(new PhoneStateListener() {
+ @Override
+ public void onActiveDataSubscriptionIdChanged(int subId) {
+ mActiveSubId = subId;
+ reevaluate();
+ }
+ }, PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
+
updateAvoidBadWifi();
updateMeteredMultipathPreference();
}
@@ -131,7 +143,12 @@
* Whether the device or carrier configuration disables avoiding bad wifi by default.
*/
public boolean configRestrictsAvoidBadWifi() {
- return (mContext.getResources().getInteger(R.integer.config_networkAvoidBadWifi) == 0);
+ return (getResourcesForActiveSubId().getInteger(R.integer.config_networkAvoidBadWifi) == 0);
+ }
+
+ @NonNull
+ private Resources getResourcesForActiveSubId() {
+ return SubscriptionManager.getResourcesForSubId(mContext, mActiveSubId);
}
/**
diff --git a/core/java/android/service/gatekeeper/GateKeeperResponse.java b/core/java/android/service/gatekeeper/GateKeeperResponse.java
index 66fee1e..7ed733c 100644
--- a/core/java/android/service/gatekeeper/GateKeeperResponse.java
+++ b/core/java/android/service/gatekeeper/GateKeeperResponse.java
@@ -31,6 +31,8 @@
public static final int RESPONSE_OK = 0;
public static final int RESPONSE_RETRY = 1;
+ public static final GateKeeperResponse ERROR = createGenericResponse(RESPONSE_ERROR);
+
private final int mResponseCode;
private int mTimeout;
diff --git a/core/java/com/android/internal/widget/ResolverDrawerLayout.java b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
index c73de8f..1bb2ba2 100644
--- a/core/java/com/android/internal/widget/ResolverDrawerLayout.java
+++ b/core/java/com/android/internal/widget/ResolverDrawerLayout.java
@@ -775,17 +775,54 @@
return false;
}
+ private boolean performAccessibilityActionCommon(int action) {
+ switch (action) {
+ case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD:
+ case AccessibilityNodeInfo.ACTION_EXPAND:
+ case R.id.accessibilityActionScrollDown:
+ if (mCollapseOffset != 0) {
+ smoothScrollTo(0, 0);
+ return true;
+ }
+ break;
+ case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD:
+ case R.id.accessibilityActionScrollUp:
+ if (mCollapseOffset < mCollapsibleHeight) {
+ smoothScrollTo(mCollapsibleHeight, 0);
+ return true;
+ } else if ((mCollapseOffset < mCollapsibleHeight + mUncollapsibleHeight)
+ && isDismissable()) {
+ smoothScrollTo(mCollapsibleHeight + mUncollapsibleHeight, 0);
+ mDismissOnScrollerFinished = true;
+ return true;
+ }
+ break;
+ case AccessibilityNodeInfo.ACTION_COLLAPSE:
+ if (mCollapseOffset < mCollapsibleHeight) {
+ smoothScrollTo(mCollapsibleHeight, 0);
+ return true;
+ }
+ break;
+ case AccessibilityNodeInfo.ACTION_DISMISS:
+ if ((mCollapseOffset < mCollapsibleHeight + mUncollapsibleHeight)
+ && isDismissable()) {
+ smoothScrollTo(mCollapsibleHeight + mUncollapsibleHeight, 0);
+ mDismissOnScrollerFinished = true;
+ return true;
+ }
+ break;
+ }
+
+ return false;
+ }
+
@Override
public boolean onNestedPrePerformAccessibilityAction(View target, int action, Bundle args) {
if (super.onNestedPrePerformAccessibilityAction(target, action, args)) {
return true;
}
- if (action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD && mCollapseOffset != 0) {
- smoothScrollTo(0, 0);
- return true;
- }
- return false;
+ return performAccessibilityActionCommon(action);
}
@Override
@@ -802,9 +839,23 @@
if (isEnabled()) {
if (mCollapseOffset != 0) {
- info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
+ info.addAction(AccessibilityAction.ACTION_SCROLL_FORWARD);
+ info.addAction(AccessibilityAction.ACTION_EXPAND);
+ info.addAction(AccessibilityAction.ACTION_SCROLL_DOWN);
info.setScrollable(true);
}
+ if ((mCollapseOffset < mCollapsibleHeight + mUncollapsibleHeight)
+ && ((mCollapseOffset < mCollapsibleHeight) || isDismissable())) {
+ info.addAction(AccessibilityAction.ACTION_SCROLL_BACKWARD);
+ info.addAction(AccessibilityAction.ACTION_SCROLL_UP);
+ info.setScrollable(true);
+ }
+ if (mCollapseOffset < mCollapsibleHeight) {
+ info.addAction(AccessibilityAction.ACTION_COLLAPSE);
+ }
+ if (mCollapseOffset < mCollapsibleHeight + mUncollapsibleHeight && isDismissable()) {
+ info.addAction(AccessibilityAction.ACTION_DISMISS);
+ }
}
// This view should never get accessibility focus, but it's interactive
@@ -823,12 +874,7 @@
return true;
}
- if (action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD && mCollapseOffset != 0) {
- smoothScrollTo(0, 0);
- return true;
- }
-
- return false;
+ return performAccessibilityActionCommon(action);
}
@Override
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 78e8e13..18a1b43 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -237,10 +237,6 @@
}
void imageInfo(JNIEnv* env, jobject bitmap, AndroidBitmapInfo* info) {
- SkASSERT(info);
- SkASSERT(env);
- SkASSERT(bitmap);
- SkASSERT(env->IsInstanceOf(bitmap, gBitmap_class));
jlong bitmapHandle = env->GetLongField(bitmap, gBitmap_nativePtr);
LocalScopedBitmap localBitmap(bitmapHandle);
@@ -262,6 +258,9 @@
case kAlpha_8_SkColorType:
info->format = ANDROID_BITMAP_FORMAT_A_8;
break;
+ case kRGBA_F16_SkColorType:
+ info->format = ANDROID_BITMAP_FORMAT_RGBA_F16;
+ break;
default:
info->format = ANDROID_BITMAP_FORMAT_NONE;
break;
diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto
index e43b6a0..e62af74 100644
--- a/core/proto/android/providers/settings.proto
+++ b/core/proto/android/providers/settings.proto
@@ -20,6 +20,7 @@
option java_multiple_files = true;
option java_outer_classname = "SettingsServiceProto";
+import "frameworks/base/core/proto/android/providers/settings/config.proto";
import "frameworks/base/core/proto/android/providers/settings/global.proto";
import "frameworks/base/core/proto/android/providers/settings/secure.proto";
import "frameworks/base/core/proto/android/providers/settings/system.proto";
@@ -33,6 +34,9 @@
// Global settings
optional GlobalSettingsProto global_settings = 2;
+
+ // Config settings
+ optional ConfigSettingsProto config_settings = 3;
}
message UserSettingsProto {
diff --git a/core/proto/android/providers/settings/config.proto b/core/proto/android/providers/settings/config.proto
new file mode 100644
index 0000000..cc24196
--- /dev/null
+++ b/core/proto/android/providers/settings/config.proto
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+syntax = "proto2";
+package android.providers.settings;
+
+option java_multiple_files = true;
+
+import "frameworks/base/core/proto/android/providers/settings/common.proto";
+import "frameworks/base/core/proto/android/privacy.proto";
+
+message ConfigSettingsProto {
+ option (android.msg_privacy).dest = DEST_EXPLICIT;
+
+ repeated SettingsOperationProto historical_operations = 1;
+ repeated NamespaceProto extra_namespaces = 2;
+ repeated SettingProto activity_manager_native_boot_settings = 3;
+ repeated SettingProto activity_manager_settings = 4;
+ repeated SettingProto app_compat_settings = 5;
+ repeated SettingProto autofill_settings = 6;
+ repeated SettingProto connectivity_settings = 7;
+ repeated SettingProto content_capture_settings = 8;
+ repeated SettingProto dex_boot_settings = 9;
+ repeated SettingProto game_driver_settings = 10;
+ repeated SettingProto input_native_boot_settings = 11;
+ repeated SettingProto netd_native_settings = 12;
+ repeated SettingProto privacy_settings = 13;
+ repeated SettingProto rollback_boot_settings = 14;
+ repeated SettingProto rollback_settings = 15;
+ repeated SettingProto runtime_native_boot_settings = 16;
+ repeated SettingProto runtime_native_settings = 17;
+ repeated SettingProto runtime_settings = 18;
+ repeated SettingProto storage_settings = 19;
+ repeated SettingProto systemui_settings = 20;
+ repeated SettingProto telephony_settings = 21;
+ repeated SettingProto textclassifier_settings = 22;
+
+ message NamespaceProto {
+ optional string namespace = 1;
+ repeated SettingProto settings = 2;
+ }
+}
\ No newline at end of file
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 4025a08..4187c80 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -24,6 +24,7 @@
<permission name="android.permission.PROVIDE_RESOLVER_RANKER_SERVICE" />
<permission name="android.permission.MONITOR_DEFAULT_SMS_PACKAGE" />
<permission name="android.permission.REQUEST_NOTIFICATION_ASSISTANT_SERVICE" />
+ <permission name="android.permission.INTERACT_ACROSS_USERS" />
</privapp-permissions>
<privapp-permissions package="com.android.apps.tag">
@@ -350,4 +351,19 @@
<permission name="android.permission.MANAGE_DYNAMIC_SYSTEM"/>
</privapp-permissions>
+ <privapp-permissions package="com.android.server.wifistack">
+ <permission name="android.permission.CHANGE_CONFIGURATION"/>
+ <permission name="android.permission.CONNECTIVITY_INTERNAL"/>
+ <permission name="android.permission.DUMP"/>
+ <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+ <permission name="android.permission.LOCAL_MAC_ADDRESS"/>
+ <permission name="android.permission.MANAGE_USERS"/>
+ <permission name="android.permission.PACKAGE_USAGE_STATS"/>
+ <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/>
+ <permission name="android.permission.REQUEST_NETWORK_SCORES"/>
+ <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
+ <permission name="android.permission.UPDATE_DEVICE_STATS"/>
+ <permission name="android.permission.UPDATE_APP_OPS_STATS"/>
+ <permission name="android.permission.LOCATION_HARDWARE"/>
+ </privapp-permissions>
</permissions>
diff --git a/libs/hostgraphics/Android.bp b/libs/hostgraphics/Android.bp
index aedb752..e713b98 100644
--- a/libs/hostgraphics/Android.bp
+++ b/libs/hostgraphics/Android.bp
@@ -1,8 +1,15 @@
cc_library_host_static {
name: "libhostgraphics",
+ cflags: [
+ "-Wno-unused-parameter",
+ ],
+
srcs: [
":libui_host_common",
+ "Fence.cpp",
+ "HostBufferQueue.cpp",
+ "PublicFormat.cpp",
],
include_dirs: [
diff --git a/libs/hostgraphics/Fence.cpp b/libs/hostgraphics/Fence.cpp
new file mode 100644
index 0000000..9e54816
--- /dev/null
+++ b/libs/hostgraphics/Fence.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <ui/Fence.h>
+
+namespace android {
+
+const sp<Fence> Fence::NO_FENCE = sp<Fence>(new Fence);
+
+} // namespace android
\ No newline at end of file
diff --git a/libs/hostgraphics/HostBufferQueue.cpp b/libs/hostgraphics/HostBufferQueue.cpp
new file mode 100644
index 0000000..ec30437
--- /dev/null
+++ b/libs/hostgraphics/HostBufferQueue.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gui/BufferQueue.h>
+
+namespace android {
+
+class HostBufferQueue : public IGraphicBufferProducer, public IGraphicBufferConsumer {
+public:
+ HostBufferQueue() : mWidth(0), mHeight(0) { }
+
+ virtual status_t setConsumerIsProtected(bool isProtected) { return OK; }
+
+ virtual status_t detachBuffer(int slot) { return OK; }
+
+ virtual status_t getReleasedBuffers(uint64_t* slotMask) { return OK; }
+
+ virtual status_t setDefaultBufferSize(uint32_t w, uint32_t h) {
+ mWidth = w;
+ mHeight = h;
+ mBuffer = sp<GraphicBuffer>(new GraphicBuffer(mWidth, mHeight));
+ return OK;
+ }
+
+ virtual status_t setDefaultBufferFormat(PixelFormat defaultFormat) { return OK; }
+
+ virtual status_t setDefaultBufferDataSpace(android_dataspace defaultDataSpace) { return OK; }
+
+ virtual status_t discardFreeBuffers() { return OK; }
+
+ virtual status_t acquireBuffer(BufferItem* buffer, nsecs_t presentWhen,
+ uint64_t maxFrameNumber = 0) {
+ buffer->mGraphicBuffer = mBuffer;
+ buffer->mSlot = 0;
+ return OK;
+ }
+
+ virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers) { return OK; }
+
+ virtual status_t setConsumerUsageBits(uint64_t usage) { return OK; }
+private:
+ sp<GraphicBuffer> mBuffer;
+ uint32_t mWidth;
+ uint32_t mHeight;
+};
+
+void BufferQueue::createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
+ sp<IGraphicBufferConsumer>* outConsumer) {
+
+ sp<HostBufferQueue> obj(new HostBufferQueue());
+
+ *outProducer = obj;
+ *outConsumer = obj;
+}
+
+} // namespace android
diff --git a/libs/hostgraphics/PublicFormat.cpp b/libs/hostgraphics/PublicFormat.cpp
new file mode 100644
index 0000000..af6d273
--- /dev/null
+++ b/libs/hostgraphics/PublicFormat.cpp
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <ui/PublicFormat.h>
+
+namespace android {
+
+android_dataspace mapPublicFormatToHalDataspace(PublicFormat f) {
+ return static_cast<android_dataspace>(0);
+}
+
+int mapPublicFormatToHalFormat(PublicFormat f) {
+ return static_cast<int>(f);
+}
+
+PublicFormat mapHalFormatDataspaceToPublicFormat(int format, android_dataspace dataSpace) {
+ return static_cast<PublicFormat>(format);
+}
+
+} // namespace android
\ No newline at end of file
diff --git a/libs/hostgraphics/gui/BufferItem.h b/libs/hostgraphics/gui/BufferItem.h
new file mode 100644
index 0000000..01409e1
--- /dev/null
+++ b/libs/hostgraphics/gui/BufferItem.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_GUI_BUFFERITEM_H
+#define ANDROID_GUI_BUFFERITEM_H
+
+#include <ui/Fence.h>
+#include <ui/Rect.h>
+
+#include <system/graphics.h>
+
+#include <utils/StrongPointer.h>
+
+namespace android {
+
+class Fence;
+class GraphicBuffer;
+
+// The only thing we need here for layoutlib is mGraphicBuffer. The rest of the fields are added
+// just to satisfy the calls from the android_media_ImageReader.h
+
+class BufferItem {
+public:
+ enum { INVALID_BUFFER_SLOT = -1 };
+
+ BufferItem() : mGraphicBuffer(nullptr), mFence(Fence::NO_FENCE) {}
+ ~BufferItem() {}
+
+ sp<GraphicBuffer> mGraphicBuffer;
+
+ sp<Fence> mFence;
+
+ Rect mCrop;
+
+ uint32_t mTransform;
+
+ uint32_t mScalingMode;
+
+ int64_t mTimestamp;
+
+ android_dataspace mDataSpace;
+
+ uint64_t mFrameNumber;
+
+ int mSlot;
+
+ bool mTransformToDisplayInverse;
+};
+
+}
+
+#endif // ANDROID_GUI_BUFFERITEM_H
diff --git a/libs/hostgraphics/gui/BufferItemConsumer.h b/libs/hostgraphics/gui/BufferItemConsumer.h
new file mode 100644
index 0000000..707b313
--- /dev/null
+++ b/libs/hostgraphics/gui/BufferItemConsumer.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_GUI_BUFFERITEMCONSUMER_H
+#define ANDROID_GUI_BUFFERITEMCONSUMER_H
+
+#include <utils/RefBase.h>
+
+#include <gui/ConsumerBase.h>
+#include <gui/IGraphicBufferConsumer.h>
+
+namespace android {
+
+class BufferItemConsumer : public ConsumerBase {
+public:
+ BufferItemConsumer(
+ const sp<IGraphicBufferConsumer>& consumer,
+ uint64_t consumerUsage,
+ int bufferCount,
+ bool controlledByApp) : mConsumer(consumer) {
+ }
+
+ status_t acquireBuffer(BufferItem *item, nsecs_t presentWhen, bool waitForFence = true) {
+ return mConsumer->acquireBuffer(item, presentWhen, 0);
+ }
+
+ status_t releaseBuffer(
+ const BufferItem &item, const sp<Fence>& releaseFence = Fence::NO_FENCE) { return OK; }
+
+ void setName(const String8& name) { }
+
+ void setFrameAvailableListener(const wp<FrameAvailableListener>& listener) { }
+
+ status_t setDefaultBufferSize(uint32_t width, uint32_t height) {
+ return mConsumer->setDefaultBufferSize(width, height);
+ }
+
+ status_t setDefaultBufferFormat(PixelFormat defaultFormat) {
+ return mConsumer->setDefaultBufferFormat(defaultFormat);
+ }
+
+ status_t setDefaultBufferDataSpace(android_dataspace defaultDataSpace) {
+ return mConsumer->setDefaultBufferDataSpace(defaultDataSpace);
+ }
+
+ void abandon() { }
+
+ status_t detachBuffer(int slot) { return OK; }
+
+ status_t discardFreeBuffers() { return OK; }
+
+ void freeBufferLocked(int slotIndex) { }
+
+ status_t addReleaseFenceLocked(
+ int slot, const sp<GraphicBuffer> graphicBuffer, const sp<Fence>& fence) { return OK; }
+private:
+ sp<IGraphicBufferConsumer> mConsumer;
+};
+
+} // namespace android
+
+#endif // ANDROID_GUI_BUFFERITEMCONSUMER_H
diff --git a/libs/hostgraphics/gui/BufferQueue.h b/libs/hostgraphics/gui/BufferQueue.h
new file mode 100644
index 0000000..aa3e726
--- /dev/null
+++ b/libs/hostgraphics/gui/BufferQueue.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_GUI_BUFFERQUEUE_H
+#define ANDROID_GUI_BUFFERQUEUE_H
+
+#include <gui/BufferItem.h>
+#include <gui/IGraphicBufferConsumer.h>
+#include <gui/IGraphicBufferProducer.h>
+
+namespace android {
+
+class BufferQueue {
+public:
+ enum { INVALID_BUFFER_SLOT = BufferItem::INVALID_BUFFER_SLOT };
+ enum { NO_BUFFER_AVAILABLE = IGraphicBufferConsumer::NO_BUFFER_AVAILABLE };
+
+ static void createBufferQueue(sp<IGraphicBufferProducer>* outProducer,
+ sp<IGraphicBufferConsumer>* outConsumer);
+};
+
+} // namespace android
+
+#endif // ANDROID_GUI_BUFFERQUEUE_H
diff --git a/libs/hostgraphics/gui/ConsumerBase.h b/libs/hostgraphics/gui/ConsumerBase.h
new file mode 100644
index 0000000..9002953
--- /dev/null
+++ b/libs/hostgraphics/gui/ConsumerBase.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_GUI_CONSUMERBASE_H
+#define ANDROID_GUI_CONSUMERBASE_H
+
+#include <gui/BufferItem.h>
+
+#include <utils/RefBase.h>
+
+namespace android {
+
+class ConsumerBase : public virtual RefBase {
+public:
+ struct FrameAvailableListener : public virtual RefBase {
+ // See IConsumerListener::onFrame{Available,Replaced}
+ virtual void onFrameAvailable(const BufferItem& item) = 0;
+ virtual void onFrameReplaced(const BufferItem& /* item */) {}
+ };
+};
+
+} // namespace android
+
+#endif // ANDROID_GUI_CONSUMERBASE_H
\ No newline at end of file
diff --git a/libs/hostgraphics/gui/IGraphicBufferConsumer.h b/libs/hostgraphics/gui/IGraphicBufferConsumer.h
new file mode 100644
index 0000000..9eb67b2
--- /dev/null
+++ b/libs/hostgraphics/gui/IGraphicBufferConsumer.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <utils/RefBase.h>
+
+#include <ui/PixelFormat.h>
+
+#include <utils/Errors.h>
+
+namespace android {
+
+class BufferItem;
+class Fence;
+class GraphicBuffer;
+
+class IGraphicBufferConsumer : virtual public RefBase {
+public:
+ enum {
+ // Returned by releaseBuffer, after which the consumer must free any references to the
+ // just-released buffer that it might have.
+ STALE_BUFFER_SLOT = 1,
+ // Returned by dequeueBuffer if there are no pending buffers available.
+ NO_BUFFER_AVAILABLE,
+ // Returned by dequeueBuffer if it's too early for the buffer to be acquired.
+ PRESENT_LATER,
+ };
+
+ virtual status_t acquireBuffer(BufferItem* buffer, nsecs_t presentWhen,
+ uint64_t maxFrameNumber = 0) = 0;
+
+ virtual status_t detachBuffer(int slot) = 0;
+
+ virtual status_t getReleasedBuffers(uint64_t* slotMask) = 0;
+
+ virtual status_t setDefaultBufferSize(uint32_t w, uint32_t h) = 0;
+
+ virtual status_t setMaxAcquiredBufferCount(int maxAcquiredBuffers) = 0;
+
+ virtual status_t setDefaultBufferFormat(PixelFormat defaultFormat) = 0;
+
+ virtual status_t setDefaultBufferDataSpace(android_dataspace defaultDataSpace) = 0;
+
+ virtual status_t setConsumerUsageBits(uint64_t usage) = 0;
+
+ virtual status_t setConsumerIsProtected(bool isProtected) = 0;
+
+ virtual status_t discardFreeBuffers() = 0;
+};
+
+} // namespace android
\ No newline at end of file
diff --git a/libs/hostgraphics/gui/IGraphicBufferProducer.h b/libs/hostgraphics/gui/IGraphicBufferProducer.h
index 0042213..a1efd0b 100644
--- a/libs/hostgraphics/gui/IGraphicBufferProducer.h
+++ b/libs/hostgraphics/gui/IGraphicBufferProducer.h
@@ -19,6 +19,8 @@
#include <utils/RefBase.h>
+#include <ui/GraphicBuffer.h>
+
namespace android {
class IGraphicBufferProducer : virtual public RefBase {
diff --git a/libs/hostgraphics/ui/Fence.h b/libs/hostgraphics/ui/Fence.h
new file mode 100644
index 0000000..04d535c
--- /dev/null
+++ b/libs/hostgraphics/ui/Fence.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_FENCE_H
+#define ANDROID_FENCE_H
+
+#include <utils/String8.h>
+#include <utils/RefBase.h>
+
+typedef int64_t nsecs_t;
+
+namespace android {
+
+class Fence : public LightRefBase<Fence> {
+public:
+ Fence() { }
+ Fence(int) { }
+ static const sp<Fence> NO_FENCE;
+ static constexpr nsecs_t SIGNAL_TIME_PENDING = INT64_MAX;
+ static constexpr nsecs_t SIGNAL_TIME_INVALID = -1;
+ static sp<Fence> merge(const char* name, const sp<Fence>& f1, const sp<Fence>& f2) {
+ return NO_FENCE;
+ }
+
+ static sp<Fence> merge(const String8& name, const sp<Fence>& f1, const sp<Fence>& f2) {
+ return NO_FENCE;
+ }
+
+ enum class Status {
+ Invalid, // Fence is invalid
+ Unsignaled, // Fence is valid but has not yet signaled
+ Signaled, // Fence is valid and has signaled
+ };
+
+ status_t wait(int timeout) { return OK; }
+
+ status_t waitForever(const char* logname) { return OK; }
+
+ int dup() const { return 0; }
+
+ inline Status getStatus() {
+ // The sync_wait call underlying wait() has been measured to be
+ // significantly faster than the sync_fence_info call underlying
+ // getSignalTime(), which might otherwise appear to be the more obvious
+ // way to check whether a fence has signaled.
+ switch (wait(0)) {
+ case NO_ERROR:
+ return Status::Signaled;
+ case -ETIME:
+ return Status::Unsignaled;
+ default:
+ return Status::Invalid;
+ }
+ }
+};
+
+} // namespace android
+
+#endif // ANDROID_FENCE_H
diff --git a/libs/hostgraphics/ui/GraphicBuffer.h b/libs/hostgraphics/ui/GraphicBuffer.h
new file mode 100644
index 0000000..ac88e44
--- /dev/null
+++ b/libs/hostgraphics/ui/GraphicBuffer.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_GRAPHIC_BUFFER_H
+#define ANDROID_GRAPHIC_BUFFER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <vector>
+
+#include <ui/PixelFormat.h>
+#include <ui/Rect.h>
+
+#include <utils/RefBase.h>
+
+namespace android {
+
+class GraphicBuffer : virtual public RefBase {
+public:
+ GraphicBuffer(uint32_t w, uint32_t h):width(w),height(h) {
+ data.resize(w*h);
+ }
+ uint32_t getWidth() const { return static_cast<uint32_t>(width); }
+ uint32_t getHeight() const { return static_cast<uint32_t>(height); }
+ uint32_t getStride() const { return static_cast<uint32_t>(width); }
+ uint64_t getUsage() const { return 0; }
+ PixelFormat getPixelFormat() const { return PIXEL_FORMAT_RGBA_8888; }
+ //uint32_t getLayerCount() const { return static_cast<uint32_t>(layerCount); }
+ Rect getBounds() const { return Rect(width, height); }
+
+ status_t lockAsyncYCbCr(uint32_t inUsage, const Rect& rect,
+ android_ycbcr *ycbcr, int fenceFd) { return OK; }
+
+ status_t lockAsync(uint32_t inUsage, const Rect& rect, void** vaddr, int fenceFd,
+ int32_t* outBytesPerPixel = nullptr, int32_t* outBytesPerStride = nullptr) {
+ *vaddr = data.data();
+ return OK;
+ }
+
+ status_t unlockAsync(int *fenceFd) { return OK; }
+
+private:
+ uint32_t width;
+ uint32_t height;
+ std::vector<uint32_t> data;
+};
+
+}; // namespace android
+
+#endif // ANDROID_GRAPHIC_BUFFER_H
diff --git a/location/lib/Android.bp b/location/lib/Android.bp
index ab01ddb..db63889 100644
--- a/location/lib/Android.bp
+++ b/location/lib/Android.bp
@@ -22,6 +22,8 @@
],
api_packages: ["com.android.location.provider"],
srcs_lib: "framework-minus-apex",
- srcs_lib_whitelist_dirs: ["location/java"],
- srcs_lib_whitelist_pkgs: ["com.android.internal.location"],
+ // TODO(b/70046217): remove core/java and android below. It was added to provide definitions for
+ // types like android.os.Bundle
+ srcs_lib_whitelist_dirs: ["core/java", "location/java"],
+ srcs_lib_whitelist_pkgs: ["android", "com.android.internal.location"],
}
diff --git a/media/java/android/media/Metadata.java b/media/java/android/media/Metadata.java
index 792a2ba..be0d966 100644
--- a/media/java/android/media/Metadata.java
+++ b/media/java/android/media/Metadata.java
@@ -272,6 +272,15 @@
@UnsupportedAppUsage
public Metadata() { }
+ // Have to declare protected for finalize() since it is protected
+ // in the base class Object.
+ @Override
+ protected void finalize() throws Throwable {
+ if (mParcel != null) {
+ mParcel.recycle();
+ }
+ }
+
/**
* Go over all the records, collecting metadata keys and records'
* type field offset in the Parcel. These are stored in
@@ -418,6 +427,10 @@
parcel.setDataPosition(pin);
return false;
}
+
+ if (mParcel != null) {
+ mParcel.recycle();
+ }
mParcel = parcel;
return true;
}
diff --git a/packages/CarSystemUI/AndroidManifest.xml b/packages/CarSystemUI/AndroidManifest.xml
index 195d4fe..261b9f5 100644
--- a/packages/CarSystemUI/AndroidManifest.xml
+++ b/packages/CarSystemUI/AndroidManifest.xml
@@ -21,4 +21,8 @@
coreApp="true">
<!-- This permission is required to monitor car power state. -->
<uses-permission android:name="android.car.permission.CAR_POWER" />
+ <!-- This permission is required to get the trusted device list of a user. -->
+ <uses-permission android:name="android.car.permission.CAR_ENROLL_TRUST"/>
+ <!-- This permission is required to get bluetooth broadcast. -->
+ <uses-permission android:name="android.permission.BLUETOOTH" />
</manifest>
diff --git a/packages/CarSystemUI/res/drawable/unlock_dialog_background.xml b/packages/CarSystemUI/res/drawable/unlock_dialog_background.xml
new file mode 100644
index 0000000..bec6ba7
--- /dev/null
+++ b/packages/CarSystemUI/res/drawable/unlock_dialog_background.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@color/unlock_dialog_background_color"/>
+ <padding
+ android:bottom="@*android:dimen/car_padding_2"
+ android:left="@*android:dimen/car_padding_2"
+ android:right="@*android:dimen/car_padding_2"
+ android:top="@*android:dimen/car_padding_2"/>
+ <corners
+ android:radius="@dimen/unlock_dialog_radius"/>
+</shape>
\ No newline at end of file
diff --git a/packages/CarSystemUI/res/layout/trust_agent_unlock_dialog.xml b/packages/CarSystemUI/res/layout/trust_agent_unlock_dialog.xml
new file mode 100644
index 0000000..2d9901c
--- /dev/null
+++ b/packages/CarSystemUI/res/layout/trust_agent_unlock_dialog.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2019 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center">
+
+ <LinearLayout
+ android:layout_width="@dimen/unlock_dialog_width"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:layout_gravity="center"
+ android:orientation="vertical"
+ android:background="@drawable/unlock_dialog_background"
+ android:padding="@*android:dimen/car_padding_2">
+ <FrameLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+ <ProgressBar
+ android:layout_gravity="center"
+ android:layout_width="@dimen/unlock_dialog_progress_bar_size"
+ android:layout_height="@dimen/unlock_dialog_progress_bar_size" />
+ <ImageView
+ android:id="@+id/avatar"
+ android:layout_gravity="center"
+ android:layout_width="@dimen/unlock_dialog_avatar_size"
+ android:layout_height="@dimen/unlock_dialog_avatar_size"
+ android:scaleType="fitCenter"/>
+ </FrameLayout>
+
+ <TextView
+ android:id="@+id/user_name"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/unlock_dialog_default_user_name"
+ android:textSize="@*android:dimen/car_body1_size"
+ android:textColor="@android:color/white"/>
+
+ <TextView
+ android:id="@+id/unlocking_text"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:layout_marginTop="@*android:dimen/car_padding_1"
+ android:text="@string/unlock_dialog_message_default"
+ android:textSize="@*android:dimen/car_body4_size"
+ android:textColor="@color/unlock_dialog_message_text_default"/>
+
+ <Button
+ android:id="@+id/enter_pin_button"
+ android:layout_marginTop="@*android:dimen/car_padding_1"
+ android:layout_height="wrap_content"
+ android:layout_width="wrap_content"
+ android:text="@string/unlock_dialog_button_text_pin"
+ style="@style/UnlockDialogButton"/>
+ </LinearLayout>
+</FrameLayout>
\ No newline at end of file
diff --git a/packages/CarSystemUI/res/values/colors_car.xml b/packages/CarSystemUI/res/values/colors_car.xml
index 69ab3f3..0a3f7aa 100644
--- a/packages/CarSystemUI/res/values/colors_car.xml
+++ b/packages/CarSystemUI/res/values/colors_car.xml
@@ -26,4 +26,9 @@
<color name="car_user_switcher_add_user_background_color">@*android:color/car_dark_blue_grey_600</color>
<color name="car_user_switcher_add_user_add_sign_color">@*android:color/car_body1_light</color>
+ <!-- colors for unlock dialog -->
+ <color name="unlock_dialog_background_color">#ff282a2d</color>
+ <color name="unlock_dialog_message_text_default">@*android:color/car_grey_400</color>
+ <color name="unlock_dialog_enter_pin_text_color">#ff66b5ff</color>
+
</resources>
diff --git a/packages/CarSystemUI/res/values/dimens_car.xml b/packages/CarSystemUI/res/values/dimens_car.xml
index 42a7649..9cb09c9 100644
--- a/packages/CarSystemUI/res/values/dimens_car.xml
+++ b/packages/CarSystemUI/res/values/dimens_car.xml
@@ -43,4 +43,10 @@
<!-- This must be the negative of car_user_switcher_container_height for the animation. -->
<dimen name="car_user_switcher_container_anim_height">-420dp</dimen>
+ <!-- dimensions for the unlock dialog -->
+ <dimen name="unlock_dialog_width">500dp</dimen>
+ <dimen name="unlock_dialog_radius">16dp</dimen>
+ <dimen name="unlock_dialog_avatar_size">100dp</dimen>
+ <dimen name="unlock_dialog_progress_bar_size">140dp</dimen>
+
</resources>
diff --git a/packages/CarSystemUI/res/values/integers_car.xml b/packages/CarSystemUI/res/values/integers_car.xml
index be2cb0d8..862ba75 100644
--- a/packages/CarSystemUI/res/values/integers_car.xml
+++ b/packages/CarSystemUI/res/values/integers_car.xml
@@ -31,5 +31,7 @@
<!--Percentage of the screen height, from the bottom, that a notification panel being peeked
at will result in remaining closed the panel if released-->
<integer name="notification_settle_close_percentage">80</integer>
+ <!-- The delay before the unlock dialog pops up -->
+ <integer name="unlock_dialog_delay_ms">3000</integer>
</resources>
diff --git a/packages/CarSystemUI/res/values/strings_car.xml b/packages/CarSystemUI/res/values/strings_car.xml
index 83e91c5..717692e 100644
--- a/packages/CarSystemUI/res/values/strings_car.xml
+++ b/packages/CarSystemUI/res/values/strings_car.xml
@@ -29,4 +29,19 @@
<string name="user_add_user_message_setup">When you add a new user, that person needs to set up their space.</string>
<!-- Message to inform user that the newly created user will have permissions to update apps for all other users. [CHAR LIMIT=100] -->
<string name="user_add_user_message_update">Any user can update apps for all other users.</string>
+ <!-- Default messages displayed on the unlock dialog before unlock advertising started. [CHAR LIMIT=30]-->
+ <string name="unlock_dialog_message_default">Waiting\u2026</string>
+ <!-- Message to inform user that the IHU is looking for trusted device. [CHAR LIMIT=30] -->
+ <string name="unlock_dialog_message_start">Looking for trusted device\u2026</string>
+
+ <!-- Cancel Button text for user who has PIN as security lock. [CHAR LIMIT=30] -->
+ <string name="unlock_dialog_button_text_pin">Enter PIN instead</string>
+ <!-- Cancel Button text for user who has Pattern as security lock. [CHAR LIMIT=30] -->
+ <string name="unlock_dialog_button_text_pattern">Enter Pattern instead</string>
+ <!-- Cancel Button text for user who has Password as security lock. [CHAR LIMIT=30] -->
+ <string name="unlock_dialog_button_text_password">Enter Password instead</string>
+ <!-- Default user name shows on unlock dialog -->
+ <string name="unlock_dialog_default_user_name">Default Name</string>
+ <!-- Default title for unlock dialog -->
+ <string name="unlock_dialog_title">Unlock Dialogue</string>
</resources>
diff --git a/packages/CarSystemUI/res/values/styles.xml b/packages/CarSystemUI/res/values/styles.xml
index 371bebd..a9423bf 100644
--- a/packages/CarSystemUI/res/values/styles.xml
+++ b/packages/CarSystemUI/res/values/styles.xml
@@ -46,4 +46,12 @@
<item name="android:layout_width">96dp</item>
<item name="android:background">@drawable/nav_button_background</item>
</style>
+
+ <style name="UnlockDialogButton">
+ <item name="android:background">?android:attr/selectableItemBackground</item>
+ <item name="android:textAlignment">center</item>
+ <item name="android:textColor">@color/unlock_dialog_enter_pin_text_color</item>
+ <item name="android:paddingHorizontal">16dp</item>
+ <item name="android:textAllCaps">false</item>
+ </style>
</resources>
\ No newline at end of file
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index b1f9797..97fbea6 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -26,6 +26,7 @@
import android.car.drivingstate.CarDrivingStateEvent;
import android.car.drivingstate.CarUxRestrictionsManager;
import android.car.hardware.power.CarPowerManager.CarPowerStateListener;
+import android.car.trust.CarTrustAgentEnrollmentManager;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.PixelFormat;
@@ -957,8 +958,12 @@
UserSwitcherController userSwitcherController =
Dependency.get(UserSwitcherController.class);
if (userSwitcherController.useFullscreenUserSwitcher()) {
+ Car car = Car.createCar(mContext);
+ CarTrustAgentEnrollmentManager enrollmentManager = (CarTrustAgentEnrollmentManager) car
+ .getCarManager(Car.CAR_TRUST_AGENT_ENROLLMENT_SERVICE);
mFullscreenUserSwitcher = new FullscreenUserSwitcher(this,
- mStatusBarWindow.findViewById(R.id.fullscreen_user_switcher_stub), mContext);
+ mStatusBarWindow.findViewById(R.id.fullscreen_user_switcher_stub),
+ enrollmentManager, mContext);
} else {
super.createUserSwitcher();
}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java
new file mode 100644
index 0000000..78bb1bc
--- /dev/null
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.car;
+
+import android.app.admin.DevicePolicyManager;
+import android.bluetooth.BluetoothAdapter;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.PixelFormat;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.WindowManager;
+import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.R;
+
+/**
+ * A helper class displays an unlock dialog and receives broadcast about detecting trusted device
+ * & unlocking state to show the appropriate message on the dialog.
+ */
+class CarTrustAgentUnlockDialogHelper extends BroadcastReceiver{
+ private static final String TAG = CarTrustAgentUnlockDialogHelper.class.getSimpleName();
+
+ private final Context mContext;
+ private final WindowManager mWindowManager;
+ private final UserManager mUserManager;
+ private final WindowManager.LayoutParams mParams;
+ /**
+ * Not using Dialog because context passed from {@link FullscreenUserSwitcher} is not an
+ * activity.
+ */
+ private final View mUnlockDialog;
+ private final TextView mUnlockingText;
+ private final Button mButton;
+ private final IntentFilter mFilter;
+ private int mUid;
+ private boolean mIsDialogShowing;
+ private OnHideListener mOnHideListener;
+
+ CarTrustAgentUnlockDialogHelper(Context context) {
+ mContext = context;
+ mUserManager = mContext.getSystemService(UserManager.class);
+ mWindowManager = mContext.getSystemService(WindowManager.class);
+ mParams = createLayoutParams();
+ mFilter = getIntentFilter();
+
+ mParams.packageName = mContext.getPackageName();
+ mParams.setTitle(mContext.getString(R.string.unlock_dialog_title));
+
+ mUnlockDialog = LayoutInflater.from(mContext).inflate(
+ R.layout.trust_agent_unlock_dialog, null);
+ mUnlockDialog.setLayoutParams(mParams);
+
+ mUnlockingText = mUnlockDialog.findViewById(R.id.unlocking_text);
+ mButton = mUnlockDialog.findViewById(R.id.enter_pin_button);
+ mButton.setOnClickListener(v -> {
+ hideUnlockDialog(/* notifyOnHideListener= */true);
+ // TODO(b/138250105) Stop unlock advertising
+ });
+
+ BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+ if (bluetoothAdapter != null
+ && bluetoothAdapter.getLeState() == BluetoothAdapter.STATE_BLE_ON) {
+ mUnlockingText.setText(R.string.unlock_dialog_message_start);
+ }
+ }
+
+ /**
+ * This filter is listening on:
+ * {@link BluetoothAdapter#ACTION_BLE_STATE_CHANGED} for starting unlock advertising;
+ * {@link Intent#ACTION_USER_UNLOCKED} for IHU unlocked
+ */
+ private IntentFilter getIntentFilter() {
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(BluetoothAdapter.ACTION_BLE_STATE_CHANGED);
+ filter.addAction(Intent.ACTION_USER_UNLOCKED);
+ return filter;
+ }
+
+ /**
+ * Show dialog for the given user
+ */
+ void showUnlockDialog(int uid, OnHideListener listener) {
+ showUnlockDialogAfterDelay(uid, 0, listener);
+ }
+
+ /**
+ * Show dialog for the given user after the certain time of delay has elapsed
+ *
+ * @param uid the user to unlock
+ * @param listener listener that listens to dialog hide
+ */
+ void showUnlockDialogAfterDelay(int uid, OnHideListener listener) {
+ long delayMillis = mContext.getResources().getInteger(R.integer.unlock_dialog_delay_ms);
+ showUnlockDialogAfterDelay(uid, delayMillis, listener);
+ }
+
+ /**
+ * Show dialog for the given user after the supplied delay has elapsed
+ */
+ private void showUnlockDialogAfterDelay(int uid, long delayMillis, OnHideListener listener) {
+ setUid(uid);
+ mOnHideListener = listener;
+ if (!mIsDialogShowing) {
+ logd("Receiver registered");
+ mContext.registerReceiverAsUser(this, UserHandle.ALL, mFilter,
+ /* broadcastPermission= */ null,
+ /* scheduler= */ null);
+ new Handler().postDelayed(() -> {
+ if (!mUserManager.isUserUnlocked(uid)) {
+ logd("Showed unlock dialog for user: " + uid + " after " + delayMillis
+ + " delay.");
+ mWindowManager.addView(mUnlockDialog, mParams);
+ }
+ }, delayMillis);
+ }
+ mIsDialogShowing = true;
+ }
+
+ private void setUid(int uid) {
+ mUid = uid;
+ TextView userName = mUnlockDialog.findViewById(R.id.user_name);
+ userName.setText(mUserManager.getUserInfo(mUid).name);
+ ImageView avatar = mUnlockDialog.findViewById(R.id.avatar);
+ avatar.setImageBitmap(mUserManager.getUserIcon(mUid));
+ setButtonText();
+ }
+
+ private void hideUnlockDialog(boolean notifyOnHideListener) {
+ if (!mIsDialogShowing) {
+ return;
+ }
+ mWindowManager.removeView(mUnlockDialog);
+ logd("Receiver unregistered");
+ mContext.unregisterReceiver(this);
+ if (notifyOnHideListener && mOnHideListener != null) {
+ mOnHideListener.onHide();
+ }
+ mIsDialogShowing = false;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action == null) {
+ return;
+ }
+ switch (action) {
+ case BluetoothAdapter.ACTION_BLE_STATE_CHANGED:
+ logd("Received ACTION_BLE_STATE_CHANGED");
+ int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
+ if (state == BluetoothAdapter.STATE_BLE_ON) {
+ logd("Received BLE_ON");
+ mUnlockingText.setText(R.string.unlock_dialog_message_start);
+ }
+ break;
+ case Intent.ACTION_USER_UNLOCKED:
+ int uid = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
+ if (uid == mUid) {
+ logd("IHU unlocked");
+ hideUnlockDialog(/* notifyOnHideListener= */false);
+ } else {
+ Log.e(TAG, "Received ACTION_USER_UNLOCKED for unexpected uid: " + uid);
+ }
+ break;
+ default:
+ Log.e(TAG, "Encountered unexpected action when attempting to set "
+ + "unlock state message: " + action);
+ }
+ }
+
+ // Set button text based on security lock type
+ private void setButtonText() {
+ LockPatternUtils lockPatternUtils = new LockPatternUtils(mContext);
+ int passwordQuality = lockPatternUtils.getActivePasswordQuality(mUid);
+ switch (passwordQuality) {
+ // PIN
+ case DevicePolicyManager.PASSWORD_QUALITY_NUMERIC_COMPLEX:
+ // Pattern
+ case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
+ mButton.setText(R.string.unlock_dialog_button_text_pattern);
+ break;
+ // Password
+ case DevicePolicyManager.PASSWORD_QUALITY_MANAGED:
+ mButton.setText(R.string.unlock_dialog_button_text_password);
+ break;
+ default:
+ Log.e(TAG, "Encountered unexpected security type when attempting to set "
+ + "button text:" + passwordQuality);
+ }
+ }
+
+ private WindowManager.LayoutParams createLayoutParams() {
+ return new WindowManager.LayoutParams(
+ WindowManager.LayoutParams.MATCH_PARENT,
+ WindowManager.LayoutParams.MATCH_PARENT,
+ WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG,
+ WindowManager.LayoutParams.FLAG_FULLSCREEN
+ | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
+ | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
+ PixelFormat.TRANSLUCENT
+ );
+ }
+
+ private void logd(String message) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, message);
+ }
+ }
+
+ /**
+ * Listener used to notify when the dialog is hidden
+ */
+ interface OnHideListener {
+ void onHide();
+ }
+}
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index 0a167d9..7cd6adb 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -18,29 +18,60 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.car.trust.CarTrustAgentEnrollmentManager;
+import android.car.userlib.CarUserManagerHelper;
+import android.content.BroadcastReceiver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.UserInfo;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.Log;
import android.view.View;
import android.view.ViewStub;
import androidx.recyclerview.widget.GridLayoutManager;
import com.android.systemui.R;
+import com.android.systemui.statusbar.car.UserGridRecyclerView.UserRecord;
/**
* Manages the fullscreen user switcher.
*/
public class FullscreenUserSwitcher {
+ private static final String TAG = FullscreenUserSwitcher.class.getSimpleName();
+ // Because user 0 is headless, user count for single user is 2
+ private static final int NUMBER_OF_BACKGROUND_USERS = 1;
private final UserGridRecyclerView mUserGridView;
private final View mParent;
private final int mShortAnimDuration;
private final CarStatusBar mStatusBar;
+ private final Context mContext;
+ private final UserManager mUserManager;
+ private final CarTrustAgentEnrollmentManager mEnrollmentManager;
+ private CarTrustAgentUnlockDialogHelper mUnlockDialogHelper;
+ private UserGridRecyclerView.UserRecord mSelectedUser;
+ private CarUserManagerHelper mCarUserManagerHelper;
+ private final BroadcastReceiver mUserUnlockReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "user 0 is unlocked, SharedPreference is accessible.");
+ }
+ showDialogForInitialUser();
+ mContext.unregisterReceiver(mUserUnlockReceiver);
+ }
+ };
- public FullscreenUserSwitcher(CarStatusBar statusBar, ViewStub containerStub, Context context) {
+
+ public FullscreenUserSwitcher(CarStatusBar statusBar, ViewStub containerStub,
+ CarTrustAgentEnrollmentManager enrollmentManager, Context context) {
mStatusBar = statusBar;
mParent = containerStub.inflate();
- // Hide the user grid by default. It will only be made visible by clicking on a cancel
- // button in a bouncer.
- hide();
+ mEnrollmentManager = enrollmentManager;
+ mContext = context;
+
View container = mParent.findViewById(R.id.container);
// Initialize user grid.
@@ -50,9 +81,51 @@
mUserGridView.setLayoutManager(layoutManager);
mUserGridView.buildAdapter();
mUserGridView.setUserSelectionListener(this::onUserSelected);
+ mCarUserManagerHelper = new CarUserManagerHelper(context);
+ mUnlockDialogHelper = new CarTrustAgentUnlockDialogHelper(mContext);
+ mUserManager = mContext.getSystemService(UserManager.class);
mShortAnimDuration = container.getResources()
.getInteger(android.R.integer.config_shortAnimTime);
+ IntentFilter filter = new IntentFilter(Intent.ACTION_USER_UNLOCKED);
+ if (mUserManager.isUserUnlocked(UserHandle.USER_SYSTEM)) {
+ // User0 is unlocked, switched to the initial user
+ showDialogForInitialUser();
+ } else {
+ // listen to USER_UNLOCKED
+ mContext.registerReceiverAsUser(mUserUnlockReceiver,
+ UserHandle.getUserHandleForUid(UserHandle.USER_SYSTEM),
+ filter,
+ /* broadcastPermission= */ null,
+ /* scheduler */ null);
+ }
+ }
+
+ private void showDialogForInitialUser() {
+ int initialUser = mCarUserManagerHelper.getInitialUser();
+ UserInfo initialUserInfo = mUserManager.getUserInfo(initialUser);
+ mSelectedUser = new UserRecord(initialUserInfo,
+ /* isStartGuestSession= */ false,
+ /* isAddUser= */ false,
+ /* isForeground= */ true);
+ // For single user without trusted device, hide the user switcher.
+ if (!hasMultipleUsers() && !hasTrustedDevice(initialUser)) {
+ dismissUserSwitcher();
+ return;
+ }
+ // Show unlock dialog for initial user
+ if (hasTrustedDevice(initialUser)) {
+ mUnlockDialogHelper.showUnlockDialogAfterDelay(initialUser,
+ () -> dismissUserSwitcher());
+ }
+ }
+
+ /**
+ * Check if there is only one possible user to login in.
+ * In a Multi-User system there is always one background user (user 0)
+ */
+ private boolean hasMultipleUsers() {
+ return mUserManager.getUserCount() > NUMBER_OF_BACKGROUND_USERS + 1;
}
/**
@@ -77,14 +150,33 @@
}
/**
- * Every time user clicks on an item in the switcher, we hide the switcher, either
- * gradually or immediately.
+ * Every time user clicks on an item in the switcher, if the clicked user has no trusted device,
+ * we hide the switcher, either gradually or immediately.
*
- * We dismiss the entire keyguard if user clicked on the foreground user (user we're already
- * logged in as).
+ * If the user has trusted device, we show an unlock dialog to notify user the unlock state.
+ * When the unlock dialog is dismissed by user, we hide the unlock dialog and the switcher.
+ *
+ * We dismiss the entire keyguard when we hide the switcher if user clicked on the foreground
+ * user (user we're already logged in as).
*/
private void onUserSelected(UserGridRecyclerView.UserRecord record) {
- if (record.mIsForeground) {
+ mSelectedUser = record;
+ if (hasTrustedDevice(record.mInfo.id)) {
+ mUnlockDialogHelper.showUnlockDialog(record.mInfo.id, () -> dismissUserSwitcher());
+ return;
+ }
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "no trusted device enrolled for uid: " + record.mInfo.id);
+ }
+ dismissUserSwitcher();
+ }
+
+ private void dismissUserSwitcher() {
+ if (mSelectedUser == null) {
+ Log.e(TAG, "Request to dismiss user switcher, but no user selected");
+ return;
+ }
+ if (mSelectedUser.mIsForeground) {
hide();
mStatusBar.dismissKeyguard();
return;
@@ -106,4 +198,8 @@
});
}
+
+ private boolean hasTrustedDevice(int uid) {
+ return !mEnrollmentManager.getEnrolledDeviceInfoForUser(uid).isEmpty();
+ }
}
diff --git a/packages/SettingsLib/res/values/styles_support_preference.xml b/packages/SettingsLib/res/values/styles_support_preference.xml
index 5d787f8..6e61196 100644
--- a/packages/SettingsLib/res/values/styles_support_preference.xml
+++ b/packages/SettingsLib/res/values/styles_support_preference.xml
@@ -26,7 +26,7 @@
<item name="allowDividerAbove">true</item>
</style>
- <style name="PreferenceThemeOverlay.SettingsBase" parent="@style/PreferenceThemeOverlay.v14.Material">
+ <style name="PreferenceThemeOverlay.SettingsBase" parent="@style/PreferenceThemeOverlay">
<item name="footerPreferenceStyle">@style/Preference.FooterPreference.SettingsBase</item>
</style>
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 3e359d2..d3bab5f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -224,7 +224,9 @@
mConnectivityManager = connectivityManager;
// check if verbose logging developer option has been turned on or off
- sVerboseLogging = mWifiManager != null && (mWifiManager.getVerboseLoggingLevel() > 0);
+ sVerboseLogging = Settings.Global.getInt(
+ mContext.getContentResolver(),
+ Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, 0) > 0;
mFilter = filter;
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index 6adb305..a3b0e6b 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -18,7 +18,9 @@
import android.annotation.NonNull;
import android.os.UserHandle;
+import android.provider.DeviceConfig;
import android.provider.Settings;
+import android.providers.settings.ConfigSettingsProto;
import android.providers.settings.GlobalSettingsProto;
import android.providers.settings.SecureSettingsProto;
import android.providers.settings.SettingProto;
@@ -28,24 +30,79 @@
import android.util.SparseBooleanArray;
import android.util.proto.ProtoOutputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
/** @hide */
class SettingsProtoDumpUtil {
+ private static final Map<String, Long> NAMESPACE_TO_FIELD_MAP = createNamespaceMap();
+
private SettingsProtoDumpUtil() {}
+ private static Map<String, Long> createNamespaceMap() {
+ Map<String, Long> namespaceToFieldMap = new HashMap<>();
+ namespaceToFieldMap.put(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+ ConfigSettingsProto.ACTIVITY_MANAGER_SETTINGS);
+ namespaceToFieldMap.put(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER_NATIVE_BOOT,
+ ConfigSettingsProto.ACTIVITY_MANAGER_NATIVE_BOOT_SETTINGS);
+ namespaceToFieldMap.put(DeviceConfig.NAMESPACE_APP_COMPAT,
+ ConfigSettingsProto.APP_COMPAT_SETTINGS);
+ namespaceToFieldMap.put(DeviceConfig.NAMESPACE_AUTOFILL,
+ ConfigSettingsProto.AUTOFILL_SETTINGS);
+ namespaceToFieldMap.put(DeviceConfig.NAMESPACE_CONNECTIVITY,
+ ConfigSettingsProto.CONNECTIVITY_SETTINGS);
+ namespaceToFieldMap.put(DeviceConfig.NAMESPACE_CONTENT_CAPTURE,
+ ConfigSettingsProto.CONTENT_CAPTURE_SETTINGS);
+ namespaceToFieldMap.put(DeviceConfig.NAMESPACE_DEX_BOOT,
+ ConfigSettingsProto.DEX_BOOT_SETTINGS);
+ namespaceToFieldMap.put(DeviceConfig.NAMESPACE_GAME_DRIVER,
+ ConfigSettingsProto.GAME_DRIVER_SETTINGS);
+ namespaceToFieldMap.put(DeviceConfig.NAMESPACE_INPUT_NATIVE_BOOT,
+ ConfigSettingsProto.INPUT_NATIVE_BOOT_SETTINGS);
+ namespaceToFieldMap.put(DeviceConfig.NAMESPACE_NETD_NATIVE,
+ ConfigSettingsProto.NETD_NATIVE_SETTINGS);
+ namespaceToFieldMap.put(DeviceConfig.NAMESPACE_PRIVACY,
+ ConfigSettingsProto.PRIVACY_SETTINGS);
+ namespaceToFieldMap.put(DeviceConfig.NAMESPACE_ROLLBACK,
+ ConfigSettingsProto.ROLLBACK_SETTINGS);
+ namespaceToFieldMap.put(DeviceConfig.NAMESPACE_ROLLBACK_BOOT,
+ ConfigSettingsProto.ROLLBACK_BOOT_SETTINGS);
+ namespaceToFieldMap.put(DeviceConfig.NAMESPACE_RUNTIME,
+ ConfigSettingsProto.RUNTIME_SETTINGS);
+ namespaceToFieldMap.put(DeviceConfig.NAMESPACE_RUNTIME_NATIVE,
+ ConfigSettingsProto.RUNTIME_NATIVE_SETTINGS);
+ namespaceToFieldMap.put(DeviceConfig.NAMESPACE_RUNTIME_NATIVE_BOOT,
+ ConfigSettingsProto.RUNTIME_NATIVE_BOOT_SETTINGS);
+ namespaceToFieldMap.put(DeviceConfig.NAMESPACE_STORAGE,
+ ConfigSettingsProto.STORAGE_SETTINGS);
+ namespaceToFieldMap.put(DeviceConfig.NAMESPACE_SYSTEMUI,
+ ConfigSettingsProto.SYSTEMUI_SETTINGS);
+ namespaceToFieldMap.put(DeviceConfig.NAMESPACE_TELEPHONY,
+ ConfigSettingsProto.TELEPHONY_SETTINGS);
+ namespaceToFieldMap.put(DeviceConfig.NAMESPACE_TEXTCLASSIFIER,
+ ConfigSettingsProto.TEXTCLASSIFIER_SETTINGS);
+ return Collections.unmodifiableMap(namespaceToFieldMap);
+ }
+
static void dumpProtoLocked(SettingsProvider.SettingsRegistry settingsRegistry,
ProtoOutputStream proto) {
// Config settings
SettingsState configSettings = settingsRegistry.getSettingsLocked(
SettingsProvider.SETTINGS_TYPE_CONFIG, UserHandle.USER_SYSTEM);
if (configSettings != null) {
- // TODO(b/113100523): dump configuration settings after they are added
+ dumpProtoConfigSettingsLocked(
+ proto, SettingsServiceDumpProto.CONFIG_SETTINGS, configSettings);
}
// Global settings
SettingsState globalSettings = settingsRegistry.getSettingsLocked(
SettingsProvider.SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
if (globalSettings != null) {
- dumpProtoGlobalSettingsLocked(proto, SettingsServiceDumpProto.GLOBAL_SETTINGS, globalSettings);
+ dumpProtoGlobalSettingsLocked(
+ proto, SettingsServiceDumpProto.GLOBAL_SETTINGS, globalSettings);
}
// Per-user settings
@@ -1599,6 +1656,33 @@
// Settings.Global.INSTALL_NON_MARKET_APPS intentionally excluded since it's deprecated.
}
+ private static void dumpProtoConfigSettingsLocked(
+ @NonNull ProtoOutputStream p, long fieldId, @NonNull SettingsState s) {
+ Map<String, List<String>> namespaceMap = new HashMap<>();
+ final long token = p.start(fieldId);
+ s.dumpHistoricalOperations(p, ConfigSettingsProto.HISTORICAL_OPERATIONS);
+ for (String name : s.getSettingNamesLocked()) {
+ String namespace = name.substring(0, name.indexOf('/'));
+ if (NAMESPACE_TO_FIELD_MAP.containsKey(namespace)) {
+ dumpSetting(s, p, name, NAMESPACE_TO_FIELD_MAP.get(namespace));
+ } else {
+ if (!namespaceMap.containsKey(namespace)) {
+ namespaceMap.put(namespace, new ArrayList<>());
+ }
+ namespaceMap.get(namespace).add(name);
+ }
+ }
+ for (String namespace : namespaceMap.keySet()) {
+ final long namespacesToken = p.start(ConfigSettingsProto.EXTRA_NAMESPACES);
+ p.write(ConfigSettingsProto.NamespaceProto.NAMESPACE, namespace);
+ for (String name : namespaceMap.get(namespace)) {
+ dumpSetting(s, p, name, ConfigSettingsProto.NamespaceProto.SETTINGS);
+ }
+ p.end(namespacesToken);
+ }
+ p.end(token);
+ }
+
/** Dumps settings that use a common prefix into a repeated field. */
private static void dumpRepeatedSetting(@NonNull SettingsState settings,
@NonNull ProtoOutputStream proto, String settingPrefix, long fieldId) {
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
index c732584..08996c3 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/QuickStepContract.java
@@ -188,9 +188,8 @@
if ((sysuiStateFlags & SYSUI_STATE_BOUNCER_SHOWING) != 0) {
return false;
}
- // Disable when in screen pinning, immersive, or the notifications are interactive
- int disableFlags = SYSUI_STATE_SCREEN_PINNING
- | SYSUI_STATE_NAV_BAR_HIDDEN
+ // Disable when in immersive, or the notifications are interactive
+ int disableFlags = SYSUI_STATE_NAV_BAR_HIDDEN
| SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED
| SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING;
return (sysuiStateFlags & disableFlags) != 0;
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 0ee9bff..59270a0 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -34,6 +34,7 @@
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.systemui.appops.AppOpsController;
import com.android.systemui.assist.AssistManager;
+import com.android.systemui.broadcast.BroadcastDispatcher;
import com.android.systemui.bubbles.BubbleController;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dock.DockManager;
@@ -200,6 +201,7 @@
@Inject Lazy<ActivityStarter> mActivityStarter;
@Inject Lazy<ActivityStarterDelegate> mActivityStarterDelegate;
+ @Inject Lazy<BroadcastDispatcher> mBroadcastDispatcher;
@Inject Lazy<AsyncSensorManager> mAsyncSensorManager;
@Inject Lazy<BluetoothController> mBluetoothController;
@Inject Lazy<LocationController> mLocationController;
@@ -317,6 +319,7 @@
mProviders.put(MAIN_HANDLER, mMainHandler::get);
mProviders.put(ActivityStarter.class, mActivityStarter::get);
mProviders.put(ActivityStarterDelegate.class, mActivityStarterDelegate::get);
+ mProviders.put(BroadcastDispatcher.class, mBroadcastDispatcher::get);
mProviders.put(AsyncSensorManager.class, mAsyncSensorManager::get);
@@ -496,6 +499,7 @@
// Make sure that the DumpController gets added to mDependencies, as they are only added
// with Dependency#get.
getDependency(DumpController.class);
+ getDependency(BroadcastDispatcher.class);
// If an arg is specified, try to dump the dependency
String controller = args != null && args.length > 1
diff --git a/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java b/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
index bc782a7..bb3bd78 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/ui/InvocationLightsView.java
@@ -100,7 +100,9 @@
int cornerRadiusBottom = DisplayUtils.getCornerRadiusBottom(context);
int cornerRadiusTop = DisplayUtils.getCornerRadiusTop(context);
- mViewHeight = Math.max(cornerRadiusBottom, cornerRadiusTop);
+ // ensure that height is non-zero even for square corners
+ mViewHeight = Math.max(Math.max(cornerRadiusBottom, cornerRadiusTop),
+ DisplayUtils.convertDpToPx(LIGHT_HEIGHT_DP, context));
final int dualToneDarkTheme = Utils.getThemeAttr(mContext, R.attr.darkIconTheme);
final int dualToneLightTheme = Utils.getThemeAttr(mContext, R.attr.lightIconTheme);
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
new file mode 100644
index 0000000..f0e8c16
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/BroadcastDispatcher.kt
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.broadcast
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.IntentFilter
+import android.os.Handler
+import android.os.Looper
+import android.os.Message
+import android.os.UserHandle
+import android.util.Log
+import android.util.SparseArray
+import com.android.internal.annotations.VisibleForTesting
+import com.android.systemui.Dependency.BG_LOOPER_NAME
+import com.android.systemui.Dependency.MAIN_HANDLER_NAME
+import com.android.systemui.Dumpable
+import java.io.FileDescriptor
+import java.io.PrintWriter
+import javax.inject.Inject
+import javax.inject.Named
+import javax.inject.Singleton
+
+data class ReceiverData(
+ val receiver: BroadcastReceiver,
+ val filter: IntentFilter,
+ val handler: Handler,
+ val user: UserHandle
+)
+
+private const val MSG_ADD_RECEIVER = 0
+private const val MSG_REMOVE_RECEIVER = 1
+private const val MSG_REMOVE_RECEIVER_FOR_USER = 2
+private const val TAG = "BroadcastDispatcher"
+private const val DEBUG = false
+
+/**
+ * SystemUI master Broadcast Dispatcher.
+ *
+ * This class allows [BroadcastReceiver] to register and centralizes registrations to [Context]
+ * from SystemUI. That way the number of calls to [BroadcastReceiver.onReceive] can be reduced for
+ * a given broadcast.
+ *
+ * Use only for IntentFilters with actions and optionally categories. It does not support,
+ * permissions, schemes or data types. Cannot be used for getting sticky broadcasts.
+ */
+@Singleton
+open class BroadcastDispatcher @Inject constructor (
+ private val context: Context,
+ @Named(MAIN_HANDLER_NAME) private val mainHandler: Handler,
+ @Named(BG_LOOPER_NAME) private val bgLooper: Looper
+) : Dumpable {
+
+ // Only modify in BG thread
+ private val receiversByUser = SparseArray<UserBroadcastDispatcher>(20)
+
+ /**
+ * Register a receiver for broadcast with the dispatcher
+ *
+ * @param receiver A receiver to dispatch the [Intent]
+ * @param filter A filter to determine what broadcasts should be dispatched to this receiver.
+ * It will only take into account actions and categories for filtering.
+ * @param handler A handler to dispatch [BroadcastReceiver.onReceive]. By default, it is the
+ * main handler.
+ * @param user A user handle to determine which broadcast should be dispatched to this receiver.
+ * By default, it is the current user.
+ */
+ @JvmOverloads
+ fun registerReceiver(
+ receiver: BroadcastReceiver,
+ filter: IntentFilter,
+ handler: Handler = mainHandler,
+ user: UserHandle = context.user
+ ) {
+ this.handler.obtainMessage(MSG_ADD_RECEIVER, ReceiverData(receiver, filter, handler, user))
+ .sendToTarget()
+ }
+
+ /**
+ * Unregister receiver for all users.
+ * <br>
+ * This will remove every registration of [receiver], not those done just with [UserHandle.ALL].
+ *
+ * @param receiver The receiver to unregister. It will be unregistered for all users.
+ */
+ fun unregisterReceiver(receiver: BroadcastReceiver) {
+ handler.obtainMessage(MSG_REMOVE_RECEIVER, receiver).sendToTarget()
+ }
+
+ /**
+ * Unregister receiver for a particular user.
+ *
+ * @param receiver The receiver to unregister. It will be unregistered for all users.
+ * @param user The user associated to the registered [receiver]. It can be [UserHandle.ALL].
+ */
+ fun unregisterReceiverForUser(receiver: BroadcastReceiver, user: UserHandle) {
+ handler.obtainMessage(MSG_REMOVE_RECEIVER_FOR_USER, user.identifier, 0, receiver)
+ .sendToTarget()
+ }
+
+ @VisibleForTesting
+ protected open fun createUBRForUser(userId: Int) =
+ UserBroadcastDispatcher(context, userId, mainHandler, bgLooper)
+
+ override fun dump(fd: FileDescriptor?, pw: PrintWriter?, args: Array<out String>?) {
+ pw?.println("Broadcast dispatcher:")
+ for (index in 0 until receiversByUser.size()) {
+ pw?.println(" User ${receiversByUser.keyAt(index)}")
+ receiversByUser.valueAt(index).dump(fd, pw, args)
+ }
+ }
+
+ private val handler = object : Handler(bgLooper) {
+ override fun handleMessage(msg: Message) {
+ when (msg.what) {
+ MSG_ADD_RECEIVER -> {
+ val data = msg.obj as ReceiverData
+ val userId = data.user.identifier
+ if (userId < UserHandle.USER_ALL) {
+ if (DEBUG) Log.w(TAG, "Register receiver for invalid user: $userId")
+ return
+ }
+ val uBR = receiversByUser.get(userId, createUBRForUser(userId))
+ receiversByUser.put(userId, uBR)
+ uBR.registerReceiver(data)
+ }
+
+ MSG_REMOVE_RECEIVER -> {
+ for (it in 0 until receiversByUser.size()) {
+ receiversByUser.valueAt(it).unregisterReceiver(msg.obj as BroadcastReceiver)
+ }
+ }
+
+ MSG_REMOVE_RECEIVER_FOR_USER -> {
+ receiversByUser.get(msg.arg1)?.unregisterReceiver(msg.obj as BroadcastReceiver)
+ }
+
+ else -> super.handleMessage(msg)
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt b/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
new file mode 100644
index 0000000..d44b63e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/broadcast/UserBroadcastDispatcher.kt
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.broadcast
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.os.Handler
+import android.os.Looper
+import android.os.Message
+import android.os.UserHandle
+import android.util.ArrayMap
+import android.util.ArraySet
+import android.util.Log
+import com.android.systemui.Dumpable
+import java.io.FileDescriptor
+import java.io.PrintWriter
+import java.util.concurrent.atomic.AtomicBoolean
+
+private const val MSG_REGISTER_RECEIVER = 0
+private const val MSG_UNREGISTER_RECEIVER = 1
+private const val TAG = "UniversalReceiver"
+private const val DEBUG = false
+
+/**
+ * Broadcast dispatcher for a given user registration [userId].
+ *
+ * Created by [BroadcastDispatcher] as needed by users. The value of [userId] can be
+ * [UserHandle.USER_ALL].
+ */
+class UserBroadcastDispatcher(
+ private val context: Context,
+ private val userId: Int,
+ private val mainHandler: Handler,
+ private val bgLooper: Looper
+) : BroadcastReceiver(), Dumpable {
+
+ private val bgHandler = object : Handler(bgLooper) {
+ override fun handleMessage(msg: Message) {
+ when (msg.what) {
+ MSG_REGISTER_RECEIVER -> handleRegisterReceiver(msg.obj as ReceiverData)
+ MSG_UNREGISTER_RECEIVER -> handleUnregisterReceiver(msg.obj as BroadcastReceiver)
+ else -> Unit
+ }
+ }
+ }
+
+ private val registered = AtomicBoolean(false)
+
+ internal fun isRegistered() = registered.get()
+
+ private val registerReceiver = Runnable {
+ val categories = mutableSetOf<String>()
+ receiverToReceiverData.values.flatten().forEach {
+ it.filter.categoriesIterator()?.asSequence()?.let {
+ categories.addAll(it)
+ }
+ }
+ val intentFilter = IntentFilter().apply {
+ actionsToReceivers.keys.forEach { addAction(it) }
+ categories.forEach { addCategory(it) }
+ }
+
+ if (registered.get()) {
+ context.unregisterReceiver(this)
+ registered.set(false)
+ }
+ // Short interval without receiver, this can be problematic
+ if (intentFilter.countActions() > 0 && !registered.get()) {
+ context.registerReceiverAsUser(
+ this,
+ UserHandle.of(userId),
+ intentFilter,
+ null,
+ bgHandler)
+ registered.set(true)
+ }
+ }
+
+ // Only modify in BG thread
+ private val actionsToReceivers = ArrayMap<String, MutableSet<ReceiverData>>()
+ private val receiverToReceiverData = ArrayMap<BroadcastReceiver, MutableSet<ReceiverData>>()
+
+ override fun onReceive(context: Context, intent: Intent) {
+ bgHandler.post(HandleBroadcastRunnable(actionsToReceivers, context, intent))
+ }
+
+ /**
+ * Register a [ReceiverData] for this user.
+ */
+ fun registerReceiver(receiverData: ReceiverData) {
+ bgHandler.obtainMessage(MSG_REGISTER_RECEIVER, receiverData).sendToTarget()
+ }
+
+ /**
+ * Unregister a given [BroadcastReceiver] for this user.
+ */
+ fun unregisterReceiver(receiver: BroadcastReceiver) {
+ bgHandler.obtainMessage(MSG_UNREGISTER_RECEIVER, receiver).sendToTarget()
+ }
+
+ private fun handleRegisterReceiver(receiverData: ReceiverData) {
+ if (DEBUG) Log.w(TAG, "Register receiver: ${receiverData.receiver}")
+ receiverToReceiverData.getOrPut(receiverData.receiver, { ArraySet() }).add(receiverData)
+ var changed = false
+ // Index the BroadcastReceiver by all its actions, that way it's easier to dispatch given
+ // a received intent.
+ receiverData.filter.actionsIterator().forEach {
+ actionsToReceivers.getOrPut(it) {
+ changed = true
+ ArraySet()
+ }.add(receiverData)
+ }
+ if (changed) {
+ mainHandler.post(registerReceiver)
+ }
+ }
+
+ private fun handleUnregisterReceiver(receiver: BroadcastReceiver) {
+ if (DEBUG) Log.w(TAG, "Unregister receiver: $receiver")
+ val actions = receiverToReceiverData.getOrElse(receiver) { return }
+ .flatMap { it.filter.actionsIterator().asSequence().asIterable() }.toSet()
+ receiverToReceiverData.get(receiver)?.clear()
+ var changed = false
+ actions.forEach { action ->
+ actionsToReceivers.get(action)?.removeIf { it.receiver == receiver }
+ if (actionsToReceivers.get(action)?.isEmpty() ?: false) {
+ changed = true
+ actionsToReceivers.remove(action)
+ }
+ }
+ if (changed) {
+ mainHandler.post(registerReceiver)
+ }
+ }
+
+ override fun dump(fd: FileDescriptor?, pw: PrintWriter?, args: Array<out String>?) {
+ pw?.println(" Registered=${registered.get()}")
+ actionsToReceivers.forEach { (action, list) ->
+ pw?.println(" $action:")
+ list.forEach { pw?.println(" ${it.receiver}") }
+ }
+ }
+
+ private class HandleBroadcastRunnable(
+ val actionsToReceivers: Map<String, Set<ReceiverData>>,
+ val context: Context,
+ val intent: Intent
+ ) : Runnable {
+ override fun run() {
+ if (DEBUG) Log.w(TAG, "Dispatching $intent")
+ actionsToReceivers.get(intent.action)
+ ?.filter {
+ it.filter.hasAction(intent.action) &&
+ it.filter.matchCategories(intent.categories) == null }
+ ?.forEach {
+ it.handler.post {
+ if (DEBUG) Log.w(TAG, "Dispatching to ${it.receiver}")
+ it.receiver.onReceive(context, intent)
+ }
+ }
+ }
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index 991d9fa..0403a05 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -248,7 +248,9 @@
int numPages = Math.max(nTiles / mPages.get(0).maxTiles(), 1);
// Add one more not full page if needed
- numPages += (nTiles % mPages.get(0).maxTiles() == 0 ? 0 : 1);
+ if (nTiles > numPages * mPages.get(0).maxTiles()) {
+ numPages++;
+ }
final int NP = mPages.size();
for (int i = 0; i < NP; i++) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 001e094..16a3975 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -73,6 +73,7 @@
if (listening) {
refreshState();
}
+ mHotspotController.handleSetListening(listening);
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
index 830b50e..8b06a9f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotController.java
@@ -20,6 +20,8 @@
import com.android.systemui.statusbar.policy.HotspotController.Callback;
public interface HotspotController extends CallbackController<Callback>, Dumpable {
+ void handleSetListening(boolean listening);
+
boolean isHotspotEnabled();
boolean isHotspotTransient();
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 db2be0e..1c6d12f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HotspotControllerImpl.java
@@ -51,6 +51,7 @@
private int mHotspotState;
private int mNumConnectedDevices;
private boolean mWaitingForTerminalState;
+ private boolean mListening;
/**
*/
@@ -105,14 +106,18 @@
if (DEBUG) Log.d(TAG, "addCallback " + callback);
mCallbacks.add(callback);
if (mWifiManager != null) {
- if (mCallbacks.size() == 1) {
- mWifiManager.registerSoftApCallback(this, mMainHandler);
- } else {
- // mWifiManager#registerSoftApCallback triggers a call to onNumClientsChanged
- // on the Main Handler. In order to always update the callback on added, we
- // make this call when adding callbacks after the first.
- mMainHandler.post(() ->
- callback.onHotspotChanged(isHotspotEnabled(), mNumConnectedDevices));
+ if (mListening) {
+ if (mCallbacks.size() == 1) {
+ mWifiManager.registerSoftApCallback(this, mMainHandler);
+ } else {
+ // mWifiManager#registerSoftApCallback triggers a call to
+ // onNumClientsChanged on the Main Handler. In order to always update the
+ // callback on added, we make this call when adding callbacks after the
+ // first.
+ mMainHandler.post(() ->
+ callback.onHotspotChanged(isHotspotEnabled(),
+ mNumConnectedDevices));
+ }
}
}
}
@@ -124,13 +129,24 @@
if (DEBUG) Log.d(TAG, "removeCallback " + callback);
synchronized (mCallbacks) {
mCallbacks.remove(callback);
- if (mCallbacks.isEmpty() && mWifiManager != null) {
+ if (mCallbacks.isEmpty() && mWifiManager != null && mListening) {
mWifiManager.unregisterSoftApCallback(this);
}
}
}
@Override
+ public void handleSetListening(boolean listening) {
+ // Wait for the first |handleSetListening(true))| to register softap callbacks (for lazy
+ // registration of the softap callbacks).
+ if (mListening || !listening) return;
+ mListening = true;
+ if (mCallbacks.size() >= 1) {
+ mWifiManager.registerSoftApCallback(this, mMainHandler);
+ }
+ }
+
+ @Override
public boolean isHotspotEnabled() {
return mHotspotState == WifiManager.WIFI_AP_STATE_ENABLED;
}
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 1c24bb9..04f96a4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -312,6 +312,7 @@
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
filter.addAction(ConnectivityManager.INET_CONDITION_ACTION);
filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+ filter.addAction(Intent.ACTION_BOOT_COMPLETED);
filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
mContext.registerReceiver(this, filter, null, mReceiverHandler);
mListening = true;
@@ -513,6 +514,9 @@
recalculateEmergency();
}
break;
+ case Intent.ACTION_BOOT_COMPLETED:
+ mWifiSignalController.handleBootCompleted();
+ break;
case CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED:
mConfig = Config.readConfig(mContext);
mReceiverHandler.post(this::handleConfigurationChanged);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
index 6f63544..a441f66 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/WifiSignalController.java
@@ -38,6 +38,7 @@
public class WifiSignalController extends
SignalController<WifiSignalController.WifiState, SignalController.IconGroup> {
private final boolean mHasMobileData;
+ private final WifiManager mWifiManager;
private final WifiStatusTracker mWifiTracker;
public WifiSignalController(Context context, boolean hasMobileData,
@@ -49,13 +50,11 @@
context.getSystemService(NetworkScoreManager.class);
ConnectivityManager connectivityManager =
context.getSystemService(ConnectivityManager.class);
+ mWifiManager = wifiManager;
mWifiTracker = new WifiStatusTracker(mContext, wifiManager, networkScoreManager,
connectivityManager, this::handleStatusUpdated);
mWifiTracker.setListening(true);
mHasMobileData = hasMobileData;
- if (wifiManager != null) {
- wifiManager.registerTrafficStateCallback(new WifiTrafficStateCallback(), null);
- }
// WiFi only has one state.
mCurrentState.iconGroup = mLastState.iconGroup = new IconGroup(
"Wi-Fi Icons",
@@ -128,6 +127,10 @@
notifyListenersIfNecessary();
}
+ public void handleBootCompleted() {
+ mWifiManager.registerTrafficStateCallback(new WifiTrafficStateCallback(), null);
+ }
+
/**
* Handler to receive the data activity on wifi.
*/
diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt
new file mode 100644
index 0000000..2bff548
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/BroadcastDispatcherTest.kt
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.broadcast
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.IntentFilter
+import android.os.Handler
+import android.os.Looper
+import android.os.UserHandle
+import android.test.suitebuilder.annotation.SmallTest
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import com.android.systemui.SysuiTestCase
+import junit.framework.Assert.assertSame
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+@SmallTest
+class BroadcastDispatcherTest : SysuiTestCase() {
+
+ companion object {
+ val user0 = UserHandle.of(0)
+ val user1 = UserHandle.of(1)
+
+ fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
+ }
+
+ @Mock
+ private lateinit var mockContext: Context
+ @Mock
+ private lateinit var mockUBRUser0: UserBroadcastDispatcher
+ @Mock
+ private lateinit var mockUBRUser1: UserBroadcastDispatcher
+ @Mock
+ private lateinit var broadcastReceiver: BroadcastReceiver
+ @Mock
+ private lateinit var broadcastReceiverOther: BroadcastReceiver
+ @Mock
+ private lateinit var intentFilter: IntentFilter
+ @Mock
+ private lateinit var intentFilterOther: IntentFilter
+ @Mock
+ private lateinit var mockHandler: Handler
+
+ @Captor
+ private lateinit var argumentCaptor: ArgumentCaptor<ReceiverData>
+
+ private lateinit var testableLooper: TestableLooper
+ private lateinit var broadcastDispatcher: BroadcastDispatcher
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ testableLooper = TestableLooper.get(this)
+
+ broadcastDispatcher = TestBroadcastDispatcher(
+ mockContext,
+ Handler(testableLooper.looper),
+ testableLooper.looper,
+ mapOf(0 to mockUBRUser0, 1 to mockUBRUser1))
+ }
+
+ @Test
+ fun testAddingReceiverToCorrectUBR() {
+ broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, mockHandler, user0)
+ broadcastDispatcher.registerReceiver(
+ broadcastReceiverOther, intentFilterOther, mockHandler, user1)
+
+ testableLooper.processAllMessages()
+
+ verify(mockUBRUser0).registerReceiver(capture(argumentCaptor))
+
+ assertSame(broadcastReceiver, argumentCaptor.value.receiver)
+ assertSame(intentFilter, argumentCaptor.value.filter)
+
+ verify(mockUBRUser1).registerReceiver(capture(argumentCaptor))
+ assertSame(broadcastReceiverOther, argumentCaptor.value.receiver)
+ assertSame(intentFilterOther, argumentCaptor.value.filter)
+ }
+
+ @Test
+ fun testRemovingReceiversRemovesFromAllUBR() {
+ broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, mockHandler, user0)
+ broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, mockHandler, user1)
+
+ broadcastDispatcher.unregisterReceiver(broadcastReceiver)
+
+ testableLooper.processAllMessages()
+
+ verify(mockUBRUser0).unregisterReceiver(broadcastReceiver)
+ verify(mockUBRUser1).unregisterReceiver(broadcastReceiver)
+ }
+
+ @Test
+ fun testRemoveReceiverFromUser() {
+ broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, mockHandler, user0)
+ broadcastDispatcher.registerReceiver(broadcastReceiver, intentFilter, mockHandler, user1)
+
+ broadcastDispatcher.unregisterReceiverForUser(broadcastReceiver, user0)
+
+ testableLooper.processAllMessages()
+
+ verify(mockUBRUser0).unregisterReceiver(broadcastReceiver)
+ verify(mockUBRUser1, never()).unregisterReceiver(broadcastReceiver)
+ }
+
+ private class TestBroadcastDispatcher(
+ context: Context,
+ mainHandler: Handler,
+ bgLooper: Looper,
+ var mockUBRMap: Map<Int, UserBroadcastDispatcher>
+ ) : BroadcastDispatcher(context, mainHandler, bgLooper) {
+ override fun createUBRForUser(userId: Int): UserBroadcastDispatcher {
+ return mockUBRMap.getOrDefault(userId, mock(UserBroadcastDispatcher::class.java))
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt b/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt
new file mode 100644
index 0000000..011c2cd
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/broadcast/UserBroadcastDispatcherTest.kt
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.broadcast
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.content.IntentFilter
+import android.os.Handler
+import android.os.UserHandle
+import android.test.suitebuilder.annotation.SmallTest
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import com.android.systemui.SysuiTestCase
+import junit.framework.Assert.assertEquals
+import junit.framework.Assert.assertFalse
+import junit.framework.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.anyString
+import org.mockito.Mockito.atLeastOnce
+import org.mockito.Mockito.never
+import org.mockito.Mockito.reset
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+@SmallTest
+class UserBroadcastDispatcherTest : SysuiTestCase() {
+
+ companion object {
+ private const val ACTION_1 = "com.android.systemui.tests.ACTION_1"
+ private const val ACTION_2 = "com.android.systemui.tests.ACTION_2"
+ private const val CATEGORY_1 = "com.android.systemui.tests.CATEGORY_1"
+ private const val CATEGORY_2 = "com.android.systemui.tests.CATEGORY_2"
+ private const val USER_ID = 0
+ private val USER_HANDLE = UserHandle.of(USER_ID)
+
+ fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
+ }
+
+ @Mock
+ private lateinit var broadcastReceiver: BroadcastReceiver
+ @Mock
+ private lateinit var broadcastReceiverOther: BroadcastReceiver
+ @Mock
+ private lateinit var mockContext: Context
+ @Mock
+ private lateinit var mockHandler: Handler
+
+ @Captor
+ private lateinit var argumentCaptor: ArgumentCaptor<IntentFilter>
+
+ private lateinit var testableLooper: TestableLooper
+ private lateinit var universalBroadcastReceiver: UserBroadcastDispatcher
+ private lateinit var intentFilter: IntentFilter
+ private lateinit var intentFilterOther: IntentFilter
+ private lateinit var handler: Handler
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ testableLooper = TestableLooper.get(this)
+ handler = Handler(testableLooper.looper)
+
+ universalBroadcastReceiver = UserBroadcastDispatcher(
+ mockContext, USER_ID, handler, testableLooper.looper)
+ }
+
+ @Test
+ fun testNotRegisteredOnStart() {
+ testableLooper.processAllMessages()
+ verify(mockContext, never()).registerReceiver(any(), any())
+ verify(mockContext, never()).registerReceiver(any(), any(), anyInt())
+ verify(mockContext, never()).registerReceiver(any(), any(), anyString(), any())
+ verify(mockContext, never()).registerReceiver(any(), any(), anyString(), any(), anyInt())
+ verify(mockContext, never()).registerReceiverAsUser(any(), any(), any(), anyString(), any())
+ }
+
+ @Test
+ fun testSingleReceiverRegistered() {
+ intentFilter = IntentFilter(ACTION_1)
+
+ universalBroadcastReceiver.registerReceiver(
+ ReceiverData(broadcastReceiver, intentFilter, mockHandler, USER_HANDLE))
+ testableLooper.processAllMessages()
+
+ assertTrue(universalBroadcastReceiver.isRegistered())
+ verify(mockContext).registerReceiverAsUser(
+ any(),
+ eq(USER_HANDLE),
+ capture(argumentCaptor),
+ any(),
+ any())
+ assertEquals(1, argumentCaptor.value.countActions())
+ assertTrue(argumentCaptor.value.hasAction(ACTION_1))
+ assertEquals(0, argumentCaptor.value.countCategories())
+ }
+
+ @Test
+ fun testSingleReceiverUnregistered() {
+ intentFilter = IntentFilter(ACTION_1)
+
+ universalBroadcastReceiver.registerReceiver(
+ ReceiverData(broadcastReceiver, intentFilter, mockHandler, USER_HANDLE))
+ testableLooper.processAllMessages()
+ reset(mockContext)
+
+ assertTrue(universalBroadcastReceiver.isRegistered())
+
+ universalBroadcastReceiver.unregisterReceiver(broadcastReceiver)
+ testableLooper.processAllMessages()
+
+ verify(mockContext, atLeastOnce()).unregisterReceiver(any())
+ verify(mockContext, never()).registerReceiverAsUser(any(), any(), any(), any(), any())
+ assertFalse(universalBroadcastReceiver.isRegistered())
+ }
+
+ @Test
+ fun testFilterHasAllActionsAndCategories_twoReceivers() {
+ intentFilter = IntentFilter(ACTION_1)
+ intentFilterOther = IntentFilter(ACTION_2).apply {
+ addCategory(CATEGORY_1)
+ addCategory(CATEGORY_2)
+ }
+
+ universalBroadcastReceiver.registerReceiver(
+ ReceiverData(broadcastReceiver, intentFilter, mockHandler, USER_HANDLE))
+ universalBroadcastReceiver.registerReceiver(
+ ReceiverData(broadcastReceiverOther, intentFilterOther, mockHandler, USER_HANDLE))
+
+ testableLooper.processAllMessages()
+ assertTrue(universalBroadcastReceiver.isRegistered())
+
+ verify(mockContext, times(2)).registerReceiverAsUser(
+ any(),
+ eq(USER_HANDLE),
+ capture(argumentCaptor),
+ any(),
+ any())
+
+ val lastFilter = argumentCaptor.value
+
+ assertTrue(lastFilter.hasAction(ACTION_1))
+ assertTrue(lastFilter.hasAction(ACTION_2))
+ assertTrue(lastFilter.hasCategory(CATEGORY_1))
+ assertTrue(lastFilter.hasCategory(CATEGORY_1))
+ }
+
+ @Test
+ fun testDispatchToCorrectReceiver() {
+ intentFilter = IntentFilter(ACTION_1)
+ intentFilterOther = IntentFilter(ACTION_2)
+
+ universalBroadcastReceiver.registerReceiver(
+ ReceiverData(broadcastReceiver, intentFilter, handler, USER_HANDLE))
+ universalBroadcastReceiver.registerReceiver(
+ ReceiverData(broadcastReceiverOther, intentFilterOther, handler, USER_HANDLE))
+
+ val intent = Intent(ACTION_2)
+
+ universalBroadcastReceiver.onReceive(mockContext, intent)
+ testableLooper.processAllMessages()
+
+ verify(broadcastReceiver, never()).onReceive(any(), any())
+ verify(broadcastReceiverOther).onReceive(mockContext, intent)
+ }
+
+ @Test
+ fun testDispatchToCorrectReceiver_differentFiltersSameReceiver() {
+ intentFilter = IntentFilter(ACTION_1)
+ intentFilterOther = IntentFilter(ACTION_2)
+
+ universalBroadcastReceiver.registerReceiver(
+ ReceiverData(broadcastReceiver, intentFilter, handler, USER_HANDLE))
+ universalBroadcastReceiver.registerReceiver(
+ ReceiverData(broadcastReceiver, intentFilterOther, handler, USER_HANDLE))
+
+ val intent = Intent(ACTION_2)
+
+ universalBroadcastReceiver.onReceive(mockContext, intent)
+ testableLooper.processAllMessages()
+
+ verify(broadcastReceiver).onReceive(mockContext, intent)
+ }
+
+ @Test
+ fun testDispatchIntentWithoutCategories() {
+ intentFilter = IntentFilter(ACTION_1)
+ intentFilter.addCategory(CATEGORY_1)
+ intentFilterOther = IntentFilter(ACTION_1)
+ intentFilterOther.addCategory(CATEGORY_2)
+
+ universalBroadcastReceiver.registerReceiver(
+ ReceiverData(broadcastReceiver, intentFilter, handler, USER_HANDLE))
+ universalBroadcastReceiver.registerReceiver(
+ ReceiverData(broadcastReceiverOther, intentFilterOther, handler, USER_HANDLE))
+
+ val intent = Intent(ACTION_1)
+
+ universalBroadcastReceiver.onReceive(mockContext, intent)
+ testableLooper.processAllMessages()
+
+ verify(broadcastReceiver).onReceive(mockContext, intent)
+ verify(broadcastReceiverOther).onReceive(mockContext, intent)
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java
index 3e4c4d6..556ed5c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/HotspotControllerImplTest.java
@@ -73,6 +73,7 @@
any(Handler.class));
mController = new HotspotControllerImpl(mContext, new Handler(mLooper.getLooper()));
+ mController.handleSetListening(true);
}
@Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeHotspotController.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeHotspotController.java
index 016160a..c9681ac 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeHotspotController.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeHotspotController.java
@@ -26,6 +26,10 @@
}
@Override
+ public void handleSetListening(boolean listening) {
+ }
+
+ @Override
public boolean isHotspotEnabled() {
return false;
}
diff --git a/services/Android.bp b/services/Android.bp
index b08d1a8..54157d0 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -35,6 +35,7 @@
"services.usage",
"services.usb",
"services.voiceinteraction",
+ "services.wifi",
"android.hidl.base-V1.0-java",
],
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index fffdba7..695fccc 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -18,29 +18,21 @@
import static com.android.internal.util.Preconditions.checkNotNull;
-import android.Manifest;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
-import android.app.ActivityManager;
import android.app.backup.BackupManager;
import android.app.backup.IBackupManagerMonitor;
import android.app.backup.IBackupObserver;
import android.app.backup.IFullBackupRestoreObserver;
import android.app.backup.IRestoreSession;
-import android.app.backup.ISelectBackupTransportCallback;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
import android.app.job.JobService;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
import android.content.pm.PackageManager;
-import android.os.Binder;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.UserHandle;
-import android.os.UserManager;
-import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
@@ -82,42 +74,6 @@
}
/**
- * If {@code userId} is different from the calling user id, then the caller must hold the
- * android.permission.INTERACT_ACROSS_USERS_FULL permission.
- *
- * @param userId User id on which the backup operation is being requested.
- * @param message A message to include in the exception if it is thrown.
- */
- private void enforceCallingPermissionOnUserId(@UserIdInt int userId, String message) {
- if (Binder.getCallingUserHandle().getIdentifier() != userId) {
- mContext.enforceCallingOrSelfPermission(
- Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
- }
- }
-
- // ---------------------------------------------
- // USER LIFECYCLE CALLBACKS
- // ---------------------------------------------
-
- boolean isAbleToServeUser(int userId) {
- return getUserServices().get(UserHandle.USER_SYSTEM) != null
- && getUserServices().get(userId) != null;
- }
-
- /**
- * Returns a list of users currently unlocked that have a {@link UserBackupManagerService}
- * registered.
- *
- * Warning: Do NOT modify returned object as it's used inside.
- *
- * TODO: Return a copy or only expose read-only information through other means.
- */
- @VisibleForTesting
- public SparseArray<UserBackupManagerService> getUserServices() {
- return mServiceUsers;
- }
-
- /**
* Returns the {@link UserBackupManagerService} instance for the specified user {@code userId}.
* If the user is not registered with the service (either the user is locked or not eligible for
* the backup service) then return {@code null}.
@@ -132,12 +88,7 @@
@VisibleForTesting
UserBackupManagerService getServiceForUserIfCallerHasPermission(
@UserIdInt int userId, String caller) {
- enforceCallingPermissionOnUserId(userId, caller);
- UserBackupManagerService userBackupManagerService = mServiceUsers.get(userId);
- if (userBackupManagerService == null) {
- Slog.w(TAG, "Called " + caller + " for unknown user: " + userId);
- }
- return userBackupManagerService;
+ return mTrampoline.getServiceForUserIfCallerHasPermission(userId, caller);
}
/*
@@ -148,326 +99,6 @@
// TODO (b/118520567): Stop hardcoding system user when we pass in user id as a parameter
// ---------------------------------------------
- // BACKUP AGENT OPERATIONS
- // ---------------------------------------------
-
- /**
- * An app's backup agent calls this method to let the service know that there's new data to
- * backup for their app {@code packageName}. Only used for apps participating in key-value
- * backup.
- */
- public void dataChanged(@UserIdInt int userId, String packageName) {
- UserBackupManagerService userBackupManagerService =
- getServiceForUserIfCallerHasPermission(userId, "dataChanged()");
-
- if (userBackupManagerService != null) {
- userBackupManagerService.dataChanged(packageName);
- }
- }
-
- /**
- * Callback: a requested backup agent has been instantiated. This should only be called from the
- * {@link ActivityManager}.
- */
- public void agentConnected(@UserIdInt int userId, String packageName, IBinder agentBinder) {
- UserBackupManagerService userBackupManagerService =
- getServiceForUserIfCallerHasPermission(userId, "agentConnected()");
-
- if (userBackupManagerService != null) {
- userBackupManagerService.agentConnected(packageName, agentBinder);
- }
- }
-
- /**
- * Callback: a backup agent has failed to come up, or has unexpectedly quit. This should only be
- * called from the {@link ActivityManager}.
- */
- public void agentDisconnected(@UserIdInt int userId, String packageName) {
- UserBackupManagerService userBackupManagerService =
- getServiceForUserIfCallerHasPermission(userId, "agentDisconnected()");
-
- if (userBackupManagerService != null) {
- userBackupManagerService.agentDisconnected(packageName);
- }
- }
-
- /**
- * Used by a currently-active backup agent to notify the service that it has completed its given
- * outstanding asynchronous backup/restore operation.
- */
- public void opComplete(@UserIdInt int userId, int token, long result) {
- UserBackupManagerService userBackupManagerService =
- getServiceForUserIfCallerHasPermission(userId, "opComplete()");
-
- if (userBackupManagerService != null) {
- userBackupManagerService.opComplete(token, result);
- }
- }
-
- // ---------------------------------------------
- // TRANSPORT OPERATIONS
- // ---------------------------------------------
-
- /** Run an initialize operation for the given transports {@code transportNames}. */
- public void initializeTransports(
- @UserIdInt int userId, String[] transportNames, IBackupObserver observer) {
- UserBackupManagerService userBackupManagerService =
- getServiceForUserIfCallerHasPermission(userId, "initializeTransports()");
-
- if (userBackupManagerService != null) {
- userBackupManagerService.initializeTransports(transportNames, observer);
- }
- }
-
- /**
- * Clear the given package {@code packageName}'s backup data from the transport {@code
- * transportName}.
- */
- public void clearBackupData(@UserIdInt int userId, String transportName, String packageName) {
- UserBackupManagerService userBackupManagerService =
- getServiceForUserIfCallerHasPermission(userId, "clearBackupData()");
-
- if (userBackupManagerService != null) {
- userBackupManagerService.clearBackupData(transportName, packageName);
- }
- }
-
- /** Return the name of the currently active transport. */
- @Nullable
- public String getCurrentTransport(@UserIdInt int userId) {
- UserBackupManagerService userBackupManagerService =
- getServiceForUserIfCallerHasPermission(userId, "getCurrentTransport()");
-
- return userBackupManagerService == null
- ? null
- : userBackupManagerService.getCurrentTransport();
- }
-
- /**
- * Returns the {@link ComponentName} of the host service of the selected transport or {@code
- * null} if no transport selected or if the transport selected is not registered.
- */
- @Nullable
- public ComponentName getCurrentTransportComponent(@UserIdInt int userId) {
- UserBackupManagerService userBackupManagerService =
- getServiceForUserIfCallerHasPermission(userId, "getCurrentTransportComponent()");
-
- return userBackupManagerService == null
- ? null
- : userBackupManagerService.getCurrentTransportComponent();
- }
-
- /** Report all known, available backup transports by name. */
- @Nullable
- public String[] listAllTransports(@UserIdInt int userId) {
- UserBackupManagerService userBackupManagerService =
- getServiceForUserIfCallerHasPermission(userId, "listAllTransports()");
-
- return userBackupManagerService == null
- ? null
- : userBackupManagerService.listAllTransports();
- }
-
- /** Report all known, available backup transports by {@link ComponentName}. */
- @Nullable
- public ComponentName[] listAllTransportComponents(@UserIdInt int userId) {
- UserBackupManagerService userBackupManagerService =
- getServiceForUserIfCallerHasPermission(userId, "listAllTransportComponents()");
-
- return userBackupManagerService == null
- ? null
- : userBackupManagerService.listAllTransportComponents();
- }
-
- /**
- * Update the attributes of the transport identified by {@code transportComponent}. If the
- * specified transport has not been bound at least once (for registration), this call will be
- * ignored. Only the host process of the transport can change its description, otherwise a
- * {@link SecurityException} will be thrown.
- *
- * @param transportComponent The identity of the transport being described.
- * @param name A {@link String} with the new name for the transport. This is NOT for
- * identification. MUST NOT be {@code null}.
- * @param configurationIntent An {@link Intent} that can be passed to {@link
- * Context#startActivity} in order to launch the transport's configuration UI. It may be
- * {@code null} if the transport does not offer any user-facing configuration UI.
- * @param currentDestinationString A {@link String} describing the destination to which the
- * transport is currently sending data. MUST NOT be {@code null}.
- * @param dataManagementIntent An {@link Intent} that can be passed to {@link
- * Context#startActivity} in order to launch the transport's data-management UI. It may be
- * {@code null} if the transport does not offer any user-facing data management UI.
- * @param dataManagementLabel A {@link CharSequence} to be used as the label for the transport's
- * data management affordance. This MUST be {@code null} when dataManagementIntent is {@code
- * null} and MUST NOT be {@code null} when dataManagementIntent is not {@code null}.
- * @throws SecurityException If the UID of the calling process differs from the package UID of
- * {@code transportComponent} or if the caller does NOT have BACKUP permission.
- */
- public void updateTransportAttributes(
- @UserIdInt int userId,
- ComponentName transportComponent,
- String name,
- @Nullable Intent configurationIntent,
- String currentDestinationString,
- @Nullable Intent dataManagementIntent,
- CharSequence dataManagementLabel) {
- UserBackupManagerService userBackupManagerService =
- getServiceForUserIfCallerHasPermission(userId, "updateTransportAttributes()");
-
- if (userBackupManagerService != null) {
- userBackupManagerService.updateTransportAttributes(
- transportComponent,
- name,
- configurationIntent,
- currentDestinationString,
- dataManagementIntent,
- dataManagementLabel);
- }
- }
-
- /**
- * Selects transport {@code transportName} and returns the previously selected transport.
- *
- * @deprecated Use {@link #selectBackupTransportAsync(ComponentName,
- * ISelectBackupTransportCallback)} instead.
- */
- @Deprecated
- @Nullable
- public String selectBackupTransport(@UserIdInt int userId, String transportName) {
- UserBackupManagerService userBackupManagerService =
- getServiceForUserIfCallerHasPermission(userId, "selectBackupTransport()");
-
- return userBackupManagerService == null
- ? null
- : userBackupManagerService.selectBackupTransport(transportName);
- }
-
- /**
- * Selects transport {@code transportComponent} asynchronously and notifies {@code listener}
- * with the result upon completion.
- */
- public void selectBackupTransportAsync(
- @UserIdInt int userId,
- ComponentName transportComponent,
- ISelectBackupTransportCallback listener) {
- UserBackupManagerService userBackupManagerService =
- getServiceForUserIfCallerHasPermission(userId, "selectBackupTransportAsync()");
-
- if (userBackupManagerService != null) {
- userBackupManagerService.selectBackupTransportAsync(transportComponent, listener);
- }
- }
-
- /**
- * Supply the configuration intent for the given transport. If the name is not one of the
- * available transports, or if the transport does not supply any configuration UI, the method
- * returns {@code null}.
- */
- @Nullable
- public Intent getConfigurationIntent(@UserIdInt int userId, String transportName) {
- UserBackupManagerService userBackupManagerService =
- getServiceForUserIfCallerHasPermission(userId, "getConfigurationIntent()");
-
- return userBackupManagerService == null
- ? null
- : userBackupManagerService.getConfigurationIntent(transportName);
- }
-
- /**
- * Sets the ancestral work profile for the calling user.
- *
- * <p> The ancestral work profile corresponds to the profile that was used to restore to the
- * callers profile.
- */
- public void setAncestralSerialNumber(long ancestralSerialNumber) {
- UserBackupManagerService userBackupManagerService =
- getServiceForUserIfCallerHasPermission(
- Binder.getCallingUserHandle().getIdentifier(),
- "setAncestralSerialNumber()");
-
- if (userBackupManagerService != null) {
- userBackupManagerService.setAncestralSerialNumber(ancestralSerialNumber);
- }
- }
-
- /**
- * Returns a {@link UserHandle} for the user that has {@code ancestralSerialNumber} as the
- * serial number of the its ancestral work profile or null if there is no {@link
- * UserBackupManagerService} associated with that user.
- *
- * <p> The ancestral work profile is set by {@link #setAncestralSerialNumber(long)}
- * and it corresponds to the profile that was used to restore to the callers profile.
- */
- @Nullable
- public UserHandle getUserForAncestralSerialNumber(long ancestralSerialNumber) {
- int callingUserId = Binder.getCallingUserHandle().getIdentifier();
- long oldId = Binder.clearCallingIdentity();
- final int[] userIds;
- try {
- userIds =
- mContext
- .getSystemService(UserManager.class)
- .getProfileIds(callingUserId, false);
- } finally {
- Binder.restoreCallingIdentity(oldId);
- }
-
- for (int userId : userIds) {
- UserBackupManagerService userBackupManagerService = mServiceUsers.get(userId);
- if (userBackupManagerService != null) {
- if (userBackupManagerService.getAncestralSerialNumber() == ancestralSerialNumber) {
- return UserHandle.of(userId);
- }
- }
- }
-
- return null;
- }
-
- /**
- * Supply the current destination string for the given transport. If the name is not one of the
- * registered transports the method will return null.
- *
- * <p>This string is used VERBATIM as the summary text of the relevant Settings item.
- *
- * @param transportName The name of the registered transport.
- * @return The current destination string or null if the transport is not registered.
- */
- @Nullable
- public String getDestinationString(@UserIdInt int userId, String transportName) {
- UserBackupManagerService userBackupManagerService =
- getServiceForUserIfCallerHasPermission(userId, "getDestinationString()");
-
- return userBackupManagerService == null
- ? null
- : userBackupManagerService.getDestinationString(transportName);
- }
-
- /** Supply the manage-data intent for the given transport. */
- @Nullable
- public Intent getDataManagementIntent(@UserIdInt int userId, String transportName) {
- UserBackupManagerService userBackupManagerService =
- getServiceForUserIfCallerHasPermission(userId, "getDataManagementIntent()");
-
- return userBackupManagerService == null
- ? null
- : userBackupManagerService.getDataManagementIntent(transportName);
- }
-
- /**
- * Supply the menu label for affordances that fire the manage-data intent for the given
- * transport.
- */
- @Nullable
- public CharSequence getDataManagementLabel(@UserIdInt int userId, String transportName) {
- UserBackupManagerService userBackupManagerService =
- getServiceForUserIfCallerHasPermission(userId, "getDataManagementLabel()");
-
- return userBackupManagerService == null
- ? null
- : userBackupManagerService.getDataManagementLabel(transportName);
- }
-
- // ---------------------------------------------
// SETTINGS OPERATIONS
// ---------------------------------------------
diff --git a/services/backup/java/com/android/server/backup/Trampoline.java b/services/backup/java/com/android/server/backup/Trampoline.java
index cd2fb03..b522c87 100644
--- a/services/backup/java/com/android/server/backup/Trampoline.java
+++ b/services/backup/java/com/android/server/backup/Trampoline.java
@@ -24,6 +24,7 @@
import android.Manifest;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.app.ActivityManager;
import android.app.admin.DevicePolicyManager;
import android.app.backup.BackupManager;
import android.app.backup.IBackupManager;
@@ -269,7 +270,8 @@
// This method should not perform any I/O (e.g. do not call isBackupActivatedForUser),
// it's used in multiple places where I/O waits would cause system lock-ups.
private boolean isUserReadyForBackup(int userId) {
- return mService.isAbleToServeUser(userId);
+ return mUserServices.get(UserHandle.USER_SYSTEM) != null
+ && mUserServices.get(userId) != null;
}
/**
@@ -501,7 +503,7 @@
@Override
public void dataChangedForUser(int userId, String packageName) throws RemoteException {
if (isUserReadyForBackup(userId)) {
- mService.dataChanged(userId, packageName);
+ dataChanged(userId, packageName);
}
}
@@ -510,11 +512,40 @@
dataChangedForUser(binderGetCallingUserId(), packageName);
}
+ /**
+ * An app's backup agent calls this method to let the service know that there's new data to
+ * backup for their app {@code packageName}. Only used for apps participating in key-value
+ * backup.
+ */
+ public void dataChanged(@UserIdInt int userId, String packageName) {
+ UserBackupManagerService userBackupManagerService =
+ getServiceForUserIfCallerHasPermission(userId, "dataChanged()");
+
+ if (userBackupManagerService != null) {
+ userBackupManagerService.dataChanged(packageName);
+ }
+ }
+
+ // ---------------------------------------------
+ // TRANSPORT OPERATIONS
+ // ---------------------------------------------
+
@Override
public void initializeTransportsForUser(
int userId, String[] transportNames, IBackupObserver observer) throws RemoteException {
if (isUserReadyForBackup(userId)) {
- mService.initializeTransports(userId, transportNames, observer);
+ initializeTransports(userId, transportNames, observer);
+ }
+ }
+
+ /** Run an initialize operation for the given transports {@code transportNames}. */
+ public void initializeTransports(
+ @UserIdInt int userId, String[] transportNames, IBackupObserver observer) {
+ UserBackupManagerService userBackupManagerService =
+ getServiceForUserIfCallerHasPermission(userId, "initializeTransports()");
+
+ if (userBackupManagerService != null) {
+ userBackupManagerService.initializeTransports(transportNames, observer);
}
}
@@ -522,7 +553,20 @@
public void clearBackupDataForUser(int userId, String transportName, String packageName)
throws RemoteException {
if (isUserReadyForBackup(userId)) {
- mService.clearBackupData(userId, transportName, packageName);
+ clearBackupData(userId, transportName, packageName);
+ }
+ }
+
+ /**
+ * Clear the given package {@code packageName}'s backup data from the transport {@code
+ * transportName}.
+ */
+ public void clearBackupData(@UserIdInt int userId, String transportName, String packageName) {
+ UserBackupManagerService userBackupManagerService =
+ getServiceForUserIfCallerHasPermission(userId, "clearBackupData()");
+
+ if (userBackupManagerService != null) {
+ userBackupManagerService.clearBackupData(transportName, packageName);
}
}
@@ -536,7 +580,7 @@
public void agentConnectedForUser(int userId, String packageName, IBinder agent)
throws RemoteException {
if (isUserReadyForBackup(userId)) {
- mService.agentConnected(userId, packageName, agent);
+ agentConnected(userId, packageName, agent);
}
}
@@ -545,10 +589,23 @@
agentConnectedForUser(binderGetCallingUserId(), packageName, agent);
}
+ /**
+ * Callback: a requested backup agent has been instantiated. This should only be called from the
+ * {@link ActivityManager}.
+ */
+ public void agentConnected(@UserIdInt int userId, String packageName, IBinder agentBinder) {
+ UserBackupManagerService userBackupManagerService =
+ getServiceForUserIfCallerHasPermission(userId, "agentConnected()");
+
+ if (userBackupManagerService != null) {
+ userBackupManagerService.agentConnected(packageName, agentBinder);
+ }
+ }
+
@Override
public void agentDisconnectedForUser(int userId, String packageName) throws RemoteException {
if (isUserReadyForBackup(userId)) {
- mService.agentDisconnected(userId, packageName);
+ agentDisconnected(userId, packageName);
}
}
@@ -557,6 +614,19 @@
agentDisconnectedForUser(binderGetCallingUserId(), packageName);
}
+ /**
+ * Callback: a backup agent has failed to come up, or has unexpectedly quit. This should only be
+ * called from the {@link ActivityManager}.
+ */
+ public void agentDisconnected(@UserIdInt int userId, String packageName) {
+ UserBackupManagerService userBackupManagerService =
+ getServiceForUserIfCallerHasPermission(userId, "agentDisconnected()");
+
+ if (userBackupManagerService != null) {
+ userBackupManagerService.agentDisconnected(packageName);
+ }
+ }
+
@Override
public void restoreAtInstallForUser(int userId, String packageName, int token)
throws RemoteException {
@@ -680,7 +750,7 @@
@Override
public String getCurrentTransportForUser(int userId) throws RemoteException {
- return (isUserReadyForBackup(userId)) ? mService.getCurrentTransport(userId) : null;
+ return (isUserReadyForBackup(userId)) ? getCurrentTransport(userId) : null;
}
@Override
@@ -688,6 +758,17 @@
return getCurrentTransportForUser(binderGetCallingUserId());
}
+ /** Return the name of the currently active transport. */
+ @Nullable
+ public String getCurrentTransport(@UserIdInt int userId) {
+ UserBackupManagerService userBackupManagerService =
+ getServiceForUserIfCallerHasPermission(userId, "getCurrentTransport()");
+
+ return userBackupManagerService == null
+ ? null
+ : userBackupManagerService.getCurrentTransport();
+ }
+
/**
* Returns the {@link ComponentName} of the host service of the selected transport or
* {@code null} if no transport selected or if the transport selected is not registered.
@@ -695,13 +776,37 @@
@Override
@Nullable
public ComponentName getCurrentTransportComponentForUser(int userId) {
- return (isUserReadyForBackup(userId))
- ? mService.getCurrentTransportComponent(userId) : null;
+ return (isUserReadyForBackup(userId)) ? getCurrentTransportComponent(userId) : null;
+ }
+
+ /**
+ * Returns the {@link ComponentName} of the host service of the selected transport or {@code
+ * null} if no transport selected or if the transport selected is not registered.
+ */
+ @Nullable
+ public ComponentName getCurrentTransportComponent(@UserIdInt int userId) {
+ UserBackupManagerService userBackupManagerService =
+ getServiceForUserIfCallerHasPermission(userId, "getCurrentTransportComponent()");
+
+ return userBackupManagerService == null
+ ? null
+ : userBackupManagerService.getCurrentTransportComponent();
}
@Override
public String[] listAllTransportsForUser(int userId) throws RemoteException {
- return (isUserReadyForBackup(userId)) ? mService.listAllTransports(userId) : null;
+ return (isUserReadyForBackup(userId)) ? listAllTransports(userId) : null;
+ }
+
+ /** Report all known, available backup transports by name. */
+ @Nullable
+ public String[] listAllTransports(@UserIdInt int userId) {
+ UserBackupManagerService userBackupManagerService =
+ getServiceForUserIfCallerHasPermission(userId, "listAllTransports()");
+
+ return userBackupManagerService == null
+ ? null
+ : userBackupManagerService.listAllTransports();
}
@Override
@@ -712,7 +817,18 @@
@Override
public ComponentName[] listAllTransportComponentsForUser(int userId) throws RemoteException {
return (isUserReadyForBackup(userId))
- ? mService.listAllTransportComponents(userId) : null;
+ ? listAllTransportComponents(userId) : null;
+ }
+
+ /** Report all known, available backup transports by {@link ComponentName}. */
+ @Nullable
+ public ComponentName[] listAllTransportComponents(@UserIdInt int userId) {
+ UserBackupManagerService userBackupManagerService =
+ getServiceForUserIfCallerHasPermission(userId, "listAllTransportComponents()");
+
+ return userBackupManagerService == null
+ ? null
+ : userBackupManagerService.listAllTransportComponents();
}
@Override
@@ -741,7 +857,7 @@
@Nullable Intent dataManagementIntent,
CharSequence dataManagementLabel) {
if (isUserReadyForBackup(userId)) {
- mService.updateTransportAttributes(
+ updateTransportAttributes(
userId,
transportComponent,
name,
@@ -752,11 +868,56 @@
}
}
+ /**
+ * Update the attributes of the transport identified by {@code transportComponent}. If the
+ * specified transport has not been bound at least once (for registration), this call will be
+ * ignored. Only the host process of the transport can change its description, otherwise a
+ * {@link SecurityException} will be thrown.
+ *
+ * @param transportComponent The identity of the transport being described.
+ * @param name A {@link String} with the new name for the transport. This is NOT for
+ * identification. MUST NOT be {@code null}.
+ * @param configurationIntent An {@link Intent} that can be passed to {@link
+ * Context#startActivity} in order to launch the transport's configuration UI. It may be
+ * {@code null} if the transport does not offer any user-facing configuration UI.
+ * @param currentDestinationString A {@link String} describing the destination to which the
+ * transport is currently sending data. MUST NOT be {@code null}.
+ * @param dataManagementIntent An {@link Intent} that can be passed to {@link
+ * Context#startActivity} in order to launch the transport's data-management UI. It may be
+ * {@code null} if the transport does not offer any user-facing data management UI.
+ * @param dataManagementLabel A {@link CharSequence} to be used as the label for the transport's
+ * data management affordance. This MUST be {@code null} when dataManagementIntent is {@code
+ * null} and MUST NOT be {@code null} when dataManagementIntent is not {@code null}.
+ * @throws SecurityException If the UID of the calling process differs from the package UID of
+ * {@code transportComponent} or if the caller does NOT have BACKUP permission.
+ */
+ public void updateTransportAttributes(
+ @UserIdInt int userId,
+ ComponentName transportComponent,
+ String name,
+ @Nullable Intent configurationIntent,
+ String currentDestinationString,
+ @Nullable Intent dataManagementIntent,
+ CharSequence dataManagementLabel) {
+ UserBackupManagerService userBackupManagerService =
+ getServiceForUserIfCallerHasPermission(userId, "updateTransportAttributes()");
+
+ if (userBackupManagerService != null) {
+ userBackupManagerService.updateTransportAttributes(
+ transportComponent,
+ name,
+ configurationIntent,
+ currentDestinationString,
+ dataManagementIntent,
+ dataManagementLabel);
+ }
+ }
+
@Override
public String selectBackupTransportForUser(int userId, String transport)
throws RemoteException {
return (isUserReadyForBackup(userId))
- ? mService.selectBackupTransport(userId, transport) : null;
+ ? selectBackupTransport(userId, transport) : null;
}
@Override
@@ -764,11 +925,28 @@
return selectBackupTransportForUser(binderGetCallingUserId(), transport);
}
+ /**
+ * Selects transport {@code transportName} and returns the previously selected transport.
+ *
+ * @deprecated Use {@link #selectBackupTransportAsync(ComponentName,
+ * ISelectBackupTransportCallback)} instead.
+ */
+ @Deprecated
+ @Nullable
+ public String selectBackupTransport(@UserIdInt int userId, String transportName) {
+ UserBackupManagerService userBackupManagerService =
+ getServiceForUserIfCallerHasPermission(userId, "selectBackupTransport()");
+
+ return userBackupManagerService == null
+ ? null
+ : userBackupManagerService.selectBackupTransport(transportName);
+ }
+
@Override
public void selectBackupTransportAsyncForUser(int userId, ComponentName transport,
ISelectBackupTransportCallback listener) throws RemoteException {
if (isUserReadyForBackup(userId)) {
- mService.selectBackupTransportAsync(userId, transport, listener);
+ selectBackupTransportAsync(userId, transport, listener);
} else {
if (listener != null) {
try {
@@ -780,10 +958,26 @@
}
}
+ /**
+ * Selects transport {@code transportComponent} asynchronously and notifies {@code listener}
+ * with the result upon completion.
+ */
+ public void selectBackupTransportAsync(
+ @UserIdInt int userId,
+ ComponentName transportComponent,
+ ISelectBackupTransportCallback listener) {
+ UserBackupManagerService userBackupManagerService =
+ getServiceForUserIfCallerHasPermission(userId, "selectBackupTransportAsync()");
+
+ if (userBackupManagerService != null) {
+ userBackupManagerService.selectBackupTransportAsync(transportComponent, listener);
+ }
+ }
+
@Override
public Intent getConfigurationIntentForUser(int userId, String transport)
throws RemoteException {
- return isUserReadyForBackup(userId) ? mService.getConfigurationIntent(userId, transport)
+ return isUserReadyForBackup(userId) ? getConfigurationIntent(userId, transport)
: null;
}
@@ -793,9 +987,24 @@
return getConfigurationIntentForUser(binderGetCallingUserId(), transport);
}
+ /**
+ * Supply the configuration intent for the given transport. If the name is not one of the
+ * available transports, or if the transport does not supply any configuration UI, the method
+ * returns {@code null}.
+ */
+ @Nullable
+ public Intent getConfigurationIntent(@UserIdInt int userId, String transportName) {
+ UserBackupManagerService userBackupManagerService =
+ getServiceForUserIfCallerHasPermission(userId, "getConfigurationIntent()");
+
+ return userBackupManagerService == null
+ ? null
+ : userBackupManagerService.getConfigurationIntent(transportName);
+ }
+
@Override
public String getDestinationStringForUser(int userId, String transport) throws RemoteException {
- return isUserReadyForBackup(userId) ? mService.getDestinationString(userId, transport)
+ return isUserReadyForBackup(userId) ? getDestinationString(userId, transport)
: null;
}
@@ -804,11 +1013,30 @@
return getDestinationStringForUser(binderGetCallingUserId(), transport);
}
+ /**
+ * Supply the current destination string for the given transport. If the name is not one of the
+ * registered transports the method will return null.
+ *
+ * <p>This string is used VERBATIM as the summary text of the relevant Settings item.
+ *
+ * @param transportName The name of the registered transport.
+ * @return The current destination string or null if the transport is not registered.
+ */
+ @Nullable
+ public String getDestinationString(@UserIdInt int userId, String transportName) {
+ UserBackupManagerService userBackupManagerService =
+ getServiceForUserIfCallerHasPermission(userId, "getDestinationString()");
+
+ return userBackupManagerService == null
+ ? null
+ : userBackupManagerService.getDestinationString(transportName);
+ }
+
@Override
public Intent getDataManagementIntentForUser(int userId, String transport)
throws RemoteException {
return isUserReadyForBackup(userId)
- ? mService.getDataManagementIntent(userId, transport) : null;
+ ? getDataManagementIntent(userId, transport) : null;
}
@Override
@@ -817,13 +1045,38 @@
return getDataManagementIntentForUser(binderGetCallingUserId(), transport);
}
+ /** Supply the manage-data intent for the given transport. */
+ @Nullable
+ public Intent getDataManagementIntent(@UserIdInt int userId, String transportName) {
+ UserBackupManagerService userBackupManagerService =
+ getServiceForUserIfCallerHasPermission(userId, "getDataManagementIntent()");
+
+ return userBackupManagerService == null
+ ? null
+ : userBackupManagerService.getDataManagementIntent(transportName);
+ }
+
@Override
public CharSequence getDataManagementLabelForUser(int userId, String transport)
throws RemoteException {
- return isUserReadyForBackup(userId) ? mService.getDataManagementLabel(userId, transport)
+ return isUserReadyForBackup(userId) ? getDataManagementLabel(userId, transport)
: null;
}
+ /**
+ * Supply the menu label for affordances that fire the manage-data intent for the given
+ * transport.
+ */
+ @Nullable
+ public CharSequence getDataManagementLabel(@UserIdInt int userId, String transportName) {
+ UserBackupManagerService userBackupManagerService =
+ getServiceForUserIfCallerHasPermission(userId, "getDataManagementLabel()");
+
+ return userBackupManagerService == null
+ ? null
+ : userBackupManagerService.getDataManagementLabel(transportName);
+ }
+
@Override
public IRestoreSession beginRestoreSessionForUser(
int userId, String packageName, String transportID) throws RemoteException {
@@ -834,7 +1087,7 @@
@Override
public void opCompleteForUser(int userId, int token, long result) throws RemoteException {
if (isUserReadyForBackup(userId)) {
- mService.opComplete(userId, token, result);
+ opComplete(userId, token, result);
}
}
@@ -843,6 +1096,19 @@
opCompleteForUser(binderGetCallingUserId(), token, result);
}
+ /**
+ * Used by a currently-active backup agent to notify the service that it has completed its given
+ * outstanding asynchronous backup/restore operation.
+ */
+ public void opComplete(@UserIdInt int userId, int token, long result) {
+ UserBackupManagerService userBackupManagerService =
+ getServiceForUserIfCallerHasPermission(userId, "opComplete()");
+
+ if (userBackupManagerService != null) {
+ userBackupManagerService.opComplete(token, result);
+ }
+ }
+
@Override
public long getAvailableRestoreTokenForUser(int userId, String packageName) {
return isUserReadyForBackup(userId) ? mService.getAvailableRestoreToken(userId,
@@ -889,18 +1155,62 @@
cancelBackupsForUser(binderGetCallingUserId());
}
+ /**
+ * Returns a {@link UserHandle} for the user that has {@code ancestralSerialNumber} as the
+ * serial number of the its ancestral work profile or null if there is no {@link
+ * UserBackupManagerService} associated with that user.
+ *
+ * <p> The ancestral work profile is set by {@link #setAncestralSerialNumber(long)}
+ * and it corresponds to the profile that was used to restore to the callers profile.
+ */
@Override
- @Nullable public UserHandle getUserForAncestralSerialNumber(long ancestralSerialNumber) {
+ @Nullable
+ public UserHandle getUserForAncestralSerialNumber(long ancestralSerialNumber) {
if (mGlobalDisable) {
return null;
}
- return mService.getUserForAncestralSerialNumber(ancestralSerialNumber);
+ int callingUserId = Binder.getCallingUserHandle().getIdentifier();
+ long oldId = Binder.clearCallingIdentity();
+ final int[] userIds;
+ try {
+ userIds =
+ mContext
+ .getSystemService(UserManager.class)
+ .getProfileIds(callingUserId, false);
+ } finally {
+ Binder.restoreCallingIdentity(oldId);
+ }
+
+ for (int userId : userIds) {
+ UserBackupManagerService userBackupManagerService = mUserServices.get(userId);
+ if (userBackupManagerService != null) {
+ if (userBackupManagerService.getAncestralSerialNumber() == ancestralSerialNumber) {
+ return UserHandle.of(userId);
+ }
+ }
+ }
+
+ return null;
}
+ /**
+ * Sets the ancestral work profile for the calling user.
+ *
+ * <p> The ancestral work profile corresponds to the profile that was used to restore to the
+ * callers profile.
+ */
@Override
public void setAncestralSerialNumber(long ancestralSerialNumber) {
- if (!mGlobalDisable) {
- mService.setAncestralSerialNumber(ancestralSerialNumber);
+ if (mGlobalDisable) {
+ return;
+ }
+ UserBackupManagerService userBackupManagerService =
+ getServiceForUserIfCallerHasPermission(
+ Binder.getCallingUserHandle().getIdentifier(),
+ "setAncestralSerialNumber()");
+
+ if (userBackupManagerService != null) {
+ userBackupManagerService.setAncestralSerialNumber(ancestralSerialNumber);
}
}
@@ -926,4 +1236,41 @@
mService.endFullBackup(userId);
}
}
+
+ /**
+ * Returns the {@link UserBackupManagerService} instance for the specified user {@code userId}.
+ * If the user is not registered with the service (either the user is locked or not eligible for
+ * the backup service) then return {@code null}.
+ *
+ * @param userId The id of the user to retrieve its instance of {@link
+ * 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.
+ */
+ @Nullable
+ @VisibleForTesting
+ UserBackupManagerService getServiceForUserIfCallerHasPermission(
+ @UserIdInt int userId, String caller) {
+ enforceCallingPermissionOnUserId(userId, caller);
+ UserBackupManagerService userBackupManagerService = mUserServices.get(userId);
+ if (userBackupManagerService == null) {
+ Slog.w(TAG, "Called " + caller + " for unknown user: " + userId);
+ }
+ return userBackupManagerService;
+ }
+
+ /**
+ * If {@code userId} is different from the calling user id, then the caller must hold the
+ * android.permission.INTERACT_ACROSS_USERS_FULL permission.
+ *
+ * @param userId User id on which the backup operation is being requested.
+ * @param message A message to include in the exception if it is thrown.
+ */
+ void enforceCallingPermissionOnUserId(@UserIdInt int userId, String message) {
+ if (Binder.getCallingUserHandle().getIdentifier() != userId) {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.INTERACT_ACROSS_USERS_FULL, message);
+ }
+ }
}
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 474dbfe..c838c60 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -13,7 +13,6 @@
},
srcs: [
"java/**/*.java",
- ":platformcompat_aidl",
":dumpstate_aidl",
":idmap2_aidl",
":installd_aidl",
@@ -82,11 +81,3 @@
name: "gps_debug.conf",
src: "java/com/android/server/location/gps_debug.conf",
}
-
-filegroup {
- name: "platformcompat_aidl",
- srcs: [
- "java/com/android/server/compat/IPlatformCompat.aidl",
- ],
- path: "java",
-}
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index fede487..9a97ddb 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -172,7 +172,7 @@
final LocalLog mLog = new LocalLog(TAG);
AppOpsManager mAppOps;
- DeviceIdleController.LocalService mLocalDeviceIdleController;
+ DeviceIdleInternal mLocalDeviceIdleController;
private UsageStatsManagerInternal mUsageStatsManagerInternal;
final Object mLock = new Object();
@@ -1594,7 +1594,7 @@
mConstants.start(getContext().getContentResolver());
mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
mLocalDeviceIdleController =
- LocalServices.getService(DeviceIdleController.LocalService.class);
+ LocalServices.getService(DeviceIdleInternal.class);
mUsageStatsManagerInternal =
LocalServices.getService(UsageStatsManagerInternal.class);
mUsageStatsManagerInternal.addAppIdleStateChangeListener(new AppStandbyTracker());
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index a303718..62930b0 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -1636,27 +1636,32 @@
}
}
- public class LocalService {
+ private class LocalService implements DeviceIdleInternal {
+ @Override
public void onConstraintStateChanged(IDeviceIdleConstraint constraint, boolean active) {
synchronized (DeviceIdleController.this) {
onConstraintStateChangedLocked(constraint, active);
}
}
+ @Override
public void registerDeviceIdleConstraint(IDeviceIdleConstraint constraint, String name,
@IDeviceIdleConstraint.MinimumState int minState) {
registerDeviceIdleConstraintInternal(constraint, name, minState);
}
+ @Override
public void unregisterDeviceIdleConstraint(IDeviceIdleConstraint constraint) {
unregisterDeviceIdleConstraintInternal(constraint);
}
+ @Override
public void exitIdle(String reason) {
exitIdleInternal(reason);
}
// duration in milliseconds
+ @Override
public void addPowerSaveTempWhitelistApp(int callingUid, String packageName,
long duration, int userId, boolean sync, String reason) {
addPowerSaveTempWhitelistAppInternal(callingUid, packageName, duration,
@@ -1664,26 +1669,31 @@
}
// duration in milliseconds
+ @Override
public void addPowerSaveTempWhitelistAppDirect(int uid, long duration, boolean sync,
String reason) {
addPowerSaveTempWhitelistAppDirectInternal(0, uid, duration, sync, reason);
}
// duration in milliseconds
+ @Override
public long getNotificationWhitelistDuration() {
return mConstants.NOTIFICATION_WHITELIST_DURATION;
}
+ @Override
public void setJobsActive(boolean active) {
DeviceIdleController.this.setJobsActive(active);
}
// Up-call from alarm manager.
+ @Override
public void setAlarmsActive(boolean active) {
DeviceIdleController.this.setAlarmsActive(active);
}
/** Is the app on any of the power save whitelists, whether system or user? */
+ @Override
public boolean isAppOnWhitelist(int appid) {
return DeviceIdleController.this.isAppOnWhitelistInternal(appid);
}
@@ -1694,10 +1704,12 @@
* can change when the list changes, so it needs to be re-acquired when
* {@link PowerManager#ACTION_POWER_SAVE_WHITELIST_CHANGED} is sent.
*/
+ @Override
public int[] getPowerSaveWhitelistUserAppIds() {
return DeviceIdleController.this.getPowerSaveWhitelistUserAppIds();
}
+ @Override
public int[] getPowerSaveTempWhitelistAppIds() {
return DeviceIdleController.this.getAppIdTempWhitelistInternal();
}
@@ -1767,7 +1779,8 @@
return mContext.getSystemService(SensorManager.class);
}
- ConstraintController getConstraintController(Handler handler, LocalService localService) {
+ ConstraintController getConstraintController(Handler handler,
+ DeviceIdleInternal localService) {
if (mContext.getPackageManager()
.hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY)) {
return new TvConstraintController(mContext, handler);
@@ -1884,7 +1897,7 @@
mBinderService = new BinderService();
publishBinderService(Context.DEVICE_IDLE_CONTROLLER, mBinderService);
- publishLocalService(LocalService.class, new LocalService());
+ publishLocalService(DeviceIdleInternal.class, new LocalService());
}
@Override
diff --git a/services/core/java/com/android/server/DeviceIdleInternal.java b/services/core/java/com/android/server/DeviceIdleInternal.java
new file mode 100644
index 0000000..1273249
--- /dev/null
+++ b/services/core/java/com/android/server/DeviceIdleInternal.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server;
+
+import com.android.server.deviceidle.IDeviceIdleConstraint;
+
+public interface DeviceIdleInternal {
+ void onConstraintStateChanged(IDeviceIdleConstraint constraint, boolean active);
+
+ void registerDeviceIdleConstraint(IDeviceIdleConstraint constraint, String name,
+ @IDeviceIdleConstraint.MinimumState int minState);
+
+ void unregisterDeviceIdleConstraint(IDeviceIdleConstraint constraint);
+
+ void exitIdle(String reason);
+
+ // duration in milliseconds
+ void addPowerSaveTempWhitelistApp(int callingUid, String packageName,
+ long duration, int userId, boolean sync, String reason);
+
+ // duration in milliseconds
+ void addPowerSaveTempWhitelistAppDirect(int uid, long duration, boolean sync,
+ String reason);
+
+ // duration in milliseconds
+ long getNotificationWhitelistDuration();
+
+ void setJobsActive(boolean active);
+
+ // Up-call from alarm manager.
+ void setAlarmsActive(boolean active);
+
+ boolean isAppOnWhitelist(int appid);
+
+ int[] getPowerSaveWhitelistUserAppIds();
+
+ int[] getPowerSaveTempWhitelistAppIds();
+}
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index dee89e5..ea3dd3d 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -25,7 +25,7 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
-import android.net.NetworkStackClient;
+import android.net.ConnectivityModuleConnector;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
@@ -116,7 +116,7 @@
// File containing the XML data of monitored packages /data/system/package-watchdog.xml
private final AtomicFile mPolicyFile;
private final ExplicitHealthCheckController mHealthCheckController;
- private final NetworkStackClient mNetworkStackClient;
+ private final ConnectivityModuleConnector mConnectivityModuleConnector;
@GuardedBy("mLock")
private boolean mIsPackagesReady;
// Flag to control whether explicit health checks are supported or not
@@ -138,7 +138,7 @@
"package-watchdog.xml")),
new Handler(Looper.myLooper()), BackgroundThread.getHandler(),
new ExplicitHealthCheckController(context),
- NetworkStackClient.getInstance());
+ ConnectivityModuleConnector.getInstance());
}
/**
@@ -147,13 +147,13 @@
@VisibleForTesting
PackageWatchdog(Context context, AtomicFile policyFile, Handler shortTaskHandler,
Handler longTaskHandler, ExplicitHealthCheckController controller,
- NetworkStackClient networkStackClient) {
+ ConnectivityModuleConnector connectivityModuleConnector) {
mContext = context;
mPolicyFile = policyFile;
mShortTaskHandler = shortTaskHandler;
mLongTaskHandler = longTaskHandler;
mHealthCheckController = controller;
- mNetworkStackClient = networkStackClient;
+ mConnectivityModuleConnector = connectivityModuleConnector;
loadFromFile();
}
@@ -179,7 +179,7 @@
() -> syncRequestsAsync());
setPropertyChangedListenerLocked();
updateConfigs();
- registerNetworkStackHealthListener();
+ registerConnectivityModuleHealthListener();
}
}
@@ -743,11 +743,11 @@
}
}
- private void registerNetworkStackHealthListener() {
+ private void registerConnectivityModuleHealthListener() {
// TODO: have an internal method to trigger a rollback by reporting high severity errors,
// and rely on ActivityManager to inform the watchdog of severe network stack crashes
// instead of having this listener in parallel.
- mNetworkStackClient.registerHealthListener(
+ mConnectivityModuleConnector.registerHealthListener(
packageName -> {
final VersionedPackage pkg = getVersionedPackage(packageName);
if (pkg == null) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 6965519..19c818f 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -330,7 +330,7 @@
import com.android.internal.util.function.TriFunction;
import com.android.server.AlarmManagerInternal;
import com.android.server.AttributeCache;
-import com.android.server.DeviceIdleController;
+import com.android.server.DeviceIdleInternal;
import com.android.server.DisplayThread;
import com.android.server.IntentResolver;
import com.android.server.IoThread;
@@ -1135,7 +1135,7 @@
/**
* Access to DeviceIdleController service.
*/
- DeviceIdleController.LocalService mLocalDeviceIdleController;
+ DeviceIdleInternal mLocalDeviceIdleController;
/**
* Power-save whitelisted app-ids (not including except-idle-whitelisted ones).
@@ -9003,8 +9003,8 @@
}
t.traceBegin("controllersReady");
- mLocalDeviceIdleController
- = LocalServices.getService(DeviceIdleController.LocalService.class);
+ mLocalDeviceIdleController =
+ LocalServices.getService(DeviceIdleInternal.class);
mActivityTaskManager.onSystemReady();
// Make sure we have the current profile info, since it is needed for security checks.
mUserController.onSystemReady();
diff --git a/services/core/java/com/android/server/appop/HistoricalRegistry.java b/services/core/java/com/android/server/appop/HistoricalRegistry.java
index 9cf342c..ace0a7d 100644
--- a/services/core/java/com/android/server/appop/HistoricalRegistry.java
+++ b/services/core/java/com/android/server/appop/HistoricalRegistry.java
@@ -291,7 +291,7 @@
makeRelativeToEpochStart(currentOps, nowMillis);
currentOps.accept(visitor);
- if(isPersistenceInitializedMLocked()) {
+ if (!isPersistenceInitializedMLocked()) {
Slog.e(LOG_TAG, "Interaction before persistence initialized");
return;
}
@@ -457,7 +457,7 @@
// it is a part of the persistence initialization process.
boolean resampleHistory = false;
Slog.i(LOG_TAG, "New history parameters: mode:"
- + AppOpsManager.historicalModeToString(mMode) + " baseSnapshotInterval:"
+ + AppOpsManager.historicalModeToString(mode) + " baseSnapshotInterval:"
+ baseSnapshotInterval + " intervalCompressionMultiplier:"
+ intervalCompressionMultiplier);
if (mMode != mode) {
@@ -1066,7 +1066,7 @@
normalizeSnapshotForSlotDuration(persistedOps, slotDurationMillis);
writeHistoricalOpsDLocked(persistedOps, intervalOverflowMillis, newFile);
if (DEBUG) {
- Slog.i(LOG_TAG, "Persisted at depth: " + depth
+ Slog.i(LOG_TAG, "Persisted at depth: " + depth + " file: " + newFile
+ " ops:\n" + opsToDebugString(persistedOps));
enforceOpsWellFormed(persistedOps);
}
@@ -1160,7 +1160,7 @@
}
if (DEBUG) {
if (allOps != null) {
- Slog.i(LOG_TAG, "Read from file: " + file + "ops:\n"
+ Slog.i(LOG_TAG, "Read from file: " + file + " ops:\n"
+ opsToDebugString(allOps));
enforceOpsWellFormed(allOps);
}
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index 3eea194..27050fa 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -16,6 +16,7 @@
package com.android.server.compat;
+import android.compat.IPlatformCompat;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.util.Slog;
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index e7a8b13..fb94907 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -95,7 +95,7 @@
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.util.ArrayUtils;
import com.android.server.ConnectivityService;
-import com.android.server.DeviceIdleController;
+import com.android.server.DeviceIdleInternal;
import com.android.server.LocalServices;
import com.android.server.net.BaseNetworkObserver;
@@ -616,8 +616,8 @@
// a short time, so we can bootstrap the VPN service.
final long oldId = Binder.clearCallingIdentity();
try {
- DeviceIdleController.LocalService idleController =
- LocalServices.getService(DeviceIdleController.LocalService.class);
+ DeviceIdleInternal idleController =
+ LocalServices.getService(DeviceIdleInternal.class);
idleController.addPowerSaveTempWhitelistApp(Process.myUid(), alwaysOnPackage,
VPN_LAUNCH_IDLE_WHITELIST_DURATION_MS, mUserHandle, false, "vpn");
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index f6c49ed..e7f537b 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -102,7 +102,7 @@
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.function.QuadConsumer;
-import com.android.server.DeviceIdleController;
+import com.android.server.DeviceIdleInternal;
import com.android.server.LocalServices;
import com.android.server.SystemService;
import com.android.server.accounts.AccountManagerService;
@@ -1634,8 +1634,8 @@
if (syncOperation.syncExemptionFlag
== ContentResolver.SYNC_EXEMPTION_PROMOTE_BUCKET_WITH_TEMP) {
- DeviceIdleController.LocalService dic =
- LocalServices.getService(DeviceIdleController.LocalService.class);
+ DeviceIdleInternal dic =
+ LocalServices.getService(DeviceIdleInternal.class);
if (dic != null) {
dic.addPowerSaveTempWhitelistApp(Process.SYSTEM_UID,
syncOperation.owningPackage,
diff --git a/services/core/java/com/android/server/deviceidle/BluetoothConstraint.java b/services/core/java/com/android/server/deviceidle/BluetoothConstraint.java
index cc319bf..731d899 100644
--- a/services/core/java/com/android/server/deviceidle/BluetoothConstraint.java
+++ b/services/core/java/com/android/server/deviceidle/BluetoothConstraint.java
@@ -29,7 +29,7 @@
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.DeviceIdleController;
+import com.android.server.DeviceIdleInternal;
/**
* Track whether there are any active Bluetooth devices connected.
@@ -40,14 +40,14 @@
private final Context mContext;
private final Handler mHandler;
- private final DeviceIdleController.LocalService mLocalService;
+ private final DeviceIdleInternal mLocalService;
private final BluetoothManager mBluetoothManager;
private volatile boolean mConnected = true;
private volatile boolean mMonitoring = false;
public BluetoothConstraint(
- Context context, Handler handler, DeviceIdleController.LocalService localService) {
+ Context context, Handler handler, DeviceIdleInternal localService) {
mContext = context;
mHandler = handler;
mLocalService = localService;
diff --git a/services/core/java/com/android/server/deviceidle/TvConstraintController.java b/services/core/java/com/android/server/deviceidle/TvConstraintController.java
index 2d472de6..7f0a271 100644
--- a/services/core/java/com/android/server/deviceidle/TvConstraintController.java
+++ b/services/core/java/com/android/server/deviceidle/TvConstraintController.java
@@ -21,7 +21,7 @@
import android.content.pm.PackageManager;
import android.os.Handler;
-import com.android.server.DeviceIdleController;
+import com.android.server.DeviceIdleInternal;
import com.android.server.LocalServices;
/**
@@ -33,7 +33,7 @@
public class TvConstraintController implements ConstraintController {
private final Context mContext;
private final Handler mHandler;
- private final DeviceIdleController.LocalService mDeviceIdleService;
+ private final DeviceIdleInternal mDeviceIdleService;
@Nullable
private final BluetoothConstraint mBluetoothConstraint;
@@ -41,7 +41,7 @@
public TvConstraintController(Context context, Handler handler) {
mContext = context;
mHandler = handler;
- mDeviceIdleService = LocalServices.getService(DeviceIdleController.LocalService.class);
+ mDeviceIdleService = LocalServices.getService(DeviceIdleInternal.class);
final PackageManager pm = context.getPackageManager();
mBluetoothConstraint = pm.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH)
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index f1f6d50..f38f2f9 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -106,6 +106,7 @@
import com.android.internal.notification.SystemNotificationChannels;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.DumpUtils;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.internal.widget.ICheckCredentialProgressCallback;
import com.android.internal.widget.ILockSettings;
@@ -137,8 +138,10 @@
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
+import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
@@ -169,6 +172,8 @@
private static final int PROFILE_KEY_IV_SIZE = 12;
private static final String SEPARATE_PROFILE_CHALLENGE_KEY = "lockscreen.profilechallenge";
private static final int SYNTHETIC_PASSWORD_ENABLED_BY_DEFAULT = 1;
+ private static final String PREV_SYNTHETIC_PASSWORD_HANDLE_KEY = "prev-sp-handle";
+ private static final String SYNTHETIC_PASSWORD_UPDATE_TIME_KEY = "sp-handle-ts";
// No challenge provided
private static final int CHALLENGE_NONE = 0;
@@ -357,7 +362,7 @@
setLong(LockPatternUtils.PASSWORD_TYPE_KEY, quality, managedUserId);
tieProfileLockToParent(managedUserId, newPassword);
Arrays.fill(newPassword, (byte) 0);
- } catch (NoSuchAlgorithmException | RemoteException e) {
+ } catch (NoSuchAlgorithmException e) {
Slog.e(TAG, "Fail to tie managed profile", e);
// Nothing client can do to fix this issue, so we do not throw exception out
}
@@ -604,15 +609,11 @@
if (ks.state(userId) == KeyStore.State.LOCKED
&& tiedManagedProfileReadyToUnlock(mUserManager.getUserInfo(userId))) {
Slog.i(TAG, "Managed profile got unlocked, will unlock its keystore");
- try {
- // If boot took too long and the password in vold got expired, parent keystore will
- // be still locked, we ignore this case since the user will be prompted to unlock
- // the device after boot.
- unlockChildProfile(userId, true /* ignoreUserNotAuthenticated */,
- CHALLENGE_NONE, 0 /* challenge */, null /* resetLockouts */);
- } catch (RemoteException e) {
- Slog.e(TAG, "Failed to unlock child profile");
- }
+ // If boot took too long and the password in vold got expired, parent keystore will
+ // be still locked, we ignore this case since the user will be prompted to unlock
+ // the device after boot.
+ unlockChildProfile(userId, true /* ignoreUserNotAuthenticated */,
+ CHALLENGE_NONE, 0 /* challenge */, null /* resetLockouts */);
}
}
@@ -648,20 +649,16 @@
return;
}
- try {
- final long handle = getSyntheticPasswordHandleLocked(userId);
- final byte[] noCredential = null;
- AuthenticationResult result =
- mSpManager.unwrapPasswordBasedSyntheticPassword(
- getGateKeeperService(), handle, noCredential, userId, null);
- if (result.authToken != null) {
- Slog.i(TAG, "Retrieved auth token for user " + userId);
- onAuthTokenKnownForUser(userId, result.authToken);
- } else {
- Slog.e(TAG, "Auth token not available for user " + userId);
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "Failure retrieving auth token", e);
+ final long handle = getSyntheticPasswordHandleLocked(userId);
+ final byte[] noCredential = null;
+ AuthenticationResult result =
+ mSpManager.unwrapPasswordBasedSyntheticPassword(
+ getGateKeeperService(), handle, noCredential, userId, null);
+ if (result.authToken != null) {
+ Slog.i(TAG, "Retrieved auth token for user " + userId);
+ onAuthTokenKnownForUser(userId, result.authToken);
+ } else {
+ Slog.e(TAG, "Auth token not available for user " + userId);
}
}
}
@@ -698,12 +695,8 @@
}
checkWritePermission(UserHandle.USER_SYSTEM);
migrateOldData();
- try {
- getGateKeeperService();
- mSpManager.initWeaverService();
- } catch (RemoteException e) {
- Slog.e(TAG, "Failure retrieving IGateKeeperService", e);
- }
+ getGateKeeperService();
+ mSpManager.initWeaverService();
// Find the AuthSecret HAL
try {
mAuthSecretService = IAuthSecret.getService();
@@ -872,16 +865,12 @@
}
private void migrateOldDataAfterSystemReady() {
- try {
- // Migrate the FRP credential to the persistent data block
- if (LockPatternUtils.frpCredentialEnabled(mContext)
- && !getBoolean("migrated_frp", false, 0)) {
- migrateFrpCredential();
- setBoolean("migrated_frp", true, 0);
- Slog.i(TAG, "Migrated migrated_frp.");
- }
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to migrateOldDataAfterSystemReady", e);
+ // Migrate the FRP credential to the persistent data block
+ if (LockPatternUtils.frpCredentialEnabled(mContext)
+ && !getBoolean("migrated_frp", false, 0)) {
+ migrateFrpCredential();
+ setBoolean("migrated_frp", true, 0);
+ Slog.i(TAG, "Migrated migrated_frp.");
}
}
@@ -891,7 +880,7 @@
* - the FRP credential is not set up
* - the credential is based on a synthetic password.
*/
- private void migrateFrpCredential() throws RemoteException {
+ private void migrateFrpCredential() {
if (mStorage.readPersistentDataBlock() != PersistentData.NONE) {
return;
}
@@ -1187,8 +1176,7 @@
private void unlockChildProfile(int profileHandle, boolean ignoreUserNotAuthenticated,
@ChallengeType int challengeType, long challenge,
- @Nullable ArrayList<PendingResetLockout> resetLockouts)
- throws RemoteException {
+ @Nullable ArrayList<PendingResetLockout> resetLockouts) {
try {
doVerifyCredential(getDecryptedPasswordForTiedProfile(profileHandle),
CREDENTIAL_TYPE_PASSWORD,
@@ -1263,14 +1251,10 @@
for (UserInfo profile : mUserManager.getProfiles(userId)) {
// Unlock managed profile with unified lock
if (tiedManagedProfileReadyToUnlock(profile)) {
- try {
- // Must pass the challenge on for resetLockout, so it's not over-written, which
- // causes LockSettingsService to revokeChallenge inappropriately.
- unlockChildProfile(profile.id, false /* ignoreUserNotAuthenticated */,
- challengeType, challenge, resetLockouts);
- } catch (RemoteException e) {
- Log.d(TAG, "Failed to unlock child profile", e);
- }
+ // Must pass the challenge on for resetLockout, so it's not over-written, which
+ // causes LockSettingsService to revokeChallenge inappropriately.
+ unlockChildProfile(profile.id, false /* ignoreUserNotAuthenticated */,
+ challengeType, challenge, resetLockouts);
}
// Now we have unlocked the parent user and attempted to unlock the profile we should
// show notifications if the profile is still locked.
@@ -1350,7 +1334,7 @@
* terminates when the user is a managed profile.
*/
private void synchronizeUnifiedWorkChallengeForProfiles(int userId,
- Map<Integer, byte[]> profilePasswordMap) throws RemoteException {
+ Map<Integer, byte[]> profilePasswordMap) {
if (mUserManager.getUserInfo(userId).isManagedProfile()) {
return;
}
@@ -1464,7 +1448,7 @@
@Override
public void setLockCredential(byte[] credential, int type,
byte[] savedCredential, int requestedQuality, int userId,
- boolean allowUntrustedChange) throws RemoteException {
+ boolean allowUntrustedChange) {
if (!mLockPatternUtils.hasSecureLockScreen()) {
throw new UnsupportedOperationException(
@@ -1490,7 +1474,7 @@
*/
private void setLockCredentialInternal(byte[] credential, @CredentialType int credentialType,
byte[] savedCredential, int requestedQuality, int userId, boolean allowUntrustedChange,
- boolean isLockTiedToParent) throws RemoteException {
+ boolean isLockTiedToParent) {
// Normalize savedCredential and credential such that empty string is always represented
// as null.
if (savedCredential == null || savedCredential.length == 0) {
@@ -1512,7 +1496,7 @@
Slog.wtf(TAG, "CredentialType is none, but credential is non-null.");
}
clearUserKeyProtection(userId);
- getGateKeeperService().clearSecureUserId(userId);
+ gateKeeperClearSecureUserId(userId);
mStorage.writeCredentialHash(CredentialHash.createEmptyHash(), userId);
setKeystorePassword(null, userId);
fixateNewestUserKeyAuth(userId);
@@ -1523,7 +1507,7 @@
return;
}
if (credential == null) {
- throw new RemoteException("Null credential with mismatched credential type");
+ throw new IllegalArgumentException("Null credential with mismatched credential type");
}
CredentialHash currentHandle = mStorage.readCredentialHash(userId);
@@ -1565,8 +1549,13 @@
CredentialHash willStore = CredentialHash.create(enrolledHandle, credentialType);
mStorage.writeCredentialHash(willStore, userId);
// push new secret and auth token to vold
- GateKeeperResponse gkResponse = getGateKeeperService()
- .verifyChallenge(userId, 0, willStore.hash, credential);
+ GateKeeperResponse gkResponse;
+ try {
+ gkResponse = getGateKeeperService().verifyChallenge(userId, 0, willStore.hash,
+ credential);
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Failed to verify current credential", e);
+ }
setUserKeyProtection(userId, credential, convertResponse(gkResponse));
fixateNewestUserKeyAuth(userId);
// Refresh the auth token
@@ -1576,8 +1565,8 @@
sendCredentialsOnChangeIfRequired(
credentialType, credential, userId, isLockTiedToParent);
} else {
- throw new RemoteException("Failed to enroll " +
- (credentialType == CREDENTIAL_TYPE_PASSWORD ? "password" : "pattern"));
+ throw new IllegalStateException(String.format("Failed to enroll %s",
+ credentialType == CREDENTIAL_TYPE_PASSWORD ? "password" : "pattern"));
}
}
@@ -1630,27 +1619,32 @@
} catch (CertificateException | UnrecoverableKeyException
| IOException | BadPaddingException | IllegalBlockSizeException | KeyStoreException
| NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException e) {
- throw new RuntimeException("Failed to encrypt key", e);
+ throw new IllegalStateException("Failed to encrypt key", e);
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try {
if (iv.length != PROFILE_KEY_IV_SIZE) {
- throw new RuntimeException("Invalid iv length: " + iv.length);
+ throw new IllegalArgumentException("Invalid iv length: " + iv.length);
}
outputStream.write(iv);
outputStream.write(encryptionResult);
} catch (IOException e) {
- throw new RuntimeException("Failed to concatenate byte arrays", e);
+ throw new IllegalStateException("Failed to concatenate byte arrays", e);
}
mStorage.writeChildProfileLock(userId, outputStream.toByteArray());
}
private byte[] enrollCredential(byte[] enrolledHandle,
- byte[] enrolledCredential, byte[] toEnroll, int userId)
- throws RemoteException {
+ byte[] enrolledCredential, byte[] toEnroll, int userId) {
checkWritePermission(userId);
- GateKeeperResponse response = getGateKeeperService().enroll(userId, enrolledHandle,
- enrolledCredential, toEnroll);
+ GateKeeperResponse response;
+ try {
+ response = getGateKeeperService().enroll(userId, enrolledHandle,
+ enrolledCredential, toEnroll);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Failed to enroll credential", e);
+ return null;
+ }
if (response == null) {
return null;
@@ -1666,34 +1660,33 @@
return hash;
}
- private void setAuthlessUserKeyProtection(int userId, byte[] key) throws RemoteException {
+ private void setAuthlessUserKeyProtection(int userId, byte[] key) {
if (DEBUG) Slog.d(TAG, "setAuthlessUserKeyProtectiond: user=" + userId);
addUserKeyAuth(userId, null, key);
}
- private void setUserKeyProtection(int userId, byte[] credential, VerifyCredentialResponse vcr)
- throws RemoteException {
+ private void setUserKeyProtection(int userId, byte[] credential, VerifyCredentialResponse vcr) {
if (DEBUG) Slog.d(TAG, "setUserKeyProtection: user=" + userId);
if (vcr == null) {
- throw new RemoteException("Null response verifying a credential we just set");
+ throw new IllegalArgumentException("Null response verifying a credential we just set");
}
if (vcr.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
- throw new RemoteException("Non-OK response verifying a credential we just set: "
+ throw new IllegalArgumentException("Non-OK response verifying a credential we just set "
+ vcr.getResponseCode());
}
byte[] token = vcr.getPayload();
if (token == null) {
- throw new RemoteException("Empty payload verifying a credential we just set");
+ throw new IllegalArgumentException("Empty payload verifying a credential we just set");
}
addUserKeyAuth(userId, token, secretFromCredential(credential));
}
- private void clearUserKeyProtection(int userId) throws RemoteException {
+ private void clearUserKeyProtection(int userId) {
if (DEBUG) Slog.d(TAG, "clearUserKeyProtection user=" + userId);
addUserKeyAuth(userId, null, null);
}
- private static byte[] secretFromCredential(byte[] credential) throws RemoteException {
+ private static byte[] secretFromCredential(byte[] credential) {
try {
MessageDigest digest = MessageDigest.getInstance("SHA-512");
// Personalize the hash
@@ -1704,7 +1697,7 @@
digest.update(credential);
return digest.digest();
} catch (NoSuchAlgorithmException e) {
- throw new RuntimeException("NoSuchAlgorithmException for SHA-512");
+ throw new IllegalStateException("NoSuchAlgorithmException for SHA-512");
}
}
@@ -1718,35 +1711,44 @@
}
/** Unlock disk encryption */
- private void unlockUserKey(int userId, byte[] token, byte[] secret) throws RemoteException {
+ private void unlockUserKey(int userId, byte[] token, byte[] secret) {
final UserInfo userInfo = mUserManager.getUserInfo(userId);
- mStorageManager.unlockUserKey(userId, userInfo.serialNumber, token, secret);
+ try {
+ mStorageManager.unlockUserKey(userId, userInfo.serialNumber, token, secret);
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Failed to unlock user key " + userId, e);
+
+ }
}
- private void addUserKeyAuth(int userId, byte[] token, byte[] secret)
- throws RemoteException {
+ private void addUserKeyAuth(int userId, byte[] token, byte[] secret) {
final UserInfo userInfo = mUserManager.getUserInfo(userId);
final long callingId = Binder.clearCallingIdentity();
try {
mStorageManager.addUserKeyAuth(userId, userInfo.serialNumber, token, secret);
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Failed to add new key to vold " + userId, e);
} finally {
Binder.restoreCallingIdentity(callingId);
}
}
- private void fixateNewestUserKeyAuth(int userId)
- throws RemoteException {
+ private void fixateNewestUserKeyAuth(int userId) {
if (DEBUG) Slog.d(TAG, "fixateNewestUserKeyAuth: user=" + userId);
final long callingId = Binder.clearCallingIdentity();
try {
mStorageManager.fixateNewestUserKeyAuth(userId);
+ } catch (RemoteException e) {
+ // OK to ignore the exception as vold would just accept both old and new
+ // keys if this call fails, and will fix itself during the next boot
+ Slog.w(TAG, "fixateNewestUserKeyAuth failed", e);
} finally {
Binder.restoreCallingIdentity(callingId);
}
}
@Override
- public void resetKeyStore(int userId) throws RemoteException {
+ public void resetKeyStore(int userId) {
checkWritePermission(userId);
if (DEBUG) Slog.v(TAG, "Reset keystore for user: " + userId);
int managedUserId = -1;
@@ -1794,14 +1796,14 @@
@Override
public VerifyCredentialResponse checkCredential(byte[] credential, int type, int userId,
- ICheckCredentialProgressCallback progressCallback) throws RemoteException {
+ ICheckCredentialProgressCallback progressCallback) {
checkPasswordReadPermission(userId);
return doVerifyCredential(credential, type, CHALLENGE_NONE, 0, userId, progressCallback);
}
@Override
public VerifyCredentialResponse verifyCredential(byte[] credential, int type, long challenge,
- int userId) throws RemoteException {
+ int userId) {
checkPasswordReadPermission(userId);
return doVerifyCredential(credential, type, CHALLENGE_FROM_CALLER, challenge, userId,
null /* progressCallback */);
@@ -1809,7 +1811,7 @@
private VerifyCredentialResponse doVerifyCredential(byte[] credential, int credentialType,
@ChallengeType int challengeType, long challenge, int userId,
- ICheckCredentialProgressCallback progressCallback) throws RemoteException {
+ ICheckCredentialProgressCallback progressCallback) {
return doVerifyCredential(credential, credentialType, challengeType, challenge, userId,
progressCallback, null /* resetLockouts */);
}
@@ -1821,7 +1823,7 @@
private VerifyCredentialResponse doVerifyCredential(byte[] credential, int credentialType,
@ChallengeType int challengeType, long challenge, int userId,
ICheckCredentialProgressCallback progressCallback,
- @Nullable ArrayList<PendingResetLockout> resetLockouts) throws RemoteException {
+ @Nullable ArrayList<PendingResetLockout> resetLockouts) {
if (credential == null || credential.length == 0) {
throw new IllegalArgumentException("Credential can't be null or empty");
}
@@ -1865,10 +1867,10 @@
@Override
public VerifyCredentialResponse verifyTiedProfileChallenge(byte[] credential, int type,
- long challenge, int userId) throws RemoteException {
+ long challenge, int userId) {
checkPasswordReadPermission(userId);
if (!isManagedProfileWithUnifiedLock(userId)) {
- throw new RemoteException("User id must be managed profile with unified lock");
+ throw new IllegalArgumentException("User id must be managed profile with unified lock");
}
final int parentProfileId = mUserManager.getProfileParent(userId).id;
// Unlock parent by using parent's challenge
@@ -1896,7 +1898,7 @@
| InvalidAlgorithmParameterException | IllegalBlockSizeException
| BadPaddingException | CertificateException | IOException e) {
Slog.e(TAG, "Failed to decrypt child profile key", e);
- throw new RemoteException("Unable to get tied profile token");
+ throw new IllegalStateException("Unable to get tied profile token");
}
}
@@ -1907,7 +1909,7 @@
*/
private VerifyCredentialResponse verifyCredential(int userId, CredentialHash storedHash,
byte[] credential, @ChallengeType int challengeType, long challenge,
- ICheckCredentialProgressCallback progressCallback) throws RemoteException {
+ ICheckCredentialProgressCallback progressCallback) {
if ((storedHash == null || storedHash.hash.length == 0)
&& (credential == null || credential.length == 0)) {
// don't need to pass empty credentials to GateKeeper
@@ -1922,8 +1924,14 @@
// of unlocking the user, so yell if calling from the main thread.
StrictMode.noteDiskRead();
- GateKeeperResponse gateKeeperResponse = getGateKeeperService()
- .verifyChallenge(userId, challenge, storedHash.hash, credential);
+ GateKeeperResponse gateKeeperResponse;
+ try {
+ gateKeeperResponse = getGateKeeperService()
+ .verifyChallenge(userId, challenge, storedHash.hash, credential);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "gatekeeper verify failed", e);
+ gateKeeperResponse = GateKeeperResponse.ERROR;
+ }
VerifyCredentialResponse response = convertResponse(gateKeeperResponse);
boolean shouldReEnroll = gateKeeperResponse.getShouldReEnroll();
@@ -1932,7 +1940,11 @@
// credential has matched
if (progressCallback != null) {
- progressCallback.onCredentialVerified();
+ try {
+ progressCallback.onCredentialVerified();
+ } catch (RemoteException e) {
+ Log.w(TAG, "progressCallback throws exception", e);
+ }
}
notifyActivePasswordMetricsAvailable(storedHash.type, credential, userId);
unlockKeystore(credential, userId);
@@ -2007,7 +2019,7 @@
}
@Override
- public boolean checkVoldPassword(int userId) throws RemoteException {
+ public boolean checkVoldPassword(int userId) {
if (!mFirstCallToVold) {
return false;
}
@@ -2030,6 +2042,9 @@
try {
password = service.getPassword();
service.clearPassword();
+ } catch (RemoteException e) {
+ Slog.w(TAG, "vold getPassword() failed", e);
+ return false;
} finally {
Binder.restoreCallingIdentity(identity);
}
@@ -2071,14 +2086,7 @@
final KeyStore ks = KeyStore.getInstance();
ks.onUserRemoved(userId);
- try {
- final IGateKeeperService gk = getGateKeeperService();
- if (gk != null) {
- gk.clearSecureUserId(userId);
- }
- } catch (RemoteException ex) {
- Slog.w(TAG, "unable to clear GK secure user id");
- }
+ gateKeeperClearSecureUserId(userId);
if (unknownUser || mUserManager.getUserInfo(userId).isManagedProfile()) {
removeKeystoreProfileKey(userId);
}
@@ -2141,8 +2149,7 @@
@Override
public void onShellCommand(FileDescriptor in, FileDescriptor out, FileDescriptor err,
- String[] args, ShellCallback callback, ResultReceiver resultReceiver)
- throws RemoteException {
+ String[] args, ShellCallback callback, ResultReceiver resultReceiver) {
enforceShell();
final long origId = Binder.clearCallingIdentity();
try {
@@ -2304,15 +2311,18 @@
}
}
- protected synchronized IGateKeeperService getGateKeeperService()
- throws RemoteException {
+ protected synchronized IGateKeeperService getGateKeeperService() {
if (mGateKeeperService != null) {
return mGateKeeperService;
}
final IBinder service = ServiceManager.getService(Context.GATEKEEPER_SERVICE);
if (service != null) {
- service.linkToDeath(new GateKeeperDiedRecipient(), 0);
+ try {
+ service.linkToDeath(new GateKeeperDiedRecipient(), 0);
+ } catch (RemoteException e) {
+ Slog.w(TAG, " Unable to register death recipient", e);
+ }
mGateKeeperService = IGateKeeperService.Stub.asInterface(service);
return mGateKeeperService;
}
@@ -2321,6 +2331,14 @@
return null;
}
+ private void gateKeeperClearSecureUserId(int userId) {
+ try {
+ getGateKeeperService().clearSecureUserId(userId);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to clear SID", e);
+ }
+ }
+
/**
* A user's synthetic password does not change so it must be cached in certain circumstances to
* enable untrusted credential reset.
@@ -2330,7 +2348,7 @@
* credential.
*/
@GuardedBy("mSpManager")
- private SparseArray<AuthenticationToken> mSpCache = new SparseArray();
+ private SparseArray<AuthenticationToken> mSpCache = new SparseArray<>();
private void onAuthTokenKnownForUser(@UserIdInt int userId, AuthenticationToken auth) {
// Preemptively cache the SP and then try to remove it in a handler.
@@ -2435,8 +2453,7 @@
@GuardedBy("mSpManager")
@VisibleForTesting
protected AuthenticationToken initializeSyntheticPasswordLocked(byte[] credentialHash,
- byte[] credential, int credentialType, int requestedQuality,
- int userId) throws RemoteException {
+ byte[] credential, int credentialType, int requestedQuality, int userId) {
Slog.i(TAG, "Initialize SyntheticPassword for user: " + userId);
final AuthenticationToken auth = mSpManager.newSyntheticPasswordAndSid(
getGateKeeperService(), credentialHash, credential, userId);
@@ -2459,10 +2476,10 @@
} else {
clearUserKeyProtection(userId);
setKeystorePassword(null, userId);
- getGateKeeperService().clearSecureUserId(userId);
+ gateKeeperClearSecureUserId(userId);
}
fixateNewestUserKeyAuth(userId);
- setLong(SYNTHETIC_PASSWORD_HANDLE_KEY, handle, userId);
+ setSyntheticPasswordHandleLocked(handle, userId);
return auth;
}
@@ -2471,6 +2488,14 @@
SyntheticPasswordManager.DEFAULT_HANDLE, userId);
}
+ private void setSyntheticPasswordHandleLocked(long handle, int userId) {
+ final long oldHandle = getSyntheticPasswordHandleLocked(userId);
+ setLong(SYNTHETIC_PASSWORD_HANDLE_KEY, handle, userId);
+ setLong(PREV_SYNTHETIC_PASSWORD_HANDLE_KEY, oldHandle, userId);
+ setLong(SYNTHETIC_PASSWORD_UPDATE_TIME_KEY, System.currentTimeMillis(), userId);
+
+ }
+
private boolean isSyntheticPasswordBasedCredentialLocked(int userId) {
if (userId == USER_FRP) {
final int type = mStorage.readPersistentDataBlock().type;
@@ -2499,7 +2524,7 @@
private VerifyCredentialResponse spBasedDoVerifyCredential(byte[] userCredential,
@CredentialType int credentialType, @ChallengeType int challengeType, long challenge,
int userId, ICheckCredentialProgressCallback progressCallback,
- @Nullable ArrayList<PendingResetLockout> resetLockouts) throws RemoteException {
+ @Nullable ArrayList<PendingResetLockout> resetLockouts) {
final boolean hasEnrolledBiometrics = mInjector.hasEnrolledBiometrics(userId);
@@ -2606,7 +2631,7 @@
@GuardedBy("mSpManager")
private long setLockCredentialWithAuthTokenLocked(byte[] credential,
@CredentialType int credentialType, AuthenticationToken auth, int requestedQuality,
- int userId) throws RemoteException {
+ int userId) {
if (DEBUG) Slog.d(TAG, "setLockCredentialWithAuthTokenLocked: user=" + userId);
long newHandle = mSpManager.createPasswordBasedSyntheticPassword(getGateKeeperService(),
credential, credentialType, auth, requestedQuality, userId);
@@ -2638,7 +2663,7 @@
// we are clearing password of a secured device, so need to nuke SID as well.
mSpManager.clearSidForUser(userId);
- getGateKeeperService().clearSecureUserId(userId);
+ gateKeeperClearSecureUserId(userId);
// Clear key from vold so ActivityManager can just unlock the user with empty secret
// during boot. Vold storage needs to be unlocked before manipulation of the keys can
// succeed.
@@ -2648,7 +2673,7 @@
unlockKeystore(auth.deriveKeyStorePassword(), userId);
setKeystorePassword(null, userId);
}
- setLong(SYNTHETIC_PASSWORD_HANDLE_KEY, newHandle, userId);
+ setSyntheticPasswordHandleLocked(newHandle, userId);
synchronizeUnifiedWorkChallengeForProfiles(userId, profilePasswords);
notifyActivePasswordMetricsAvailable(credentialType, credential, userId);
@@ -2665,7 +2690,7 @@
@GuardedBy("mSpManager")
private void spBasedSetLockCredentialInternalLocked(byte[] credential, int credentialType,
byte[] savedCredential, int requestedQuality, int userId,
- boolean allowUntrustedChange, boolean isLockTiedToParent) throws RemoteException {
+ boolean allowUntrustedChange, boolean isLockTiedToParent) {
if (DEBUG) Slog.d(TAG, "spBasedSetLockCredentialInternalLocked: user=" + userId);
if (isManagedProfileWithUnifiedLock(userId)) {
// get credential from keystore when managed profile has unified lock
@@ -2688,9 +2713,8 @@
// If existing credential is provided, the existing credential must match.
if (savedCredential != null && auth == null) {
- throw new IllegalStateException("Failed to enroll "
- + (credentialType == CREDENTIAL_TYPE_PASSWORD
- ? "password" : "pattern"));
+ throw new IllegalStateException(String.format("Failed to enroll %s",
+ credentialType == CREDENTIAL_TYPE_PASSWORD ? "password" : "pattern"));
}
boolean untrustedReset = false;
if (auth != null) {
@@ -2741,7 +2765,7 @@
* If user is a managed profile with unified challenge, currentCredential is ignored.
*/
@Override
- public byte[] getHashFactor(byte[] currentCredential, int userId) throws RemoteException {
+ public byte[] getHashFactor(byte[] currentCredential, int userId) {
checkPasswordReadPermission(userId);
if (currentCredential == null || currentCredential.length == 0) {
currentCredential = null;
@@ -2770,8 +2794,7 @@
}
}
- private long addEscrowToken(byte[] token, int userId, EscrowTokenStateChangeCallback callback)
- throws RemoteException {
+ private long addEscrowToken(byte[] token, int userId, EscrowTokenStateChangeCallback callback) {
if (DEBUG) Slog.d(TAG, "addEscrowToken: user=" + userId);
synchronized (mSpManager) {
enableSyntheticPasswordLocked();
@@ -2847,7 +2870,7 @@
}
private boolean setLockCredentialWithToken(byte[] credential, int type, long tokenHandle,
- byte[] token, int requestedQuality, int userId) throws RemoteException {
+ byte[] token, int requestedQuality, int userId) {
boolean result;
synchronized (mSpManager) {
if (!mSpManager.hasEscrowData(userId)) {
@@ -2874,8 +2897,7 @@
@GuardedBy("mSpManager")
private boolean setLockCredentialWithTokenInternalLocked(byte[] credential, int type,
- long tokenHandle, byte[] token, int requestedQuality, int userId)
- throws RemoteException {
+ long tokenHandle, byte[] token, int requestedQuality, int userId) {
final AuthenticationResult result;
result = mSpManager.unwrapTokenBasedSyntheticPassword(
getGateKeeperService(), tokenHandle, token, userId);
@@ -2901,8 +2923,7 @@
return true;
}
- private boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId)
- throws RemoteException {
+ private boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId) {
AuthenticationResult authResult;
synchronized (mSpManager) {
if (!mSpManager.hasEscrowData(userId)) {
@@ -2920,29 +2941,57 @@
return true;
}
+ static String timestampToString(long timestamp) {
+ return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(timestamp));
+ }
+
@Override
- protected void dump(FileDescriptor fd, PrintWriter pw, String[] args){
- if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
+ protected void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
+ if (!DumpUtils.checkDumpPermission(mContext, TAG, printWriter)) return;
+ IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " ");
pw.println("Current lock settings service state:");
+
pw.println(String.format("SP Enabled = %b",
mLockPatternUtils.isSyntheticPasswordEnabled()));
+ pw.println();
+ pw.println("User State:");
+ pw.increaseIndent();
List<UserInfo> users = mUserManager.getUsers();
for (int user = 0; user < users.size(); user++) {
final int userId = users.get(user).id;
- pw.println(" User " + userId);
+ pw.println("User " + userId);
+ pw.increaseIndent();
synchronized (mSpManager) {
- pw.println(String.format(" SP Handle = %x",
+ pw.println(String.format("SP Handle: %x",
getSyntheticPasswordHandleLocked(userId)));
+ pw.println(String.format("Last changed: %s (%x)",
+ timestampToString(getLong(SYNTHETIC_PASSWORD_UPDATE_TIME_KEY, 0, userId)),
+ getLong(PREV_SYNTHETIC_PASSWORD_HANDLE_KEY, 0, userId)));
}
try {
- pw.println(String.format(" SID = %x",
+ pw.println(String.format("SID: %x",
getGateKeeperService().getSecureUserId(userId)));
} catch (RemoteException e) {
// ignore.
}
+ // It's OK to dump the password type since anyone with physical access can just
+ // observe it from the keyguard directly.
+ pw.println("PasswordType: " + getLong(LockPatternUtils.PASSWORD_TYPE_KEY, 0, userId));
+ pw.println("hasPassword: " + havePassword(userId));
+ pw.println("hasPattern: " + havePattern(userId)); // print raw credential type instead?
+ pw.println("SeparateChallenge: " + getSeparateProfileChallengeEnabled(userId));
+ pw.decreaseIndent();
}
+ pw.println();
+ pw.decreaseIndent();
+
+ pw.println("Storage:");
+ pw.increaseIndent();
+ mStorage.dump(pw);
+ pw.println();
+ pw.decreaseIndent();
}
private void disableEscrowTokenOnNonManagedDevicesIfNeeded(int userId) {
@@ -3081,11 +3130,7 @@
@Override
public long addEscrowToken(byte[] token, int userId,
EscrowTokenStateChangeCallback callback) {
- try {
- return LockSettingsService.this.addEscrowToken(token, userId, callback);
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
- }
+ return LockSettingsService.this.addEscrowToken(token, userId, callback);
}
@Override
@@ -3105,21 +3150,13 @@
throw new UnsupportedOperationException(
"This operation requires secure lock screen feature.");
}
- try {
- return LockSettingsService.this.setLockCredentialWithToken(credential, type,
- tokenHandle, token, requestedQuality, userId);
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
- }
+ return LockSettingsService.this.setLockCredentialWithToken(credential, type,
+ tokenHandle, token, requestedQuality, userId);
}
@Override
public boolean unlockUserWithToken(long tokenHandle, byte[] token, int userId) {
- try {
- return LockSettingsService.this.unlockUserWithToken(tokenHandle, token, userId);
- } catch (RemoteException re) {
- throw re.rethrowFromSystemServer();
- }
+ return LockSettingsService.this.unlockUserWithToken(tokenHandle, token, userId);
}
}
}
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
index 29b8aa2..fe12a94 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsStorage.java
@@ -35,6 +35,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockPatternUtils.CredentialType;
@@ -140,7 +141,7 @@
dos.close();
return os.toByteArray();
} catch (IOException e) {
- throw new RuntimeException(e);
+ throw new IllegalStateException("Fail to serialze credential hash", e);
}
}
@@ -157,7 +158,7 @@
}
return new CredentialHash(hash, type);
} catch (IOException e) {
- throw new RuntimeException(e);
+ throw new IllegalStateException("Fail to deserialze credential hash", e);
}
}
}
@@ -666,7 +667,7 @@
dos.writeInt(qualityForUi);
dos.write(payload);
} catch (IOException e) {
- throw new RuntimeException("ByteArrayOutputStream cannot throw IOException");
+ throw new IllegalStateException("ByteArrayOutputStream cannot throw IOException");
}
return os.toByteArray();
}
@@ -676,6 +677,26 @@
void initialize(SQLiteDatabase db);
}
+ public void dump(IndentingPrintWriter pw) {
+ final UserManager um = UserManager.get(mContext);
+ for (UserInfo user : um.getUsers(false)) {
+ File userPath = getSyntheticPasswordDirectoryForUser(user.id);
+ pw.println(String.format("User %d [%s]:", user.id, userPath.getAbsolutePath()));
+ pw.increaseIndent();
+ File[] files = userPath.listFiles();
+ if (files != null) {
+ for (File file : files) {
+ pw.println(String.format("%4d %s %s", file.length(),
+ LockSettingsService.timestampToString(file.lastModified()),
+ file.getName()));
+ }
+ } else {
+ pw.println("[Not found]");
+ }
+ pw.decreaseIndent();
+ }
+ }
+
static class DatabaseHelper extends SQLiteOpenHelper {
private static final String TAG = "LockSettingsDB";
private static final String DATABASE_NAME = "locksettings.db";
diff --git a/services/core/java/com/android/server/locksettings/PasswordSlotManager.java b/services/core/java/com/android/server/locksettings/PasswordSlotManager.java
index 4ef63c0..17aca15 100644
--- a/services/core/java/com/android/server/locksettings/PasswordSlotManager.java
+++ b/services/core/java/com/android/server/locksettings/PasswordSlotManager.java
@@ -109,7 +109,7 @@
public void markSlotInUse(int slot) throws RuntimeException {
ensureSlotMapLoaded();
if (mSlotMap.containsKey(slot) && !mSlotMap.get(slot).equals(getMode())) {
- throw new RuntimeException("password slot " + slot + " is not available");
+ throw new IllegalStateException("password slot " + slot + " is not available");
}
mSlotMap.put(slot, getMode());
saveSlotMap();
@@ -123,7 +123,7 @@
public void markSlotDeleted(int slot) throws RuntimeException {
ensureSlotMapLoaded();
if (mSlotMap.containsKey(slot) && !mSlotMap.get(slot).equals(getMode())) {
- throw new RuntimeException("password slot " + slot + " cannot be deleted");
+ throw new IllegalStateException("password slot " + slot + " cannot be deleted");
}
mSlotMap.remove(slot);
saveSlotMap();
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java
index 388e51f..ea0fb47 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordCrypto.java
@@ -18,6 +18,7 @@
import android.security.keystore.KeyProperties;
import android.security.keystore.KeyProtection;
+import android.util.Slog;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -43,6 +44,7 @@
import javax.crypto.spec.SecretKeySpec;
public class SyntheticPasswordCrypto {
+ private static final String TAG = "SyntheticPasswordCrypto";
private static final int PROFILE_KEY_IV_SIZE = 12;
private static final int DEFAULT_TAG_LENGTH_BITS = 128;
private static final int AES_KEY_LENGTH = 32; // 256-bit AES key
@@ -80,12 +82,12 @@
byte[] ciphertext = cipher.doFinal(blob);
byte[] iv = cipher.getIV();
if (iv.length != PROFILE_KEY_IV_SIZE) {
- throw new RuntimeException("Invalid iv length: " + iv.length);
+ throw new IllegalArgumentException("Invalid iv length: " + iv.length);
}
final GCMParameterSpec spec = cipher.getParameters().getParameterSpec(
GCMParameterSpec.class);
if (spec.getTLen() != DEFAULT_TAG_LENGTH_BITS) {
- throw new RuntimeException("Invalid tag length: " + spec.getTLen());
+ throw new IllegalArgumentException("Invalid tag length: " + spec.getTLen());
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
outputStream.write(iv);
@@ -102,7 +104,7 @@
} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException
| IllegalBlockSizeException | BadPaddingException | IOException
| InvalidParameterSpecException e) {
- e.printStackTrace();
+ Slog.e(TAG, "Failed to encrypt", e);
return null;
}
}
@@ -116,7 +118,7 @@
} catch (InvalidKeyException | NoSuchAlgorithmException | NoSuchPaddingException
| IllegalBlockSizeException | BadPaddingException
| InvalidAlgorithmParameterException e) {
- e.printStackTrace();
+ Slog.e(TAG, "Failed to decrypt", e);
return null;
}
}
@@ -130,8 +132,8 @@
byte[] intermediate = decrypt(applicationId, APPLICATION_ID_PERSONALIZATION, blob);
return decrypt(decryptionKey, intermediate);
} catch (Exception e) {
- e.printStackTrace();
- throw new RuntimeException("Failed to decrypt blob", e);
+ Slog.e(TAG, "Failed to decrypt V1 blob", e);
+ throw new IllegalStateException("Failed to decrypt blob", e);
}
}
@@ -148,8 +150,8 @@
| KeyStoreException | NoSuchPaddingException | NoSuchAlgorithmException
| InvalidKeyException | UnrecoverableKeyException
| InvalidAlgorithmParameterException e) {
- e.printStackTrace();
- throw new RuntimeException("Failed to decrypt blob", e);
+ Slog.e(TAG, "Failed to decrypt blob", e);
+ throw new IllegalStateException("Failed to decrypt blob", e);
}
}
@@ -180,8 +182,8 @@
| KeyStoreException | NoSuchPaddingException | NoSuchAlgorithmException
| InvalidKeyException
| InvalidParameterSpecException e) {
- e.printStackTrace();
- throw new RuntimeException("Failed to encrypt blob", e);
+ Slog.e(TAG, "Failed to create blob", e);
+ throw new IllegalStateException("Failed to encrypt blob", e);
}
}
@@ -193,7 +195,7 @@
keyStore.deleteEntry(keyAlias);
} catch (KeyStoreException | NoSuchAlgorithmException | CertificateException
| IOException e) {
- e.printStackTrace();
+ Slog.e(TAG, "Failed to destroy blob", e);
}
}
@@ -202,7 +204,7 @@
final int PADDING_LENGTH = 128;
MessageDigest digest = MessageDigest.getInstance("SHA-512");
if (personalisation.length > PADDING_LENGTH) {
- throw new RuntimeException("Personalisation too long");
+ throw new IllegalArgumentException("Personalisation too long");
}
// Personalize the hash
// Pad it to the block size of the hash function
@@ -213,7 +215,7 @@
}
return digest.digest();
} catch (NoSuchAlgorithmException e) {
- throw new RuntimeException("NoSuchAlgorithmException for SHA-512", e);
+ throw new IllegalStateException("NoSuchAlgorithmException for SHA-512", e);
}
}
}
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index 1ba0e8c..955a9aa 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -349,25 +349,28 @@
* a default all-zero key is used. If the value is not specified, a fresh random secret is
* generated as the value.
*
- * @return the value stored in the weaver slot
- * @throws RemoteException
+ * @return the value stored in the weaver slot, or null if the operation fails
*/
- private byte[] weaverEnroll(int slot, byte[] key, @Nullable byte[] value)
- throws RemoteException {
+ private byte[] weaverEnroll(int slot, byte[] key, @Nullable byte[] value) {
if (slot == INVALID_WEAVER_SLOT || slot >= mWeaverConfig.slots) {
- throw new RuntimeException("Invalid slot for weaver");
+ throw new IllegalArgumentException("Invalid slot for weaver");
}
if (key == null) {
key = new byte[mWeaverConfig.keySize];
} else if (key.length != mWeaverConfig.keySize) {
- throw new RuntimeException("Invalid key size for weaver");
+ throw new IllegalArgumentException("Invalid key size for weaver");
}
if (value == null) {
value = secureRandom(mWeaverConfig.valueSize);
}
- int writeStatus = mWeaver.write(slot, toByteArrayList(key), toByteArrayList(value));
- if (writeStatus != WeaverStatus.OK) {
- Log.e(TAG, "weaver write failed, slot: " + slot + " status: " + writeStatus);
+ try {
+ int writeStatus = mWeaver.write(slot, toByteArrayList(key), toByteArrayList(value));
+ if (writeStatus != WeaverStatus.OK) {
+ Log.e(TAG, "weaver write failed, slot: " + slot + " status: " + writeStatus);
+ return null;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "weaver write failed", e);
return null;
}
return value;
@@ -377,47 +380,53 @@
* Verify the supplied key against a weaver slot, returning a response indicating whether
* the verification is successful, throttled or failed. If successful, the bound secret
* is also returned.
- * @throws RemoteException
*/
- private VerifyCredentialResponse weaverVerify(int slot, byte[] key) throws RemoteException {
+ private VerifyCredentialResponse weaverVerify(int slot, byte[] key) {
if (slot == INVALID_WEAVER_SLOT || slot >= mWeaverConfig.slots) {
- throw new RuntimeException("Invalid slot for weaver");
+ throw new IllegalArgumentException("Invalid slot for weaver");
}
if (key == null) {
key = new byte[mWeaverConfig.keySize];
} else if (key.length != mWeaverConfig.keySize) {
- throw new RuntimeException("Invalid key size for weaver");
+ throw new IllegalArgumentException("Invalid key size for weaver");
}
final VerifyCredentialResponse[] response = new VerifyCredentialResponse[1];
- mWeaver.read(slot, toByteArrayList(key), (int status, WeaverReadResponse readResponse) -> {
- switch (status) {
- case WeaverReadStatus.OK:
- response[0] = new VerifyCredentialResponse(
- fromByteArrayList(readResponse.value));
- break;
- case WeaverReadStatus.THROTTLE:
- response[0] = new VerifyCredentialResponse(readResponse.timeout);
- Log.e(TAG, "weaver read failed (THROTTLE), slot: " + slot);
- break;
- case WeaverReadStatus.INCORRECT_KEY:
- if (readResponse.timeout == 0) {
- response[0] = VerifyCredentialResponse.ERROR;
- Log.e(TAG, "weaver read failed (INCORRECT_KEY), slot: " + slot);
- } else {
- response[0] = new VerifyCredentialResponse(readResponse.timeout);
- Log.e(TAG, "weaver read failed (INCORRECT_KEY/THROTTLE), slot: " + slot);
+ try {
+ mWeaver.read(slot, toByteArrayList(key),
+ (int status, WeaverReadResponse readResponse) -> {
+ switch (status) {
+ case WeaverReadStatus.OK:
+ response[0] = new VerifyCredentialResponse(
+ fromByteArrayList(readResponse.value));
+ break;
+ case WeaverReadStatus.THROTTLE:
+ response[0] = new VerifyCredentialResponse(readResponse.timeout);
+ Log.e(TAG, "weaver read failed (THROTTLE), slot: " + slot);
+ break;
+ case WeaverReadStatus.INCORRECT_KEY:
+ if (readResponse.timeout == 0) {
+ response[0] = VerifyCredentialResponse.ERROR;
+ Log.e(TAG, "weaver read failed (INCORRECT_KEY), slot: " + slot);
+ } else {
+ response[0] = new VerifyCredentialResponse(readResponse.timeout);
+ Log.e(TAG, "weaver read failed (INCORRECT_KEY/THROTTLE), slot: "
+ + slot);
+ }
+ break;
+ case WeaverReadStatus.FAILED:
+ response[0] = VerifyCredentialResponse.ERROR;
+ Log.e(TAG, "weaver read failed (FAILED), slot: " + slot);
+ break;
+ default:
+ response[0] = VerifyCredentialResponse.ERROR;
+ Log.e(TAG, "weaver read unknown status " + status + ", slot: " + slot);
+ break;
}
- break;
- case WeaverReadStatus.FAILED:
- response[0] = VerifyCredentialResponse.ERROR;
- Log.e(TAG, "weaver read failed (FAILED), slot: " + slot);
- break;
- default:
- response[0] = VerifyCredentialResponse.ERROR;
- Log.e(TAG, "weaver read unknown status " + status + ", slot: " + slot);
- break;
- }
- });
+ });
+ } catch (RemoteException e) {
+ response[0] = VerifyCredentialResponse.ERROR;
+ Log.e(TAG, "weaver read failed, slot: " + slot, e);
+ }
return response[0];
}
@@ -460,12 +469,15 @@
*
*/
public AuthenticationToken newSyntheticPasswordAndSid(IGateKeeperService gatekeeper,
- byte[] hash, byte[] credential, int userId) throws RemoteException {
+ byte[] hash, byte[] credential, int userId) {
AuthenticationToken result = AuthenticationToken.create();
GateKeeperResponse response;
if (hash != null) {
- response = gatekeeper.enroll(userId, hash, credential,
- result.deriveGkPassword());
+ try {
+ response = gatekeeper.enroll(userId, hash, credential, result.deriveGkPassword());
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Failed to enroll credential duing SP init", e);
+ }
if (response.getResponseCode() != GateKeeperResponse.RESPONSE_OK) {
Log.w(TAG, "Fail to migrate SID, assuming no SID, user " + userId);
clearSidForUser(userId);
@@ -484,9 +496,13 @@
* Used when adding password to previously-unsecured devices.
*/
public void newSidForUser(IGateKeeperService gatekeeper, AuthenticationToken authToken,
- int userId) throws RemoteException {
- GateKeeperResponse response = gatekeeper.enroll(userId, null, null,
- authToken.deriveGkPassword());
+ int userId) {
+ GateKeeperResponse response;
+ try {
+ response = gatekeeper.enroll(userId, null, null, authToken.deriveGkPassword());
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Failed to create new SID for user", e);
+ }
if (response.getResponseCode() != GateKeeperResponse.RESPONSE_OK) {
Log.e(TAG, "Fail to create new SID for user " + userId);
return;
@@ -565,12 +581,8 @@
Set<Integer> usedSlots = getUsedWeaverSlots();
if (!usedSlots.contains(slot)) {
Log.i(TAG, "Destroy weaver slot " + slot + " for user " + userId);
- try {
- weaverEnroll(slot, null, null);
- mPasswordSlotManager.markSlotDeleted(slot);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to destroy slot", e);
- }
+ weaverEnroll(slot, null, null);
+ mPasswordSlotManager.markSlotDeleted(slot);
} else {
Log.w(TAG, "Skip destroying reused weaver slot " + slot + " for user " + userId);
}
@@ -608,7 +620,7 @@
return i;
}
}
- throw new RuntimeException("Run out of weaver slots.");
+ throw new IllegalStateException("Run out of weaver slots.");
}
/**
@@ -622,11 +634,12 @@
*
* @see #newSidForUser
* @see #clearSidForUser
+ * @return a new password handle for the wrapped SP blob
+ * @throw IllegalStateException if creation fails.
*/
public long createPasswordBasedSyntheticPassword(IGateKeeperService gatekeeper,
byte[] credential, int credentialType, AuthenticationToken authToken,
- int requestedQuality, int userId)
- throws RemoteException {
+ int requestedQuality, int userId) {
if (credential == null || credentialType == LockPatternUtils.CREDENTIAL_TYPE_NONE) {
credentialType = LockPatternUtils.CREDENTIAL_TYPE_NONE;
credential = DEFAULT_PASSWORD;
@@ -642,10 +655,11 @@
// Weaver based user password
int weaverSlot = getNextAvailableWeaverSlot();
Log.i(TAG, "Weaver enroll password to slot " + weaverSlot + " for user " + userId);
- byte[] weaverSecret = weaverEnroll(weaverSlot, passwordTokenToWeaverKey(pwdToken), null);
+ byte[] weaverSecret = weaverEnroll(weaverSlot, passwordTokenToWeaverKey(pwdToken),
+ null);
if (weaverSecret == null) {
- Log.e(TAG, "Fail to enroll user password under weaver " + userId);
- return DEFAULT_HANDLE;
+ throw new IllegalStateException(
+ "Fail to enroll user password under weaver " + userId);
}
saveWeaverSlot(weaverSlot, handle, userId);
mPasswordSlotManager.markSlotInUse(weaverSlot);
@@ -657,13 +671,22 @@
} else {
// In case GK enrollment leaves persistent state around (in RPMB), this will nuke them
// to prevent them from accumulating and causing problems.
- gatekeeper.clearSecureUserId(fakeUid(userId));
+ try {
+ gatekeeper.clearSecureUserId(fakeUid(userId));
+ } catch (RemoteException ignore) {
+ Log.w(TAG, "Failed to clear SID from gatekeeper");
+ }
// GateKeeper based user password
- GateKeeperResponse response = gatekeeper.enroll(fakeUid(userId), null, null,
- passwordTokenToGkInput(pwdToken));
+ GateKeeperResponse response;
+ try {
+ response = gatekeeper.enroll(fakeUid(userId), null, null,
+ passwordTokenToGkInput(pwdToken));
+ } catch (RemoteException e) {
+ throw new IllegalStateException("Failed to enroll password for new SP blob", e);
+ }
if (response.getResponseCode() != GateKeeperResponse.RESPONSE_OK) {
- Log.e(TAG, "Fail to enroll user password when creating SP for user " + userId);
- return DEFAULT_HANDLE;
+ throw new IllegalStateException(
+ "Fail to enroll user password when creating SP for user " + userId);
}
pwd.passwordHandle = response.getPayload();
sid = sidFromPasswordHandle(pwd.passwordHandle);
@@ -680,14 +703,20 @@
public VerifyCredentialResponse verifyFrpCredential(IGateKeeperService gatekeeper,
byte[] userCredential, int credentialType,
- ICheckCredentialProgressCallback progressCallback) throws RemoteException {
+ ICheckCredentialProgressCallback progressCallback) {
PersistentData persistentData = mStorage.readPersistentDataBlock();
if (persistentData.type == PersistentData.TYPE_SP) {
PasswordData pwd = PasswordData.fromBytes(persistentData.payload);
byte[] pwdToken = computePasswordToken(userCredential, pwd);
- GateKeeperResponse response = gatekeeper.verifyChallenge(fakeUid(persistentData.userId),
- 0 /* challenge */, pwd.passwordHandle, passwordTokenToGkInput(pwdToken));
+ GateKeeperResponse response;
+ try {
+ response = gatekeeper.verifyChallenge(fakeUid(persistentData.userId),
+ 0 /* challenge */, pwd.passwordHandle, passwordTokenToGkInput(pwdToken));
+ } catch (RemoteException e) {
+ Log.e(TAG, "FRP verifyChallenge failed", e);
+ return VerifyCredentialResponse.ERROR;
+ }
return VerifyCredentialResponse.fromGateKeeperResponse(response);
} else if (persistentData.type == PersistentData.TYPE_SP_WEAVER) {
PasswordData pwd = PasswordData.fromBytes(persistentData.payload);
@@ -805,11 +834,9 @@
}
if (isWeaverAvailable()) {
int slot = getNextAvailableWeaverSlot();
- try {
- Log.i(TAG, "Weaver enroll token to slot " + slot + " for user " + userId);
- weaverEnroll(slot, null, tokenData.weaverSecret);
- } catch (RemoteException e) {
- Log.e(TAG, "Failed to enroll weaver secret when activating token", e);
+ Log.i(TAG, "Weaver enroll token to slot " + slot + " for user " + userId);
+ if (weaverEnroll(slot, null, tokenData.weaverSecret) == null) {
+ Log.e(TAG, "Failed to enroll weaver secret when activating token");
return false;
}
saveWeaverSlot(slot, handle, userId);
@@ -859,7 +886,7 @@
*/
public AuthenticationResult unwrapPasswordBasedSyntheticPassword(IGateKeeperService gatekeeper,
long handle, byte[] credential, int userId,
- ICheckCredentialProgressCallback progressCallback) throws RemoteException {
+ ICheckCredentialProgressCallback progressCallback) {
if (credential == null) {
credential = DEFAULT_PASSWORD;
}
@@ -886,14 +913,28 @@
applicationId = transformUnderWeaverSecret(pwdToken, result.gkResponse.getPayload());
} else {
byte[] gkPwdToken = passwordTokenToGkInput(pwdToken);
- GateKeeperResponse response = gatekeeper.verifyChallenge(fakeUid(userId), 0L,
- pwd.passwordHandle, gkPwdToken);
+ GateKeeperResponse response;
+ try {
+ response = gatekeeper.verifyChallenge(fakeUid(userId), 0L,
+ pwd.passwordHandle, gkPwdToken);
+ } catch (RemoteException e) {
+ Log.e(TAG, "gatekeeper verify failed", e);
+ result.gkResponse = VerifyCredentialResponse.ERROR;
+ return result;
+ }
int responseCode = response.getResponseCode();
if (responseCode == GateKeeperResponse.RESPONSE_OK) {
result.gkResponse = VerifyCredentialResponse.OK;
if (response.getShouldReEnroll()) {
- GateKeeperResponse reenrollResponse = gatekeeper.enroll(fakeUid(userId),
- pwd.passwordHandle, gkPwdToken, gkPwdToken);
+ GateKeeperResponse reenrollResponse;
+ try {
+ reenrollResponse = gatekeeper.enroll(fakeUid(userId),
+ pwd.passwordHandle, gkPwdToken, gkPwdToken);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Fail to invoke gatekeeper.enroll", e);
+ reenrollResponse = GateKeeperResponse.ERROR;
+ // continue the flow anyway
+ }
if (reenrollResponse.getResponseCode() == GateKeeperResponse.RESPONSE_OK) {
pwd.passwordHandle = reenrollResponse.getPayload();
saveState(PASSWORD_DATA_NAME, pwd.toBytes(), handle, userId);
@@ -922,7 +963,11 @@
// Supplied credential passes first stage weaver/gatekeeper check so it should be correct.
// Notify the callback so the keyguard UI can proceed immediately.
if (progressCallback != null) {
- progressCallback.onCredentialVerified();
+ try {
+ progressCallback.onCredentialVerified();
+ } catch (RemoteException e) {
+ Log.w(TAG, "progressCallback throws exception", e);
+ }
}
result.authToken = unwrapSyntheticPasswordBlob(handle, SYNTHETIC_PASSWORD_PASSWORD_BASED,
applicationId, sid, userId);
@@ -938,8 +983,7 @@
* verification to referesh the SID & Auth token maintained by the system.
*/
public @NonNull AuthenticationResult unwrapTokenBasedSyntheticPassword(
- IGateKeeperService gatekeeper, long handle, byte[] token, int userId)
- throws RemoteException {
+ IGateKeeperService gatekeeper, long handle, byte[] token, int userId) {
AuthenticationResult result = new AuthenticationResult();
byte[] secdiscardable = loadSecdiscardable(handle, userId);
int slotId = loadWeaverSlot(handle, userId);
@@ -985,10 +1029,10 @@
if (version != SYNTHETIC_PASSWORD_VERSION_V3
&& version != SYNTHETIC_PASSWORD_VERSION_V2
&& version != SYNTHETIC_PASSWORD_VERSION_V1) {
- throw new RuntimeException("Unknown blob version");
+ throw new IllegalArgumentException("Unknown blob version");
}
if (blob[1] != type) {
- throw new RuntimeException("Invalid blob type");
+ throw new IllegalArgumentException("Invalid blob type");
}
final byte[] secret;
if (version == SYNTHETIC_PASSWORD_VERSION_V1) {
@@ -1028,38 +1072,48 @@
* decrypt SP.
*/
public @Nullable VerifyCredentialResponse verifyChallenge(IGateKeeperService gatekeeper,
- @NonNull AuthenticationToken auth, long challenge, int userId) throws RemoteException {
+ @NonNull AuthenticationToken auth, long challenge, int userId) {
byte[] spHandle = loadSyntheticPasswordHandle(userId);
if (spHandle == null) {
// There is no password handle associated with the given user, i.e. the user is not
// secured by lockscreen and has no SID, so just return here;
return null;
}
- VerifyCredentialResponse result;
- GateKeeperResponse response = gatekeeper.verifyChallenge(userId, challenge,
- spHandle, auth.deriveGkPassword());
+ GateKeeperResponse response;
+ try {
+ response = gatekeeper.verifyChallenge(userId, challenge,
+ spHandle, auth.deriveGkPassword());
+ } catch (RemoteException e) {
+ Log.e(TAG, "Fail to verify with gatekeeper " + userId, e);
+ return VerifyCredentialResponse.ERROR;
+ }
int responseCode = response.getResponseCode();
if (responseCode == GateKeeperResponse.RESPONSE_OK) {
- result = new VerifyCredentialResponse(response.getPayload());
+ VerifyCredentialResponse result = new VerifyCredentialResponse(response.getPayload());
if (response.getShouldReEnroll()) {
- response = gatekeeper.enroll(userId, spHandle,
- spHandle, auth.deriveGkPassword());
+ try {
+ response = gatekeeper.enroll(userId, spHandle, spHandle,
+ auth.deriveGkPassword());
+ } catch (RemoteException e) {
+ Log.e(TAG, "Failed to invoke gatekeeper.enroll", e);
+ response = GateKeeperResponse.ERROR;
+ }
if (response.getResponseCode() == GateKeeperResponse.RESPONSE_OK) {
spHandle = response.getPayload();
saveSyntheticPasswordHandle(spHandle, userId);
// Call self again to re-verify with updated handle
return verifyChallenge(gatekeeper, auth, challenge, userId);
} else {
+ // Fall through, return result from the previous verification attempt.
Log.w(TAG, "Fail to re-enroll SP handle for user " + userId);
- // Fall through, return existing handle
}
}
+ return result;
} else if (responseCode == GateKeeperResponse.RESPONSE_RETRY) {
- result = new VerifyCredentialResponse(response.getTimeout());
+ return new VerifyCredentialResponse(response.getTimeout());
} else {
- result = VerifyCredentialResponse.ERROR;
+ return VerifyCredentialResponse.ERROR;
}
- return result;
}
public boolean existsHandle(long handle, int userId) {
@@ -1183,7 +1237,7 @@
private byte[] passwordTokenToWeaverKey(byte[] token) {
byte[] key = SyntheticPasswordCrypto.personalisedHash(PERSONALISATION_WEAVER_KEY, token);
if (key.length < mWeaverConfig.keySize) {
- throw new RuntimeException("weaver key length too small");
+ throw new IllegalArgumentException("weaver key length too small");
}
return Arrays.copyOf(key, mWeaverConfig.keySize);
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 6fe924e..aa548f2 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -231,7 +231,7 @@
import com.android.internal.util.Preconditions;
import com.android.internal.util.XmlUtils;
import com.android.internal.util.function.TriPredicate;
-import com.android.server.DeviceIdleController;
+import com.android.server.DeviceIdleInternal;
import com.android.server.EventLogTags;
import com.android.server.IoThread;
import com.android.server.LocalServices;
@@ -4830,7 +4830,7 @@
final ActivityManagerInternal am = LocalServices
.getService(ActivityManagerInternal.class);
final long duration = LocalServices.getService(
- DeviceIdleController.LocalService.class).getNotificationWhitelistDuration();
+ DeviceIdleInternal.class).getNotificationWhitelistDuration();
for (int i = 0; i < intentCount; i++) {
PendingIntent pendingIntent = notification.allPendingIntents.valueAt(i);
if (pendingIntent != null) {
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index ce95181..8171a8d 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -752,7 +752,7 @@
@Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
final DumpState dumpState = new DumpState();
- dumpState.setUserId(UserHandle.getUserId(Binder.getCallingUid()));
+ dumpState.setUserId(UserHandle.USER_ALL);
int opti = 0;
while (opti < args.length) {
@@ -772,13 +772,13 @@
pw.println(" so the following are equivalent: mState, mstate, State, state.");
return;
} else if ("--user".equals(opt)) {
- opti++;
if (opti >= args.length) {
pw.println("Error: user missing argument");
return;
}
try {
dumpState.setUserId(Integer.parseInt(args[opti]));
+ opti++;
} catch (NumberFormatException e) {
pw.println("Error: user argument is not a number: " + args[opti]);
return;
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index 7b13720..4431d86 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -28,13 +28,11 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.permission.IPermissionManager;
-import android.provider.DeviceConfig;
import android.util.ArraySet;
import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.R;
-import com.android.server.FgThread;
import java.io.PrintWriter;
import java.util.Collections;
@@ -135,19 +133,7 @@
}
IPermissionManager permissionmgr =
(IPermissionManager) ServiceManager.getService("permissionmgr");
- return new AppsFilter(() -> {
- if (featureEnabled.get() < 0) {
- featureEnabled.set(DeviceConfig.getBoolean(
- DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
- "package_query_filtering_enabled", false) ? 1 : 0);
- DeviceConfig.addOnPropertiesChangedListener(
- DeviceConfig.NAMESPACE_PACKAGE_MANAGER_SERVICE,
- FgThread.getExecutor(),
- pr -> featureEnabled.set(
- pr.getBoolean("package_query_filtering_enabled", false) ? 1 : 0));
- }
- return featureEnabled.get() == 1;
- }, permissionmgr,
+ return new AppsFilter(() -> false, permissionmgr,
context.getSystemService(AppOpsManager.class), forcedQueryablePackageNames,
forceSystemAppsQueryable);
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index af20346..4f0e4c8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -290,7 +290,7 @@
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
import com.android.server.AttributeCache;
-import com.android.server.DeviceIdleController;
+import com.android.server.DeviceIdleInternal;
import com.android.server.EventLogTags;
import com.android.server.FgThread;
import com.android.server.LocalServices;
@@ -816,7 +816,7 @@
private final Singleton<UserManagerService> mUserManagerProducer;
private final Singleton<Settings> mSettingsProducer;
private final Singleton<ActivityTaskManagerInternal> mActivityTaskManagerProducer;
- private final Singleton<DeviceIdleController.LocalService> mLocalDeviceIdleController;
+ private final Singleton<DeviceIdleInternal> mLocalDeviceIdleController;
private final Singleton<StorageManagerInternal> mStorageManagerInternalProducer;
private final Singleton<NetworkPolicyManagerInternal> mNetworkPolicyManagerProducer;
private final Singleton<PermissionPolicyInternal> mPermissionPolicyProducer;
@@ -832,7 +832,7 @@
Producer<UserManagerService> userManagerProducer,
Producer<Settings> settingsProducer,
Producer<ActivityTaskManagerInternal> activityTaskManagerProducer,
- Producer<DeviceIdleController.LocalService> deviceIdleControllerProducer,
+ Producer<DeviceIdleInternal> deviceIdleControllerProducer,
Producer<StorageManagerInternal> storageManagerInternalProducer,
Producer<NetworkPolicyManagerInternal> networkPolicyManagerProducer,
Producer<PermissionPolicyInternal> permissionPolicyProvider,
@@ -912,7 +912,7 @@
return mActivityTaskManagerProducer.get(this, mPackageManager);
}
- public DeviceIdleController.LocalService getLocalDeviceIdleController() {
+ public DeviceIdleInternal getLocalDeviceIdleController() {
return mLocalDeviceIdleController.get(this, mPackageManager);
}
@@ -1249,7 +1249,7 @@
final BroadcastOptions options = BroadcastOptions.makeBasic();
options.setTemporaryAppWhitelistDuration(whitelistTimeout);
- DeviceIdleController.LocalService idleController =
+ DeviceIdleInternal idleController =
mInjector.getLocalDeviceIdleController();
idleController.addPowerSaveTempWhitelistApp(Process.myUid(),
mIntentFilterVerifierComponent.getPackageName(), whitelistTimeout,
@@ -2425,7 +2425,7 @@
i.getPermissionManagerServiceInternal().getPermissionSettings(),
lock),
new Injector.LocalServicesProducer<>(ActivityTaskManagerInternal.class),
- new Injector.LocalServicesProducer<>(DeviceIdleController.LocalService.class),
+ new Injector.LocalServicesProducer<>(DeviceIdleInternal.class),
new Injector.LocalServicesProducer<>(StorageManagerInternal.class),
new Injector.LocalServicesProducer<>(NetworkPolicyManagerInternal.class),
new Injector.LocalServicesProducer<>(PermissionPolicyInternal.class),
@@ -14511,7 +14511,7 @@
final List<ComponentName> sufficientVerifiers = matchVerifiers(pkgLite,
receivers, verificationState);
- DeviceIdleController.LocalService idleController =
+ DeviceIdleInternal idleController =
mInjector.getLocalDeviceIdleController();
final long idleDuration = getVerificationTimeout();
@@ -14580,17 +14580,6 @@
TRACE_TAG_PACKAGE_MANAGER, "enable_rollback", enableRollbackToken);
mPendingEnableRollback.append(enableRollbackToken, this);
- final int[] installedUsers;
- synchronized (mLock) {
- PackageSetting ps = mSettings.getPackageLPr(pkgLite.packageName);
- if (ps != null) {
- installedUsers = ps.queryInstalledUsers(mUserManager.getUserIds(),
- true);
- } else {
- installedUsers = new int[0];
- }
- }
-
Intent enableRollbackIntent = new Intent(Intent.ACTION_PACKAGE_ENABLE_ROLLBACK);
enableRollbackIntent.putExtra(
PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_TOKEN,
@@ -14599,9 +14588,6 @@
PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_INSTALL_FLAGS,
installFlags);
enableRollbackIntent.putExtra(
- PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_INSTALLED_USERS,
- installedUsers);
- enableRollbackIntent.putExtra(
PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_USER,
getRollbackUser().getIdentifier());
enableRollbackIntent.setDataAndType(Uri.fromFile(new File(origin.resolvedPath)),
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 6d3424c..dd1eb83 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -35,7 +35,6 @@
import android.content.pm.PackageParser.SigningDetails;
import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
import android.content.pm.ParceledListSlice;
-import android.content.pm.Signature;
import android.content.rollback.IRollbackManager;
import android.os.Bundle;
import android.os.Handler;
@@ -106,8 +105,19 @@
return new ParceledListSlice<>(result);
}
- private void validateApexSignature(String apexPath, String packageName)
+ /**
+ * Validates the signature used to sign the container of the new apex package
+ *
+ * @param newApexPkg The new apex package that is being installed
+ * @param installFlags flags related to the session
+ * @throws PackageManagerException
+ */
+ private void validateApexSignature(PackageInfo newApexPkg, int installFlags)
throws PackageManagerException {
+ // Get signing details of the new package
+ final String apexPath = newApexPkg.applicationInfo.sourceDir;
+ final String packageName = newApexPkg.packageName;
+
final SigningDetails signingDetails;
try {
signingDetails = ApkSignatureVerifier.verify(apexPath, SignatureSchemeVersion.JAR);
@@ -116,9 +126,10 @@
"Failed to parse APEX package " + apexPath, e);
}
- final PackageInfo packageInfo = mApexManager.getPackageInfo(packageName,
+ // Get signing details of the existing package
+ final PackageInfo existingApexPkg = mApexManager.getPackageInfo(packageName,
ApexManager.MATCH_ACTIVE_PACKAGE);
- if (packageInfo == null) {
+ if (existingApexPkg == null) {
// This should never happen, because submitSessionToApexService ensures that no new
// apexes were installed.
throw new IllegalStateException("Unknown apex package " + packageName);
@@ -127,22 +138,22 @@
final SigningDetails existingSigningDetails;
try {
existingSigningDetails = ApkSignatureVerifier.verify(
- packageInfo.applicationInfo.sourceDir, SignatureSchemeVersion.JAR);
+ existingApexPkg.applicationInfo.sourceDir, SignatureSchemeVersion.JAR);
} catch (PackageParserException e) {
throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
- "Failed to parse APEX package " + packageInfo.applicationInfo.sourceDir, e);
+ "Failed to parse APEX package " + existingApexPkg.applicationInfo.sourceDir, e);
}
- // Now that we have both sets of signatures, demand that they're an exact match.
- if (Signature.areExactMatch(existingSigningDetails.signatures, signingDetails.signatures)) {
+ // Verify signing details for upgrade
+ if (signingDetails.checkCapability(existingSigningDetails,
+ PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA)) {
return;
}
throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
- "APK-container signature verification failed for package "
- + packageName + ". Signature of file "
- + apexPath + " does not match the signature of "
- + " the package already installed.");
+ "APK-container signature of APEX package " + packageName + " with version "
+ + newApexPkg.versionCodeMajor + " and path " + apexPath + " is not"
+ + " compatible with the one currently installed on device");
}
private List<PackageInfo> submitSessionToApexService(
@@ -239,8 +250,7 @@
try {
final List<PackageInfo> apexPackages = submitSessionToApexService(session);
for (PackageInfo apexPackage : apexPackages) {
- validateApexSignature(apexPackage.applicationInfo.sourceDir,
- apexPackage.packageName);
+ validateApexSignature(apexPackage, session.params.installFlags);
}
} catch (PackageManagerException e) {
session.setStagedSessionFailed(e.error, e.getMessage());
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index ead9d7a..1fe5512 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -2252,14 +2252,10 @@
@GuardedBy({"mPackagesLock", "mRestrictionsLock"})
private void fallbackToSingleUserLP() {
- int flags = UserInfo.FLAG_SYSTEM | UserInfo.FLAG_INITIALIZED;
- // In split system user mode, the admin and primary flags are assigned to the first human
- // user.
- if (!UserManager.isSplitSystemUser()) {
- flags |= UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY;
- }
+ int flags = UserInfo.FLAG_SYSTEM | UserInfo.FLAG_INITIALIZED | UserInfo.FLAG_ADMIN;
+ // In headless system user mode, the primary flag is assigned to the first human user.
if (!UserManager.isHeadlessSystemUserMode()) {
- flags |= UserInfo.FLAG_FULL;
+ flags |= UserInfo.FLAG_PRIMARY | UserInfo.FLAG_FULL;
}
// Create the system user
UserInfo system = new UserInfo(UserHandle.USER_SYSTEM, null, null, flags);
@@ -2773,9 +2769,9 @@
return null;
}
}
- // In split system user mode, we assign the first human user the primary flag.
+ // In headless system user mode, we assign the first human user the primary flag.
// And if there is no device owner, we also assign the admin flag to primary user.
- if (UserManager.isSplitSystemUser()
+ if (UserManager.isHeadlessSystemUserMode()
&& !isGuest && !isManagedProfile && getPrimaryUser() == null) {
flags |= UserInfo.FLAG_PRIMARY;
synchronized (mUsersLock) {
diff --git a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
index f5f7d67..cae09ea3 100644
--- a/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
+++ b/services/core/java/com/android/server/rollback/AppDataRollbackHelper.java
@@ -52,12 +52,13 @@
}
/**
- * Creates an app data snapshot for a specified {@code packageRollbackInfo}. Updates said {@code
- * packageRollbackInfo} with the inodes of the CE user data snapshot folders.
+ * Creates an app data snapshot for a specified {@code packageRollbackInfo} and the specified
+ * {@code userIds}. Updates said {@code packageRollbackInfo} with the inodes of the CE user data
+ * snapshot folders.
*/
- public void snapshotAppData(int snapshotId, PackageRollbackInfo packageRollbackInfo) {
- final int[] installedUsers = packageRollbackInfo.getInstalledUsers().toArray();
- for (int user : installedUsers) {
+ public void snapshotAppData(
+ int snapshotId, PackageRollbackInfo packageRollbackInfo, int[] userIds) {
+ for (int user : userIds) {
final int storageFlags;
if (isUserCredentialLocked(user)) {
// We've encountered a user that hasn't unlocked on a FBE device, so we can't copy
@@ -80,6 +81,7 @@
+ packageRollbackInfo.getPackageName() + ", userId: " + user, ie);
}
}
+ packageRollbackInfo.getSnapshottedUsers().addAll(IntArray.wrap(userIds));
}
/**
@@ -96,14 +98,14 @@
final IntArray pendingBackups = packageRollbackInfo.getPendingBackups();
final List<RestoreInfo> pendingRestores = packageRollbackInfo.getPendingRestores();
- boolean changedRollbackData = false;
+ boolean changedRollback = false;
// If we still have a userdata backup pending for this user, it implies that the user
// hasn't unlocked their device between the point of backup and the point of restore,
// so the data cannot have changed. We simply skip restoring CE data in this case.
if (pendingBackups != null && pendingBackups.indexOf(userId) != -1) {
pendingBackups.remove(pendingBackups.indexOf(userId));
- changedRollbackData = true;
+ changedRollback = true;
} else {
// There's no pending CE backup for this user, which means that we successfully
// managed to backup data for the user, which means we seek to restore it
@@ -111,7 +113,7 @@
// We've encountered a user that hasn't unlocked on a FBE device, so we can't
// copy across app user data until the user unlocks their device.
pendingRestores.add(new RestoreInfo(userId, appId, seInfo));
- changedRollbackData = true;
+ changedRollback = true;
} else {
// This user has unlocked, we can proceed to restore both CE and DE data.
storageFlags = storageFlags | Installer.FLAG_STORAGE_CE;
@@ -126,7 +128,7 @@
+ packageRollbackInfo.getPackageName(), ie);
}
- return changedRollbackData;
+ return changedRollback;
}
/**
@@ -158,29 +160,29 @@
* Packages pending backup for the given user are added to {@code pendingBackupPackages} along
* with their corresponding {@code PackageRollbackInfo}.
*
- * @return the list of {@code RollbackData} that has pending backups. Note that some of the
+ * @return the list of rollbacks that have pending backups. Note that some of the
* backups won't be performed, because they might be counteracted by pending restores.
*/
- private static List<RollbackData> computePendingBackups(int userId,
+ private static List<Rollback> computePendingBackups(int userId,
Map<String, PackageRollbackInfo> pendingBackupPackages,
- List<RollbackData> rollbacks) {
- List<RollbackData> rd = new ArrayList<>();
+ List<Rollback> rollbacks) {
+ List<Rollback> rollbacksWithPendingBackups = new ArrayList<>();
- for (RollbackData data : rollbacks) {
- for (PackageRollbackInfo info : data.info.getPackages()) {
+ for (Rollback rollback : rollbacks) {
+ for (PackageRollbackInfo info : rollback.info.getPackages()) {
final IntArray pendingBackupUsers = info.getPendingBackups();
if (pendingBackupUsers != null) {
final int idx = pendingBackupUsers.indexOf(userId);
if (idx != -1) {
pendingBackupPackages.put(info.getPackageName(), info);
- if (rd.indexOf(data) == -1) {
- rd.add(data);
+ if (rollbacksWithPendingBackups.indexOf(rollback) == -1) {
+ rollbacksWithPendingBackups.add(rollback);
}
}
}
}
}
- return rd;
+ return rollbacksWithPendingBackups;
}
/**
@@ -188,45 +190,45 @@
* Packages pending restore are added to {@code pendingRestores} along with their corresponding
* {@code PackageRollbackInfo}.
*
- * @return the list of {@code RollbackData} that has pending restores. Note that some of the
+ * @return the list of rollbacks that have pending restores. Note that some of the
* restores won't be performed, because they might be counteracted by pending backups.
*/
- private static List<RollbackData> computePendingRestores(int userId,
+ private static List<Rollback> computePendingRestores(int userId,
Map<String, PackageRollbackInfo> pendingRestorePackages,
- List<RollbackData> rollbacks) {
- List<RollbackData> rd = new ArrayList<>();
+ List<Rollback> rollbacks) {
+ List<Rollback> rollbacksWithPendingRestores = new ArrayList<>();
- for (RollbackData data : rollbacks) {
- for (PackageRollbackInfo info : data.info.getPackages()) {
+ for (Rollback rollback : rollbacks) {
+ for (PackageRollbackInfo info : rollback.info.getPackages()) {
final RestoreInfo ri = info.getRestoreInfo(userId);
if (ri != null) {
pendingRestorePackages.put(info.getPackageName(), info);
- if (rd.indexOf(data) == -1) {
- rd.add(data);
+ if (rollbacksWithPendingRestores.indexOf(rollback) == -1) {
+ rollbacksWithPendingRestores.add(rollback);
}
}
}
}
- return rd;
+ return rollbacksWithPendingRestores;
}
/**
- * Commits the list of pending backups and restores for a given {@code userId}. For the pending
- * backups updates corresponding {@code changedRollbackData} with a mapping from {@code userId}
- * to a inode of theirs CE user data snapshot.
+ * Commits the list of pending backups and restores for a given {@code userId}. For rollbacks
+ * with pending backups, updates the {@code Rollback} instance with a mapping from
+ * {@code userId} to inode of the CE user data snapshot.
*
- * @return the set of {@code RollbackData} that have been changed and should be stored on disk.
+ * @return the set of rollbacks with changes that should be stored on disk.
*/
- public Set<RollbackData> commitPendingBackupAndRestoreForUser(int userId,
- List<RollbackData> rollbacks) {
+ public Set<Rollback> commitPendingBackupAndRestoreForUser(int userId,
+ List<Rollback> rollbacks) {
final Map<String, PackageRollbackInfo> pendingBackupPackages = new HashMap<>();
- final List<RollbackData> pendingBackups = computePendingBackups(userId,
+ final List<Rollback> pendingBackups = computePendingBackups(userId,
pendingBackupPackages, rollbacks);
final Map<String, PackageRollbackInfo> pendingRestorePackages = new HashMap<>();
- final List<RollbackData> pendingRestores = computePendingRestores(userId,
+ final List<Rollback> pendingRestores = computePendingRestores(userId,
pendingRestorePackages, rollbacks);
// First remove unnecessary backups, i.e. when user did not unlock their phone between the
@@ -246,14 +248,15 @@
}
if (!pendingBackupPackages.isEmpty()) {
- for (RollbackData data : pendingBackups) {
- for (PackageRollbackInfo info : data.info.getPackages()) {
+ for (Rollback rollback : pendingBackups) {
+ for (PackageRollbackInfo info : rollback.info.getPackages()) {
final IntArray pendingBackupUsers = info.getPendingBackups();
final int idx = pendingBackupUsers.indexOf(userId);
if (idx != -1) {
try {
long ceSnapshotInode = mInstaller.snapshotAppData(info.getPackageName(),
- userId, data.info.getRollbackId(), Installer.FLAG_STORAGE_CE);
+ userId, rollback.info.getRollbackId(),
+ Installer.FLAG_STORAGE_CE);
info.putCeSnapshotInode(userId, ceSnapshotInode);
pendingBackupUsers.remove(idx);
} catch (InstallerException ie) {
@@ -267,13 +270,13 @@
}
if (!pendingRestorePackages.isEmpty()) {
- for (RollbackData data : pendingRestores) {
- for (PackageRollbackInfo info : data.info.getPackages()) {
+ for (Rollback rollback : pendingRestores) {
+ for (PackageRollbackInfo info : rollback.info.getPackages()) {
final RestoreInfo ri = info.getRestoreInfo(userId);
if (ri != null) {
try {
mInstaller.restoreAppDataSnapshot(info.getPackageName(), ri.appId,
- ri.seInfo, userId, data.info.getRollbackId(),
+ ri.seInfo, userId, rollback.info.getRollbackId(),
Installer.FLAG_STORAGE_CE);
info.removeRestoreInfo(ri);
} catch (InstallerException ie) {
@@ -285,7 +288,7 @@
}
}
- final Set<RollbackData> changed = new HashSet<>(pendingBackups);
+ final Set<Rollback> changed = new HashSet<>(pendingBackups);
changed.addAll(pendingRestores);
return changed;
}
diff --git a/services/core/java/com/android/server/rollback/RollbackData.java b/services/core/java/com/android/server/rollback/Rollback.java
similarity index 85%
rename from services/core/java/com/android/server/rollback/RollbackData.java
rename to services/core/java/com/android/server/rollback/Rollback.java
index b37e268..0d5746b 100644
--- a/services/core/java/com/android/server/rollback/RollbackData.java
+++ b/services/core/java/com/android/server/rollback/Rollback.java
@@ -32,7 +32,7 @@
* Information about a rollback available for a set of atomically installed
* packages.
*/
-class RollbackData {
+class Rollback {
@IntDef(flag = true, prefix = { "ROLLBACK_STATE_" }, value = {
ROLLBACK_STATE_ENABLING,
ROLLBACK_STATE_AVAILABLE,
@@ -102,13 +102,13 @@
public boolean restoreUserDataInProgress = false;
/**
- * Constructs a new, empty RollbackData instance.
+ * Constructs a new, empty Rollback instance.
*
* @param rollbackId the id of the rollback.
* @param backupDir the directory where the rollback data is stored.
* @param stagedSessionId the session id if this is a staged rollback, -1 otherwise.
*/
- RollbackData(int rollbackId, File backupDir, int stagedSessionId) {
+ Rollback(int rollbackId, File backupDir, int stagedSessionId) {
this.info = new RollbackInfo(rollbackId,
/* packages */ new ArrayList<>(),
/* isStaged */ stagedSessionId != -1,
@@ -121,9 +121,9 @@
}
/**
- * Constructs a RollbackData instance with full rollback data information.
+ * Constructs a pre-populated Rollback instance.
*/
- RollbackData(RollbackInfo info, File backupDir, Instant timestamp, int stagedSessionId,
+ Rollback(RollbackInfo info, File backupDir, Instant timestamp, int stagedSessionId,
@RollbackState int state, int apkSessionId, boolean restoreUserDataInProgress) {
this.info = info;
this.backupDir = backupDir;
@@ -143,9 +143,9 @@
static String rollbackStateToString(@RollbackState int state) {
switch (state) {
- case RollbackData.ROLLBACK_STATE_ENABLING: return "enabling";
- case RollbackData.ROLLBACK_STATE_AVAILABLE: return "available";
- case RollbackData.ROLLBACK_STATE_COMMITTED: return "committed";
+ case Rollback.ROLLBACK_STATE_ENABLING: return "enabling";
+ case Rollback.ROLLBACK_STATE_AVAILABLE: return "available";
+ case Rollback.ROLLBACK_STATE_COMMITTED: return "committed";
}
throw new AssertionError("Invalid rollback state: " + state);
}
@@ -153,9 +153,9 @@
static @RollbackState int rollbackStateFromString(String state)
throws ParseException {
switch (state) {
- case "enabling": return RollbackData.ROLLBACK_STATE_ENABLING;
- case "available": return RollbackData.ROLLBACK_STATE_AVAILABLE;
- case "committed": return RollbackData.ROLLBACK_STATE_COMMITTED;
+ case "enabling": return Rollback.ROLLBACK_STATE_ENABLING;
+ case "available": return Rollback.ROLLBACK_STATE_AVAILABLE;
+ case "committed": return Rollback.ROLLBACK_STATE_COMMITTED;
}
throw new ParseException("Invalid rollback state: " + state, 0);
}
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index f0cf9cf..02f98b4 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -110,13 +110,13 @@
@GuardedBy("mLock")
private final SparseBooleanArray mAllocatedRollbackIds = new SparseBooleanArray();
- // Package rollback data for rollbacks we are in the process of enabling.
+ // Rollbacks we are in the process of enabling.
@GuardedBy("mLock")
private final Set<NewRollback> mNewRollbacks = new ArraySet<>();
// The list of all rollbacks, including available and committed rollbacks.
@GuardedBy("mLock")
- private final List<RollbackData> mRollbacks;
+ private final List<Rollback> mRollbacks;
private final RollbackStore mRollbackStore;
@@ -127,7 +127,7 @@
private final AppDataRollbackHelper mAppDataRollbackHelper;
// This field stores the difference in Millis between the uptime (millis since device
- // has booted) and current time (device wall clock) - it's used to update rollback data
+ // has booted) and current time (device wall clock) - it's used to update rollback
// timestamps when the time is changed, by the user or by change of timezone.
// No need for guarding with lock because value is only accessed in handler thread.
private long mRelativeBootTime = calculateRelativeBootTime();
@@ -146,9 +146,9 @@
// Load rollback data from device storage.
synchronized (mLock) {
- mRollbacks = mRollbackStore.loadAllRollbackData();
- for (RollbackData data : mRollbacks) {
- mAllocatedRollbackIds.put(data.info.getRollbackId(), true);
+ mRollbacks = mRollbackStore.loadRollbacks();
+ for (Rollback rollback : mRollbacks) {
+ mAllocatedRollbackIds.put(rollback.info.getRollbackId(), true);
}
}
@@ -177,16 +177,14 @@
PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_TOKEN, -1);
int installFlags = intent.getIntExtra(
PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_INSTALL_FLAGS, 0);
- int[] installedUsers = intent.getIntArrayExtra(
- PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_INSTALLED_USERS);
int user = intent.getIntExtra(
PackageManagerInternal.EXTRA_ENABLE_ROLLBACK_USER, 0);
File newPackageCodePath = new File(intent.getData().getPath());
getHandler().post(() -> {
- boolean success = enableRollback(installFlags, newPackageCodePath,
- installedUsers, user, token);
+ boolean success =
+ enableRollback(installFlags, newPackageCodePath, user, token);
int ret = PackageManagerInternal.ENABLE_ROLLBACK_SUCCEEDED;
if (!success) {
ret = PackageManagerInternal.ENABLE_ROLLBACK_FAILED;
@@ -303,9 +301,9 @@
synchronized (mLock) {
List<RollbackInfo> rollbacks = new ArrayList<>();
for (int i = 0; i < mRollbacks.size(); ++i) {
- RollbackData data = mRollbacks.get(i);
- if (data.state == RollbackData.ROLLBACK_STATE_AVAILABLE) {
- rollbacks.add(data.info);
+ Rollback rollback = mRollbacks.get(i);
+ if (rollback.state == Rollback.ROLLBACK_STATE_AVAILABLE) {
+ rollbacks.add(rollback.info);
}
}
return new ParceledListSlice<>(rollbacks);
@@ -319,9 +317,9 @@
synchronized (mLock) {
List<RollbackInfo> rollbacks = new ArrayList<>();
for (int i = 0; i < mRollbacks.size(); ++i) {
- RollbackData data = mRollbacks.get(i);
- if (data.state == RollbackData.ROLLBACK_STATE_COMMITTED) {
- rollbacks.add(data.info);
+ Rollback rollback = mRollbacks.get(i);
+ if (rollback.state == Rollback.ROLLBACK_STATE_COMMITTED) {
+ rollbacks.add(rollback.info);
}
}
return new ParceledListSlice<>(rollbacks);
@@ -351,11 +349,11 @@
final long timeDifference = mRelativeBootTime - oldRelativeBootTime;
synchronized (mLock) {
- Iterator<RollbackData> iter = mRollbacks.iterator();
+ Iterator<Rollback> iter = mRollbacks.iterator();
while (iter.hasNext()) {
- RollbackData data = iter.next();
- data.timestamp = data.timestamp.plusMillis(timeDifference);
- saveRollbackData(data);
+ Rollback rollback = iter.next();
+ rollback.timestamp = rollback.timestamp.plusMillis(timeDifference);
+ saveRollback(rollback);
}
}
}
@@ -379,8 +377,8 @@
String callerPackageName, IntentSender statusReceiver) {
Slog.i(TAG, "Initiating rollback");
- RollbackData data = getRollbackForId(rollbackId);
- if (data == null || data.state != RollbackData.ROLLBACK_STATE_AVAILABLE) {
+ Rollback rollback = getRollbackForId(rollbackId);
+ if (rollback == null || rollback.state != Rollback.ROLLBACK_STATE_AVAILABLE) {
sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE_ROLLBACK_UNAVAILABLE,
"Rollback unavailable");
return;
@@ -404,14 +402,14 @@
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
parentParams.setRequestDowngrade(true);
parentParams.setMultiPackage();
- if (data.isStaged()) {
+ if (rollback.isStaged()) {
parentParams.setStaged();
}
int parentSessionId = packageInstaller.createSession(parentParams);
PackageInstaller.Session parentSession = packageInstaller.openSession(parentSessionId);
- for (PackageRollbackInfo info : data.info.getPackages()) {
+ for (PackageRollbackInfo info : rollback.info.getPackages()) {
PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
PackageInstaller.SessionParams.MODE_FULL_INSTALL);
// TODO: We can't get the installerPackageName for apex
@@ -426,7 +424,7 @@
params.setRequestDowngrade(true);
params.setRequiredInstalledVersionCode(
info.getVersionRolledBackFrom().getLongVersionCode());
- if (data.isStaged()) {
+ if (rollback.isStaged()) {
params.setStaged();
}
if (info.isApex()) {
@@ -435,7 +433,7 @@
int sessionId = packageInstaller.createSession(params);
PackageInstaller.Session session = packageInstaller.openSession(sessionId);
File[] packageCodePaths = RollbackStore.getPackageCodePaths(
- data, info.getPackageName());
+ rollback, info.getPackageName());
if (packageCodePaths == null) {
sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE,
"Backup copy of package inaccessible");
@@ -476,8 +474,8 @@
// TODO: Could this cause a rollback to be
// resurrected if it should otherwise have
// expired by now?
- data.state = RollbackData.ROLLBACK_STATE_AVAILABLE;
- data.restoreUserDataInProgress = false;
+ rollback.state = Rollback.ROLLBACK_STATE_AVAILABLE;
+ rollback.restoreUserDataInProgress = false;
}
sendFailure(statusReceiver, RollbackManager.STATUS_FAILURE_INSTALL,
"Rollback downgrade install failed: "
@@ -487,17 +485,17 @@
}
synchronized (mLock) {
- if (!data.isStaged()) {
+ if (!rollback.isStaged()) {
// All calls to restoreUserData should have
// completed by now for a non-staged install.
- data.restoreUserDataInProgress = false;
+ rollback.restoreUserDataInProgress = false;
}
- data.info.setCommittedSessionId(parentSessionId);
- data.info.getCausePackages().addAll(causePackages);
+ rollback.info.setCommittedSessionId(parentSessionId);
+ rollback.info.getCausePackages().addAll(causePackages);
}
- mRollbackStore.deletePackageCodePaths(data);
- saveRollbackData(data);
+ mRollbackStore.deletePackageCodePaths(rollback);
+ saveRollback(rollback);
sendSuccess(statusReceiver);
@@ -512,8 +510,8 @@
);
synchronized (mLock) {
- data.state = RollbackData.ROLLBACK_STATE_COMMITTED;
- data.restoreUserDataInProgress = true;
+ rollback.state = Rollback.ROLLBACK_STATE_COMMITTED;
+ rollback.restoreUserDataInProgress = true;
}
parentSession.commit(receiver.getIntentSender());
} catch (IOException e) {
@@ -535,7 +533,7 @@
updateRollbackLifetimeDurationInMillis();
synchronized (mLock) {
mRollbacks.clear();
- mRollbacks.addAll(mRollbackStore.loadAllRollbackData());
+ mRollbacks.addAll(mRollbackStore.loadRollbacks());
}
latch.countDown();
});
@@ -553,13 +551,13 @@
Manifest.permission.TEST_MANAGE_ROLLBACKS,
"expireRollbackForPackage");
synchronized (mLock) {
- Iterator<RollbackData> iter = mRollbacks.iterator();
+ Iterator<Rollback> iter = mRollbacks.iterator();
while (iter.hasNext()) {
- RollbackData data = iter.next();
- for (PackageRollbackInfo info : data.info.getPackages()) {
+ Rollback rollback = iter.next();
+ for (PackageRollbackInfo info : rollback.info.getPackages()) {
if (info.getPackageName().equals(packageName)) {
iter.remove();
- deleteRollback(data);
+ deleteRollback(rollback);
break;
}
}
@@ -583,16 +581,16 @@
void onUnlockUser(int userId) {
getHandler().post(() -> {
- final List<RollbackData> rollbacks;
+ final List<Rollback> rollbacks;
synchronized (mLock) {
rollbacks = new ArrayList<>(mRollbacks);
}
- final Set<RollbackData> changed =
+ final Set<Rollback> changed =
mAppDataRollbackHelper.commitPendingBackupAndRestoreForUser(userId, rollbacks);
- for (RollbackData rd : changed) {
- saveRollbackData(rd);
+ for (Rollback rollback : changed) {
+ saveRollback(rollback);
}
});
}
@@ -615,19 +613,19 @@
getHandler().post(() -> {
// Check to see if any rollback-enabled staged sessions or staged
// rollback sessions been applied.
- List<RollbackData> enabling = new ArrayList<>();
- List<RollbackData> restoreInProgress = new ArrayList<>();
+ List<Rollback> enabling = new ArrayList<>();
+ List<Rollback> restoreInProgress = new ArrayList<>();
Set<String> apexPackageNames = new HashSet<>();
synchronized (mLock) {
- for (RollbackData data : mRollbacks) {
- if (data.isStaged()) {
- if (data.state == RollbackData.ROLLBACK_STATE_ENABLING) {
- enabling.add(data);
- } else if (data.restoreUserDataInProgress) {
- restoreInProgress.add(data);
+ for (Rollback rollback : mRollbacks) {
+ if (rollback.isStaged()) {
+ if (rollback.state == Rollback.ROLLBACK_STATE_ENABLING) {
+ enabling.add(rollback);
+ } else if (rollback.restoreUserDataInProgress) {
+ restoreInProgress.add(rollback);
}
- for (PackageRollbackInfo info : data.info.getPackages()) {
+ for (PackageRollbackInfo info : rollback.info.getPackages()) {
if (info.isApex()) {
apexPackageNames.add(info.getPackageName());
}
@@ -636,32 +634,32 @@
}
}
- for (RollbackData data : enabling) {
+ for (Rollback rollback : enabling) {
PackageInstaller installer = mContext.getPackageManager().getPackageInstaller();
PackageInstaller.SessionInfo session = installer.getSessionInfo(
- data.stagedSessionId);
+ rollback.stagedSessionId);
if (session == null || session.isStagedSessionFailed()) {
// TODO: Do we need to remove this from
// mRollbacks, or is it okay to leave as
// unavailable until the next reboot when it will go
// away on its own?
- deleteRollback(data);
+ deleteRollback(rollback);
} else if (session.isStagedSessionApplied()) {
- makeRollbackAvailable(data);
+ makeRollbackAvailable(rollback);
}
}
- for (RollbackData data : restoreInProgress) {
+ for (Rollback rollback : restoreInProgress) {
PackageInstaller installer = mContext.getPackageManager().getPackageInstaller();
PackageInstaller.SessionInfo session = installer.getSessionInfo(
- data.stagedSessionId);
+ rollback.stagedSessionId);
// TODO: What if session is null?
if (session != null) {
if (session.isStagedSessionApplied() || session.isStagedSessionFailed()) {
synchronized (mLock) {
- data.restoreUserDataInProgress = false;
+ rollback.restoreUserDataInProgress = false;
}
- saveRollbackData(data);
+ saveRollback(rollback);
}
}
}
@@ -688,19 +686,19 @@
VersionedPackage installedVersion = getInstalledPackageVersion(packageName);
synchronized (mLock) {
- Iterator<RollbackData> iter = mRollbacks.iterator();
+ Iterator<Rollback> iter = mRollbacks.iterator();
while (iter.hasNext()) {
- RollbackData data = iter.next();
+ Rollback rollback = iter.next();
// TODO: Should we remove rollbacks in the ENABLING state here?
- if (data.state == RollbackData.ROLLBACK_STATE_AVAILABLE
- || data.state == RollbackData.ROLLBACK_STATE_ENABLING) {
- for (PackageRollbackInfo info : data.info.getPackages()) {
+ if (rollback.state == Rollback.ROLLBACK_STATE_AVAILABLE
+ || rollback.state == Rollback.ROLLBACK_STATE_ENABLING) {
+ for (PackageRollbackInfo info : rollback.info.getPackages()) {
if (info.getPackageName().equals(packageName)
&& !packageVersionsEqual(
info.getVersionRolledBackFrom(),
installedVersion)) {
iter.remove();
- deleteRollback(data);
+ deleteRollback(rollback);
break;
}
}
@@ -756,17 +754,18 @@
Instant now = Instant.now();
Instant oldest = null;
synchronized (mLock) {
- Iterator<RollbackData> iter = mRollbacks.iterator();
+ Iterator<Rollback> iter = mRollbacks.iterator();
while (iter.hasNext()) {
- RollbackData data = iter.next();
- if (data.state != RollbackData.ROLLBACK_STATE_AVAILABLE) {
+ Rollback rollback = iter.next();
+ if (rollback.state != Rollback.ROLLBACK_STATE_AVAILABLE) {
continue;
}
- if (!now.isBefore(data.timestamp.plusMillis(mRollbackLifetimeDurationInMillis))) {
+ if (!now.isBefore(
+ rollback.timestamp.plusMillis(mRollbackLifetimeDurationInMillis))) {
iter.remove();
- deleteRollback(data);
- } else if (oldest == null || oldest.isAfter(data.timestamp)) {
- oldest = data.timestamp;
+ deleteRollback(rollback);
+ } else if (oldest == null || oldest.isAfter(rollback.timestamp)) {
+ oldest = rollback.timestamp;
}
}
}
@@ -821,13 +820,12 @@
*
* @param installFlags information about what is being installed.
* @param newPackageCodePath path to the package about to be installed.
- * @param installedUsers the set of users for which a given package is installed.
* @param user the user that owns the install session to enable rollback on.
* @param token the distinct rollback token sent by package manager.
* @return true if enabling the rollback succeeds, false otherwise.
*/
- private boolean enableRollback(int installFlags, File newPackageCodePath,
- int[] installedUsers, @UserIdInt int user, int token) {
+ private boolean enableRollback(
+ int installFlags, File newPackageCodePath, @UserIdInt int user, int token) {
// Find the session id associated with this install.
// TODO: It would be nice if package manager or package installer told
@@ -872,38 +870,15 @@
// Check to see if this is the apk session for a staged session with
// rollback enabled.
- // TODO: This check could be made more efficient.
- RollbackData rd = null;
synchronized (mLock) {
for (int i = 0; i < mRollbacks.size(); ++i) {
- RollbackData data = mRollbacks.get(i);
- if (data.apkSessionId == parentSession.getSessionId()) {
- rd = data;
- break;
- }
- }
- }
-
- if (rd != null) {
- // This is the apk session for a staged session. We do not need to create a new rollback
- // for this session.
- PackageParser.PackageLite newPackage = null;
- try {
- newPackage = PackageParser.parsePackageLite(
- new File(packageSession.resolvedBaseCodePath), 0);
- } catch (PackageParser.PackageParserException e) {
- Slog.e(TAG, "Unable to parse new package", e);
- return false;
- }
- String packageName = newPackage.packageName;
- for (PackageRollbackInfo info : rd.info.getPackages()) {
- if (info.getPackageName().equals(packageName)) {
- info.getInstalledUsers().addAll(IntArray.wrap(installedUsers));
+ Rollback rollback = mRollbacks.get(i);
+ if (rollback.apkSessionId == parentSession.getSessionId()) {
+ // This is the apk session for a staged session with rollback enabled. We do not
+ // need to create a new rollback for this session.
return true;
}
}
- Slog.e(TAG, "Unable to find package in apk session");
- return false;
}
NewRollback newRollback;
@@ -919,7 +894,7 @@
}
newRollback.addToken(token);
- return enableRollbackForPackageSession(newRollback.data, packageSession, installedUsers);
+ return enableRollbackForPackageSession(newRollback.rollback, packageSession);
}
/**
@@ -929,8 +904,8 @@
*
* @return true on success, false on failure.
*/
- private boolean enableRollbackForPackageSession(RollbackData data,
- PackageInstaller.SessionInfo session, @NonNull int[] installedUsers) {
+ private boolean enableRollbackForPackageSession(Rollback rollback,
+ PackageInstaller.SessionInfo session) {
// TODO: Don't attempt to enable rollback for split installs.
final int installFlags = session.installFlags;
if ((installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) == 0) {
@@ -988,15 +963,14 @@
PackageRollbackInfo packageRollbackInfo = new PackageRollbackInfo(
newVersion, installedVersion,
new IntArray() /* pendingBackups */, new ArrayList<>() /* pendingRestores */,
- isApex, IntArray.wrap(installedUsers),
- new SparseLongArray() /* ceSnapshotInodes */);
+ isApex, new IntArray(), new SparseLongArray() /* ceSnapshotInodes */);
try {
ApplicationInfo appInfo = pkgInfo.applicationInfo;
- RollbackStore.backupPackageCodePath(data, packageName, appInfo.sourceDir);
+ RollbackStore.backupPackageCodePath(rollback, packageName, appInfo.sourceDir);
if (!ArrayUtils.isEmpty(appInfo.splitSourceDirs)) {
for (String sourceDir : appInfo.splitSourceDirs) {
- RollbackStore.backupPackageCodePath(data, packageName, sourceDir);
+ RollbackStore.backupPackageCodePath(rollback, packageName, sourceDir);
}
}
} catch (IOException e) {
@@ -1005,7 +979,7 @@
}
synchronized (mLock) {
- data.info.getPackages().add(packageRollbackInfo);
+ rollback.info.getPackages().add(packageRollbackInfo);
}
return true;
}
@@ -1019,7 +993,7 @@
}
getHandler().post(() -> {
- snapshotUserDataInternal(packageName);
+ snapshotUserDataInternal(packageName, userIds);
restoreUserDataInternal(packageName, userIds, appId, ceDataInode, seInfo, token);
final PackageManagerInternal pmi = LocalServices.getService(
PackageManagerInternal.class);
@@ -1027,19 +1001,20 @@
});
}
- private void snapshotUserDataInternal(String packageName) {
+ private void snapshotUserDataInternal(String packageName, int[] userIds) {
synchronized (mLock) {
// staged installs
for (int i = 0; i < mRollbacks.size(); i++) {
- RollbackData data = mRollbacks.get(i);
- if (data.state != RollbackData.ROLLBACK_STATE_ENABLING) {
+ Rollback rollback = mRollbacks.get(i);
+ if (rollback.state != Rollback.ROLLBACK_STATE_ENABLING) {
continue;
}
- for (PackageRollbackInfo info : data.info.getPackages()) {
+ for (PackageRollbackInfo info : rollback.info.getPackages()) {
if (info.getPackageName().equals(packageName)) {
- mAppDataRollbackHelper.snapshotAppData(data.info.getRollbackId(), info);
- saveRollbackData(data);
+ mAppDataRollbackHelper.snapshotAppData(
+ rollback.info.getRollbackId(), info, userIds);
+ saveRollback(rollback);
break;
}
}
@@ -1047,11 +1022,11 @@
// non-staged installs
PackageRollbackInfo info;
for (NewRollback rollback : mNewRollbacks) {
- info = getPackageRollbackInfo(rollback.data, packageName);
+ info = getPackageRollbackInfo(rollback.rollback, packageName);
if (info != null) {
- mAppDataRollbackHelper.snapshotAppData(rollback.data.info.getRollbackId(),
- info);
- saveRollbackData(rollback.data);
+ mAppDataRollbackHelper.snapshotAppData(
+ rollback.rollback.info.getRollbackId(), info, userIds);
+ saveRollback(rollback.rollback);
}
}
}
@@ -1060,31 +1035,31 @@
private void restoreUserDataInternal(String packageName, int[] userIds, int appId,
long ceDataInode, String seInfo, int token) {
PackageRollbackInfo info = null;
- RollbackData rollbackData = null;
+ Rollback rollback = null;
synchronized (mLock) {
for (int i = 0; i < mRollbacks.size(); ++i) {
- RollbackData data = mRollbacks.get(i);
- if (data.restoreUserDataInProgress) {
- info = getPackageRollbackInfo(data, packageName);
+ Rollback candidate = mRollbacks.get(i);
+ if (candidate.restoreUserDataInProgress) {
+ info = getPackageRollbackInfo(candidate, packageName);
if (info != null) {
- rollbackData = data;
+ rollback = candidate;
break;
}
}
}
}
- if (rollbackData == null) {
+ if (rollback == null) {
return;
}
for (int userId : userIds) {
- final boolean changedRollbackData = mAppDataRollbackHelper.restoreAppData(
- rollbackData.info.getRollbackId(), info, userId, appId, seInfo);
+ final boolean changedRollback = mAppDataRollbackHelper.restoreAppData(
+ rollback.info.getRollbackId(), info, userId, appId, seInfo);
// We've updated metadata about this rollback, so save it to flash.
- if (changedRollbackData) {
- saveRollbackData(rollbackData);
+ if (changedRollback) {
+ saveRollback(rollback);
}
}
}
@@ -1114,8 +1089,7 @@
}
if (!session.isMultiPackage()) {
- if (!enableRollbackForPackageSession(newRollback.data, session,
- new int[0])) {
+ if (!enableRollbackForPackageSession(newRollback.rollback, session)) {
Slog.e(TAG, "Unable to enable rollback for session: " + sessionId);
result.offer(false);
return;
@@ -1129,8 +1103,7 @@
result.offer(false);
return;
}
- if (!enableRollbackForPackageSession(newRollback.data, childSession,
- new int[0])) {
+ if (!enableRollbackForPackageSession(newRollback.rollback, childSession)) {
Slog.e(TAG, "Unable to enable rollback for session: " + sessionId);
result.offer(false);
return;
@@ -1155,20 +1128,20 @@
throw new SecurityException("notifyStagedApkSession may only be called by the system.");
}
getHandler().post(() -> {
- RollbackData rd = null;
+ Rollback rollback = null;
synchronized (mLock) {
for (int i = 0; i < mRollbacks.size(); ++i) {
- RollbackData data = mRollbacks.get(i);
- if (data.stagedSessionId == originalSessionId) {
- data.apkSessionId = apkSessionId;
- rd = data;
+ Rollback candidate = mRollbacks.get(i);
+ if (candidate.stagedSessionId == originalSessionId) {
+ candidate.apkSessionId = apkSessionId;
+ rollback = candidate;
break;
}
}
}
- if (rd != null) {
- saveRollbackData(rd);
+ if (rollback != null) {
+ saveRollback(rollback);
}
});
}
@@ -1278,7 +1251,7 @@
}
if (newRollback != null) {
- RollbackData rollback = completeEnableRollback(newRollback, success);
+ Rollback rollback = completeEnableRollback(newRollback, success);
if (rollback != null && !rollback.isStaged()) {
makeRollbackAvailable(rollback);
}
@@ -1291,32 +1264,32 @@
* This should be called after rollback has been enabled for all packages
* in the rollback. It does not make the rollback available yet.
*
- * @return the rollback data for a successfully enable-completed rollback,
+ * @return the Rollback instance for a successfully enable-completed rollback,
* or null on error.
*/
- private RollbackData completeEnableRollback(NewRollback newRollback, boolean success) {
- RollbackData data = newRollback.data;
+ private Rollback completeEnableRollback(NewRollback newRollback, boolean success) {
+ Rollback rollback = newRollback.rollback;
if (!success) {
// The install session was aborted, clean up the pending install.
- deleteRollback(data);
+ deleteRollback(rollback);
return null;
}
if (newRollback.isCancelled) {
Slog.e(TAG, "Rollback has been cancelled by PackageManager");
- deleteRollback(data);
+ deleteRollback(rollback);
return null;
}
- // It's safe to access data.info outside a synchronized block because
+ // It's safe to access rollback.info outside a synchronized block because
// this is running on the handler thread and all changes to the
- // data.info occur on the handler thread.
- if (data.info.getPackages().size() != newRollback.packageSessionIds.length) {
+ // rollback.info occur on the handler thread.
+ if (rollback.info.getPackages().size() != newRollback.packageSessionIds.length) {
Slog.e(TAG, "Failed to enable rollback for all packages in session.");
- deleteRollback(data);
+ deleteRollback(rollback);
return null;
}
- saveRollbackData(data);
+ saveRollback(rollback);
synchronized (mLock) {
// Note: There is a small window of time between when
// the session has been committed by the package
@@ -1324,25 +1297,25 @@
// here. Presumably the window is small enough that
// nobody will want to roll back the newly installed
// package before we make the rollback available.
- // TODO: We'll lose the rollback data if the
+ // TODO: We'll lose the rollback if the
// device reboots between when the session is
// committed and this point. Revisit this after
// adding support for rollback of staged installs.
- mRollbacks.add(data);
+ mRollbacks.add(rollback);
}
- return data;
+ return rollback;
}
- private void makeRollbackAvailable(RollbackData data) {
+ private void makeRollbackAvailable(Rollback rollback) {
// TODO: What if the rollback has since been expired, for example due
// to a new package being installed. Won't this revive an expired
// rollback? Consider adding a ROLLBACK_STATE_EXPIRED to address this.
synchronized (mLock) {
- data.state = RollbackData.ROLLBACK_STATE_AVAILABLE;
- data.timestamp = Instant.now();
+ rollback.state = Rollback.ROLLBACK_STATE_AVAILABLE;
+ rollback.timestamp = Instant.now();
}
- saveRollbackData(data);
+ saveRollback(rollback);
// TODO(zezeozue): Provide API to explicitly start observing instead
// of doing this for all rollbacks. If we do this for all rollbacks,
@@ -1350,8 +1323,8 @@
// After enabling and commiting any rollback, observe packages and
// prepare to rollback if packages crashes too frequently.
List<String> packages = new ArrayList<>();
- for (int i = 0; i < data.info.getPackages().size(); i++) {
- packages.add(data.info.getPackages().get(i).getPackageName());
+ for (int i = 0; i < rollback.info.getPackages().size(); i++) {
+ packages.add(rollback.info.getPackages().get(i).getPackageName());
}
mPackageHealthObserver.startObservingHealth(packages,
mRollbackLifetimeDurationInMillis);
@@ -1359,15 +1332,14 @@
}
/*
- * Returns the RollbackData, if any, for a rollback with the given
- * rollbackId.
+ * Returns the rollback with the given rollbackId, if any.
*/
- private RollbackData getRollbackForId(int rollbackId) {
+ private Rollback getRollbackForId(int rollbackId) {
synchronized (mLock) {
for (int i = 0; i < mRollbacks.size(); ++i) {
- RollbackData data = mRollbacks.get(i);
- if (data.info.getRollbackId() == rollbackId) {
- return data;
+ Rollback rollback = mRollbacks.get(i);
+ if (rollback.info.getRollbackId() == rollbackId) {
+ return rollback;
}
}
}
@@ -1377,11 +1349,11 @@
/**
* Returns the {@code PackageRollbackInfo} associated with {@code packageName} from
- * a specified {@code RollbackData}.
+ * a specified {@code Rollback}.
*/
- private static PackageRollbackInfo getPackageRollbackInfo(RollbackData data,
+ private static PackageRollbackInfo getPackageRollbackInfo(Rollback rollback,
String packageName) {
- for (PackageRollbackInfo info : data.info.getPackages()) {
+ for (PackageRollbackInfo info : rollback.info.getPackages()) {
if (info.getPackageName().equals(packageName)) {
return info;
}
@@ -1405,30 +1377,30 @@
throw new IllegalStateException("Failed to allocate rollback ID");
}
- private void deleteRollback(RollbackData rollbackData) {
- for (PackageRollbackInfo info : rollbackData.info.getPackages()) {
- IntArray installedUsers = info.getInstalledUsers();
- for (int i = 0; i < installedUsers.size(); i++) {
- int userId = installedUsers.get(i);
- mAppDataRollbackHelper.destroyAppDataSnapshot(rollbackData.info.getRollbackId(),
+ private void deleteRollback(Rollback rollback) {
+ for (PackageRollbackInfo info : rollback.info.getPackages()) {
+ IntArray snapshottedUsers = info.getSnapshottedUsers();
+ for (int i = 0; i < snapshottedUsers.size(); i++) {
+ int userId = snapshottedUsers.get(i);
+ mAppDataRollbackHelper.destroyAppDataSnapshot(rollback.info.getRollbackId(),
info, userId);
}
}
- mRollbackStore.deleteRollbackData(rollbackData);
+ mRollbackStore.deleteRollback(rollback);
}
/**
- * Saves rollback data, swallowing any IOExceptions.
+ * Saves a rollback, swallowing any IOExceptions.
* For those times when it's not obvious what to do about the IOException.
* TODO: Double check we can't do a better job handling the IOException in
* a cases where this method is called.
*/
- private void saveRollbackData(RollbackData rollbackData) {
+ private void saveRollback(Rollback rollback) {
try {
- mRollbackStore.saveRollbackData(rollbackData);
+ mRollbackStore.saveRollback(rollback);
} catch (IOException ioe) {
- Slog.e(TAG, "Unable to save rollback info for: "
- + rollbackData.info.getRollbackId(), ioe);
+ Slog.e(TAG, "Unable to save rollback for: "
+ + rollback.info.getRollbackId(), ioe);
}
}
@@ -1436,14 +1408,14 @@
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
IndentingPrintWriter ipw = new IndentingPrintWriter(pw, " ");
synchronized (mLock) {
- for (RollbackData data : mRollbacks) {
- RollbackInfo info = data.info;
+ for (Rollback rollback : mRollbacks) {
+ RollbackInfo info = rollback.info;
ipw.println(info.getRollbackId() + ":");
ipw.increaseIndent();
- ipw.println("-state: " + data.getStateAsString());
- ipw.println("-timestamp: " + data.timestamp);
- if (data.stagedSessionId != -1) {
- ipw.println("-stagedSessionId: " + data.stagedSessionId);
+ ipw.println("-state: " + rollback.getStateAsString());
+ ipw.println("-timestamp: " + rollback.timestamp);
+ if (rollback.stagedSessionId != -1) {
+ ipw.println("-stagedSessionId: " + rollback.stagedSessionId);
}
ipw.println("-packages:");
ipw.increaseIndent();
@@ -1453,7 +1425,7 @@
+ " -> " + pkg.getVersionRolledBackTo().getLongVersionCode());
}
ipw.decreaseIndent();
- if (data.state == RollbackData.ROLLBACK_STATE_COMMITTED) {
+ if (rollback.state == Rollback.ROLLBACK_STATE_COMMITTED) {
ipw.println("-causePackages:");
ipw.increaseIndent();
for (VersionedPackage cPkg : info.getCausePackages()) {
@@ -1479,7 +1451,7 @@
}
private static class NewRollback {
- public final RollbackData data;
+ public final Rollback rollback;
/**
* This array holds all of the rollback tokens associated with package sessions included
@@ -1497,9 +1469,9 @@
public final int[] packageSessionIds;
/**
- * Flag to determine whether the RollbackData has been cancelled.
+ * Flag to determine whether the rollback has been cancelled.
*
- * <p>RollbackData could be invalidated and cancelled if RollbackManager receives
+ * <p>Rollback could be invalidated and cancelled if RollbackManager receives
* {@link Intent#ACTION_CANCEL_ENABLE_ROLLBACK} from {@link PackageManager}.
*
* <p>The main underlying assumption here is that if enabling the rollback times out, then
@@ -1509,8 +1481,8 @@
*/
public boolean isCancelled = false;
- NewRollback(RollbackData data, int[] packageSessionIds) {
- this.data = data;
+ NewRollback(Rollback rollback, int[] packageSessionIds) {
+ this.rollback = rollback;
this.packageSessionIds = packageSessionIds;
}
@@ -1525,13 +1497,13 @@
NewRollback createNewRollbackLocked(PackageInstaller.SessionInfo parentSession) {
int rollbackId = allocateRollbackIdLocked();
- final RollbackData data;
+ final Rollback rollback;
int parentSessionId = parentSession.getSessionId();
if (parentSession.isStaged()) {
- data = mRollbackStore.createStagedRollback(rollbackId, parentSessionId);
+ rollback = mRollbackStore.createStagedRollback(rollbackId, parentSessionId);
} else {
- data = mRollbackStore.createNonStagedRollback(rollbackId);
+ rollback = mRollbackStore.createNonStagedRollback(rollbackId);
}
int[] packageSessionIds;
@@ -1541,7 +1513,7 @@
packageSessionIds = new int[]{parentSessionId};
}
- return new NewRollback(data, packageSessionIds);
+ return new NewRollback(rollback, packageSessionIds);
}
/**
@@ -1552,10 +1524,10 @@
NewRollback getNewRollbackForPackageSessionLocked(int packageSessionId) {
// We expect mNewRollbacks to be a very small list; linear search
// should be plenty fast.
- for (NewRollback newRollbackData : mNewRollbacks) {
- for (int id : newRollbackData.packageSessionIds) {
+ for (NewRollback newRollback: mNewRollbacks) {
+ for (int id : newRollback.packageSessionIds) {
if (id == packageSessionId) {
- return newRollbackData;
+ return newRollback;
}
}
}
diff --git a/services/core/java/com/android/server/rollback/RollbackStore.java b/services/core/java/com/android/server/rollback/RollbackStore.java
index 1c36dc7..b2448f6 100644
--- a/services/core/java/com/android/server/rollback/RollbackStore.java
+++ b/services/core/java/com/android/server/rollback/RollbackStore.java
@@ -16,8 +16,8 @@
package com.android.server.rollback;
-import static com.android.server.rollback.RollbackData.rollbackStateFromString;
-import static com.android.server.rollback.RollbackData.rollbackStateToString;
+import static com.android.server.rollback.Rollback.rollbackStateFromString;
+import static com.android.server.rollback.Rollback.rollbackStateToString;
import android.annotation.NonNull;
import android.content.pm.VersionedPackage;
@@ -73,17 +73,17 @@
}
/**
- * Reads the rollback data from persistent storage.
+ * Reads the rollbacks from persistent storage.
*/
- List<RollbackData> loadAllRollbackData() {
- List<RollbackData> rollbacks = new ArrayList<>();
+ List<Rollback> loadRollbacks() {
+ List<Rollback> rollbacks = new ArrayList<>();
mRollbackDataDir.mkdirs();
for (File rollbackDir : mRollbackDataDir.listFiles()) {
if (rollbackDir.isDirectory()) {
try {
- rollbacks.add(loadRollbackData(rollbackDir));
+ rollbacks.add(loadRollback(rollbackDir));
} catch (IOException e) {
- Slog.e(TAG, "Unable to read rollback data at " + rollbackDir, e);
+ Slog.e(TAG, "Unable to read rollback at " + rollbackDir, e);
removeFile(rollbackDir);
}
}
@@ -191,21 +191,21 @@
}
/**
- * Creates a new RollbackData instance for a non-staged rollback with
+ * Creates a new Rollback instance for a non-staged rollback with
* backupDir assigned.
*/
- RollbackData createNonStagedRollback(int rollbackId) {
+ Rollback createNonStagedRollback(int rollbackId) {
File backupDir = new File(mRollbackDataDir, Integer.toString(rollbackId));
- return new RollbackData(rollbackId, backupDir, -1);
+ return new Rollback(rollbackId, backupDir, -1);
}
/**
- * Creates a new RollbackData instance for a staged rollback with
+ * Creates a new Rollback instance for a staged rollback with
* backupDir assigned.
*/
- RollbackData createStagedRollback(int rollbackId, int stagedSessionId) {
+ Rollback createStagedRollback(int rollbackId, int stagedSessionId) {
File backupDir = new File(mRollbackDataDir, Integer.toString(rollbackId));
- return new RollbackData(rollbackId, backupDir, stagedSessionId);
+ return new Rollback(rollbackId, backupDir, stagedSessionId);
}
/**
@@ -213,10 +213,10 @@
* For packages containing splits, this method should be called for each
* of the package's split apks in addition to the base apk.
*/
- static void backupPackageCodePath(RollbackData data, String packageName, String codePath)
+ static void backupPackageCodePath(Rollback rollback, String packageName, String codePath)
throws IOException {
File sourceFile = new File(codePath);
- File targetDir = new File(data.backupDir, packageName);
+ File targetDir = new File(rollback.backupDir, packageName);
targetDir.mkdirs();
File targetFile = new File(targetDir, sourceFile.getName());
@@ -228,8 +228,8 @@
* Returns the apk or apex files backed up for the given package.
* Includes the base apk and any splits. Returns null if none found.
*/
- static File[] getPackageCodePaths(RollbackData data, String packageName) {
- File targetDir = new File(data.backupDir, packageName);
+ static File[] getPackageCodePaths(Rollback rollback, String packageName) {
+ File targetDir = new File(rollback.backupDir, packageName);
File[] files = targetDir.listFiles();
if (files == null || files.length == 0) {
return null;
@@ -241,27 +241,27 @@
* Deletes all backed up apks and apex files associated with the given
* rollback.
*/
- static void deletePackageCodePaths(RollbackData data) {
- for (PackageRollbackInfo info : data.info.getPackages()) {
- File targetDir = new File(data.backupDir, info.getPackageName());
+ static void deletePackageCodePaths(Rollback rollback) {
+ for (PackageRollbackInfo info : rollback.info.getPackages()) {
+ File targetDir = new File(rollback.backupDir, info.getPackageName());
removeFile(targetDir);
}
}
/**
- * Saves the rollback data to persistent storage.
+ * Saves the given rollback to persistent storage.
*/
- void saveRollbackData(RollbackData data) throws IOException {
+ void saveRollback(Rollback rollback) throws IOException {
try {
JSONObject dataJson = new JSONObject();
- dataJson.put("info", rollbackInfoToJson(data.info));
- dataJson.put("timestamp", data.timestamp.toString());
- dataJson.put("stagedSessionId", data.stagedSessionId);
- dataJson.put("state", rollbackStateToString(data.state));
- dataJson.put("apkSessionId", data.apkSessionId);
- dataJson.put("restoreUserDataInProgress", data.restoreUserDataInProgress);
+ dataJson.put("info", rollbackInfoToJson(rollback.info));
+ dataJson.put("timestamp", rollback.timestamp.toString());
+ dataJson.put("stagedSessionId", rollback.stagedSessionId);
+ dataJson.put("state", rollbackStateToString(rollback.state));
+ dataJson.put("apkSessionId", rollback.apkSessionId);
+ dataJson.put("restoreUserDataInProgress", rollback.restoreUserDataInProgress);
- PrintWriter pw = new PrintWriter(new File(data.backupDir, "rollback.json"));
+ PrintWriter pw = new PrintWriter(new File(rollback.backupDir, "rollback.json"));
pw.println(dataJson.toString());
pw.close();
} catch (JSONException e) {
@@ -270,23 +270,23 @@
}
/**
- * Removes all persistant storage associated with the given rollback data.
+ * Removes all persistent storage associated with the given rollback.
*/
- void deleteRollbackData(RollbackData data) {
- removeFile(data.backupDir);
+ void deleteRollback(Rollback rollback) {
+ removeFile(rollback.backupDir);
}
/**
* Reads the metadata for a rollback from the given directory.
* @throws IOException in case of error reading the data.
*/
- private static RollbackData loadRollbackData(File backupDir) throws IOException {
+ private static Rollback loadRollback(File backupDir) throws IOException {
try {
File rollbackJsonFile = new File(backupDir, "rollback.json");
JSONObject dataJson = new JSONObject(
IoUtils.readFileAsString(rollbackJsonFile.getAbsolutePath()));
- return new RollbackData(
+ return new Rollback(
rollbackInfoFromJson(dataJson.getJSONObject("info")),
backupDir,
Instant.parse(dataJson.getString("timestamp")),
@@ -319,13 +319,14 @@
IntArray pendingBackups = info.getPendingBackups();
List<RestoreInfo> pendingRestores = info.getPendingRestores();
- IntArray installedUsers = info.getInstalledUsers();
+ IntArray snapshottedUsers = info.getSnapshottedUsers();
json.put("pendingBackups", convertToJsonArray(pendingBackups));
json.put("pendingRestores", convertToJsonArray(pendingRestores));
json.put("isApex", info.isApex());
- json.put("installedUsers", convertToJsonArray(installedUsers));
+ // Field is named 'installedUsers' for legacy reasons.
+ json.put("installedUsers", convertToJsonArray(snapshottedUsers));
json.put("ceSnapshotInodes", ceSnapshotInodesToJson(info.getCeSnapshotInodes()));
return json;
@@ -345,12 +346,13 @@
final boolean isApex = json.getBoolean("isApex");
- final IntArray installedUsers = convertToIntArray(json.getJSONArray("installedUsers"));
+ // Field is named 'installedUsers' for legacy reasons.
+ final IntArray snapshottedUsers = convertToIntArray(json.getJSONArray("installedUsers"));
final SparseLongArray ceSnapshotInodes = ceSnapshotInodesFromJson(
json.getJSONArray("ceSnapshotInodes"));
return new PackageRollbackInfo(versionRolledBackFrom, versionRolledBackTo,
- pendingBackups, pendingRestores, isApex, installedUsers, ceSnapshotInodes);
+ pendingBackups, pendingRestores, isApex, snapshottedUsers, ceSnapshotInodes);
}
private static JSONArray versionedPackagesToJson(List<VersionedPackage> packages)
diff --git a/services/core/java/com/android/server/security/KeyChainSystemService.java b/services/core/java/com/android/server/security/KeyChainSystemService.java
index 2f681a3..3c06d0e 100644
--- a/services/core/java/com/android/server/security/KeyChainSystemService.java
+++ b/services/core/java/com/android/server/security/KeyChainSystemService.java
@@ -27,7 +27,7 @@
import android.security.IKeyChainService;
import android.util.Slog;
-import com.android.server.DeviceIdleController;
+import com.android.server.DeviceIdleInternal;
import com.android.server.LocalServices;
import com.android.server.SystemService;
@@ -99,8 +99,8 @@
}
final String packageName = intent.getComponent().getPackageName();
- final DeviceIdleController.LocalService idleController =
- LocalServices.getService(DeviceIdleController.LocalService.class);
+ final DeviceIdleInternal idleController =
+ LocalServices.getService(DeviceIdleInternal.class);
idleController.addPowerSaveTempWhitelistApp(Process.myUid(), packageName,
KEYCHAIN_IDLE_WHITELIST_DURATION_MS, user.getIdentifier(), false, "keychain");
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index e14514b..d87a0ed 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -5125,9 +5125,17 @@
// relative layering of multiple APPLICATION_MEDIA/OVERLAY has never
// been defined and so we can use static layers and leave it that way.
if (w.mAttrs.type == TYPE_APPLICATION_MEDIA) {
- w.assignLayer(t, -2);
+ if (mWinAnimator.hasSurface()) {
+ w.assignRelativeLayer(t, mWinAnimator.mSurfaceController.mSurfaceControl, -2);
+ } else {
+ w.assignLayer(t, -2);
+ }
} else if (w.mAttrs.type == TYPE_APPLICATION_MEDIA_OVERLAY) {
- w.assignLayer(t, -1);
+ if (mWinAnimator.hasSurface()) {
+ w.assignRelativeLayer(t, mWinAnimator.mSurfaceController.mSurfaceControl, -1);
+ } else {
+ w.assignLayer(t, -1);
+ }
} else {
w.assignLayer(t, layer);
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 3d2a3f6..ed900b1 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -40,7 +40,9 @@
import android.database.sqlite.SQLiteCompatibilityWalFlags;
import android.database.sqlite.SQLiteGlobal;
import android.hardware.display.DisplayManagerInternal;
+import android.net.ConnectivityModuleConnector;
import android.net.NetworkStackClient;
+import android.net.wifi.WifiStackClient;
import android.os.BaseBundle;
import android.os.Binder;
import android.os.Build;
@@ -1283,6 +1285,14 @@
Slog.d(TAG, "ContentSuggestionsService not defined by OEM");
}
+ t.traceBegin("InitConnectivityModuleConnector");
+ try {
+ ConnectivityModuleConnector.getInstance().init(context);
+ } catch (Throwable e) {
+ reportWtf("initializing ConnectivityModuleConnector", e);
+ }
+ t.traceEnd();
+
t.traceBegin("InitNetworkStackClient");
try {
NetworkStackClient.getInstance().init();
@@ -1345,40 +1355,6 @@
t.traceEnd();
if (context.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_WIFI)) {
- // Wifi Service must be started first for wifi-related services.
- t.traceBegin("StartWifi");
- mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
- t.traceEnd();
- t.traceBegin("StartWifiScanning");
- mSystemServiceManager.startService(
- "com.android.server.wifi.scanner.WifiScanningService");
- t.traceEnd();
- }
-
- if (context.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_WIFI_RTT)) {
- t.traceBegin("StartRttService");
- mSystemServiceManager.startService(
- "com.android.server.wifi.rtt.RttService");
- t.traceEnd();
- }
-
- if (context.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_WIFI_AWARE)) {
- t.traceBegin("StartWifiAware");
- mSystemServiceManager.startService(WIFI_AWARE_SERVICE_CLASS);
- t.traceEnd();
- }
-
- if (context.getPackageManager().hasSystemFeature(
- PackageManager.FEATURE_WIFI_DIRECT)) {
- t.traceBegin("StartWifiP2P");
- mSystemServiceManager.startService(WIFI_P2P_SERVICE_CLASS);
- t.traceEnd();
- }
-
- if (context.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_LOWPAN)) {
t.traceBegin("StartLowpan");
mSystemServiceManager.startService(LOWPAN_SERVICE_CLASS);
@@ -2177,12 +2153,21 @@
// ActivityManagerService.mSystemReady and ActivityManagerService.mProcessesReady
// are set to true. Be careful if moving this to a different place in the
// startup sequence.
- NetworkStackClient.getInstance().start(context);
+ NetworkStackClient.getInstance().start();
} catch (Throwable e) {
reportWtf("starting Network Stack", e);
}
t.traceEnd();
+ t.traceBegin("StartWifiStack");
+ try {
+ WifiStackClient.getInstance().start();
+ } catch (Throwable e) {
+ reportWtf("starting Wifi Stack", e);
+ }
+ t.traceEnd();
+
+
t.traceBegin("MakeLocationServiceReady");
try {
if (locationF != null) {
diff --git a/services/net/java/android/net/ConnectivityModuleConnector.java b/services/net/java/android/net/ConnectivityModuleConnector.java
new file mode 100644
index 0000000..7333f58
--- /dev/null
+++ b/services/net/java/android/net/ConnectivityModuleConnector.java
@@ -0,0 +1,389 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.net;
+
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.net.util.SharedLog;
+import android.os.Build;
+import android.os.Environment;
+import android.os.IBinder;
+import android.os.Process;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.provider.DeviceConfig;
+import android.text.format.DateUtils;
+import android.util.ArraySet;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.File;
+import java.io.PrintWriter;
+
+/**
+ * Class used to communicate to the various networking mainline modules running in the network stack
+ * process from {@link com.android.server.SystemServer}.
+ * @hide
+ */
+public class ConnectivityModuleConnector {
+ private static final String TAG = ConnectivityModuleConnector.class.getSimpleName();
+ private static final String IN_PROCESS_SUFFIX = ".InProcess";
+
+ private static final String PREFS_FILE = "ConnectivityModuleConnector.xml";
+ private static final String PREF_KEY_LAST_CRASH_TIME = "lastcrash_time";
+ private static final String CONFIG_MIN_CRASH_INTERVAL_MS = "min_crash_interval";
+ private static final String CONFIG_MIN_UPTIME_BEFORE_CRASH_MS = "min_uptime_before_crash";
+ private static final String CONFIG_ALWAYS_RATELIMIT_NETWORKSTACK_CRASH =
+ "always_ratelimit_networkstack_crash";
+
+ // Even if the network stack is lost, do not crash the system more often than this.
+ // Connectivity would be broken, but if the user needs the device for something urgent
+ // (like calling emergency services) we should not bootloop the device.
+ // This is the default value: the actual value can be adjusted via device config.
+ private static final long DEFAULT_MIN_CRASH_INTERVAL_MS = 6 * DateUtils.HOUR_IN_MILLIS;
+
+ // Even if the network stack is lost, do not crash the system server if it was less than
+ // this much after boot. This avoids bootlooping the device, and crashes should address very
+ // infrequent failures, not failures on boot.
+ private static final long DEFAULT_MIN_UPTIME_BEFORE_CRASH_MS = 30 * DateUtils.MINUTE_IN_MILLIS;
+
+ private static ConnectivityModuleConnector sInstance;
+
+ private Context mContext;
+ @GuardedBy("mLog")
+ private final SharedLog mLog = new SharedLog(TAG);
+ @GuardedBy("mHealthListeners")
+ private final ArraySet<ConnectivityModuleHealthListener> mHealthListeners = new ArraySet<>();
+
+ private ConnectivityModuleConnector() { }
+
+ /**
+ * Get the {@link ConnectivityModuleConnector} singleton instance.
+ */
+ public static synchronized ConnectivityModuleConnector getInstance() {
+ if (sInstance == null) {
+ sInstance = new ConnectivityModuleConnector();
+ }
+ return sInstance;
+ }
+
+ /**
+ * Initialize the network stack connector. Should be called only once on device startup, before
+ * any client attempts to use the network stack.
+ */
+ public void init(Context context) {
+ log("Network stack init");
+ mContext = context;
+ }
+
+ /**
+ * Callback interface for severe failures of the NetworkStack.
+ *
+ * <p>Useful for health monitors such as PackageWatchdog.
+ */
+ public interface ConnectivityModuleHealthListener {
+ /**
+ * Called when there is a severe failure of the network stack.
+ * @param packageName Package name of the network stack.
+ */
+ void onNetworkStackFailure(@NonNull String packageName);
+ }
+
+ /**
+ * Callback invoked by the connector once the connection to the corresponding module is
+ * established.
+ */
+ public interface ModuleServiceCallback {
+ /**
+ * Invoked when the corresponding service has connected.
+ *
+ * @param iBinder Binder object for the service.
+ */
+ void onModuleServiceConnected(@NonNull IBinder iBinder);
+ }
+
+
+ /**
+ * Add a {@link ConnectivityModuleHealthListener} to listen to network stack health events.
+ */
+ public void registerHealthListener(@NonNull ConnectivityModuleHealthListener listener) {
+ synchronized (mHealthListeners) {
+ mHealthListeners.add(listener);
+ }
+ }
+
+ /**
+ * Start a module running in the network stack or system_server process. Should be called only
+ * once for each module per device startup.
+ *
+ * <p>This method will start a networking module either in the network stack
+ * process, or inside the system server on devices that do not support the corresponding
+ * mainline network . The corresponding networking module service's binder
+ * object will then be delivered asynchronously via the provided {@link ModuleServiceCallback}.
+ *
+ * @param serviceIntentBaseAction Base action to use for constructing the intent needed to
+ * bind to the corresponding module.
+ * @param servicePermissionName Permission to be held by the corresponding module.
+ */
+ public void startModuleService(
+ @NonNull String serviceIntentBaseAction,
+ @NonNull String servicePermissionName,
+ @NonNull ModuleServiceCallback callback) {
+ log("Starting networking module " + serviceIntentBaseAction);
+
+ final PackageManager pm = mContext.getPackageManager();
+
+ // Try to bind in-process if the device was shipped with an in-process version
+ Intent intent = getModuleServiceIntent(pm, serviceIntentBaseAction, servicePermissionName,
+ true /* inSystemProcess */);
+
+ // Otherwise use the updatable module version
+ if (intent == null) {
+ intent = getModuleServiceIntent(pm, serviceIntentBaseAction, servicePermissionName,
+ false /* inSystemProcess */);
+ log("Starting networking module in network_stack process");
+ } else {
+ log("Starting networking module in system_server process");
+ }
+
+ if (intent == null) {
+ maybeCrashWithTerribleFailure("Could not resolve the networking module", null);
+ return;
+ }
+
+ final String packageName = intent.getComponent().getPackageName();
+
+ // Start the network stack. The service will be added to the service manager by the
+ // corresponding client in ModuleServiceCallback.onModuleServiceConnected().
+ if (!mContext.bindServiceAsUser(
+ intent, new ModuleServiceConnection(packageName, callback),
+ Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.SYSTEM)) {
+ maybeCrashWithTerribleFailure(
+ "Could not bind to networking module in-process, or in app with "
+ + intent, packageName);
+ return;
+ }
+
+ log("Networking module service start requested");
+ }
+
+ private class ModuleServiceConnection implements ServiceConnection {
+ @NonNull
+ private final String mPackageName;
+ @NonNull
+ private final ModuleServiceCallback mModuleServiceCallback;
+
+ private ModuleServiceConnection(
+ @NonNull String packageName,
+ @NonNull ModuleServiceCallback moduleCallback) {
+ mPackageName = packageName;
+ mModuleServiceCallback = moduleCallback;
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ logi("Networking module service connected");
+ mModuleServiceCallback.onModuleServiceConnected(service);
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ // onServiceDisconnected is not being called on device shutdown, so this method being
+ // called always indicates a bad state for the system server.
+ // This code path is only run by the system server: only the system server binds
+ // to the NetworkStack as a service. Other processes get the NetworkStack from
+ // the ServiceManager.
+ maybeCrashWithTerribleFailure("Lost network stack", mPackageName);
+ }
+ }
+
+ @Nullable
+ private Intent getModuleServiceIntent(
+ @NonNull PackageManager pm, @NonNull String serviceIntentBaseAction,
+ @NonNull String servicePermissionName, boolean inSystemProcess) {
+ final Intent intent =
+ new Intent(inSystemProcess
+ ? serviceIntentBaseAction + IN_PROCESS_SUFFIX
+ : serviceIntentBaseAction);
+ final ComponentName comp = intent.resolveSystemService(pm, 0);
+ if (comp == null) {
+ return null;
+ }
+ intent.setComponent(comp);
+
+ int uid = -1;
+ try {
+ uid = pm.getPackageUidAsUser(comp.getPackageName(), UserHandle.USER_SYSTEM);
+ } catch (PackageManager.NameNotFoundException e) {
+ logWtf("Networking module package not found", e);
+ // Fall through
+ }
+
+ final int expectedUid = inSystemProcess ? Process.SYSTEM_UID : Process.NETWORK_STACK_UID;
+ if (uid != expectedUid) {
+ throw new SecurityException("Invalid network stack UID: " + uid);
+ }
+
+ if (!inSystemProcess) {
+ checkModuleServicePermission(pm, comp, servicePermissionName);
+ }
+
+ return intent;
+ }
+
+ private void checkModuleServicePermission(
+ @NonNull PackageManager pm, @NonNull ComponentName comp,
+ @NonNull String servicePermissionName) {
+ final int hasPermission =
+ pm.checkPermission(servicePermissionName, comp.getPackageName());
+ if (hasPermission != PERMISSION_GRANTED) {
+ throw new SecurityException(
+ "Networking module does not have permission " + servicePermissionName);
+ }
+ }
+
+ private synchronized void maybeCrashWithTerribleFailure(@NonNull String message,
+ @Nullable String packageName) {
+ logWtf(message, null);
+ // uptime is monotonic even after a framework restart
+ final long uptime = SystemClock.elapsedRealtime();
+ final long now = System.currentTimeMillis();
+ final long minCrashIntervalMs = DeviceConfig.getLong(DeviceConfig.NAMESPACE_CONNECTIVITY,
+ CONFIG_MIN_CRASH_INTERVAL_MS, DEFAULT_MIN_CRASH_INTERVAL_MS);
+ final long minUptimeBeforeCrash = DeviceConfig.getLong(DeviceConfig.NAMESPACE_CONNECTIVITY,
+ CONFIG_MIN_UPTIME_BEFORE_CRASH_MS, DEFAULT_MIN_UPTIME_BEFORE_CRASH_MS);
+ final boolean alwaysRatelimit = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_CONNECTIVITY,
+ CONFIG_ALWAYS_RATELIMIT_NETWORKSTACK_CRASH, false);
+
+ final SharedPreferences prefs = getSharedPreferences();
+ final long lastCrashTime = tryGetLastCrashTime(prefs);
+
+ // Only crash if there was enough time since boot, and (if known) enough time passed since
+ // the last crash.
+ // time and lastCrashTime may be unreliable if devices have incorrect clock time, but they
+ // are only used to limit the number of crashes compared to only using the time since boot,
+ // which would also be OK behavior by itself.
+ // - If lastCrashTime is incorrectly more than the current time, only look at uptime
+ // - If it is much less than current time, only look at uptime
+ // - If current time is during the next few hours after last crash time, don't crash.
+ // Considering that this only matters if last boot was some time ago, it's likely that
+ // time will be set correctly. Otherwise, not crashing is not a big problem anyway. Being
+ // in this last state would also not last for long since the window is only a few hours.
+ final boolean alwaysCrash = Build.IS_DEBUGGABLE && !alwaysRatelimit;
+ final boolean justBooted = uptime < minUptimeBeforeCrash;
+ final boolean haveLastCrashTime = (lastCrashTime != 0) && (lastCrashTime < now);
+ final boolean haveKnownRecentCrash =
+ haveLastCrashTime && (now < lastCrashTime + minCrashIntervalMs);
+ if (alwaysCrash || (!justBooted && !haveKnownRecentCrash)) {
+ // The system is not bound to its network stack (for example due to a crash in the
+ // network stack process): better crash rather than stay in a bad state where all
+ // networking is broken.
+ // Using device-encrypted SharedPreferences as DeviceConfig does not have a synchronous
+ // API to persist settings before a crash.
+ tryWriteLastCrashTime(prefs, now);
+ throw new IllegalStateException(message);
+ }
+
+ // Here the system crashed recently already. Inform listeners that something is
+ // definitely wrong.
+ if (packageName != null) {
+ final ArraySet<ConnectivityModuleHealthListener> listeners;
+ synchronized (mHealthListeners) {
+ listeners = new ArraySet<>(mHealthListeners);
+ }
+ for (ConnectivityModuleHealthListener listener : listeners) {
+ listener.onNetworkStackFailure(packageName);
+ }
+ }
+ }
+
+ @Nullable
+ private SharedPreferences getSharedPreferences() {
+ try {
+ final File prefsFile = new File(
+ Environment.getDataSystemDeDirectory(UserHandle.USER_SYSTEM), PREFS_FILE);
+ return mContext.createDeviceProtectedStorageContext()
+ .getSharedPreferences(prefsFile, Context.MODE_PRIVATE);
+ } catch (Throwable e) {
+ logWtf("Error loading shared preferences", e);
+ return null;
+ }
+ }
+
+ private long tryGetLastCrashTime(@Nullable SharedPreferences prefs) {
+ if (prefs == null) return 0L;
+ try {
+ return prefs.getLong(PREF_KEY_LAST_CRASH_TIME, 0L);
+ } catch (Throwable e) {
+ logWtf("Error getting last crash time", e);
+ return 0L;
+ }
+ }
+
+ private void tryWriteLastCrashTime(@Nullable SharedPreferences prefs, long value) {
+ if (prefs == null) return;
+ try {
+ prefs.edit().putLong(PREF_KEY_LAST_CRASH_TIME, value).commit();
+ } catch (Throwable e) {
+ logWtf("Error writing last crash time", e);
+ }
+ }
+
+ private void log(@NonNull String message) {
+ Slog.d(TAG, message);
+ synchronized (mLog) {
+ mLog.log(message);
+ }
+ }
+
+ private void logWtf(@NonNull String message, @Nullable Throwable e) {
+ Slog.wtf(TAG, message, e);
+ synchronized (mLog) {
+ mLog.e(message);
+ }
+ }
+
+ private void loge(@NonNull String message, @Nullable Throwable e) {
+ Slog.e(TAG, message, e);
+ synchronized (mLog) {
+ mLog.e(message);
+ }
+ }
+
+ private void logi(@NonNull String message) {
+ Slog.i(TAG, message);
+ synchronized (mLog) {
+ mLog.i(message);
+ }
+ }
+
+ /**
+ * Dump ConnectivityModuleConnector logs to the specified {@link PrintWriter}.
+ */
+ public void dump(PrintWriter pw) {
+ // dump is thread-safe on SharedLog
+ mLog.dump(null, pw, null);
+ }
+}
diff --git a/services/net/java/android/net/NetworkStackClient.java b/services/net/java/android/net/NetworkStackClient.java
index 56b728c..abb4666 100644
--- a/services/net/java/android/net/NetworkStackClient.java
+++ b/services/net/java/android/net/NetworkStackClient.java
@@ -15,40 +15,27 @@
*/
package android.net;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
import android.net.dhcp.DhcpServingParamsParcel;
import android.net.dhcp.IDhcpServerCallbacks;
import android.net.ip.IIpClientCallbacks;
import android.net.util.SharedLog;
import android.os.Binder;
-import android.os.Build;
-import android.os.Environment;
import android.os.IBinder;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
-import android.os.SystemClock;
import android.os.UserHandle;
-import android.provider.DeviceConfig;
-import android.text.format.DateUtils;
-import android.util.ArraySet;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
-import java.io.File;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -60,24 +47,6 @@
private static final String TAG = NetworkStackClient.class.getSimpleName();
private static final int NETWORKSTACK_TIMEOUT_MS = 10_000;
- private static final String IN_PROCESS_SUFFIX = ".InProcess";
- private static final String PREFS_FILE = "NetworkStackClientPrefs.xml";
- private static final String PREF_KEY_LAST_CRASH_TIME = "lastcrash_time";
- private static final String CONFIG_MIN_CRASH_INTERVAL_MS = "min_crash_interval";
- private static final String CONFIG_MIN_UPTIME_BEFORE_CRASH_MS = "min_uptime_before_crash";
- private static final String CONFIG_ALWAYS_RATELIMIT_NETWORKSTACK_CRASH =
- "always_ratelimit_networkstack_crash";
-
- // Even if the network stack is lost, do not crash the system more often than this.
- // Connectivity would be broken, but if the user needs the device for something urgent
- // (like calling emergency services) we should not bootloop the device.
- // This is the default value: the actual value can be adjusted via device config.
- private static final long DEFAULT_MIN_CRASH_INTERVAL_MS = 6 * DateUtils.HOUR_IN_MILLIS;
-
- // Even if the network stack is lost, do not crash the system server if it was less than
- // this much after boot. This avoids bootlooping the device, and crashes should address very
- // infrequent failures, not failures on boot.
- private static final long DEFAULT_MIN_UPTIME_BEFORE_CRASH_MS = 30 * DateUtils.MINUTE_IN_MILLIS;
private static NetworkStackClient sInstance;
@@ -93,26 +62,10 @@
private volatile boolean mWasSystemServerInitialized = false;
- @GuardedBy("mHealthListeners")
- private final ArraySet<NetworkStackHealthListener> mHealthListeners = new ArraySet<>();
-
private interface NetworkStackCallback {
void onNetworkStackConnected(INetworkStackConnector connector);
}
- /**
- * Callback interface for severe failures of the NetworkStack.
- *
- * <p>Useful for health monitors such as PackageWatchdog.
- */
- public interface NetworkStackHealthListener {
- /**
- * Called when there is a severe failure of the network stack.
- * @param packageName Package name of the network stack.
- */
- void onNetworkStackFailure(@NonNull String packageName);
- }
-
private NetworkStackClient() { }
/**
@@ -126,15 +79,6 @@
}
/**
- * Add a {@link NetworkStackHealthListener} to listen to network stack health events.
- */
- public void registerHealthListener(@NonNull NetworkStackHealthListener listener) {
- synchronized (mHealthListeners) {
- mHealthListeners.add(listener);
- }
- }
-
- /**
* Create a DHCP server according to the specified parameters.
*
* <p>The server will be returned asynchronously through the provided callbacks.
@@ -195,32 +139,13 @@
});
}
- private class NetworkStackConnection implements ServiceConnection {
- @NonNull
- private final Context mContext;
- @NonNull
- private final String mPackageName;
-
- private NetworkStackConnection(@NonNull Context context, @NonNull String packageName) {
- mContext = context;
- mPackageName = packageName;
- }
-
+ private class NetworkStackConnection implements
+ ConnectivityModuleConnector.ModuleServiceCallback {
@Override
- public void onServiceConnected(ComponentName name, IBinder service) {
+ public void onModuleServiceConnected(IBinder service) {
logi("Network stack service connected");
registerNetworkStackService(service);
}
-
- @Override
- public void onServiceDisconnected(ComponentName name) {
- // onServiceDisconnected is not being called on device shutdown, so this method being
- // called always indicates a bad state for the system server.
- // This code path is only run by the system server: only the system server binds
- // to the NetworkStack as a service. Other processes get the NetworkStack from
- // the ServiceManager.
- maybeCrashWithTerribleFailure("Lost network stack", mContext, mPackageName);
- }
}
private void registerNetworkStackService(@NonNull IBinder service) {
@@ -259,171 +184,13 @@
* connector will then be delivered asynchronously to clients that requested it before it was
* started.
*/
- public void start(Context context) {
- log("Starting network stack");
-
- final PackageManager pm = context.getPackageManager();
-
- // Try to bind in-process if the device was shipped with an in-process version
- Intent intent = getNetworkStackIntent(pm, true /* inSystemProcess */);
-
- // Otherwise use the updatable module version
- if (intent == null) {
- intent = getNetworkStackIntent(pm, false /* inSystemProcess */);
- log("Starting network stack process");
- } else {
- log("Starting network stack in-process");
- }
-
- if (intent == null) {
- maybeCrashWithTerribleFailure("Could not resolve the network stack", context, null);
- return;
- }
-
- final String packageName = intent.getComponent().getPackageName();
-
- // Start the network stack. The service will be added to the service manager in
- // NetworkStackConnection.onServiceConnected().
- if (!context.bindServiceAsUser(intent, new NetworkStackConnection(context, packageName),
- Context.BIND_AUTO_CREATE | Context.BIND_IMPORTANT, UserHandle.SYSTEM)) {
- maybeCrashWithTerribleFailure(
- "Could not bind to network stack in-process, or in app with " + intent,
- context, packageName);
- return;
- }
-
+ public void start() {
+ ConnectivityModuleConnector.getInstance().startModuleService(
+ INetworkStackConnector.class.getName(), PERMISSION_MAINLINE_NETWORK_STACK,
+ new NetworkStackConnection());
log("Network stack service start requested");
}
- @Nullable
- private Intent getNetworkStackIntent(@NonNull PackageManager pm, boolean inSystemProcess) {
- final String baseAction = INetworkStackConnector.class.getName();
- final Intent intent =
- new Intent(inSystemProcess ? baseAction + IN_PROCESS_SUFFIX : baseAction);
- final ComponentName comp = intent.resolveSystemService(pm, 0);
-
- if (comp == null) {
- return null;
- }
- intent.setComponent(comp);
-
- int uid = -1;
- try {
- uid = pm.getPackageUidAsUser(comp.getPackageName(), UserHandle.USER_SYSTEM);
- } catch (PackageManager.NameNotFoundException e) {
- logWtf("Network stack package not found", e);
- // Fall through
- }
-
- final int expectedUid = inSystemProcess ? Process.SYSTEM_UID : Process.NETWORK_STACK_UID;
- if (uid != expectedUid) {
- throw new SecurityException("Invalid network stack UID: " + uid);
- }
-
- if (!inSystemProcess) {
- checkNetworkStackPermission(pm, comp);
- }
-
- return intent;
- }
-
- private void checkNetworkStackPermission(
- @NonNull PackageManager pm, @NonNull ComponentName comp) {
- final int hasPermission =
- pm.checkPermission(PERMISSION_MAINLINE_NETWORK_STACK, comp.getPackageName());
- if (hasPermission != PERMISSION_GRANTED) {
- throw new SecurityException(
- "Network stack does not have permission " + PERMISSION_MAINLINE_NETWORK_STACK);
- }
- }
-
- private void maybeCrashWithTerribleFailure(@NonNull String message,
- @NonNull Context context, @Nullable String packageName) {
- logWtf(message, null);
- // uptime is monotonic even after a framework restart
- final long uptime = SystemClock.elapsedRealtime();
- final long now = System.currentTimeMillis();
- final long minCrashIntervalMs = DeviceConfig.getLong(DeviceConfig.NAMESPACE_CONNECTIVITY,
- CONFIG_MIN_CRASH_INTERVAL_MS, DEFAULT_MIN_CRASH_INTERVAL_MS);
- final long minUptimeBeforeCrash = DeviceConfig.getLong(DeviceConfig.NAMESPACE_CONNECTIVITY,
- CONFIG_MIN_UPTIME_BEFORE_CRASH_MS, DEFAULT_MIN_UPTIME_BEFORE_CRASH_MS);
- final boolean alwaysRatelimit = DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_CONNECTIVITY,
- CONFIG_ALWAYS_RATELIMIT_NETWORKSTACK_CRASH, false);
-
- final SharedPreferences prefs = getSharedPreferences(context);
- final long lastCrashTime = tryGetLastCrashTime(prefs);
-
- // Only crash if there was enough time since boot, and (if known) enough time passed since
- // the last crash.
- // time and lastCrashTime may be unreliable if devices have incorrect clock time, but they
- // are only used to limit the number of crashes compared to only using the time since boot,
- // which would also be OK behavior by itself.
- // - If lastCrashTime is incorrectly more than the current time, only look at uptime
- // - If it is much less than current time, only look at uptime
- // - If current time is during the next few hours after last crash time, don't crash.
- // Considering that this only matters if last boot was some time ago, it's likely that
- // time will be set correctly. Otherwise, not crashing is not a big problem anyway. Being
- // in this last state would also not last for long since the window is only a few hours.
- final boolean alwaysCrash = Build.IS_DEBUGGABLE && !alwaysRatelimit;
- final boolean justBooted = uptime < minUptimeBeforeCrash;
- final boolean haveLastCrashTime = (lastCrashTime != 0) && (lastCrashTime < now);
- final boolean haveKnownRecentCrash =
- haveLastCrashTime && (now < lastCrashTime + minCrashIntervalMs);
- if (alwaysCrash || (!justBooted && !haveKnownRecentCrash)) {
- // The system is not bound to its network stack (for example due to a crash in the
- // network stack process): better crash rather than stay in a bad state where all
- // networking is broken.
- // Using device-encrypted SharedPreferences as DeviceConfig does not have a synchronous
- // API to persist settings before a crash.
- tryWriteLastCrashTime(prefs, now);
- throw new IllegalStateException(message);
- }
-
- // Here the system crashed recently already. Inform listeners that something is
- // definitely wrong.
- if (packageName != null) {
- final ArraySet<NetworkStackHealthListener> listeners;
- synchronized (mHealthListeners) {
- listeners = new ArraySet<>(mHealthListeners);
- }
- for (NetworkStackHealthListener listener : listeners) {
- listener.onNetworkStackFailure(packageName);
- }
- }
- }
-
- @Nullable
- private SharedPreferences getSharedPreferences(@NonNull Context context) {
- try {
- final File prefsFile = new File(
- Environment.getDataSystemDeDirectory(UserHandle.USER_SYSTEM), PREFS_FILE);
- return context.createDeviceProtectedStorageContext()
- .getSharedPreferences(prefsFile, Context.MODE_PRIVATE);
- } catch (Throwable e) {
- logWtf("Error loading shared preferences", e);
- return null;
- }
- }
-
- private long tryGetLastCrashTime(@Nullable SharedPreferences prefs) {
- if (prefs == null) return 0L;
- try {
- return prefs.getLong(PREF_KEY_LAST_CRASH_TIME, 0L);
- } catch (Throwable e) {
- logWtf("Error getting last crash time", e);
- return 0L;
- }
- }
-
- private void tryWriteLastCrashTime(@Nullable SharedPreferences prefs, long value) {
- if (prefs == null) return;
- try {
- prefs.edit().putLong(PREF_KEY_LAST_CRASH_TIME, value).commit();
- } catch (Throwable e) {
- logWtf("Error writing last crash time", e);
- }
- }
-
/**
* Log a message in the local log.
*/
@@ -524,6 +291,8 @@
public void dump(PrintWriter pw) {
// dump is thread-safe on SharedLog
mLog.dump(null, pw, null);
+ // dump connectivity module connector logs.
+ ConnectivityModuleConnector.getInstance().dump(pw);
final int requestsQueueLength;
synchronized (mPendingNetStackRequests) {
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 c92737b..ca3c6ce 100644
--- a/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/BackupManagerServiceTest.java
@@ -21,8 +21,6 @@
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
import static android.Manifest.permission.PACKAGE_USAGE_STATS;
-import static com.android.server.backup.testing.TransportData.backupTransport;
-
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertEquals;
@@ -41,10 +39,7 @@
import android.app.backup.IBackupManagerMonitor;
import android.app.backup.IBackupObserver;
import android.app.backup.IFullBackupRestoreObserver;
-import android.app.backup.ISelectBackupTransportCallback;
import android.content.Context;
-import android.content.Intent;
-import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.Process;
import android.os.UserHandle;
@@ -52,7 +47,6 @@
import android.platform.test.annotations.Presubmit;
import android.util.SparseArray;
-import com.android.server.backup.testing.TransportData;
import com.android.server.testing.shadows.ShadowApplicationPackageManager;
import com.android.server.testing.shadows.ShadowBinder;
import com.android.server.testing.shadows.ShadowEnvironment;
@@ -222,475 +216,6 @@
}
// ---------------------------------------------
- // Backup agent tests
- // ---------------------------------------------
-
- /** Test that the backup service routes methods correctly to the user that requests it. */
- @Test
- public void testDataChanged_onRegisteredUser_callsMethodForUser() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
-
- backupManagerService.dataChanged(mUserOneId, TEST_PACKAGE);
-
- verify(mUserOneService).dataChanged(TEST_PACKAGE);
- }
-
- /** Test that the backup service does not route methods for non-registered users. */
- @Test
- public void testDataChanged_onUnknownUser_doesNotPropagateCall() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
-
- backupManagerService.dataChanged(mUserTwoId, TEST_PACKAGE);
-
- verify(mUserOneService, never()).dataChanged(TEST_PACKAGE);
- }
-
- /** Test that the backup service routes methods correctly to the user that requests it. */
- @Test
- public void testAgentConnected_onRegisteredUser_callsMethodForUser() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
- IBinder agentBinder = mock(IBinder.class);
-
- backupManagerService.agentConnected(mUserOneId, TEST_PACKAGE, agentBinder);
-
- verify(mUserOneService).agentConnected(TEST_PACKAGE, agentBinder);
- }
-
- /** Test that the backup service does not route methods for non-registered users. */
- @Test
- public void testAgentConnected_onUnknownUser_doesNotPropagateCall() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
- IBinder agentBinder = mock(IBinder.class);
-
- backupManagerService.agentConnected(mUserTwoId, TEST_PACKAGE, agentBinder);
-
- verify(mUserOneService, never()).agentConnected(TEST_PACKAGE, agentBinder);
- }
-
- /** Test that the backup service routes methods correctly to the user that requests it. */
- @Test
- public void testAgentDisconnected_onRegisteredUser_callsMethodForUser() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
-
- backupManagerService.agentDisconnected(mUserOneId, TEST_PACKAGE);
-
- verify(mUserOneService).agentDisconnected(TEST_PACKAGE);
- }
-
- /** Test that the backup service does not route methods for non-registered users. */
- @Test
- public void testAgentDisconnected_onUnknownUser_doesNotPropagateCall() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
-
- backupManagerService.agentDisconnected(mUserTwoId, TEST_PACKAGE);
-
- verify(mUserOneService, never()).agentDisconnected(TEST_PACKAGE);
- }
-
- /** Test that the backup service routes methods correctly to the user that requests it. */
- @Test
- public void testOpComplete_onRegisteredUser_callsMethodForUser() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
-
- backupManagerService.opComplete(mUserOneId, /* token */ 0, /* result */ 0L);
-
- verify(mUserOneService).opComplete(/* token */ 0, /* result */ 0L);
- }
-
- /** Test that the backup service does not route methods for non-registered users. */
- @Test
- public void testOpComplete_onUnknownUser_doesNotPropagateCall() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
-
- backupManagerService.opComplete(mUserTwoId, /* token */ 0, /* result */ 0L);
-
- verify(mUserOneService, never()).opComplete(/* token */ 0, /* result */ 0L);
- }
-
- // ---------------------------------------------
- // Transport tests
- // ---------------------------------------------
-
- /** Test that the backup service routes methods correctly to the user that requests it. */
- @Test
- public void testInitializeTransports_onRegisteredUser_callsMethodForUser() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
- String[] transports = {TEST_TRANSPORT};
-
- backupManagerService.initializeTransports(mUserOneId, transports, /* observer */ null);
-
- verify(mUserOneService).initializeTransports(transports, /* observer */ null);
- }
-
- /** Test that the backup service does not route methods for non-registered users. */
- @Test
- public void testInitializeTransports_onUnknownUser_doesNotPropagateCall() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
- String[] transports = {TEST_TRANSPORT};
-
- backupManagerService.initializeTransports(mUserTwoId, transports, /* observer */ null);
-
- verify(mUserOneService, never()).initializeTransports(transports, /* observer */ null);
- }
-
- /** Test that the backup service routes methods correctly to the user that requests it. */
- @Test
- public void testClearBackupData_onRegisteredUser_callsMethodForUser() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
-
- backupManagerService.clearBackupData(mUserOneId, TEST_TRANSPORT, TEST_PACKAGE);
-
- verify(mUserOneService).clearBackupData(TEST_TRANSPORT, TEST_PACKAGE);
- }
-
- /** Test that the backup service does not route methods for non-registered users. */
- @Test
- public void testClearBackupData_onUnknownUser_doesNotPropagateCall() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
-
- backupManagerService.clearBackupData(mUserTwoId, TEST_TRANSPORT, TEST_PACKAGE);
-
- verify(mUserOneService, never()).clearBackupData(TEST_TRANSPORT, TEST_PACKAGE);
- }
-
- /** Test that the backup service routes methods correctly to the user that requests it. */
- @Test
- public void testGetCurrentTransport_onRegisteredUser_callsMethodForUser() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
-
- backupManagerService.getCurrentTransport(mUserOneId);
-
- verify(mUserOneService).getCurrentTransport();
- }
-
- /** Test that the backup service does not route methods for non-registered users. */
- @Test
- public void testGetCurrentTransport_onUnknownUser_doesNotPropagateCall() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
-
- backupManagerService.getCurrentTransport(mUserTwoId);
-
- verify(mUserOneService, never()).getCurrentTransport();
- }
-
- /** Test that the backup service routes methods correctly to the user that requests it. */
- @Test
- public void testGetCurrentTransportComponent_onRegisteredUser_callsMethodForUser()
- throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
-
- backupManagerService.getCurrentTransportComponent(mUserOneId);
-
- verify(mUserOneService).getCurrentTransportComponent();
- }
-
- /** Test that the backup service does not route methods for non-registered users. */
- @Test
- public void testGetCurrentTransportComponent_onUnknownUser_doesNotPropagateCall()
- throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
-
- backupManagerService.getCurrentTransportComponent(mUserTwoId);
-
- verify(mUserOneService, never()).getCurrentTransportComponent();
- }
-
- /** Test that the backup service routes methods correctly to the user that requests it. */
- @Test
- public void testListAllTransports_onRegisteredUser_callsMethodForUser() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
-
- backupManagerService.listAllTransports(mUserOneId);
-
- verify(mUserOneService).listAllTransports();
- }
-
- /** Test that the backup service does not route methods for non-registered users. */
- @Test
- public void testListAllTransports_onUnknownUser_doesNotPropagateCall() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
-
- backupManagerService.listAllTransports(mUserTwoId);
-
- verify(mUserOneService, never()).listAllTransports();
- }
-
- /** Test that the backup service routes methods correctly to the user that requests it. */
- @Test
- public void testListAllTransportComponents_onRegisteredUser_callsMethodForUser()
- throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
-
- backupManagerService.listAllTransportComponents(mUserOneId);
-
- verify(mUserOneService).listAllTransportComponents();
- }
-
- /** Test that the backup service does not route methods for non-registered users. */
- @Test
- public void testListAllTransportComponents_onUnknownUser_doesNotPropagateCall()
- throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
-
- backupManagerService.listAllTransportComponents(mUserTwoId);
-
- verify(mUserOneService, never()).listAllTransportComponents();
- }
-
- /** Test that the backup service routes methods correctly to the user that requests it. */
- @Test
- public void testUpdateTransportAttributes_onRegisteredUser_callsMethodForUser()
- throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
- TransportData transport = backupTransport();
- Intent configurationIntent = new Intent();
- Intent dataManagementIntent = new Intent();
-
- backupManagerService.updateTransportAttributes(
- mUserOneId,
- transport.getTransportComponent(),
- transport.transportName,
- configurationIntent,
- "currentDestinationString",
- dataManagementIntent,
- "dataManagementLabel");
-
- verify(mUserOneService)
- .updateTransportAttributes(
- transport.getTransportComponent(),
- transport.transportName,
- configurationIntent,
- "currentDestinationString",
- dataManagementIntent,
- "dataManagementLabel");
- }
-
- /** Test that the backup service does not route methods for non-registered users. */
- @Test
- public void testUpdateTransportAttributes_onUnknownUser_doesNotPropagateCall()
- throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
- TransportData transport = backupTransport();
- Intent configurationIntent = new Intent();
- Intent dataManagementIntent = new Intent();
-
- backupManagerService.updateTransportAttributes(
- mUserTwoId,
- transport.getTransportComponent(),
- transport.transportName,
- configurationIntent,
- "currentDestinationString",
- dataManagementIntent,
- "dataManagementLabel");
-
- verify(mUserOneService, never())
- .updateTransportAttributes(
- transport.getTransportComponent(),
- transport.transportName,
- configurationIntent,
- "currentDestinationString",
- dataManagementIntent,
- "dataManagementLabel");
- }
-
- /** Test that the backup service routes methods correctly to the user that requests it. */
- @Test
- public void testSelectBackupTransport_onRegisteredUser_callsMethodForUser() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
-
- backupManagerService.selectBackupTransport(mUserOneId, TEST_TRANSPORT);
-
- verify(mUserOneService).selectBackupTransport(TEST_TRANSPORT);
- }
-
- /** Test that the backup service does not route methods for non-registered users. */
- @Test
- public void testSelectBackupTransport_onUnknownUser_doesNotPropagateCall() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
-
- backupManagerService.selectBackupTransport(mUserTwoId, TEST_TRANSPORT);
-
- verify(mUserOneService, never()).selectBackupTransport(TEST_TRANSPORT);
- }
-
- /** Test that the backup service routes methods correctly to the user that requests it. */
- @Test
- public void testSelectTransportAsync_onRegisteredUser_callsMethodForUser() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
- TransportData transport = backupTransport();
- ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
-
- backupManagerService.selectBackupTransportAsync(
- mUserOneId, transport.getTransportComponent(), callback);
-
- verify(mUserOneService)
- .selectBackupTransportAsync(transport.getTransportComponent(), callback);
- }
-
- /** Test that the backup service does not route methods for non-registered users. */
- @Test
- public void testSelectBackupTransportAsync_onUnknownUser_doesNotPropagateCall()
- throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
- TransportData transport = backupTransport();
- ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
-
- backupManagerService.selectBackupTransportAsync(
- mUserTwoId, transport.getTransportComponent(), callback);
-
- verify(mUserOneService, never())
- .selectBackupTransportAsync(transport.getTransportComponent(), callback);
- }
-
- /** Test that the backup service routes methods correctly to the user that requests it. */
- @Test
- public void testGetConfigurationIntent_onRegisteredUser_callsMethodForUser() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
-
- backupManagerService.getConfigurationIntent(mUserOneId, TEST_TRANSPORT);
-
- verify(mUserOneService).getConfigurationIntent(TEST_TRANSPORT);
- }
-
- /** Test that the backup service does not route methods for non-registered users. */
- @Test
- public void testGetConfigurationIntent_onUnknownUser_doesNotPropagateCall() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
-
- backupManagerService.getConfigurationIntent(mUserTwoId, TEST_TRANSPORT);
-
- verify(mUserOneService, never()).getConfigurationIntent(TEST_TRANSPORT);
- }
-
- /** Test that the backup service routes methods correctly to the user that requests it. */
- @Test
- public void testGetDestinationString_onRegisteredUser_callsMethodForUser() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
-
- backupManagerService.getDestinationString(mUserOneId, TEST_TRANSPORT);
-
- verify(mUserOneService).getDestinationString(TEST_TRANSPORT);
- }
-
- /** Test that the backup service does not route methods for non-registered users. */
- @Test
- public void testGetDestinationString_onUnknownUser_doesNotPropagateCall() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
-
- backupManagerService.getDestinationString(mUserTwoId, TEST_TRANSPORT);
-
- verify(mUserOneService, never()).getDestinationString(TEST_TRANSPORT);
- }
-
- /** Test that the backup service routes methods correctly to the user that requests it. */
- @Test
- public void testGetDataManagementIntent_onRegisteredUser_callsMethodForUser() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
-
- backupManagerService.getDataManagementIntent(mUserOneId, TEST_TRANSPORT);
-
- verify(mUserOneService).getDataManagementIntent(TEST_TRANSPORT);
- }
-
- /** Test that the backup service does not route methods for non-registered users. */
- @Test
- public void testGetDataManagementIntent_onUnknownUser_doesNotPropagateCall() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
-
- backupManagerService.getDataManagementIntent(mUserTwoId, TEST_TRANSPORT);
-
- verify(mUserOneService, never()).getDataManagementIntent(TEST_TRANSPORT);
- }
-
- /** Test that the backup service routes methods correctly to the user that requests it. */
- @Test
- public void testGetDataManagementLabel_onRegisteredUser_callsMethodForUser() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
-
- backupManagerService.getDataManagementLabel(mUserOneId, TEST_TRANSPORT);
-
- verify(mUserOneService).getDataManagementLabel(TEST_TRANSPORT);
- }
-
- /** Test that the backup service does not route methods for non-registered users. */
- @Test
- public void testGetDataManagementLabel_onUnknownUser_doesNotPropagateCall() throws Exception {
- registerUser(mUserOneId, mUserOneService);
- BackupManagerService backupManagerService = createService();
- setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
-
- backupManagerService.getDataManagementLabel(mUserTwoId, TEST_TRANSPORT);
-
- verify(mUserOneService, never()).getDataManagementLabel(TEST_TRANSPORT);
- }
-
- // ---------------------------------------------
// Settings tests
// ---------------------------------------------
/**
diff --git a/services/robotests/backup/src/com/android/server/backup/TrampolineRoboTest.java b/services/robotests/backup/src/com/android/server/backup/TrampolineRoboTest.java
index dfad1a9..d1fb10a 100644
--- a/services/robotests/backup/src/com/android/server/backup/TrampolineRoboTest.java
+++ b/services/robotests/backup/src/com/android/server/backup/TrampolineRoboTest.java
@@ -19,21 +19,28 @@
import static android.Manifest.permission.BACKUP;
import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+import static com.android.server.backup.testing.TransportData.backupTransport;
+
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.robolectric.Shadows.shadowOf;
import android.annotation.UserIdInt;
import android.app.Application;
+import android.app.backup.ISelectBackupTransportCallback;
import android.content.Context;
+import android.content.Intent;
+import android.os.IBinder;
import android.os.Process;
import android.os.UserHandle;
import android.os.UserManager;
import android.platform.test.annotations.Presubmit;
import android.util.SparseArray;
+import com.android.server.backup.testing.TransportData;
import com.android.server.testing.shadows.ShadowApplicationPackageManager;
import com.android.server.testing.shadows.ShadowBinder;
import com.android.server.testing.shadows.ShadowEnvironment;
@@ -63,6 +70,9 @@
})
@Presubmit
public class TrampolineRoboTest {
+ private static final String TEST_PACKAGE = "package";
+ private static final String TEST_TRANSPORT = "transport";
+
private Context mContext;
private ShadowContextWrapper mShadowContext;
private ShadowUserManager mShadowUserManager;
@@ -161,10 +171,461 @@
assertThat(serviceUsers.size()).isEqualTo(0);
}
+ // ---------------------------------------------
+ // Backup agent tests
+ // ---------------------------------------------
+
+ /** Test that the backup service routes methods correctly to the user that requests it. */
+ @Test
+ public void testDataChanged_onRegisteredUser_callsMethodForUser() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
+
+ backupManagerService.dataChanged(mUserOneId, TEST_PACKAGE);
+
+ verify(mUserOneService).dataChanged(TEST_PACKAGE);
+ }
+
+ /** Test that the backup service does not route methods for non-registered users. */
+ @Test
+ public void testDataChanged_onUnknownUser_doesNotPropagateCall() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
+
+ backupManagerService.dataChanged(mUserTwoId, TEST_PACKAGE);
+
+ verify(mUserOneService, never()).dataChanged(TEST_PACKAGE);
+ }
+
+ /** Test that the backup service routes methods correctly to the user that requests it. */
+ @Test
+ public void testAgentConnected_onRegisteredUser_callsMethodForUser() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
+ IBinder agentBinder = mock(IBinder.class);
+
+ backupManagerService.agentConnected(mUserOneId, TEST_PACKAGE, agentBinder);
+
+ verify(mUserOneService).agentConnected(TEST_PACKAGE, agentBinder);
+ }
+
+ /** Test that the backup service does not route methods for non-registered users. */
+ @Test
+ public void testAgentConnected_onUnknownUser_doesNotPropagateCall() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
+ IBinder agentBinder = mock(IBinder.class);
+
+ backupManagerService.agentConnected(mUserTwoId, TEST_PACKAGE, agentBinder);
+
+ verify(mUserOneService, never()).agentConnected(TEST_PACKAGE, agentBinder);
+ }
+
+ /** Test that the backup service routes methods correctly to the user that requests it. */
+ @Test
+ public void testOpComplete_onRegisteredUser_callsMethodForUser() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
+
+ backupManagerService.opComplete(mUserOneId, /* token */ 0, /* result */ 0L);
+
+ verify(mUserOneService).opComplete(/* token */ 0, /* result */ 0L);
+ }
+
+ /** Test that the backup service does not route methods for non-registered users. */
+ @Test
+ public void testOpComplete_onUnknownUser_doesNotPropagateCall() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
+
+ backupManagerService.opComplete(mUserTwoId, /* token */ 0, /* result */ 0L);
+
+ verify(mUserOneService, never()).opComplete(/* token */ 0, /* result */ 0L);
+ }
+
+ // ---------------------------------------------
+ // Transport tests
+ // ---------------------------------------------
+
+ /** Test that the backup service routes methods correctly to the user that requests it. */
+ @Test
+ public void testInitializeTransports_onRegisteredUser_callsMethodForUser() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
+ String[] transports = {TEST_TRANSPORT};
+
+ backupManagerService.initializeTransports(mUserOneId, transports, /* observer */ null);
+
+ verify(mUserOneService).initializeTransports(transports, /* observer */ null);
+ }
+
+ /** Test that the backup service does not route methods for non-registered users. */
+ @Test
+ public void testInitializeTransports_onUnknownUser_doesNotPropagateCall() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
+ String[] transports = {TEST_TRANSPORT};
+
+ backupManagerService.initializeTransports(mUserTwoId, transports, /* observer */ null);
+
+ verify(mUserOneService, never()).initializeTransports(transports, /* observer */ null);
+ }
+
+ /** Test that the backup service routes methods correctly to the user that requests it. */
+ @Test
+ public void testClearBackupData_onRegisteredUser_callsMethodForUser() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
+
+ backupManagerService.clearBackupData(mUserOneId, TEST_TRANSPORT, TEST_PACKAGE);
+
+ verify(mUserOneService).clearBackupData(TEST_TRANSPORT, TEST_PACKAGE);
+ }
+
+ /** Test that the backup service does not route methods for non-registered users. */
+ @Test
+ public void testClearBackupData_onUnknownUser_doesNotPropagateCall() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
+
+ backupManagerService.clearBackupData(mUserTwoId, TEST_TRANSPORT, TEST_PACKAGE);
+
+ verify(mUserOneService, never()).clearBackupData(TEST_TRANSPORT, TEST_PACKAGE);
+ }
+
+ /** Test that the backup service routes methods correctly to the user that requests it. */
+ @Test
+ public void testGetCurrentTransport_onRegisteredUser_callsMethodForUser() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
+
+ backupManagerService.getCurrentTransport(mUserOneId);
+
+ verify(mUserOneService).getCurrentTransport();
+ }
+
+ /** Test that the backup service does not route methods for non-registered users. */
+ @Test
+ public void testGetCurrentTransport_onUnknownUser_doesNotPropagateCall() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
+
+ backupManagerService.getCurrentTransport(mUserTwoId);
+
+ verify(mUserOneService, never()).getCurrentTransport();
+ }
+
+ /** Test that the backup service routes methods correctly to the user that requests it. */
+ @Test
+ public void testGetCurrentTransportComponent_onRegisteredUser_callsMethodForUser()
+ throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
+
+ backupManagerService.getCurrentTransportComponent(mUserOneId);
+
+ verify(mUserOneService).getCurrentTransportComponent();
+ }
+
+ /** Test that the backup service does not route methods for non-registered users. */
+ @Test
+ public void testGetCurrentTransportComponent_onUnknownUser_doesNotPropagateCall()
+ throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
+
+ backupManagerService.getCurrentTransportComponent(mUserTwoId);
+
+ verify(mUserOneService, never()).getCurrentTransportComponent();
+ }
+
+ /** Test that the backup service routes methods correctly to the user that requests it. */
+ @Test
+ public void testListAllTransports_onRegisteredUser_callsMethodForUser() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
+
+ backupManagerService.listAllTransports(mUserOneId);
+
+ verify(mUserOneService).listAllTransports();
+ }
+
+ /** Test that the backup service does not route methods for non-registered users. */
+ @Test
+ public void testListAllTransports_onUnknownUser_doesNotPropagateCall() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
+
+ backupManagerService.listAllTransports(mUserTwoId);
+
+ verify(mUserOneService, never()).listAllTransports();
+ }
+
+ /** Test that the backup service routes methods correctly to the user that requests it. */
+ @Test
+ public void testListAllTransportComponents_onRegisteredUser_callsMethodForUser()
+ throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
+
+ backupManagerService.listAllTransportComponents(mUserOneId);
+
+ verify(mUserOneService).listAllTransportComponents();
+ }
+
+ /** Test that the backup service does not route methods for non-registered users. */
+ @Test
+ public void testListAllTransportComponents_onUnknownUser_doesNotPropagateCall()
+ throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
+
+ backupManagerService.listAllTransportComponents(mUserTwoId);
+
+ verify(mUserOneService, never()).listAllTransportComponents();
+ }
+
+ /** Test that the backup service routes methods correctly to the user that requests it. */
+ @Test
+ public void testSelectBackupTransport_onRegisteredUser_callsMethodForUser() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
+
+ backupManagerService.selectBackupTransport(mUserOneId, TEST_TRANSPORT);
+
+ verify(mUserOneService).selectBackupTransport(TEST_TRANSPORT);
+ }
+
+ /** Test that the backup service does not route methods for non-registered users. */
+ @Test
+ public void testSelectBackupTransport_onUnknownUser_doesNotPropagateCall() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
+
+ backupManagerService.selectBackupTransport(mUserTwoId, TEST_TRANSPORT);
+
+ verify(mUserOneService, never()).selectBackupTransport(TEST_TRANSPORT);
+ }
+
+ /** Test that the backup service routes methods correctly to the user that requests it. */
+ @Test
+ public void testSelectTransportAsync_onRegisteredUser_callsMethodForUser() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
+ TransportData transport = backupTransport();
+ ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
+
+ backupManagerService.selectBackupTransportAsync(
+ mUserOneId, transport.getTransportComponent(), callback);
+
+ verify(mUserOneService)
+ .selectBackupTransportAsync(transport.getTransportComponent(), callback);
+ }
+
+ /** Test that the backup service does not route methods for non-registered users. */
+ @Test
+ public void testSelectBackupTransportAsync_onUnknownUser_doesNotPropagateCall()
+ throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
+ TransportData transport = backupTransport();
+ ISelectBackupTransportCallback callback = mock(ISelectBackupTransportCallback.class);
+
+ backupManagerService.selectBackupTransportAsync(
+ mUserTwoId, transport.getTransportComponent(), callback);
+
+ verify(mUserOneService, never())
+ .selectBackupTransportAsync(transport.getTransportComponent(), callback);
+ }
+
+ /** Test that the backup service routes methods correctly to the user that requests it. */
+ @Test
+ public void testGetConfigurationIntent_onRegisteredUser_callsMethodForUser() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
+
+ backupManagerService.getConfigurationIntent(mUserOneId, TEST_TRANSPORT);
+
+ verify(mUserOneService).getConfigurationIntent(TEST_TRANSPORT);
+ }
+
+ /** Test that the backup service does not route methods for non-registered users. */
+ @Test
+ public void testGetConfigurationIntent_onUnknownUser_doesNotPropagateCall() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
+
+ backupManagerService.getConfigurationIntent(mUserTwoId, TEST_TRANSPORT);
+
+ verify(mUserOneService, never()).getConfigurationIntent(TEST_TRANSPORT);
+ }
+
+ /** Test that the backup service routes methods correctly to the user that requests it. */
+ @Test
+ public void testGetDestinationString_onRegisteredUser_callsMethodForUser() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
+
+ backupManagerService.getDestinationString(mUserOneId, TEST_TRANSPORT);
+
+ verify(mUserOneService).getDestinationString(TEST_TRANSPORT);
+ }
+
+ /** Test that the backup service does not route methods for non-registered users. */
+ @Test
+ public void testGetDestinationString_onUnknownUser_doesNotPropagateCall() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
+
+ backupManagerService.getDestinationString(mUserTwoId, TEST_TRANSPORT);
+
+ verify(mUserOneService, never()).getDestinationString(TEST_TRANSPORT);
+ }
+
+ /** Test that the backup service routes methods correctly to the user that requests it. */
+ @Test
+ public void testGetDataManagementIntent_onRegisteredUser_callsMethodForUser() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
+
+ backupManagerService.getDataManagementIntent(mUserOneId, TEST_TRANSPORT);
+
+ verify(mUserOneService).getDataManagementIntent(TEST_TRANSPORT);
+ }
+
+ /** Test that the backup service does not route methods for non-registered users. */
+ @Test
+ public void testGetDataManagementIntent_onUnknownUser_doesNotPropagateCall() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
+
+ backupManagerService.getDataManagementIntent(mUserTwoId, TEST_TRANSPORT);
+
+ verify(mUserOneService, never()).getDataManagementIntent(TEST_TRANSPORT);
+ }
+
+ /** Test that the backup service routes methods correctly to the user that requests it. */
+ @Test
+ public void testGetDataManagementLabel_onRegisteredUser_callsMethodForUser() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
+
+ backupManagerService.getDataManagementLabel(mUserOneId, TEST_TRANSPORT);
+
+ verify(mUserOneService).getDataManagementLabel(TEST_TRANSPORT);
+ }
+
+ /** Test that the backup service does not route methods for non-registered users. */
+ @Test
+ public void testGetDataManagementLabel_onUnknownUser_doesNotPropagateCall() throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
+
+ backupManagerService.getDataManagementLabel(mUserTwoId, TEST_TRANSPORT);
+
+ verify(mUserOneService, never()).getDataManagementLabel(TEST_TRANSPORT);
+ }
+
+ /** Test that the backup service routes methods correctly to the user that requests it. */
+ @Test
+ public void testUpdateTransportAttributes_onRegisteredUser_callsMethodForUser()
+ throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserOneId, /* shouldGrantPermission */ false);
+ TransportData transport = backupTransport();
+ Intent configurationIntent = new Intent();
+ Intent dataManagementIntent = new Intent();
+
+ backupManagerService.updateTransportAttributes(
+ mUserOneId,
+ transport.getTransportComponent(),
+ transport.transportName,
+ configurationIntent,
+ "currentDestinationString",
+ dataManagementIntent,
+ "dataManagementLabel");
+
+ verify(mUserOneService)
+ .updateTransportAttributes(
+ transport.getTransportComponent(),
+ transport.transportName,
+ configurationIntent,
+ "currentDestinationString",
+ dataManagementIntent,
+ "dataManagementLabel");
+ }
+
+ /** Test that the backup service does not route methods for non-registered users. */
+ @Test
+ public void testUpdateTransportAttributes_onUnknownUser_doesNotPropagateCall()
+ throws Exception {
+ Trampoline backupManagerService = createService();
+ registerUser(backupManagerService, mUserOneId, mUserOneService);
+ setCallerAndGrantInteractUserPermission(mUserTwoId, /* shouldGrantPermission */ false);
+ TransportData transport = backupTransport();
+ Intent configurationIntent = new Intent();
+ Intent dataManagementIntent = new Intent();
+
+ backupManagerService.updateTransportAttributes(
+ mUserTwoId,
+ transport.getTransportComponent(),
+ transport.transportName,
+ configurationIntent,
+ "currentDestinationString",
+ dataManagementIntent,
+ "dataManagementLabel");
+
+ verify(mUserOneService, never())
+ .updateTransportAttributes(
+ transport.getTransportComponent(),
+ transport.transportName,
+ configurationIntent,
+ "currentDestinationString",
+ dataManagementIntent,
+ "dataManagementLabel");
+ }
+
private Trampoline createService() {
return new Trampoline(mContext);
}
+ private void registerUser(
+ Trampoline trampoline, int userId, UserBackupManagerService userBackupManagerService) {
+ trampoline.setBackupServiceActive(userId, true);
+ trampoline.startServiceForUser(userId, userBackupManagerService);
+ }
+
private Trampoline createServiceAndRegisterUser(
int userId, UserBackupManagerService userBackupManagerService) {
Trampoline backupManagerService = createService();
@@ -172,4 +633,19 @@
backupManagerService.startServiceForUser(userId, userBackupManagerService);
return backupManagerService;
}
+
+ /**
+ * Sets the calling user to {@code userId} and grants the permission INTERACT_ACROSS_USERS_FULL
+ * to the caller if {@code shouldGrantPermission} is {@code true}, else it denies the
+ * permission.
+ */
+ private void setCallerAndGrantInteractUserPermission(
+ @UserIdInt int userId, boolean shouldGrantPermission) {
+ ShadowBinder.setCallingUserHandle(UserHandle.of(userId));
+ if (shouldGrantPermission) {
+ mShadowContext.grantPermissions(INTERACT_ACROSS_USERS_FULL);
+ } else {
+ mShadowContext.denyPermissions(INTERACT_ACROSS_USERS_FULL);
+ }
+ }
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
index 1e29ed6..6e8b86a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/AlarmManagerServiceTest.java
@@ -253,7 +253,7 @@
doReturn(mIActivityManager).when(ActivityManager::getService);
doReturn(mAppStateTracker).when(() -> LocalServices.getService(AppStateTracker.class));
doReturn(null)
- .when(() -> LocalServices.getService(DeviceIdleController.LocalService.class));
+ .when(() -> LocalServices.getService(DeviceIdleInternal.class));
doReturn(mUsageStatsManagerInternal).when(
() -> LocalServices.getService(UsageStatsManagerInternal.class));
when(mUsageStatsManagerInternal.getAppStandbyBucket(eq(TEST_CALLING_PACKAGE),
diff --git a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
index 6feac52..108b017 100644
--- a/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/DeviceIdleControllerTest.java
@@ -186,7 +186,7 @@
@Override
ConstraintController getConstraintController(
- Handler handler, DeviceIdleController.LocalService localService) {
+ Handler handler, DeviceIdleInternal localService) {
return constraintController;
}
@@ -291,7 +291,7 @@
// 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);
+ LocalServices.removeServiceForTest(DeviceIdleInternal.class);
}
@Test
diff --git a/services/tests/mockingservicestests/src/com/android/server/deviceidle/BluetoothConstraintTest.java b/services/tests/mockingservicestests/src/com/android/server/deviceidle/BluetoothConstraintTest.java
index f74ac1f..a9d1c2d 100644
--- a/services/tests/mockingservicestests/src/com/android/server/deviceidle/BluetoothConstraintTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/deviceidle/BluetoothConstraintTest.java
@@ -39,7 +39,7 @@
import androidx.test.runner.AndroidJUnit4;
-import com.android.server.DeviceIdleController;
+import com.android.server.DeviceIdleInternal;
import org.junit.After;
import org.junit.Before;
@@ -71,7 +71,7 @@
private BluetoothManager mBluetoothManager;
@Mock
- private DeviceIdleController.LocalService mDeviceIdleService;
+ private DeviceIdleInternal mDeviceIdleService;
private BluetoothConstraint mConstraint;
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
index 22cd3d3..71f7d2c 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/JobSchedulerServiceTest.java
@@ -53,7 +53,7 @@
import android.os.SystemClock;
import com.android.server.AppStateTracker;
-import com.android.server.DeviceIdleController;
+import com.android.server.DeviceIdleInternal;
import com.android.server.LocalServices;
import com.android.server.job.controllers.JobStatus;
@@ -114,8 +114,8 @@
when(mContext.getSystemService(NetworkPolicyManager.class))
.thenReturn(mock(NetworkPolicyManager.class));
// Called in DeviceIdleJobsController constructor.
- doReturn(mock(DeviceIdleController.LocalService.class))
- .when(() -> LocalServices.getService(DeviceIdleController.LocalService.class));
+ doReturn(mock(DeviceIdleInternal.class))
+ .when(() -> LocalServices.getService(DeviceIdleInternal.class));
// Used in JobStatus.
doReturn(mock(PackageManagerInternal.class))
.when(() -> LocalServices.getService(PackageManagerInternal.class));
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 1f93513..e95c578 100644
--- a/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
+++ b/services/tests/servicestests/src/com/android/server/backup/TrampolineTest.java
@@ -16,18 +16,18 @@
package com.android.server.backup;
+import static com.google.common.truth.Truth.assertThat;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
-import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
@@ -42,7 +42,6 @@
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.UserInfo;
import android.os.ConditionVariable;
@@ -139,7 +138,6 @@
mUserServices = new SparseArray<>();
mUserServices.append(UserHandle.USER_SYSTEM, mUserBackupManagerService);
mUserServices.append(NON_USER_SYSTEM, mUserBackupManagerService);
- when(mBackupManagerServiceMock.getUserServices()).thenReturn(mUserServices);
when(mUserManagerMock.getUserInfo(UserHandle.USER_SYSTEM)).thenReturn(mUserInfoMock);
when(mUserManagerMock.getUserInfo(NON_USER_SYSTEM)).thenReturn(mUserInfoMock);
@@ -484,73 +482,6 @@
}
@Test
- public void dataChangedForUser_forwarded() throws Exception {
- mTrampoline.dataChangedForUser(mUserId, PACKAGE_NAME);
-
- verify(mBackupManagerServiceMock).dataChanged(mUserId, PACKAGE_NAME);
- }
-
- @Test
- public void dataChanged_forwarded() throws Exception {
- TrampolineTestable.sCallingUserId = mUserId;
-
- mTrampoline.dataChanged(PACKAGE_NAME);
-
- verify(mBackupManagerServiceMock).dataChanged(mUserId, PACKAGE_NAME);
- }
-
- @Test
- public void clearBackupDataForUser_forwarded() throws Exception {
-
- mTrampoline.clearBackupDataForUser(mUserId, TRANSPORT_NAME, PACKAGE_NAME);
-
- verify(mBackupManagerServiceMock).clearBackupData(mUserId, TRANSPORT_NAME, PACKAGE_NAME);
- }
-
- @Test
- public void clearBackupData_forwarded() throws Exception {
- TrampolineTestable.sCallingUserId = mUserId;
-
- mTrampoline.clearBackupData(TRANSPORT_NAME, PACKAGE_NAME);
-
- verify(mBackupManagerServiceMock).clearBackupData(mUserId, TRANSPORT_NAME, PACKAGE_NAME);
- }
-
- @Test
- public void agentConnectedForUser_forwarded() throws Exception {
-
- mTrampoline.agentConnectedForUser(mUserId, PACKAGE_NAME, mAgentMock);
-
- verify(mBackupManagerServiceMock).agentConnected(mUserId, PACKAGE_NAME, mAgentMock);
- }
-
- @Test
- public void agentConnected_forwarded() throws Exception {
- TrampolineTestable.sCallingUserId = mUserId;
-
- mTrampoline.agentConnected(PACKAGE_NAME, mAgentMock);
-
- verify(mBackupManagerServiceMock).agentConnected(mUserId, PACKAGE_NAME, mAgentMock);
- }
-
- @Test
- public void agentDisconnectedForUser_forwarded() throws Exception {
-
- mTrampoline.agentDisconnectedForUser(mUserId, PACKAGE_NAME);
-
- verify(mBackupManagerServiceMock).agentDisconnected(mUserId, PACKAGE_NAME);
- }
-
- @Test
- public void agentDisconnected_forwarded() throws Exception {
- TrampolineTestable.sCallingUserId = mUserId;
-
- mTrampoline.agentDisconnected(PACKAGE_NAME);
-
- verify(mBackupManagerServiceMock).agentDisconnected(mUserId, PACKAGE_NAME);
- }
-
- @Test
public void restoreAtInstallForUser_forwarded() throws Exception {
mTrampoline.restoreAtInstallForUser(mUserId, PACKAGE_NAME, 123);
@@ -709,92 +640,9 @@
}
@Test
- public void getCurrentTransportForUser_forwarded() throws Exception {
- when(mBackupManagerServiceMock.getCurrentTransport(mUserId)).thenReturn(TRANSPORT_NAME);
-
- assertEquals(TRANSPORT_NAME, mTrampoline.getCurrentTransportForUser(mUserId));
- verify(mBackupManagerServiceMock).getCurrentTransport(mUserId);
- }
-
- @Test
- public void getCurrentTransport_forwarded() throws Exception {
- TrampolineTestable.sCallingUserId = mUserId;
- when(mBackupManagerServiceMock.getCurrentTransport(mUserId)).thenReturn(TRANSPORT_NAME);
-
- assertEquals(TRANSPORT_NAME, mTrampoline.getCurrentTransport());
- verify(mBackupManagerServiceMock).getCurrentTransport(mUserId);
- }
-
- @Test
- public void listAllTransportsForUser_forwarded() throws Exception {
- when(mBackupManagerServiceMock.listAllTransports(mUserId)).thenReturn(TRANSPORTS);
-
- assertEquals(TRANSPORTS, mTrampoline.listAllTransportsForUser(mUserId));
- verify(mBackupManagerServiceMock).listAllTransports(mUserId);
- }
-
-
- @Test
- public void listAllTransports_forwarded() throws Exception {
- TrampolineTestable.sCallingUserId = mUserId;
- when(mBackupManagerServiceMock.listAllTransports(mUserId)).thenReturn(TRANSPORTS);
-
- assertEquals(TRANSPORTS, mTrampoline.listAllTransports());
- verify(mBackupManagerServiceMock).listAllTransports(mUserId);
- }
-
- @Test
- public void listAllTransportComponentsForUser_forwarded() throws Exception {
- when(mBackupManagerServiceMock.listAllTransportComponents(mUserId)).thenReturn(
- TRANSPORT_COMPONENTS);
-
- assertEquals(TRANSPORT_COMPONENTS, mTrampoline.listAllTransportComponentsForUser(mUserId));
- verify(mBackupManagerServiceMock).listAllTransportComponents(mUserId);
- }
-
- @Test
- public void updateTransportAttributesForUser_forwarded() {
- mTrampoline.updateTransportAttributesForUser(
- mUserId,
- TRANSPORT_COMPONENT_NAME,
- TRANSPORT_NAME,
- null,
- "Transport Destination",
- null,
- "Data Management");
-
- verify(mBackupManagerServiceMock)
- .updateTransportAttributes(
- mUserId,
- TRANSPORT_COMPONENT_NAME,
- TRANSPORT_NAME,
- null,
- "Transport Destination",
- null,
- "Data Management");
- }
-
- @Test
- public void selectBackupTransportForUser_forwarded() throws Exception {
-
- mTrampoline.selectBackupTransportForUser(mUserId, TRANSPORT_NAME);
-
- verify(mBackupManagerServiceMock).selectBackupTransport(mUserId, TRANSPORT_NAME);
- }
-
- @Test
- public void selectBackupTransport_forwarded() throws Exception {
- TrampolineTestable.sCallingUserId = mUserId;
-
- mTrampoline.selectBackupTransport(TRANSPORT_NAME);
-
- verify(mBackupManagerServiceMock).selectBackupTransport(mUserId, TRANSPORT_NAME);
- }
-
- @Test
public void selectBackupTransportAsyncForUser_beforeUserUnlocked_notifiesBackupNotAllowed()
throws Exception {
- when(mBackupManagerServiceMock.getUserServices()).thenReturn(new SparseArray<>());
+ mUserServices.clear();
CompletableFuture<Integer> future = new CompletableFuture<>();
ISelectBackupTransportCallback listener =
new ISelectBackupTransportCallback.Stub() {
@@ -841,111 +689,6 @@
}
@Test
- public void selectBackupTransportAsyncForUser_forwarded() throws Exception {
-
- mTrampoline.selectBackupTransportAsyncForUser(mUserId, TRANSPORT_COMPONENT_NAME, null);
-
- verify(mBackupManagerServiceMock)
- .selectBackupTransportAsync(mUserId, TRANSPORT_COMPONENT_NAME, null);
- }
-
- @Test
- public void getConfigurationIntentForUser_forwarded() throws Exception {
- Intent configurationIntentStub = new Intent();
- when(mBackupManagerServiceMock.getConfigurationIntent(mUserId, TRANSPORT_NAME)).thenReturn(
- configurationIntentStub);
-
- assertEquals(
- configurationIntentStub,
- mTrampoline.getConfigurationIntentForUser(mUserId, TRANSPORT_NAME));
- verify(mBackupManagerServiceMock).getConfigurationIntent(mUserId, TRANSPORT_NAME);
- }
-
- @Test
- public void getConfigurationIntent_forwarded() throws Exception {
- TrampolineTestable.sCallingUserId = mUserId;
- Intent configurationIntentStub = new Intent();
- when(mBackupManagerServiceMock.getConfigurationIntent(mUserId, TRANSPORT_NAME)).thenReturn(
- configurationIntentStub);
-
- assertEquals(configurationIntentStub, mTrampoline.getConfigurationIntent(TRANSPORT_NAME));
- verify(mBackupManagerServiceMock).getConfigurationIntent(mUserId, TRANSPORT_NAME);
- }
-
- @Test
- public void getDestinationStringForUser_forwarded() throws Exception {
- when(mBackupManagerServiceMock.getDestinationString(mUserId, TRANSPORT_NAME)).thenReturn(
- DESTINATION_STRING);
-
- assertEquals(
- DESTINATION_STRING,
- mTrampoline.getDestinationStringForUser(mUserId, TRANSPORT_NAME));
- verify(mBackupManagerServiceMock).getDestinationString(mUserId, TRANSPORT_NAME);
- }
-
- @Test
- public void getDestinationString_forwarded() throws Exception {
- TrampolineTestable.sCallingUserId = mUserId;
- when(mBackupManagerServiceMock.getDestinationString(mUserId, TRANSPORT_NAME)).thenReturn(
- DESTINATION_STRING);
-
- assertEquals(DESTINATION_STRING, mTrampoline.getDestinationString(TRANSPORT_NAME));
- verify(mBackupManagerServiceMock).getDestinationString(mUserId, TRANSPORT_NAME);
- }
-
- @Test
- public void getDataManagementIntentForUser_forwarded() throws Exception {
- Intent dataManagementIntent = new Intent();
- when(mBackupManagerServiceMock.getDataManagementIntent(mUserId, TRANSPORT_NAME)).thenReturn(
- dataManagementIntent);
-
- assertEquals(
- dataManagementIntent,
- mTrampoline.getDataManagementIntentForUser(mUserId, TRANSPORT_NAME));
- verify(mBackupManagerServiceMock).getDataManagementIntent(mUserId, TRANSPORT_NAME);
- }
-
- @Test
- public void getDataManagementIntent_forwarded() throws Exception {
- TrampolineTestable.sCallingUserId = mUserId;
- Intent dataManagementIntent = new Intent();
- when(mBackupManagerServiceMock.getDataManagementIntent(mUserId, TRANSPORT_NAME)).thenReturn(
- dataManagementIntent);
-
- assertEquals(dataManagementIntent, mTrampoline.getDataManagementIntent(TRANSPORT_NAME));
- verify(mBackupManagerServiceMock).getDataManagementIntent(mUserId, TRANSPORT_NAME);
- }
-
- @Test
- public void getDataManagementLabelForUser_forwarded() throws Exception {
- when(mBackupManagerServiceMock.getDataManagementLabel(mUserId, TRANSPORT_NAME)).thenReturn(
- DATA_MANAGEMENT_LABEL);
-
- assertEquals(
- DATA_MANAGEMENT_LABEL,
- mTrampoline.getDataManagementLabelForUser(mUserId, TRANSPORT_NAME));
- verify(mBackupManagerServiceMock).getDataManagementLabel(mUserId, TRANSPORT_NAME);
- }
-
- @Test
- public void beginRestoreSessionForUser_forwarded() throws Exception {
-
- mTrampoline.beginRestoreSessionForUser(mUserId, PACKAGE_NAME, TRANSPORT_NAME);
-
- verify(mBackupManagerServiceMock)
- .beginRestoreSession(mUserId, PACKAGE_NAME, TRANSPORT_NAME);
- }
-
- @Test
- public void opComplete_forwarded() throws Exception {
- TrampolineTestable.sCallingUserId = mUserId;
-
- mTrampoline.opComplete(1, 2);
-
- verify(mBackupManagerServiceMock).opComplete(mUserId, 1, 2);
- }
-
- @Test
public void getAvailableRestoreTokenForUser_forwarded() {
when(mBackupManagerServiceMock.getAvailableRestoreToken(mUserId, PACKAGE_NAME))
.thenReturn(123L);
@@ -1043,17 +786,21 @@
public void testGetUserForAncestralSerialNumber() {
TrampolineTestable.sBackupDisabled = false;
Trampoline trampoline = new TrampolineTestable(mContextMock, mUserServices);
+ when(mUserBackupManagerService.getAncestralSerialNumber()).thenReturn(11L);
- trampoline.getUserForAncestralSerialNumber(0L);
- verify(mBackupManagerServiceMock).getUserForAncestralSerialNumber(anyInt());
+ UserHandle user = trampoline.getUserForAncestralSerialNumber(11L);
+
+ assertThat(user).isEqualTo(UserHandle.of(1));
}
public void testGetUserForAncestralSerialNumber_whenDisabled() {
TrampolineTestable.sBackupDisabled = true;
Trampoline trampoline = new TrampolineTestable(mContextMock, mUserServices);
+ when(mUserBackupManagerService.getAncestralSerialNumber()).thenReturn(11L);
- trampoline.getUserForAncestralSerialNumber(0L);
- verify(mBackupManagerServiceMock, never()).getUserForAncestralSerialNumber(anyInt());
+ UserHandle user = trampoline.getUserForAncestralSerialNumber(11L);
+
+ assertThat(user).isNull();
}
private static class TrampolineTestable extends Trampoline {
diff --git a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
index 09ae3a2..ba12b73 100644
--- a/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/net/NetworkPolicyManagerServiceTest.java
@@ -139,7 +139,7 @@
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.internal.util.test.BroadcastInterceptingContext.FutureIntent;
-import com.android.server.DeviceIdleController;
+import com.android.server.DeviceIdleInternal;
import com.android.server.LocalServices;
import com.google.common.util.concurrent.AbstractFuture;
@@ -293,7 +293,7 @@
};
private void registerLocalServices() {
- addLocalServiceMock(DeviceIdleController.LocalService.class);
+ addLocalServiceMock(DeviceIdleInternal.class);
final UsageStatsManagerInternal usageStats =
addLocalServiceMock(UsageStatsManagerInternal.class);
@@ -442,7 +442,7 @@
// Added in registerLocalServices()
LocalServices.removeServiceForTest(ActivityManagerInternal.class);
LocalServices.removeServiceForTest(PowerManagerInternal.class);
- LocalServices.removeServiceForTest(DeviceIdleController.LocalService.class);
+ LocalServices.removeServiceForTest(DeviceIdleInternal.class);
LocalServices.removeServiceForTest(UsageStatsManagerInternal.class);
LocalServices.removeServiceForTest(NetworkStatsManagerInternal.class);
}
diff --git a/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java b/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java
index 7986055..8cb5197 100644
--- a/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/rollback/AppDataRollbackHelperTest.java
@@ -16,6 +16,7 @@
package com.android.server.rollback;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
@@ -58,8 +59,8 @@
// All users are unlocked so we should snapshot data for them.
doReturn(true).when(helper).isUserCredentialLocked(eq(10));
doReturn(true).when(helper).isUserCredentialLocked(eq(11));
- PackageRollbackInfo info = createPackageRollbackInfo("com.foo.bar", new int[]{10, 11});
- helper.snapshotAppData(5, info);
+ PackageRollbackInfo info = createPackageRollbackInfo("com.foo.bar");
+ helper.snapshotAppData(5, info, new int[]{10, 11});
assertEquals(2, info.getPendingBackups().size());
assertEquals(10, info.getPendingBackups().get(0));
@@ -79,8 +80,8 @@
doReturn(true).when(helper).isUserCredentialLocked(eq(11));
when(installer.snapshotAppData(anyString(), anyInt(), anyInt(), anyInt())).thenReturn(239L);
- PackageRollbackInfo info2 = createPackageRollbackInfo("com.foo.bar", new int[]{10, 11});
- helper.snapshotAppData(7, info2);
+ PackageRollbackInfo info2 = createPackageRollbackInfo("com.foo.bar");
+ helper.snapshotAppData(7, info2, new int[]{10, 11});
assertEquals(1, info2.getPendingBackups().size());
assertEquals(11, info2.getPendingBackups().get(0));
@@ -234,22 +235,22 @@
wasRecentlyRestored.getPendingRestores().add(
new RestoreInfo(73 /* userId */, 239 /* appId*/, "seInfo"));
- RollbackData dataWithPendingBackup = new RollbackData(101, new File("/does/not/exist"), -1);
+ Rollback dataWithPendingBackup = new Rollback(101, new File("/does/not/exist"), -1);
dataWithPendingBackup.info.getPackages().add(pendingBackup);
- RollbackData dataWithRecentRestore = new RollbackData(17239, new File("/does/not/exist"),
+ Rollback dataWithRecentRestore = new Rollback(17239, new File("/does/not/exist"),
-1);
dataWithRecentRestore.info.getPackages().add(wasRecentlyRestored);
- RollbackData dataForDifferentUser = new RollbackData(17239, new File("/does/not/exist"),
+ Rollback dataForDifferentUser = new Rollback(17239, new File("/does/not/exist"),
-1);
dataForDifferentUser.info.getPackages().add(ignoredInfo);
- RollbackData dataForRestore = new RollbackData(17239, new File("/does/not/exist"), -1);
+ Rollback dataForRestore = new Rollback(17239, new File("/does/not/exist"), -1);
dataForRestore.info.getPackages().add(pendingRestore);
dataForRestore.info.getPackages().add(wasRecentlyRestored);
- Set<RollbackData> changed = helper.commitPendingBackupAndRestoreForUser(37,
+ Set<Rollback> changed = helper.commitPendingBackupAndRestoreForUser(37,
Arrays.asList(dataWithPendingBackup, dataWithRecentRestore, dataForDifferentUser,
dataForRestore));
InOrder inOrder = Mockito.inOrder(installer);
@@ -264,7 +265,7 @@
assertEquals(-1, pendingBackup.getPendingBackups().indexOf(37));
assertEquals(53, pendingBackup.getCeSnapshotInodes().get(37));
- // Check that changed returns correct RollbackData.
+ // Check that changed returns correct Rollback.
assertEquals(3, changed.size());
assertTrue(changed.contains(dataWithPendingBackup));
assertTrue(changed.contains(dataWithRecentRestore));
@@ -278,4 +279,15 @@
inOrder.verifyNoMoreInteractions();
}
+
+ @Test
+ public void snapshotAddDataSavesSnapshottedUsersToInfo() {
+ Installer installer = mock(Installer.class);
+ AppDataRollbackHelper helper = new AppDataRollbackHelper(installer);
+
+ PackageRollbackInfo info = createPackageRollbackInfo("com.foo.bar");
+ helper.snapshotAppData(5, info, new int[]{10, 11});
+
+ assertArrayEquals(info.getSnapshottedUsers().toArray(), new int[]{10, 11});
+ }
}
diff --git a/services/wifi/Android.bp b/services/wifi/Android.bp
new file mode 100644
index 0000000..3c916a6
--- /dev/null
+++ b/services/wifi/Android.bp
@@ -0,0 +1,11 @@
+// Interfaces between the core system and the wifi mainline module.
+java_library_static {
+ name: "services.wifi",
+ srcs: [
+ "java/**/*.java",
+ "java/**/*.aidl",
+ ],
+ libs: [
+ "services.net",
+ ],
+}
diff --git a/services/wifi/java/android/net/wifi/IWifiStackConnector.aidl b/services/wifi/java/android/net/wifi/IWifiStackConnector.aidl
new file mode 100644
index 0000000..eadc726
--- /dev/null
+++ b/services/wifi/java/android/net/wifi/IWifiStackConnector.aidl
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) 2019, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing perNmissions and
+ * limitations under the License.
+ */
+package android.net.wifi;
+
+/** @hide */
+interface IWifiStackConnector {
+ IBinder retrieveApiServiceImpl(String serviceName);
+ boolean startApiService(String serviceName);
+}
diff --git a/services/wifi/java/android/net/wifi/WifiStackClient.java b/services/wifi/java/android/net/wifi/WifiStackClient.java
new file mode 100644
index 0000000..fa66e4c
--- /dev/null
+++ b/services/wifi/java/android/net/wifi/WifiStackClient.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.net.wifi;
+
+import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_HIGH;
+import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_NORMAL;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.net.ConnectivityModuleConnector;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+/**
+ * Service used to communicate with the wifi stack, which could be running in a separate
+ * module.
+ * @hide
+ */
+public class WifiStackClient {
+ public static final String PERMISSION_MAINLINE_WIFI_STACK =
+ "android.permission.MAINLINE_WIFI_STACK";
+
+ private static final String TAG = WifiStackClient.class.getSimpleName();
+ private static WifiStackClient sInstance;
+
+ private WifiStackClient() { }
+
+ /**
+ * Get the WifiStackClient singleton instance.
+ */
+ public static synchronized WifiStackClient getInstance() {
+ if (sInstance == null) {
+ sInstance = new WifiStackClient();
+ }
+ return sInstance;
+ }
+
+ private class WifiStackConnection implements
+ ConnectivityModuleConnector.ModuleServiceCallback {
+ @Override
+ public void onModuleServiceConnected(IBinder service) {
+ Log.i(TAG, "Wifi stack connected");
+
+ registerWifiStackService(service);
+ IWifiStackConnector connector = IWifiStackConnector.Stub.asInterface(service);
+ registerApiServiceAndStart(connector, Context.WIFI_SERVICE);
+ registerApiServiceAndStart(connector, Context.WIFI_SCANNING_SERVICE);
+ registerApiServiceAndStart(connector, Context.WIFI_P2P_SERVICE);
+ registerApiServiceAndStart(connector, Context.WIFI_AWARE_SERVICE);
+ registerApiServiceAndStart(connector, Context.WIFI_RTT_RANGING_SERVICE);
+ }
+ }
+
+ private void registerWifiStackService(@NonNull IBinder service) {
+ ServiceManager.addService(Context.WIFI_STACK_SERVICE, service,
+ false /* allowIsolated */,
+ DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
+ Log.i(TAG, "Wifi stack service registered");
+ }
+
+ private void registerApiServiceAndStart(
+ IWifiStackConnector stackConnector, String serviceName) {
+ IBinder service = null;
+ try {
+ service = stackConnector.retrieveApiServiceImpl(serviceName);
+ } catch (RemoteException e) {
+ throw new RuntimeException("Failed to retrieve service impl " + serviceName, e);
+ }
+ if (service == null) {
+ Log.i(TAG, "Service " + serviceName + " not available");
+ return;
+ }
+ Log.i(TAG, "Registering " + serviceName);
+ ServiceManager.addService(serviceName, service);
+
+ boolean success = false;
+ try {
+ success = stackConnector.startApiService(serviceName);
+ } catch (RemoteException e) {
+ throw new RuntimeException("Failed to start service " + serviceName, e);
+ }
+ if (!success) {
+ throw new RuntimeException("Service " + serviceName + " start failed");
+ }
+ }
+
+ /**
+ * Start the wifi stack. Should be called only once on device startup.
+ *
+ * <p>This method will start the wifi stack either in the wifi stack
+ * process, or inside the system server on devices that do not support the wifi stack
+ * module.
+ */
+ public void start() {
+ Log.i(TAG, "Starting wifi stack");
+ ConnectivityModuleConnector.getInstance().startModuleService(
+ IWifiStackConnector.class.getName(), PERMISSION_MAINLINE_WIFI_STACK,
+ new WifiStackConnection());
+ }
+}
diff --git a/telephony/java/android/telephony/data/DataServiceCallback.java b/telephony/java/android/telephony/data/DataServiceCallback.java
index 5d8d793..89d30c0d 100644
--- a/telephony/java/android/telephony/data/DataServiceCallback.java
+++ b/telephony/java/android/telephony/data/DataServiceCallback.java
@@ -42,6 +42,8 @@
private static final String TAG = DataServiceCallback.class.getSimpleName();
+ private static final boolean DBG = true;
+
/**
* Result of data requests
* @hide
@@ -81,6 +83,7 @@
IDataServiceCallback callback = mCallback.get();
if (callback != null) {
try {
+ if (DBG) Rlog.d(TAG, "onSetupDataCallComplete");
callback.onSetupDataCallComplete(result, response);
} catch (RemoteException e) {
Rlog.e(TAG, "Failed to onSetupDataCallComplete on the remote");
@@ -98,6 +101,7 @@
IDataServiceCallback callback = mCallback.get();
if (callback != null) {
try {
+ if (DBG) Rlog.d(TAG, "onDeactivateDataCallComplete");
callback.onDeactivateDataCallComplete(result);
} catch (RemoteException e) {
Rlog.e(TAG, "Failed to onDeactivateDataCallComplete on the remote");
@@ -169,6 +173,7 @@
IDataServiceCallback callback = mCallback.get();
if (callback != null) {
try {
+ if (DBG) Rlog.d(TAG, "onDataCallListChanged");
callback.onDataCallListChanged(dataCallList);
} catch (RemoteException e) {
Rlog.e(TAG, "Failed to onDataCallListChanged on the remote");
diff --git a/telephony/java/com/android/internal/telephony/SmsApplication.java b/telephony/java/com/android/internal/telephony/SmsApplication.java
index c61ad42..f10398f 100644
--- a/telephony/java/com/android/internal/telephony/SmsApplication.java
+++ b/telephony/java/com/android/internal/telephony/SmsApplication.java
@@ -194,7 +194,7 @@
* @return
*/
private static int getIncomingUserId(Context context) {
- int contextUserId = context.getUserId();
+ int contextUserId = UserHandle.myUserId();
final int callingUid = Binder.getCallingUid();
if (DEBUG_MULTIUSER) {
Log.i(LOG_TAG, "getIncomingUserHandle caller=" + callingUid + ", myuid="
@@ -429,9 +429,6 @@
final SmsApplicationData smsApplicationData = receivers.get(packageName);
if (smsApplicationData != null) {
if (!smsApplicationData.isComplete()) {
- Log.w(LOG_TAG, "Package " + packageName
- + " lacks required manifest declarations to be a default sms app: "
- + smsApplicationData);
receivers.remove(packageName);
}
}
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index 232b5cb..c42201f 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -35,8 +35,8 @@
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.VersionedPackage;
-import android.net.NetworkStackClient;
-import android.net.NetworkStackClient.NetworkStackHealthListener;
+import android.net.ConnectivityModuleConnector;
+import android.net.ConnectivityModuleConnector.ConnectivityModuleHealthListener;
import android.os.Handler;
import android.os.test.TestLooper;
import android.provider.DeviceConfig;
@@ -86,11 +86,11 @@
private TestLooper mTestLooper;
private Context mSpyContext;
@Mock
- private NetworkStackClient mMockNetworkStackClient;
+ private ConnectivityModuleConnector mConnectivityModuleConnector;
@Mock
private PackageManager mMockPackageManager;
@Captor
- private ArgumentCaptor<NetworkStackHealthListener> mNetworkStackCallbackCaptor;
+ private ArgumentCaptor<ConnectivityModuleHealthListener> mConnectivityModuleCallbackCaptor;
@Before
public void setUp() throws Exception {
@@ -736,7 +736,7 @@
wd.startObservingHealth(observer, Collections.singletonList(APP_A), SHORT_DURATION);
// Notify of NetworkStack failure
- mNetworkStackCallbackCaptor.getValue().onNetworkStackFailure(APP_A);
+ mConnectivityModuleCallbackCaptor.getValue().onNetworkStackFailure(APP_A);
// Run handler so package failures are dispatched to observers
mTestLooper.dispatchAll();
@@ -782,18 +782,18 @@
Handler handler = new Handler(mTestLooper.getLooper());
PackageWatchdog watchdog =
new PackageWatchdog(mSpyContext, policyFile, handler, handler, controller,
- mMockNetworkStackClient);
+ mConnectivityModuleConnector);
// Verify controller is not automatically started
assertFalse(controller.mIsEnabled);
if (withPackagesReady) {
// Only capture the NetworkStack callback for the latest registered watchdog
- reset(mMockNetworkStackClient);
+ reset(mConnectivityModuleConnector);
watchdog.onPackagesReady();
// Verify controller by default is started when packages are ready
assertTrue(controller.mIsEnabled);
- verify(mMockNetworkStackClient).registerHealthListener(
- mNetworkStackCallbackCaptor.capture());
+ verify(mConnectivityModuleConnector).registerHealthListener(
+ mConnectivityModuleCallbackCaptor.capture());
}
return watchdog;
}
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index bbf71e7..99a686b 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -1084,7 +1084,8 @@
case OutputFormat::kProto: {
pb::ResourceTable pb_table;
- SerializeTableToPb(*table, &pb_table, context_->GetDiagnostics());
+ SerializeTableToPb(*table, &pb_table, context_->GetDiagnostics(),
+ options_.proto_table_flattener_options);
return io::CopyProtoToArchive(context_, &pb_table, kProtoResourceTablePath,
ArchiveEntry::kCompress, writer);
} break;
diff --git a/tools/aapt2/cmd/Link.h b/tools/aapt2/cmd/Link.h
index 324807c..56bff8f 100644
--- a/tools/aapt2/cmd/Link.h
+++ b/tools/aapt2/cmd/Link.h
@@ -24,6 +24,7 @@
#include "Resource.h"
#include "split/TableSplitter.h"
#include "format/binary/TableFlattener.h"
+#include "format/proto/ProtoSerialize.h"
#include "link/ManifestFixer.h"
#include "trace/TraceBuffer.h"
@@ -81,6 +82,7 @@
// Flattening options.
TableFlattenerOptions table_flattener_options;
+ SerializeTableOptions proto_table_flattener_options;
bool keep_raw_values = false;
// Split APK options.
@@ -245,9 +247,9 @@
"<add-resource> tags.",
&options_.auto_add_overlay);
AddOptionalSwitch("--override-styles-instead-of-overlaying",
- "Causes styles defined in -R resources to replace previous definitions\n"
- "instead of merging into them\n",
- &options_.override_styles_instead_of_overlaying);
+ "Causes styles defined in -R resources to replace previous definitions\n"
+ "instead of merging into them\n",
+ &options_.override_styles_instead_of_overlaying);
AddOptionalFlag("--rename-manifest-package", "Renames the package in AndroidManifest.xml.",
&options_.manifest_fixer_options.rename_manifest_package);
AddOptionalFlag("--rename-instrumentation-target-package",
@@ -283,13 +285,18 @@
AddOptionalSwitch("--strict-visibility",
"Do not allow overlays with different visibility levels.",
&options_.strict_visibility);
- AddOptionalSwitch("-v", "Enables verbose logging.", &verbose_);
- AddOptionalFlag("--trace-folder", "Generate systrace json trace fragment to specified folder.",
- &trace_folder_);
+ AddOptionalSwitch("--exclude-sources",
+ "Do not serialize source file information when generating resources in\n"
+ "Protobuf format.",
+ &options_.proto_table_flattener_options.exclude_sources);
+ AddOptionalFlag("--trace-folder",
+ "Generate systrace json trace fragment to specified folder.",
+ &trace_folder_);
AddOptionalSwitch("--merge-only",
- "Only merge the resources, without verifying resource references. This flag\n"
- "should only be used together with the --static-lib flag.",
- &options_.merge_only);
+ "Only merge the resources, without verifying resource references. This flag\n"
+ "should only be used together with the --static-lib flag.",
+ &options_.merge_only);
+ AddOptionalSwitch("-v", "Enables verbose logging.", &verbose_);
}
int Action(const std::vector<std::string>& args) override;
diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp
index aa6547e..e4b3fce 100644
--- a/tools/aapt2/format/proto/ProtoSerialize.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize.cpp
@@ -290,8 +290,10 @@
pb::Overlayable* pb_overlayable = pb_table->add_overlayable();
pb_overlayable->set_name(overlayable_item.overlayable->name);
pb_overlayable->set_actor(overlayable_item.overlayable->actor);
- SerializeSourceToPb(overlayable_item.overlayable->source, source_pool,
- pb_overlayable->mutable_source());
+ if (source_pool != nullptr) {
+ SerializeSourceToPb(overlayable_item.overlayable->source, source_pool,
+ pb_overlayable->mutable_source());
+ }
}
pb::OverlayableItem* pb_overlayable_item = pb_entry->mutable_overlayable_item();
@@ -319,14 +321,17 @@
pb_overlayable_item->add_policy(pb::OverlayableItem::OEM);
}
- SerializeSourceToPb(overlayable_item.source, source_pool,
- pb_overlayable_item->mutable_source());
+ if (source_pool != nullptr) {
+ SerializeSourceToPb(overlayable_item.source, source_pool,
+ pb_overlayable_item->mutable_source());
+ }
pb_overlayable_item->set_comment(overlayable_item.comment);
}
void SerializeTableToPb(const ResourceTable& table, pb::ResourceTable* out_table,
- IDiagnostics* diag) {
- StringPool source_pool;
+ IDiagnostics* diag, SerializeTableOptions options) {
+ auto source_pool = (options.exclude_sources) ? nullptr : util::make_unique<StringPool>();
+
pb::ToolFingerprint* pb_fingerprint = out_table->add_tool_fingerprint();
pb_fingerprint->set_tool(util::GetToolName());
pb_fingerprint->set_version(util::GetToolFingerprint());
@@ -356,32 +361,40 @@
// Write the Visibility struct.
pb::Visibility* pb_visibility = pb_entry->mutable_visibility();
pb_visibility->set_level(SerializeVisibilityToPb(entry->visibility.level));
- SerializeSourceToPb(entry->visibility.source, &source_pool,
- pb_visibility->mutable_source());
+ if (source_pool != nullptr) {
+ SerializeSourceToPb(entry->visibility.source, source_pool.get(),
+ pb_visibility->mutable_source());
+ }
pb_visibility->set_comment(entry->visibility.comment);
if (entry->allow_new) {
pb::AllowNew* pb_allow_new = pb_entry->mutable_allow_new();
- SerializeSourceToPb(entry->allow_new.value().source, &source_pool,
- pb_allow_new->mutable_source());
+ if (source_pool != nullptr) {
+ SerializeSourceToPb(entry->allow_new.value().source, source_pool.get(),
+ pb_allow_new->mutable_source());
+ }
pb_allow_new->set_comment(entry->allow_new.value().comment);
}
if (entry->overlayable_item) {
- SerializeOverlayableItemToPb(entry->overlayable_item.value(), overlayables, &source_pool,
- pb_entry, out_table);
+ SerializeOverlayableItemToPb(entry->overlayable_item.value(), overlayables,
+ source_pool.get(), pb_entry, out_table);
}
for (const std::unique_ptr<ResourceConfigValue>& config_value : entry->values) {
pb::ConfigValue* pb_config_value = pb_entry->add_config_value();
SerializeConfig(config_value->config, pb_config_value->mutable_config());
pb_config_value->mutable_config()->set_product(config_value->product);
- SerializeValueToPb(*config_value->value, pb_config_value->mutable_value(), &source_pool);
+ SerializeValueToPb(*config_value->value, pb_config_value->mutable_value(),
+ source_pool.get());
}
}
}
}
- SerializeStringPoolToPb(source_pool, out_table->mutable_source_pool(), diag);
+
+ if (source_pool != nullptr) {
+ SerializeStringPoolToPb(*source_pool, out_table->mutable_source_pool(), diag);
+ }
}
static pb::Reference_Type SerializeReferenceTypeToPb(Reference::Type type) {
diff --git a/tools/aapt2/format/proto/ProtoSerialize.h b/tools/aapt2/format/proto/ProtoSerialize.h
index 33ffd18..7a3ea99 100644
--- a/tools/aapt2/format/proto/ProtoSerialize.h
+++ b/tools/aapt2/format/proto/ProtoSerialize.h
@@ -35,6 +35,11 @@
bool remove_empty_text_nodes = false;
};
+struct SerializeTableOptions {
+ /** Prevent serializing the source pool and source protos. */
+ bool exclude_sources = false;
+};
+
// Serializes a Value to its protobuf representation. An optional StringPool will hold the
// source path string.
void SerializeValueToPb(const Value& value, pb::Value* out_value, StringPool* src_pool = nullptr);
@@ -59,7 +64,8 @@
void SerializeConfig(const android::ConfigDescription& config, pb::Configuration* out_pb_config);
// Serializes a ResourceTable into its protobuf representation.
-void SerializeTableToPb(const ResourceTable& table, pb::ResourceTable* out_table, IDiagnostics* diag);
+void SerializeTableToPb(const ResourceTable& table, pb::ResourceTable* out_table,
+ IDiagnostics* diag, SerializeTableOptions options = {});
// Serializes a ResourceFile into its protobuf representation.
void SerializeCompiledFileToPb(const ResourceFile& file, pb::internal::CompiledFile* out_file);
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 20d772c..ca65736 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -50,6 +50,7 @@
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.WorkSource;
import android.util.Log;
import android.util.Pair;
@@ -1149,18 +1150,40 @@
* {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
* the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}.
* @param context the application context
- * @param service the Binder interface
* @hide - hide this because it takes in a parameter of type IWifiManager, which
* is a system private class.
*/
- public WifiManager(Context context, IWifiManager service, Looper looper) {
+ public WifiManager(Context context, Looper looper) {
mContext = context;
- mService = service;
mLooper = looper;
mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
+ }
+
+ /**
+ * This is used only for unit testing.
+ * @hide
+ */
+ @VisibleForTesting
+ public WifiManager(Context context, IWifiManager service, Looper looper) {
+ this(context, looper);
+ mService = service;
updateVerboseLoggingEnabledFromService();
}
+ private IWifiManager getIWifiManager() throws RemoteException {
+ if (mService == null) {
+ synchronized (this) {
+ mService = IWifiManager.Stub.asInterface(
+ ServiceManager.getService(Context.WIFI_SERVICE));
+ if (mService == null) {
+ throw new RemoteException("Wifi Service not running");
+ }
+ updateVerboseLoggingEnabledFromService();
+ }
+ }
+ return mService;
+ }
+
/**
* Return a list of all the networks configured for the current foreground
* user.
@@ -1201,7 +1224,7 @@
public List<WifiConfiguration> getConfiguredNetworks() {
try {
ParceledListSlice<WifiConfiguration> parceledList =
- mService.getConfiguredNetworks(mContext.getOpPackageName());
+ getIWifiManager().getConfiguredNetworks(mContext.getOpPackageName());
if (parceledList == null) {
return Collections.emptyList();
}
@@ -1217,7 +1240,7 @@
public List<WifiConfiguration> getPrivilegedConfiguredNetworks() {
try {
ParceledListSlice<WifiConfiguration> parceledList =
- mService.getPrivilegedConfiguredNetworks(mContext.getOpPackageName());
+ getIWifiManager().getPrivilegedConfiguredNetworks(mContext.getOpPackageName());
if (parceledList == null) {
return Collections.emptyList();
}
@@ -1249,13 +1272,13 @@
List<Pair<WifiConfiguration, Map<Integer, List<ScanResult>>>> configs = new ArrayList<>();
try {
Map<String, Map<Integer, List<ScanResult>>> results =
- mService.getAllMatchingFqdnsForScanResults(
+ getIWifiManager().getAllMatchingFqdnsForScanResults(
scanResults);
if (results.isEmpty()) {
return configs;
}
List<WifiConfiguration> wifiConfigurations =
- mService.getWifiConfigsForPasspointProfiles(
+ getIWifiManager().getWifiConfigsForPasspointProfiles(
new ArrayList<>(results.keySet()));
for (WifiConfiguration configuration : wifiConfigurations) {
Map<Integer, List<ScanResult>> scanResultsPerNetworkType = results.get(
@@ -1293,7 +1316,7 @@
return new HashMap<>();
}
try {
- return mService.getMatchingOsuProviders(scanResults);
+ return getIWifiManager().getMatchingOsuProviders(scanResults);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1320,7 +1343,7 @@
public Map<OsuProvider, PasspointConfiguration> getMatchingPasspointConfigsForOsuProviders(
@NonNull Set<OsuProvider> osuProviders) {
try {
- return mService.getMatchingPasspointConfigsForOsuProviders(
+ return getIWifiManager().getMatchingPasspointConfigsForOsuProviders(
new ArrayList<>(osuProviders));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -1405,7 +1428,7 @@
*/
private int addOrUpdateNetwork(WifiConfiguration config) {
try {
- return mService.addOrUpdateNetwork(config, mContext.getOpPackageName());
+ return getIWifiManager().addOrUpdateNetwork(config, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1631,7 +1654,7 @@
Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper();
Binder binder = new Binder();
try {
- mService.registerNetworkRequestMatchCallback(
+ getIWifiManager().registerNetworkRequestMatchCallback(
binder, new NetworkRequestMatchCallbackProxy(looper, callback),
callback.hashCode());
} catch (RemoteException e) {
@@ -1657,7 +1680,7 @@
Log.v(TAG, "unregisterNetworkRequestMatchCallback: callback=" + callback);
try {
- mService.unregisterNetworkRequestMatchCallback(callback.hashCode());
+ getIWifiManager().unregisterNetworkRequestMatchCallback(callback.hashCode());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1691,7 +1714,8 @@
public @NetworkSuggestionsStatusCode int addNetworkSuggestions(
@NonNull List<WifiNetworkSuggestion> networkSuggestions) {
try {
- return mService.addNetworkSuggestions(networkSuggestions, mContext.getOpPackageName());
+ return getIWifiManager().addNetworkSuggestions(
+ networkSuggestions, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1714,7 +1738,7 @@
public @NetworkSuggestionsStatusCode int removeNetworkSuggestions(
@NonNull List<WifiNetworkSuggestion> networkSuggestions) {
try {
- return mService.removeNetworkSuggestions(
+ return getIWifiManager().removeNetworkSuggestions(
networkSuggestions, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -1760,7 +1784,8 @@
*/
public void addOrUpdatePasspointConfiguration(PasspointConfiguration config) {
try {
- if (!mService.addOrUpdatePasspointConfiguration(config, mContext.getOpPackageName())) {
+ if (!getIWifiManager().addOrUpdatePasspointConfiguration(
+ config, mContext.getOpPackageName())) {
throw new IllegalArgumentException();
}
} catch (RemoteException e) {
@@ -1783,7 +1808,8 @@
})
public void removePasspointConfiguration(String fqdn) {
try {
- if (!mService.removePasspointConfiguration(fqdn, mContext.getOpPackageName())) {
+ if (!getIWifiManager().removePasspointConfiguration(
+ fqdn, mContext.getOpPackageName())) {
throw new IllegalArgumentException();
}
} catch (RemoteException e) {
@@ -1806,7 +1832,7 @@
})
public List<PasspointConfiguration> getPasspointConfigurations() {
try {
- return mService.getPasspointConfigurations(mContext.getOpPackageName());
+ return getIWifiManager().getPasspointConfigurations(mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1826,7 +1852,7 @@
*/
public void queryPasspointIcon(long bssid, String fileName) {
try {
- mService.queryPasspointIcon(bssid, fileName);
+ getIWifiManager().queryPasspointIcon(bssid, fileName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1840,7 +1866,7 @@
*/
public int matchProviderWithCurrentNetwork(String fqdn) {
try {
- return mService.matchProviderWithCurrentNetwork(fqdn);
+ return getIWifiManager().matchProviderWithCurrentNetwork(fqdn);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1854,7 +1880,7 @@
*/
public void deauthenticateNetwork(long holdoff, boolean ess) {
try {
- mService.deauthenticateNetwork(holdoff, ess);
+ getIWifiManager().deauthenticateNetwork(holdoff, ess);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1884,7 +1910,7 @@
@Deprecated
public boolean removeNetwork(int netId) {
try {
- return mService.removeNetwork(netId, mContext.getOpPackageName());
+ return getIWifiManager().removeNetwork(netId, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1939,7 +1965,8 @@
boolean success;
try {
- success = mService.enableNetwork(netId, attemptConnect, mContext.getOpPackageName());
+ success = getIWifiManager().enableNetwork(
+ netId, attemptConnect, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1975,7 +2002,7 @@
@Deprecated
public boolean disableNetwork(int netId) {
try {
- return mService.disableNetwork(netId, mContext.getOpPackageName());
+ return getIWifiManager().disableNetwork(netId, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1998,7 +2025,7 @@
@Deprecated
public boolean disconnect() {
try {
- return mService.disconnect(mContext.getOpPackageName());
+ return getIWifiManager().disconnect(mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2022,7 +2049,7 @@
@Deprecated
public boolean reconnect() {
try {
- return mService.reconnect(mContext.getOpPackageName());
+ return getIWifiManager().reconnect(mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2046,7 +2073,7 @@
@Deprecated
public boolean reassociate() {
try {
- return mService.reassociate(mContext.getOpPackageName());
+ return getIWifiManager().reassociate(mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2132,7 +2159,7 @@
private long getSupportedFeatures() {
try {
- return mService.getSupportedFeatures();
+ return getIWifiManager().getSupportedFeatures();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2261,10 +2288,9 @@
* @hide
*/
public WifiActivityEnergyInfo getControllerActivityEnergyInfo() {
- if (mService == null) return null;
try {
synchronized(this) {
- return mService.reportActivityInfo();
+ return getIWifiManager().reportActivityInfo();
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -2304,7 +2330,7 @@
public boolean startScan(WorkSource workSource) {
try {
String packageName = mContext.getOpPackageName();
- return mService.startScan(packageName);
+ return getIWifiManager().startScan(packageName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2333,7 +2359,7 @@
*/
public WifiInfo getConnectionInfo() {
try {
- return mService.getConnectionInfo(mContext.getOpPackageName());
+ return getIWifiManager().getConnectionInfo(mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2347,7 +2373,7 @@
*/
public List<ScanResult> getScanResults() {
try {
- return mService.getScanResults(mContext.getOpPackageName());
+ return getIWifiManager().getScanResults(mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2366,7 +2392,7 @@
@Deprecated
public boolean isScanAlwaysAvailable() {
try {
- return mService.isScanAlwaysAvailable();
+ return getIWifiManager().isScanAlwaysAvailable();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2397,7 +2423,7 @@
*/
public void setCountryCode(@NonNull String country) {
try {
- mService.setCountryCode(country);
+ getIWifiManager().setCountryCode(country);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2411,12 +2437,12 @@
*/
@UnsupportedAppUsage
public String getCountryCode() {
- try {
- String country = mService.getCountryCode();
- return country;
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- }
+ try {
+ String country = getIWifiManager().getCountryCode();
+ return country;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
}
/**
@@ -2427,7 +2453,7 @@
@UnsupportedAppUsage
public boolean isDualBandSupported() {
try {
- return mService.isDualBandSupported();
+ return getIWifiManager().isDualBandSupported();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2440,7 +2466,7 @@
*/
public boolean isDualModeSupported() {
try {
- return mService.needs5GHzToAnyApBandConversion();
+ return getIWifiManager().needs5GHzToAnyApBandConversion();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2453,7 +2479,7 @@
*/
public DhcpInfo getDhcpInfo() {
try {
- return mService.getDhcpInfo();
+ return getIWifiManager().getDhcpInfo();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2480,7 +2506,7 @@
@Deprecated
public boolean setWifiEnabled(boolean enabled) {
try {
- return mService.setWifiEnabled(mContext.getOpPackageName(), enabled);
+ return getIWifiManager().setWifiEnabled(mContext.getOpPackageName(), enabled);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2495,7 +2521,7 @@
*/
public int getWifiState() {
try {
- return mService.getWifiEnabledState();
+ return getIWifiManager().getWifiEnabledState();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2569,7 +2595,7 @@
*/
public void updateInterfaceIpState(String ifaceName, int mode) {
try {
- mService.updateInterfaceIpState(ifaceName, mode);
+ getIWifiManager().updateInterfaceIpState(ifaceName, mode);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2587,7 +2613,7 @@
*/
public boolean startSoftAp(@Nullable WifiConfiguration wifiConfig) {
try {
- return mService.startSoftAp(wifiConfig);
+ return getIWifiManager().startSoftAp(wifiConfig);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2602,7 +2628,7 @@
*/
public boolean stopSoftAp() {
try {
- return mService.stopSoftAp();
+ return getIWifiManager().stopSoftAp();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2671,7 +2697,7 @@
new LocalOnlyHotspotCallbackProxy(this, looper, callback);
try {
String packageName = mContext.getOpPackageName();
- int returnCode = mService.startLocalOnlyHotspot(
+ int returnCode = getIWifiManager().startLocalOnlyHotspot(
proxy.getMessenger(), new Binder(), packageName);
if (returnCode != LocalOnlyHotspotCallback.REQUEST_REGISTERED) {
// Send message to the proxy to make sure we call back on the correct thread
@@ -2723,7 +2749,7 @@
}
mLOHSCallbackProxy = null;
try {
- mService.stopLocalOnlyHotspot();
+ getIWifiManager().stopLocalOnlyHotspot();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2753,7 +2779,7 @@
Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper();
mLOHSObserverProxy = new LocalOnlyHotspotObserverProxy(this, looper, observer);
try {
- mService.startWatchLocalOnlyHotspot(
+ getIWifiManager().startWatchLocalOnlyHotspot(
mLOHSObserverProxy.getMessenger(), new Binder());
mLOHSObserverProxy.registered();
} catch (RemoteException e) {
@@ -2777,7 +2803,7 @@
}
mLOHSObserverProxy = null;
try {
- mService.stopWatchLocalOnlyHotspot();
+ getIWifiManager().stopWatchLocalOnlyHotspot();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2797,7 +2823,7 @@
@RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
public int getWifiApState() {
try {
- return mService.getWifiApEnabledState();
+ return getIWifiManager().getWifiApEnabledState();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2826,7 +2852,7 @@
@RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
public WifiConfiguration getWifiApConfiguration() {
try {
- return mService.getWifiApConfiguration();
+ return getIWifiManager().getWifiApConfiguration();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2843,7 +2869,8 @@
@RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE)
public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) {
try {
- return mService.setWifiApConfiguration(wifiConfig, mContext.getOpPackageName());
+ return getIWifiManager().setWifiApConfiguration(
+ wifiConfig, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2858,7 +2885,7 @@
public void notifyUserOfApBandConversion() {
Log.d(TAG, "apBand was converted, notify the user");
try {
- mService.notifyUserOfApBandConversion(mContext.getOpPackageName());
+ getIWifiManager().notifyUserOfApBandConversion(mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2886,7 +2913,7 @@
*/
public void setTdlsEnabled(InetAddress remoteIPAddress, boolean enable) {
try {
- mService.enableTdls(remoteIPAddress.getHostAddress(), enable);
+ getIWifiManager().enableTdls(remoteIPAddress.getHostAddress(), enable);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -2900,7 +2927,7 @@
*/
public void setTdlsEnabledWithMacAddress(String remoteMacAddress, boolean enable) {
try {
- mService.enableTdlsWithMacAddress(remoteMacAddress, enable);
+ getIWifiManager().enableTdlsWithMacAddress(remoteMacAddress, enable);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -3189,8 +3216,8 @@
Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper();
Binder binder = new Binder();
try {
- mService.registerSoftApCallback(binder, new SoftApCallbackProxy(looper, callback),
- callback.hashCode());
+ getIWifiManager().registerSoftApCallback(
+ binder, new SoftApCallbackProxy(looper, callback), callback.hashCode());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -3210,7 +3237,7 @@
Log.v(TAG, "unregisterSoftApCallback: callback=" + callback);
try {
- mService.unregisterSoftApCallback(callback.hashCode());
+ getIWifiManager().unregisterSoftApCallback(callback.hashCode());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -3780,7 +3807,7 @@
public void disableEphemeralNetwork(String SSID) {
if (SSID == null) throw new IllegalArgumentException("SSID cannot be null");
try {
- mService.disableEphemeralNetwork(SSID, mContext.getOpPackageName());
+ getIWifiManager().disableEphemeralNetwork(SSID, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -3824,7 +3851,7 @@
@UnsupportedAppUsage
private Messenger getWifiServiceMessenger() {
try {
- return mService.getWifiServiceMessenger(mContext.getOpPackageName());
+ return getIWifiManager().getWifiServiceMessenger(mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -3884,10 +3911,10 @@
synchronized (mBinder) {
if (mRefCounted ? (++mRefCount == 1) : (!mHeld)) {
try {
- mService.acquireWifiLock(mBinder, mLockType, mTag, mWorkSource);
+ getIWifiManager().acquireWifiLock(mBinder, mLockType, mTag, mWorkSource);
synchronized (WifiManager.this) {
if (mActiveLockCount >= MAX_ACTIVE_LOCKS) {
- mService.releaseWifiLock(mBinder);
+ getIWifiManager().releaseWifiLock(mBinder);
throw new UnsupportedOperationException(
"Exceeded maximum number of wifi locks");
}
@@ -3917,7 +3944,7 @@
synchronized (mBinder) {
if (mRefCounted ? (--mRefCount == 0) : (mHeld)) {
try {
- mService.releaseWifiLock(mBinder);
+ getIWifiManager().releaseWifiLock(mBinder);
synchronized (WifiManager.this) {
mActiveLockCount--;
}
@@ -3980,7 +4007,7 @@
}
if (changed && mHeld) {
try {
- mService.updateWifiLockWorkSource(mBinder, mWorkSource);
+ getIWifiManager().updateWifiLockWorkSource(mBinder, mWorkSource);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -4008,7 +4035,7 @@
synchronized (mBinder) {
if (mHeld) {
try {
- mService.releaseWifiLock(mBinder);
+ getIWifiManager().releaseWifiLock(mBinder);
synchronized (WifiManager.this) {
mActiveLockCount--;
}
@@ -4121,10 +4148,10 @@
synchronized (mBinder) {
if (mRefCounted ? (++mRefCount == 1) : (!mHeld)) {
try {
- mService.acquireMulticastLock(mBinder, mTag);
+ getIWifiManager().acquireMulticastLock(mBinder, mTag);
synchronized (WifiManager.this) {
if (mActiveLockCount >= MAX_ACTIVE_LOCKS) {
- mService.releaseMulticastLock(mTag);
+ getIWifiManager().releaseMulticastLock(mTag);
throw new UnsupportedOperationException(
"Exceeded maximum number of wifi locks");
}
@@ -4166,7 +4193,7 @@
synchronized (mBinder) {
if (mRefCounted ? (--mRefCount == 0) : (mHeld)) {
try {
- mService.releaseMulticastLock(mTag);
+ getIWifiManager().releaseMulticastLock(mTag);
synchronized (WifiManager.this) {
mActiveLockCount--;
}
@@ -4243,7 +4270,7 @@
*/
public boolean isMulticastEnabled() {
try {
- return mService.isMulticastEnabled();
+ return getIWifiManager().isMulticastEnabled();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -4256,7 +4283,7 @@
@UnsupportedAppUsage
public boolean initializeMulticastFiltering() {
try {
- mService.initializeMulticastFiltering();
+ getIWifiManager().initializeMulticastFiltering();
return true;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -4281,7 +4308,7 @@
@UnsupportedAppUsage
public void enableVerboseLogging (int verbose) {
try {
- mService.enableVerboseLogging(verbose);
+ getIWifiManager().enableVerboseLogging(verbose);
} catch (Exception e) {
//ignore any failure here
Log.e(TAG, "enableVerboseLogging " + e.toString());
@@ -4296,7 +4323,7 @@
@UnsupportedAppUsage
public int getVerboseLoggingLevel() {
try {
- return mService.getVerboseLoggingLevel();
+ return getIWifiManager().getVerboseLoggingLevel();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -4309,7 +4336,7 @@
*/
public void factoryReset() {
try {
- mService.factoryReset(mContext.getOpPackageName());
+ getIWifiManager().factoryReset(mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -4323,7 +4350,7 @@
@UnsupportedAppUsage
public Network getCurrentNetwork() {
try {
- return mService.getCurrentNetwork();
+ return getIWifiManager().getCurrentNetwork();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -4355,7 +4382,7 @@
*/
public void enableWifiConnectivityManager(boolean enabled) {
try {
- mService.enableWifiConnectivityManager(enabled);
+ getIWifiManager().enableWifiConnectivityManager(enabled);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -4367,7 +4394,7 @@
*/
public byte[] retrieveBackupData() {
try {
- return mService.retrieveBackupData();
+ return getIWifiManager().retrieveBackupData();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -4379,7 +4406,7 @@
*/
public void restoreBackupData(byte[] data) {
try {
- mService.restoreBackupData(data);
+ getIWifiManager().restoreBackupData(data);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -4395,7 +4422,7 @@
@Deprecated
public void restoreSupplicantBackupData(byte[] supplicantData, byte[] ipConfigData) {
try {
- mService.restoreSupplicantBackupData(supplicantData, ipConfigData);
+ getIWifiManager().restoreSupplicantBackupData(supplicantData, ipConfigData);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -4424,7 +4451,7 @@
throw new IllegalArgumentException("callback must not be null");
}
try {
- mService.startSubscriptionProvisioning(provider,
+ getIWifiManager().startSubscriptionProvisioning(provider,
new ProvisioningCallbackProxy(executor, callback));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -4538,7 +4565,7 @@
Looper looper = (handler == null) ? mContext.getMainLooper() : handler.getLooper();
Binder binder = new Binder();
try {
- mService.registerTrafficStateCallback(
+ getIWifiManager().registerTrafficStateCallback(
binder, new TrafficStateCallbackProxy(looper, callback), callback.hashCode());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -4558,7 +4585,7 @@
Log.v(TAG, "unregisterTrafficStateCallback: callback=" + callback);
try {
- mService.unregisterTrafficStateCallback(callback.hashCode());
+ getIWifiManager().unregisterTrafficStateCallback(callback.hashCode());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -4614,7 +4641,7 @@
@RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
public String[] getFactoryMacAddresses() {
try {
- return mService.getFactoryMacAddresses();
+ return getIWifiManager().getFactoryMacAddresses();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -4683,7 +4710,7 @@
@RequiresPermission(android.Manifest.permission.WIFI_SET_DEVICE_MOBILITY_STATE)
public void setDeviceMobilityState(@DeviceMobilityState int state) {
try {
- mService.setDeviceMobilityState(state);
+ getIWifiManager().setDeviceMobilityState(state);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -4738,8 +4765,9 @@
@NonNull EasyConnectStatusCallback callback) {
Binder binder = new Binder();
try {
- mService.startDppAsConfiguratorInitiator(binder, enrolleeUri, selectedNetworkId,
- enrolleeNetworkRole, new EasyConnectCallbackProxy(executor, callback));
+ getIWifiManager().startDppAsConfiguratorInitiator(
+ binder, enrolleeUri, selectedNetworkId, enrolleeNetworkRole,
+ new EasyConnectCallbackProxy(executor, callback));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -4764,7 +4792,7 @@
@NonNull EasyConnectStatusCallback callback) {
Binder binder = new Binder();
try {
- mService.startDppAsEnrolleeInitiator(binder, configuratorUri,
+ getIWifiManager().startDppAsEnrolleeInitiator(binder, configuratorUri,
new EasyConnectCallbackProxy(executor, callback));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -4786,7 +4814,7 @@
public void stopEasyConnectSession() {
try {
/* Request lower layers to stop/abort and clear resources */
- mService.stopDppSession();
+ getIWifiManager().stopDppSession();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -4885,7 +4913,7 @@
Log.v(TAG, "addOnWifiUsabilityStatsListener: listener=" + listener);
}
try {
- mService.addOnWifiUsabilityStatsListener(new Binder(),
+ getIWifiManager().addOnWifiUsabilityStatsListener(new Binder(),
new IOnWifiUsabilityStatsListener.Stub() {
@Override
public void onWifiUsabilityStats(int seqNum, boolean isSameBssidAndFreq,
@@ -4922,7 +4950,7 @@
Log.v(TAG, "removeOnWifiUsabilityStatsListener: listener=" + listener);
}
try {
- mService.removeOnWifiUsabilityStatsListener(listener.hashCode());
+ getIWifiManager().removeOnWifiUsabilityStatsListener(listener.hashCode());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -4945,7 +4973,7 @@
@RequiresPermission(android.Manifest.permission.WIFI_UPDATE_USABILITY_STATS_SCORE)
public void updateWifiUsabilityScore(int seqNum, int score, int predictionHorizonSec) {
try {
- mService.updateWifiUsabilityScore(seqNum, score, predictionHorizonSec);
+ getIWifiManager().updateWifiUsabilityScore(seqNum, score, predictionHorizonSec);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}