Merge "Make ActivityStarter single use."
diff --git a/Android.bp b/Android.bp
index d8027c1..32adc1c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -12,6 +12,649 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+// Build the master framework library.
+
+// READ ME: ########################################################
+//
+// When updating this list of aidl files, consider if that aidl is
+// part of the SDK API.  If it is, also add it to the list in Android.mk
+// that is preprocessed and distributed with the SDK.  This list should
+// not contain any aidl files for parcelables, but the one below should
+// if you intend for 3rd parties to be able to send those objects
+// across process boundaries.
+//
+// READ ME: ########################################################
+
+java_library {
+    name: "framework",
+
+    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/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/IInputForwarder.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/ISearchManager.aidl",
+        "core/java/android/app/ISearchManagerCallback.aidl",
+        "core/java/android/app/IServiceConnection.aidl",
+        "core/java/android/app/IStopUserCallback.aidl",
+        "core/java/android/app/job/IJobCallback.aidl",
+        "core/java/android/app/job/IJobScheduler.aidl",
+        "core/java/android/app/job/IJobService.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/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/trust/IStrongAuthTracker.aidl",
+        "core/java/android/app/trust/ITrustManager.aidl",
+        "core/java/android/app/trust/ITrustListener.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/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/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/crossprofile/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/IOnPermissionsChangeListener.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/permission/IRuntimePermissionPresenter.aidl",
+        "core/java/android/database/IContentObserver.aidl",
+        ":libcamera_client_aidl",
+        ":libcamera_client_framework_aidl",
+        "core/java/android/hardware/IConsumerIrService.aidl",
+        "core/java/android/hardware/ISerialManager.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/IFingerprintService.aidl",
+        "core/java/android/hardware/fingerprint/IFingerprintServiceLockoutResetCallback.aidl",
+        "core/java/android/hardware/fingerprint/IFingerprintClientActiveCallback.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/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/IFusedLocationHardware.aidl",
+        "core/java/android/hardware/location/IFusedLocationHardwareSink.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/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/net/ICaptivePortal.aidl",
+        "core/java/android/net/IConnectivityManager.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/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/os/IBatteryPropertiesListener.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",
+        "core/java/android/os/IIncidentManager.aidl",
+        "core/java/android/os/IIncidentReportCompletedListener.aidl",
+        "core/java/android/os/IIncidentReportStatusListener.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",
+        "core/java/android/os/IStatsCompanionService.aidl",
+        "core/java/android/os/IStatsManager.aidl",
+        "core/java/android/os/IThermalEventListener.aidl",
+        "core/java/android/os/IThermalService.aidl",
+        "core/java/android/os/IUpdateLock.aidl",
+        "core/java/android/os/IUserManager.aidl",
+        "core/java/android/os/IVibratorService.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/security/IKeystoreService.aidl",
+        "core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl",
+        "core/java/android/service/autofill/IAutoFillService.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/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/IRetainSubscriptionsForFactoryResetCallback.aidl",
+        "core/java/android/service/euicc/ISwitchToSubscriptionCallback.aidl",
+        "core/java/android/service/euicc/IUpdateSubscriptionNicknameCallback.aidl",
+        "core/java/android/service/gatekeeper/IGateKeeperService.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/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/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/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/IAutofillWindowPresenter.aidl",
+        "core/java/android/view/IApplicationToken.aidl",
+        "core/java/android/view/IAppTransitionAnimationSpecsFuture.aidl",
+        "core/java/android/view/IDockedStackListener.aidl",
+        "core/java/android/view/IGraphicsStats.aidl",
+        "core/java/android/view/IGraphicsStatsCallback.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/IRotationWatcher.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/IAppOpsCallback.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/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/car/ICarServiceHelper.aidl",
+        "core/java/com/android/internal/inputmethod/IInputContentUriToken.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/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/IFusedProvider.aidl",
+        "location/java/android/location/IGeocodeProvider.aidl",
+        "location/java/android/location/IGeofenceProvider.aidl",
+        "location/java/android/location/IGnssStatusListener.aidl",
+        "location/java/android/location/IGnssStatusProvider.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",
+        "media/java/android/media/IAudioService.aidl",
+        "media/java/android/media/IAudioFocusDispatcher.aidl",
+        "media/java/android/media/IAudioRoutesObserver.aidl",
+        "media/java/android/media/IMediaHTTPConnection.aidl",
+        "media/java/android/media/IMediaHTTPService.aidl",
+        "media/java/android/media/IMediaResourceMonitor.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/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/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/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/ITelecomService.aidl",
+        "telecomm/java/com/android/internal/telecom/RemoteServiceCallback.aidl",
+        "telephony/java/android/telephony/mbms/IMbmsDownloadSessionCallback.aidl",
+        "telephony/java/android/telephony/mbms/IMbmsStreamingSessionCallback.aidl",
+        "telephony/java/android/telephony/mbms/IDownloadStateCallback.aidl",
+        "telephony/java/android/telephony/mbms/IStreamingServiceCallback.aidl",
+        "telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl",
+        "telephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.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/IImsSmsFeature.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/ISmsListener.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/IMms.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/ISms.aidl",
+        "telephony/java/com/android/internal/telephony/ISub.aidl",
+        "telephony/java/com/android/internal/telephony/ITelephony.aidl",
+        "telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl",
+        "telephony/java/com/android/internal/telephony/IWapPushManager.aidl",
+        "telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl",
+        "wifi/java/android/net/wifi/IWifiManager.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/IWifiScanner.aidl",
+        "wifi/java/android/net/wifi/IRttManager.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",
+        ":netd_aidl",
+        ":vold_aidl",
+        ":installd_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/webkit/EventLogTags.logtags",
+        "core/java/com/android/internal/logging/EventLogTags.logtags",
+
+        ":framework-statslog-gen",
+    ],
+    logtags: [
+        "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/webkit/EventLogTags.logtags",
+        "core/java/com/android/internal/logging/EventLogTags.logtags",
+    ],
+
+    aidl: {
+        local_include_dirs: [
+            // From build/make/core/pathmap.mk FRAMEWORK_BASE_SUBDIRS
+            "core/java",
+            "graphics/java",
+            "location/java",
+            "lowpan/java",
+            "media/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",
+        ],
+
+        include_dirs: [
+            "system/update_engine/binder_bindings",
+            "frameworks/native/aidl/binder",
+            "frameworks/av/camera/aidl",
+            "frameworks/av/media/libaudioclient/aidl",
+            "frameworks/native/aidl/gui",
+            "system/core/storaged/binder",
+            "system/netd/server/binder",
+            "system/vold/binder",
+            "system/bt/binder",
+        ],
+    },
+
+    no_framework_libs: true,
+    libs: [
+        "conscrypt",
+        "okhttp",
+        "bouncycastle",
+        "ext",
+    ],
+
+    static_libs: [
+        "framework-protos",
+        "android.hidl.base-V1.0-java",
+        "android.hardware.cas-V1.0-java",
+        "android.hardware.contexthub-V1.0-java",
+        "android.hardware.health-V1.0-java-constants",
+        "android.hardware.thermal-V1.0-java-constants",
+        "android.hardware.tv.input-V1.0-java-constants",
+        "android.hardware.usb-V1.0-java-constants",
+        "android.hardware.usb-V1.1-java-constants",
+        "android.hardware.vibrator-V1.0-java-constants",
+        "android.hardware.vibrator-V1.1-java-constants",
+        "android.hardware.wifi-V1.0-java-constants",
+    ],
+
+    // Loaded with System.loadLibrary by android.view.textclassifier
+    required: ["libtextclassifier"],
+
+    javac_shard_size: 150,
+
+    dxflags: [
+        "--core-library",
+        "--multi-dex",
+    ],
+}
+
+genrule {
+    name: "framework-statslog-gen",
+    tools: ["stats-log-api-gen"],
+    cmd: "$(location stats-log-api-gen) --java $(out)",
+    out: ["android/util/StatsLog.java"],
+}
+
+gensrcs {
+    name: "framework-javastream-protos",
+    depfile: true,
+
+    tools: [
+        "aprotoc",
+        "protoc-gen-javastream",
+        "soong_zip",
+    ],
+
+    // Append protoc-gen-javastream tool's PATH otherwise aprotoc can't find the plugin tool
+    cmd: "export PATH=$$PATH:$$(dirname $(location protoc-gen-javastream)) " +
+        "&& mkdir -p $(genDir)/$(in) " +
+        "&& $(location aprotoc) " +
+        "  --plugin=protoc-gen-java-stream=protoc-gen-javastream " +
+        "  --dependency_out=$(depfile) " +
+        "  --javastream_out=$(genDir)/$(in) " +
+        "  -Iexternal/protobuf/src " +
+        "  -I . " +
+        "  $(in) " +
+        "&& $(location soong_zip) -jar -o $(out) -C $(genDir)/$(in) -D $(genDir)/$(in)",
+
+    srcs: ["core/proto/**/*.proto"],
+    output_extension: "srcjar",
+}
+
 // Build ext.jar
 // ============================================================
 java_library {
diff --git a/Android.mk b/Android.mk
index a69170f..8ce2616 100644
--- a/Android.mk
+++ b/Android.mk
@@ -15,16 +15,8 @@
 #
 LOCAL_PATH := $(call my-dir)
 
-# We have a special case here where we build the library's resources
-# independently from its code, so we need to find where the resource
-# class source got placed in the course of building the resources.
-# Thus, the magic here.
-# Also, this module cannot depend directly on the R.java file; if it
-# did, the PRIVATE_* vars for R.java wouldn't be guaranteed to be correct.
-# Instead, it depends on the R.stamp file, which lists the corresponding
-# R.java file as a prerequisite.
-# TODO: find a more appropriate way to do this.
-framework_res_source_path := APPS/framework-res_intermediates/src
+# Load framework-specific path mappings used later in the build.
+include $(LOCAL_PATH)/pathmap.mk
 
 # Build the master framework library.
 # The framework contains too many method references (>64K) for poor old DEX.
@@ -35,651 +27,6 @@
 # embedded builds use nothing in frameworks/base
 ifneq ($(ANDROID_BUILD_EMBEDDED),true)
 
-include $(CLEAR_VARS)
-
-# Load framework-specific path mappings used later in the build.
-include $(LOCAL_PATH)/pathmap.mk
-
-# FRAMEWORKS_BASE_SUBDIRS comes from build/core/pathmap.mk
-LOCAL_SRC_FILES := \
-        $(call find-other-java-files,$(FRAMEWORKS_BASE_SUBDIRS)) \
-        $(call all-proto-files-under, core/proto)
-
-# EventLogTags files.
-LOCAL_SRC_FILES += \
-       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/webkit/EventLogTags.logtags \
-       core/java/com/android/internal/logging/EventLogTags.logtags \
-
-## READ ME: ########################################################
-##
-## When updating this list of aidl files, consider if that aidl is
-## part of the SDK API.  If it is, also add it to the list below that
-## is preprocessed and distributed with the SDK.  This list should
-## not contain any aidl files for parcelables, but the one below should
-## if you intend for 3rd parties to be able to send those objects
-## across process boundaries.
-##
-## READ ME: ########################################################
-LOCAL_SRC_FILES += \
-	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/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/IInputForwarder.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/ISearchManager.aidl \
-	core/java/android/app/ISearchManagerCallback.aidl \
-	core/java/android/app/IServiceConnection.aidl \
-	core/java/android/app/IStopUserCallback.aidl \
-	core/java/android/app/job/IJobCallback.aidl \
-	core/java/android/app/job/IJobScheduler.aidl \
-	core/java/android/app/job/IJobService.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/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/trust/IStrongAuthTracker.aidl \
-	core/java/android/app/trust/ITrustManager.aidl \
-	core/java/android/app/trust/ITrustListener.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/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 \
-	../../system/bt/binder/android/bluetooth/IBluetooth.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothA2dp.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothA2dpSink.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothAvrcpController.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothCallback.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothProfileServiceConnection.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothHeadset.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothHeadsetPhone.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothHealth.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothHealthCallback.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothHidHost.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothPan.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothManager.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothManagerCallback.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothMap.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothMapClient.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothPbap.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothPbapClient.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothSap.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothSocketManager.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothStateChangeCallback.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothHeadsetClient.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothHidDevice.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothHidDeviceCallback.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothGatt.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothGattCallback.aidl \
-	../../system/bt/binder/android/bluetooth/IBluetoothGattServerCallback.aidl \
-	../../system/bt/binder/android/bluetooth/le/IAdvertisingSetCallback.aidl \
-	../../system/bt/binder/android/bluetooth/le/IPeriodicAdvertisingCallback.aidl \
-	../../system/bt/binder/android/bluetooth/le/IScannerCallback.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/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/crossprofile/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/IOnPermissionsChangeListener.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 \
-	../native/libs/binder/aidl/android/content/pm/IPackageManagerNative.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/permission/IRuntimePermissionPresenter.aidl \
-	core/java/android/database/IContentObserver.aidl \
-	../av/camera/aidl/android/hardware/ICameraService.aidl \
-	../av/camera/aidl/android/hardware/ICameraServiceListener.aidl \
-	../av/camera/aidl/android/hardware/ICameraServiceProxy.aidl \
-	../av/camera/aidl/android/hardware/ICamera.aidl \
-	../av/camera/aidl/android/hardware/ICameraClient.aidl \
-	../av/camera/aidl/android/hardware/camera2/ICameraDeviceUser.aidl \
-	../av/camera/aidl/android/hardware/camera2/ICameraDeviceCallbacks.aidl \
-	core/java/android/hardware/IConsumerIrService.aidl \
-	core/java/android/hardware/ISerialManager.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/IFingerprintService.aidl \
-	core/java/android/hardware/fingerprint/IFingerprintServiceLockoutResetCallback.aidl \
-	core/java/android/hardware/fingerprint/IFingerprintClientActiveCallback.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/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/IFusedLocationHardware.aidl \
-	core/java/android/hardware/location/IFusedLocationHardwareSink.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/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/net/ICaptivePortal.aidl \
-	core/java/android/net/IConnectivityManager.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/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/os/IBatteryPropertiesListener.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 \
-	core/java/android/os/IIncidentManager.aidl \
-	core/java/android/os/IIncidentReportCompletedListener.aidl \
-	core/java/android/os/IIncidentReportStatusListener.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 \
-	core/java/android/os/IStatsCompanionService.aidl \
-	core/java/android/os/IStatsManager.aidl \
-	core/java/android/os/IThermalEventListener.aidl \
-	core/java/android/os/IThermalService.aidl \
-	core/java/android/os/IUpdateLock.aidl \
-	core/java/android/os/IUserManager.aidl \
-	core/java/android/os/IVibratorService.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/security/IKeystoreService.aidl \
-	core/java/android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl \
-	core/java/android/service/autofill/IAutoFillService.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/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/IRetainSubscriptionsForFactoryResetCallback.aidl \
-	core/java/android/service/euicc/ISwitchToSubscriptionCallback.aidl \
-	core/java/android/service/euicc/IUpdateSubscriptionNicknameCallback.aidl \
-	core/java/android/service/gatekeeper/IGateKeeperService.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/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/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/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/IAutofillWindowPresenter.aidl \
-	core/java/android/view/IApplicationToken.aidl \
-	core/java/android/view/IAppTransitionAnimationSpecsFuture.aidl \
-	core/java/android/view/IDockedStackListener.aidl \
-	core/java/android/view/IGraphicsStats.aidl \
-	core/java/android/view/IGraphicsStatsCallback.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/IRotationWatcher.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/IAppOpsCallback.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/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/car/ICarServiceHelper.aidl \
-	core/java/com/android/internal/inputmethod/IInputContentUriToken.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/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/IFusedProvider.aidl \
-	location/java/android/location/IGeocodeProvider.aidl \
-	location/java/android/location/IGeofenceProvider.aidl \
-	location/java/android/location/IGnssStatusListener.aidl \
-	location/java/android/location/IGnssStatusProvider.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 \
-	media/java/android/media/IAudioService.aidl \
-	media/java/android/media/IAudioFocusDispatcher.aidl \
-	media/java/android/media/IAudioRoutesObserver.aidl \
-	media/java/android/media/IMediaHTTPConnection.aidl \
-	media/java/android/media/IMediaHTTPService.aidl \
-	media/java/android/media/IMediaResourceMonitor.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 \
-	../av/media/libaudioclient/aidl/android/media/IPlayer.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/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/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/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/ITelecomService.aidl \
-	telecomm/java/com/android/internal/telecom/RemoteServiceCallback.aidl \
-	telephony/java/android/telephony/mbms/IMbmsDownloadSessionCallback.aidl \
-	telephony/java/android/telephony/mbms/IMbmsStreamingSessionCallback.aidl \
-	telephony/java/android/telephony/mbms/IDownloadStateCallback.aidl \
-        telephony/java/android/telephony/mbms/IStreamingServiceCallback.aidl \
-	telephony/java/android/telephony/mbms/vendor/IMbmsDownloadService.aidl \
-	telephony/java/android/telephony/mbms/vendor/IMbmsStreamingService.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/IImsSmsFeature.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/ISmsListener.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/IMms.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/ISms.aidl \
-	telephony/java/com/android/internal/telephony/ISub.aidl \
-	telephony/java/com/android/internal/telephony/ITelephony.aidl \
-	telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl \
-	telephony/java/com/android/internal/telephony/IWapPushManager.aidl \
-	telephony/java/com/android/internal/telephony/euicc/IEuiccController.aidl \
-	wifi/java/android/net/wifi/IWifiManager.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/IWifiScanner.aidl \
-	wifi/java/android/net/wifi/IRttManager.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 \
-
-# The following are native binders that need to go with the native component
-# at system/update_engine/binder_bindings/. Use relative path to refer to them.
-LOCAL_SRC_FILES += \
-	../../system/update_engine/binder_bindings/android/os/IUpdateEngine.aidl \
-	../../system/update_engine/binder_bindings/android/os/IUpdateEngineCallback.aidl \
-
-LOCAL_SRC_FILES += \
-	../../system/core/storaged/binder/android/os/IStoraged.aidl \
-	../../system/netd/server/binder/android/net/INetd.aidl \
-	../../system/vold/binder/android/os/IVold.aidl \
-	../../system/vold/binder/android/os/IVoldListener.aidl \
-	../../system/vold/binder/android/os/IVoldTaskListener.aidl \
-	../native/cmds/installd/binder/android/os/IInstalld.aidl \
-
-LOCAL_AIDL_INCLUDES += system/update_engine/binder_bindings
-
-LOCAL_AIDL_INCLUDES += core/java/android/os/StatsLogEventWrapper.aidl
-
-LOCAL_AIDL_INCLUDES += frameworks/base/lowpan/java
-LOCAL_SRC_FILES += \
-	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
-
-# StatsLog generated functions
-statslog_src_dir := $(call intermediates-dir-for,JAVA_LIBRARIES,framework,,COMMON)/statslog
-gen := $(statslog_src_dir)/android/util/StatsLog.java
-$(gen): PRIVATE_PATH := $(LOCAL_PATH)
-$(gen): PRIVATE_CUSTOM_TOOL = $(HOST_OUT_EXECUTABLES)/stats-log-api-gen --java $@
-$(gen): $(HOST_OUT_EXECUTABLES)/stats-log-api-gen
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(gen)
-statslog_src_dir:=
-gen:=
-
-# FRAMEWORKS_BASE_JAVA_SRC_DIRS comes from build/core/pathmap.mk
-LOCAL_AIDL_INCLUDES += \
-      $(FRAMEWORKS_BASE_JAVA_SRC_DIRS) \
-      frameworks/native/aidl/binder
-
-LOCAL_AIDL_INCLUDES += \
-	frameworks/av/camera/aidl \
-	frameworks/av/drm/libmediadrm/aidl \
-	frameworks/av/media/libaudioclient/aidl \
-	frameworks/native/aidl/gui \
-	system/core/storaged/binder \
-	system/netd/server/binder \
-	system/vold/binder \
-	system/bt/binder
-
-LOCAL_INTERMEDIATE_SOURCES := \
-			$(framework_res_source_path)/android/R.java \
-			$(framework_res_source_path)/android/Manifest.java \
-			$(framework_res_source_path)/com/android/internal/R.java
-
-# Make sure that R.java and Manifest.java are built before we build
-# the source for this library.
-framework_res_R_stamp := \
-	$(call intermediates-dir-for,APPS,framework-res,,COMMON)/src/R.stamp
-LOCAL_ADDITIONAL_DEPENDENCIES := $(framework_res_R_stamp)
-
-LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_JAVA_LIBRARIES := core-oj core-libart conscrypt okhttp bouncycastle ext
-
-LOCAL_STATIC_JAVA_LIBRARIES :=                           \
-    framework-protos                                     \
-    android.hidl.base-V1.0-java                          \
-    android.hardware.cas-V1.0-java                       \
-    android.hardware.contexthub-V1.0-java                \
-    android.hardware.health-V1.0-java-constants          \
-    android.hardware.thermal-V1.0-java-constants         \
-    android.hardware.tv.input-V1.0-java-constants        \
-    android.hardware.usb-V1.0-java-constants             \
-    android.hardware.usb-V1.1-java-constants             \
-    android.hardware.vibrator-V1.0-java-constants        \
-    android.hardware.vibrator-V1.1-java-constants        \
-    android.hardware.wifi-V1.0-java-constants            \
-
-# Loaded with System.loadLibrary by android.view.textclassifier
-LOCAL_REQUIRED_MODULES += libtextclassifier
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := stream
-LOCAL_PROTOC_FLAGS := \
-    -Iexternal/protobuf/src
-
-LOCAL_MODULE := framework
-
-LOCAL_JAVAC_SHARD_SIZE := 150
-
-LOCAL_DX_FLAGS := --core-library --multi-dex
-LOCAL_JACK_FLAGS := --multi-dex native
-
-LOCAL_RMTYPEDEFS := true
-
-ifeq ($(EMMA_INSTRUMENT_FRAMEWORK),true)
-LOCAL_EMMA_INSTRUMENT := true
-endif
-
-include $(BUILD_JAVA_LIBRARY)
-
-framework_module := $(LOCAL_INSTALLED_MODULE)
-$(framework_module): | $(dir $(framework_module))framework-res.apk
-
-framework_built := $(call java-lib-deps,framework)
-
 # Copy AIDL files to be preprocessed and included in the SDK,
 # specified relative to the root of the build tree.
 # ============================================================
@@ -910,85 +257,79 @@
 
 # TODO: deal with com/google/android/googleapps
 packages_to_document := \
-	android \
-	javax/microedition/khronos \
-	org/apache/http/conn \
-	org/apache/http/params
-
-
-# Search through the base framework dirs for these packages.
-# The result will be relative to frameworks/base.
-fwbase_dirs_to_document := \
-	test-base/src \
-	$(patsubst $(LOCAL_PATH)/%,%, \
-	  $(wildcard \
-	    $(foreach dir, $(FRAMEWORKS_BASE_JAVA_SRC_DIRS), \
-	      $(addprefix $(dir)/, $(packages_to_document)) \
-	     ) \
-	   ) \
-	 )
+  android \
+  javax/microedition/khronos \
+  org/apache/http/conn \
+  org/apache/http/params \
 
 # include definition of libcore_to_document
 include libcore/Docs.mk
 
 non_base_dirs := \
-	../opt/telephony/src/java/android/telephony \
-	../opt/telephony/src/java/android/telephony/gsm \
-	../opt/net/voip/src/java/android/net/rtp \
-	../opt/net/voip/src/java/android/net/sip
+  ../opt/telephony/src/java/android/telephony \
+  ../opt/telephony/src/java/android/telephony/gsm \
+  ../opt/net/voip/src/java/android/net/rtp \
+  ../opt/net/voip/src/java/android/net/sip \
 
 framework_base_android_test_mock_src_files := \
-	$(call all-java-files-under, test-mock/src/android/test/mock)
+  $(call all-java-files-under, test-mock/src/android/test/mock)
 
 framework_base_android_test_runner_excluding_mock_src_files := \
-	$(filter-out $(framework_base_android_test_mock_src_files), $(call all-java-files-under, test-runner/src))
+  $(filter-out $(framework_base_android_test_mock_src_files), $(call all-java-files-under, test-runner/src))
 
-# These are relative to frameworks/base
-dirs_to_check_apis := \
-  $(fwbase_dirs_to_document) \
-	$(non_base_dirs)
+# Find all files in specific directories (relative to frameworks/base)
+# to document and check apis
+files_to_check_apis := \
+  $(call find-other-java-files, \
+    test-base/src \
+    $(non_base_dirs) \
+  )
 
-###########################################################
-## Return all directories that have a 'NO_DOCS' file in
-## them, appending a '%' to them to form a pattern to
-## filter out files under those directories.
-## $(1): A list of base directories to look at.
-###########################################################
-define find-no-docs-pattern
-$(addsuffix %, $(dir $(foreach dir, $(1), $(shell cd $(LOCAL_PATH); find $(dir) -name NO_DOCS))))
-endef
+# Find all files in specific packages that were used to compile
+# framework.jar to document and check apis
+files_to_check_apis += \
+  $(addprefix ../../,\
+    $(filter \
+      $(foreach dir,$(FRAMEWORKS_BASE_JAVA_SRC_DIRS),\
+        $(foreach package,$(packages_to_document),\
+          $(dir)/$(package)/%.java)),\
+      $(SOONG_FRAMEWORK_SRCS)))
+
+# Find all generated files that were used to compile framework.jar
+files_to_check_apis += \
+  $(addprefix ../../,\
+    $(filter $(OUT_DIR)/%,\
+      $(SOONG_FRAMEWORK_SRCS)))
 
 # These are relative to frameworks/base
 # FRAMEWORKS_BASE_SUBDIRS comes from build/core/pathmap.mk
-dirs_to_document := \
-	$(dirs_to_check_apis) \
-	test-runner/src \
-	$(addprefix ../../, $(FRAMEWORKS_DATA_BINDING_JAVA_SRC_DIRS))
-
-patterns_to_not_document := \
-	$(call find-no-docs-pattern, $(dirs_to_document))
+files_to_document := \
+  $(files_to_check_apis) \
+  $(call find-other-java-files,\
+    $(addprefix ../../, $(FRAMEWORKS_DATA_BINDING_JAVA_SRC_DIRS)) \
+    test-runner/src)
 
 # These are relative to frameworks/base
 html_dirs := \
 	$(FRAMEWORKS_BASE_SUBDIRS) \
-	$(non_base_dirs)
+	$(non_base_dirs) \
 
 # Common sources for doc check and api check
 common_src_files := \
 	$(call find-other-html-files, $(html_dirs)) \
-	$(addprefix ../../, $(libcore_to_document))
+	$(addprefix ../../, $(libcore_to_document)) \
 
 # These are relative to frameworks/base
 framework_docs_LOCAL_SRC_FILES := \
-	$(filter-out $(patterns_to_not_document), $(call find-other-java-files, $(dirs_to_document))) \
-	$(common_src_files)
+  $(files_to_document) \
+  $(common_src_files) \
 
 # These are relative to frameworks/base
 framework_docs_LOCAL_API_CHECK_SRC_FILES := \
-	$(framework_base_android_test_mock_src_files) \
-	$(framework_base_android_test_runner_excluding_mock_src_files) \
-	$(call all-java-files-under, $(dirs_to_check_apis)) \
-	$(common_src_files)
+  $(framework_base_android_test_mock_src_files) \
+  $(framework_base_android_test_runner_excluding_mock_src_files) \
+  $(files_to_check_apis) \
+  $(common_src_files) \
 
 # This is used by ide.mk as the list of source files that are
 # always included.
@@ -997,10 +338,9 @@
 framework_docs_LOCAL_DROIDDOC_SOURCE_PATH := \
 	$(FRAMEWORKS_BASE_JAVA_SRC_DIRS)
 
+framework_docs_LOCAL_SRCJARS := $(SOONG_FRAMEWORK_SRCJARS)
+
 framework_docs_LOCAL_INTERMEDIATE_SOURCES := \
-	$(framework_res_source_path)/android/R.java \
-	$(framework_res_source_path)/android/Manifest.java \
-	$(framework_res_source_path)/com/android/internal/R.java \
 	$(patsubst $(TARGET_OUT_COMMON_INTERMEDIATES)/%,%,$(libcore_to_document_generated))
 
 framework_docs_LOCAL_API_CHECK_JAVA_LIBRARIES := \
@@ -1123,6 +463,7 @@
 
 LOCAL_SRC_FILES := $(framework_docs_LOCAL_API_CHECK_SRC_FILES)
 LOCAL_INTERMEDIATE_SOURCES := $(framework_docs_LOCAL_INTERMEDIATE_SOURCES)
+LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
 LOCAL_JAVA_LIBRARIES := $(framework_docs_LOCAL_API_CHECK_JAVA_LIBRARIES)
 LOCAL_MODULE_CLASS := $(framework_docs_LOCAL_MODULE_CLASS)
 LOCAL_ADDITIONAL_JAVA_DIR := $(framework_docs_LOCAL_API_CHECK_ADDITIONAL_JAVA_DIR)
@@ -1148,6 +489,7 @@
 
 LOCAL_SRC_FILES := $(framework_docs_LOCAL_API_CHECK_SRC_FILES)
 LOCAL_INTERMEDIATE_SOURCES := $(framework_docs_LOCAL_INTERMEDIATE_SOURCES)
+LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
 LOCAL_JAVA_LIBRARIES := $(framework_docs_LOCAL_API_CHECK_JAVA_LIBRARIES)
 LOCAL_MODULE_CLASS := $(framework_docs_LOCAL_MODULE_CLASS)
 LOCAL_ADDITIONAL_JAVA_DIR := $(framework_docs_LOCAL_API_CHECK_ADDITIONAL_JAVA_DIR)
@@ -1173,6 +515,7 @@
 
 LOCAL_SRC_FILES:=$(framework_docs_LOCAL_API_CHECK_SRC_FILES)
 LOCAL_INTERMEDIATE_SOURCES:=$(framework_docs_LOCAL_INTERMEDIATE_SOURCES)
+LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
 LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_API_CHECK_JAVA_LIBRARIES)
 LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
 LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
@@ -1198,7 +541,7 @@
 include $(BUILD_DROIDDOC)
 
 # $(gen), i.e. framework.aidl, is also needed while building against the current stub.
-$(full_target): $(framework_built) $(gen)
+$(full_target): $(gen)
 $(INTERNAL_PLATFORM_API_FILE): $(full_target)
 $(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_API_FILE))
 
@@ -1207,6 +550,7 @@
 
 LOCAL_SRC_FILES:=$(framework_docs_LOCAL_API_CHECK_SRC_FILES)
 LOCAL_INTERMEDIATE_SOURCES:=$(framework_docs_LOCAL_INTERMEDIATE_SOURCES)
+LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
 LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_API_CHECK_JAVA_LIBRARIES)
 LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
 LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
@@ -1234,7 +578,7 @@
 include $(BUILD_DROIDDOC)
 
 # $(gen), i.e. framework.aidl, is also needed while building against the current stub.
-$(full_target): $(framework_built) $(gen)
+$(full_target): $(gen)
 $(INTERNAL_PLATFORM_SYSTEM_API_FILE): $(full_target)
 $(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_SYSTEM_API_FILE))
 
@@ -1243,6 +587,7 @@
 
 LOCAL_SRC_FILES:=$(framework_docs_LOCAL_API_CHECK_SRC_FILES)
 LOCAL_INTERMEDIATE_SOURCES:=$(framework_docs_LOCAL_INTERMEDIATE_SOURCES)
+LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
 LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_API_CHECK_JAVA_LIBRARIES)
 LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
 LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
@@ -1271,7 +616,7 @@
 include $(BUILD_DROIDDOC)
 
 # $(gen), i.e. framework.aidl, is also needed while building against the current stub.
-$(full_target): $(framework_built) $(gen)
+$(full_target): $(gen)
 $(INTERNAL_PLATFORM_TEST_API_FILE): $(full_target)
 $(call dist-for-goals,sdk,$(INTERNAL_PLATFORM_TEST_API_FILE))
 
@@ -1280,6 +625,7 @@
 
 LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
 LOCAL_INTERMEDIATE_SOURCES:=$(framework_docs_LOCAL_INTERMEDIATE_SOURCES)
+LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
 LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
 LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
 LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
@@ -1301,7 +647,7 @@
 include $(BUILD_DROIDDOC)
 
 # $(gen), i.e. framework.aidl, is also needed while building against the current stub.
-$(full_target): $(framework_built) $(gen)
+$(full_target): $(gen)
 
 # Run this for checkbuild
 checkbuild: doc-comment-check-docs
@@ -1313,6 +659,7 @@
 
 LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
 LOCAL_INTERMEDIATE_SOURCES:=$(framework_docs_LOCAL_INTERMEDIATE_SOURCES)
+LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
 LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
 LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
 LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
@@ -1341,7 +688,6 @@
 	$(hide) $(ACP) $< $@
 
 $(full_target): $(static_doc_index_redirect)
-$(full_target): $(framework_built)
 
 
 # ==== Public API static reference docs ==================================
@@ -1349,6 +695,7 @@
 
 LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
 LOCAL_INTERMEDIATE_SOURCES:=$(framework_docs_LOCAL_INTERMEDIATE_SOURCES)
+LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
 LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
 LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
 LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
@@ -1383,7 +730,6 @@
 
 $(full_target): $(static_doc_index_redirect)
 $(full_target): $(static_doc_properties)
-$(full_target): $(framework_built)
 
 
 # ==== System API static reference docs ==================================
@@ -1391,6 +737,7 @@
 
 LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
 LOCAL_INTERMEDIATE_SOURCES:=$(framework_docs_LOCAL_INTERMEDIATE_SOURCES)
+LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
 LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
 LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
 LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
@@ -1435,6 +782,7 @@
 
 LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
 LOCAL_INTERMEDIATE_SOURCES:=$(framework_docs_LOCAL_INTERMEDIATE_SOURCES)
+LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
 LOCAL_STATIC_JAVA_LIBRARIES:=$(framework_docs_LOCAL_STATIC_JAVA_LIBRARIES)
 LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
 LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
@@ -1463,6 +811,7 @@
 
 LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
 LOCAL_INTERMEDIATE_SOURCES:=$(framework_docs_LOCAL_INTERMEDIATE_SOURCES)
+LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
 LOCAL_STATIC_JAVA_LIBRARIES:=$(framework_docs_LOCAL_STATIC_JAVA_LIBRARIES)
 LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
 LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
@@ -1498,6 +847,7 @@
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
 LOCAL_INTERMEDIATE_SOURCES:=$(framework_docs_LOCAL_INTERMEDIATE_SOURCES)
+LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
 LOCAL_STATIC_JAVA_LIBRARIES:=$(framework_docs_LOCAL_STATIC_JAVA_LIBRARIES)
 LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
 LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
@@ -1527,6 +877,7 @@
 include $(CLEAR_VARS)
 LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
 LOCAL_INTERMEDIATE_SOURCES:=$(framework_docs_LOCAL_INTERMEDIATE_SOURCES)
+LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
 LOCAL_STATIC_JAVA_LIBRARIES:=$(framework_docs_LOCAL_STATIC_JAVA_LIBRARIES)
 LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
 LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
@@ -1556,6 +907,7 @@
 
 LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
 LOCAL_INTERMEDIATE_SOURCES:=$(framework_docs_LOCAL_INTERMEDIATE_SOURCES)
+LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
 LOCAL_STATIC_JAVA_LIBRARIES:=$(framework_docs_LOCAL_STATIC_JAVA_LIBRARIES)
 LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
 LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
@@ -1581,6 +933,7 @@
 
 LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
 LOCAL_INTERMEDIATE_SOURCES:=$(framework_docs_LOCAL_INTERMEDIATE_SOURCES)
+LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
 LOCAL_STATIC_JAVA_LIBRARIES:=$(framework_docs_LOCAL_STATIC_JAVA_LIBRARIES)
 LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
 LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
@@ -1609,6 +962,7 @@
 
 LOCAL_SRC_FILES:=$(framework_docs_LOCAL_SRC_FILES)
 LOCAL_INTERMEDIATE_SOURCES:=$(framework_docs_LOCAL_INTERMEDIATE_SOURCES)
+LOCAL_SRCJARS:=$(framework_docs_LOCAL_SRCJARS)
 LOCAL_JAVA_LIBRARIES:=$(framework_docs_LOCAL_JAVA_LIBRARIES)
 LOCAL_MODULE_CLASS:=$(framework_docs_LOCAL_MODULE_CLASS)
 LOCAL_DROIDDOC_SOURCE_PATH:=$(framework_docs_LOCAL_DROIDDOC_SOURCE_PATH)
diff --git a/api/current.txt b/api/current.txt
index 182dd3a..279a6f2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -7209,6 +7209,7 @@
   }
 
   public final class UsageStatsManager {
+    method public int getAppStandbyBucket();
     method public boolean isAppInactive(java.lang.String);
     method public java.util.Map<java.lang.String, android.app.usage.UsageStats> queryAndAggregateUsageStats(long, long);
     method public java.util.List<android.app.usage.ConfigurationStats> queryConfigurations(int, long, long);
@@ -7219,6 +7220,10 @@
     field public static final int INTERVAL_MONTHLY = 2; // 0x2
     field public static final int INTERVAL_WEEKLY = 1; // 0x1
     field public static final int INTERVAL_YEARLY = 3; // 0x3
+    field public static final int STANDBY_BUCKET_ACTIVE = 10; // 0xa
+    field public static final int STANDBY_BUCKET_FREQUENT = 30; // 0x1e
+    field public static final int STANDBY_BUCKET_RARE = 40; // 0x28
+    field public static final int STANDBY_BUCKET_WORKING_SET = 20; // 0x14
   }
 
 }
diff --git a/api/system-current.txt b/api/system-current.txt
index 4cf9d95..50a8ea4 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -609,8 +609,11 @@
   }
 
   public final class UsageStatsManager {
+    method public int getAppStandbyBucket(java.lang.String);
     method public void setAppStandbyBucket(java.lang.String, int);
     method public void whitelistAppTemporarily(java.lang.String, long, android.os.UserHandle);
+    field public static final int STANDBY_BUCKET_EXEMPTED = 5; // 0x5
+    field public static final int STANDBY_BUCKET_NEVER = 50; // 0x32
   }
 
 }
diff --git a/cmds/statsd/src/StatsService.cpp b/cmds/statsd/src/StatsService.cpp
index 9259793..eb3ea0b 100644
--- a/cmds/statsd/src/StatsService.cpp
+++ b/cmds/statsd/src/StatsService.cpp
@@ -731,6 +731,7 @@
         *success = true;
         return Status::ok();
     } else {
+        *success = false;
         return Status::fromExceptionCode(binder::Status::EX_SECURITY);
     }
 }
@@ -740,6 +741,7 @@
     if (checkCallingPermission(String16(kPermissionDump))) {
         string keyStr = string(String8(key).string());
         mConfigManager->RemoveConfig(ConfigKey(ipc->getCallingUid(), keyStr));
+        *success = true;
         return Status::ok();
     } else {
         *success = false;
diff --git a/cmds/statsd/src/external/StatsCompanionServicePuller.cpp b/cmds/statsd/src/external/StatsCompanionServicePuller.cpp
index 8e96399..e1c02d7 100644
--- a/cmds/statsd/src/external/StatsCompanionServicePuller.cpp
+++ b/cmds/statsd/src/external/StatsCompanionServicePuller.cpp
@@ -45,10 +45,11 @@
     if (statsCompanion != NULL) {
         Status status = statsCompanion->pullData(tagId, &returned_value);
         if (!status.isOk()) {
-            ALOGW("error pulling kernel wakelock");
+            ALOGW("error pulling for %d", tagId);
             return false;
         }
         data->clear();
+        long timestamp = time(nullptr);
         for (const StatsLogEventWrapper& it : returned_value) {
             log_msg tmp;
             tmp.entry_v1.len = it.bytes.size();
@@ -56,9 +57,10 @@
             tmp.entry.hdr_size = kLogMsgHeaderSize;
             // And set the received bytes starting after the 28 bytes reserved for header.
             std::copy(it.bytes.begin(), it.bytes.end(), tmp.buf + kLogMsgHeaderSize);
+            tmp.entry_v1.sec = timestamp;
             data->push_back(make_shared<LogEvent>(tmp));
         }
-        ALOGD("KernelWakelockPuller::pull succeeded!");
+        ALOGD("StatsCompanionServicePuller::pull succeeded for %d", tagId);
         return true;
     } else {
         ALOGW("statsCompanion not found!");
diff --git a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
index 3ffcd77..c4688a2 100644
--- a/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
+++ b/cmds/statsd/src/external/StatsPullerManagerImpl.cpp
@@ -76,7 +76,9 @@
     if (DEBUG) ALOGD("Initiating pulling %d", tagId);
 
     if (mPullers.find(tagId) != mPullers.end()) {
-        return mPullers.find(tagId)->second->Pull(tagId, data);
+        bool ret = mPullers.find(tagId)->second->Pull(tagId, data);
+        ALOGD("pulled %d items", (int)data->size());
+        return ret;
     } else {
         ALOGD("Unknown tagId %d", tagId);
         return false;  // Return early since we don't know what to pull.
diff --git a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
index 2284ff1..50cc8d4 100644
--- a/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
+++ b/cmds/statsd/src/metrics/GaugeMetricProducer.cpp
@@ -99,6 +99,9 @@
 
 GaugeMetricProducer::~GaugeMetricProducer() {
     VLOG("~GaugeMetricProducer() called");
+    if (mPullTagId != -1) {
+        mStatsPullerManager.UnRegisterReceiver(mPullTagId, this);
+    }
 }
 
 void GaugeMetricProducer::startNewProtoOutputStreamLocked(long long startTime) {
diff --git a/cmds/statsd/tools/loadtest/Android.mk b/cmds/statsd/tools/loadtest/Android.mk
new file mode 100644
index 0000000..f3f0a7c
--- /dev/null
+++ b/cmds/statsd/tools/loadtest/Android.mk
@@ -0,0 +1,35 @@
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+
+LOCAL_SRC_FILES += ../../src/stats_log.proto \
+                   ../../src/atoms_copy.proto \
+                   ../../src/statsd_config.proto
+
+LOCAL_PROTOC_FLAGS := --proto_path=$(LOCAL_PATH)/../../src/
+
+LOCAL_PROTOC_OPTIMIZE_TYPE := lite-static
+
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
+
+LOCAL_PACKAGE_NAME := StatsdLoadtest
+LOCAL_CERTIFICATE := platform
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_DEX_PREOPT := false
+include $(BUILD_PACKAGE)
diff --git a/cmds/statsd/tools/loadtest/AndroidManifest.xml b/cmds/statsd/tools/loadtest/AndroidManifest.xml
new file mode 100644
index 0000000..d74c707
--- /dev/null
+++ b/cmds/statsd/tools/loadtest/AndroidManifest.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2007, 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.
+*/
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.statsd.loadtest"
+    android:sharedUserId="android.uid.system"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+  <uses-permission android:name="android.permission.DUMP" />
+  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+  <application
+      android:allowBackup="true"
+      android:icon="@drawable/ic_launcher"
+      android:label="@string/app_name" >
+    <activity
+        android:name=".LoadtestActivity"
+        android:label="@string/app_name"
+        android:launchMode="singleTop" >
+      <intent-filter>
+        <action android:name="android.intent.action.MAIN" />
+        <category android:name="android.intent.category.LAUNCHER" />
+      </intent-filter>
+    </activity>
+    <receiver android:name=".LoadtestActivity$PusherAlarmReceiver" />
+    <receiver android:name=".LoadtestActivity$StopperAlarmReceiver"/>
+  </application>
+</manifest>
diff --git a/cmds/statsd/tools/loadtest/res/drawable-hdpi/ic_launcher.png b/cmds/statsd/tools/loadtest/res/drawable-hdpi/ic_launcher.png
new file mode 100644
index 0000000..55621cc
--- /dev/null
+++ b/cmds/statsd/tools/loadtest/res/drawable-hdpi/ic_launcher.png
Binary files differ
diff --git a/cmds/statsd/tools/loadtest/res/drawable-mdpi/ic_launcher.png b/cmds/statsd/tools/loadtest/res/drawable-mdpi/ic_launcher.png
new file mode 100644
index 0000000..11ec206
--- /dev/null
+++ b/cmds/statsd/tools/loadtest/res/drawable-mdpi/ic_launcher.png
Binary files differ
diff --git a/cmds/statsd/tools/loadtest/res/drawable-xhdpi/ic_launcher.png b/cmds/statsd/tools/loadtest/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..7c02b78
--- /dev/null
+++ b/cmds/statsd/tools/loadtest/res/drawable-xhdpi/ic_launcher.png
Binary files differ
diff --git a/cmds/statsd/tools/loadtest/res/drawable-xxhdpi/ic_launcher.png b/cmds/statsd/tools/loadtest/res/drawable-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..915d914
--- /dev/null
+++ b/cmds/statsd/tools/loadtest/res/drawable-xxhdpi/ic_launcher.png
Binary files differ
diff --git a/cmds/statsd/tools/loadtest/res/layout/activity_loadtest.xml b/cmds/statsd/tools/loadtest/res/layout/activity_loadtest.xml
new file mode 100644
index 0000000..82964ab
--- /dev/null
+++ b/cmds/statsd/tools/loadtest/res/layout/activity_loadtest.xml
@@ -0,0 +1,187 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2007, 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.
+*/
+-->
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" >
+
+    <LinearLayout
+        android:id="@+id/outside"
+        android:clickable="true"
+        android:focusable="true"
+        android:focusableInTouchMode="true"
+        android:gravity="center"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_marginRight="10dp"
+        android:layout_marginLeft="10dp"
+        android:orientation="vertical">
+      <requestFocus />
+
+        <LinearLayout
+            android:gravity="center"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:orientation="horizontal">
+            <TextView
+                android:textSize="30dp"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:text="@string/replication_label" />
+            <EditText
+                android:id="@+id/replication"
+                android:inputType="number"
+                android:layout_weight="1"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:maxLength="3"
+                android:text="@integer/replication_default"
+                android:textSize="30dp"/>
+        </LinearLayout>
+
+        <LinearLayout
+            android:gravity="center"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:orientation="horizontal">
+            <TextView
+                android:textSize="30dp"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:text="@string/bucket_label" />
+            <EditText
+                android:id="@+id/bucket"
+                android:inputType="number"
+                android:layout_weight="1"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:maxLength="3"
+                android:text="@integer/bucket_default"
+                android:textSize="30dp"/>
+        </LinearLayout>
+
+        <LinearLayout
+            android:gravity="center"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:orientation="horizontal">
+            <TextView
+                android:textSize="30dp"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:text="@string/period_label" />
+            <EditText
+                android:id="@+id/period"
+                android:inputType="number"
+                android:layout_weight="1"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:maxLength="3"
+                android:text="@integer/period_default"
+                android:textSize="30dp"/>
+        </LinearLayout>
+
+        <LinearLayout
+            android:gravity="center"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:orientation="horizontal">
+            <TextView
+                android:textSize="30dp"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:text="@string/burst_label" />
+            <EditText
+                android:id="@+id/burst"
+                android:inputType="number"
+                android:layout_weight="1"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:maxLength="2"
+                android:text="@integer/burst_default"
+                android:textSize="30dp"/>
+        </LinearLayout>
+
+        <LinearLayout
+            android:gravity="center"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:orientation="horizontal">
+            <TextView
+                android:textSize="30dp"
+                android:layout_height="wrap_content"
+                android:layout_width="wrap_content"
+                android:text="@string/duration_label" />
+            <EditText
+                android:id="@+id/duration"
+                android:inputType="number"
+                android:layout_weight="1"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:maxLength="4"
+                android:text="@integer/duration_default"
+                android:textSize="30dp"/>
+        </LinearLayout>
+	<CheckBox
+            android:id="@+id/placebo"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/placebo"
+            android:checked="false" />
+
+        <Space
+            android:layout_width="1dp"
+            android:layout_height="30dp"/>
+
+        <Button
+            android:id="@+id/start_stop"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:background="#ffff0000"
+            android:text="@string/start"
+            android:textSize="50dp"/>
+
+        <Space
+            android:layout_width="1dp"
+            android:layout_height="30dp"/>
+
+        <Button
+            android:id="@+id/display_output"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/display_output"
+            android:textSize="30dp"/>
+        <Button
+            android:id="@+id/display_perf"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/display_perf"
+            android:textSize="30dp"/>
+
+        <Space
+            android:layout_width="1dp"
+            android:layout_height="30dp"/>
+
+        <TextView
+            android:id="@+id/report_text"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+
+    </LinearLayout>
+
+</ScrollView>
diff --git a/cmds/statsd/tools/loadtest/res/raw/loadtest_config b/cmds/statsd/tools/loadtest/res/raw/loadtest_config
new file mode 100755
index 0000000..7822367
--- /dev/null
+++ b/cmds/statsd/tools/loadtest/res/raw/loadtest_config
Binary files differ
diff --git a/cmds/statsd/tools/loadtest/res/values/integers.xml b/cmds/statsd/tools/loadtest/res/values/integers.xml
new file mode 100644
index 0000000..76b5692
--- /dev/null
+++ b/cmds/statsd/tools/loadtest/res/values/integers.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+    <integer name="bucket_default">10</integer>
+    <integer name="burst_default">1</integer>
+    <integer name="period_default">2</integer>
+    <integer name="replication_default">1</integer>
+    <integer name="duration_default">240</integer>
+</resources>
diff --git a/cmds/statsd/tools/loadtest/res/values/strings.xml b/cmds/statsd/tools/loadtest/res/values/strings.xml
new file mode 100644
index 0000000..9913503
--- /dev/null
+++ b/cmds/statsd/tools/loadtest/res/values/strings.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+    <string name="app_name">Statsd Loadtest</string>
+    <string name="bucket_label">bucket size (mins):&#160;</string>
+    <string name="burst_label">burst:&#160;</string>
+    <string name="display_output">Show metrics data</string>
+    <string name="display_perf">Show perf data</string>
+    <string name="placebo">placebo</string>
+    <string name="period_label">logging period (secs):&#160;</string>
+    <string name="replication_label">metric replication:&#160;</string>
+    <string name="duration_label">test duration (mins):&#160;</string>
+    <string name="start"> &#160;Start&#160; </string>
+    <string name="stop"> &#160;Stop&#160; </string>
+
+</resources>
diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/BatteryStatsParser.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/BatteryStatsParser.java
new file mode 100644
index 0000000..96e6bef
--- /dev/null
+++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/BatteryStatsParser.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.statsd.loadtest;
+
+import android.annotation.Nullable;
+import android.util.Log;
+import java.text.ParseException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class BatteryStatsParser {
+
+    private static final Pattern LINE_PATTERN =
+        Pattern.compile("\\s*\\+*(\\S*)\\s\\(\\d+\\)\\s(\\d\\d\\d)\\s.*");
+    private static final Pattern TIME_PATTERN =
+        Pattern.compile("(\\d+)?(h)?(\\d+)?(m)?(\\d+)?(s)?(\\d+)?(ms)?");
+    private static final String TAG = "BatteryStatsParser";
+
+    private boolean mHistoryStarted;
+    private boolean mHistoryEnded;
+
+    public BatteryStatsParser() {
+    }
+
+    @Nullable
+    public String parseLine(String line) {
+        if (mHistoryEnded) {
+            return null;
+        }
+        if (!mHistoryStarted) {
+            if (line.contains("Battery History")) {
+                mHistoryStarted = true;
+            }
+            return null;
+        }
+        if (line.isEmpty()) {
+            mHistoryEnded = true;
+            return null;
+        }
+        Matcher lineMatcher = LINE_PATTERN.matcher(line);
+        if (lineMatcher.find() && lineMatcher.group(1) != null && lineMatcher.group(2) != null) {
+            if (lineMatcher.group(1).equals("0")) {
+                return "0," + lineMatcher.group(2) + "\n";
+            } else {
+                Matcher timeMatcher = TIME_PATTERN.matcher(lineMatcher.group(1));
+                if (timeMatcher.find()) {
+                    Long time = getTime(lineMatcher.group(1));
+                    if (time != null) {
+                        return time + "," + lineMatcher.group(2) + "\n";
+                      } else {
+                        return null; // bad time
+                    }
+                } else {
+                  return null;  // bad or no time
+                }
+            }
+        }
+        return null;
+    }
+
+    @Nullable
+    private Long getTime(String group) {
+        if ("0".equals(group)) {
+            return 0L;
+        }
+        Matcher timeMatcher = TIME_PATTERN.matcher(group);
+        if (!timeMatcher.find()) {
+            return null;
+        }
+
+        // Get rid of "ms".
+        String[] matches = group.split("ms", -1);
+        if (matches.length > 1) {
+            group = matches[0];
+        }
+
+        long time = 0L;
+        matches = group.split("h");
+        if (matches.length > 1) {
+            time += Long.parseLong(matches[0]) * 60 * 60 * 1000;  // hours
+            group = matches[1];
+        }
+        matches = group.split("m");
+        if (matches.length > 1) {
+            time += Long.parseLong(matches[0]) * 60 * 1000;  // minutes
+            group = matches[1];
+        }
+        matches = group.split("s");
+        if (matches.length > 1) {
+            time += Long.parseLong(matches[0]) * 1000; // seconds
+            group = matches[1];
+        }
+
+        if (!group.isEmpty()) {
+            time += Long.parseLong(group); // milliseconds
+        }
+        return time;
+    }
+}
diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ConfigFactory.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ConfigFactory.java
new file mode 100644
index 0000000..7ecc124
--- /dev/null
+++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ConfigFactory.java
@@ -0,0 +1,301 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.statsd.loadtest;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.util.Log;
+import android.util.StatsLog;
+
+import com.android.internal.os.StatsdConfigProto.Bucket;
+import com.android.internal.os.StatsdConfigProto.Condition;
+import com.android.internal.os.StatsdConfigProto.CountMetric;
+import com.android.internal.os.StatsdConfigProto.DurationMetric;
+import com.android.internal.os.StatsdConfigProto.EventConditionLink;
+import com.android.internal.os.StatsdConfigProto.EventMetric;
+import com.android.internal.os.StatsdConfigProto.GaugeMetric;
+import com.android.internal.os.StatsdConfigProto.ValueMetric;
+import com.android.internal.os.StatsdConfigProto.KeyMatcher;
+import com.android.internal.os.StatsdConfigProto.KeyValueMatcher;
+import com.android.internal.os.StatsdConfigProto.LogEntryMatcher;
+import com.android.internal.os.StatsdConfigProto.SimpleCondition;
+import com.android.internal.os.StatsdConfigProto.SimpleLogEntryMatcher;
+import com.android.internal.os.StatsdConfigProto.StatsdConfig;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Creates StatsdConfig protos for loadtesting.
+ */
+public class ConfigFactory {
+    public static final String CONFIG_NAME = "LOADTEST";
+
+    private static final String TAG = "ConfigFactory";
+
+    private final StatsdConfig mTemplate;
+
+    public ConfigFactory(Context context) {
+        // Read the config template from the resoures.
+        Resources res = context.getResources();
+        byte[] template = null;
+        StatsdConfig templateProto = null;
+        try {
+            InputStream inputStream = res.openRawResource(R.raw.loadtest_config);
+            template = new byte[inputStream.available()];
+            inputStream.read(template);
+            templateProto = StatsdConfig.parseFrom(template);
+        } catch (IOException e) {
+            Log.e(TAG, "Unable to read or parse loadtest config template. Using an empty config.");
+        }
+        mTemplate = templateProto == null ? StatsdConfig.newBuilder().build() : templateProto;
+
+        Log.d(TAG, "Loadtest template config: " + mTemplate);
+    }
+
+    /**
+     * Generates a config.
+     *
+     * All configs are based on the same template.
+     * That template is designed to make the most use of the set of atoms that {@code SequencePusher}
+     * pushes, and to exercise as many of the metrics features as possible.
+     * Furthermore, by passing a replication factor to this method, one can artificially inflate
+     * the number of metrics in the config. One can also adjust the bucket size for aggregate
+     * metrics.
+     *
+     * @param replication The number of times each metric is replicated in the config.
+     *        If the config template has n metrics, the generated config will have n * replication
+     *        ones
+     * @param bucketMillis The bucket size, in milliseconds, for aggregate metrics
+     * @param placebo If true, only return an empty config
+     * @return The serialized config
+     */
+  public byte[] getConfig(int replication, long bucketMillis, boolean placebo) {
+        StatsdConfig.Builder config = StatsdConfig.newBuilder()
+            .setName(CONFIG_NAME);
+        if (placebo) {
+          replication = 0;  // Config will be empty, aside from a name.
+        }
+        int numMetrics = 0;
+        for (int i = 0; i < replication; i++) {
+            // metrics
+            for (EventMetric metric : mTemplate.getEventMetricList()) {
+                addEventMetric(metric, i, config);
+                numMetrics++;
+            }
+            for (CountMetric metric : mTemplate.getCountMetricList()) {
+                addCountMetric(metric, i, bucketMillis, config);
+                numMetrics++;
+            }
+            for (DurationMetric metric : mTemplate.getDurationMetricList()) {
+                addDurationMetric(metric, i, bucketMillis, config);
+                numMetrics++;
+            }
+            for (GaugeMetric metric : mTemplate.getGaugeMetricList()) {
+                addGaugeMetric(metric, i, bucketMillis, config);
+                numMetrics++;
+            }
+            for (ValueMetric metric : mTemplate.getValueMetricList()) {
+                addValueMetric(metric, i, bucketMillis, config);
+                numMetrics++;
+            }
+            // conditions
+            for (Condition condition : mTemplate.getConditionList()) {
+              addCondition(condition, i, config);
+            }
+            // matchers
+            for (LogEntryMatcher matcher : mTemplate.getLogEntryMatcherList()) {
+              addMatcher(matcher, i, config);
+            }
+        }
+
+        Log.d(TAG, "Loadtest config is : " + config.build());
+        Log.d(TAG, "Generated config has " + numMetrics + " metrics");
+
+        return config.build().toByteArray();
+    }
+
+    /**
+     * Creates {@link EventConditionLink}s that are identical to the one passed to this method,
+     * except that the names are appended with the provided suffix.
+     */
+    private List<EventConditionLink> getLinks(
+        List<EventConditionLink> links, int suffix) {
+        List<EventConditionLink> newLinks = new ArrayList();
+        for (EventConditionLink link : links) {
+            newLinks.add(link.toBuilder()
+                .setCondition(link.getCondition() + suffix)
+                .build());
+        }
+        return newLinks;
+    }
+
+    /**
+     * Creates an {@link EventMetric} based on the template. Makes sure that all names are appended
+     * with the provided suffix. Then adds that metric to the config.
+     */
+    private void addEventMetric(EventMetric template, int suffix, StatsdConfig.Builder config) {
+        EventMetric.Builder metric = template.toBuilder()
+            .setName(template.getName() + suffix)
+            .setWhat(template.getWhat() + suffix);
+        if (template.hasCondition()) {
+            metric.setCondition(template.getCondition() + suffix);
+        }
+        if (template.getLinksCount() > 0) {
+            List<EventConditionLink> links = getLinks(template.getLinksList(), suffix);
+            metric.clearLinks();
+            metric.addAllLinks(links);
+        }
+        config.addEventMetric(metric);
+    }
+
+    private Bucket getBucket(long bucketMillis) {
+        return Bucket.newBuilder()
+            .setBucketSizeMillis(bucketMillis)
+            .build();
+    }
+
+    /**
+     * Creates a {@link CountMetric} based on the template. Makes sure that all names are appended
+     * with the provided suffix, and overrides the bucket size. Then adds that metric to the config.
+     */
+    private void addCountMetric(CountMetric template, int suffix, long bucketMillis,
+        StatsdConfig.Builder config) {
+        CountMetric.Builder metric = template.toBuilder()
+            .setName(template.getName() + suffix)
+            .setWhat(template.getWhat() + suffix);
+        if (template.hasCondition()) {
+            metric.setCondition(template.getCondition() + suffix);
+        }
+        if (template.getLinksCount() > 0) {
+            List<EventConditionLink> links = getLinks(template.getLinksList(), suffix);
+            metric.clearLinks();
+            metric.addAllLinks(links);
+        }
+        metric.setBucket(getBucket(bucketMillis));
+        config.addCountMetric(metric);
+    }
+
+    /**
+     * Creates a {@link DurationMetric} based on the template. Makes sure that all names are appended
+     * with the provided suffix, and overrides the bucket size. Then adds that metric to the config.
+     */
+    private void addDurationMetric(DurationMetric template, int suffix, long bucketMillis,
+        StatsdConfig.Builder config) {
+        DurationMetric.Builder metric = template.toBuilder()
+            .setName(template.getName() + suffix)
+            .setWhat(template.getWhat() + suffix);
+        if (template.hasCondition()) {
+            metric.setCondition(template.getCondition() + suffix);
+        }
+        if (template.getLinksCount() > 0) {
+            List<EventConditionLink> links = getLinks(template.getLinksList(), suffix);
+            metric.clearLinks();
+            metric.addAllLinks(links);
+        }
+        metric.setBucket(getBucket(bucketMillis));
+        config.addDurationMetric(metric);
+    }
+
+    /**
+     * Creates a {@link GaugeMetric} based on the template. Makes sure that all names are appended
+     * with the provided suffix, and overrides the bucket size. Then adds that metric to the config.
+     */
+    private void addGaugeMetric(GaugeMetric template, int suffix, long bucketMillis,
+        StatsdConfig.Builder config) {
+        GaugeMetric.Builder metric = template.toBuilder()
+            .setName(template.getName() + suffix)
+            .setWhat(template.getWhat() + suffix);
+        if (template.hasCondition()) {
+            metric.setCondition(template.getCondition() + suffix);
+        }
+        if (template.getLinksCount() > 0) {
+            List<EventConditionLink> links = getLinks(template.getLinksList(), suffix);
+            metric.clearLinks();
+            metric.addAllLinks(links);
+        }
+        metric.setBucket(getBucket(bucketMillis));
+        config.addGaugeMetric(metric);
+    }
+
+    /**
+     * Creates a {@link ValueMetric} based on the template. Makes sure that all names are appended
+     * with the provided suffix, and overrides the bucket size. Then adds that metric to the config.
+     */
+    private void addValueMetric(ValueMetric template, int suffix, long bucketMillis,
+        StatsdConfig.Builder config) {
+        ValueMetric.Builder metric = template.toBuilder()
+            .setName(template.getName() + suffix)
+            .setWhat(template.getWhat() + suffix);
+        if (template.hasCondition()) {
+            metric.setCondition(template.getCondition() + suffix);
+        }
+        if (template.getLinksCount() > 0) {
+            List<EventConditionLink> links = getLinks(template.getLinksList(), suffix);
+            metric.clearLinks();
+            metric.addAllLinks(links);
+        }
+        metric.setBucket(getBucket(bucketMillis));
+        config.addValueMetric(metric);
+    }
+
+    /**
+     * Creates a {@link Condition} based on the template. Makes sure that all names
+     * are appended with the provided suffix. Then adds that condition to the config.
+     */
+    private void addCondition(Condition template, int suffix, StatsdConfig.Builder config) {
+        Condition.Builder condition = template.toBuilder()
+            .setName(template.getName() + suffix);
+        if (template.hasCombination()) {
+            Condition.Combination.Builder cb = template.getCombination().toBuilder()
+                .clearCondition();
+            for (String child : template.getCombination().getConditionList()) {
+                cb.addCondition(child + suffix);
+            }
+            condition.setCombination(cb.build());
+        }
+        if (template.hasSimpleCondition()) {
+            SimpleCondition.Builder sc = template.getSimpleCondition().toBuilder()
+                .setStart(template.getSimpleCondition().getStart() + suffix)
+                .setStop(template.getSimpleCondition().getStop() + suffix);
+            if (template.getSimpleCondition().hasStopAll()) {
+                sc.setStopAll(template.getSimpleCondition().getStopAll() + suffix);
+            }
+            condition.setSimpleCondition(sc.build());
+        }
+        config.addCondition(condition);
+    }
+
+    /**
+     * Creates a {@link LogEntryMatcher} based on the template. Makes sure that all names
+     * are appended with the provided suffix. Then adds that matcher to the config.
+     */
+    private void addMatcher(LogEntryMatcher template, int suffix, StatsdConfig.Builder config) {
+        LogEntryMatcher.Builder matcher = template.toBuilder()
+            .setName(template.getName() + suffix);
+        if (template.hasCombination()) {
+            LogEntryMatcher.Combination.Builder cb = template.getCombination().toBuilder()
+                .clearMatcher();
+            for (String child : template.getCombination().getMatcherList()) {
+                cb.addMatcher(child + suffix);
+            }
+            matcher.setCombination(cb);
+        }
+        config.addLogEntryMatcher(matcher);
+    }
+}
diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java
new file mode 100644
index 0000000..5e8f26d
--- /dev/null
+++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/DisplayProtoUtils.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.statsd.loadtest;
+
+import android.text.format.DateFormat;
+
+import com.android.os.StatsLog;
+
+import java.util.List;
+
+public class DisplayProtoUtils {
+    public static void displayLogReport(StringBuilder sb, StatsLog.ConfigMetricsReportList reports) {
+        sb.append("ConfigKey: ");
+        if (reports.hasConfigKey()) {
+            com.android.os.StatsLog.ConfigMetricsReportList.ConfigKey key = reports.getConfigKey();
+            sb.append("\tuid: ").append(key.getUid()).append(" name: ").append(key.getName())
+                    .append("\n");
+        }
+
+        for (StatsLog.ConfigMetricsReport report : reports.getReportsList()) {
+            sb.append("StatsLogReport size: ").append(report.getMetricsCount()).append("\n");
+            for (StatsLog.StatsLogReport log : report.getMetricsList()) {
+                sb.append("\n\n");
+                sb.append("metric id: ").append(log.getMetricName()).append("\n");
+                sb.append("start time:").append(getDateStr(log.getStartReportNanos())).append("\n");
+                sb.append("end time:").append(getDateStr(log.getEndReportNanos())).append("\n");
+
+                switch (log.getDataCase()) {
+                    case DURATION_METRICS:
+                        sb.append("Duration metric data\n");
+                        displayDurationMetricData(sb, log);
+                        break;
+                    case EVENT_METRICS:
+                        sb.append("Event metric data\n");
+                        displayEventMetricData(sb, log);
+                        break;
+                    case COUNT_METRICS:
+                        sb.append("Count metric data\n");
+                        displayCountMetricData(sb, log);
+                        break;
+                    case GAUGE_METRICS:
+                        sb.append("Gauge metric data\n");
+                        displayGaugeMetricData(sb, log);
+                        break;
+                    case VALUE_METRICS:
+                        sb.append("Value metric data\n");
+                        displayValueMetricData(sb, log);
+                        break;
+                    case DATA_NOT_SET:
+                        sb.append("No metric data\n");
+                        break;
+                }
+            }
+        }
+    }
+
+    public static String getDateStr(long nanoSec) {
+        return DateFormat.format("dd/MM hh:mm:ss", nanoSec/1000000).toString();
+    }
+
+    private static void displayDimension(StringBuilder sb, List<StatsLog.KeyValuePair> pairs) {
+        for (com.android.os.StatsLog.KeyValuePair kv : pairs) {
+            sb.append(kv.getKey()).append(":");
+            if (kv.hasValueBool()) {
+                sb.append(kv.getValueBool());
+            } else if (kv.hasValueFloat()) {
+                sb.append(kv.getValueFloat());
+            } else if (kv.hasValueInt()) {
+                sb.append(kv.getValueInt());
+            } else if (kv.hasValueStr()) {
+                sb.append(kv.getValueStr());
+            }
+            sb.append(" ");
+        }
+    }
+
+    public static void displayDurationMetricData(StringBuilder sb, StatsLog.StatsLogReport log) {
+        StatsLog.StatsLogReport.DurationMetricDataWrapper durationMetricDataWrapper
+                = log.getDurationMetrics();
+        sb.append("Dimension size: ").append(durationMetricDataWrapper.getDataCount()).append("\n");
+        for (StatsLog.DurationMetricData duration : durationMetricDataWrapper.getDataList()) {
+            sb.append("dimension: ");
+            displayDimension(sb, duration.getDimensionList());
+            sb.append("\n");
+
+            for (StatsLog.DurationBucketInfo info : duration.getBucketInfoList())  {
+                sb.append("\t[").append(getDateStr(info.getStartBucketNanos())).append("-")
+                        .append(getDateStr(info.getEndBucketNanos())).append("] -> ")
+                        .append(info.getDurationNanos()).append(" ns\n");
+            }
+        }
+    }
+
+    public static void displayEventMetricData(StringBuilder sb, StatsLog.StatsLogReport log) {
+        sb.append("Contains ").append(log.getEventMetrics().getDataCount()).append(" events\n");
+        StatsLog.StatsLogReport.EventMetricDataWrapper eventMetricDataWrapper =
+                log.getEventMetrics();
+        for (StatsLog.EventMetricData event : eventMetricDataWrapper.getDataList()) {
+            sb.append(getDateStr(event.getTimestampNanos())).append(": ");
+            switch (event.getAtom().getPushedCase()) {
+                case SETTING_CHANGED:
+                    sb.append("SETTING_CHANGED\n");
+                    break;
+                case SYNC_STATE_CHANGED:
+                    sb.append("SYNC_STATE_CHANGED\n");
+                    break;
+                case AUDIO_STATE_CHANGED:
+                    sb.append("AUDIO_STATE_CHANGED\n");
+                    break;
+                case CAMERA_STATE_CHANGED:
+                    sb.append("CAMERA_STATE_CHANGED\n");
+                    break;
+                case ISOLATED_UID_CHANGED:
+                    sb.append("ISOLATED_UID_CHANGED\n");
+                    break;
+                case SCREEN_STATE_CHANGED:
+                    sb.append("SCREEN_STATE_CHANGED\n");
+                    break;
+                case SENSOR_STATE_CHANGED:
+                    sb.append("SENSOR_STATE_CHANGED\n");
+                    break;
+                case BATTERY_LEVEL_CHANGED:
+                    sb.append("BATTERY_LEVEL_CHANGED\n");
+                    break;
+                case PLUGGED_STATE_CHANGED:
+                    sb.append("PLUGGED_STATE_CHANGED\n");
+                    break;
+                case WAKEUP_ALARM_OCCURRED:
+                    sb.append("WAKEUP_ALARM_OCCURRED\n");
+                    break;
+                case BLE_SCAN_STATE_CHANGED:
+                    sb.append("BLE_SCAN_STATE_CHANGED\n");
+                    break;
+                case CHARGING_STATE_CHANGED:
+                    sb.append("CHARGING_STATE_CHANGED\n");
+                    break;
+                case GPS_SCAN_STATE_CHANGED:
+                    sb.append("GPS_SCAN_STATE_CHANGED\n");
+                    break;
+                case KERNEL_WAKEUP_REPORTED:
+                    sb.append("KERNEL_WAKEUP_REPORTED\n");
+                    break;
+                case WAKELOCK_STATE_CHANGED:
+                    sb.append("WAKELOCK_STATE_CHANGED\n");
+                    break;
+                case WIFI_LOCK_STATE_CHANGED:
+                    sb.append("WIFI_LOCK_STATE_CHANGED\n");
+                    break;
+                case WIFI_SCAN_STATE_CHANGED:
+                    sb.append("WIFI_SCAN_STATE_CHANGED\n");
+                    break;
+                case BLE_SCAN_RESULT_RECEIVED:
+                    sb.append("BLE_SCAN_RESULT_RECEIVED\n");
+                    break;
+                case DEVICE_ON_STATUS_CHANGED:
+                    sb.append("DEVICE_ON_STATUS_CHANGED\n");
+                    break;
+                case FLASHLIGHT_STATE_CHANGED:
+                    sb.append("FLASHLIGHT_STATE_CHANGED\n");
+                    break;
+                case SCREEN_BRIGHTNESS_CHANGED:
+                    sb.append("SCREEN_BRIGHTNESS_CHANGED\n");
+                    break;
+                case UID_PROCESS_STATE_CHANGED:
+                    sb.append("UID_PROCESS_STATE_CHANGED\n");
+                    break;
+                case UID_WAKELOCK_STATE_CHANGED:
+                    sb.append("UID_WAKELOCK_STATE_CHANGED\n");
+                    break;
+                case DEVICE_TEMPERATURE_REPORTED:
+                    sb.append("DEVICE_TEMPERATURE_REPORTED\n");
+                    break;
+                case SCHEDULED_JOB_STATE_CHANGED:
+                    sb.append("SCHEDULED_JOB_STATE_CHANGED\n");
+                    break;
+                case MEDIA_CODEC_ACTIVITY_CHANGED:
+                    sb.append("MEDIA_CODEC_ACTIVITY_CHANGED\n");
+                    break;
+                case WIFI_SIGNAL_STRENGTH_CHANGED:
+                    sb.append("WIFI_SIGNAL_STRENGTH_CHANGED\n");
+                    break;
+                case PHONE_SIGNAL_STRENGTH_CHANGED:
+                    sb.append("PHONE_SIGNAL_STRENGTH_CHANGED\n");
+                    break;
+                case DEVICE_IDLE_MODE_STATE_CHANGED:
+                    sb.append("DEVICE_IDLE_MODE_STATE_CHANGED\n");
+                    break;
+                case BATTERY_SAVER_MODE_STATE_CHANGED:
+                    sb.append("BATTERY_SAVER_MODE_STATE_CHANGED\n");
+                    break;
+                case PROCESS_LIFE_CYCLE_STATE_CHANGED:
+                    sb.append("PROCESS_LIFE_CYCLE_STATE_CHANGED\n");
+                    break;
+                case ACTIVITY_FOREGROUND_STATE_CHANGED:
+                    sb.append("ACTIVITY_FOREGROUND_STATE_CHANGED\n");
+                    break;
+                case BLE_UNOPTIMIZED_SCAN_STATE_CHANGED:
+                    sb.append("BLE_UNOPTIMIZED_SCAN_STATE_CHANGED\n");
+                    break;
+                case LONG_PARTIAL_WAKELOCK_STATE_CHANGED:
+                    sb.append("LONG_PARTIAL_WAKELOCK_STATE_CHANGED\n");
+                    break;
+                case PUSHED_NOT_SET:
+                    sb.append("PUSHED_NOT_SET\n");
+                    break;
+            }
+        }
+    }
+
+    public static void displayCountMetricData(StringBuilder sb, StatsLog.StatsLogReport log) {
+        StatsLog.StatsLogReport.CountMetricDataWrapper countMetricDataWrapper
+                = log.getCountMetrics();
+        sb.append("Dimension size: ").append(countMetricDataWrapper.getDataCount()).append("\n");
+        for (StatsLog.CountMetricData count : countMetricDataWrapper.getDataList()) {
+            sb.append("dimension: ");
+            displayDimension(sb, count.getDimensionList());
+            sb.append("\n");
+
+            for (StatsLog.CountBucketInfo info : count.getBucketInfoList())  {
+                sb.append("\t[").append(getDateStr(info.getStartBucketNanos())).append("-")
+                        .append(getDateStr(info.getEndBucketNanos())).append("] -> ")
+                        .append(info.getCount()).append("\n");
+            }
+        }
+    }
+
+    public static void displayGaugeMetricData(StringBuilder sb, StatsLog.StatsLogReport log) {
+        sb.append("Display me!");
+    }
+
+    public static void displayValueMetricData(StringBuilder sb, StatsLog.StatsLogReport log) {
+        sb.append("Display me!");
+    }
+}
diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/LoadtestActivity.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/LoadtestActivity.java
new file mode 100644
index 0000000..3ae85a7
--- /dev/null
+++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/LoadtestActivity.java
@@ -0,0 +1,533 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.statsd.loadtest;
+
+import android.app.Activity;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IStatsManager;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.util.StatsLog;
+import android.util.StatsManager;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+import android.view.MotionEvent;
+import android.view.View.OnFocusChangeListener;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.Toast;
+
+/**
+ * Runs a load test for statsd.
+ * How it works:
+ * <ul>
+ *   <li> Sets up and pushes a custom config with metrics that exercise a large swath of code paths.
+ *   <li> Periodically logs certain atoms into logd.
+ *   <li> Impact on battery can be printed to logcat, or a bug report can be filed and analyzed
+ *        in battery Historian.
+ * </ul>
+ * The load depends on how demanding the config is, as well as how frequently atoms are pushsed
+ * to logd. Those are all controlled by 4 adjustable parameters:
+ * <ul>
+ *   <li> The 'replication' parameter artificially multiplies the number of metrics in the config.
+ *   <li> The bucket size controls the time-bucketing the aggregate metrics.
+ *   <li> The period parameter controls how frequently atoms are pushed to logd.
+ *   <li> The 'burst' parameter controls how many atoms are pushed at the same time (per period).
+ * </ul>
+ */
+public class LoadtestActivity extends Activity {
+
+    private static final String TAG = "StatsdLoadtest";
+    private static final String TYPE = "type";
+    private static final String ALARM = "push_alarm";
+    private static final String START = "start";
+    private static final String STOP = "stop";
+
+    public final static class PusherAlarmReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            Intent activityIntent = new Intent(context, LoadtestActivity.class);
+            activityIntent.putExtra(TYPE, ALARM);
+            context.startActivity(activityIntent);
+         }
+    }
+
+    public final static class StopperAlarmReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            Intent activityIntent = new Intent(context, LoadtestActivity.class);
+            activityIntent.putExtra(TYPE, STOP);
+            context.startActivity(activityIntent);
+         }
+    }
+
+    private AlarmManager mAlarmMgr;
+
+    /** Used to periodically log atoms to logd. */
+    private PendingIntent mPushPendingIntent;
+
+    /** Used to end the loadtest. */
+    private PendingIntent mStopPendingIntent;
+
+    private Button mStartStop;
+    private EditText mReplicationText;
+    private EditText mBucketText;
+    private EditText mPeriodText;
+    private EditText mBurstText;
+    private EditText mDurationText;
+    private TextView mReportText;
+    private CheckBox mPlaceboCheckBox;
+
+    /** For measuring perf data. */
+    private PerfData mPerfData;
+
+    /** For communicating with statsd. */
+    private StatsManager mStatsManager;
+
+    private PowerManager mPowerManager;
+    private WakeLock mWakeLock;
+
+    /**
+     * If true, we only measure the effect of the loadtest infrastructure. No atom are pushed and
+     * the configuration is empty.
+     */
+    private boolean mPlacebo;
+
+    /** The burst size. */
+    private int mBurst;
+
+    /** The metrics replication. */
+    private int mReplication;
+
+    /** The period, in seconds, at which batches of atoms are pushed. */
+    private long mPeriodSecs;
+
+    /** The bucket size, in minutes, for aggregate metrics. */
+    private long mBucketMins;
+
+    /** The duration, in minutes, of the loadtest. */
+    private long mDurationMins;
+
+    /** Whether the loadtest has started. */
+    private boolean mStarted = false;
+
+    /** Orchestrates the logging of pushed events into logd. */
+    private SequencePusher mPusher;
+
+    /** Generates statsd configs. */
+    private ConfigFactory mFactory;
+
+    /** For intra-minute periods. */
+    private final Handler mHandler = new Handler();
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        Log.d(TAG, "Starting loadtest");
+
+        setContentView(R.layout.activity_loadtest);
+        mReportText = (TextView) findViewById(R.id.report_text);
+        initBurst();
+        initReplication();
+        initBucket();
+        initPeriod();
+        initDuration();
+        initPlacebo();
+
+        // Hide the keyboard outside edit texts.
+        findViewById(R.id.outside).setOnTouchListener(new View.OnTouchListener() {
+            @Override
+            public boolean onTouch(View v, MotionEvent event) {
+                InputMethodManager imm =
+                    (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+                if (getCurrentFocus() != null) {
+                    imm.hideSoftInputFromWindow(getCurrentFocus().getWindowToken(), 0);
+                }
+                return true;
+            }
+        });
+
+        mStartStop = findViewById(R.id.start_stop);
+        mStartStop.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                if (mStarted) {
+                    stopLoadtest(true);
+                } else {
+                    startLoadtest();
+                }
+            }
+        });
+
+        findViewById(R.id.display_output).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                fetchAndDisplayData();
+            }
+        });
+
+        findViewById(R.id.display_perf).setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                mPerfData.publishData(LoadtestActivity.this, mPlacebo, mReplication, mBucketMins,
+                    mPeriodSecs, mBurst);
+            }
+        });
+
+        mAlarmMgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
+        mStatsManager = (StatsManager) getSystemService("stats");
+        mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
+        mFactory = new ConfigFactory(this);
+        mPerfData = new PerfData();
+        stopLoadtest(false);
+        mReportText.setText("");
+    }
+
+    @Override
+    public void onNewIntent(Intent intent) {
+        String type = intent.getStringExtra(TYPE);
+        if (type == null) {
+            return;
+        }
+        switch (type) {
+            case ALARM:
+              onAlarm(intent);
+              break;
+            case START:
+                startLoadtest();
+                break;
+          case STOP:
+                stopLoadtest(true);
+                break;
+            default:
+                throw new IllegalArgumentException("Unknown type: " + type);
+        }
+    }
+
+    @Override
+    public void onDestroy() {
+        Log.d(TAG, "Destroying");
+        stopLoadtest(false);
+        clearConfigs();
+        super.onDestroy();
+    }
+
+    private void onAlarm(Intent intent) {
+        Log.d(TAG, "ON ALARM");
+
+        // Set the next task.
+        scheduleNext();
+
+        // Do the work.
+        mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "StatsdLoadTest");
+        mWakeLock.acquire();
+        if (mPusher != null) {
+            mPusher.next();
+        }
+        mWakeLock.release();
+        mWakeLock = null;
+    }
+
+    /** Schedules the next cycle of pushing atoms into logd. */
+    private void scheduleNext() {
+        Intent intent = new Intent(this, PusherAlarmReceiver.class);
+        intent.putExtra(TYPE, ALARM);
+        mPushPendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
+        long nextTime =  SystemClock.elapsedRealtime() + mPeriodSecs * 1000;
+        mAlarmMgr.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextTime, mPushPendingIntent);
+    }
+
+    private synchronized void startLoadtest() {
+        if (mStarted) {
+            return;
+        }
+
+        // Clean up the state.
+        stopLoadtest(false);
+
+        // Prepare to push a sequence of atoms to logd.
+        mPusher = new SequencePusher(mBurst, mPlacebo);
+
+        // Create a config and push it to statsd.
+        if (!setConfig(mFactory.getConfig(mReplication, mBucketMins * 60 * 1000, mPlacebo))) {
+            return;
+        }
+
+        // Remember to stop in the future.
+        Intent intent = new Intent(this, StopperAlarmReceiver.class);
+        intent.putExtra(TYPE, STOP);
+        mStopPendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
+        long nextTime =  SystemClock.elapsedRealtime() + mDurationMins * 60 * 1000;
+        mAlarmMgr.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, nextTime, mStopPendingIntent);
+
+        // Log atoms.
+        scheduleNext();
+
+        // Reset battery data.
+        mPerfData.resetData(this);
+
+        mReportText.setText("");
+
+        updateStarted(true);
+    }
+
+    private synchronized void stopLoadtest(boolean publishPerfData) {
+        if (mPushPendingIntent != null) {
+            Log.d(TAG, "Canceling pre-existing push alarm");
+            mAlarmMgr.cancel(mPushPendingIntent);
+            mPushPendingIntent = null;
+        }
+        if (mStopPendingIntent != null) {
+            Log.d(TAG, "Canceling pre-existing stop alarm");
+            mAlarmMgr.cancel(mStopPendingIntent);
+            mStopPendingIntent = null;
+        }
+        if (mWakeLock != null) {
+            mWakeLock.release();
+            mWakeLock = null;
+        }
+        fetchAndDisplayData();
+        clearConfigs();
+        updateStarted(false);
+        if (publishPerfData) {
+            mPerfData.publishData(this, mPlacebo, mReplication, mBucketMins, mPeriodSecs, mBurst);
+        }
+    }
+
+    private synchronized void updateStarted(boolean started) {
+        mStarted = started;
+        mStartStop.setBackgroundColor(started ?
+            Color.parseColor("#FFFF0000") : Color.parseColor("#FF00FF00"));
+        mStartStop.setText(started ? getString(R.string.stop) : getString(R.string.start));
+        updateControlsEnabled();
+    }
+
+    private void updateControlsEnabled() {
+        mBurstText.setEnabled(!mPlacebo && !mStarted);
+        mReplicationText.setEnabled(!mPlacebo && !mStarted);
+        mPeriodText.setEnabled(!mStarted);
+        mBucketText.setEnabled(!mPlacebo && !mStarted);
+        mDurationText.setEnabled(!mStarted);
+        mPlaceboCheckBox.setEnabled(!mStarted);
+    }
+
+    private void fetchAndDisplayData() {
+        if (!statsdRunning()) {
+            return;
+        }
+        if (mStatsManager != null) {
+            byte[] data = mStatsManager.getData(ConfigFactory.CONFIG_NAME);
+            if (data != null) {
+                displayData(data);
+            } else {
+                mReportText.setText("Failed to pull data");
+            }
+        }
+    }
+
+    private void displayData(byte[] data) {
+        com.android.os.StatsLog.ConfigMetricsReportList reports = null;
+        boolean good = false;
+        if (data != null) {
+            try {
+                reports = com.android.os.StatsLog.ConfigMetricsReportList.parseFrom(data);
+                good = true;
+            } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+                // display it in the text view.
+            }
+        }
+        int size = data == null ? 0 : data.length;
+        StringBuilder sb = new StringBuilder();
+        sb.append(good ? "Proto parsing OK!" : "Proto parsing Error!");
+        sb.append(" size:").append(size).append("\n");
+
+        if (good && reports != null) {
+            DisplayProtoUtils.displayLogReport(sb, reports);
+            mReportText.setText(sb.toString());
+        }
+    }
+
+    private boolean statsdRunning() {
+        if (IStatsManager.Stub.asInterface(ServiceManager.getService("stats")) == null) {
+            Log.d(TAG, "Statsd not running");
+            Toast.makeText(LoadtestActivity.this, "Statsd NOT running!", Toast.LENGTH_LONG).show();
+            return false;
+        }
+        return true;
+    }
+
+    private int sanitizeInt(int val, int min, int max) {
+        if (val > max) {
+            val = max;
+        } else if (val < min) {
+            val = min;
+        }
+        return val;
+    }
+
+    private void clearConfigs() {
+        // TODO: Clear all configs instead of specific ones.
+        if (mStatsManager != null) {
+            if (!mStatsManager.removeConfiguration("fake")) {
+                Log.d(TAG, "Removed \"fake\" statsd configs.");
+            } else {
+                Log.d(TAG, "Failed to remove \"fake\" config. Loadtest results cannot be trusted.");
+            }
+            if (mStarted) {
+                if (!mStatsManager.removeConfiguration(ConfigFactory.CONFIG_NAME)) {
+                    Log.d(TAG, "Removed loadtest statsd configs.");
+                } else {
+                    Log.d(TAG, "Failed to remove loadtest configs.");
+                }
+            }
+        }
+    }
+
+    private boolean setConfig(byte[] config) {
+      if (mStatsManager != null) {
+            if (mStatsManager.addConfiguration(ConfigFactory.CONFIG_NAME,
+                config, getPackageName(), LoadtestActivity.this.getClass().getName())) {
+                Log.d(TAG, "Config pushed to statsd");
+                return true;
+            } else {
+                Log.d(TAG, "Failed to push config to statsd");
+            }
+      }
+      return false;
+    }
+
+    private synchronized void setReplication(int replication) {
+        mReplication = replication;
+    }
+
+    private synchronized void setPeriodSecs(long periodSecs) {
+        mPeriodSecs = periodSecs;
+    }
+
+    private synchronized void setBucketMins(long bucketMins) {
+        mBucketMins = bucketMins;
+    }
+
+    private synchronized void setBurst(int burst) {
+        mBurst = burst;
+    }
+
+    private synchronized void setDurationMins(long durationMins) {
+        mDurationMins = durationMins;
+    }
+
+    private synchronized void setPlacebo(boolean placebo) {
+        mPlacebo = placebo;
+        updateControlsEnabled();
+    }
+
+    private void handleFocus(EditText editText) {
+        editText.setOnFocusChangeListener(new OnFocusChangeListener() {
+            @Override
+            public void onFocusChange(View v, boolean hasFocus) {
+                if (!hasFocus && editText.getText().toString().isEmpty()) {
+                    editText.setText("-1", TextView.BufferType.EDITABLE);
+                }
+            }
+        });
+    }
+
+    private void initBurst() {
+        mBurst = getResources().getInteger(R.integer.burst_default);
+        mBurstText = (EditText) findViewById(R.id.burst);
+        mBurstText.addTextChangedListener(new NumericalWatcher(mBurstText, 0, 50) {
+            @Override
+            public void onNewValue(int newValue) {
+                setBurst(newValue);
+            }
+        });
+        handleFocus(mBurstText);
+    }
+
+    private void initReplication() {
+        mReplication = getResources().getInteger(R.integer.replication_default);
+        mReplicationText = (EditText) findViewById(R.id.replication);
+        mReplicationText.addTextChangedListener(new NumericalWatcher(mReplicationText, 1, 100) {
+            @Override
+            public void onNewValue(int newValue) {
+                setReplication(newValue);
+            }
+        });
+        handleFocus(mReplicationText);
+    }
+
+    private void initBucket() {
+        mBucketMins = getResources().getInteger(R.integer.bucket_default);
+        mBucketText = (EditText) findViewById(R.id.bucket);
+        mBucketText.addTextChangedListener(new NumericalWatcher(mBucketText, 1, 24 * 60) {
+            @Override
+            public void onNewValue(int newValue) {
+                setBucketMins(newValue);
+            }
+        });
+        handleFocus(mBucketText);
+    }
+
+    private void initPeriod() {
+        mPeriodSecs = getResources().getInteger(R.integer.period_default);
+        mPeriodText = (EditText) findViewById(R.id.period);
+        mPeriodText.addTextChangedListener(new NumericalWatcher(mPeriodText, 1, 60) {
+            @Override
+            public void onNewValue(int newValue) {
+                setPeriodSecs(newValue);
+            }
+        });
+        handleFocus(mPeriodText);
+    }
+
+    private void initDuration() {
+        mDurationMins = getResources().getInteger(R.integer.duration_default);
+        mDurationText = (EditText) findViewById(R.id.duration);
+        mDurationText.addTextChangedListener(new NumericalWatcher(mDurationText, 1, 24 * 60) {
+            @Override
+            public void onNewValue(int newValue) {
+                setDurationMins(newValue);
+            }
+        });
+        handleFocus(mDurationText);
+    }
+
+    private void initPlacebo() {
+        mPlaceboCheckBox = findViewById(R.id.placebo);
+        mPlacebo = false;
+        mPlaceboCheckBox.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View view) {
+                setPlacebo(((CheckBox) view).isChecked());
+            }
+        });
+    }
+}
diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/NumericalWatcher.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/NumericalWatcher.java
new file mode 100644
index 0000000..57f85b5
--- /dev/null
+++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/NumericalWatcher.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.statsd.loadtest;
+
+import android.app.Activity;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.util.Log;
+import android.util.StatsLog;
+import android.util.StatsManager;
+import android.view.View;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.Toast;
+import android.os.IStatsManager;
+import android.os.ServiceManager;
+import android.view.View.OnFocusChangeListener;
+
+public abstract class NumericalWatcher implements TextWatcher {
+
+  private static final String TAG = "NumericalWatcher";
+
+    private final TextView mTextView;
+    private final int mMin;
+    private final int mMax;
+    private int currentValue = -1;
+
+    public NumericalWatcher(TextView textView, int min, int max) {
+        mTextView = textView;
+        mMin = min;
+        mMax = max;
+    }
+
+    public abstract void onNewValue(int newValue);
+
+    @Override
+    final public void afterTextChanged(Editable editable) {
+        String s = mTextView.getText().toString();
+        if (s.isEmpty()) {
+          return;
+        }
+        int unsanitized = Integer.parseInt(s);
+        int newValue = sanitize(unsanitized);
+
+        Log.d(TAG, "YOYO " + currentValue + " " + newValue + " " + unsanitized);
+
+        if (currentValue != newValue || unsanitized != newValue) {
+            currentValue = newValue;
+            editable.clear();
+            editable.append(newValue + "");
+        }
+        onNewValue(newValue);
+    }
+
+    @Override
+    final public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+
+    @Override
+    final public void onTextChanged(CharSequence s, int start, int before, int count) {}
+
+    private int sanitize(int val) {
+        if (val > mMax) {
+            val = mMax;
+        } else if (val < mMin) {
+            val = mMin;
+        }
+        return val;
+    }
+}
diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfData.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfData.java
new file mode 100644
index 0000000..e3e23f5
--- /dev/null
+++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/PerfData.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.statsd.loadtest;
+
+import android.annotation.Nullable;
+import android.app.Activity;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Environment;
+import android.util.Log;
+import android.os.Debug;
+
+import java.io.BufferedReader;
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/** Prints some information about the device via Dumpsys in order to evaluate health metrics. */
+public class PerfData {
+
+    private static final String TAG = "PerfData";
+    private static final String DUMP_FILENAME = TAG + "_dump.tmp";
+
+    public void resetData(Context context) {
+        runDumpsysStats(context, "batterystats", "--reset");
+    }
+
+    public void publishData(Context context, boolean placebo, int replication, long bucketMins,
+        long periodSecs, int burst) {
+        publishBatteryData(context, placebo, replication, bucketMins, periodSecs, burst);
+    }
+
+    private void publishBatteryData(Context context, boolean placebo, int replication,
+        long bucketMins, long periodSecs, int burst) {
+        // Don't use --checkin.
+        runDumpsysStats(context, "batterystats");
+        writeBatteryData(context, placebo, replication, bucketMins, periodSecs, burst);
+    }
+
+    private void runDumpsysStats(Context context, String cmd, String... args) {
+        boolean success = false;
+        // Call dumpsys Dump statistics to a file.
+        FileOutputStream fo = null;
+        try {
+            fo = context.openFileOutput(DUMP_FILENAME, Context.MODE_PRIVATE);
+            if (!Debug.dumpService(cmd, fo.getFD(), args)) {
+                Log.w(TAG, "Dumpsys failed.");
+            }
+            success = true;
+        } catch (IOException | SecurityException | NullPointerException e) {
+            // SecurityException may occur when trying to dump multi-user info.
+            // NPE can occur during dumpService  (root cause unknown).
+            throw new RuntimeException(e);
+        } finally {
+            closeQuietly(fo);
+        }
+    }
+
+    private String readDumpFile(Context context) {
+        StringBuilder sb = new StringBuilder();
+        FileInputStream fi = null;
+        BufferedReader br = null;
+        try {
+            fi = context.openFileInput(DUMP_FILENAME);
+            br = new BufferedReader(new InputStreamReader(fi));
+            String line = br.readLine();
+            while (line != null) {
+                sb.append(line);
+                sb.append(System.lineSeparator());
+                line = br.readLine();
+            }
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        } finally {
+            closeQuietly(br);
+        }
+        return sb.toString();
+    }
+
+    private static void closeQuietly(@Nullable Closeable c) {
+        if (c != null) {
+            try {
+                c.close();
+            } catch (IOException ignore) {
+            }
+        }
+    }
+
+    public void writeBatteryData(Context context, boolean placebo, int replication, long bucketMins,
+        long periodSecs, int burst) {
+        BatteryStatsParser parser = new BatteryStatsParser();
+        FileInputStream fi = null;
+        BufferedReader br = null;
+        String suffix = new SimpleDateFormat("YYYY_MM_dd_HH_mm_ss").format(new Date());
+        File batteryDataFile = new File(getStorageDir(), "battery_" + suffix + ".csv");
+        Log.d(TAG, "Writing battery data to " + batteryDataFile.getAbsolutePath());
+
+        FileWriter writer = null;
+        try {
+            fi = context.openFileInput(DUMP_FILENAME);
+            writer = new FileWriter(batteryDataFile);
+            writer.append("time,battery_level"
+                + getColumnName(placebo, replication, bucketMins, periodSecs, burst) + "\n");
+            br = new BufferedReader(new InputStreamReader(fi));
+            String line = br.readLine();
+            while (line != null) {
+                String recordLine = parser.parseLine(line);
+                if (recordLine != null) {
+                    writer.append(recordLine);
+                }
+                line = br.readLine();
+            }
+            writer.flush();
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        } finally {
+            closeQuietly(writer);
+            closeQuietly(br);
+        }
+    }
+
+    private File getStorageDir() {
+        File file = new File(Environment.getExternalStoragePublicDirectory(
+            Environment.DIRECTORY_DOCUMENTS), "loadtest");
+        if (!file.mkdirs()) {
+            Log.e(TAG, "Directory not created");
+        }
+        return file;
+    }
+
+    private String getColumnName(boolean placebo, int replication, long bucketMins, long periodSecs,
+        int burst) {
+        if (placebo) {
+            return "_placebo_p=" + periodSecs;
+        }
+        return "_r=" + replication + "_bkt=" + bucketMins + "_p=" + periodSecs + "_bst=" + burst;
+    }
+}
diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/SequencePusher.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/SequencePusher.java
new file mode 100644
index 0000000..d4b2aa4
--- /dev/null
+++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/SequencePusher.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.statsd.loadtest;
+
+import android.util.Log;
+import android.util.StatsLog;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Manages the pushing of atoms into logd for loadtesting.
+ * We rely on small number of pushed atoms, and a config with metrics based on those atoms.
+ * The atoms are:
+ * <ul>
+ *   <li> BatteryLevelChanged   - For EventMetric, CountMetric and GaugeMetric (no dimensions).
+ *   <li> BleScanResultReceived - For CountMetric and ValueMetric, sliced by uid.
+ *   <li> ChargingStateChanged  - For DurationMetric (no dimension).
+ *   <li> GpsScanStateChanged   - For DurationMetric, sliced by uid.
+ *   <li> ScreenStateChanged    - For Conditions with no dimensions.
+ *   <li> AudioStateChanged     - For Conditions with dimensions (uid).
+ * </ul>
+ * The sequence is played over and over at a given frequency.
+ */
+public class SequencePusher {
+    private static final String TAG = "SequencePusher";
+
+    /** Some atoms are pushed in burst of {@code mBurst} events. */
+    private final int mBurst;
+
+    /** If this is true, we don't log anything in logd. */
+    private final boolean mPlacebo;
+
+    /** Current state in the automaton. */
+    private int mCursor = 0;
+
+  public SequencePusher(int burst, boolean placebo) {
+        mBurst = burst;
+        mPlacebo = placebo;
+    }
+
+    /**
+     * Pushes the next atom to logd.
+     * This follows a small automaton which makes the right events and conditions overlap:
+     *   (0)  Push a burst of BatteryLevelChanged atoms.
+     *   (1)  Push a burst of BleScanResultReceived atoms.
+     *   (2)  Push ChargingStateChanged with BATTERY_STATUS_CHARGING once.
+     *   (3)  Push a burst of GpsScanStateChanged atoms with ON, with a different uid each time.
+     *   (4)  Push ChargingStateChanged with BATTERY_STATUS_NOT_CHARGING once.
+     *   (5)  Push a burst GpsScanStateChanged atoms with OFF, with a different uid each time.
+     *   (6)  Push ScreenStateChanged with STATE_ON once.
+     *   (7)  Push a burst of AudioStateChanged with ON, with a different uid each time.
+     *   (8)  Repeat steps (0)-(5).
+     *   (9)  Push ScreenStateChanged with STATE_OFF once.
+     *   (10) Push a burst of AudioStateChanged with OFF, with a different uid each time.
+     * and repeat.
+     */
+    public void next() {
+        Log.d(TAG, "Next step: " + mCursor);
+        if (mPlacebo) {
+            return;
+        }
+        switch (mCursor) {
+            case 0:
+            case 8:
+                for (int i = 0; i < mBurst; i++) {
+                    StatsLog.write(StatsLog.BATTERY_LEVEL_CHANGED, 50 + i /* battery_level */);
+                }
+                break;
+            case 1:
+            case 9:
+                for (int i = 0; i < mBurst; i++) {
+                    StatsLog.write(StatsLog.BLE_SCAN_RESULT_RECEIVED, i /* uid */,
+                        100 /* num_of_results */);
+                }
+                break;
+            case 2:
+            case 10:
+                StatsLog.write(StatsLog.CHARGING_STATE_CHANGED,
+                    StatsLog.CHARGING_STATE_CHANGED__CHARGING_STATE__BATTERY_STATUS_CHARGING
+                    /* charging_state */);
+                break;
+            case 3:
+            case 11:
+                for (int i = 0; i < mBurst; i++) {
+                    StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, i /* uid */,
+                        StatsLog.GPS_SCAN_STATE_CHANGED__STATE__ON /* state */);
+                }
+                break;
+            case 4:
+            case 12:
+                StatsLog.write(StatsLog.CHARGING_STATE_CHANGED,
+                    StatsLog.CHARGING_STATE_CHANGED__CHARGING_STATE__BATTERY_STATUS_NOT_CHARGING
+                    /* charging_state */);
+                break;
+            case 5:
+            case 13:
+                for (int i = 0; i < mBurst; i++) {
+                    StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, i /* uid */,
+                        StatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF /* state */);
+                }
+                break;
+            case 6:
+                StatsLog.write(StatsLog.SCREEN_STATE_CHANGED,
+                    StatsLog.SCREEN_STATE_CHANGED__DISPLAY_STATE__STATE_ON /* display_state */);
+                break;
+            case 7:
+                for (int i = 0; i < mBurst; i++) {
+                    StatsLog.write(StatsLog.AUDIO_STATE_CHANGED, i /* uid */,
+                        StatsLog.AUDIO_STATE_CHANGED__STATE__ON /* state */);
+                }
+                break;
+            case 14:
+                StatsLog.write(StatsLog.SCREEN_STATE_CHANGED,
+                    StatsLog.SCREEN_STATE_CHANGED__DISPLAY_STATE__STATE_OFF /* display_state */);
+                break;
+            case 15:
+                for (int i = 0; i < mBurst; i++) {
+                    StatsLog.write(StatsLog.AUDIO_STATE_CHANGED, i /* uid */,
+                        StatsLog.AUDIO_STATE_CHANGED__STATE__OFF /* state */);
+                }
+                break;
+            default:
+        }
+        mCursor++;
+        if (mCursor > 15) {
+            mCursor = 0;
+        }
+    }
+
+    /**
+     * Properly finishes in order to be close all conditions and durations.
+     */
+    public void finish() {
+        // Screen goes back to off. This will ensure that conditions get back to false.
+        StatsLog.write(StatsLog.SCREEN_STATE_CHANGED,
+            StatsLog.SCREEN_STATE_CHANGED__DISPLAY_STATE__STATE_OFF /* display_state */);
+        for (int i = 0; i < mBurst; i++) {
+          StatsLog.write(StatsLog.AUDIO_STATE_CHANGED, i /* uid */,
+              StatsLog.AUDIO_STATE_CHANGED__STATE__OFF /* state */);
+        }
+        // Stop charging, to ensure the corresponding durations are closed.
+        StatsLog.write(StatsLog.CHARGING_STATE_CHANGED,
+            StatsLog.CHARGING_STATE_CHANGED__CHARGING_STATE__BATTERY_STATUS_NOT_CHARGING
+            /* charging_state */);
+        // Stop scanning GPS, to ensure the corresponding conditions get back to false.
+        for (int i = 0; i < mBurst; i++) {
+          StatsLog.write(StatsLog.GPS_SCAN_STATE_CHANGED, i /* uid */,
+              StatsLog.GPS_SCAN_STATE_CHANGED__STATE__OFF /* state */);
+        }
+    }
+}
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index f6d9710..de6230c 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -638,8 +638,7 @@
         final String defaultSearchPaths = System.getProperty("java.library.path");
         final boolean treatVendorApkAsUnbundled = !defaultSearchPaths.contains("/vendor/lib");
         if (mApplicationInfo.getCodePath() != null
-                && mApplicationInfo.getCodePath().startsWith("/vendor/")
-                && treatVendorApkAsUnbundled) {
+                && mApplicationInfo.isVendor() && treatVendorApkAsUnbundled) {
             isBundledApp = false;
         }
 
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java
index 8c47598..b186666 100644
--- a/core/java/android/app/SharedPreferencesImpl.java
+++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -50,6 +50,11 @@
 import java.util.Set;
 import java.util.WeakHashMap;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 final class SharedPreferencesImpl implements SharedPreferences {
     private static final String TAG = "SharedPreferencesImpl";
@@ -69,16 +74,12 @@
     private final Object mLock = new Object();
     private final Object mWritingToDiskLock = new Object();
 
-    @GuardedBy("mLock")
-    private Map<String, Object> mMap;
+    private Future<Map<String, Object>> mMap;
 
     @GuardedBy("mLock")
     private int mDiskWritesInFlight = 0;
 
     @GuardedBy("mLock")
-    private boolean mLoaded = false;
-
-    @GuardedBy("mLock")
     private StructTimespec mStatTimestamp;
 
     @GuardedBy("mLock")
@@ -105,27 +106,18 @@
         mFile = file;
         mBackupFile = makeBackupFile(file);
         mMode = mode;
-        mLoaded = false;
         mMap = null;
         startLoadFromDisk();
     }
 
     private void startLoadFromDisk() {
-        synchronized (mLock) {
-            mLoaded = false;
-        }
-        new Thread("SharedPreferencesImpl-load") {
-            public void run() {
-                loadFromDisk();
-            }
-        }.start();
+        FutureTask<Map<String, Object>> futureTask = new FutureTask<>(() -> loadFromDisk());
+        mMap = futureTask;
+        new Thread(futureTask, "SharedPreferencesImpl-load").start();
     }
 
-    private void loadFromDisk() {
+    private Map<String, Object> loadFromDisk() {
         synchronized (mLock) {
-            if (mLoaded) {
-                return;
-            }
             if (mBackupFile.exists()) {
                 mFile.delete();
                 mBackupFile.renameTo(mFile);
@@ -158,16 +150,14 @@
         }
 
         synchronized (mLock) {
-            mLoaded = true;
             if (map != null) {
-                mMap = map;
                 mStatTimestamp = stat.st_mtim;
                 mStatSize = stat.st_size;
             } else {
-                mMap = new HashMap<>();
+                map = new HashMap<>();
             }
-            mLock.notifyAll();
         }
+        return map;
     }
 
     static File makeBackupFile(File prefsFile) {
@@ -226,36 +216,37 @@
         }
     }
 
-    private void awaitLoadedLocked() {
-        if (!mLoaded) {
+    private @GuardedBy("mLock") Map<String, Object> getLoaded() {
+        try {
+            return mMap.get();
+        } catch (InterruptedException | ExecutionException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+    private @GuardedBy("mLock") Map<String, Object> getLoadedWithBlockGuard() {
+        if (!mMap.isDone()) {
             // Raise an explicit StrictMode onReadFromDisk for this
             // thread, since the real read will be in a different
             // thread and otherwise ignored by StrictMode.
             BlockGuard.getThreadPolicy().onReadFromDisk();
         }
-        while (!mLoaded) {
-            try {
-                mLock.wait();
-            } catch (InterruptedException unused) {
-            }
-        }
+        return getLoaded();
     }
 
     @Override
     public Map<String, ?> getAll() {
+        Map<String, Object> map = getLoadedWithBlockGuard();
         synchronized (mLock) {
-            awaitLoadedLocked();
-            //noinspection unchecked
-            return new HashMap<String, Object>(mMap);
+            return new HashMap<String, Object>(map);
         }
     }
 
     @Override
     @Nullable
     public String getString(String key, @Nullable String defValue) {
+        Map<String, Object> map = getLoadedWithBlockGuard();
         synchronized (mLock) {
-            awaitLoadedLocked();
-            String v = (String)mMap.get(key);
+            String v = (String) map.get(key);
             return v != null ? v : defValue;
         }
     }
@@ -263,66 +254,65 @@
     @Override
     @Nullable
     public Set<String> getStringSet(String key, @Nullable Set<String> defValues) {
+        Map<String, Object> map = getLoadedWithBlockGuard();
         synchronized (mLock) {
-            awaitLoadedLocked();
-            Set<String> v = (Set<String>) mMap.get(key);
+            @SuppressWarnings("unchecked")
+            Set<String> v = (Set<String>) map.get(key);
             return v != null ? v : defValues;
         }
     }
 
     @Override
     public int getInt(String key, int defValue) {
+        Map<String, Object> map = getLoadedWithBlockGuard();
         synchronized (mLock) {
-            awaitLoadedLocked();
-            Integer v = (Integer)mMap.get(key);
+            Integer v = (Integer) map.get(key);
             return v != null ? v : defValue;
         }
     }
     @Override
     public long getLong(String key, long defValue) {
+        Map<String, Object> map = getLoadedWithBlockGuard();
         synchronized (mLock) {
-            awaitLoadedLocked();
-            Long v = (Long)mMap.get(key);
+            Long v = (Long) map.get(key);
             return v != null ? v : defValue;
         }
     }
     @Override
     public float getFloat(String key, float defValue) {
+        Map<String, Object> map = getLoadedWithBlockGuard();
         synchronized (mLock) {
-            awaitLoadedLocked();
-            Float v = (Float)mMap.get(key);
+            Float v = (Float) map.get(key);
             return v != null ? v : defValue;
         }
     }
     @Override
     public boolean getBoolean(String key, boolean defValue) {
+        Map<String, Object> map = getLoadedWithBlockGuard();
         synchronized (mLock) {
-            awaitLoadedLocked();
-            Boolean v = (Boolean)mMap.get(key);
+            Boolean v = (Boolean) map.get(key);
             return v != null ? v : defValue;
         }
     }
 
     @Override
     public boolean contains(String key) {
+        Map<String, Object> map = getLoadedWithBlockGuard();
         synchronized (mLock) {
-            awaitLoadedLocked();
-            return mMap.containsKey(key);
+            return map.containsKey(key);
         }
     }
 
     @Override
     public Editor edit() {
-        // TODO: remove the need to call awaitLoadedLocked() when
+        // TODO: remove the need to call getLoaded() when
         // requesting an editor.  will require some work on the
         // Editor, but then we should be able to do:
         //
         //      context.getSharedPreferences(..).edit().putString(..).apply()
         //
         // ... all without blocking.
-        synchronized (mLock) {
-            awaitLoadedLocked();
-        }
+        getLoadedWithBlockGuard();
 
         return new EditorImpl();
     }
@@ -476,13 +466,43 @@
                 // a memory commit comes in when we're already
                 // writing to disk.
                 if (mDiskWritesInFlight > 0) {
-                    // We can't modify our mMap as a currently
+                    // We can't modify our map as a currently
                     // in-flight write owns it.  Clone it before
                     // modifying it.
                     // noinspection unchecked
-                    mMap = new HashMap<String, Object>(mMap);
+                    mMap = new Future<Map<String, Object>>() {
+                        private Map<String, Object> mCopiedMap =
+                                new HashMap<String, Object>(getLoaded());
+
+                        @Override
+                        public boolean cancel(boolean mayInterruptIfRunning) {
+                            return false;
+                        }
+
+                        @Override
+                        public boolean isCancelled() {
+                            return false;
+                        }
+
+                        @Override
+                        public boolean isDone() {
+                            return true;
+                        }
+
+                        @Override
+                        public Map<String, Object> get()
+                                throws InterruptedException, ExecutionException {
+                            return mCopiedMap;
+                        }
+
+                        @Override
+                        public Map<String, Object> get(long timeout, TimeUnit unit)
+                                throws InterruptedException, ExecutionException, TimeoutException {
+                            return mCopiedMap;
+                        }
+                    };
                 }
-                mapToWriteToDisk = mMap;
+                mapToWriteToDisk = getLoaded();
                 mDiskWritesInFlight++;
 
                 boolean hasListeners = mListeners.size() > 0;
diff --git a/core/java/android/app/usage/AppStandby.java b/core/java/android/app/usage/AppStandby.java
deleted file mode 100644
index 6f9fc2f..0000000
--- a/core/java/android/app/usage/AppStandby.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.app.usage;
-
-import android.annotation.IntDef;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Set of constants for app standby buckets and reasons. Apps will be moved into different buckets
- * that affect how frequently they can run in the background or perform other battery-consuming
- * actions. Buckets will be assigned based on how frequently or when the system thinks the user
- * is likely to use the app.
- * @hide
- */
-public class AppStandby {
-
-    /** The app was used very recently, currently in use or likely to be used very soon. */
-    public static final int STANDBY_BUCKET_ACTIVE = 0;
-
-    // Leave some gap in case we want to increase the number of buckets
-
-    /** The app was used recently and/or likely to be used in the next few hours  */
-    public static final int STANDBY_BUCKET_WORKING_SET = 3;
-
-    // Leave some gap in case we want to increase the number of buckets
-
-    /** The app was used in the last few days and/or likely to be used in the next few days */
-    public static final int STANDBY_BUCKET_FREQUENT = 6;
-
-    // Leave some gap in case we want to increase the number of buckets
-
-    /** The app has not be used for several days and/or is unlikely to be used for several days */
-    public static final int STANDBY_BUCKET_RARE = 9;
-
-    // Leave some gap in case we want to increase the number of buckets
-
-    /** The app has never been used. */
-    public static final int STANDBY_BUCKET_NEVER = 12;
-
-    /** Reason for bucketing -- default initial state */
-    public static final String REASON_DEFAULT = "default";
-
-    /** Reason for bucketing -- timeout */
-    public static final String REASON_TIMEOUT = "timeout";
-
-    /** Reason for bucketing -- usage */
-    public static final String REASON_USAGE = "usage";
-
-    /** Reason for bucketing -- forced by user / shell command */
-    public static final String REASON_FORCED = "forced";
-
-    /**
-     * Reason for bucketing -- predicted. This is a prefix and the UID of the bucketeer will
-     * be appended.
-     */
-    public static final String REASON_PREDICTED = "predicted";
-
-    @IntDef(flag = false, value = {
-            STANDBY_BUCKET_ACTIVE,
-            STANDBY_BUCKET_WORKING_SET,
-            STANDBY_BUCKET_FREQUENT,
-            STANDBY_BUCKET_RARE,
-            STANDBY_BUCKET_NEVER,
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface StandbyBuckets {}
-}
diff --git a/core/java/android/app/usage/UsageStatsManager.java b/core/java/android/app/usage/UsageStatsManager.java
index 3a3e16e..d614b20 100644
--- a/core/java/android/app/usage/UsageStatsManager.java
+++ b/core/java/android/app/usage/UsageStatsManager.java
@@ -16,16 +16,18 @@
 
 package android.app.usage;
 
+import android.annotation.IntDef;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
-import android.app.usage.AppStandby.StandbyBuckets;
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.ArrayMap;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -90,6 +92,76 @@
      */
     public static final int INTERVAL_COUNT = 4;
 
+
+    /**
+     * The app is whitelisted for some reason and the bucket cannot be changed.
+     * {@hide}
+     */
+    @SystemApi
+    public static final int STANDBY_BUCKET_EXEMPTED = 5;
+
+    /**
+     * The app was used very recently, currently in use or likely to be used very soon.
+     * @see #getAppStandbyBucket()
+     */
+    public static final int STANDBY_BUCKET_ACTIVE = 10;
+
+    /**
+     * The app was used recently and/or likely to be used in the next few hours.
+     * @see #getAppStandbyBucket()
+     */
+    public static final int STANDBY_BUCKET_WORKING_SET = 20;
+
+    /**
+     * The app was used in the last few days and/or likely to be used in the next few days.
+     * @see #getAppStandbyBucket()
+     */
+    public static final int STANDBY_BUCKET_FREQUENT = 30;
+
+    /**
+     * The app has not be used for several days and/or is unlikely to be used for several days.
+     * @see #getAppStandbyBucket()
+     */
+    public static final int STANDBY_BUCKET_RARE = 40;
+
+    /**
+     * The app has never been used.
+     * {@hide}
+     */
+    @SystemApi
+    public static final int STANDBY_BUCKET_NEVER = 50;
+
+    /** {@hide} Reason for bucketing -- default initial state */
+    public static final String REASON_DEFAULT = "default";
+
+    /** {@hide} Reason for bucketing -- timeout */
+    public static final String REASON_TIMEOUT = "timeout";
+
+    /** {@hide} Reason for bucketing -- usage */
+    public static final String REASON_USAGE = "usage";
+
+    /** {@hide} Reason for bucketing -- forced by user / shell command */
+    public static final String REASON_FORCED = "forced";
+
+    /**
+     * {@hide}
+     * Reason for bucketing -- predicted. This is a prefix and the UID of the bucketeer will
+     * be appended.
+     */
+    public static final String REASON_PREDICTED = "predicted";
+
+    /** @hide */
+    @IntDef(flag = false, value = {
+            STANDBY_BUCKET_EXEMPTED,
+            STANDBY_BUCKET_ACTIVE,
+            STANDBY_BUCKET_WORKING_SET,
+            STANDBY_BUCKET_FREQUENT,
+            STANDBY_BUCKET_RARE,
+            STANDBY_BUCKET_NEVER,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface StandbyBuckets {}
+
     private static final UsageEvents sEmptyResults = new UsageEvents();
 
     private final Context mContext;
@@ -237,7 +309,7 @@
     }
 
     /**
-     * @hide
+     * {@hide}
      */
     public void setAppInactive(String packageName, boolean inactive) {
         try {
@@ -248,19 +320,45 @@
     }
 
     /**
-     * @hide
+     * Returns the current standby bucket of the calling app. The system determines the standby
+     * state of the app based on app usage patterns. Standby buckets determine how much an app will
+     * be restricted from running background tasks such as jobs, alarms and certain PendingIntent
+     * callbacks.
+     * Restrictions increase progressively from {@link #STANDBY_BUCKET_ACTIVE} to
+     * {@link #STANDBY_BUCKET_RARE}, with {@link #STANDBY_BUCKET_ACTIVE} being the least
+     * restrictive. The battery level of the device might also affect the restrictions.
+     *
+     * @return the current standby bucket of the calling app.
      */
+    public @StandbyBuckets int getAppStandbyBucket() {
+        try {
+            return mService.getAppStandbyBucket(mContext.getOpPackageName(),
+                    mContext.getOpPackageName(),
+                    mContext.getUserId());
+        } catch (RemoteException e) {
+        }
+        return STANDBY_BUCKET_ACTIVE;
+    }
+
+    /**
+     * {@hide}
+     * Returns the current standby bucket of the specified app. The caller must hold the permission
+     * android.permission.PACKAGE_USAGE_STATS.
+     * @param packageName the package for which to fetch the current standby bucket.
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.PACKAGE_USAGE_STATS)
     public @StandbyBuckets int getAppStandbyBucket(String packageName) {
         try {
             return mService.getAppStandbyBucket(packageName, mContext.getOpPackageName(),
                     mContext.getUserId());
         } catch (RemoteException e) {
         }
-        return AppStandby.STANDBY_BUCKET_ACTIVE;
+        return STANDBY_BUCKET_ACTIVE;
     }
 
     /**
-     * @hide
+     * {@hide}
      * Changes the app standby state to the provided bucket.
      */
     @SystemApi
diff --git a/core/java/android/app/usage/UsageStatsManagerInternal.java b/core/java/android/app/usage/UsageStatsManagerInternal.java
index 9954484f..4b4fe72 100644
--- a/core/java/android/app/usage/UsageStatsManagerInternal.java
+++ b/core/java/android/app/usage/UsageStatsManagerInternal.java
@@ -16,7 +16,7 @@
 
 package android.app.usage;
 
-import android.app.usage.AppStandby.StandbyBuckets;
+import android.app.usage.UsageStatsManager.StandbyBuckets;
 import android.content.ComponentName;
 import android.content.res.Configuration;
 
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index edb27cd..5298f57 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -594,6 +594,13 @@
      */
     public static final int PRIVATE_FLAG_OEM = 1 << 17;
 
+    /**
+     * Value for {@linl #privateFlags}: whether this app is pre-installed on the
+     * vendor partition of the system image.
+     * @hide
+     */
+    public static final int PRIVATE_FLAG_VENDOR = 1 << 18;
+
     /** @hide */
     @IntDef(flag = true, prefix = { "PRIVATE_FLAG_" }, value = {
             PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE,
@@ -613,6 +620,7 @@
             PRIVATE_FLAG_PRIVILEGED,
             PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER,
             PRIVATE_FLAG_STATIC_SHARED_LIBRARY,
+            PRIVATE_FLAG_VENDOR,
             PRIVATE_FLAG_VIRTUAL_PRELOAD,
     })
     @Retention(RetentionPolicy.SOURCE)
@@ -1569,6 +1577,11 @@
         return (flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
     }
 
+    /** @hide */
+    public boolean isVendor() {
+        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
+    }
+
     /**
      * Returns whether or not this application was installed as a virtual preload.
      */
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index ebeaad7..98c824d 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -6267,6 +6267,11 @@
         }
 
         /** @hide */
+        public boolean isVendor() {
+            return applicationInfo.isVendor();
+        }
+
+        /** @hide */
         public boolean isPrivileged() {
             return applicationInfo.isPrivilegedApp();
         }
diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java
index 7588762..551d53b 100644
--- a/core/java/android/content/pm/PermissionInfo.java
+++ b/core/java/android/content/pm/PermissionInfo.java
@@ -144,6 +144,15 @@
     public static final int PROTECTION_FLAG_OEM = 0x4000;
 
     /**
+     * Additional flag for {${link #protectionLevel}, corresponding
+     * to the <code>vendorPrivileged</code> value of
+     * {@link android.R.attr#protectionLevel}.
+     *
+     * @hide
+     */
+    public static final int PROTECTION_FLAG_VENDOR_PRIVILEGED = 0x8000;
+
+    /**
      * Mask for {@link #protectionLevel}: the basic protection type.
      */
     public static final int PROTECTION_MASK_BASE = 0xf;
@@ -231,6 +240,12 @@
         if (level == PROTECTION_SIGNATURE_OR_SYSTEM) {
             level = PROTECTION_SIGNATURE | PROTECTION_FLAG_PRIVILEGED;
         }
+        if ((level & PROTECTION_FLAG_VENDOR_PRIVILEGED) != 0
+                && (level & PROTECTION_FLAG_PRIVILEGED) == 0) {
+            // 'vendorPrivileged' must be 'privileged'. If not,
+            // drop the vendorPrivileged.
+            level = level & ~PROTECTION_FLAG_VENDOR_PRIVILEGED;
+        }
         return level;
     }
 
@@ -284,6 +299,9 @@
         if ((level & PermissionInfo.PROTECTION_FLAG_OEM) != 0) {
             protLevel += "|oem";
         }
+        if ((level & PermissionInfo.PROTECTION_FLAG_VENDOR_PRIVILEGED) != 0) {
+            protLevel += "|vendorPrivileged";
+        }
         return protLevel;
     }
 
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index b5031f2..b7a6719 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -146,6 +146,9 @@
     final ArrayMap<String, ArraySet<String>> mPrivAppPermissions = new ArrayMap<>();
     final ArrayMap<String, ArraySet<String>> mPrivAppDenyPermissions = new ArrayMap<>();
 
+    final ArrayMap<String, ArraySet<String>> mVendorPrivAppPermissions = new ArrayMap<>();
+    final ArrayMap<String, ArraySet<String>> mVendorPrivAppDenyPermissions = new ArrayMap<>();
+
     final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>();
 
     public static SystemConfig getInstance() {
@@ -229,6 +232,14 @@
         return mPrivAppDenyPermissions.get(packageName);
     }
 
+    public ArraySet<String> getVendorPrivAppPermissions(String packageName) {
+        return mVendorPrivAppPermissions.get(packageName);
+    }
+
+    public ArraySet<String> getVendorPrivAppDenyPermissions(String packageName) {
+        return mVendorPrivAppDenyPermissions.get(packageName);
+    }
+
     public Map<String, Boolean> getOemPermissions(String packageName) {
         final Map<String, Boolean> oemPermissions = mOemPermissions.get(packageName);
         if (oemPermissions != null) {
@@ -248,7 +259,7 @@
 
         // Allow Vendor to customize system configs around libs, features, permissions and apps
         int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
-                ALLOW_APP_CONFIGS;
+                ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS;
         readPermissions(Environment.buildPath(
                 Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
         readPermissions(Environment.buildPath(
@@ -587,7 +598,19 @@
                     }
                     XmlUtils.skipCurrentTag(parser);
                 } else if ("privapp-permissions".equals(name) && allowPrivappPermissions) {
-                    readPrivAppPermissions(parser);
+                    // privapp permissions from system and vendor partitions are stored
+                    // separately. This is to prevent xml files in the vendor partition from
+                    // granting permissions to priv apps in the system partition and vice
+                    // versa.
+                    boolean vendor = permFile.toPath().startsWith(
+                            Environment.getVendorDirectory().toPath());
+                    if (vendor) {
+                        readPrivAppPermissions(parser, mVendorPrivAppPermissions,
+                                mVendorPrivAppDenyPermissions);
+                    } else {
+                        readPrivAppPermissions(parser, mPrivAppPermissions,
+                                mPrivAppDenyPermissions);
+                    }
                 } else if ("oem-permissions".equals(name) && allowOemPermissions) {
                     readOemPermissions(parser);
                 } else {
@@ -674,7 +697,10 @@
         }
     }
 
-    void readPrivAppPermissions(XmlPullParser parser) throws IOException, XmlPullParserException {
+    private void readPrivAppPermissions(XmlPullParser parser,
+            ArrayMap<String, ArraySet<String>> grantMap,
+            ArrayMap<String, ArraySet<String>> denyMap)
+            throws IOException, XmlPullParserException {
         String packageName = parser.getAttributeValue(null, "package");
         if (TextUtils.isEmpty(packageName)) {
             Slog.w(TAG, "package is required for <privapp-permissions> in "
@@ -682,11 +708,11 @@
             return;
         }
 
-        ArraySet<String> permissions = mPrivAppPermissions.get(packageName);
+        ArraySet<String> permissions = grantMap.get(packageName);
         if (permissions == null) {
             permissions = new ArraySet<>();
         }
-        ArraySet<String> denyPermissions = mPrivAppDenyPermissions.get(packageName);
+        ArraySet<String> denyPermissions = denyMap.get(packageName);
         int depth = parser.getDepth();
         while (XmlUtils.nextElementWithin(parser, depth)) {
             String name = parser.getName();
@@ -711,9 +737,9 @@
                 denyPermissions.add(permName);
             }
         }
-        mPrivAppPermissions.put(packageName, permissions);
+        grantMap.put(packageName, permissions);
         if (denyPermissions != null) {
-            mPrivAppDenyPermissions.put(packageName, denyPermissions);
+            denyMap.put(packageName, denyPermissions);
         }
     }
 
diff --git a/core/res/Android.bp b/core/res/Android.bp
new file mode 100644
index 0000000..e66f1a2
--- /dev/null
+++ b/core/res/Android.bp
@@ -0,0 +1,41 @@
+//
+// Copyright (C) 2008 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+android_app {
+    name: "framework-res",
+    no_framework_libs: true,
+    certificate: "platform",
+
+    // Soong special-cases framework-res to install this alongside
+    // the libraries at /system/framework/framework-res.apk.
+
+    // Generate private symbols into the com.android.internal.R class
+    // so they are not accessible to 3rd party apps.
+    aaptflags: [
+        "--private-symbols",
+        "com.android.internal",
+
+        // Framework doesn't need versioning since it IS the platform.
+        "--no-auto-version",
+
+        // Allow overlay to add resource
+        "--auto-add-overlay",
+    ],
+
+    // Create package-export.apk, which other packages can use to get
+    // PRODUCT-agnostic resource data like IDs and type definitions.
+    export_package_resources: true,
+}
diff --git a/core/res/Android.mk b/core/res/Android.mk
deleted file mode 100644
index 370a01f..0000000
--- a/core/res/Android.mk
+++ /dev/null
@@ -1,42 +0,0 @@
-#
-# Copyright (C) 2008 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_USE_AAPT2 := true
-LOCAL_NO_STANDARD_LIBRARIES := true
-LOCAL_PACKAGE_NAME := framework-res
-LOCAL_CERTIFICATE := platform
-LOCAL_MODULE_TAGS := optional
-
-# Generate private symbols into the com.android.internal.R class
-# so they are not accessible to 3rd party apps.
-LOCAL_AAPT_FLAGS += --private-symbols com.android.internal
-
-# Framework doesn't need versioning since it IS the platform.
-LOCAL_AAPT_FLAGS += --no-auto-version
-
-# Allow overlay to add resource
-LOCAL_AAPT_FLAGS += --auto-add-overlay
-
-# Install this alongside the libraries.
-LOCAL_MODULE_PATH := $(TARGET_OUT_JAVA_LIBRARIES)
-
-# Create package-export.apk, which other packages can use to get
-# PRODUCT-agnostic resource data like IDs and type definitions.
-LOCAL_EXPORT_PACKAGE_RESOURCES := true
-
-include $(BUILD_PACKAGE)
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 5906b27..d9fb230 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1740,7 +1740,7 @@
          @hide
     -->
     <permission android:name="android.permission.BIND_IMS_SERVICE"
-        android:protectionLevel="signature|privileged" />
+        android:protectionLevel="signature|privileged|vendorPrivileged" />
 
     <!-- Allows an application to manage embedded subscriptions (those on a eUICC) through
          EuiccManager APIs.
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 4d410e5..4d67494 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -262,6 +262,9 @@
              and the OEM has white-listed the app to receive this permission by the OEM.
          -->
         <flag name="oem" value="0x4000" />
+        <!-- Additional flag from base permission type: this permission can be granted to
+             privileged apps in vendor partition. -->
+        <flag name="vendorPrivileged" value="0x8000" />
     </attr>
 
     <!-- Flags indicating more context for a permission group. -->
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 23d9cae..e04bd0e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -112,6 +112,7 @@
     private int mNotificationMaxHeight;
     private int mNotificationAmbientHeight;
     private int mIncreasedPaddingBetweenElements;
+    private boolean mMustStayOnScreen;
 
     /** Does this row contain layouts that can adapt to row expansion */
     private boolean mExpandable;
@@ -491,6 +492,7 @@
             notifyHeightChanged(false  /* needsAnimation */);
         }
         if (isHeadsUp) {
+            mMustStayOnScreen = true;
             setAboveShelf(true);
         } else if (isAboveShelf() != wasAboveShelf) {
             mAboveShelfChangedListener.onAboveShelfStateChanged(!wasAboveShelf);
@@ -517,6 +519,12 @@
         addChildNotification(row, -1);
     }
 
+    @Override
+    public void setHeadsUpIsVisible() {
+        super.setHeadsUpIsVisible();
+        mMustStayOnScreen = false;
+    }
+
     /**
      * Add a child notification to this view.
      *
@@ -1942,7 +1950,7 @@
 
     @Override
     public boolean mustStayOnScreen() {
-        return mIsHeadsUp;
+        return mIsHeadsUp && mMustStayOnScreen;
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 18b9860..f762513 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -478,6 +478,9 @@
         return false;
     }
 
+    public void setHeadsUpIsVisible() {
+    }
+
     public boolean isChildInGroup() {
         return false;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ExpandableViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ExpandableViewState.java
index e0fd481..0650e23 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/ExpandableViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ExpandableViewState.java
@@ -95,6 +95,12 @@
     public boolean inShelf;
 
     /**
+     * A state indicating whether a headsup is currently fully visible, even when not scrolled.
+     * Only valid if the view is heads upped.
+     */
+    public boolean headsUpIsVisible;
+
+    /**
      * How much the child overlaps with the previous child on top. This is used to
      * show the background properly when the child on top is translating away.
      */
@@ -126,6 +132,7 @@
             clipTopAmount = svs.clipTopAmount;
             notGoneIndex = svs.notGoneIndex;
             location = svs.location;
+            headsUpIsVisible = svs.headsUpIsVisible;
         }
     }
 
@@ -175,6 +182,10 @@
 
             expandableView.setTransformingInShelf(false);
             expandableView.setInShelf(inShelf);
+
+            if (headsUpIsVisible) {
+                expandableView.setHeadsUpIsVisible();
+            }
         }
     }
 
@@ -229,6 +240,10 @@
             expandableView.setTransformingInShelf(true);
         }
         expandableView.setInShelf(this.inShelf);
+
+        if (headsUpIsVisible) {
+            expandableView.setHeadsUpIsVisible();
+        }
     }
 
     private void startHeightAnimation(final ExpandableView child, AnimationProperties properties) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index ebebfac..a3d2423 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -624,7 +624,7 @@
         if (childViewState == null) {
             return false;
         }
-        if ((childViewState.location &= ExpandableViewState.VISIBLE_LOCATIONS) == 0) {
+        if ((childViewState.location & ExpandableViewState.VISIBLE_LOCATIONS) == 0) {
             return false;
         }
         if (row.getVisibility() != View.VISIBLE) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index c060b08..195607d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -135,7 +135,7 @@
         for (int i = 0; i < childCount; i++) {
             ExpandableView child = algorithmState.visibleChildren.get(i);
             ExpandableViewState state = resultState.getViewStateForView(child);
-            if (!child.mustStayOnScreen()) {
+            if (!child.mustStayOnScreen() || state.headsUpIsVisible) {
                 previousNotificationEnd = Math.max(drawStart, previousNotificationEnd);
                 previousNotificationStart = Math.max(drawStart, previousNotificationStart);
             }
@@ -378,6 +378,13 @@
         boolean isEmptyShadeView = child instanceof EmptyShadeView;
 
         childViewState.location = ExpandableViewState.LOCATION_MAIN_AREA;
+        float inset = ambientState.getTopPadding() + ambientState.getStackTranslation();
+        if (child.mustStayOnScreen() && childViewState.yTranslation >= 0) {
+            // Even if we're not scrolled away we're in view and we're also not in the
+            // shelf. We can relax the constraints and let us scroll off the top!
+            float end = childViewState.yTranslation + childViewState.height + inset;
+            childViewState.headsUpIsVisible = end < ambientState.getMaxHeadsUpTranslation();
+        }
         if (isDismissView) {
             childViewState.yTranslation = Math.min(childViewState.yTranslation,
                     ambientState.getInnerHeight() - childHeight);
@@ -396,8 +403,7 @@
             Log.wtf(LOG_TAG, "Failed to assign location for child " + i);
         }
 
-        childViewState.yTranslation += ambientState.getTopPadding()
-                + ambientState.getStackTranslation();
+        childViewState.yTranslation += inset;
         return currentYPosition;
     }
 
@@ -420,19 +426,21 @@
                 break;
             }
             ExpandableViewState childState = resultState.getViewStateForView(row);
-            if (topHeadsUpEntry == null) {
+            if (topHeadsUpEntry == null && row.mustStayOnScreen() && !childState.headsUpIsVisible) {
                 topHeadsUpEntry = row;
                 childState.location = ExpandableViewState.LOCATION_FIRST_HUN;
             }
             boolean isTopEntry = topHeadsUpEntry == row;
             float unmodifiedEndLocation = childState.yTranslation + childState.height;
             if (mIsExpanded) {
-                // Ensure that the heads up is always visible even when scrolled off
-                clampHunToTop(ambientState, row, childState);
-                if (i == 0 && ambientState.isAboveShelf(row)) {
-                    // the first hun can't get off screen.
-                    clampHunToMaxTranslation(ambientState, row, childState);
-                    childState.hidden = false;
+                if (row.mustStayOnScreen() && !childState.headsUpIsVisible) {
+                    // Ensure that the heads up is always visible even when scrolled off
+                    clampHunToTop(ambientState, row, childState);
+                    if (i == 0 && ambientState.isAboveShelf(row)) {
+                        // the first hun can't get off screen.
+                        clampHunToMaxTranslation(ambientState, row, childState);
+                        childState.hidden = false;
+                    }
                 }
             }
             if (row.isPinned()) {
@@ -493,6 +501,7 @@
         if (childViewState.yTranslation >= shelfStart) {
             childViewState.hidden = true;
             childViewState.inShelf = true;
+            childViewState.headsUpIsVisible = false;
         }
         if (!ambientState.isShadeExpanded()) {
             childViewState.height = (int) (mStatusBarHeight - childViewState.yTranslation);
@@ -531,7 +540,8 @@
         ExpandableViewState childViewState = resultState.getViewStateForView(child);
         int zDistanceBetweenElements = ambientState.getZDistanceBetweenElements();
         float baseZ = ambientState.getBaseZHeight();
-        if (child.mustStayOnScreen() && !ambientState.isDozingAndNotPulsing(child)
+        if (child.mustStayOnScreen() && !childViewState.headsUpIsVisible
+                && !ambientState.isDozingAndNotPulsing(child)
                 && childViewState.yTranslation < ambientState.getTopPadding()
                 + ambientState.getStackTranslation()) {
             if (childrenOnTop != 0.0f) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
index e3c746b..588b758 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -84,6 +84,7 @@
         viewState.scaleX = view.getScaleX();
         viewState.scaleY = view.getScaleY();
         viewState.inShelf = false;
+        viewState.headsUpIsVisible = false;
     }
 
     public ExpandableViewState getViewStateForView(View requestedView) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index 7eb922c..979323f 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -224,6 +224,8 @@
                     return runGetInactive(pw);
                 case "set-standby-bucket":
                     return runSetStandbyBucket(pw);
+                case "get-standby-bucket":
+                    return runGetStandbyBucket(pw);
                 case "send-trim-memory":
                     return runSendTrimMemory(pw);
                 case "display":
@@ -1826,6 +1828,29 @@
         return 0;
     }
 
+    private int bucketNameToBucketValue(String name) {
+        String lower = name.toLowerCase();
+        if (lower.startsWith("ac")) {
+            return UsageStatsManager.STANDBY_BUCKET_ACTIVE;
+        } else if (lower.startsWith("wo")) {
+            return UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
+        } else if (lower.startsWith("fr")) {
+            return UsageStatsManager.STANDBY_BUCKET_FREQUENT;
+        } else if (lower.startsWith("ra")) {
+            return UsageStatsManager.STANDBY_BUCKET_RARE;
+        } else if (lower.startsWith("ne")) {
+            return UsageStatsManager.STANDBY_BUCKET_NEVER;
+        } else {
+            try {
+                int bucket = Integer.parseInt(lower);
+                return bucket;
+            } catch (NumberFormatException nfe) {
+                getErrPrintWriter().println("Error: Unknown bucket: " + name);
+            }
+        }
+        return -1;
+    }
+
     int runSetStandbyBucket(PrintWriter pw) throws RemoteException {
         int userId = UserHandle.USER_CURRENT;
 
@@ -1840,10 +1865,33 @@
         }
         String packageName = getNextArgRequired();
         String value = getNextArgRequired();
+        int bucket = bucketNameToBucketValue(value);
+        if (bucket < 0) return -1;
 
         IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService(
                 Context.USAGE_STATS_SERVICE));
-        usm.setAppStandbyBucket(packageName, Integer.parseInt(value), userId);
+        usm.setAppStandbyBucket(packageName, bucketNameToBucketValue(value), userId);
+        return 0;
+    }
+
+    int runGetStandbyBucket(PrintWriter pw) throws RemoteException {
+        int userId = UserHandle.USER_CURRENT;
+
+        String opt;
+        while ((opt=getNextOption()) != null) {
+            if (opt.equals("--user")) {
+                userId = UserHandle.parseUserArg(getNextArgRequired());
+            } else {
+                getErrPrintWriter().println("Error: Unknown option: " + opt);
+                return -1;
+            }
+        }
+        String packageName = getNextArgRequired();
+
+        IUsageStatsManager usm = IUsageStatsManager.Stub.asInterface(ServiceManager.getService(
+                Context.USAGE_STATS_SERVICE));
+        int bucket = usm.getAppStandbyBucket(packageName, null, userId);
+        pw.println(bucket);
         return 0;
     }
 
@@ -2597,8 +2645,10 @@
             pw.println("      Sets the inactive state of an app.");
             pw.println("  get-inactive [--user <USER_ID>] <PACKAGE>");
             pw.println("      Returns the inactive state of an app.");
-            pw.println("  set-standby-bucket [--user <USER_ID>] <PACKAGE> <BUCKET>");
+            pw.println("  set-standby-bucket [--user <USER_ID>] <PACKAGE> active|working_set|frequent|rare");
             pw.println("      Puts an app in the standby bucket.");
+            pw.println("  get-standby-bucket [--user <USER_ID>] <PACKAGE>");
+            pw.println("      Returns the standby bucket of an app.");
             pw.println("  send-trim-memory [--user <USER_ID>] <PROCESS>");
             pw.println("          [HIDDEN|RUNNING_MODERATE|BACKGROUND|RUNNING_LOW|MODERATE|RUNNING_CRITICAL|COMPLETE]");
             pw.println("      Send a memory trim event to a <PROCESS>.  May also supply a raw trim int level.");
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index 4af86a0..3f014b5 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -29,7 +29,7 @@
 import android.app.job.JobScheduler;
 import android.app.job.JobService;
 import android.app.job.JobWorkItem;
-import android.app.usage.AppStandby;
+import android.app.usage.UsageStatsManager;
 import android.app.usage.UsageStatsManagerInternal;
 import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
 import android.content.BroadcastReceiver;
@@ -2074,10 +2074,10 @@
 
     public static int standbyBucketToBucketIndex(int bucket) {
         // Normalize AppStandby constants to indices into our bookkeeping
-        if (bucket == AppStandby.STANDBY_BUCKET_NEVER) return 4;
-        else if (bucket >= AppStandby.STANDBY_BUCKET_RARE) return 3;
-        else if (bucket >= AppStandby.STANDBY_BUCKET_FREQUENT) return 2;
-        else if (bucket >= AppStandby.STANDBY_BUCKET_WORKING_SET) return 1;
+        if (bucket == UsageStatsManager.STANDBY_BUCKET_NEVER) return 4;
+        else if (bucket >= UsageStatsManager.STANDBY_BUCKET_RARE) return 3;
+        else if (bucket >= UsageStatsManager.STANDBY_BUCKET_FREQUENT) return 2;
+        else if (bucket >= UsageStatsManager.STANDBY_BUCKET_WORKING_SET) return 1;
         else return 0;
     }
 
diff --git a/services/core/java/com/android/server/location/ContextHubServiceTransaction.java b/services/core/java/com/android/server/location/ContextHubServiceTransaction.java
index 66145bb..a543daf 100644
--- a/services/core/java/com/android/server/location/ContextHubServiceTransaction.java
+++ b/services/core/java/com/android/server/location/ContextHubServiceTransaction.java
@@ -54,18 +54,10 @@
     abstract int onTransact();
 
     /**
-     * A function to invoke when a transaction times out.
-     *
-     * All instances of this class must implement this method by reporting the timeout to the
-     * client.
-     */
-    /* package */
-    abstract void onTimeout();
-
-    /**
      * A function to invoke when the transaction completes.
      *
-     * Only relevant for load, unload, enable, or disable transactions.
+     * For transactions with expected contents (such as a query), the class instance should
+     * implement the appropriate behavior (e.g. invoke onQueryResponse with an empty list).
      *
      * @param result the result of the transaction
      */
diff --git a/services/core/java/com/android/server/location/ContextHubTransactionManager.java b/services/core/java/com/android/server/location/ContextHubTransactionManager.java
index 47d9d56..3fcc682 100644
--- a/services/core/java/com/android/server/location/ContextHubTransactionManager.java
+++ b/services/core/java/com/android/server/location/ContextHubTransactionManager.java
@@ -106,17 +106,12 @@
                             contextHubId, hidlNanoAppBinary, this.getTransactionId());
                 } catch (RemoteException e) {
                     Log.e(TAG, "RemoteException while trying to load nanoapp with ID 0x" +
-                            Long.toHexString(nanoAppBinary.getNanoAppId()));
+                            Long.toHexString(nanoAppBinary.getNanoAppId()), e);
                     return Result.UNKNOWN_FAILURE;
                 }
             }
 
             @Override
-            /* package */ void onTimeout() {
-                onTransactionComplete(ContextHubTransaction.TRANSACTION_FAILED_TIMEOUT);
-            }
-
-            @Override
             /* package */ void onTransactionComplete(int result) {
                 try {
                     onCompleteCallback.onTransactionComplete(result);
@@ -124,7 +119,7 @@
                         mClientManager.onNanoAppLoaded(contextHubId, nanoAppBinary.getNanoAppId());
                     }
                 } catch (RemoteException e) {
-                    Log.e(TAG, "RemoteException while calling client onTransactionComplete");
+                    Log.e(TAG, "RemoteException while calling client onTransactionComplete", e);
                 }
             }
         };
@@ -149,17 +144,12 @@
                             contextHubId, nanoAppId, this.getTransactionId());
                 } catch (RemoteException e) {
                     Log.e(TAG, "RemoteException while trying to unload nanoapp with ID 0x" +
-                            Long.toHexString(nanoAppId));
+                            Long.toHexString(nanoAppId), e);
                     return Result.UNKNOWN_FAILURE;
                 }
             }
 
             @Override
-            /* package */ void onTimeout() {
-                onTransactionComplete(ContextHubTransaction.TRANSACTION_FAILED_TIMEOUT);
-            }
-
-            @Override
             /* package */ void onTransactionComplete(int result) {
                 try {
                     onCompleteCallback.onTransactionComplete(result);
@@ -167,7 +157,7 @@
                         mClientManager.onNanoAppUnloaded(contextHubId, nanoAppId);
                     }
                 } catch (RemoteException e) {
-                    Log.e(TAG, "RemoteException while calling client onTransactionComplete");
+                    Log.e(TAG, "RemoteException while calling client onTransactionComplete", e);
                 }
             }
         };
@@ -189,15 +179,14 @@
                 try {
                     return mContextHubProxy.queryApps(contextHubId);
                 } catch (RemoteException e) {
-                    Log.e(TAG, "RemoteException while trying to query for nanoapps");
+                    Log.e(TAG, "RemoteException while trying to query for nanoapps", e);
                     return Result.UNKNOWN_FAILURE;
                 }
             }
 
             @Override
-            /* package */ void onTimeout() {
-                onQueryResponse(ContextHubTransaction.TRANSACTION_FAILED_TIMEOUT,
-                        Collections.emptyList());
+            /* package */ void onTransactionComplete(int result) {
+                onQueryResponse(result, Collections.emptyList());
             }
 
             @Override
@@ -205,7 +194,7 @@
                 try {
                     onCompleteCallback.onQueryResponse(result, nanoAppStateList);
                 } catch (RemoteException e) {
-                    Log.e(TAG, "RemoteException while calling client onQueryComplete");
+                    Log.e(TAG, "RemoteException while calling client onQueryComplete", e);
                 }
             }
         };
@@ -333,7 +322,8 @@
                     synchronized (this) {
                         if (!transaction.isComplete()) {
                             Log.d(TAG, transaction + " timed out");
-                            transaction.onTimeout();
+                            transaction.onTransactionComplete(
+                                    ContextHubTransaction.TRANSACTION_FAILED_TIMEOUT);
 
                             removeTransactionAndStartNext();
                         }
@@ -344,6 +334,8 @@
                 mTimeoutFuture = mTimeoutExecutor.schedule(onTimeoutFunc, timeoutSeconds,
                         TimeUnit.SECONDS);
             } else {
+                transaction.onTransactionComplete(
+                        ContextHubServiceUtil.toTransactionResult(result));
                 mTransactionQueue.remove();
             }
         }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d0ad4ac..4b6589c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -467,6 +467,7 @@
     static final int SCAN_AS_SYSTEM = 1<<17;
     static final int SCAN_AS_PRIVILEGED = 1<<18;
     static final int SCAN_AS_OEM = 1<<19;
+    static final int SCAN_AS_VENDOR = 1<<20;
 
     @IntDef(flag = true, prefix = { "SCAN_" }, value = {
             SCAN_NO_DEX,
@@ -2574,8 +2575,25 @@
                     | SCAN_AS_SYSTEM,
                     0);
 
-            // Collect all vendor packages.
-            File vendorAppDir = new File("/vendor/app");
+            // Collected privileged vendor packages.
+                File privilegedVendorAppDir = new File(Environment.getVendorDirectory(),
+                        "priv-app");
+            try {
+                privilegedVendorAppDir = privilegedVendorAppDir.getCanonicalFile();
+            } catch (IOException e) {
+                // failed to look up canonical path, continue with original one
+            }
+            scanDirTracedLI(privilegedVendorAppDir,
+                    mDefParseFlags
+                    | PackageParser.PARSE_IS_SYSTEM_DIR,
+                    scanFlags
+                    | SCAN_AS_SYSTEM
+                    | SCAN_AS_VENDOR
+                    | SCAN_AS_PRIVILEGED,
+                    0);
+
+            // Collect ordinary vendor packages.
+            File vendorAppDir = new File(Environment.getVendorDirectory(), "app");
             try {
                 vendorAppDir = vendorAppDir.getCanonicalFile();
             } catch (IOException e) {
@@ -2585,7 +2603,8 @@
                     mDefParseFlags
                     | PackageParser.PARSE_IS_SYSTEM_DIR,
                     scanFlags
-                    | SCAN_AS_SYSTEM,
+                    | SCAN_AS_SYSTEM
+                    | SCAN_AS_VENDOR,
                     0);
 
             // Collect all OEM packages.
@@ -2770,13 +2789,23 @@
                             rescanFlags =
                                     scanFlags
                                     | SCAN_AS_SYSTEM;
+                        } else if (FileUtils.contains(privilegedVendorAppDir, scanFile)) {
+                            reparseFlags =
+                                    mDefParseFlags |
+                                    PackageParser.PARSE_IS_SYSTEM_DIR;
+                            rescanFlags =
+                                    scanFlags
+                                    | SCAN_AS_SYSTEM
+                                    | SCAN_AS_VENDOR
+                                    | SCAN_AS_PRIVILEGED;
                         } else if (FileUtils.contains(vendorAppDir, scanFile)) {
                             reparseFlags =
                                     mDefParseFlags |
                                     PackageParser.PARSE_IS_SYSTEM_DIR;
                             rescanFlags =
                                     scanFlags
-                                    | SCAN_AS_SYSTEM;
+                                    | SCAN_AS_SYSTEM
+                                    | SCAN_AS_VENDOR;
                         } else if (FileUtils.contains(oemAppDir, scanFile)) {
                             reparseFlags =
                                     mDefParseFlags |
@@ -8335,6 +8364,13 @@
             } else {
                 updatedPs.pkgPrivateFlags &= ~ApplicationInfo.PRIVATE_FLAG_OEM;
             }
+            // If new package is not located in "/vendor" (e.g. due to an OTA),
+            // it needs to drop FLAG_VENDOR.
+            if (locationIsVendor(pkg.codePath)) {
+                updatedPs.pkgPrivateFlags |= ApplicationInfo.PRIVATE_FLAG_VENDOR;
+            } else {
+                updatedPs.pkgPrivateFlags &= ~ApplicationInfo.PRIVATE_FLAG_VENDOR;
+            }
 
             if (ps != null && !ps.codePathString.equals(pkg.codePath)) {
                 // The path has changed from what was last scanned...  check the
@@ -8455,11 +8491,17 @@
                 scanFlags |= SCAN_AS_PRIVILEGED;
             }
 
-            // An updated OEM app will not have the PARSE_IS_OEM
+            // An updated OEM app will not have the SCAN_AS_OEM
             // flag set initially
             if ((updatedPs.pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_OEM) != 0) {
                 scanFlags |= SCAN_AS_OEM;
             }
+
+            // An updated vendor app will not have the SCAN_AS_VENDOR
+            // flag set initially
+            if ((updatedPs.pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0) {
+                scanFlags |= SCAN_AS_VENDOR;
+            }
         }
 
         // Verify certificates against what was last scanned
@@ -10208,6 +10250,10 @@
             pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_OEM;
         }
 
+        if ((scanFlags & SCAN_AS_VENDOR) != 0) {
+            pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_VENDOR;
+        }
+
         if (!isSystemApp(pkg)) {
             // Only system apps can use these features.
             pkg.mOriginalPackages = null;
@@ -15493,6 +15539,15 @@
                 return;
             }
 
+            // check if the new package supports all of the abis which the old package supports
+            boolean oldPkgSupportMultiArch = oldPackage.applicationInfo.secondaryCpuAbi != null;
+            boolean newPkgSupportMultiArch = pkg.applicationInfo.secondaryCpuAbi != null;
+            if (isSystemApp(oldPackage) && oldPkgSupportMultiArch && !newPkgSupportMultiArch) {
+                res.setError(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
+                        "Update to package " + pkgName + " doesn't support multi arch");
+                return;
+            }
+
             // In case of rollback, remember per-user/profile install state
             allUsers = sUserManager.getUserIds();
             installedUsers = ps.queryInstalledUsers(allUsers, true);
@@ -15574,18 +15629,22 @@
 
         boolean sysPkg = (isSystemApp(oldPackage));
         if (sysPkg) {
-            // Set the system/privileged/oem flags as needed
+            // Set the system/privileged/oem/vendor flags as needed
             final boolean privileged =
                     (oldPackage.applicationInfo.privateFlags
                             & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
             final boolean oem =
                     (oldPackage.applicationInfo.privateFlags
                             & ApplicationInfo.PRIVATE_FLAG_OEM) != 0;
+            final boolean vendor =
+                    (oldPackage.applicationInfo.privateFlags
+                            & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
             final @ParseFlags int systemParseFlags = parseFlags;
             final @ScanFlags int systemScanFlags = scanFlags
                     | SCAN_AS_SYSTEM
                     | (privileged ? SCAN_AS_PRIVILEGED : 0)
-                    | (oem ? SCAN_AS_OEM : 0);
+                    | (oem ? SCAN_AS_OEM : 0)
+                    | (vendor ? SCAN_AS_VENDOR : 0);
 
             replaceSystemPackageLIF(oldPackage, pkg, systemParseFlags, systemScanFlags,
                     user, allUsers, installerPackageName, res, installReason);
@@ -16764,6 +16823,10 @@
         return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_OEM) != 0;
     }
 
+    private static boolean isVendorApp(PackageParser.Package pkg) {
+        return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
+    }
+
     private static boolean hasDomainURLs(PackageParser.Package pkg) {
         return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0;
     }
@@ -17498,7 +17561,9 @@
     static boolean locationIsPrivileged(String path) {
         try {
             final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
-            return path.startsWith(privilegedAppDir.getCanonicalPath());
+            final File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app");
+            return path.startsWith(privilegedAppDir.getCanonicalPath())
+                    || path.startsWith(privilegedVendorAppDir.getCanonicalPath());
         } catch (IOException e) {
             Slog.e(TAG, "Unable to access code path " + path);
         }
@@ -17514,6 +17579,15 @@
         return false;
     }
 
+    static boolean locationIsVendor(String path) {
+        try {
+            return path.startsWith(Environment.getVendorDirectory().getCanonicalPath());
+        } catch (IOException e) {
+            Slog.e(TAG, "Unable to access code path " + path);
+        }
+        return false;
+    }
+
     /*
      * Tries to delete system package.
      */
@@ -17635,6 +17709,9 @@
         if (locationIsOem(codePathString)) {
             scanFlags |= SCAN_AS_OEM;
         }
+        if (locationIsVendor(codePathString)) {
+            scanFlags |= SCAN_AS_VENDOR;
+        }
 
         final File codePath = new File(codePathString);
         final PackageParser.Package pkg =
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 44f36d1..45b94a4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -1538,13 +1538,26 @@
         return 0;
     }
 
+    private boolean isVendorApp(String pkg) {
+        try {
+            final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
+            return info != null && info.applicationInfo.isVendor();
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
     private int runGetPrivappPermissions() {
         final String pkg = getNextArg();
         if (pkg == null) {
             getErrPrintWriter().println("Error: no package specified.");
             return 1;
         }
-        ArraySet<String> privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
+
+        ArraySet<String> privAppPermissions = isVendorApp(pkg) ?
+                SystemConfig.getInstance().getVendorPrivAppPermissions(pkg)
+                    : SystemConfig.getInstance().getPrivAppPermissions(pkg);
+
         getOutPrintWriter().println(privAppPermissions == null
                 ? "{}" : privAppPermissions.toString());
         return 0;
@@ -1556,10 +1569,13 @@
             getErrPrintWriter().println("Error: no package specified.");
             return 1;
         }
-        ArraySet<String> privAppDenyPermissions =
-                SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
-        getOutPrintWriter().println(privAppDenyPermissions == null
-                ? "{}" : privAppDenyPermissions.toString());
+
+        ArraySet<String> privAppPermissions = isVendorApp(pkg) ?
+                SystemConfig.getInstance().getVendorPrivAppDenyPermissions(pkg)
+                    : SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
+
+        getOutPrintWriter().println(privAppPermissions == null
+                ? "{}" : privAppPermissions.toString());
         return 0;
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 3b414e9..258dd4d4 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -140,6 +140,10 @@
         return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_OEM) != 0;
     }
 
+    public boolean isVendor() {
+        return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
+    }
+
     public boolean isForwardLocked() {
         return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0;
     }
diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java
index c97f5e5..46ba006 100644
--- a/services/core/java/com/android/server/pm/SettingBase.java
+++ b/services/core/java/com/android/server/pm/SettingBase.java
@@ -61,6 +61,7 @@
         this.pkgPrivateFlags = pkgPrivateFlags
                 & (ApplicationInfo.PRIVATE_FLAG_PRIVILEGED
                 | ApplicationInfo.PRIVATE_FLAG_OEM
+                | ApplicationInfo.PRIVATE_FLAG_VENDOR
                 | ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK
                 | ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER);
     }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index ddad677..af1a4d1 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -847,6 +847,8 @@
                 pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
         pkgSetting.pkgPrivateFlags |=
                 pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_OEM;
+        pkgSetting.pkgPrivateFlags |=
+                pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR;
         pkgSetting.primaryCpuAbiString = primaryCpuAbi;
         pkgSetting.secondaryCpuAbiString = secondaryCpuAbi;
         if (childPkgNames != null) {
@@ -4421,6 +4423,7 @@
             ApplicationInfo.PRIVATE_FLAG_PRIVILEGED, "PRIVILEGED",
             ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER, "REQUIRED_FOR_SYSTEM_USER",
             ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY, "STATIC_SHARED_LIBRARY",
+            ApplicationInfo.PRIVATE_FLAG_VENDOR, "VENDOR",
             ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD, "VIRTUAL_PRELOAD",
     };
 
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java
index 8c86db6..75a6106 100644
--- a/services/core/java/com/android/server/pm/permission/BasePermission.java
+++ b/services/core/java/com/android/server/pm/permission/BasePermission.java
@@ -225,6 +225,9 @@
     public boolean isVerifier() {
         return (protectionLevel & PermissionInfo.PROTECTION_FLAG_VERIFIER) != 0;
     }
+    public boolean isVendorPrivileged() {
+        return (protectionLevel & PermissionInfo.PROTECTION_FLAG_VENDOR_PRIVILEGED) != 0;
+    }
 
     public void transfer(@NonNull String origPackageName, @NonNull String newPackageName) {
         if (!origPackageName.equals(sourcePackageName)) {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 7d8e206..90ac4ab 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -959,8 +959,9 @@
      * <p>This handles parent/child apps.
      */
     private boolean hasPrivappWhitelistEntry(String perm, PackageParser.Package pkg) {
-        ArraySet<String> wlPermissions = SystemConfig.getInstance()
-                .getPrivAppPermissions(pkg.packageName);
+        ArraySet<String> wlPermissions = pkg.isVendor() ?
+                SystemConfig.getInstance().getVendorPrivAppPermissions(pkg.packageName)
+                    : SystemConfig.getInstance().getPrivAppPermissions(pkg.packageName);
         // Let's check if this package is whitelisted...
         boolean whitelisted = wlPermissions != null && wlPermissions.contains(perm);
         // If it's not, we'll also tail-recurse to the parent.
@@ -971,7 +972,8 @@
     private boolean grantSignaturePermission(String perm, PackageParser.Package pkg,
             BasePermission bp, PermissionsState origPermissions) {
         boolean oemPermission = bp.isOEM();
-        boolean privilegedPermission = bp.isPrivileged();
+        boolean vendorPrivilegedPermission = bp.isVendorPrivileged();
+        boolean privilegedPermission = bp.isPrivileged() || bp.isVendorPrivileged();
         boolean privappPermissionsDisable =
                 RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_DISABLE;
         boolean platformPermission = PLATFORM_PACKAGE_NAME.equals(bp.getSourcePackageName());
@@ -982,8 +984,11 @@
                 // Only report violations for apps on system image
                 if (!mSystemReady && !pkg.isUpdatedSystemApp()) {
                     // it's only a reportable violation if the permission isn't explicitly denied
-                    final ArraySet<String> deniedPermissions = SystemConfig.getInstance()
-                            .getPrivAppDenyPermissions(pkg.packageName);
+                    final ArraySet<String> deniedPermissions = pkg.isVendor() ?
+                            SystemConfig.getInstance()
+                                    .getVendorPrivAppDenyPermissions(pkg.packageName)
+                            : SystemConfig.getInstance()
+                                    .getPrivAppDenyPermissions(pkg.packageName);
                     final boolean permissionViolation =
                             deniedPermissions == null || !deniedPermissions.contains(perm);
                     if (permissionViolation) {
@@ -1086,6 +1091,15 @@
                             || (oemPermission && pkg.isOem()
                                     && canGrantOemPermission(ps, perm));
                 }
+                // In any case, don't grant a privileged permission to privileged vendor apps, if
+                // the permission's protectionLevel does not have the extra 'vendorPrivileged'
+                // flag.
+                if (allowed && privilegedPermission &&
+                        !vendorPrivilegedPermission && pkg.isVendor()) {
+                   Slog.w(TAG, "Permission " + perm + " cannot be granted to privileged vendor apk "
+                           + pkg.packageName + " because it isn't a 'vendorPrivileged' permission.");
+                   allowed = false;
+                }
             }
         }
         if (!allowed) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerPresubmitTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerPresubmitTest.java
deleted file mode 100644
index e6b4540f..0000000
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerPresubmitTest.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.pm;
-
-import android.content.Context;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PermissionInfo;
-import android.platform.test.annotations.GlobalPresubmit;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.util.ArraySet;
-
-import com.android.internal.os.RoSystemProperties;
-import com.android.internal.util.ArrayUtils;
-import com.android.server.SystemConfig;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import java.util.List;
-
-import static android.content.pm.PackageManager.GET_PERMISSIONS;
-import static junit.framework.Assert.assertTrue;
-
-
-/**
- * Presubmit tests for {@link PackageManager}.
- */
-@RunWith(AndroidJUnit4.class)
-public class PackageManagerPresubmitTest {
-
-    private Context mContext;
-
-    private PackageManager mPackageManager;
-
-    @Before
-    public void setUp() {
-        mContext = InstrumentationRegistry.getContext();
-        mPackageManager = mContext.getPackageManager();
-    }
-
-    /**
-     * <p>This test ensures that all signature|privileged permissions are granted to priv-apps.
-     * If CONTROL_PRIVAPP_PERMISSIONS_ENFORCE is set, the test also verifies that
-     * granted permissions are whitelisted in {@link SystemConfig}
-     */
-    @Test
-    @SmallTest
-    @GlobalPresubmit
-    public void testPrivAppPermissions() throws PackageManager.NameNotFoundException {
-        List<PackageInfo> installedPackages = mPackageManager
-                .getInstalledPackages(PackageManager.MATCH_UNINSTALLED_PACKAGES | GET_PERMISSIONS);
-        for (PackageInfo packageInfo : installedPackages) {
-            if (!packageInfo.applicationInfo.isPrivilegedApp()
-                    || PackageManagerService.PLATFORM_PACKAGE_NAME.equals(packageInfo.packageName)) {
-                continue;
-            }
-            testPackagePrivAppPermission(packageInfo);
-        }
-
-    }
-
-    private void testPackagePrivAppPermission(PackageInfo packageInfo)
-            throws PackageManager.NameNotFoundException {
-        String packageName = packageInfo.packageName;
-        ArraySet<String> privAppPermissions = SystemConfig.getInstance()
-                .getPrivAppPermissions(packageName);
-        if (ArrayUtils.isEmpty(packageInfo.requestedPermissions)) {
-            return;
-        }
-        for (int i = 0; i < packageInfo.requestedPermissions.length; i++) {
-            String pName = packageInfo.requestedPermissions[i];
-            int protectionLevel;
-            boolean platformPermission;
-            try {
-                PermissionInfo permissionInfo = mPackageManager.getPermissionInfo(pName, 0);
-                platformPermission = PackageManagerService.PLATFORM_PACKAGE_NAME.equals(
-                        permissionInfo.packageName);
-                protectionLevel = permissionInfo.protectionLevel;
-            } catch (PackageManager.NameNotFoundException e) {
-                continue;
-            }
-            if ((protectionLevel & PermissionInfo.PROTECTION_FLAG_PRIVILEGED) != 0) {
-                boolean granted = (packageInfo.requestedPermissionsFlags[i]
-                        & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0;
-                // if privapp permissions are enforced, platform permissions must be whitelisted
-                // in SystemConfig
-                if (platformPermission && RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
-                    assertTrue("Permission " + pName + " should be declared in "
-                                    + "privapp-permissions-<category>.xml file for package "
-                                    + packageName,
-                            privAppPermissions != null && privAppPermissions.contains(pName));
-                }
-                assertTrue("Permission " + pName + " should be granted to " + packageName, granted);
-            }
-        }
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java b/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
index 39d256a..b62d724 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppIdleHistoryTests.java
@@ -16,14 +16,17 @@
 
 package com.android.server.usage;
 
-import android.app.usage.AppStandby;
+import static android.app.usage.UsageStatsManager.REASON_TIMEOUT;
+import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
+import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
+import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
+
+import android.app.usage.UsageStatsManager;
 import android.os.FileUtils;
 import android.test.AndroidTestCase;
 
 import java.io.File;
 
-import static android.app.usage.AppStandby.*;
-
 public class AppIdleHistoryTests extends AndroidTestCase {
 
     File mStorageDir;
@@ -85,12 +88,12 @@
         AppIdleHistory aih = new AppIdleHistory(mStorageDir, 1000);
 
         aih.setAppStandbyBucket(PACKAGE_1, USER_ID, 1000, STANDBY_BUCKET_ACTIVE,
-                AppStandby.REASON_USAGE);
+                UsageStatsManager.REASON_USAGE);
         // ACTIVE means not idle
         assertFalse(aih.isIdle(PACKAGE_1, USER_ID, 2000));
 
         aih.setAppStandbyBucket(PACKAGE_2, USER_ID, 2000, STANDBY_BUCKET_ACTIVE,
-                AppStandby.REASON_USAGE);
+                UsageStatsManager.REASON_USAGE);
         aih.setAppStandbyBucket(PACKAGE_1, USER_ID, 3000, STANDBY_BUCKET_RARE,
                 REASON_TIMEOUT);
 
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index 40edfd2..87b34ab 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -16,9 +16,12 @@
 
 package com.android.server.usage;
 
-import static android.app.usage.AppStandby.*;
 import static android.app.usage.UsageEvents.Event.NOTIFICATION_SEEN;
 import static android.app.usage.UsageEvents.Event.USER_INTERACTION;
+import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
+import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
+import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
+import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -30,8 +33,8 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 
-import android.app.usage.AppStandby;
 import android.app.usage.UsageEvents;
+import android.app.usage.UsageStatsManager;
 import android.appwidget.AppWidgetManager;
 import android.content.Context;
 import android.content.ContextWrapper;
@@ -280,7 +283,7 @@
     public void testBuckets() throws Exception {
         AppStandbyController controller = setupController();
 
-        assertTimeout(controller, 0, STANDBY_BUCKET_NEVER);
+        assertTimeout(controller, 0, UsageStatsManager.STANDBY_BUCKET_NEVER);
 
         reportEvent(controller, USER_INTERACTION, 0);
 
@@ -312,7 +315,7 @@
         AppStandbyController controller = setupController();
         mInjector.setDisplayOn(false);
 
-        assertTimeout(controller, 0, STANDBY_BUCKET_NEVER);
+        assertTimeout(controller, 0, UsageStatsManager.STANDBY_BUCKET_NEVER);
 
         reportEvent(controller, USER_INTERACTION, 0);
 
diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java
index ee11241..5aef55b 100644
--- a/services/usage/java/com/android/server/usage/AppIdleHistory.java
+++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java
@@ -16,10 +16,7 @@
 
 package com.android.server.usage;
 
-import static android.app.usage.AppStandby.*;
-
-import android.app.usage.AppStandby;
-import android.os.Environment;
+import android.app.usage.UsageStatsManager;
 import android.os.SystemClock;
 import android.util.ArrayMap;
 import android.util.AtomicFile;
@@ -99,7 +96,8 @@
         final byte[] recent = new byte[HISTORY_SIZE];
         long lastUsedElapsedTime;
         long lastUsedScreenTime;
-        @StandbyBuckets int currentBucket;
+        @UsageStatsManager.StandbyBuckets
+        int currentBucket;
         String bucketingReason;
         int lastInformedBucket;
     }
@@ -190,14 +188,14 @@
                 + (elapsedRealtime - mElapsedSnapshot);
         appUsageHistory.lastUsedScreenTime = getScreenOnTime(elapsedRealtime);
         appUsageHistory.recent[HISTORY_SIZE - 1] = FLAG_LAST_STATE | FLAG_PARTIAL_ACTIVE;
-        if (appUsageHistory.currentBucket > STANDBY_BUCKET_ACTIVE) {
-            appUsageHistory.currentBucket = STANDBY_BUCKET_ACTIVE;
+        if (appUsageHistory.currentBucket > UsageStatsManager.STANDBY_BUCKET_ACTIVE) {
+            appUsageHistory.currentBucket = UsageStatsManager.STANDBY_BUCKET_ACTIVE;
             if (DEBUG) {
                 Slog.d(TAG, "Moved " + packageName + " to bucket=" + appUsageHistory.currentBucket
                         + ", reason=" + appUsageHistory.bucketingReason);
             }
         }
-        appUsageHistory.bucketingReason = AppStandby.REASON_USAGE;
+        appUsageHistory.bucketingReason = UsageStatsManager.REASON_USAGE;
 
         return appUsageHistory.currentBucket;
     }
@@ -206,15 +204,15 @@
         ArrayMap<String, AppUsageHistory> userHistory = getUserHistory(userId);
         AppUsageHistory appUsageHistory = getPackageHistory(userHistory, packageName,
                 elapsedRealtime, true);
-        if (appUsageHistory.currentBucket > STANDBY_BUCKET_WORKING_SET) {
-            appUsageHistory.currentBucket = STANDBY_BUCKET_WORKING_SET;
+        if (appUsageHistory.currentBucket > UsageStatsManager.STANDBY_BUCKET_WORKING_SET) {
+            appUsageHistory.currentBucket = UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
             if (DEBUG) {
                 Slog.d(TAG, "Moved " + packageName + " to bucket=" + appUsageHistory.currentBucket
                         + ", reason=" + appUsageHistory.bucketingReason);
             }
         }
         // TODO: Should this be a different reason for partial usage?
-        appUsageHistory.bucketingReason = AppStandby.REASON_USAGE;
+        appUsageHistory.bucketingReason = UsageStatsManager.REASON_USAGE;
 
         return appUsageHistory.currentBucket;
     }
@@ -271,8 +269,9 @@
             appUsageHistory = new AppUsageHistory();
             appUsageHistory.lastUsedElapsedTime = getElapsedTime(elapsedRealtime);
             appUsageHistory.lastUsedScreenTime = getScreenOnTime(elapsedRealtime);
-            appUsageHistory.currentBucket = AppStandby.STANDBY_BUCKET_NEVER;
-            appUsageHistory.bucketingReason = REASON_DEFAULT;
+            appUsageHistory.currentBucket = UsageStatsManager.STANDBY_BUCKET_NEVER;
+            appUsageHistory.bucketingReason = UsageStatsManager.REASON_DEFAULT;
+            appUsageHistory.lastInformedBucket = -1;
             userHistory.put(packageName, appUsageHistory);
         }
         return appUsageHistory;
@@ -289,7 +288,7 @@
         if (appUsageHistory == null) {
             return false; // Default to not idle
         } else {
-            return appUsageHistory.currentBucket >= AppStandby.STANDBY_BUCKET_RARE;
+            return appUsageHistory.currentBucket >= UsageStatsManager.STANDBY_BUCKET_RARE;
             // Whether or not it's passed will now be externally calculated and the
             // bucket will be pushed to the history using setAppStandbyBucket()
             //return hasPassedThresholds(appUsageHistory, elapsedRealtime);
@@ -333,12 +332,12 @@
         AppUsageHistory appUsageHistory = getPackageHistory(userHistory, packageName,
                 elapsedRealtime, true);
         if (idle) {
-            appUsageHistory.currentBucket = STANDBY_BUCKET_RARE;
-            appUsageHistory.bucketingReason = REASON_FORCED;
+            appUsageHistory.currentBucket = UsageStatsManager.STANDBY_BUCKET_RARE;
+            appUsageHistory.bucketingReason = UsageStatsManager.REASON_FORCED;
         } else {
-            appUsageHistory.currentBucket = STANDBY_BUCKET_ACTIVE;
+            appUsageHistory.currentBucket = UsageStatsManager.STANDBY_BUCKET_ACTIVE;
             // This is to pretend that the app was just used, don't freeze the state anymore.
-            appUsageHistory.bucketingReason = REASON_USAGE;
+            appUsageHistory.bucketingReason = UsageStatsManager.REASON_USAGE;
         }
         return appUsageHistory.currentBucket;
     }
@@ -435,12 +434,12 @@
                         String currentBucketString = parser.getAttributeValue(null,
                                 ATTR_CURRENT_BUCKET);
                         appUsageHistory.currentBucket = currentBucketString == null
-                                ? AppStandby.STANDBY_BUCKET_ACTIVE
+                                ? UsageStatsManager.STANDBY_BUCKET_ACTIVE
                                 : Integer.parseInt(currentBucketString);
                         appUsageHistory.bucketingReason =
                                 parser.getAttributeValue(null, ATTR_BUCKETING_REASON);
                         if (appUsageHistory.bucketingReason == null) {
-                            appUsageHistory.bucketingReason = REASON_DEFAULT;
+                            appUsageHistory.bucketingReason = UsageStatsManager.REASON_DEFAULT;
                         }
                         userHistory.put(packageName, appUsageHistory);
                     }
diff --git a/services/usage/java/com/android/server/usage/AppStandbyController.java b/services/usage/java/com/android/server/usage/AppStandbyController.java
index 3c099c2..4527879 100644
--- a/services/usage/java/com/android/server/usage/AppStandbyController.java
+++ b/services/usage/java/com/android/server/usage/AppStandbyController.java
@@ -16,15 +16,23 @@
 
 package com.android.server.usage;
 
+import static android.app.usage.UsageStatsManager.REASON_FORCED;
+import static android.app.usage.UsageStatsManager.REASON_TIMEOUT;
+import static android.app.usage.UsageStatsManager.REASON_USAGE;
+import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_ACTIVE;
+import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_FREQUENT;
+import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_RARE;
+import static android.app.usage.UsageStatsManager.STANDBY_BUCKET_WORKING_SET;
+
 import static com.android.server.SystemService.PHASE_BOOT_COMPLETED;
 import static com.android.server.SystemService.PHASE_SYSTEM_SERVICES_READY;
 
 import android.app.ActivityManager;
 import android.app.AppGlobals;
 import android.app.admin.DevicePolicyManager;
-import android.app.usage.AppStandby;
-import android.app.usage.AppStandby.StandbyBuckets;
+import android.app.usage.UsageStatsManager.StandbyBuckets;
 import android.app.usage.UsageEvents;
+import android.app.usage.UsageStatsManager;
 import android.app.usage.UsageStatsManagerInternal.AppIdleStateChangeListener;
 import android.appwidget.AppWidgetManager;
 import android.content.BroadcastReceiver;
@@ -102,10 +110,10 @@
     };
 
     static final int[] THRESHOLD_BUCKETS = {
-            AppStandby.STANDBY_BUCKET_ACTIVE,
-            AppStandby.STANDBY_BUCKET_WORKING_SET,
-            AppStandby.STANDBY_BUCKET_FREQUENT,
-            AppStandby.STANDBY_BUCKET_RARE
+            STANDBY_BUCKET_ACTIVE,
+            STANDBY_BUCKET_WORKING_SET,
+            STANDBY_BUCKET_FREQUENT,
+            STANDBY_BUCKET_RARE
     };
 
     // To name the lock for stack traces
@@ -371,18 +379,18 @@
                 }
                 if (isSpecial) {
                     maybeInformListeners(packageName, userId, elapsedRealtime,
-                            AppStandby.STANDBY_BUCKET_ACTIVE);
+                            STANDBY_BUCKET_ACTIVE);
                 } else {
                     synchronized (mAppIdleLock) {
                         String bucketingReason = mAppIdleHistory.getAppStandbyReason(packageName,
                                 userId, elapsedRealtime);
                         // If the bucket was forced by the developer, leave it alone
-                        if (AppStandby.REASON_FORCED.equals(bucketingReason)) {
+                        if (REASON_FORCED.equals(bucketingReason)) {
                             continue;
                         }
                         // If the bucket was moved up due to usage, let the timeouts apply.
-                        if (AppStandby.REASON_USAGE.equals(bucketingReason)
-                                || AppStandby.REASON_TIMEOUT.equals(bucketingReason)) {
+                        if (REASON_USAGE.equals(bucketingReason)
+                                || REASON_TIMEOUT.equals(bucketingReason)) {
                             int oldBucket = mAppIdleHistory.getAppStandbyBucket(packageName, userId,
                                     elapsedRealtime);
                             int newBucket = getBucketForLocked(packageName, userId,
@@ -393,7 +401,7 @@
                             }
                             if (oldBucket < newBucket) {
                                 mAppIdleHistory.setAppStandbyBucket(packageName, userId,
-                                        elapsedRealtime, newBucket, AppStandby.REASON_TIMEOUT);
+                                        elapsedRealtime, newBucket, REASON_TIMEOUT);
                                 maybeInformListeners(packageName, userId, elapsedRealtime,
                                         newBucket);
                             }
@@ -742,7 +750,7 @@
             long elapsedRealtime, boolean shouldObfuscateInstantApps) {
         if (shouldObfuscateInstantApps &&
                 mInjector.isPackageEphemeral(userId, packageName)) {
-            return AppStandby.STANDBY_BUCKET_ACTIVE;
+            return STANDBY_BUCKET_ACTIVE;
         }
 
         return mAppIdleHistory.getAppStandbyBucket(packageName, userId, elapsedRealtime);
@@ -811,7 +819,7 @@
     }
 
     void informListeners(String packageName, int userId, int bucket) {
-        final boolean idle = bucket >= AppStandby.STANDBY_BUCKET_RARE;
+        final boolean idle = bucket >= STANDBY_BUCKET_RARE;
         for (AppIdleStateChangeListener listener : mPackageAccessListeners) {
             listener.onAppIdleStateChanged(packageName, userId, idle, bucket);
         }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 65c1cef..878fbed 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -20,11 +20,11 @@
 import android.app.ActivityManager;
 import android.app.AppOpsManager;
 import android.app.IUidObserver;
-import android.app.usage.AppStandby;
 import android.app.usage.ConfigurationStats;
 import android.app.usage.IUsageStatsManager;
 import android.app.usage.UsageEvents;
-import android.app.usage.AppStandby.StandbyBuckets;
+import android.app.usage.UsageStatsManager;
+import android.app.usage.UsageStatsManager.StandbyBuckets;
 import android.app.usage.UsageEvents.Event;
 import android.app.usage.UsageStats;
 import android.app.usage.UsageStatsManagerInternal;
@@ -149,6 +149,8 @@
 
         publishLocalService(UsageStatsManagerInternal.class, new LocalService());
         publishBinderService(Context.USAGE_STATS_SERVICE, new BinderService());
+        // Make sure we initialize the data, in case job scheduler needs it early.
+        getUserDataAndInitializeIfNeededLocked(UserHandle.USER_SYSTEM, mSystemTimeSnapshot);
     }
 
     @Override
@@ -678,10 +680,6 @@
 
         @Override
         public int getAppStandbyBucket(String packageName, String callingPackage, int userId) {
-            if (!hasPermission(callingPackage)) {
-                throw new SecurityException("Don't have permission to query app standby bucket");
-            }
-
             final int callingUid = Binder.getCallingUid();
             try {
                 userId = ActivityManager.getService().handleIncomingUser(
@@ -690,6 +688,14 @@
             } catch (RemoteException re) {
                 throw re.rethrowFromSystemServer();
             }
+            // If the calling app is asking about itself, continue, else check for permission.
+            if (mPackageManagerInternal.getPackageUid(packageName, PackageManager.MATCH_ANY_USER,
+                    userId) != callingUid) {
+                if (!hasPermission(callingPackage)) {
+                    throw new SecurityException(
+                            "Don't have permission to query app standby bucket");
+                }
+            }
             final boolean obfuscateInstantApps = shouldObfuscateInstantAppsForCaller(callingUid,
                     userId);
             final long token = Binder.clearCallingIdentity();
@@ -707,6 +713,10 @@
             getContext().enforceCallingPermission(Manifest.permission.CHANGE_APP_IDLE_STATE,
                     "No permission to change app standby state");
 
+            if (bucket < UsageStatsManager.STANDBY_BUCKET_ACTIVE
+                    || bucket > UsageStatsManager.STANDBY_BUCKET_NEVER) {
+                throw new IllegalArgumentException("Cannot set the standby bucket to " + bucket);
+            }
             final int callingUid = Binder.getCallingUid();
             try {
                 userId = ActivityManager.getService().handleIncomingUser(
@@ -717,8 +727,13 @@
             }
             final long token = Binder.clearCallingIdentity();
             try {
+                // Caller cannot set their own standby state
+                if (mPackageManagerInternal.getPackageUid(packageName,
+                        PackageManager.MATCH_ANY_USER, userId) == callingUid) {
+                    throw new IllegalArgumentException("Cannot set your own standby bucket");
+                }
                 mAppStandby.setAppStandbyBucket(packageName, userId, bucket,
-                        AppStandby.REASON_PREDICTED + ":" + callingUid,
+                        UsageStatsManager.REASON_PREDICTED + ":" + callingUid,
                         SystemClock.elapsedRealtime());
             } finally {
                 Binder.restoreCallingIdentity(token);
diff --git a/telephony/java/android/telephony/MbmsDownloadSession.java b/telephony/java/android/telephony/MbmsDownloadSession.java
index f392570..a554c69 100644
--- a/telephony/java/android/telephony/MbmsDownloadSession.java
+++ b/telephony/java/android/telephony/MbmsDownloadSession.java
@@ -347,6 +347,7 @@
 
                     @Override
                     public void onServiceDisconnected(ComponentName name) {
+                        Log.w(LOG_TAG, "bindAndInitialize: Remote service disconnected");
                         sIsInitialized.set(false);
                         mService.set(null);
                     }
@@ -385,6 +386,7 @@
         } catch (RemoteException e) {
             Log.w(LOG_TAG, "Remote process died");
             mService.set(null);
+            sIsInitialized.set(false);
             sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
         }
     }
@@ -438,6 +440,7 @@
             }
         } catch (RemoteException e) {
             mService.set(null);
+            sIsInitialized.set(false);
             sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
             return;
         }
@@ -521,6 +524,7 @@
             downloadService.download(request);
         } catch (RemoteException e) {
             mService.set(null);
+            sIsInitialized.set(false);
             sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
         }
     }
@@ -542,6 +546,7 @@
             return downloadService.listPendingDownloads(mSubscriptionId);
         } catch (RemoteException e) {
             mService.set(null);
+            sIsInitialized.set(false);
             sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
             return Collections.emptyList();
         }
@@ -583,6 +588,7 @@
             }
         } catch (RemoteException e) {
             mService.set(null);
+            sIsInitialized.set(false);
             sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
             return;
         }
@@ -622,6 +628,7 @@
                 }
             } catch (RemoteException e) {
                 mService.set(null);
+                sIsInitialized.set(false);
                 sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
             }
         } finally {
@@ -658,6 +665,7 @@
             }
         } catch (RemoteException e) {
             mService.set(null);
+            sIsInitialized.set(false);
             sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
             return;
         }
@@ -686,6 +694,7 @@
             return downloadService.getDownloadStatus(downloadRequest, fileInfo);
         } catch (RemoteException e) {
             mService.set(null);
+            sIsInitialized.set(false);
             sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
             return STATUS_UNKNOWN;
         }
@@ -727,6 +736,7 @@
             }
         } catch (RemoteException e) {
             mService.set(null);
+            sIsInitialized.set(false);
             sendErrorToApp(MbmsErrors.ERROR_MIDDLEWARE_LOST, null);
         }
     }
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index a13af5f..2507cfee 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -63,7 +63,7 @@
      * embedded SIM.
      *
      * <p>The activity will immediately finish with {@link android.app.Activity#RESULT_CANCELED} if
-     * {@link #isEnabled} is false or if the device is already provisioned.
+     * {@link #isEnabled} is false.
      *
      * TODO(b/35851809): Make this a SystemApi.
      */
diff --git a/tests/privapp-permissions/Android.mk b/tests/privapp-permissions/Android.mk
new file mode 100644
index 0000000..b001c8c
--- /dev/null
+++ b/tests/privapp-permissions/Android.mk
@@ -0,0 +1,31 @@
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := PrivAppPermissionTest
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_MANIFEST_FILE := system/AndroidManifest.xml
+LOCAL_REQUIRED_MODULES := privapp-permissions-test.xml
+include $(BUILD_PACKAGE)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := privapp-permissions-test.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions
+LOCAL_SRC_FILES:= system/privapp-permissions-test.xml
+include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := VendorPrivAppPermissionTest
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_MANIFEST_FILE := vendor/AndroidManifest.xml
+LOCAL_VENDOR_MODULE := true
+LOCAL_REQUIRED_MODULES := vendorprivapp-permissions-test.xml
+include $(BUILD_PACKAGE)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := vendorprivapp-permissions-test.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/permissions
+LOCAL_SRC_FILES:= vendor/privapp-permissions-test.xml
+include $(BUILD_PREBUILT)
+
diff --git a/tests/privapp-permissions/system/AndroidManifest.xml b/tests/privapp-permissions/system/AndroidManifest.xml
new file mode 100644
index 0000000..2099e31
--- /dev/null
+++ b/tests/privapp-permissions/system/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2017 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.framework.permission.privapp.tests.system">
+
+    <!-- MANAGE_USB is signature|privileged -->
+    <uses-permission android:name="android.permission.MANAGE_USB"/>
+</manifest>
diff --git a/tests/privapp-permissions/system/privapp-permissions-test.xml b/tests/privapp-permissions/system/privapp-permissions-test.xml
new file mode 100644
index 0000000..a0cb6bc
--- /dev/null
+++ b/tests/privapp-permissions/system/privapp-permissions-test.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<permissions>
+    <privapp-permissions package="com.android.framework.permission.privapp.tests.system">
+        <permission name="android.permission.MANAGE_USB"/>
+    </privapp-permissions>
+</permissions>
diff --git a/tests/privapp-permissions/vendor/AndroidManifest.xml b/tests/privapp-permissions/vendor/AndroidManifest.xml
new file mode 100644
index 0000000..78dedc5
--- /dev/null
+++ b/tests/privapp-permissions/vendor/AndroidManifest.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2017 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.framework.permission.privapp.tests.vendor">
+
+    <!-- BIND_IMS_SERVICE is signature|privileged|vendorPrivileged -->
+    <uses-permission android:name="android.permission.BIND_IMS_SERVICE"/>
+    <!-- MANAGE_USB is signature|privileged and thus cannot be granted to this app -->
+    <uses-permission android:name="android.permission.MANAGE_USB"/>
+</manifest>
diff --git a/tests/privapp-permissions/vendor/privapp-permissions-test.xml b/tests/privapp-permissions/vendor/privapp-permissions-test.xml
new file mode 100644
index 0000000..51c588f
--- /dev/null
+++ b/tests/privapp-permissions/vendor/privapp-permissions-test.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<permissions>
+    <privapp-permissions package="com.android.framework.permission.privapp.tests.vendor">
+        <permission name="android.permission.BIND_IMS_SERVICE"/>
+        <permission name="android.permission.MANAGE_USB"/>
+    </privapp-permissions>
+</permissions>
diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk
index e0c9d1c..c9987b8 100644
--- a/tools/aapt2/Android.mk
+++ b/tools/aapt2/Android.mk
@@ -1,7 +1,11 @@
+LOCAL_PATH := $(call my-dir)
+
 include $(CLEAR_VARS)
 
+# Target for running host unit tests on post/pre-submit.
 .PHONY: aapt2_run_host_unit_tests
 aapt2_run_host_unit_tests: PRIVATE_GTEST_OPTIONS := --gtest_output=xml:$(DIST_DIR)/gtest/aapt2_host_unit_tests_result.xml
 aapt2_run_host_unit_tests: $(HOST_OUT_NATIVE_TESTS)/aapt2_tests/aapt2_tests
 	-$(HOST_OUT_NATIVE_TESTS)/aapt2_tests/aapt2_tests $(PRIVATE_GTEST_OPTIONS) > /dev/null 2>&1
 
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tools/aapt2/cmd/Link.cpp b/tools/aapt2/cmd/Link.cpp
index e94c0b4..d2aebfd 100644
--- a/tools/aapt2/cmd/Link.cpp
+++ b/tools/aapt2/cmd/Link.cpp
@@ -36,6 +36,7 @@
 #include "ValueVisitor.h"
 #include "cmd/Util.h"
 #include "compile/IdAssigner.h"
+#include "compile/XmlIdCollector.h"
 #include "filter/ConfigFilter.h"
 #include "format/Archive.h"
 #include "format/Container.h"
@@ -1235,19 +1236,10 @@
     return true;
   }
 
-  bool MergeCompiledFile(const ResourceFile& compiled_file, io::IFile* file, bool override) {
-    if (context_->IsVerbose()) {
-      context_->GetDiagnostics()->Note(DiagMessage()
-                                       << "merging '" << compiled_file.name
-                                       << "' from compiled file " << compiled_file.source);
-    }
-
-    if (!table_merger_->MergeFile(compiled_file, override, file)) {
-      return false;
-    }
-
+  bool MergeExportedSymbols(const Source& source,
+                            const std::vector<SourcedResourceName>& exported_symbols) {
     // Add the exports of this file to the table.
-    for (const SourcedResourceName& exported_symbol : compiled_file.exported_symbols) {
+    for (const SourcedResourceName& exported_symbol : exported_symbols) {
       ResourceName res_name = exported_symbol.name;
       if (res_name.package.empty()) {
         res_name.package = context_->GetCompilationPackage();
@@ -1259,7 +1251,7 @@
       }
 
       std::unique_ptr<Id> id = util::make_unique<Id>();
-      id->SetSource(compiled_file.source.WithLine(exported_symbol.line));
+      id->SetSource(source.WithLine(exported_symbol.line));
       bool result = final_table_.AddResourceAllowMangled(
           res_name, ConfigDescription::DefaultConfig(), std::string(), std::move(id),
           context_->GetDiagnostics());
@@ -1270,6 +1262,19 @@
     return true;
   }
 
+  bool MergeCompiledFile(const ResourceFile& compiled_file, io::IFile* file, bool override) {
+    if (context_->IsVerbose()) {
+      context_->GetDiagnostics()->Note(DiagMessage()
+                                       << "merging '" << compiled_file.name
+                                       << "' from compiled file " << compiled_file.source);
+    }
+
+    if (!table_merger_->MergeFile(compiled_file, override, file)) {
+      return false;
+    }
+    return MergeExportedSymbols(compiled_file.source, compiled_file.exported_symbols);
+  }
+
   // Takes a path to load as a ZIP file and merges the files within into the master ResourceTable.
   // If override is true, conflicting resources are allowed to override each other, in order of last
   // seen.
@@ -1573,6 +1578,19 @@
                                                        context_->GetPackageId()));
     }
 
+    // Extract symbols from AndroidManifest.xml, since this isn't merged like the other XML files
+    // in res/**/*.
+    {
+      XmlIdCollector collector;
+      if (!collector.Consume(context_, manifest_xml.get())) {
+        return false;
+      }
+
+      if (!MergeExportedSymbols(manifest_xml->file.source, manifest_xml->file.exported_symbols)) {
+        return false;
+      }
+    }
+
     for (const std::string& input : input_files) {
       if (!MergePath(input, false)) {
         context_->GetDiagnostics()->Error(DiagMessage() << "failed parsing input");
diff --git a/tools/aapt2/integration-tests/StaticLibTest/App/AndroidManifest.xml b/tools/aapt2/integration-tests/StaticLibTest/App/AndroidManifest.xml
index a5f202d..c8f4bda 100644
--- a/tools/aapt2/integration-tests/StaticLibTest/App/AndroidManifest.xml
+++ b/tools/aapt2/integration-tests/StaticLibTest/App/AndroidManifest.xml
@@ -21,7 +21,7 @@
     <uses-permission-sdk-23 android:name="android.permission.TEST" android:maxSdkVersion="22" />
 
     <application>
-        <activity android:name=".MyActivity">
+        <activity android:name=".MyActivity" android:id="@+id/sample_generated_id">
             <layout android:defaultHeight="500dp"
                 android:defaultWidth="600dp" />
         </activity>
diff --git a/tools/aapt2/integration-tests/StaticLibTest/App/res/layout/main.xml b/tools/aapt2/integration-tests/StaticLibTest/App/res/layout/main.xml
index aaa884b..5a73429 100644
--- a/tools/aapt2/integration-tests/StaticLibTest/App/res/layout/main.xml
+++ b/tools/aapt2/integration-tests/StaticLibTest/App/res/layout/main.xml
@@ -19,7 +19,7 @@
     android:layout_width="match_parent"
     android:layout_height="wrap_content">
 
-    <fragment class="android.test.sample.App$Inner" />
+    <fragment class="android.test.sample.App$Inner" android:id="@id/sample_generated_id"/>
 
     <variable name="user" type="com.android.User" />